diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2023-04-14 21:41:27 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2023-06-22 18:20:56 +0000 |
commit | bdd1243df58e60e85101c09001d9812a789b6bc4 (patch) | |
tree | a1ce621c7301dd47ba2ddc3b8eaa63b441389481 /contrib/llvm-project/lldb | |
parent | 781624ca2d054430052c828ba8d2c2eaf2d733e7 (diff) | |
parent | e3b557809604d036af6e00c60f012c2025b59a5e (diff) |
Diffstat (limited to 'contrib/llvm-project/lldb')
797 files changed, 23823 insertions, 12820 deletions
diff --git a/contrib/llvm-project/lldb/bindings/interface/SBData.i b/contrib/llvm-project/lldb/bindings/interface/SBData.i index 1f2f9fbf05e2..8e1d2fcf9d3e 100644 --- a/contrib/llvm-project/lldb/bindings/interface/SBData.i +++ b/contrib/llvm-project/lldb/bindings/interface/SBData.i @@ -157,7 +157,7 @@ public: for x in range(*key.indices(self.__len__())): list.append(self.__getitem__(x)) return list - if not (isinstance(key,six.integer_types)): + if not (isinstance(key, int)): raise TypeError('must be int') key = key * self.item_size # SBData uses byte-based indexes, but we want to use itemsize-based indexes here error = SBError() diff --git a/contrib/llvm-project/lldb/bindings/interface/SBDebugger.i b/contrib/llvm-project/lldb/bindings/interface/SBDebugger.i index 5d51a6ac20d2..e82ce2aa8e7c 100644 --- a/contrib/llvm-project/lldb/bindings/interface/SBDebugger.i +++ b/contrib/llvm-project/lldb/bindings/interface/SBDebugger.i @@ -225,6 +225,8 @@ public: } } + lldb::SBStructuredData GetSetting(const char *setting = nullptr); + SBError SetInputString (const char* data); diff --git a/contrib/llvm-project/lldb/bindings/interface/SBFileSpec.i b/contrib/llvm-project/lldb/bindings/interface/SBFileSpec.i index b549321487ec..e6f9bb81e240 100644 --- a/contrib/llvm-project/lldb/bindings/interface/SBFileSpec.i +++ b/contrib/llvm-project/lldb/bindings/interface/SBFileSpec.i @@ -84,18 +84,7 @@ public: #ifdef SWIGPYTHON %pythoncode %{ - def __get_fullpath__(self): - spec_dir = self.GetDirectory() - spec_file = self.GetFilename() - if spec_dir and spec_file: - return '%s/%s' % (spec_dir, spec_file) - elif spec_dir: - return spec_dir - elif spec_file: - return spec_file - return None - - fullpath = property(__get_fullpath__, None, doc='''A read only property that returns the fullpath as a python string.''') + fullpath = property(str, None, doc='''A read only property that returns the fullpath as a python string.''') basename = property(GetFilename, None, doc='''A read only property that returns the path basename as a python string.''') dirname = property(GetDirectory, None, doc='''A read only property that returns the path directory name as a python string.''') exists = property(Exists, None, doc='''A read only property that returns a boolean value that indicates if the file exists.''') diff --git a/contrib/llvm-project/lldb/bindings/interface/SBInstruction.i b/contrib/llvm-project/lldb/bindings/interface/SBInstruction.i index e9e018b7deed..a467a6f0d93d 100644 --- a/contrib/llvm-project/lldb/bindings/interface/SBInstruction.i +++ b/contrib/llvm-project/lldb/bindings/interface/SBInstruction.i @@ -44,6 +44,9 @@ public: const char * GetComment (lldb::SBTarget target); + lldb::InstructionControlFlowKind + GetControlFlowKind(lldb::SBTarget target); + lldb::SBData GetData (lldb::SBTarget target); diff --git a/contrib/llvm-project/lldb/bindings/interface/SBModule.i b/contrib/llvm-project/lldb/bindings/interface/SBModule.i index bda602d15690..de476f706261 100644 --- a/contrib/llvm-project/lldb/bindings/interface/SBModule.i +++ b/contrib/llvm-project/lldb/bindings/interface/SBModule.i @@ -137,8 +137,11 @@ public: void Clear(); - %feature("docstring", "Check if the module is file backed. + %feature("docstring", " + Check if the module is file backed. + @return + True, if the module is backed by an object file on disk. False, if the module is backed by an object file in memory.") IsFileBacked; bool diff --git a/contrib/llvm-project/lldb/bindings/interface/SBProcess.i b/contrib/llvm-project/lldb/bindings/interface/SBProcess.i index 7a9f8fc5757c..52f9fc7fa204 100644 --- a/contrib/llvm-project/lldb/bindings/interface/SBProcess.i +++ b/contrib/llvm-project/lldb/bindings/interface/SBProcess.i @@ -422,7 +422,7 @@ public: %feature("autodoc", " Allocates a block of memory within the process, with size and - access permissions specified in the arguments. The permisssions + access permissions specified in the arguments. The permissions argument is an or-combination of zero or more of lldb.ePermissionsWritable, lldb.ePermissionsReadable, and lldb.ePermissionsExecutable. Returns the address diff --git a/contrib/llvm-project/lldb/bindings/interface/SBSymbol.i b/contrib/llvm-project/lldb/bindings/interface/SBSymbol.i index fa0b3e4e1378..f5efee75e249 100644 --- a/contrib/llvm-project/lldb/bindings/interface/SBSymbol.i +++ b/contrib/llvm-project/lldb/bindings/interface/SBSymbol.i @@ -49,6 +49,10 @@ public: SBAddress GetEndAddress (); + uint64_t GetValue(); + + uint64_t GetSize(); + uint32_t GetPrologueByteSize (); diff --git a/contrib/llvm-project/lldb/bindings/interface/SBTarget.i b/contrib/llvm-project/lldb/bindings/interface/SBTarget.i index a6a764944d02..e887762b8313 100644 --- a/contrib/llvm-project/lldb/bindings/interface/SBTarget.i +++ b/contrib/llvm-project/lldb/bindings/interface/SBTarget.i @@ -947,7 +947,7 @@ public: %feature("docstring", " Returns true if the module has been loaded in this `SBTarget`. A module can be loaded either by the dynamic loader or by being manually - added to the target (see `SBTarget.AddModule` and the `target module add` command). + added to the target (see `SBTarget.AddModule` and the ``target module add`` command). :rtype: bool ") IsLoaded; diff --git a/contrib/llvm-project/lldb/bindings/interface/SBTrace.i b/contrib/llvm-project/lldb/bindings/interface/SBTrace.i index 0d74881a3f3d..e947572c0f84 100644 --- a/contrib/llvm-project/lldb/bindings/interface/SBTrace.i +++ b/contrib/llvm-project/lldb/bindings/interface/SBTrace.i @@ -15,6 +15,8 @@ class LLDB_API SBTrace { public: SBTrace(); + SBTraceCursor CreateNewCursor(SBError &error, SBThread &thread); + const char *GetStartConfigurationHelp(); SBFileSpec SaveToDisk(SBError &error, const SBFileSpec &bundle_dir, bool compact = false); diff --git a/contrib/llvm-project/lldb/bindings/interface/SBTraceCursor.i b/contrib/llvm-project/lldb/bindings/interface/SBTraceCursor.i new file mode 100644 index 000000000000..c1c73de31103 --- /dev/null +++ b/contrib/llvm-project/lldb/bindings/interface/SBTraceCursor.i @@ -0,0 +1,58 @@ +//===-- SWIG Interface for SBTraceCursor.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 +// +//===----------------------------------------------------------------------===// + +namespace lldb { + +%feature("docstring", +"Represents a trace cursor." +) SBTrace; +class LLDB_API SBTraceCursor { +public: + SBTraceCursor(); + + SBTraceCursor(lldb::TraceCursorSP trace_cursor_sp); + + void SetForwards(bool forwards); + + bool IsForwards() const; + + void Next(); + + bool HasValue(); + + bool GoToId(lldb::user_id_t id); + + bool HasId(lldb::user_id_t id) const; + + lldb::user_id_t GetId() const; + + bool Seek(int64_t offset, lldb::TraceCursorSeekType origin); + + lldb::TraceItemKind GetItemKind() const; + + bool IsError() const; + + const char *GetError() const; + + bool IsEvent() const; + + lldb::TraceEvent GetEventType() const; + + const char *GetEventTypeAsString() const; + + bool IsInstruction() const; + + lldb::addr_t GetLoadAddress() const; + + lldb::cpu_id_t GetCPU() const; + + bool IsValid() const; + + explicit operator bool() const; +}; +} // namespace lldb diff --git a/contrib/llvm-project/lldb/bindings/interface/SBType.i b/contrib/llvm-project/lldb/bindings/interface/SBType.i index 8db2fa749634..5bead82cd2c5 100644 --- a/contrib/llvm-project/lldb/bindings/interface/SBType.i +++ b/contrib/llvm-project/lldb/bindings/interface/SBType.i @@ -229,7 +229,7 @@ public: function returns ``0``. * C++: Same as in C. * Objective-C: Same as in C. For Objective-C classes this always returns - `0`` as the actual size depends on runtime information. + ``0`` as the actual size depends on runtime information. ") GetByteSize; uint64_t GetByteSize(); @@ -506,7 +506,7 @@ public: Language-specific behaviour: - * C: Returns a constant-size array `T[size]` for any non-void type. + * C: Returns a constant-size array ``T[size]`` for any non-void type. * C++: Same as in C. * Objective-C: Same as in C. @@ -537,8 +537,8 @@ public: "Returns the `BasicType` value that is most appropriate to this type. Returns `eBasicTypeInvalid` if no appropriate `BasicType` was found or this - type is invalid. See the `BasicType` documentation for the language-specific m - aning of each `BasicType` value. + type is invalid. See the `BasicType` documentation for the language-specific + meaning of each `BasicType` value. **Overload behaviour:** When called with a `BasicType` parameter, the following behaviour applies: @@ -731,8 +731,8 @@ public: * C: Always returns ``0``. * C++: If this type is a class template instantiation then this returns the - number of template parameters that were used in this instantiation. This i - cludes both explicit and implicit template parameters. + number of template parameters that were used in this instantiation. This + includes both explicit and implicit template parameters. * Objective-C: Always returns ``0``. ") GetNumberOfTemplateArguments; uint32_t diff --git a/contrib/llvm-project/lldb/bindings/interface/SBTypeNameSpecifier.i b/contrib/llvm-project/lldb/bindings/interface/SBTypeNameSpecifier.i index 772f7c174093..4bd5f205cfbc 100644 --- a/contrib/llvm-project/lldb/bindings/interface/SBTypeNameSpecifier.i +++ b/contrib/llvm-project/lldb/bindings/interface/SBTypeNameSpecifier.i @@ -20,6 +20,9 @@ namespace lldb { SBTypeNameSpecifier (const char* name, bool is_regex = false); + SBTypeNameSpecifier (const char* name, + lldb::FormatterMatchType match_type); + SBTypeNameSpecifier (SBType type); SBTypeNameSpecifier (const lldb::SBTypeNameSpecifier &rhs); @@ -40,6 +43,9 @@ namespace lldb { lldb::SBType GetType (); + lldb::FormatterMatchType + GetMatchType(); + bool IsRegex(); diff --git a/contrib/llvm-project/lldb/bindings/interface/SBValueList.i b/contrib/llvm-project/lldb/bindings/interface/SBValueList.i index 76fa937b9876..e03b5c649db9 100644 --- a/contrib/llvm-project/lldb/bindings/interface/SBValueList.i +++ b/contrib/llvm-project/lldb/bindings/interface/SBValueList.i @@ -102,8 +102,12 @@ public: lldb::SBValue GetFirstValueByName (const char* name) const; + lldb::SBError GetError(); + %extend { +#ifdef SWIGPYTHON %nothreadallow; +#endif std::string lldb::SBValueList::__str__ (){ lldb::SBStream description; const size_t n = $self->GetSize(); @@ -122,7 +126,9 @@ public: --desc_len; return std::string(desc, desc_len); } +#ifdef SWIGPYTHON %clearnothreadallow; +#endif } #ifdef SWIGPYTHON diff --git a/contrib/llvm-project/lldb/bindings/interfaces.swig b/contrib/llvm-project/lldb/bindings/interfaces.swig index 021c7683d170..d984711bbd8a 100644 --- a/contrib/llvm-project/lldb/bindings/interfaces.swig +++ b/contrib/llvm-project/lldb/bindings/interfaces.swig @@ -66,6 +66,7 @@ %include "./interface/SBThreadCollection.i" %include "./interface/SBThreadPlan.i" %include "./interface/SBTrace.i" +%include "./interface/SBTraceCursor.i" %include "./interface/SBType.i" %include "./interface/SBTypeCategory.i" %include "./interface/SBTypeEnumMember.i" diff --git a/contrib/llvm-project/lldb/bindings/lua/lua-typemaps.swig b/contrib/llvm-project/lldb/bindings/lua/lua-typemaps.swig index 15a18deaa3a4..56756936a532 100644 --- a/contrib/llvm-project/lldb/bindings/lua/lua-typemaps.swig +++ b/contrib/llvm-project/lldb/bindings/lua/lua-typemaps.swig @@ -247,7 +247,7 @@ LLDB_NUMBER_TYPEMAP(enum SWIGTYPE); // Typemap for file handles (e.g. used in SBDebugger::GetOutputFileHandle) %typemap(out) lldb::FileSP { - lldb::FileSP &sp = $1; + lldb::FileSP sp = $1; if (sp && sp->IsValid()) { luaL_Stream *p = (luaL_Stream *)lua_newuserdata(L, sizeof(luaL_Stream)); p->closef = &LLDBSwigLuaCloseFileHandle; diff --git a/contrib/llvm-project/lldb/bindings/python/python-swigsafecast.swig b/contrib/llvm-project/lldb/bindings/python/python-swigsafecast.swig index eb684133abef..a1e883b3b19d 100644 --- a/contrib/llvm-project/lldb/bindings/python/python-swigsafecast.swig +++ b/contrib/llvm-project/lldb/bindings/python/python-swigsafecast.swig @@ -5,28 +5,6 @@ PythonObject ToSWIGHelper(void *obj, swig_type_info *info) { return {PyRefType::Owned, SWIG_NewPointerObj(obj, info, SWIG_POINTER_OWN)}; } -/// A class that automatically clears an SB object when it goes out of scope. -/// Use for cases where the SB object points to a temporary/unowned entity. -template <typename T> class ScopedPythonObject : PythonObject { -public: - ScopedPythonObject(T *sb, swig_type_info *info) - : PythonObject(ToSWIGHelper(sb, info)), m_sb(sb) {} - ~ScopedPythonObject() { - if (m_sb) - *m_sb = T(); - } - ScopedPythonObject(ScopedPythonObject &&rhs) - : PythonObject(std::move(rhs)), m_sb(std::exchange(rhs.m_sb, nullptr)) {} - ScopedPythonObject(const ScopedPythonObject &) = delete; - ScopedPythonObject &operator=(const ScopedPythonObject &) = delete; - ScopedPythonObject &operator=(ScopedPythonObject &&) = delete; - - const PythonObject &obj() const { return *this; } - -private: - T *m_sb; -}; - PythonObject ToSWIGWrapper(std::unique_ptr<lldb::SBValue> value_sb) { return ToSWIGHelper(value_sb.release(), SWIGTYPE_p_lldb__SBValue); } @@ -55,6 +33,10 @@ PythonObject ToSWIGWrapper(lldb::BreakpointSP breakpoint_sp) { SWIGTYPE_p_lldb__SBBreakpoint); } +PythonObject ToSWIGWrapper(const Status& status) { + return ToSWIGHelper(new lldb::SBError(status), SWIGTYPE_p_lldb__SBError); +} + PythonObject ToSWIGWrapper(std::unique_ptr<lldb::SBStream> stream_sb) { return ToSWIGHelper(stream_sb.release(), SWIGTYPE_p_lldb__SBStream); } @@ -97,6 +79,10 @@ PythonObject ToSWIGWrapper(lldb::ExecutionContextRefSP ctx_sp) { SWIGTYPE_p_lldb__SBExecutionContext); } +PythonObject ToSWIGWrapper(lldb::TypeImplSP type_impl_sp) { + return ToSWIGHelper(new lldb::SBType(type_impl_sp), SWIGTYPE_p_lldb__SBType); +} + PythonObject ToSWIGWrapper(const TypeSummaryOptions &summary_options) { return ToSWIGHelper(new lldb::SBTypeSummaryOptions(summary_options), SWIGTYPE_p_lldb__SBTypeSummaryOptions); diff --git a/contrib/llvm-project/lldb/bindings/python/python-typemaps.h b/contrib/llvm-project/lldb/bindings/python/python-typemaps.h index b45352ad6295..8a533e822988 100644 --- a/contrib/llvm-project/lldb/bindings/python/python-typemaps.h +++ b/contrib/llvm-project/lldb/bindings/python/python-typemaps.h @@ -1,6 +1,8 @@ #ifndef LLDB_BINDINGS_PYTHON_PYTHON_TYPEMAPS_H #define LLDB_BINDINGS_PYTHON_PYTHON_TYPEMAPS_H +#include <Python.h> + // Defined here instead of a .swig file because SWIG 2 doesn't support // explicit deleted functions. struct Py_buffer_RAII { diff --git a/contrib/llvm-project/lldb/bindings/python/python-typemaps.swig b/contrib/llvm-project/lldb/bindings/python/python-typemaps.swig index d45431c771ca..11f68d59ae7b 100644 --- a/contrib/llvm-project/lldb/bindings/python/python-typemaps.swig +++ b/contrib/llvm-project/lldb/bindings/python/python-typemaps.swig @@ -18,7 +18,7 @@ if (!py_str.IsAllocated()) { PyErr_SetString(PyExc_TypeError, "list must contain strings"); free($1); - return nullptr; + SWIG_fail; } $1[i] = const_cast<char *>(py_str.GetString().data()); @@ -28,7 +28,7 @@ $1 = NULL; } else { PyErr_SetString(PyExc_TypeError, "not a list"); - return NULL; + SWIG_fail; } } @@ -70,7 +70,7 @@ PythonObject obj = Retain<PythonObject>($input); lldb::tid_t value = unwrapOrSetPythonException(As<unsigned long long>(obj)); if (PyErr_Occurred()) - return nullptr; + SWIG_fail; $1 = value; } @@ -79,10 +79,10 @@ unsigned long long state_type_value = unwrapOrSetPythonException(As<unsigned long long>(obj)); if (PyErr_Occurred()) - return nullptr; + SWIG_fail; if (state_type_value > lldb::StateType::kLastStateType) { PyErr_SetString(PyExc_ValueError, "Not a valid StateType value"); - return nullptr; + SWIG_fail; } $1 = static_cast<lldb::StateType>(state_type_value); } @@ -93,12 +93,12 @@ %typemap(in) (char *dst, size_t dst_len) { if (!PyInt_Check($input)) { PyErr_SetString(PyExc_ValueError, "Expecting an integer"); - return NULL; + SWIG_fail; } $2 = PyInt_AsLong($input); if ($2 <= 0) { PyErr_SetString(PyExc_ValueError, "Positive integer expected"); - return NULL; + SWIG_fail; } $1 = (char *)malloc($2); } @@ -129,12 +129,12 @@ %typemap(in) (char *dst_or_null, size_t dst_len) { if (!PyInt_Check($input)) { PyErr_SetString(PyExc_ValueError, "Expecting an integer"); - return NULL; + SWIG_fail; } $2 = PyInt_AsLong($input); if ($2 <= 0) { PyErr_SetString(PyExc_ValueError, "Positive integer expected"); - return NULL; + SWIG_fail; } $1 = (char *)malloc($2); } @@ -166,7 +166,7 @@ $2 = bytes.GetSize(); } else { PyErr_SetString(PyExc_ValueError, "Expecting a string"); - return NULL; + SWIG_fail; } } // For SBProcess::WriteMemory, SBTarget::GetInstructions and SBDebugger::DispatchInput. @@ -186,7 +186,7 @@ $2 = bytes.GetSize(); } else { PyErr_SetString(PyExc_ValueError, "Expecting a buffer"); - return NULL; + SWIG_fail; } } @@ -199,11 +199,11 @@ $2 = PyLong_AsLong($input); } else { PyErr_SetString(PyExc_ValueError, "Expecting an integer or long object"); - return NULL; + SWIG_fail; } if ($2 <= 0) { PyErr_SetString(PyExc_ValueError, "Positive integer expected"); - return NULL; + SWIG_fail; } $1 = (void *)malloc($2); } @@ -287,12 +287,12 @@ template <> bool SetNumberFromPyObject<double>(double &number, PyObject *obj) { if (!SetNumberFromPyObject($1[i], o)) { PyErr_SetString(PyExc_TypeError, "list must contain numbers"); free($1); - return NULL; + SWIG_fail; } if (PyErr_Occurred()) { free($1); - return NULL; + SWIG_fail; } } } else if ($input == Py_None) { @@ -300,7 +300,7 @@ template <> bool SetNumberFromPyObject<double>(double &number, PyObject *obj) { $2 = 0; } else { PyErr_SetString(PyExc_TypeError, "not a list"); - return NULL; + SWIG_fail; } } @@ -353,7 +353,7 @@ template <> bool SetNumberFromPyObject<double>(double &number, PyObject *obj) { if (!($input == Py_None || PyCallable_Check(reinterpret_cast<PyObject *>($input)))) { PyErr_SetString(PyExc_TypeError, "Need a callable object or None!"); - return NULL; + SWIG_fail; } // FIXME (filcab): We can't currently check if our callback is already @@ -377,11 +377,11 @@ template <> bool SetNumberFromPyObject<double>(double &number, PyObject *obj) { PythonFile py_file(PyRefType::Borrowed, $input); if (!py_file) { PyErr_SetString(PyExc_TypeError, "not a file"); - return nullptr; + SWIG_fail; } auto sp = unwrapOrSetPythonException(py_file.ConvertToFile()); if (!sp) - return nullptr; + SWIG_fail; $1 = sp; } @@ -389,12 +389,12 @@ template <> bool SetNumberFromPyObject<double>(double &number, PyObject *obj) { PythonFile py_file(PyRefType::Borrowed, $input); if (!py_file) { PyErr_SetString(PyExc_TypeError, "not a file"); - return nullptr; + SWIG_fail; } auto sp = unwrapOrSetPythonException( py_file.ConvertToFileForcingUseOfScriptingIOMethods()); if (!sp) - return nullptr; + SWIG_fail; $1 = sp; } @@ -402,12 +402,12 @@ template <> bool SetNumberFromPyObject<double>(double &number, PyObject *obj) { PythonFile py_file(PyRefType::Borrowed, $input); if (!py_file) { PyErr_SetString(PyExc_TypeError, "not a file"); - return nullptr; + SWIG_fail; } auto sp = unwrapOrSetPythonException(py_file.ConvertToFile(/*borrowed=*/true)); if (!sp) - return nullptr; + SWIG_fail; $1 = sp; } @@ -415,12 +415,12 @@ template <> bool SetNumberFromPyObject<double>(double &number, PyObject *obj) { PythonFile py_file(PyRefType::Borrowed, $input); if (!py_file) { PyErr_SetString(PyExc_TypeError, "not a file"); - return nullptr; + SWIG_fail; } auto sp = unwrapOrSetPythonException( py_file.ConvertToFileForcingUseOfScriptingIOMethods(/*borrowed=*/true)); if (!sp) - return nullptr; + SWIG_fail; $1 = sp; } @@ -439,7 +439,7 @@ template <> bool SetNumberFromPyObject<double>(double &number, PyObject *obj) { if (sp) { PythonFile pyfile = unwrapOrSetPythonException(PythonFile::FromFile(*sp)); if (!pyfile.IsValid()) - return nullptr; + SWIG_fail; $result = pyfile.release(); } if (!$result) { @@ -468,7 +468,7 @@ template <> bool SetNumberFromPyObject<double>(double &number, PyObject *obj) { py_str.release(); } else { PyErr_SetString(PyExc_TypeError, "not a string-like object"); - return NULL; + SWIG_fail; } } diff --git a/contrib/llvm-project/lldb/bindings/python/python-wrapper.swig b/contrib/llvm-project/lldb/bindings/python/python-wrapper.swig index 626fc47bebb9..9a08c3000b79 100644 --- a/contrib/llvm-project/lldb/bindings/python/python-wrapper.swig +++ b/contrib/llvm-project/lldb/bindings/python/python-wrapper.swig @@ -90,6 +90,32 @@ bool lldb_private::LLDBSwigPythonWatchpointCallbackFunction( return stop_at_watchpoint; } +// This function is called by +// ScriptInterpreterPython::FormatterMatchingCallbackFunction and it's used when +// a data formatter provides the name of a callback to inspect a candidate type +// before considering a match. +bool lldb_private::LLDBSwigPythonFormatterCallbackFunction( + const char *python_function_name, const char *session_dictionary_name, + lldb::TypeImplSP type_impl_sp) { + + PyErr_Cleaner py_err_cleaner(true); + + auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>( + session_dictionary_name); + auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>( + python_function_name, dict); + + if (!pfunc.IsAllocated()) + return false; + + PythonObject result = + pfunc(ToSWIGWrapper(type_impl_sp), dict); + + // Only if everything goes okay and the function returns True we'll consider + // it a match. + return result.get() == Py_True; +} + bool lldb_private::LLDBSwigPythonCallTypeScript( const char *python_function_name, const void *session_dictionary, const lldb::ValueObjectSP &valobj_sp, void **pyfunct_wrapper, @@ -203,9 +229,9 @@ PythonObject lldb_private::LLDBSwigPythonCreateCommandObject( return pfunc(ToSWIGWrapper(std::move(debugger_sp)), dict); } -PythonObject lldb_private::LLDBSwigPythonCreateScriptedProcess( +PythonObject lldb_private::LLDBSwigPythonCreateScriptedObject( const char *python_class_name, const char *session_dictionary_name, - const lldb::TargetSP &target_sp, + lldb::ExecutionContextRefSP exe_ctx_sp, const lldb_private::StructuredDataImpl &args_impl, std::string &error_string) { if (python_class_name == NULL || python_class_name[0] == '\0' || @@ -225,8 +251,6 @@ PythonObject lldb_private::LLDBSwigPythonCreateScriptedProcess( return PythonObject(); } - PythonObject target_arg = ToSWIGWrapper(target_sp); - llvm::Expected<PythonCallable::ArgInfo> arg_info = pfunc.GetArgInfo(); if (!arg_info) { llvm::handleAllErrors( @@ -240,7 +264,7 @@ PythonObject lldb_private::LLDBSwigPythonCreateScriptedProcess( PythonObject result = {}; if (arg_info.get().max_positional_args == 2) { - result = pfunc(target_arg, ToSWIGWrapper(args_impl)); + result = pfunc(ToSWIGWrapper(exe_ctx_sp), ToSWIGWrapper(args_impl)); } else { error_string.assign("wrong number of arguments in __init__, should be 2 " "(not including self)"); @@ -248,46 +272,6 @@ PythonObject lldb_private::LLDBSwigPythonCreateScriptedProcess( return result; } -PythonObject lldb_private::LLDBSwigPythonCreateScriptedThread( - const char *python_class_name, const char *session_dictionary_name, - const lldb::ProcessSP &process_sp, const StructuredDataImpl &args_impl, - std::string &error_string) { - 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()) { - error_string.append("could not find script class: "); - error_string.append(python_class_name); - return PythonObject(); - } - - llvm::Expected<PythonCallable::ArgInfo> arg_info = pfunc.GetArgInfo(); - if (!arg_info) { - llvm::handleAllErrors( - arg_info.takeError(), - [&](PythonException &E) { error_string.append(E.ReadBacktrace()); }, - [&](const llvm::ErrorInfoBase &E) { - error_string.append(E.message()); - }); - return PythonObject(); - } - - if (arg_info.get().max_positional_args == 2) - return pfunc(ToSWIGWrapper(process_sp), ToSWIGWrapper(args_impl)); - - error_string.assign("wrong number of arguments in __init__, should be 2 " - "(not including self)"); - return PythonObject(); -} - PythonObject lldb_private::LLDBSwigPythonCreateScriptedThreadPlan( const char *python_class_name, const char *session_dictionary_name, const lldb_private::StructuredDataImpl &args_impl, @@ -915,12 +899,12 @@ bool lldb_private::LLDBSWIGPythonRunScriptKeywordProcess( return true; } -llvm::Optional<std::string> lldb_private::LLDBSWIGPythonRunScriptKeywordThread( +std::optional<std::string> lldb_private::LLDBSWIGPythonRunScriptKeywordThread( const char *python_function_name, const char *session_dictionary_name, lldb::ThreadSP thread) { if (python_function_name == NULL || python_function_name[0] == '\0' || !session_dictionary_name) - return llvm::None; + return std::nullopt; PyErr_Cleaner py_err_cleaner(true); @@ -930,7 +914,7 @@ llvm::Optional<std::string> lldb_private::LLDBSWIGPythonRunScriptKeywordThread( python_function_name, dict); if (!pfunc.IsAllocated()) - return llvm::None; + return std::nullopt; auto result = pfunc(ToSWIGWrapper(std::move(thread)), dict); @@ -962,12 +946,12 @@ bool lldb_private::LLDBSWIGPythonRunScriptKeywordTarget( return true; } -llvm::Optional<std::string> lldb_private::LLDBSWIGPythonRunScriptKeywordFrame( +std::optional<std::string> lldb_private::LLDBSWIGPythonRunScriptKeywordFrame( const char *python_function_name, const char *session_dictionary_name, lldb::StackFrameSP frame) { if (python_function_name == NULL || python_function_name[0] == '\0' || !session_dictionary_name) - return llvm::None; + return std::nullopt; PyErr_Cleaner py_err_cleaner(true); @@ -977,7 +961,7 @@ llvm::Optional<std::string> lldb_private::LLDBSWIGPythonRunScriptKeywordFrame( python_function_name, dict); if (!pfunc.IsAllocated()) - return llvm::None; + return std::nullopt; auto result = pfunc(ToSWIGWrapper(std::move(frame)), dict); diff --git a/contrib/llvm-project/lldb/bindings/python/python.swig b/contrib/llvm-project/lldb/bindings/python/python.swig index cb80e1be61a8..b1f6c4b9301d 100644 --- a/contrib/llvm-project/lldb/bindings/python/python.swig +++ b/contrib/llvm-project/lldb/bindings/python/python.swig @@ -84,8 +84,6 @@ void name ## _set(type *t, int index, type val) { import uuid import re import os - -import six %} // Include the version of swig that was used to generate this interface. diff --git a/contrib/llvm-project/lldb/include/lldb/API/SBBreakpointLocation.h b/contrib/llvm-project/lldb/include/lldb/API/SBBreakpointLocation.h index a906727f938a..ca29696065ea 100644 --- a/contrib/llvm-project/lldb/include/lldb/API/SBBreakpointLocation.h +++ b/contrib/llvm-project/lldb/include/lldb/API/SBBreakpointLocation.h @@ -48,11 +48,13 @@ public: void SetCondition(const char *condition); const char *GetCondition(); - + void SetAutoContinue(bool auto_continue); bool GetAutoContinue(); + void SetCallback(SBBreakpointHitCallback callback, void *baton); + void SetScriptCallbackFunction(const char *callback_function_name); SBError SetScriptCallbackFunction(const char *callback_function_name, diff --git a/contrib/llvm-project/lldb/include/lldb/API/SBCommunication.h b/contrib/llvm-project/lldb/include/lldb/API/SBCommunication.h index e407d859d885..fa8c88acd3fb 100644 --- a/contrib/llvm-project/lldb/include/lldb/API/SBCommunication.h +++ b/contrib/llvm-project/lldb/include/lldb/API/SBCommunication.h @@ -75,7 +75,7 @@ private: SBCommunication(const SBCommunication &) = delete; const SBCommunication &operator=(const SBCommunication &) = delete; - lldb_private::Communication *m_opaque = nullptr; + lldb_private::ThreadedCommunication *m_opaque = nullptr; bool m_opaque_owned = false; }; diff --git a/contrib/llvm-project/lldb/include/lldb/API/SBDebugger.h b/contrib/llvm-project/lldb/include/lldb/API/SBDebugger.h index b9a9b593d0ad..950e8e29ef79 100644 --- a/contrib/llvm-project/lldb/include/lldb/API/SBDebugger.h +++ b/contrib/llvm-project/lldb/include/lldb/API/SBDebugger.h @@ -94,6 +94,8 @@ public: static void PrintStackTraceOnError(); + static void PrintDiagnosticsOnError(); + static void Terminate(); // Deprecated, use the one that takes a source_init_files bool. @@ -115,6 +117,21 @@ public: void Clear(); + /// Getting a specific setting value into SBStructuredData format. + /// Client can specify empty string or null to get all settings. + /// + /// Example usages: + /// lldb::SBStructuredData settings = debugger.GetSetting(); + /// lldb::SBStructuredData settings = debugger.GetSetting(nullptr); + /// lldb::SBStructuredData settings = debugger.GetSetting(""); + /// lldb::SBStructuredData settings = debugger.GetSetting("target.arg0"); + /// lldb::SBStructuredData settings = debugger.GetSetting("target"); + /// + /// \param[out] setting + /// Property setting path to retrieve values. e.g "target.source-map" + /// + lldb::SBStructuredData GetSetting(const char *setting = nullptr); + void SetAsync(bool b); bool GetAsync(); diff --git a/contrib/llvm-project/lldb/include/lldb/API/SBDefines.h b/contrib/llvm-project/lldb/include/lldb/API/SBDefines.h index ecf1dc34d8c5..6833c0542c16 100644 --- a/contrib/llvm-project/lldb/include/lldb/API/SBDefines.h +++ b/contrib/llvm-project/lldb/include/lldb/API/SBDefines.h @@ -88,6 +88,7 @@ class LLDB_API SBThread; class LLDB_API SBThreadCollection; class LLDB_API SBThreadPlan; class LLDB_API SBTrace; +class LLDB_API SBTraceCursor; class LLDB_API SBType; class LLDB_API SBTypeCategory; class LLDB_API SBTypeEnumMember; diff --git a/contrib/llvm-project/lldb/include/lldb/API/SBError.h b/contrib/llvm-project/lldb/include/lldb/API/SBError.h index f8289e2fcbb3..e698ee9e9333 100644 --- a/contrib/llvm-project/lldb/include/lldb/API/SBError.h +++ b/contrib/llvm-project/lldb/include/lldb/API/SBError.h @@ -23,10 +23,16 @@ public: SBError(const lldb::SBError &rhs); + SBError(const lldb_private::Status &error); + ~SBError(); const SBError &operator=(const lldb::SBError &rhs); + /// Get the error string as a NULL terminated UTF8 c-string. + /// + /// This SBError object owns the returned string and this object must be kept + /// around long enough to use the returned string. const char *GetCString() const; void Clear(); @@ -64,6 +70,7 @@ protected: friend class SBCommunication; friend class SBData; friend class SBDebugger; + friend class SBFile; friend class SBHostOS; friend class SBPlatform; friend class SBProcess; @@ -73,8 +80,8 @@ protected: friend class SBThread; friend class SBTrace; friend class SBValue; + friend class SBValueList; friend class SBWatchpoint; - friend class SBFile; friend class lldb_private::ScriptInterpreter; diff --git a/contrib/llvm-project/lldb/include/lldb/API/SBInstruction.h b/contrib/llvm-project/lldb/include/lldb/API/SBInstruction.h index b9d781550b5d..def9482b02ed 100644 --- a/contrib/llvm-project/lldb/include/lldb/API/SBInstruction.h +++ b/contrib/llvm-project/lldb/include/lldb/API/SBInstruction.h @@ -43,6 +43,8 @@ public: const char *GetComment(lldb::SBTarget target); + lldb::InstructionControlFlowKind GetControlFlowKind(lldb::SBTarget target); + lldb::SBData GetData(lldb::SBTarget target); size_t GetByteSize(); diff --git a/contrib/llvm-project/lldb/include/lldb/API/SBReproducer.h b/contrib/llvm-project/lldb/include/lldb/API/SBReproducer.h index ecf28d6f0e11..f84645eff016 100644 --- a/contrib/llvm-project/lldb/include/lldb/API/SBReproducer.h +++ b/contrib/llvm-project/lldb/include/lldb/API/SBReproducer.h @@ -32,9 +32,6 @@ public: void SetCheckVersion(bool check); bool GetCheckVersion() const; - -private: - std::unique_ptr<lldb_private::repro::ReplayOptions> m_opaque_up; }; /// The SBReproducer class is special because it bootstraps the capture and diff --git a/contrib/llvm-project/lldb/include/lldb/API/SBSymbol.h b/contrib/llvm-project/lldb/include/lldb/API/SBSymbol.h index 5935ccfed024..94521881f82f 100644 --- a/contrib/llvm-project/lldb/include/lldb/API/SBSymbol.h +++ b/contrib/llvm-project/lldb/include/lldb/API/SBSymbol.h @@ -41,10 +41,46 @@ public: lldb::SBInstructionList GetInstructions(lldb::SBTarget target, const char *flavor_string); + /// Get the start address of this symbol + /// + /// \returns + /// If the symbol's value is not an address, an invalid SBAddress object + /// will be returned. If the symbol's value is an address, a valid SBAddress + /// object will be returned. SBAddress GetStartAddress(); + /// Get the end address of this symbol + /// + /// \returns + /// If the symbol's value is not an address, an invalid SBAddress object + /// will be returned. If the symbol's value is an address, a valid SBAddress + /// object will be returned. SBAddress GetEndAddress(); + /// Get the raw value of a symbol. + /// + /// This accessor allows direct access to the symbol's value from the symbol + /// table regardless of what the value is. The value can be a file address or + /// it can be an integer value that depends on what the symbol's type is. Some + /// symbol values are not addresses, but absolute values or integer values + /// that can be mean different things. The GetStartAddress() accessor will + /// only return a valid SBAddress if the symbol's value is an address, so this + /// accessor provides a way to access the symbol's value when the value is + /// not an address. + /// + /// \returns + /// Returns the raw integer value of a symbol from the symbol table. + uint64_t GetValue(); + + /// Get the size of the symbol. + /// + /// This accessor allows direct access to the symbol's size from the symbol + /// table regardless of what the value is (address or integer value). + /// + /// \returns + /// Returns the size of a symbol from the symbol table. + uint64_t GetSize(); + uint32_t GetPrologueByteSize(); SymbolType GetType(); diff --git a/contrib/llvm-project/lldb/include/lldb/API/SBTrace.h b/contrib/llvm-project/lldb/include/lldb/API/SBTrace.h index 19d759013955..7929d217ef26 100644 --- a/contrib/llvm-project/lldb/include/lldb/API/SBTrace.h +++ b/contrib/llvm-project/lldb/include/lldb/API/SBTrace.h @@ -11,6 +11,7 @@ #include "lldb/API/SBDefines.h" #include "lldb/API/SBError.h" +#include "lldb/API/SBTraceCursor.h" namespace lldb { @@ -25,6 +26,20 @@ public: static SBTrace LoadTraceFromFile(SBError &error, SBDebugger &debugger, const SBFileSpec &trace_description_file); + /// Get a \a TraceCursor for the given thread's trace. + /// + /// \param[out] error + /// This will be set with an error in case of failures. + // + /// \param[in] thread + /// The thread to get a \a TraceCursor for. + // + /// \return + /// A \a SBTraceCursor. If the thread is not traced or its trace + /// information failed to load, an invalid \a SBTraceCursor is returned + /// and the \p error parameter is set. + SBTraceCursor CreateNewCursor(SBError &error, SBThread &thread); + /// Save the trace to the specified directory, which will be created if /// needed. This will also create a a file \a <directory>/trace.json with the /// main properties of the trace session, along with others files which diff --git a/contrib/llvm-project/lldb/include/lldb/API/SBTraceCursor.h b/contrib/llvm-project/lldb/include/lldb/API/SBTraceCursor.h new file mode 100644 index 000000000000..c2f38b6b4868 --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/API/SBTraceCursor.h @@ -0,0 +1,181 @@ +//===-- SBTraceCursor.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_API_SBTRACECURSOR_H +#define LLDB_API_SBTRACECURSOR_H + +#include "lldb/API/SBDefines.h" +#include "lldb/API/SBError.h" +#include "lldb/API/SBExecutionContext.h" + +namespace lldb { + +class LLDB_API SBTraceCursor { +public: + /// Default constructor for an invalid \a SBTraceCursor object. + SBTraceCursor(); + + /// Create a cursor that initially points to the end of the trace, i.e. the + /// most recent item. + SBTraceCursor(lldb::TraceCursorSP trace_cursor_sp); + + /// Set the direction to use in the \a SBTraceCursor::Next() method. + /// + /// \param[in] forwards + /// If \b true, then the traversal will be forwards, otherwise backwards. + void SetForwards(bool forwards); + + /// Check if the direction to use in the \a SBTraceCursor::Next() method is + /// forwards. + /// + /// \return + /// \b true if the current direction is forwards, \b false if backwards. + bool IsForwards() const; + + /// Move the cursor to the next item (instruction or error). + /// + /// Direction: + /// The traversal is done following the current direction of the trace. If + /// it is forwards, the instructions are visited forwards + /// chronologically. Otherwise, the traversal is done in + /// the opposite direction. By default, a cursor moves backwards unless + /// changed with \a SBTraceCursor::SetForwards(). + void Next(); + + /// \return + /// \b true if the cursor is pointing to a valid item. \b false if the + /// cursor has reached the end of the trace. + bool HasValue() const; + + /// Instruction identifiers: + /// + /// When building complex higher level tools, fast random accesses in the + /// trace might be needed, for which each instruction requires a unique + /// identifier within its thread trace. For example, a tool might want to + /// repeatedly inspect random consecutive portions of a trace. This means that + /// it will need to first move quickly to the beginning of each section and + /// then start its iteration. Given that the number of instructions can be in + /// the order of hundreds of millions, fast random access is necessary. + /// + /// An example of such a tool could be an inspector of the call graph of a + /// trace, where each call is represented with its start and end instructions. + /// Inspecting all the instructions of a call requires moving to its first + /// instruction and then iterating until the last instruction, which following + /// the pattern explained above. + /// + /// Instead of using 0-based indices as identifiers, each Trace plug-in can + /// decide the nature of these identifiers and thus no assumptions can be made + /// regarding their ordering and sequentiality. The reason is that an + /// instruction might be encoded by the plug-in in a way that hides its actual + /// 0-based index in the trace, but it's still possible to efficiently find + /// it. + /// + /// Requirements: + /// - For a given thread, no two instructions have the same id. + /// - In terms of efficiency, moving the cursor to a given id should be as + /// fast as possible, but not necessarily O(1). That's why the recommended + /// way to traverse sequential instructions is to use the \a + /// SBTraceCursor::Next() method and only use \a SBTraceCursor::GoToId(id) + /// sparingly. + + /// Make the cursor point to the item whose identifier is \p id. + /// + /// \return + /// \b true if the given identifier exists and the cursor effectively + /// moved to it. Otherwise, \b false is returned and the cursor now points + /// to an invalid item, i.e. calling \a HasValue() will return \b false. + bool GoToId(lldb::user_id_t id); + + /// \return + /// \b true if and only if there's an instruction item with the given \p + /// id. + bool HasId(lldb::user_id_t id) const; + + /// \return + /// A unique identifier for the instruction or error this cursor is + /// pointing to. + lldb::user_id_t GetId() const; + /// \} + + /// Make the cursor point to an item in the trace based on an origin point and + /// an offset. + /// + /// The resulting position of the trace is + /// origin + offset + /// + /// If this resulting position would be out of bounds, the trace then points + /// to an invalid item, i.e. calling \a HasValue() returns \b false. + /// + /// \param[in] offset + /// How many items to move forwards (if positive) or backwards (if + /// negative) from the given origin point. For example, if origin is \b + /// End, then a negative offset would move backward in the trace, but a + /// positive offset would move past the trace to an invalid item. + /// + /// \param[in] origin + /// The reference point to use when moving the cursor. + /// + /// \return + /// \b true if and only if the cursor ends up pointing to a valid item. + bool Seek(int64_t offset, lldb::TraceCursorSeekType origin); + + /// \return + /// The \a ExecutionContextRef of the backing thread from the creation time + /// of this cursor. + SBExecutionContext &GetExecutionContextRef(); + + /// Trace item information (instructions, errors and events) + /// \{ + + /// \return + /// The kind of item the cursor is pointing at. + lldb::TraceItemKind GetItemKind() const; + + /// \return + /// Whether the cursor points to an error or not. + bool IsError() const; + + /// \return + /// The error message the cursor is pointing at. + const char *GetError() const; + + /// \return + /// Whether the cursor points to an event or not. + bool IsEvent() const; + + /// \return + /// The specific kind of event the cursor is pointing at. + lldb::TraceEvent GetEventType() const; + + /// \return + /// A human-readable description of the event this cursor is pointing at. + const char *GetEventTypeAsString() const; + + /// \return + /// Whether the cursor points to an instruction. + bool IsInstruction() const; + + /// \return + /// The load address of the instruction the cursor is pointing at. + lldb::addr_t GetLoadAddress() const; + + /// \return + /// The requested CPU id, or LLDB_INVALID_CPU_ID if this information is + /// not available for the current item. + lldb::cpu_id_t GetCPU() const; + + bool IsValid() const; + + explicit operator bool() const; + +protected: + lldb::TraceCursorSP m_opaque_sp; +}; +} // namespace lldb + +#endif // LLDB_API_SBTRACECURSOR_H diff --git a/contrib/llvm-project/lldb/include/lldb/API/SBType.h b/contrib/llvm-project/lldb/include/lldb/API/SBType.h index aa45aeeec476..215e03fad99b 100644 --- a/contrib/llvm-project/lldb/include/lldb/API/SBType.h +++ b/contrib/llvm-project/lldb/include/lldb/API/SBType.h @@ -106,6 +106,7 @@ public: SBType(); SBType(const lldb::SBType &rhs); + SBType(const lldb::TypeImplSP &); ~SBType(); @@ -239,7 +240,6 @@ protected: SBType(const lldb_private::CompilerType &); SBType(const lldb::TypeSP &); - SBType(const lldb::TypeImplSP &); }; class SBTypeList { diff --git a/contrib/llvm-project/lldb/include/lldb/API/SBTypeNameSpecifier.h b/contrib/llvm-project/lldb/include/lldb/API/SBTypeNameSpecifier.h index eee424c1710a..56a85d72c723 100644 --- a/contrib/llvm-project/lldb/include/lldb/API/SBTypeNameSpecifier.h +++ b/contrib/llvm-project/lldb/include/lldb/API/SBTypeNameSpecifier.h @@ -20,6 +20,9 @@ public: SBTypeNameSpecifier(const char *name, bool is_regex = false); + SBTypeNameSpecifier(const char *name, + lldb::FormatterMatchType match_type); + SBTypeNameSpecifier(SBType type); SBTypeNameSpecifier(const lldb::SBTypeNameSpecifier &rhs); @@ -34,6 +37,8 @@ public: SBType GetType(); + lldb::FormatterMatchType GetMatchType(); + bool IsRegex(); bool GetDescription(lldb::SBStream &description, diff --git a/contrib/llvm-project/lldb/include/lldb/API/SBValueList.h b/contrib/llvm-project/lldb/include/lldb/API/SBValueList.h index dc8389b75293..a5017bccc505 100644 --- a/contrib/llvm-project/lldb/include/lldb/API/SBValueList.h +++ b/contrib/llvm-project/lldb/include/lldb/API/SBValueList.h @@ -43,6 +43,33 @@ public: const lldb::SBValueList &operator=(const lldb::SBValueList &rhs); + // Get an error for why this list is empty. + // + // If this list is empty, check for an underlying error in the debug + // information that prevented this list from being populated. This is not + // meant to return an error if there is no debug information as it is ok for a + // value list to be empty and no error should be returned in that case. If the + // debug info is for an assembly file or language that doesn't have any + // variables, no error should be returned. + // + // This is designed as a way to let users know when they enable certain + // compiler options that enable debug information but provide a degraded + // debug information content, like -gline-tables-only, which is a compiler + // option that allows users to set file and line breakpoints, but users get + // confused when no variables show up during debugging. + // + // It is also designed to inform a user that debug information might be + // available if an external file, like a .dwo file, but that file doesn't + // exist or wasn't able to be loaded due to a mismatched ID. When debugging + // with fission enabled, the line tables are linked into the main executable, + // but if the .dwo or .dwp files are not available or have been modified, + // users can get confused if they can stop at a file and line breakpoint but + // can't see variables in this case. + // + // This error can give vital clues to the user about the cause is and allow + // the user to fix the issue. + lldb::SBError GetError(); + protected: // only useful for visualizing the pointer or comparing two SBValueLists to // see if they are backed by the same underlying Impl. @@ -68,6 +95,8 @@ private: ValueListImpl &ref(); std::unique_ptr<ValueListImpl> m_opaque_up; + + void SetError(const lldb_private::Status &status); }; } // namespace lldb diff --git a/contrib/llvm-project/lldb/include/lldb/Breakpoint/Breakpoint.h b/contrib/llvm-project/lldb/include/lldb/Breakpoint/Breakpoint.h index 39c6d0b7f3a7..7490982cb05b 100644 --- a/contrib/llvm-project/lldb/include/lldb/Breakpoint/Breakpoint.h +++ b/contrib/llvm-project/lldb/include/lldb/Breakpoint/Breakpoint.h @@ -330,6 +330,9 @@ public: /// The current hit count for all locations. uint32_t GetHitCount() const; + /// Resets the current hit count for all locations. + void ResetHitCount(); + /// If \a one_shot is \b true, breakpoint will be deleted on first hit. void SetOneShot(bool one_shot); @@ -379,7 +382,10 @@ public: /// \param[in] is_synchronous /// If \b true the callback will be run on the private event thread /// before the stop event gets reported. If false, the callback will get - /// handled on the public event thread after the stop has been posted. + /// handled on the public event thread while the stop event is being + /// pulled off the event queue. + /// Note: synchronous callbacks cannot cause the target to run, in + /// particular, they should not try to run the expression evaluator. void SetCallback(BreakpointHitCallback callback, void *baton, bool is_synchronous = false); diff --git a/contrib/llvm-project/lldb/include/lldb/Breakpoint/BreakpointID.h b/contrib/llvm-project/lldb/include/lldb/Breakpoint/BreakpointID.h index 64432f2d3cd5..a62323061b75 100644 --- a/contrib/llvm-project/lldb/include/lldb/Breakpoint/BreakpointID.h +++ b/contrib/llvm-project/lldb/include/lldb/Breakpoint/BreakpointID.h @@ -12,8 +12,8 @@ #include "lldb/lldb-private.h" #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/Optional.h" #include "llvm/ADT/StringRef.h" +#include <optional> namespace lldb_private { @@ -55,9 +55,9 @@ public: /// A string containing JUST the breakpoint description. /// \return /// If \p input was not a valid breakpoint ID string, returns - /// \b llvm::None. Otherwise returns a BreakpointID with members filled + /// \b std::nullopt. Otherwise returns a BreakpointID with members filled /// out accordingly. - static llvm::Optional<BreakpointID> + static std::optional<BreakpointID> ParseCanonicalReference(llvm::StringRef input); /// Takes an input string and checks to see whether it is a breakpoint name. diff --git a/contrib/llvm-project/lldb/include/lldb/Breakpoint/BreakpointList.h b/contrib/llvm-project/lldb/include/lldb/Breakpoint/BreakpointList.h index 346972ec3a1f..a7399d385f6f 100644 --- a/contrib/llvm-project/lldb/include/lldb/Breakpoint/BreakpointList.h +++ b/contrib/llvm-project/lldb/include/lldb/Breakpoint/BreakpointList.h @@ -138,6 +138,9 @@ public: void ClearAllBreakpointSites(); + /// Resets the hit count of all breakpoints. + void ResetHitCounts(); + /// Sets the passed in Locker to hold the Breakpoint List mutex. /// /// \param[in] lock diff --git a/contrib/llvm-project/lldb/include/lldb/Breakpoint/BreakpointLocation.h b/contrib/llvm-project/lldb/include/lldb/Breakpoint/BreakpointLocation.h index a6d1232162fc..2a4f9fc01bf3 100644 --- a/contrib/llvm-project/lldb/include/lldb/Breakpoint/BreakpointLocation.h +++ b/contrib/llvm-project/lldb/include/lldb/Breakpoint/BreakpointLocation.h @@ -87,6 +87,9 @@ public: /// Return the current Hit Count. uint32_t GetHitCount() const { return m_hit_counter.GetValue(); } + /// Resets the current Hit Count. + void ResetHitCount() { m_hit_counter.Reset(); } + /// Return the current Ignore Count. /// /// \return diff --git a/contrib/llvm-project/lldb/include/lldb/Breakpoint/BreakpointLocationList.h b/contrib/llvm-project/lldb/include/lldb/Breakpoint/BreakpointLocationList.h index 4b36c919ee3c..f76a8fcfdd7e 100644 --- a/contrib/llvm-project/lldb/include/lldb/Breakpoint/BreakpointLocationList.h +++ b/contrib/llvm-project/lldb/include/lldb/Breakpoint/BreakpointLocationList.h @@ -126,6 +126,9 @@ public: /// Hit count of all locations in this list. uint32_t GetHitCount() const; + /// Resets the hit count of all locations in this list. + void ResetHitCount(); + /// Enquires of the breakpoint location in this list with ID \a breakID /// whether we should stop. /// diff --git a/contrib/llvm-project/lldb/include/lldb/Breakpoint/BreakpointResolver.h b/contrib/llvm-project/lldb/include/lldb/Breakpoint/BreakpointResolver.h index 7aa43b9f45df..a0b37c94ac2b 100644 --- a/contrib/llvm-project/lldb/include/lldb/Breakpoint/BreakpointResolver.h +++ b/contrib/llvm-project/lldb/include/lldb/Breakpoint/BreakpointResolver.h @@ -16,6 +16,7 @@ #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/RegularExpression.h" #include "lldb/lldb-private.h" +#include <optional> namespace lldb_private { @@ -205,7 +206,7 @@ protected: void SetSCMatchesByLine(SearchFilter &filter, SymbolContextList &sc_list, bool skip_prologue, llvm::StringRef log_ident, uint32_t line = 0, - llvm::Optional<uint16_t> column = llvm::None); + std::optional<uint16_t> column = std::nullopt); void SetSCMatchesByLine(SearchFilter &, SymbolContextList &, bool, const char *) = delete; diff --git a/contrib/llvm-project/lldb/include/lldb/Breakpoint/BreakpointResolverFileLine.h b/contrib/llvm-project/lldb/include/lldb/Breakpoint/BreakpointResolverFileLine.h index bd8d0394d4d2..5864a284d6f1 100644 --- a/contrib/llvm-project/lldb/include/lldb/Breakpoint/BreakpointResolverFileLine.h +++ b/contrib/llvm-project/lldb/include/lldb/Breakpoint/BreakpointResolverFileLine.h @@ -11,6 +11,7 @@ #include "lldb/Breakpoint/BreakpointResolver.h" #include "lldb/Core/SourceLocationSpec.h" +#include <optional> namespace lldb_private { @@ -21,9 +22,10 @@ namespace lldb_private { class BreakpointResolverFileLine : public BreakpointResolver { public: - BreakpointResolverFileLine(const lldb::BreakpointSP &bkpt, - lldb::addr_t offset, bool skip_prologue, - const SourceLocationSpec &location_spec); + BreakpointResolverFileLine( + const lldb::BreakpointSP &bkpt, lldb::addr_t offset, bool skip_prologue, + const SourceLocationSpec &location_spec, + std::optional<llvm::StringRef> removed_prefix_opt = std::nullopt); static BreakpointResolver * CreateFromStructuredData(const lldb::BreakpointSP &bkpt, @@ -56,11 +58,15 @@ public: CopyForBreakpoint(lldb::BreakpointSP &breakpoint) override; protected: - void FilterContexts(SymbolContextList &sc_list, bool is_relative); + void FilterContexts(SymbolContextList &sc_list); + void DeduceSourceMapping(SymbolContextList &sc_list); friend class Breakpoint; SourceLocationSpec m_location_spec; bool m_skip_prologue; + // Any previously removed file path prefix by reverse source mapping. + // This is used to auto deduce source map if needed. + std::optional<llvm::StringRef> m_removed_prefix_opt; private: BreakpointResolverFileLine(const BreakpointResolverFileLine &) = delete; diff --git a/contrib/llvm-project/lldb/include/lldb/Breakpoint/Watchpoint.h b/contrib/llvm-project/lldb/include/lldb/Breakpoint/Watchpoint.h index 41b723a66b6a..a5a72e3ad5a1 100644 --- a/contrib/llvm-project/lldb/include/lldb/Breakpoint/Watchpoint.h +++ b/contrib/llvm-project/lldb/include/lldb/Breakpoint/Watchpoint.h @@ -75,7 +75,7 @@ public: bool IsHardware() const override; bool ShouldStop(StoppointCallbackContext *context) override; - + bool WatchpointRead() const; bool WatchpointWrite() const; uint32_t GetIgnoreCount() const; @@ -157,12 +157,15 @@ public: private: friend class Target; friend class WatchpointList; + friend class StopInfoWatchpoint; // This needs to call UndoHitCount() void ResetHistoricValues() { m_old_value_sp.reset(); m_new_value_sp.reset(); } + void UndoHitCount() { m_hit_counter.Decrement(); } + Target &m_target; bool m_enabled; // Is this watchpoint enabled bool m_is_hardware; // Is this a hardware watchpoint diff --git a/contrib/llvm-project/lldb/include/lldb/Core/Communication.h b/contrib/llvm-project/lldb/include/lldb/Core/Communication.h index 44b3a16a0526..f5f636816cb4 100644 --- a/contrib/llvm-project/lldb/include/lldb/Core/Communication.h +++ b/contrib/llvm-project/lldb/include/lldb/Core/Communication.h @@ -9,22 +9,15 @@ #ifndef LLDB_CORE_COMMUNICATION_H #define LLDB_CORE_COMMUNICATION_H -#include "lldb/Host/HostThread.h" -#include "lldb/Utility/Broadcaster.h" #include "lldb/Utility/Timeout.h" #include "lldb/lldb-defines.h" #include "lldb/lldb-enumerations.h" #include "lldb/lldb-forward.h" #include "lldb/lldb-types.h" -#include <atomic> #include <mutex> -#include <ratio> #include <string> -#include <cstddef> -#include <cstdint> - namespace lldb_private { class Connection; class ConstString; @@ -38,90 +31,22 @@ class Status; /// approach has a couple of advantages: it allows a single instance of this /// class to be used even though its connection can change. Connections could /// negotiate for different connections based on abilities like starting with -/// Bluetooth and negotiating up to WiFi if available. It also allows this -/// class to be subclassed by any interfaces that don't want to give bytes but -/// want to validate and give out packets. This can be done by overriding: -/// -/// AppendBytesToCache (const uint8_t *src, size_t src_len, bool broadcast); -/// -/// Communication inherits from Broadcaster which means it can be used in -/// conjunction with Listener to wait for multiple broadcaster objects and -/// multiple events from each of those objects. Communication defines a set of -/// pre-defined event bits (see enumerations definitions that start with -/// "eBroadcastBit" below). -/// -/// There are two modes in which communications can occur: -/// \li single-threaded -/// \li multi-threaded -/// -/// In single-threaded mode, all reads and writes happen synchronously on the -/// calling thread. -/// -/// In multi-threaded mode, a read thread is spawned that continually reads -/// data and caches any received bytes. To start the read thread clients call: -/// -/// bool Communication::StartReadThread (Status *); -/// -/// If true is returned a read thread has been spawned that will continually -/// execute a call to the pure virtual DoRead function: +/// Bluetooth and negotiating up to WiFi if available. /// -/// size_t Communication::ReadFromConnection (void *, size_t, uint32_t); -/// -/// When bytes are received the data gets cached in \a m_bytes and this class -/// will broadcast a \b eBroadcastBitReadThreadGotBytes event. Clients that -/// want packet based communication should override AppendBytesToCache. The -/// subclasses can choose to call the built in AppendBytesToCache with the \a -/// broadcast parameter set to false. This will cause the \b -/// eBroadcastBitReadThreadGotBytes event not get broadcast, and then the -/// subclass can post a \b eBroadcastBitPacketAvailable event when a full -/// packet of data has been received. -/// -/// If the connection is disconnected a \b eBroadcastBitDisconnected event -/// gets broadcast. If the read thread exits a \b -/// eBroadcastBitReadThreadDidExit event will be broadcast. Clients can also -/// post a \b eBroadcastBitReadThreadShouldExit event to this object which -/// will cause the read thread to exit. -class Communication : public Broadcaster { +/// When using this class, all reads and writes happen synchronously on the +/// calling thread. There is also a ThreadedCommunication class that supports +/// multi-threaded mode. +class Communication { public: - FLAGS_ANONYMOUS_ENUM(){ - eBroadcastBitDisconnected = - (1u << 0), ///< Sent when the communications connection is lost. - eBroadcastBitReadThreadGotBytes = - (1u << 1), ///< Sent by the read thread when bytes become available. - eBroadcastBitReadThreadDidExit = - (1u - << 2), ///< Sent by the read thread when it exits to inform clients. - eBroadcastBitReadThreadShouldExit = - (1u << 3), ///< Sent by clients that need to cancel the read thread. - eBroadcastBitPacketAvailable = - (1u << 4), ///< Sent when data received makes a complete packet. - eBroadcastBitNoMorePendingInput = (1u << 5), ///< Sent by the read thread - ///to indicate all pending - ///input has been processed. - kLoUserBroadcastBit = - (1u << 16), ///< Subclasses can used bits 31:16 for any needed events. - kHiUserBroadcastBit = (1u << 31), - eAllEventBits = 0xffffffff}; - - typedef void (*ReadThreadBytesReceived)(void *baton, const void *src, - size_t src_len); - - /// Construct the Communication object with the specified name for the - /// Broadcaster that this object inherits from. - /// - /// \param[in] broadcaster_name - /// The name of the broadcaster object. This name should be as - /// complete as possible to uniquely identify this object. The - /// broadcaster name can be updated after the connect function - /// is called. - Communication(const char *broadcaster_name); + /// Construct the Communication object. + Communication(); /// Destructor. /// /// The destructor is virtual since this class gets subclassed. - ~Communication() override; + virtual ~Communication(); - void Clear(); + virtual void Clear(); /// Connect using the current connection by passing \a url to its connect /// function. string. @@ -148,7 +73,7 @@ public: /// /// \see Status& Communication::GetError (); /// \see bool Connection::Disconnect (); - lldb::ConnectionStatus Disconnect(Status *error_ptr = nullptr); + virtual lldb::ConnectionStatus Disconnect(Status *error_ptr = nullptr); /// Check if the connection is valid. /// @@ -166,13 +91,6 @@ public: /// If no read thread is running, this function call the connection's /// Connection::Read(...) function to get any available. /// - /// If a read thread has been started, this function will check for any - /// cached bytes that have already been read and return any currently - /// available bytes. If no bytes are cached, it will wait for the bytes to - /// become available by listening for the \a eBroadcastBitReadThreadGotBytes - /// event. If this function consumes all of the bytes in the cache, it will - /// reset the \a eBroadcastBitReadThreadGotBytes event bit. - /// /// \param[in] dst /// A destination buffer that must be at least \a dst_len bytes /// long. @@ -182,14 +100,15 @@ public: /// number of bytes that can be placed into \a dst. /// /// \param[in] timeout - /// A timeout value or llvm::None for no timeout. + /// A timeout value or std::nullopt for no timeout. /// /// \return /// The number of bytes actually read. /// /// \see size_t Connection::Read (void *, size_t); - size_t Read(void *dst, size_t dst_len, const Timeout<std::micro> &timeout, - lldb::ConnectionStatus &status, Status *error_ptr); + virtual size_t Read(void *dst, size_t dst_len, + const Timeout<std::micro> &timeout, + lldb::ConnectionStatus &status, Status *error_ptr); /// The actual write function that attempts to write to the communications /// protocol. @@ -237,69 +156,7 @@ public: /// /// \see /// class Connection - void SetConnection(std::unique_ptr<Connection> connection); - - /// Starts a read thread whose sole purpose it to read bytes from the - /// current connection. This function will call connection's read function: - /// - /// size_t Connection::Read (void *, size_t); - /// - /// When bytes are read and cached, this function will call: - /// - /// Communication::AppendBytesToCache (const uint8_t * bytes, size_t len, - /// bool - /// broadcast); - /// - /// Subclasses should override this function if they wish to override the - /// default action of caching the bytes and broadcasting a \b - /// eBroadcastBitReadThreadGotBytes event. - /// - /// \return - /// \b True if the read thread was successfully started, \b - /// false otherwise. - /// - /// \see size_t Connection::Read (void *, size_t); - /// \see void Communication::AppendBytesToCache (const uint8_t * bytes, - /// size_t len, bool broadcast); - virtual bool StartReadThread(Status *error_ptr = nullptr); - - /// Stops the read thread by cancelling it. - /// - /// \return - /// \b True if the read thread was successfully canceled, \b - /// false otherwise. - virtual bool StopReadThread(Status *error_ptr = nullptr); - - virtual bool JoinReadThread(Status *error_ptr = nullptr); - /// Checks if there is a currently running read thread. - /// - /// \return - /// \b True if the read thread is running, \b false otherwise. - bool ReadThreadIsRunning(); - - /// The read thread function. This function will call the "DoRead" - /// function continuously and wait for data to become available. When data - /// is received it will append the available data to the internal cache and - /// broadcast a \b eBroadcastBitReadThreadGotBytes event. - /// - /// \param[in] comm_ptr - /// A pointer to an instance of this class. - /// - /// \return - /// \b NULL. - /// - /// \see void Communication::ReadThreadGotBytes (const uint8_t *, size_t); - lldb::thread_result_t ReadThread(); - - void SetReadThreadBytesReceivedCallback(ReadThreadBytesReceived callback, - void *callback_baton); - - /// Wait for the read thread to process all outstanding data. - /// - /// After this function returns, the read thread has processed all data that - /// has been waiting in the Connection queue. - /// - void SynchronizeWithReadThread(); + virtual void SetConnection(std::unique_ptr<Connection> connection); static std::string ConnectionStatusAsString(lldb::ConnectionStatus status); @@ -307,73 +164,17 @@ public: void SetCloseOnEOF(bool b) { m_close_on_eof = b; } - static ConstString &GetStaticBroadcasterClass(); - - ConstString &GetBroadcasterClass() const override { - return GetStaticBroadcasterClass(); - } - protected: lldb::ConnectionSP m_connection_sp; ///< The connection that is current in use ///by this communications class. - HostThread m_read_thread; ///< The read thread handle in case we need to - ///cancel the thread. - std::atomic<bool> m_read_thread_enabled; - std::atomic<bool> m_read_thread_did_exit; - std::string - m_bytes; ///< A buffer to cache bytes read in the ReadThread function. - std::recursive_mutex m_bytes_mutex; ///< A mutex to protect multi-threaded - ///access to the cached bytes. std::mutex m_write_mutex; ///< Don't let multiple threads write at the same time... - std::mutex m_synchronize_mutex; - ReadThreadBytesReceived m_callback; - void *m_callback_baton; bool m_close_on_eof; size_t ReadFromConnection(void *dst, size_t dst_len, const Timeout<std::micro> &timeout, lldb::ConnectionStatus &status, Status *error_ptr); - /// Append new bytes that get read from the read thread into the internal - /// object byte cache. This will cause a \b eBroadcastBitReadThreadGotBytes - /// event to be broadcast if \a broadcast is true. - /// - /// Subclasses can override this function in order to inspect the received - /// data and check if a packet is available. - /// - /// Subclasses can also still call this function from the overridden method - /// to allow the caching to correctly happen and suppress the broadcasting - /// of the \a eBroadcastBitReadThreadGotBytes event by setting \a broadcast - /// to false. - /// - /// \param[in] src - /// A source buffer that must be at least \a src_len bytes - /// long. - /// - /// \param[in] src_len - /// The number of bytes to append to the cache. - virtual void AppendBytesToCache(const uint8_t *src, size_t src_len, - bool broadcast, - lldb::ConnectionStatus status); - - /// Get any available bytes from our data cache. If this call empties the - /// data cache, the \b eBroadcastBitReadThreadGotBytes event will be reset - /// to signify no more bytes are available. - /// - /// \param[in] dst - /// A destination buffer that must be at least \a dst_len bytes - /// long. - /// - /// \param[in] dst_len - /// The number of bytes to attempt to read from the cache, - /// and also the max number of bytes that can be placed into - /// \a dst. - /// - /// \return - /// The number of bytes extracted from the data cache. - size_t GetCachedBytes(void *dst, size_t dst_len); - private: Communication(const Communication &) = delete; const Communication &operator=(const Communication &) = delete; diff --git a/contrib/llvm-project/lldb/include/lldb/Core/DataFileCache.h b/contrib/llvm-project/lldb/include/lldb/Core/DataFileCache.h index 2dc69f6ce6b0..8a233afaff38 100644 --- a/contrib/llvm-project/lldb/include/lldb/Core/DataFileCache.h +++ b/contrib/llvm-project/lldb/include/lldb/Core/DataFileCache.h @@ -14,8 +14,12 @@ #include "lldb/Utility/UUID.h" #include "lldb/lldb-forward.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/Support/CachePruning.h" #include "llvm/Support/Caching.h" +#include "llvm/Support/MemoryBuffer.h" + #include <mutex> +#include <optional> namespace lldb_private { @@ -40,11 +44,18 @@ namespace lldb_private { class DataFileCache { public: - /// Create a data file cache in the directory path that is specified. + /// Create a data file cache in the directory path that is specified, using + /// the specified policy. /// /// Data will be cached in files created in this directory when clients call /// DataFileCache::SetCacheData. - DataFileCache(llvm::StringRef path); + DataFileCache(llvm::StringRef path, + llvm::CachePruningPolicy policy = + DataFileCache::GetLLDBIndexCachePolicy()); + + /// Gets the default LLDB index cache policy, which is controlled by the + /// "LLDBIndexCache" family of settings. + static llvm::CachePruningPolicy GetLLDBIndexCachePolicy(); /// Get cached data from the cache directory for the specified key. /// @@ -97,13 +108,13 @@ private: /// it is out of date. struct CacheSignature { /// UUID of object file or module. - llvm::Optional<UUID> m_uuid = llvm::None; + std::optional<UUID> m_uuid; /// Modification time of file on disk. - llvm::Optional<std::time_t> m_mod_time = llvm::None; + std::optional<std::time_t> m_mod_time; /// If this describes a .o file with a BSD archive, the BSD archive's /// modification time will be in m_mod_time, and the .o file's modification /// time will be in this m_obj_mod_time. - llvm::Optional<std::time_t> m_obj_mod_time = llvm::None; + std::optional<std::time_t> m_obj_mod_time; CacheSignature() = default; @@ -114,9 +125,9 @@ struct CacheSignature { CacheSignature(lldb_private::ObjectFile *objfile); void Clear() { - m_uuid = llvm::None; - m_mod_time = llvm::None; - m_obj_mod_time = llvm::None; + m_uuid = std::nullopt; + m_mod_time = std::nullopt; + m_obj_mod_time = std::nullopt; } /// Return true only if the CacheSignature is valid. diff --git a/contrib/llvm-project/lldb/include/lldb/Core/Debugger.h b/contrib/llvm-project/lldb/include/lldb/Core/Debugger.h index 031c9a9674d7..dd3e6c061fcf 100644 --- a/contrib/llvm-project/lldb/include/lldb/Core/Debugger.h +++ b/contrib/llvm-project/lldb/include/lldb/Core/Debugger.h @@ -12,6 +12,7 @@ #include <cstdint> #include <memory> +#include <optional> #include <vector> #include "lldb/Core/DebuggerEvents.h" @@ -82,6 +83,7 @@ public: eBroadcastBitProgress = (1 << 0), eBroadcastBitWarning = (1 << 1), eBroadcastBitError = (1 << 2), + eBroadcastSymbolChange = (1 << 3), }; static ConstString GetStaticBroadcasterClass(); @@ -151,11 +153,7 @@ public: Status SetInputString(const char *data); - // This method will setup data recorder if reproducer enabled. - // On reply mode this method should take instructions from reproducer file. - Status SetInputFile(lldb::FileSP file); - - void SetInputFile(lldb::FileSP file, repro::DataRecorder *recorder); + void SetInputFile(lldb::FileSP file); void SetOutputFile(lldb::FileSP file); @@ -176,7 +174,7 @@ public: ScriptInterpreter * GetScriptInterpreter(bool can_create = true, - llvm::Optional<lldb::ScriptLanguage> language = {}); + std::optional<lldb::ScriptLanguage> language = {}); lldb::ListenerSP GetListener() { return m_listener_sp; } @@ -293,8 +291,6 @@ public: void SetPrompt(llvm::StringRef p); void SetPrompt(const char *) = delete; - llvm::StringRef GetReproducerPath() const; - bool GetUseExternalEditor() const; bool SetUseExternalEditor(bool use_external_editor_p); @@ -353,6 +349,8 @@ public: bool SetTabSize(uint32_t tab_size); + lldb::DWIMPrintVerbosity GetDWIMPrintVerbosity() const; + bool GetEscapeNonPrintables() const; bool GetNotifyVoid() const; @@ -388,29 +386,29 @@ public: /// Report warning events. /// - /// Progress events will be delivered to any debuggers that have listeners - /// for the eBroadcastBitError. + /// Warning events will be delivered to any debuggers that have listeners + /// for the eBroadcastBitWarning. /// /// \param[in] message /// The warning message to be reported. /// /// \param [in] debugger_id /// If this optional parameter has a value, it indicates the unique - /// debugger identifier that this progress should be delivered to. If this - /// optional parameter does not have a value, the progress will be - /// delivered to all debuggers. + /// debugger identifier that this diagnostic should be delivered to. If + /// this optional parameter does not have a value, the diagnostic event + /// will be delivered to all debuggers. /// /// \param [in] once /// If a pointer is passed to a std::once_flag, then it will be used to /// ensure the given warning is only broadcast once. static void - ReportWarning(std::string messsage, - llvm::Optional<lldb::user_id_t> debugger_id = llvm::None, + ReportWarning(std::string message, + std::optional<lldb::user_id_t> debugger_id = std::nullopt, std::once_flag *once = nullptr); /// Report error events. /// - /// Progress events will be delivered to any debuggers that have listeners + /// Error events will be delivered to any debuggers that have listeners /// for the eBroadcastBitError. /// /// \param[in] message @@ -418,18 +416,40 @@ public: /// /// \param [in] debugger_id /// If this optional parameter has a value, it indicates the unique - /// debugger identifier that this progress should be delivered to. If this - /// optional parameter does not have a value, the progress will be - /// delivered to all debuggers. + /// debugger identifier that this diagnostic should be delivered to. If + /// this optional parameter does not have a value, the diagnostic event + /// will be delivered to all debuggers. /// /// \param [in] once /// If a pointer is passed to a std::once_flag, then it will be used to /// ensure the given error is only broadcast once. static void - ReportError(std::string messsage, - llvm::Optional<lldb::user_id_t> debugger_id = llvm::None, + ReportError(std::string message, + std::optional<lldb::user_id_t> debugger_id = std::nullopt, std::once_flag *once = nullptr); + /// Report info events. + /// + /// Unlike warning and error events, info events are not broadcast but are + /// logged for diagnostic purposes. + /// + /// \param[in] message + /// The info message to be reported. + /// + /// \param [in] debugger_id + /// If this optional parameter has a value, it indicates this diagnostic is + /// associated with a unique debugger instance. + /// + /// \param [in] once + /// If a pointer is passed to a std::once_flag, then it will be used to + /// ensure the given info is only logged once. + static void + ReportInfo(std::string message, + std::optional<lldb::user_id_t> debugger_id = std::nullopt, + std::once_flag *once = nullptr); + + static void ReportSymbolChange(const ModuleSpec &module_spec); + protected: friend class CommandInterpreter; friend class REPL; @@ -466,11 +486,11 @@ protected: /// delivered to all debuggers. static void ReportProgress(uint64_t progress_id, const std::string &message, uint64_t completed, uint64_t total, - llvm::Optional<lldb::user_id_t> debugger_id); + std::optional<lldb::user_id_t> debugger_id); static void ReportDiagnosticImpl(DiagnosticEventData::Type type, std::string message, - llvm::Optional<lldb::user_id_t> debugger_id, + std::optional<lldb::user_id_t> debugger_id, std::once_flag *once); void PrintProgress(const ProgressEventData &data); @@ -554,7 +574,7 @@ protected: IOHandlerStack m_io_handler_stack; std::recursive_mutex m_io_handler_synchronous_mutex; - llvm::Optional<uint64_t> m_current_event_id; + std::optional<uint64_t> m_current_event_id; llvm::StringMap<std::weak_ptr<LogHandler>> m_stream_handlers; std::shared_ptr<CallbackLogHandler> m_callback_handler_sp; diff --git a/contrib/llvm-project/lldb/include/lldb/Core/DebuggerEvents.h b/contrib/llvm-project/lldb/include/lldb/Core/DebuggerEvents.h index b584b6285af8..f2e23a94e610 100644 --- a/contrib/llvm-project/lldb/include/lldb/Core/DebuggerEvents.h +++ b/contrib/llvm-project/lldb/include/lldb/Core/DebuggerEvents.h @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +#include "lldb/Core/ModuleSpec.h" #include "lldb/Utility/ConstString.h" #include "lldb/Utility/Event.h" @@ -51,6 +52,7 @@ private: class DiagnosticEventData : public EventData { public: enum class Type { + Info, Warning, Error, }; @@ -82,6 +84,28 @@ protected: const DiagnosticEventData &operator=(const DiagnosticEventData &) = delete; }; +class SymbolChangeEventData : public EventData { +public: + SymbolChangeEventData(lldb::DebuggerWP debugger_wp, ModuleSpec module_spec) + : m_debugger_wp(debugger_wp), m_module_spec(std::move(module_spec)) {} + + static ConstString GetFlavorString(); + ConstString GetFlavor() const override; + + static const SymbolChangeEventData * + GetEventDataFromEvent(const Event *event_ptr); + + void DoOnRemoval(Event *event_ptr) override; + +private: + lldb::DebuggerWP m_debugger_wp; + ModuleSpec m_module_spec; + + SymbolChangeEventData(const SymbolChangeEventData &) = delete; + const SymbolChangeEventData & + operator=(const SymbolChangeEventData &) = delete; +}; + } // namespace lldb_private #endif // LLDB_CORE_DEBUGGER_EVENTS_H diff --git a/contrib/llvm-project/lldb/include/lldb/Core/DumpRegisterValue.h b/contrib/llvm-project/lldb/include/lldb/Core/DumpRegisterValue.h index 443fdb34266a..08bf0af8f36b 100644 --- a/contrib/llvm-project/lldb/include/lldb/Core/DumpRegisterValue.h +++ b/contrib/llvm-project/lldb/include/lldb/Core/DumpRegisterValue.h @@ -14,16 +14,18 @@ namespace lldb_private { +class ExecutionContextScope; class RegisterValue; struct RegisterInfo; class Stream; // The default value of 0 for reg_name_right_align_at means no alignment at // all. -bool DumpRegisterValue(const RegisterValue ®_val, Stream *s, +void DumpRegisterValue(const RegisterValue ®_val, Stream *s, const RegisterInfo *reg_info, bool prefix_with_name, bool prefix_with_alt_name, lldb::Format format, - uint32_t reg_name_right_align_at = 0); + uint32_t reg_name_right_align_at = 0, + ExecutionContextScope *exe_scope = nullptr); } // namespace lldb_private diff --git a/contrib/llvm-project/lldb/include/lldb/Core/EmulateInstruction.h b/contrib/llvm-project/lldb/include/lldb/Core/EmulateInstruction.h index e5421e5e91d1..6d76380ce659 100644 --- a/contrib/llvm-project/lldb/include/lldb/Core/EmulateInstruction.h +++ b/contrib/llvm-project/lldb/include/lldb/Core/EmulateInstruction.h @@ -9,6 +9,7 @@ #ifndef LLDB_CORE_EMULATEINSTRUCTION_H #define LLDB_CORE_EMULATEINSTRUCTION_H +#include <optional> #include <string> #include "lldb/Core/Address.h" @@ -183,8 +184,13 @@ public: struct Context { ContextType type = eContextInvalid; + + private: enum InfoType info_type = eInfoTypeNoArgs; - union { + + public: + enum InfoType GetInfoType() const { return info_type; } + union ContextInfo { struct RegisterPlusOffset { RegisterInfo reg; // base register int64_t signed_offset; // signed offset added to base register @@ -236,6 +242,8 @@ public: uint32_t isa; } info; + static_assert(std::is_trivial<ContextInfo>::value, + "ContextInfo must be trivial."); Context() = default; @@ -370,8 +378,8 @@ public: virtual bool TestEmulation(Stream *out_stream, ArchSpec &arch, OptionValueDictionary *test_data) = 0; - virtual bool GetRegisterInfo(lldb::RegisterKind reg_kind, uint32_t reg_num, - RegisterInfo ®_info) = 0; + virtual std::optional<RegisterInfo> + GetRegisterInfo(lldb::RegisterKind reg_kind, uint32_t reg_num) = 0; // Optional overrides virtual bool SetInstruction(const Opcode &insn_opcode, @@ -383,16 +391,16 @@ public: uint32_t reg_num, std::string ®_name); // RegisterInfo variants - bool ReadRegister(const RegisterInfo *reg_info, RegisterValue ®_value); + std::optional<RegisterValue> ReadRegister(const RegisterInfo ®_info); - uint64_t ReadRegisterUnsigned(const RegisterInfo *reg_info, + uint64_t ReadRegisterUnsigned(const RegisterInfo ®_info, uint64_t fail_value, bool *success_ptr); - bool WriteRegister(const Context &context, const RegisterInfo *ref_info, + bool WriteRegister(const Context &context, const RegisterInfo &ref_info, const RegisterValue ®_value); bool WriteRegisterUnsigned(const Context &context, - const RegisterInfo *reg_info, uint64_t reg_value); + const RegisterInfo ®_info, uint64_t reg_value); // Register kind and number variants bool ReadRegister(lldb::RegisterKind reg_kind, uint32_t reg_num, diff --git a/contrib/llvm-project/lldb/include/lldb/Core/FileSpecList.h b/contrib/llvm-project/lldb/include/lldb/Core/FileSpecList.h index 117c6b691498..a5720d85e7cd 100644 --- a/contrib/llvm-project/lldb/include/lldb/Core/FileSpecList.h +++ b/contrib/llvm-project/lldb/include/lldb/Core/FileSpecList.h @@ -116,6 +116,32 @@ public: /// else UINT32_MAX is returned. size_t FindFileIndex(size_t idx, const FileSpec &file, bool full) const; + /// Find a compatible file index. + /// + /// Find the index of a compatible file in the file spec list that matches \a + /// file starting \a idx entries into the file spec list. A file is considered + /// compatible if: + /// - The file matches exactly (only filename if \a file has no directory) + /// - If \a file is relative and any file in the list has this same suffix + /// - If any file in the list is relative and the relative path is a suffix + /// of \a file + /// + /// This is used to implement better matching for setting breakpoints in + /// source files where an IDE might specify a full path when setting the + /// breakpoint and debug info contains relative paths, if a user specifies + /// a relative path when setting a breakpoint. + /// + /// \param[in] idx + /// An index into the file list. + /// + /// \param[in] file + /// The file specification to search for. + /// + /// \return + /// The index of the file that matches \a file if it is found, + /// else UINT32_MAX is returned. + size_t FindCompatibleIndex(size_t idx, const FileSpec &file) const; + /// Get file at index. /// /// Gets a file from the file list. If \a idx is not a valid index, an empty diff --git a/contrib/llvm-project/lldb/include/lldb/Core/FormatEntity.h b/contrib/llvm-project/lldb/include/lldb/Core/FormatEntity.h index cd9019d55554..a4972be514cf 100644 --- a/contrib/llvm-project/lldb/include/lldb/Core/FormatEntity.h +++ b/contrib/llvm-project/lldb/include/lldb/Core/FormatEntity.h @@ -241,6 +241,17 @@ public: llvm::StringRef elements, llvm::StringRef element_format); + /// For each variable in 'args' this function writes the variable + /// name and it's pretty-printed value representation to 'out_stream' + /// in following format: + /// + /// \verbatim + /// name_1=repr_1, name_2=repr_2 ... + /// \endverbatim + static void PrettyPrintFunctionArguments(Stream &out_stream, + VariableList const &args, + ExecutionContextScope *exe_scope); + protected: static Status ParseInternal(llvm::StringRef &format, Entry &parent_entry, uint32_t depth); diff --git a/contrib/llvm-project/lldb/include/lldb/Core/Highlighter.h b/contrib/llvm-project/lldb/include/lldb/Core/Highlighter.h index b138e57af419..58ecd37180e5 100644 --- a/contrib/llvm-project/lldb/include/lldb/Core/Highlighter.h +++ b/contrib/llvm-project/lldb/include/lldb/Core/Highlighter.h @@ -9,6 +9,7 @@ #ifndef LLDB_CORE_HIGHLIGHTER_H #define LLDB_CORE_HIGHLIGHTER_H +#include <optional> #include <utility> #include <vector> @@ -112,12 +113,12 @@ public: /// The stream to which the highlighted version of the user string should /// be written. virtual void Highlight(const HighlightStyle &options, llvm::StringRef line, - llvm::Optional<size_t> cursor_pos, + std::optional<size_t> cursor_pos, llvm::StringRef previous_lines, Stream &s) const = 0; /// Utility method for calling Highlight without a stream. std::string Highlight(const HighlightStyle &options, llvm::StringRef line, - llvm::Optional<size_t> cursor_pos, + std::optional<size_t> cursor_pos, llvm::StringRef previous_lines = "") const; }; @@ -128,7 +129,7 @@ public: llvm::StringRef GetName() const override { return "none"; } void Highlight(const HighlightStyle &options, llvm::StringRef line, - llvm::Optional<size_t> cursor_pos, + std::optional<size_t> cursor_pos, llvm::StringRef previous_lines, Stream &s) const override; }; diff --git a/contrib/llvm-project/lldb/include/lldb/Core/IOHandler.h b/contrib/llvm-project/lldb/include/lldb/Core/IOHandler.h index 2ba421f7ba50..18d87acbd872 100644 --- a/contrib/llvm-project/lldb/include/lldb/Core/IOHandler.h +++ b/contrib/llvm-project/lldb/include/lldb/Core/IOHandler.h @@ -23,6 +23,7 @@ #include <memory> #include <mutex> +#include <optional> #include <string> #include <vector> @@ -31,9 +32,6 @@ namespace lldb_private { class Debugger; -namespace repro { -class DataRecorder; -} } // namespace lldb_private namespace curses { @@ -63,8 +61,7 @@ public: IOHandler(Debugger &debugger, IOHandler::Type type, const lldb::FileSP &input_sp, const lldb::StreamFileSP &output_sp, - const lldb::StreamFileSP &error_sp, uint32_t flags, - repro::DataRecorder *data_recorder); + const lldb::StreamFileSP &error_sp, uint32_t flags); virtual ~IOHandler(); @@ -173,7 +170,6 @@ protected: lldb::StreamFileSP m_output_sp; lldb::StreamFileSP m_error_sp; std::recursive_mutex m_output_mutex; - repro::DataRecorder *m_data_recorder; Predicate<bool> m_popped; Flags m_flags; Type m_type; @@ -205,8 +201,8 @@ public: virtual void IOHandlerDeactivated(IOHandler &io_handler) {} - virtual llvm::Optional<std::string> IOHandlerSuggestion(IOHandler &io_handler, - llvm::StringRef line); + virtual std::optional<std::string> IOHandlerSuggestion(IOHandler &io_handler, + llvm::StringRef line); virtual void IOHandlerComplete(IOHandler &io_handler, CompletionRequest &request); @@ -338,8 +334,7 @@ public: uint32_t line_number_start, // If non-zero show line numbers // starting at // 'line_number_start' - IOHandlerDelegate &delegate, - repro::DataRecorder *data_recorder); + IOHandlerDelegate &delegate); IOHandlerEditline(Debugger &debugger, IOHandler::Type type, const lldb::FileSP &input_sp, @@ -351,8 +346,7 @@ public: uint32_t line_number_start, // If non-zero show line numbers // starting at // 'line_number_start' - IOHandlerDelegate &delegate, - repro::DataRecorder *data_recorder); + IOHandlerDelegate &delegate); IOHandlerEditline(Debugger &, IOHandler::Type, const char *, const char *, const char *, bool, bool, uint32_t, @@ -424,7 +418,7 @@ private: int FixIndentationCallback(Editline *editline, const StringList &lines, int cursor_position); - llvm::Optional<std::string> SuggestionCallback(llvm::StringRef line); + std::optional<std::string> SuggestionCallback(llvm::StringRef line); void AutoCompleteCallback(CompletionRequest &request); #endif diff --git a/contrib/llvm-project/lldb/include/lldb/Core/LoadedModuleInfoList.h b/contrib/llvm-project/lldb/include/lldb/Core/LoadedModuleInfoList.h index 6ff456545840..537a2b0f1d37 100644 --- a/contrib/llvm-project/lldb/include/lldb/Core/LoadedModuleInfoList.h +++ b/contrib/llvm-project/lldb/include/lldb/Core/LoadedModuleInfoList.h @@ -95,10 +95,10 @@ public: protected: bool m_has[e_num]; std::string m_name; - lldb::addr_t m_link_map; - lldb::addr_t m_base; - bool m_base_is_offset; - lldb::addr_t m_dynamic; + lldb::addr_t m_link_map = LLDB_INVALID_ADDRESS; + lldb::addr_t m_base = LLDB_INVALID_ADDRESS; + bool m_base_is_offset = false; + lldb::addr_t m_dynamic = LLDB_INVALID_ADDRESS; }; LoadedModuleInfoList() = default; diff --git a/contrib/llvm-project/lldb/include/lldb/Core/Mangled.h b/contrib/llvm-project/lldb/include/lldb/Core/Mangled.h index aaefb69f017b..dcaa7a8cda6c 100644 --- a/contrib/llvm-project/lldb/include/lldb/Core/Mangled.h +++ b/contrib/llvm-project/lldb/include/lldb/Core/Mangled.h @@ -26,7 +26,7 @@ namespace lldb_private { /// /// Designed to handle mangled names. The demangled version of any names will /// be computed when the demangled name is accessed through the Demangled() -/// acccessor. This class can also tokenize the demangled version of the name +/// accessor. This class can also tokenize the demangled version of the name /// for powerful searches. Functions and symbols could make instances of this /// class for their mangled names. Uniqued string pools are used for the /// mangled, demangled, and token string values to allow for faster diff --git a/contrib/llvm-project/lldb/include/lldb/Core/Module.h b/contrib/llvm-project/lldb/include/lldb/Core/Module.h index cc3edbb3f1bb..31f7894178d7 100644 --- a/contrib/llvm-project/lldb/include/lldb/Core/Module.h +++ b/contrib/llvm-project/lldb/include/lldb/Core/Module.h @@ -29,6 +29,7 @@ #include "lldb/lldb-types.h" #include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/STLFunctionalExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Chrono.h" @@ -37,6 +38,7 @@ #include <cstdint> #include <memory> #include <mutex> +#include <optional> #include <string> #include <vector> @@ -85,6 +87,7 @@ struct ModuleFunctionSearchOptions { class Module : public std::enable_shared_from_this<Module>, public SymbolContextScope { public: + class LookupInfo; // Static functions that can track the lifetime of module objects. This is // handy because we might have Module objects that are in shared pointers // that aren't in the global module list (from ModuleList). If this is the @@ -261,9 +264,10 @@ public: lldb::SymbolType symbol_type, SymbolContextList &sc_list); - void FindSymbolsMatchingRegExAndType(const RegularExpression ®ex, - lldb::SymbolType symbol_type, - SymbolContextList &sc_list); + void FindSymbolsMatchingRegExAndType( + const RegularExpression ®ex, lldb::SymbolType symbol_type, + SymbolContextList &sc_list, + Mangled::NamePreference mangling_preference = Mangled::ePreferDemangled); /// Find a function symbols in the object file's symbol table. /// @@ -293,6 +297,23 @@ public: /// matches. void FindCompileUnits(const FileSpec &path, SymbolContextList &sc_list); + /// Find functions by lookup info. + /// + /// If the function is an inlined function, it will have a block, + /// representing the inlined function, and the function will be the + /// containing function. If it is not inlined, then the block will be NULL. + /// + /// \param[in] lookup_info + /// The lookup info of the function we are looking for. + /// + /// \param[out] sc_list + /// A symbol context list that gets filled in with all of the + /// matches. + void FindFunctions(const LookupInfo &lookup_info, + const CompilerDeclContext &parent_decl_ctx, + const ModuleFunctionSearchOptions &options, + SymbolContextList &sc_list); + /// Find functions by name. /// /// If the function is an inlined function, it will have a block, @@ -792,36 +813,53 @@ public: bool GetIsDynamicLinkEditor(); - llvm::Expected<TypeSystem &> + llvm::Expected<lldb::TypeSystemSP> GetTypeSystemForLanguage(lldb::LanguageType language); + /// Call \p callback for each \p TypeSystem in this \p Module. + /// Return true from callback to keep iterating, false to stop iterating. + void ForEachTypeSystem(llvm::function_ref<bool(lldb::TypeSystemSP)> callback); + // Special error functions that can do printf style formatting that will // prepend the message with something appropriate for this module (like the // architecture, path and object name (if any)). This centralizes code so // that everyone doesn't need to format their error and log messages on their // own and keeps the output a bit more consistent. - void LogMessage(Log *log, const char *format, ...) - __attribute__((format(printf, 3, 4))); + template <typename... Args> + void LogMessage(Log *log, const char *format, Args &&...args) { + LogMessage(log, llvm::formatv(format, std::forward<Args>(args)...)); + } - void LogMessageVerboseBacktrace(Log *log, const char *format, ...) - __attribute__((format(printf, 3, 4))); + template <typename... Args> + void LogMessageVerboseBacktrace(Log *log, const char *format, + Args &&...args) { + LogMessageVerboseBacktrace( + log, llvm::formatv(format, std::forward<Args>(args)...)); + } - void ReportWarning(const char *format, ...) - __attribute__((format(printf, 2, 3))); + template <typename... Args> + void ReportWarning(const char *format, Args &&...args) { + ReportWarning(llvm::formatv(format, std::forward<Args>(args)...)); + } - void ReportError(const char *format, ...) - __attribute__((format(printf, 2, 3))); + template <typename... Args> + void ReportError(const char *format, Args &&...args) { + ReportError(llvm::formatv(format, std::forward<Args>(args)...)); + } // Only report an error once when the module is first detected to be modified // so we don't spam the console with many messages. - void ReportErrorIfModifyDetected(const char *format, ...) - __attribute__((format(printf, 2, 3))); + template <typename... Args> + void ReportErrorIfModifyDetected(const char *format, Args &&...args) { + ReportErrorIfModifyDetected( + llvm::formatv(format, std::forward<Args>(args)...)); + } - void ReportWarningOptimization(llvm::Optional<lldb::user_id_t> debugger_id); + void ReportWarningOptimization(std::optional<lldb::user_id_t> debugger_id); void ReportWarningUnsupportedLanguage(lldb::LanguageType language, - llvm::Optional<lldb::user_id_t> debugger_id); + std::optional<lldb::user_id_t> debugger_id); // Return true if the file backing this module has changed since the module // was originally created since we saved the initial file modification time @@ -870,7 +908,7 @@ public: /// \return /// The newly remapped filespec that is may or may not exist if /// \a path was successfully located. - llvm::Optional<std::string> RemapSourceFile(llvm::StringRef path) const; + std::optional<std::string> RemapSourceFile(llvm::StringRef path) const; bool RemapSourceFile(const char *, std::string &) const = delete; /// Update the ArchSpec to a more specific variant. @@ -930,6 +968,12 @@ public: m_name_type_mask = mask; } + lldb::LanguageType GetLanguageType() const { return m_language; } + + bool NameMatchesLookupInfo( + ConstString function_name, + lldb::LanguageType language_type = lldb::eLanguageTypeUnknown) const; + void Prune(SymbolContextList &sc_list, size_t start_idx) const; protected: @@ -1023,9 +1067,9 @@ protected: lldb::ObjectFileSP m_objfile_sp; ///< A shared pointer to the object file /// parser for this module as it may or may /// not be shared with the SymbolFile - llvm::Optional<UnwindTable> m_unwind_table; ///< Table of FuncUnwinders - /// objects created for this - /// Module's functions + std::optional<UnwindTable> m_unwind_table; ///< Table of FuncUnwinders + /// objects created for this + /// Module's functions lldb::SymbolVendorUP m_symfile_up; ///< A pointer to the symbol vendor for this module. std::vector<lldb::SymbolVendorUP> @@ -1124,6 +1168,13 @@ private: Module(const Module &) = delete; const Module &operator=(const Module &) = delete; + + void LogMessage(Log *log, const llvm::formatv_object_base &payload); + void LogMessageVerboseBacktrace(Log *log, + const llvm::formatv_object_base &payload); + void ReportWarning(const llvm::formatv_object_base &payload); + void ReportError(const llvm::formatv_object_base &payload); + void ReportErrorIfModifyDetected(const llvm::formatv_object_base &payload); }; } // namespace lldb_private diff --git a/contrib/llvm-project/lldb/include/lldb/Core/ModuleList.h b/contrib/llvm-project/lldb/include/lldb/Core/ModuleList.h index 67205ca27e80..631d7889f367 100644 --- a/contrib/llvm-project/lldb/include/lldb/Core/ModuleList.h +++ b/contrib/llvm-project/lldb/include/lldb/Core/ModuleList.h @@ -60,6 +60,7 @@ public: bool SetClangModulesCachePath(const FileSpec &path); bool GetEnableExternalLookup() const; bool SetEnableExternalLookup(bool new_value); + bool GetEnableBackgroundLookup() const; bool GetEnableLLDBIndexCache() const; bool SetEnableLLDBIndexCache(bool new_value); uint64_t GetLLDBIndexCacheMaxByteSize(); @@ -457,13 +458,28 @@ public: static void FindSharedModules(const ModuleSpec &module_spec, ModuleList &matching_module_list); + static lldb::ModuleSP FindSharedModule(const UUID &uuid); + static size_t RemoveOrphanSharedModules(bool mandatory); static bool RemoveSharedModuleIfOrphaned(const Module *module_ptr); + /// Applies 'callback' to each module in this ModuleList. + /// If 'callback' returns false, iteration terminates. + /// The 'module_sp' passed to 'callback' is guaranteed to + /// be non-null. + /// + /// This function is thread-safe. void ForEach(std::function<bool(const lldb::ModuleSP &module_sp)> const &callback) const; + /// Returns true if 'callback' returns true for one of the modules + /// in this ModuleList. + /// + /// This function is thread-safe. + bool AnyOf( + std::function<bool(lldb_private::Module &module)> const &callback) const; + protected: // Class typedefs. typedef std::vector<lldb::ModuleSP> diff --git a/contrib/llvm-project/lldb/include/lldb/Core/PluginManager.h b/contrib/llvm-project/lldb/include/lldb/Core/PluginManager.h index 58be1d2b18dc..4e036e0d4caa 100644 --- a/contrib/llvm-project/lldb/include/lldb/Core/PluginManager.h +++ b/contrib/llvm-project/lldb/include/lldb/Core/PluginManager.h @@ -197,16 +197,20 @@ public: llvm::StringRef plugin_name); // ObjectContainer - static bool - RegisterPlugin(llvm::StringRef name, llvm::StringRef description, - ObjectContainerCreateInstance create_callback, - ObjectFileGetModuleSpecifications get_module_specifications); + static bool RegisterPlugin( + llvm::StringRef name, llvm::StringRef description, + ObjectContainerCreateInstance create_callback, + ObjectFileGetModuleSpecifications get_module_specifications, + ObjectContainerCreateMemoryInstance create_memory_callback = nullptr); static bool UnregisterPlugin(ObjectContainerCreateInstance create_callback); static ObjectContainerCreateInstance GetObjectContainerCreateCallbackAtIndex(uint32_t idx); + static ObjectContainerCreateMemoryInstance + GetObjectContainerCreateMemoryCallbackAtIndex(uint32_t idx); + static ObjectFileGetModuleSpecifications GetObjectContainerGetModuleSpecificationsCallbackAtIndex(uint32_t idx); @@ -338,7 +342,8 @@ public: llvm::StringRef name, llvm::StringRef description, TraceCreateInstanceFromBundle create_callback_from_bundle, TraceCreateInstanceForLiveProcess create_callback_for_live_process, - llvm::StringRef schema); + llvm::StringRef schema, + DebuggerInitializeCallback debugger_init_callback); static bool UnregisterPlugin(TraceCreateInstanceFromBundle create_callback); @@ -483,6 +488,10 @@ public: Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp, ConstString description, bool is_global_property); + static bool CreateSettingForTracePlugin( + Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp, + ConstString description, bool is_global_property); + static lldb::OptionValuePropertiesSP GetSettingForObjectFilePlugin(Debugger &debugger, ConstString setting_name); diff --git a/contrib/llvm-project/lldb/include/lldb/Core/Progress.h b/contrib/llvm-project/lldb/include/lldb/Core/Progress.h index f625d014f268..48078705ae6b 100644 --- a/contrib/llvm-project/lldb/include/lldb/Core/Progress.h +++ b/contrib/llvm-project/lldb/include/lldb/Core/Progress.h @@ -13,6 +13,7 @@ #include "lldb/lldb-types.h" #include <atomic> #include <mutex> +#include <optional> namespace lldb_private { @@ -102,7 +103,7 @@ private: const uint64_t m_total; /// The optional debugger ID to report progress to. If this has no value then /// all debuggers will receive this event. - llvm::Optional<lldb::user_id_t> m_debugger_id; + std::optional<lldb::user_id_t> m_debugger_id; /// Set to true when progress has been reported where m_completed == m_total /// to ensure that we don't send progress updates after progress has /// completed. diff --git a/contrib/llvm-project/lldb/include/lldb/Core/RichManglingContext.h b/contrib/llvm-project/lldb/include/lldb/Core/RichManglingContext.h index ecd11e93f044..3b79924e88a9 100644 --- a/contrib/llvm-project/lldb/include/lldb/Core/RichManglingContext.h +++ b/contrib/llvm-project/lldb/include/lldb/Core/RichManglingContext.h @@ -86,9 +86,9 @@ private: /// trait to deduce \a ParserT from a given InfoProvider, but unfortunately we /// can't access CPlusPlusLanguage::MethodName from within the header. template <class ParserT> static ParserT *get(llvm::Any parser) { - assert(parser.hasValue()); - assert(llvm::any_isa<ParserT *>(parser)); - return llvm::any_cast<ParserT *>(parser); + assert(parser.has_value()); + assert(llvm::any_cast<ParserT *>(&parser)); + return *llvm::any_cast<ParserT *>(&parser); } }; diff --git a/contrib/llvm-project/lldb/include/lldb/Core/SourceLocationSpec.h b/contrib/llvm-project/lldb/include/lldb/Core/SourceLocationSpec.h index 808931186dba..9c2512bff4b7 100644 --- a/contrib/llvm-project/lldb/include/lldb/Core/SourceLocationSpec.h +++ b/contrib/llvm-project/lldb/include/lldb/Core/SourceLocationSpec.h @@ -11,8 +11,8 @@ #include "lldb/Core/Declaration.h" #include "lldb/lldb-defines.h" -#include "llvm/ADT/Optional.h" +#include <optional> #include <string> namespace lldb_private { @@ -29,7 +29,7 @@ public: /// Constructor. /// /// Takes a \a file_spec with a \a line number and a \a column number. If - /// \a column is null or not provided, it is set to llvm::None. + /// \a column is null or not provided, it is set to std::nullopt. /// /// \param[in] file_spec /// The full or partial path to a file. @@ -47,7 +47,7 @@ public: /// Whether to look for an exact match. /// explicit SourceLocationSpec(FileSpec file_spec, uint32_t line, - llvm::Optional<uint16_t> column = llvm::None, + std::optional<uint16_t> column = std::nullopt, bool check_inlines = false, bool exact_match = false); @@ -165,9 +165,9 @@ public: FileSpec GetFileSpec() const { return m_declaration.GetFile(); } - llvm::Optional<uint32_t> GetLine() const; + std::optional<uint32_t> GetLine() const; - llvm::Optional<uint16_t> GetColumn() const; + std::optional<uint16_t> GetColumn() const; bool GetCheckInlines() const { return m_check_inlines; } diff --git a/contrib/llvm-project/lldb/include/lldb/Core/SourceManager.h b/contrib/llvm-project/lldb/include/lldb/Core/SourceManager.h index 5f2c1de84652..c272f7f43112 100644 --- a/contrib/llvm-project/lldb/include/lldb/Core/SourceManager.h +++ b/contrib/llvm-project/lldb/include/lldb/Core/SourceManager.h @@ -19,6 +19,7 @@ #include <cstdint> #include <map> #include <memory> +#include <optional> #include <string> #include <vector> @@ -41,7 +42,7 @@ public: void UpdateIfNeeded(); - size_t DisplaySourceLines(uint32_t line, llvm::Optional<size_t> column, + size_t DisplaySourceLines(uint32_t line, std::optional<size_t> column, uint32_t context_before, uint32_t context_after, Stream *s); void FindLinesMatchingRegex(RegularExpression ®ex, uint32_t start_line, diff --git a/contrib/llvm-project/lldb/include/lldb/Core/StructuredDataImpl.h b/contrib/llvm-project/lldb/include/lldb/Core/StructuredDataImpl.h index e755c53aaa9f..16dbc5263b28 100644 --- a/contrib/llvm-project/lldb/include/lldb/Core/StructuredDataImpl.h +++ b/contrib/llvm-project/lldb/include/lldb/Core/StructuredDataImpl.h @@ -80,7 +80,7 @@ public: error.SetErrorString("No data to describe."); return error; } - m_data_sp->Dump(stream, true); + m_data_sp->GetDescription(stream); return error; } // Get the data's description. diff --git a/contrib/llvm-project/lldb/include/lldb/Core/ThreadSafeValue.h b/contrib/llvm-project/lldb/include/lldb/Core/ThreadSafeValue.h index 979f008b3170..ddd7b56e82ce 100644 --- a/contrib/llvm-project/lldb/include/lldb/Core/ThreadSafeValue.h +++ b/contrib/llvm-project/lldb/include/lldb/Core/ThreadSafeValue.h @@ -42,6 +42,7 @@ public: // Call this if you have already manually locked the mutex using the // GetMutex() accessor + // coverity[missing_lock] void SetValueNoLock(const T &value) { m_value = value; } std::recursive_mutex &GetMutex() { return m_mutex; } diff --git a/contrib/llvm-project/lldb/include/lldb/Core/ThreadedCommunication.h b/contrib/llvm-project/lldb/include/lldb/Core/ThreadedCommunication.h new file mode 100644 index 000000000000..2e3afde3c058 --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/Core/ThreadedCommunication.h @@ -0,0 +1,288 @@ +//===-- ThreadedCommunication.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_CORE_THREADEDCOMMUNICATION_H +#define LLDB_CORE_THREADEDCOMMUNICATION_H + +#include "lldb/Core/Communication.h" +#include "lldb/Host/HostThread.h" +#include "lldb/Utility/Broadcaster.h" + +#include <atomic> +#include <mutex> +#include <string> + +#include <cstddef> +#include <cstdint> + +namespace lldb_private { + +/// \class ThreadedCommunication ThreadedCommunication.h +/// "lldb/Core/ThreadedCommunication.h" Variation of Communication that +/// supports threaded reads. +/// +/// ThreadedCommunication enhances the base Communication class with support +/// for multi-threaded mode. In this mode, a read thread is spawned that +/// continually reads data and caches any received bytes. To start the read +/// thread clients call: +/// +/// bool ThreadedCommunication::StartReadThread (Status *); +/// +/// If true is returned a read thread has been spawned that will continually +/// execute a call to the pure virtual DoRead function: +/// +/// size_t Communication::ReadFromConnection (void *, size_t, uint32_t); +/// +/// When bytes are received the data gets cached in \a m_bytes and this class +/// will broadcast a \b eBroadcastBitReadThreadGotBytes event. Clients that +/// want packet based communication should override AppendBytesToCache. The +/// subclasses can choose to call the built in AppendBytesToCache with the \a +/// broadcast parameter set to false. This will cause the \b +/// eBroadcastBitReadThreadGotBytes event not get broadcast, and then the +/// subclass can post a \b eBroadcastBitPacketAvailable event when a full +/// packet of data has been received. +/// +/// If the connection is disconnected a \b eBroadcastBitDisconnected event +/// gets broadcast. If the read thread exits a \b +/// eBroadcastBitReadThreadDidExit event will be broadcast. Clients can also +/// post a \b eBroadcastBitReadThreadShouldExit event to this object which +/// will cause the read thread to exit. +/// +/// ThreadedCommunication inherits from Broadcaster which means it can be used +/// in conjunction with Listener to wait for multiple broadcaster objects and +/// multiple events from each of those objects. ThreadedCommunication defines a +/// set of pre-defined event bits (see enumerations definitions that start with +/// "eBroadcastBit" below). +class ThreadedCommunication : public Communication, public Broadcaster { + using Communication::Communication; + +public: + FLAGS_ANONYMOUS_ENUM(){ + eBroadcastBitDisconnected = + (1u << 0), ///< Sent when the communications connection is lost. + eBroadcastBitReadThreadGotBytes = + (1u << 1), ///< Sent by the read thread when bytes become available. + eBroadcastBitReadThreadDidExit = + (1u + << 2), ///< Sent by the read thread when it exits to inform clients. + eBroadcastBitReadThreadShouldExit = + (1u << 3), ///< Sent by clients that need to cancel the read thread. + eBroadcastBitPacketAvailable = + (1u << 4), ///< Sent when data received makes a complete packet. + eBroadcastBitNoMorePendingInput = (1u << 5), ///< Sent by the read thread + /// to indicate all pending + /// input has been processed. + }; + + typedef void (*ReadThreadBytesReceived)(void *baton, const void *src, + size_t src_len); + + /// Construct the ThreadedCommunication object with the specified name for the + /// Broadcaster that this object inherits from. + /// + /// \param[in] broadcaster_name + /// The name of the broadcaster object. This name should be as + /// complete as possible to uniquely identify this object. The + /// broadcaster name can be updated after the connect function + /// is called. + ThreadedCommunication(const char *broadcaster_name); + + /// Destructor. + /// + /// The destructor is virtual since this class gets subclassed. + ~ThreadedCommunication() override; + + void Clear() override; + + /// Disconnect the communications connection if one is currently connected. + /// + /// \return + /// \b True if the disconnect succeeded, \b false otherwise. The + /// internal error object should be filled in with an + /// appropriate value based on the result of this function. + /// + /// \see Status& Communication::GetError (); + /// \see bool Connection::Disconnect (); + lldb::ConnectionStatus Disconnect(Status *error_ptr = nullptr) override; + + /// Read bytes from the current connection. + /// + /// If no read thread is running, this function call the connection's + /// Connection::Read(...) function to get any available. + /// + /// If a read thread has been started, this function will check for any + /// cached bytes that have already been read and return any currently + /// available bytes. If no bytes are cached, it will wait for the bytes to + /// become available by listening for the \a eBroadcastBitReadThreadGotBytes + /// event. If this function consumes all of the bytes in the cache, it will + /// reset the \a eBroadcastBitReadThreadGotBytes event bit. + /// + /// \param[in] dst + /// A destination buffer that must be at least \a dst_len bytes + /// long. + /// + /// \param[in] dst_len + /// The number of bytes to attempt to read, and also the max + /// number of bytes that can be placed into \a dst. + /// + /// \param[in] timeout + /// A timeout value or std::nullopt for no timeout. + /// + /// \return + /// The number of bytes actually read. + /// + /// \see size_t Connection::Read (void *, size_t); + size_t Read(void *dst, size_t dst_len, const Timeout<std::micro> &timeout, + lldb::ConnectionStatus &status, Status *error_ptr) override; + + /// Sets the connection that it to be used by this class. + /// + /// By making a communication class that uses different connections it + /// allows a single communication interface to negotiate and change its + /// connection without any interruption to the client. It also allows the + /// Communication class to be subclassed for packet based communication. + /// + /// \param[in] connection + /// A connection that this class will own and destroy. + /// + /// \see + /// class Connection + void SetConnection(std::unique_ptr<Connection> connection) override; + + /// Starts a read thread whose sole purpose it to read bytes from the + /// current connection. This function will call connection's read function: + /// + /// size_t Connection::Read (void *, size_t); + /// + /// When bytes are read and cached, this function will call: + /// + /// Communication::AppendBytesToCache (const uint8_t * bytes, size_t len, + /// bool + /// broadcast); + /// + /// Subclasses should override this function if they wish to override the + /// default action of caching the bytes and broadcasting a \b + /// eBroadcastBitReadThreadGotBytes event. + /// + /// \return + /// \b True if the read thread was successfully started, \b + /// false otherwise. + /// + /// \see size_t Connection::Read (void *, size_t); + /// \see void Communication::AppendBytesToCache (const uint8_t * bytes, + /// size_t len, bool broadcast); + virtual bool StartReadThread(Status *error_ptr = nullptr); + + /// Stops the read thread by cancelling it. + /// + /// \return + /// \b True if the read thread was successfully canceled, \b + /// false otherwise. + virtual bool StopReadThread(Status *error_ptr = nullptr); + + virtual bool JoinReadThread(Status *error_ptr = nullptr); + /// Checks if there is a currently running read thread. + /// + /// \return + /// \b True if the read thread is running, \b false otherwise. + bool ReadThreadIsRunning(); + + /// The read thread function. This function will call the "DoRead" + /// function continuously and wait for data to become available. When data + /// is received it will append the available data to the internal cache and + /// broadcast a \b eBroadcastBitReadThreadGotBytes event. + /// + /// \param[in] comm_ptr + /// A pointer to an instance of this class. + /// + /// \return + /// \b NULL. + /// + /// \see void Communication::ReadThreadGotBytes (const uint8_t *, size_t); + lldb::thread_result_t ReadThread(); + + void SetReadThreadBytesReceivedCallback(ReadThreadBytesReceived callback, + void *callback_baton); + + /// Wait for the read thread to process all outstanding data. + /// + /// After this function returns, the read thread has processed all data that + /// has been waiting in the Connection queue. + /// + void SynchronizeWithReadThread(); + + static ConstString &GetStaticBroadcasterClass(); + + ConstString &GetBroadcasterClass() const override { + return GetStaticBroadcasterClass(); + } + +protected: + HostThread m_read_thread; ///< The read thread handle in case we need to + /// cancel the thread. + std::atomic<bool> m_read_thread_enabled; + std::atomic<bool> m_read_thread_did_exit; + std::string + m_bytes; ///< A buffer to cache bytes read in the ReadThread function. + std::recursive_mutex m_bytes_mutex; ///< A mutex to protect multi-threaded + /// access to the cached bytes. + lldb::ConnectionStatus m_pass_status; ///< Connection status passthrough + /// from read thread. + Status m_pass_error; ///< Error passthrough from read thread. + std::mutex m_synchronize_mutex; + ReadThreadBytesReceived m_callback; + void *m_callback_baton; + + /// Append new bytes that get read from the read thread into the internal + /// object byte cache. This will cause a \b eBroadcastBitReadThreadGotBytes + /// event to be broadcast if \a broadcast is true. + /// + /// Subclasses can override this function in order to inspect the received + /// data and check if a packet is available. + /// + /// Subclasses can also still call this function from the overridden method + /// to allow the caching to correctly happen and suppress the broadcasting + /// of the \a eBroadcastBitReadThreadGotBytes event by setting \a broadcast + /// to false. + /// + /// \param[in] src + /// A source buffer that must be at least \a src_len bytes + /// long. + /// + /// \param[in] src_len + /// The number of bytes to append to the cache. + virtual void AppendBytesToCache(const uint8_t *src, size_t src_len, + bool broadcast, + lldb::ConnectionStatus status); + + /// Get any available bytes from our data cache. If this call empties the + /// data cache, the \b eBroadcastBitReadThreadGotBytes event will be reset + /// to signify no more bytes are available. + /// + /// \param[in] dst + /// A destination buffer that must be at least \a dst_len bytes + /// long. + /// + /// \param[in] dst_len + /// The number of bytes to attempt to read from the cache, + /// and also the max number of bytes that can be placed into + /// \a dst. + /// + /// \return + /// The number of bytes extracted from the data cache. + size_t GetCachedBytes(void *dst, size_t dst_len); + +private: + ThreadedCommunication(const ThreadedCommunication &) = delete; + const ThreadedCommunication & + operator=(const ThreadedCommunication &) = delete; +}; + +} // namespace lldb_private + +#endif // LLDB_CORE_THREADEDCOMMUNICATION_H diff --git a/contrib/llvm-project/lldb/include/lldb/Core/UserSettingsController.h b/contrib/llvm-project/lldb/include/lldb/Core/UserSettingsController.h index 35555f08c351..8afef0635973 100644 --- a/contrib/llvm-project/lldb/include/lldb/Core/UserSettingsController.h +++ b/contrib/llvm-project/lldb/include/lldb/Core/UserSettingsController.h @@ -57,10 +57,11 @@ public: virtual Status DumpPropertyValue(const ExecutionContext *exe_ctx, Stream &strm, llvm::StringRef property_path, - uint32_t dump_mask); + uint32_t dump_mask, bool is_json = false); virtual void DumpAllPropertyValues(const ExecutionContext *exe_ctx, - Stream &strm, uint32_t dump_mask); + Stream &strm, uint32_t dump_mask, + bool is_json = false); virtual void DumpAllDescriptions(CommandInterpreter &interpreter, Stream &strm) const; diff --git a/contrib/llvm-project/lldb/include/lldb/Core/ValueObject.h b/contrib/llvm-project/lldb/include/lldb/Core/ValueObject.h index 58a05352537f..a666d0bab173 100644 --- a/contrib/llvm-project/lldb/include/lldb/Core/ValueObject.h +++ b/contrib/llvm-project/lldb/include/lldb/Core/ValueObject.h @@ -26,7 +26,6 @@ #include "lldb/lldb-types.h" #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" @@ -34,6 +33,7 @@ #include <initializer_list> #include <map> #include <mutex> +#include <optional> #include <string> #include <utility> @@ -357,7 +357,7 @@ public: virtual bool CanProvideValue(); // Subclasses must implement the functions below. - virtual llvm::Optional<uint64_t> GetByteSize() = 0; + virtual std::optional<uint64_t> GetByteSize() = 0; virtual lldb::ValueType GetValueType() const = 0; diff --git a/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectCast.h b/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectCast.h index 84cf13353aee..fe053c12d9c3 100644 --- a/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectCast.h +++ b/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectCast.h @@ -17,6 +17,7 @@ #include <cstddef> #include <cstdint> +#include <optional> namespace lldb_private { class ConstString; @@ -30,7 +31,7 @@ public: ConstString name, const CompilerType &cast_type); - llvm::Optional<uint64_t> GetByteSize() override; + std::optional<uint64_t> GetByteSize() override; size_t CalculateNumChildren(uint32_t max) override; diff --git a/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectChild.h b/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectChild.h index 8a7a7f17bc76..07b37aa8a405 100644 --- a/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectChild.h +++ b/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectChild.h @@ -18,10 +18,9 @@ #include "lldb/lldb-private-enumerations.h" #include "lldb/lldb-types.h" -#include "llvm/ADT/Optional.h" - #include <cstddef> #include <cstdint> +#include <optional> namespace lldb_private { @@ -30,7 +29,7 @@ class ValueObjectChild : public ValueObject { public: ~ValueObjectChild() override; - llvm::Optional<uint64_t> GetByteSize() override { return m_byte_size; } + std::optional<uint64_t> GetByteSize() override { return m_byte_size; } lldb::offset_t GetByteOffset() override { return m_byte_offset; } @@ -69,7 +68,7 @@ protected: uint8_t m_bitfield_bit_offset; bool m_is_base_class; bool m_is_deref_of_parent; - llvm::Optional<LazyBool> m_can_update_with_invalid_exe_ctx; + std::optional<LazyBool> m_can_update_with_invalid_exe_ctx; friend class ValueObject; friend class ValueObjectConstResult; diff --git a/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectConstResult.h b/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectConstResult.h index 58cda6fd6196..4edd49521606 100644 --- a/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectConstResult.h +++ b/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectConstResult.h @@ -23,6 +23,7 @@ #include <cstddef> #include <cstdint> +#include <optional> namespace lldb_private { class DataExtractor; @@ -62,7 +63,7 @@ public: static lldb::ValueObjectSP Create(ExecutionContextScope *exe_scope, const Status &error); - llvm::Optional<uint64_t> GetByteSize() override; + std::optional<uint64_t> GetByteSize() override; lldb::ValueType GetValueType() const override; @@ -113,7 +114,7 @@ protected: CompilerType GetCompilerTypeImpl() override; ConstString m_type_name; - llvm::Optional<uint64_t> m_byte_size; + std::optional<uint64_t> m_byte_size; ValueObjectConstResultImpl m_impl; diff --git a/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectDynamicValue.h b/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectDynamicValue.h index a36db44f449a..2758b4e5bb56 100644 --- a/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectDynamicValue.h +++ b/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectDynamicValue.h @@ -22,6 +22,7 @@ #include <cassert> #include <cstddef> #include <cstdint> +#include <optional> namespace lldb_private { class DataExtractor; @@ -34,7 +35,7 @@ class ValueObjectDynamicValue : public ValueObject { public: ~ValueObjectDynamicValue() override = default; - llvm::Optional<uint64_t> GetByteSize() override; + std::optional<uint64_t> GetByteSize() override; ConstString GetTypeName() override; diff --git a/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectMemory.h b/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectMemory.h index 83671a794b5f..3c01df388d2e 100644 --- a/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectMemory.h +++ b/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectMemory.h @@ -20,6 +20,7 @@ #include <cstddef> #include <cstdint> +#include <optional> namespace lldb_private { class ExecutionContextScope; @@ -40,7 +41,7 @@ public: const Address &address, const CompilerType &ast_type); - llvm::Optional<uint64_t> GetByteSize() override; + std::optional<uint64_t> GetByteSize() override; ConstString GetTypeName() override; diff --git a/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectRegister.h b/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectRegister.h index 20a7411b6fde..60c299c5fb40 100644 --- a/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectRegister.h +++ b/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectRegister.h @@ -20,6 +20,7 @@ #include <cstddef> #include <cstdint> +#include <optional> namespace lldb_private { class DataExtractor; @@ -36,7 +37,7 @@ public: lldb::RegisterContextSP ®_ctx_sp, uint32_t set_idx); - llvm::Optional<uint64_t> GetByteSize() override; + std::optional<uint64_t> GetByteSize() override; lldb::ValueType GetValueType() const override { return lldb::eValueTypeRegisterSet; @@ -86,7 +87,7 @@ public: lldb::RegisterContextSP ®_ctx_sp, const RegisterInfo *reg_info); - llvm::Optional<uint64_t> GetByteSize() override; + std::optional<uint64_t> GetByteSize() override; lldb::ValueType GetValueType() const override { return lldb::eValueTypeRegister; diff --git a/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectSyntheticFilter.h b/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectSyntheticFilter.h index f7a233047cc1..bdd6c1be4212 100644 --- a/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectSyntheticFilter.h +++ b/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectSyntheticFilter.h @@ -19,6 +19,7 @@ #include <cstdint> #include <memory> +#include <optional> #include <cstddef> @@ -36,7 +37,7 @@ class ValueObjectSynthetic : public ValueObject { public: ~ValueObjectSynthetic() override; - llvm::Optional<uint64_t> GetByteSize() override; + std::optional<uint64_t> GetByteSize() override; ConstString GetTypeName() override; diff --git a/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectVariable.h b/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectVariable.h index cbf7e5b52ced..bba28ce567b2 100644 --- a/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectVariable.h +++ b/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectVariable.h @@ -20,6 +20,7 @@ #include <cstddef> #include <cstdint> +#include <optional> namespace lldb_private { class DataExtractor; @@ -37,7 +38,7 @@ public: static lldb::ValueObjectSP Create(ExecutionContextScope *exe_scope, const lldb::VariableSP &var_sp); - llvm::Optional<uint64_t> GetByteSize() override; + std::optional<uint64_t> GetByteSize() override; ConstString GetTypeName() override; diff --git a/contrib/llvm-project/lldb/include/lldb/DataFormatters/DataVisualization.h b/contrib/llvm-project/lldb/include/lldb/DataFormatters/DataVisualization.h index 7be07d65acdd..5aea29132b8f 100644 --- a/contrib/llvm-project/lldb/include/lldb/DataFormatters/DataVisualization.h +++ b/contrib/llvm-project/lldb/include/lldb/DataFormatters/DataVisualization.h @@ -51,7 +51,7 @@ public: GetSyntheticChildren(ValueObject &valobj, lldb::DynamicValueType use_dynamic); static bool - AnyMatches(ConstString type_name, + AnyMatches(const FormattersMatchCandidate &candidate_type, TypeCategoryImpl::FormatCategoryItems items = TypeCategoryImpl::ALL_ITEM_TYPES, bool only_enabled = true, const char **matching_category = nullptr, diff --git a/contrib/llvm-project/lldb/include/lldb/DataFormatters/FormatClasses.h b/contrib/llvm-project/lldb/include/lldb/DataFormatters/FormatClasses.h index 158d2531d0da..a6bc3a354253 100644 --- a/contrib/llvm-project/lldb/include/lldb/DataFormatters/FormatClasses.h +++ b/contrib/llvm-project/lldb/include/lldb/DataFormatters/FormatClasses.h @@ -17,6 +17,7 @@ #include "lldb/DataFormatters/TypeFormat.h" #include "lldb/DataFormatters/TypeSummary.h" #include "lldb/DataFormatters/TypeSynthetic.h" +#include "lldb/Interpreter/ScriptInterpreter.h" #include "lldb/Symbol/CompilerType.h" #include "lldb/Symbol/Type.h" #include "lldb/lldb-enumerations.h" @@ -43,20 +44,57 @@ public: class FormattersMatchCandidate { public: - FormattersMatchCandidate(ConstString name, bool strip_ptr, - bool strip_ref, bool strip_tydef) - : m_type_name(name), m_stripped_pointer(strip_ptr), - m_stripped_reference(strip_ref), m_stripped_typedef(strip_tydef) {} + // Contains flags to indicate how this candidate was generated (e.g. if + // typedefs were stripped, or pointers were skipped). These are later compared + // to flags in formatters to confirm a string match. + struct Flags { + bool stripped_pointer = false; + bool stripped_reference = false; + bool stripped_typedef = false; + + // Returns a copy of this with the "stripped pointer" flag set. + Flags WithStrippedPointer() { + Flags result(*this); + result.stripped_pointer = true; + return result; + } + + // Returns a copy of this with the "stripped reference" flag set. + Flags WithStrippedReference() { + Flags result(*this); + result.stripped_reference = true; + return result; + } + + // Returns a copy of this with the "stripped typedef" flag set. + Flags WithStrippedTypedef() { + Flags result(*this); + result.stripped_typedef = true; + return result; + } + }; + + FormattersMatchCandidate(ConstString name, + ScriptInterpreter *script_interpreter, TypeImpl type, + Flags flags) + : m_type_name(name), m_script_interpreter(script_interpreter), + m_type(type), m_flags(flags) {} ~FormattersMatchCandidate() = default; ConstString GetTypeName() const { return m_type_name; } - bool DidStripPointer() const { return m_stripped_pointer; } + TypeImpl GetType() const { return m_type; } + + ScriptInterpreter *GetScriptInterpreter() const { + return m_script_interpreter; + } - bool DidStripReference() const { return m_stripped_reference; } + bool DidStripPointer() const { return m_flags.stripped_pointer; } - bool DidStripTypedef() const { return m_stripped_typedef; } + bool DidStripReference() const { return m_flags.stripped_reference; } + + bool DidStripTypedef() const { return m_flags.stripped_typedef; } template <class Formatter> bool IsMatch(const std::shared_ptr<Formatter> &formatter_sp) const { @@ -73,9 +111,11 @@ public: private: ConstString m_type_name; - bool m_stripped_pointer; - bool m_stripped_reference; - bool m_stripped_typedef; + // If a formatter provides a matching callback function, we need the script + // interpreter and the type object (as an argument to the callback). + ScriptInterpreter *m_script_interpreter; + TypeImpl m_type; + Flags m_flags; }; typedef std::vector<FormattersMatchCandidate> FormattersMatchVector; @@ -107,21 +147,23 @@ class TypeNameSpecifierImpl { public: TypeNameSpecifierImpl() = default; - TypeNameSpecifierImpl(llvm::StringRef name, bool is_regex) - : m_is_regex(is_regex) { + TypeNameSpecifierImpl(llvm::StringRef name, + lldb::FormatterMatchType match_type) + : m_match_type(match_type) { m_type.m_type_name = std::string(name); } - // if constructing with a given type, is_regex cannot be true since we are - // giving an exact type to match - TypeNameSpecifierImpl(lldb::TypeSP type) : m_is_regex(false) { + // if constructing with a given type, we consider that a case of exact match. + TypeNameSpecifierImpl(lldb::TypeSP type) + : m_match_type(lldb::eFormatterMatchExact) { if (type) { m_type.m_type_name = std::string(type->GetName().GetStringRef()); m_type.m_compiler_type = type->GetForwardCompilerType(); } } - TypeNameSpecifierImpl(CompilerType type) : m_is_regex(false) { + TypeNameSpecifierImpl(CompilerType type) + : m_match_type(lldb::eFormatterMatchExact) { if (type.IsValid()) { m_type.m_type_name.assign(type.GetTypeName().GetCString()); m_type.m_compiler_type = type; @@ -140,10 +182,12 @@ public: return CompilerType(); } - bool IsRegex() { return m_is_regex; } + lldb::FormatterMatchType GetMatchType() { return m_match_type; } + + bool IsRegex() { return m_match_type == lldb::eFormatterMatchRegex; } private: - bool m_is_regex = false; + lldb::FormatterMatchType m_match_type = lldb::eFormatterMatchExact; // TODO: Replace this with TypeAndOrName. struct TypeOrName { std::string m_type_name; diff --git a/contrib/llvm-project/lldb/include/lldb/DataFormatters/FormatManager.h b/contrib/llvm-project/lldb/include/lldb/DataFormatters/FormatManager.h index 978ad148d6c4..295d3b84342a 100644 --- a/contrib/llvm-project/lldb/include/lldb/DataFormatters/FormatManager.h +++ b/contrib/llvm-project/lldb/include/lldb/DataFormatters/FormatManager.h @@ -128,12 +128,12 @@ public: GetSyntheticChildren(ValueObject &valobj, lldb::DynamicValueType use_dynamic); bool - AnyMatches(ConstString type_name, + AnyMatches(const FormattersMatchCandidate &candidate_type, TypeCategoryImpl::FormatCategoryItems items = TypeCategoryImpl::ALL_ITEM_TYPES, bool only_enabled = true, const char **matching_category = nullptr, TypeCategoryImpl::FormatCategoryItems *matching_type = nullptr) { - return m_categories_map.AnyMatches(type_name, items, only_enabled, + return m_categories_map.AnyMatches(candidate_type, items, only_enabled, matching_category, matching_type); } @@ -162,8 +162,8 @@ public: static FormattersMatchVector GetPossibleMatches(ValueObject &valobj, lldb::DynamicValueType use_dynamic) { FormattersMatchVector matches; - GetPossibleMatches(valobj, valobj.GetCompilerType(), - use_dynamic, matches, false, false, false, true); + GetPossibleMatches(valobj, valobj.GetCompilerType(), use_dynamic, matches, + FormattersMatchCandidate::Flags(), true); return matches; } @@ -179,8 +179,7 @@ private: CompilerType compiler_type, lldb::DynamicValueType use_dynamic, FormattersMatchVector &entries, - bool did_strip_ptr, bool did_strip_ref, - bool did_strip_typedef, + FormattersMatchCandidate::Flags current_flags, bool root_level = false); std::atomic<uint32_t> m_last_revision; diff --git a/contrib/llvm-project/lldb/include/lldb/DataFormatters/FormattersContainer.h b/contrib/llvm-project/lldb/include/lldb/DataFormatters/FormattersContainer.h index 2f56218c43a7..fd046e773b69 100644 --- a/contrib/llvm-project/lldb/include/lldb/DataFormatters/FormattersContainer.h +++ b/contrib/llvm-project/lldb/include/lldb/DataFormatters/FormattersContainer.h @@ -39,11 +39,17 @@ public: /// Class for matching type names. class TypeMatcher { + /// Type name for exact match, or name of the python callback if m_match_type + /// is `eFormatterMatchCallback`. + ConstString m_name; RegularExpression m_type_name_regex; - ConstString m_type_name; - /// False if m_type_name_regex should be used for matching. False if this is - /// just matching by comparing with m_type_name string. - bool m_is_regex; + /// Indicates what kind of matching strategy should be used: + /// - eFormatterMatchExact: match the exact type name in m_name. + /// - eFormatterMatchRegex: match using the RegularExpression object + /// `m_type_name_regex` instead. + /// - eFormatterMatchCallback: run the function in m_name to decide if a type + /// matches or not. + lldb::FormatterMatchType m_match_type; // if the user tries to add formatters for, say, "struct Foo" those will not // match any type because of the way we strip qualifiers from typenames this @@ -71,24 +77,52 @@ public: TypeMatcher() = delete; /// Creates a matcher that accepts any type with exactly the given type name. TypeMatcher(ConstString type_name) - : m_type_name(type_name), m_is_regex(false) {} + : m_name(type_name), m_match_type(lldb::eFormatterMatchExact) {} /// Creates a matcher that accepts any type matching the given regex. TypeMatcher(RegularExpression regex) - : m_type_name_regex(std::move(regex)), m_is_regex(true) {} + : m_type_name_regex(std::move(regex)), + m_match_type(lldb::eFormatterMatchRegex) {} + /// Creates a matcher using the matching type and string from the given type + /// name specifier. + TypeMatcher(lldb::TypeNameSpecifierImplSP type_specifier) + : m_name(type_specifier->GetName()), + m_match_type(type_specifier->GetMatchType()) { + if (m_match_type == lldb::eFormatterMatchRegex) + m_type_name_regex = RegularExpression(type_specifier->GetName()); + } - /// True iff this matches the given type name. - bool Matches(ConstString type_name) const { - if (m_is_regex) + /// True iff this matches the given type. + bool Matches(FormattersMatchCandidate candidate_type) const { + ConstString type_name = candidate_type.GetTypeName(); + switch (m_match_type) { + case lldb::eFormatterMatchExact: + return m_name == type_name || + StripTypeName(m_name) == StripTypeName(type_name); + case lldb::eFormatterMatchRegex: return m_type_name_regex.Execute(type_name.GetStringRef()); - return m_type_name == type_name || - StripTypeName(m_type_name) == StripTypeName(type_name); + case lldb::eFormatterMatchCallback: + // CommandObjectType{Synth,Filter}Add tries to prevent the user from + // creating both a synthetic child provider and a filter for the same type + // in the same category, but we don't have a type object at that point, so + // it creates a dummy candidate without type or script interpreter. + // Skip callback matching in these cases. + if (candidate_type.GetScriptInterpreter()) + return candidate_type.GetScriptInterpreter()->FormatterCallbackFunction( + m_name.AsCString(), + std::make_shared<TypeImpl>(candidate_type.GetType())); + } + return false; } + lldb::FormatterMatchType GetMatchType() const { return m_match_type; } + /// Returns the underlying match string for this TypeMatcher. ConstString GetMatchString() const { - if (m_is_regex) - return ConstString(m_type_name_regex.GetText()); - return StripTypeName(m_type_name); + if (m_match_type == lldb::eFormatterMatchExact) + return StripTypeName(m_name); + if (m_match_type == lldb::eFormatterMatchRegex) + return ConstString(m_type_name_regex.GetText()); + return m_name; } /// Returns true if this TypeMatcher and the given one were most created by @@ -142,10 +176,11 @@ public: return false; } - bool Get(ConstString type, ValueSP &entry) { + // Finds the first formatter in the container that matches `candidate`. + bool Get(FormattersMatchCandidate candidate, ValueSP &entry) { std::lock_guard<std::recursive_mutex> guard(m_map_mutex); for (auto &formatter : llvm::reverse(m_map)) { - if (formatter.first.Matches(type)) { + if (formatter.first.Matches(candidate)) { entry = formatter.second; return true; } @@ -153,6 +188,22 @@ public: return false; } + // Finds the first match between candidate types in `candidates` and + // formatters in this container. + bool Get(const FormattersMatchVector &candidates, ValueSP &entry) { + for (const FormattersMatchCandidate &candidate : candidates) { + if (Get(candidate, entry)) { + if (candidate.IsMatch(entry) == false) { + entry.reset(); + continue; + } else { + return true; + } + } + } + return false; + } + bool GetExact(TypeMatcher matcher, ValueSP &entry) { std::lock_guard<std::recursive_mutex> guard(m_map_mutex); for (const auto &pos : m_map) @@ -176,7 +227,8 @@ public: return lldb::TypeNameSpecifierImplSP(); TypeMatcher type_matcher = m_map[index].first; return std::make_shared<TypeNameSpecifierImpl>( - type_matcher.GetMatchString().GetStringRef(), true); + type_matcher.GetMatchString().GetStringRef(), + type_matcher.GetMatchType()); } void Clear() { @@ -213,20 +265,6 @@ protected: FormattersContainer(const FormattersContainer &) = delete; const FormattersContainer &operator=(const FormattersContainer &) = delete; - bool Get(const FormattersMatchVector &candidates, ValueSP &entry) { - for (const FormattersMatchCandidate &candidate : candidates) { - if (Get(candidate.GetTypeName(), entry)) { - if (candidate.IsMatch(entry) == false) { - entry.reset(); - continue; - } else { - return true; - } - } - } - return false; - } - MapType m_map; std::recursive_mutex m_map_mutex; IFormatChangeListener *listener; diff --git a/contrib/llvm-project/lldb/include/lldb/DataFormatters/TypeCategory.h b/contrib/llvm-project/lldb/include/lldb/DataFormatters/TypeCategory.h index 16255f9488bd..884a27d76e05 100644 --- a/contrib/llvm-project/lldb/include/lldb/DataFormatters/TypeCategory.h +++ b/contrib/llvm-project/lldb/include/lldb/DataFormatters/TypeCategory.h @@ -9,6 +9,7 @@ #ifndef LLDB_DATAFORMATTERS_TYPECATEGORY_H #define LLDB_DATAFORMATTERS_TYPECATEGORY_H +#include <array> #include <initializer_list> #include <memory> #include <mutex> @@ -23,225 +24,273 @@ namespace lldb_private { -template <typename FormatterImpl> class FormatterContainerPair { +// A formatter container with sub-containers for different priority tiers, that +// also exposes a flat view of all formatters in it. +// +// Formatters have different priority during matching, depending on the type of +// matching specified at registration. Exact matchers are processed first, then +// regex, and finally callback matchers. However, the scripting API presents a +// flat view of formatters in a category, with methods like `GetNumFormats()` +// and `GetFormatAtIndex(i)`. So we need something that can behave like both +// representations. +template <typename FormatterImpl> class TieredFormatterContainer { public: - typedef FormattersContainer<FormatterImpl> ExactMatchContainer; - typedef FormattersContainer<FormatterImpl> RegexMatchContainer; + using Subcontainer = FormattersContainer<FormatterImpl>; + using SubcontainerSP = std::shared_ptr<Subcontainer>; + using ForEachCallback = typename Subcontainer::ForEachCallback; + using MapValueType = typename Subcontainer::ValueSP; + + TieredFormatterContainer(IFormatChangeListener *change_listener) { + for (auto& sc : m_subcontainers) + sc = std::make_shared<Subcontainer>(change_listener); + } - typedef TypeMatcher ExactMatchMap; - typedef TypeMatcher RegexMatchMap; + /// Clears all subcontainers. + void Clear() { + for (auto sc : m_subcontainers) + sc->Clear(); + } - typedef typename ExactMatchContainer::ValueSP MapValueType; + /// Adds a formatter to the right subcontainer depending on the matching type + /// specified by `type_sp`. + void Add(lldb::TypeNameSpecifierImplSP type_sp, + std::shared_ptr<FormatterImpl> format_sp) { + m_subcontainers[type_sp->GetMatchType()]->Add(TypeMatcher(type_sp), + format_sp); + } - typedef typename ExactMatchContainer::SharedPointer ExactMatchContainerSP; - typedef typename RegexMatchContainer::SharedPointer RegexMatchContainerSP; + /// Deletes the formatter specified by `type_sp`. + bool Delete(lldb::TypeNameSpecifierImplSP type_sp) { + return m_subcontainers[type_sp->GetMatchType()]->Delete( + TypeMatcher(type_sp)); + } - typedef - typename ExactMatchContainer::ForEachCallback ExactMatchForEachCallback; - typedef - typename RegexMatchContainer::ForEachCallback RegexMatchForEachCallback; + /// Deletes all formatters registered with the string `name`, in all + /// subcontainers. + bool Delete(ConstString name) { + bool success = false; + for (auto sc : m_subcontainers) + success = sc->Delete(name) || success; + return success; + } - FormatterContainerPair(IFormatChangeListener *clist) - : m_exact_sp(new ExactMatchContainer(clist)), - m_regex_sp(new RegexMatchContainer(clist)) {} + /// Returns the total count of elements across all subcontainers. + uint32_t GetCount() { + uint32_t result = 0; + for (auto sc : m_subcontainers) + result += sc->GetCount(); + return result; + } - ~FormatterContainerPair() = default; + /// Returns the formatter at `index`, simulating a flattened view of all + /// subcontainers in priority order. + MapValueType GetAtIndex(size_t index) { + for (auto sc : m_subcontainers) { + if (index < sc->GetCount()) + return sc->GetAtIndex(index); + index -= sc->GetCount(); + } + return MapValueType(); + } - ExactMatchContainerSP GetExactMatch() const { return m_exact_sp; } + /// Looks for a matching candidate across all priority tiers, in priority + /// order. If a match is found, returns `true` and puts the matching entry in + /// `entry`. + bool Get(const FormattersMatchVector &candidates, + std::shared_ptr<FormatterImpl> &entry) { + for (auto sc : m_subcontainers) { + if (sc->Get(candidates, entry)) + return true; + } + return false; + } - RegexMatchContainerSP GetRegexMatch() const { return m_regex_sp; } + bool AnyMatches(const FormattersMatchCandidate &candidate) { + std::shared_ptr<FormatterImpl> entry; + for (auto sc : m_subcontainers) { + if (sc->Get(FormattersMatchVector{candidate}, entry)) + return true; + } + return false; + } - uint32_t GetCount() { - return GetExactMatch()->GetCount() + GetRegexMatch()->GetCount(); + /// Returns a formatter that is an exact match for `type_specifier_sp`. It + /// looks for a formatter with the same matching type that was created from + /// the same string. This is useful so we can refer to a formatter using the + /// same string used to register it. + /// + /// For example, `type_specifier_sp` can be something like + /// {"std::vector<.*>", eFormatterMatchRegex}, and we'd look for a regex + /// matcher with that exact regex string, NOT try to match that string using + /// regex. + MapValueType + GetForTypeNameSpecifier(lldb::TypeNameSpecifierImplSP type_specifier_sp) { + MapValueType retval; + if (type_specifier_sp) { + m_subcontainers[type_specifier_sp->GetMatchType()]->GetExact( + ConstString(type_specifier_sp->GetName()), retval); + } + return retval; } -private: - ExactMatchContainerSP m_exact_sp; - RegexMatchContainerSP m_regex_sp; + /// Returns the type name specifier at `index`, simulating a flattened view of + /// all subcontainers in priority order. + lldb::TypeNameSpecifierImplSP GetTypeNameSpecifierAtIndex(size_t index) { + for (auto sc : m_subcontainers) { + if (index < sc->GetCount()) + return sc->GetTypeNameSpecifierAtIndex(index); + index -= sc->GetCount(); + } + return lldb::TypeNameSpecifierImplSP(); + } + + /// Iterates through tiers in order, running `callback` on each element of + /// each tier. + void ForEach(std::function<bool(const TypeMatcher &, + const std::shared_ptr<FormatterImpl> &)> + callback) { + for (auto sc : m_subcontainers) { + sc->ForEach(callback); + } + } + + void AutoComplete(CompletionRequest &request) { + for (auto sc: m_subcontainers) + sc->AutoComplete(request); + } + + private: + std::array<std::shared_ptr<Subcontainer>, lldb::eLastFormatterMatchType + 1> + m_subcontainers; }; class TypeCategoryImpl { private: - typedef FormatterContainerPair<TypeFormatImpl> FormatContainer; - typedef FormatterContainerPair<TypeSummaryImpl> SummaryContainer; - typedef FormatterContainerPair<TypeFilterImpl> FilterContainer; - typedef FormatterContainerPair<SyntheticChildren> SynthContainer; + typedef TieredFormatterContainer<TypeFormatImpl> FormatContainer; + typedef TieredFormatterContainer<TypeSummaryImpl> SummaryContainer; + typedef TieredFormatterContainer<TypeFilterImpl> FilterContainer; + typedef TieredFormatterContainer<SyntheticChildren> SynthContainer; public: typedef uint16_t FormatCategoryItems; static const uint16_t ALL_ITEM_TYPES = UINT16_MAX; - typedef FormatContainer::ExactMatchContainerSP FormatContainerSP; - typedef FormatContainer::RegexMatchContainerSP RegexFormatContainerSP; - - typedef SummaryContainer::ExactMatchContainerSP SummaryContainerSP; - typedef SummaryContainer::RegexMatchContainerSP RegexSummaryContainerSP; - - typedef FilterContainer::ExactMatchContainerSP FilterContainerSP; - typedef FilterContainer::RegexMatchContainerSP RegexFilterContainerSP; - - typedef SynthContainer::ExactMatchContainerSP SynthContainerSP; - typedef SynthContainer::RegexMatchContainerSP RegexSynthContainerSP; - - template <typename T> class ForEachCallbacks { - public: - ForEachCallbacks() = default; - ~ForEachCallbacks() = default; - - template <typename U = TypeFormatImpl> - typename std::enable_if<std::is_same<U, T>::value, ForEachCallbacks &>::type - SetExact(FormatContainer::ExactMatchForEachCallback callback) { - m_format_exact = std::move(callback); - return *this; - } - template <typename U = TypeFormatImpl> - typename std::enable_if<std::is_same<U, T>::value, ForEachCallbacks &>::type - SetWithRegex(FormatContainer::RegexMatchForEachCallback callback) { - m_format_regex = std::move(callback); - return *this; - } - - template <typename U = TypeSummaryImpl> - typename std::enable_if<std::is_same<U, T>::value, ForEachCallbacks &>::type - SetExact(SummaryContainer::ExactMatchForEachCallback callback) { - m_summary_exact = std::move(callback); - return *this; - } - template <typename U = TypeSummaryImpl> - typename std::enable_if<std::is_same<U, T>::value, ForEachCallbacks &>::type - SetWithRegex(SummaryContainer::RegexMatchForEachCallback callback) { - m_summary_regex = std::move(callback); - return *this; - } - - template <typename U = TypeFilterImpl> - typename std::enable_if<std::is_same<U, T>::value, ForEachCallbacks &>::type - SetExact(FilterContainer::ExactMatchForEachCallback callback) { - m_filter_exact = std::move(callback); - return *this; - } - template <typename U = TypeFilterImpl> - typename std::enable_if<std::is_same<U, T>::value, ForEachCallbacks &>::type - SetWithRegex(FilterContainer::RegexMatchForEachCallback callback) { - m_filter_regex = std::move(callback); - return *this; - } - - template <typename U = SyntheticChildren> - typename std::enable_if<std::is_same<U, T>::value, ForEachCallbacks &>::type - SetExact(SynthContainer::ExactMatchForEachCallback callback) { - m_synth_exact = std::move(callback); - return *this; - } - template <typename U = SyntheticChildren> - typename std::enable_if<std::is_same<U, T>::value, ForEachCallbacks &>::type - SetWithRegex(SynthContainer::RegexMatchForEachCallback callback) { - m_synth_regex = std::move(callback); - return *this; - } - - FormatContainer::ExactMatchForEachCallback GetFormatExactCallback() const { - return m_format_exact; - } - FormatContainer::RegexMatchForEachCallback GetFormatRegexCallback() const { - return m_format_regex; - } + // TypeFilterImpl inherits from SyntheticChildren, so we can't simply overload + // ForEach on the type of the callback because it would result in "call to + // member function 'ForEach' is ambiguous" errors. Instead we use this + // templated struct to hold the formatter type and the callback. + template<typename T> + struct ForEachCallback { + // Make it constructible from any callable that fits. This allows us to use + // lambdas a bit more easily at the call site. For example: + // ForEachCallback<TypeFormatImpl> callback = [](...) {...}; + template <typename Callable> ForEachCallback(Callable c) : callback(c) {} + std::function<bool(const TypeMatcher &, const std::shared_ptr<T> &)> + callback; + }; - SummaryContainer::ExactMatchForEachCallback - GetSummaryExactCallback() const { - return m_summary_exact; - } - SummaryContainer::RegexMatchForEachCallback - GetSummaryRegexCallback() const { - return m_summary_regex; - } + TypeCategoryImpl(IFormatChangeListener *clist, ConstString name); - FilterContainer::ExactMatchForEachCallback GetFilterExactCallback() const { - return m_filter_exact; - } - FilterContainer::RegexMatchForEachCallback GetFilterRegexCallback() const { - return m_filter_regex; - } + void ForEach(ForEachCallback<TypeFormatImpl> callback) { + m_format_cont.ForEach(callback.callback); + } - SynthContainer::ExactMatchForEachCallback GetSynthExactCallback() const { - return m_synth_exact; - } - SynthContainer::RegexMatchForEachCallback GetSynthRegexCallback() const { - return m_synth_regex; - } + void ForEach(ForEachCallback<TypeSummaryImpl> callback) { + m_summary_cont.ForEach(callback.callback); + } - private: - FormatContainer::ExactMatchForEachCallback m_format_exact; - FormatContainer::RegexMatchForEachCallback m_format_regex; + void ForEach(ForEachCallback<TypeFilterImpl> callback) { + m_filter_cont.ForEach(callback.callback); + } - SummaryContainer::ExactMatchForEachCallback m_summary_exact; - SummaryContainer::RegexMatchForEachCallback m_summary_regex; + void ForEach(ForEachCallback<SyntheticChildren> callback) { + m_synth_cont.ForEach(callback.callback); + } - FilterContainer::ExactMatchForEachCallback m_filter_exact; - FilterContainer::RegexMatchForEachCallback m_filter_regex; + FormatContainer::MapValueType + GetFormatForType(lldb::TypeNameSpecifierImplSP type_sp); - SynthContainer::ExactMatchForEachCallback m_synth_exact; - SynthContainer::RegexMatchForEachCallback m_synth_regex; - }; + SummaryContainer::MapValueType + GetSummaryForType(lldb::TypeNameSpecifierImplSP type_sp); - TypeCategoryImpl(IFormatChangeListener *clist, ConstString name); + FilterContainer::MapValueType + GetFilterForType(lldb::TypeNameSpecifierImplSP type_sp); - template <typename T> void ForEach(const ForEachCallbacks<T> &foreach) { - GetTypeFormatsContainer()->ForEach(foreach.GetFormatExactCallback()); - GetRegexTypeFormatsContainer()->ForEach(foreach.GetFormatRegexCallback()); + SynthContainer::MapValueType + GetSyntheticForType(lldb::TypeNameSpecifierImplSP type_sp); - GetTypeSummariesContainer()->ForEach(foreach.GetSummaryExactCallback()); - GetRegexTypeSummariesContainer()->ForEach( - foreach.GetSummaryRegexCallback()); + void AddTypeFormat(lldb::TypeNameSpecifierImplSP type_sp, + lldb::TypeFormatImplSP format_sp) { + m_format_cont.Add(type_sp, format_sp); + } - GetTypeFiltersContainer()->ForEach(foreach.GetFilterExactCallback()); - GetRegexTypeFiltersContainer()->ForEach(foreach.GetFilterRegexCallback()); + void AddTypeFormat(llvm::StringRef name, lldb::FormatterMatchType match_type, + lldb::TypeFormatImplSP format_sp) { + AddTypeFormat( + std::make_shared<lldb_private::TypeNameSpecifierImpl>(name, match_type), + format_sp); + } - GetTypeSyntheticsContainer()->ForEach(foreach.GetSynthExactCallback()); - GetRegexTypeSyntheticsContainer()->ForEach(foreach.GetSynthRegexCallback()); + void AddTypeSummary(lldb::TypeNameSpecifierImplSP type_sp, + lldb::TypeSummaryImplSP summary_sp) { + m_summary_cont.Add(type_sp, summary_sp); } - FormatContainerSP GetTypeFormatsContainer() { - return m_format_cont.GetExactMatch(); + void AddTypeSummary(llvm::StringRef name, lldb::FormatterMatchType match_type, + lldb::TypeSummaryImplSP summary_sp) { + AddTypeSummary( + std::make_shared<lldb_private::TypeNameSpecifierImpl>(name, match_type), + summary_sp); } - RegexFormatContainerSP GetRegexTypeFormatsContainer() { - return m_format_cont.GetRegexMatch(); + void AddTypeFilter(lldb::TypeNameSpecifierImplSP type_sp, + lldb::TypeFilterImplSP filter_sp) { + m_filter_cont.Add(type_sp, filter_sp); } - FormatContainer &GetFormatContainer() { return m_format_cont; } + void AddTypeFilter(llvm::StringRef name, lldb::FormatterMatchType match_type, + lldb::TypeFilterImplSP filter_sp) { + AddTypeFilter( + std::make_shared<lldb_private::TypeNameSpecifierImpl>(name, match_type), + filter_sp); + } - SummaryContainerSP GetTypeSummariesContainer() { - return m_summary_cont.GetExactMatch(); + void AddTypeSynthetic(lldb::TypeNameSpecifierImplSP type_sp, + lldb::SyntheticChildrenSP synth_sp) { + m_synth_cont.Add(type_sp, synth_sp); } - RegexSummaryContainerSP GetRegexTypeSummariesContainer() { - return m_summary_cont.GetRegexMatch(); + void AddTypeSynthetic(llvm::StringRef name, + lldb::FormatterMatchType match_type, + lldb::SyntheticChildrenSP synth_sp) { + AddTypeSynthetic( + std::make_shared<lldb_private::TypeNameSpecifierImpl>(name, match_type), + synth_sp); } - SummaryContainer &GetSummaryContainer() { return m_summary_cont; } + bool DeleteTypeFormat(lldb::TypeNameSpecifierImplSP type_sp) { + return m_format_cont.Delete(type_sp); + } - FilterContainerSP GetTypeFiltersContainer() { - return m_filter_cont.GetExactMatch(); + bool DeleteTypeSummary(lldb::TypeNameSpecifierImplSP type_sp) { + return m_summary_cont.Delete(type_sp); } - RegexFilterContainerSP GetRegexTypeFiltersContainer() { - return m_filter_cont.GetRegexMatch(); + bool DeleteTypeFilter(lldb::TypeNameSpecifierImplSP type_sp) { + return m_filter_cont.Delete(type_sp); } - FilterContainer &GetFilterContainer() { return m_filter_cont; } + bool DeleteTypeSynthetic(lldb::TypeNameSpecifierImplSP type_sp) { + return m_synth_cont.Delete(type_sp); + } - FormatContainer::MapValueType - GetFormatForType(lldb::TypeNameSpecifierImplSP type_sp); + uint32_t GetNumFormats() { return m_format_cont.GetCount(); } - SummaryContainer::MapValueType - GetSummaryForType(lldb::TypeNameSpecifierImplSP type_sp); + uint32_t GetNumSummaries() { return m_summary_cont.GetCount(); } - FilterContainer::MapValueType - GetFilterForType(lldb::TypeNameSpecifierImplSP type_sp); + uint32_t GetNumFilters() { return m_filter_cont.GetCount(); } - SynthContainer::MapValueType - GetSyntheticForType(lldb::TypeNameSpecifierImplSP type_sp); + uint32_t GetNumSynthetics() { return m_synth_cont.GetCount(); } lldb::TypeNameSpecifierImplSP GetTypeNameSpecifierForFormatAtIndex(size_t index); @@ -249,30 +298,20 @@ public: lldb::TypeNameSpecifierImplSP GetTypeNameSpecifierForSummaryAtIndex(size_t index); - FormatContainer::MapValueType GetFormatAtIndex(size_t index); - - SummaryContainer::MapValueType GetSummaryAtIndex(size_t index); - - FilterContainer::MapValueType GetFilterAtIndex(size_t index); - lldb::TypeNameSpecifierImplSP GetTypeNameSpecifierForFilterAtIndex(size_t index); - SynthContainerSP GetTypeSyntheticsContainer() { - return m_synth_cont.GetExactMatch(); - } + lldb::TypeNameSpecifierImplSP + GetTypeNameSpecifierForSyntheticAtIndex(size_t index); - RegexSynthContainerSP GetRegexTypeSyntheticsContainer() { - return m_synth_cont.GetRegexMatch(); - } + FormatContainer::MapValueType GetFormatAtIndex(size_t index); + + SummaryContainer::MapValueType GetSummaryAtIndex(size_t index); - SynthContainer &GetSyntheticsContainer() { return m_synth_cont; } + FilterContainer::MapValueType GetFilterAtIndex(size_t index); SynthContainer::MapValueType GetSyntheticAtIndex(size_t index); - lldb::TypeNameSpecifierImplSP - GetTypeNameSpecifierForSyntheticAtIndex(size_t index); - bool IsEnabled() const { return m_enabled; } uint32_t GetEnabledPosition() { @@ -307,12 +346,14 @@ public: std::string GetDescription(); - bool AnyMatches(ConstString type_name, + bool AnyMatches(const FormattersMatchCandidate &candidate_type, FormatCategoryItems items = ALL_ITEM_TYPES, bool only_enabled = true, const char **matching_category = nullptr, FormatCategoryItems *matching_type = nullptr); + void AutoComplete(CompletionRequest &request, FormatCategoryItems items); + typedef std::shared_ptr<TypeCategoryImpl> SharedPointer; private: diff --git a/contrib/llvm-project/lldb/include/lldb/DataFormatters/TypeCategoryMap.h b/contrib/llvm-project/lldb/include/lldb/DataFormatters/TypeCategoryMap.h index 45dbb306aa75..d4f7634c90b0 100644 --- a/contrib/llvm-project/lldb/include/lldb/DataFormatters/TypeCategoryMap.h +++ b/contrib/llvm-project/lldb/include/lldb/DataFormatters/TypeCategoryMap.h @@ -17,6 +17,7 @@ #include "lldb/lldb-enumerations.h" #include "lldb/lldb-public.h" +#include "lldb/DataFormatters/FormatClasses.h" #include "lldb/DataFormatters/FormattersContainer.h" #include "lldb/DataFormatters/TypeCategory.h" @@ -69,7 +70,7 @@ public: lldb::TypeCategoryImplSP GetAtIndex(uint32_t); bool - AnyMatches(ConstString type_name, + AnyMatches(const FormattersMatchCandidate &candidate_type, TypeCategoryImpl::FormatCategoryItems items = TypeCategoryImpl::ALL_ITEM_TYPES, bool only_enabled = true, const char **matching_category = nullptr, diff --git a/contrib/llvm-project/lldb/include/lldb/DataFormatters/TypeSummary.h b/contrib/llvm-project/lldb/include/lldb/DataFormatters/TypeSummary.h index 30bc8cbf3feb..a82641021dad 100644 --- a/contrib/llvm-project/lldb/include/lldb/DataFormatters/TypeSummary.h +++ b/contrib/llvm-project/lldb/include/lldb/DataFormatters/TypeSummary.h @@ -263,7 +263,7 @@ public: typedef std::shared_ptr<TypeSummaryImpl> SharedPointer; protected: - uint32_t m_my_revision; + uint32_t m_my_revision = 0; Flags m_flags; TypeSummaryImpl(Kind kind, const TypeSummaryImpl::Flags &flags); diff --git a/contrib/llvm-project/lldb/include/lldb/DataFormatters/VectorIterator.h b/contrib/llvm-project/lldb/include/lldb/DataFormatters/VectorIterator.h index 33650a3dac8f..3414298f255b 100644 --- a/contrib/llvm-project/lldb/include/lldb/DataFormatters/VectorIterator.h +++ b/contrib/llvm-project/lldb/include/lldb/DataFormatters/VectorIterator.h @@ -15,13 +15,14 @@ #include "lldb/DataFormatters/TypeSynthetic.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Utility/ConstString.h" +#include "llvm/ADT/SmallVector.h" namespace lldb_private { namespace formatters { class VectorIteratorSyntheticFrontEnd : public SyntheticChildrenFrontEnd { public: VectorIteratorSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp, - ConstString item_name); + llvm::ArrayRef<ConstString> item_names); size_t CalculateNumChildren() override; @@ -35,7 +36,7 @@ public: private: ExecutionContextRef m_exe_ctx_ref; - ConstString m_item_name; + llvm::SmallVector<ConstString, 2> m_item_names; lldb::ValueObjectSP m_item_sp; }; diff --git a/contrib/llvm-project/lldb/include/lldb/Expression/DWARFExpression.h b/contrib/llvm-project/lldb/include/lldb/Expression/DWARFExpression.h index 49e51d51f211..aea41926d848 100644 --- a/contrib/llvm-project/lldb/include/lldb/Expression/DWARFExpression.h +++ b/contrib/llvm-project/lldb/include/lldb/Expression/DWARFExpression.h @@ -75,14 +75,15 @@ public: lldb::addr_t GetLocation_DW_OP_addr(const DWARFUnit *dwarf_cu, uint32_t op_addr_idx, bool &error) const; - bool Update_DW_OP_addr(lldb::addr_t file_addr); + bool Update_DW_OP_addr(const DWARFUnit *dwarf_cu, lldb::addr_t file_addr); void UpdateValue(uint64_t const_value, lldb::offset_t const_value_byte_size, uint8_t addr_byte_size); - bool ContainsThreadLocalStorage() const; + bool ContainsThreadLocalStorage(const DWARFUnit *dwarf_cu) const; bool LinkThreadLocalStorage( + const DWARFUnit *dwarf_cu, std::function<lldb::addr_t(lldb::addr_t file_addr)> const &link_address_callback); diff --git a/contrib/llvm-project/lldb/include/lldb/Expression/DWARFExpressionList.h b/contrib/llvm-project/lldb/include/lldb/Expression/DWARFExpressionList.h index a8f2a7126e3c..c0939647056d 100644 --- a/contrib/llvm-project/lldb/include/lldb/Expression/DWARFExpressionList.h +++ b/contrib/llvm-project/lldb/include/lldb/Expression/DWARFExpressionList.h @@ -12,7 +12,6 @@ #include "lldb/Expression/DWARFExpression.h" #include "lldb/Utility/RangeMap.h" #include "lldb/lldb-private.h" -#include "llvm/ADT/Optional.h" class DWARFUnit; diff --git a/contrib/llvm-project/lldb/include/lldb/Expression/ExpressionVariable.h b/contrib/llvm-project/lldb/include/lldb/Expression/ExpressionVariable.h index de700b676611..27343530780a 100644 --- a/contrib/llvm-project/lldb/include/lldb/Expression/ExpressionVariable.h +++ b/contrib/llvm-project/lldb/include/lldb/Expression/ExpressionVariable.h @@ -10,6 +10,7 @@ #define LLDB_EXPRESSION_EXPRESSIONVARIABLE_H #include <memory> +#include <optional> #include <vector> #include "llvm/ADT/DenseMap.h" @@ -32,7 +33,7 @@ public: virtual ~ExpressionVariable(); - llvm::Optional<uint64_t> GetByteSize() { return m_frozen_sp->GetByteSize(); } + std::optional<uint64_t> GetByteSize() { return m_frozen_sp->GetByteSize(); } ConstString GetName() { return m_frozen_sp->GetName(); } @@ -226,7 +227,7 @@ public: virtual void RemovePersistentVariable(lldb::ExpressionVariableSP variable) = 0; - virtual llvm::Optional<CompilerType> + virtual std::optional<CompilerType> GetCompilerTypeFromPersistentDecl(ConstString type_name) = 0; virtual lldb::addr_t LookupSymbol(ConstString name); diff --git a/contrib/llvm-project/lldb/include/lldb/Host/Config.h.cmake b/contrib/llvm-project/lldb/include/lldb/Host/Config.h.cmake index c24603f866d6..14ce46f6559c 100644 --- a/contrib/llvm-project/lldb/include/lldb/Host/Config.h.cmake +++ b/contrib/llvm-project/lldb/include/lldb/Host/Config.h.cmake @@ -51,7 +51,7 @@ #cmakedefine LLDB_PYTHON_HOME R"(${LLDB_PYTHON_HOME})" -#define LLDB_LIBDIR_SUFFIX "${LLVM_LIBDIR_SUFFIX}" +#define LLDB_INSTALL_LIBDIR_BASENAME "${LLDB_INSTALL_LIBDIR_BASENAME}" #cmakedefine LLDB_GLOBAL_INIT_DIRECTORY R"(${LLDB_GLOBAL_INIT_DIRECTORY})" diff --git a/contrib/llvm-project/lldb/include/lldb/Host/Editline.h b/contrib/llvm-project/lldb/include/lldb/Host/Editline.h index ffe2e3500aaa..bda3f06d8946 100644 --- a/contrib/llvm-project/lldb/include/lldb/Host/Editline.h +++ b/contrib/llvm-project/lldb/include/lldb/Host/Editline.h @@ -46,6 +46,7 @@ #include <csignal> #include <mutex> +#include <optional> #include <string> #include <vector> @@ -98,7 +99,7 @@ using FixIndentationCallbackType = llvm::unique_function<int(Editline *, StringList &, int)>; using SuggestionCallbackType = - llvm::unique_function<llvm::Optional<std::string>(llvm::StringRef)>; + llvm::unique_function<std::optional<std::string>(llvm::StringRef)>; using CompleteCallbackType = llvm::unique_function<void(CompletionRequest &)>; diff --git a/contrib/llvm-project/lldb/include/lldb/Host/File.h b/contrib/llvm-project/lldb/include/lldb/Host/File.h index 85e8185ebc96..a1199a51b8a6 100644 --- a/contrib/llvm-project/lldb/include/lldb/Host/File.h +++ b/contrib/llvm-project/lldb/include/lldb/Host/File.h @@ -19,6 +19,7 @@ #include <cstdarg> #include <cstdio> #include <mutex> +#include <optional> #include <sys/types.h> namespace lldb_private { @@ -225,7 +226,7 @@ public: /// A buffer where to put the bytes that are read. /// /// \param[in,out] num_bytes - /// The number of bytes to read form the current file position + /// The number of bytes to read from the current file position /// which gets modified with the number of bytes that were read. /// /// \param[in,out] offset @@ -437,10 +438,10 @@ private: class SerialPort : public NativeFile { public: struct Options { - llvm::Optional<unsigned int> BaudRate = llvm::None; - llvm::Optional<Terminal::Parity> Parity = llvm::None; - llvm::Optional<Terminal::ParityCheck> ParityCheck = llvm::None; - llvm::Optional<unsigned int> StopBits = llvm::None; + std::optional<unsigned int> BaudRate; + std::optional<Terminal::Parity> Parity; + std::optional<Terminal::ParityCheck> ParityCheck; + std::optional<unsigned int> StopBits; }; // Obtain Options corresponding to the passed URL query string diff --git a/contrib/llvm-project/lldb/include/lldb/Host/FileSystem.h b/contrib/llvm-project/lldb/include/lldb/Host/FileSystem.h index 8a4ee8470af2..823e7710b4ef 100644 --- a/contrib/llvm-project/lldb/include/lldb/Host/FileSystem.h +++ b/contrib/llvm-project/lldb/include/lldb/Host/FileSystem.h @@ -14,7 +14,6 @@ #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/Status.h" -#include "llvm/ADT/Optional.h" #include "llvm/Support/Chrono.h" #include "llvm/Support/VirtualFileSystem.h" @@ -22,6 +21,7 @@ #include <cstdint> #include <cstdio> +#include <optional> #include <sys/stat.h> namespace lldb_private { @@ -195,7 +195,7 @@ public: void SetHomeDirectory(std::string home_directory); private: - static llvm::Optional<FileSystem> &InstanceImpl(); + static std::optional<FileSystem> &InstanceImpl(); llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> m_fs; std::string m_home_directory; }; diff --git a/contrib/llvm-project/lldb/include/lldb/Host/HostInfoBase.h b/contrib/llvm-project/lldb/include/lldb/Host/HostInfoBase.h index eeed881101d0..42f71d91f9bf 100644 --- a/contrib/llvm-project/lldb/include/lldb/Host/HostInfoBase.h +++ b/contrib/llvm-project/lldb/include/lldb/Host/HostInfoBase.h @@ -19,6 +19,7 @@ #include <cstdint> +#include <optional> #include <string> namespace lldb_private { @@ -64,7 +65,8 @@ public: static const ArchSpec & GetArchitecture(ArchitectureKind arch_kind = eArchKindDefault); - static llvm::Optional<ArchitectureKind> ParseArchitectureKind(llvm::StringRef kind); + static std::optional<ArchitectureKind> + ParseArchitectureKind(llvm::StringRef kind); /// Returns the directory containing the lldb shared library. Only the /// directory member of the FileSpec is filled in. @@ -108,7 +110,9 @@ public: static FileSpec GetXcodeDeveloperDirectory() { return {}; } /// Return the directory containing a specific Xcode SDK. - static llvm::StringRef GetXcodeSDKPath(XcodeSDK sdk) { return {}; } + static llvm::Expected<llvm::StringRef> GetXcodeSDKPath(XcodeSDK sdk) { + return ""; + } /// Return information about module \p image_name if it is loaded in /// the current process's address space. diff --git a/contrib/llvm-project/lldb/include/lldb/Host/MainLoop.h b/contrib/llvm-project/lldb/include/lldb/Host/MainLoop.h index f04ac7359cc1..c88b9f8920ec 100644 --- a/contrib/llvm-project/lldb/include/lldb/Host/MainLoop.h +++ b/contrib/llvm-project/lldb/include/lldb/Host/MainLoop.h @@ -9,114 +9,16 @@ #ifndef LLDB_HOST_MAINLOOP_H #define LLDB_HOST_MAINLOOP_H -#include "lldb/Host/Config.h" -#include "lldb/Host/MainLoopBase.h" -#include "llvm/ADT/DenseMap.h" -#include <csignal> -#include <list> -#include <vector> - -#if !HAVE_PPOLL && !HAVE_SYS_EVENT_H && !defined(__ANDROID__) -#define SIGNAL_POLLING_UNSUPPORTED 1 -#endif - +#ifdef _WIN32 +#include "lldb/Host/windows/MainLoopWindows.h" namespace lldb_private { - -// Implementation of the MainLoopBase class. It can monitor file descriptors -// for readability using ppoll, kqueue, poll or WSAPoll. On Windows it only -// supports polling sockets, and will not work on generic file handles or -// pipes. On systems without kqueue or ppoll handling singnals is not -// supported. In addition to the common base, this class provides the ability -// to invoke a given handler when a signal is received. -// -// Since this class is primarily intended to be used for single-threaded -// processing, it does not attempt to perform any internal synchronisation and -// any concurrent accesses must be protected externally. However, it is -// perfectly legitimate to have more than one instance of this class running on -// separate threads, or even a single thread (with some limitations on signal -// monitoring). -// TODO: Add locking if this class is to be used in a multi-threaded context. -class MainLoop : public MainLoopBase { -private: - class SignalHandle; - -public: - typedef std::unique_ptr<SignalHandle> SignalHandleUP; - - MainLoop(); - ~MainLoop() override; - - ReadHandleUP RegisterReadObject(const lldb::IOObjectSP &object_sp, - const Callback &callback, - Status &error) override; - - // Listening for signals from multiple MainLoop instances is perfectly safe - // as long as they don't try to listen for the same signal. The callback - // function is invoked when the control returns to the Run() function, not - // when the hander is executed. This mean that you can treat the callback as - // a normal function and perform things which would not be safe in a signal - // handler. However, since the callback is not invoked synchronously, you - // cannot use this mechanism to handle SIGSEGV and the like. - SignalHandleUP RegisterSignal(int signo, const Callback &callback, - Status &error); - - // Add a pending callback that will be executed once after all the pending - // events are processed. The callback will be executed even if termination - // was requested. - void AddPendingCallback(const Callback &callback) override; - - Status Run() override; - - // This should only be performed from a callback. Do not attempt to terminate - // the processing from another thread. - // TODO: Add synchronization if we want to be terminated from another thread. - void RequestTermination() override { m_terminate_request = true; } - -protected: - void UnregisterReadObject(IOObject::WaitableHandle handle) override; - - void UnregisterSignal(int signo, std::list<Callback>::iterator callback_it); - -private: - void ProcessReadObject(IOObject::WaitableHandle handle); - void ProcessSignal(int signo); - - class SignalHandle { - public: - ~SignalHandle() { m_mainloop.UnregisterSignal(m_signo, m_callback_it); } - - private: - SignalHandle(MainLoop &mainloop, int signo, - std::list<Callback>::iterator callback_it) - : m_mainloop(mainloop), m_signo(signo), m_callback_it(callback_it) {} - - MainLoop &m_mainloop; - int m_signo; - std::list<Callback>::iterator m_callback_it; - - friend class MainLoop; - SignalHandle(const SignalHandle &) = delete; - const SignalHandle &operator=(const SignalHandle &) = delete; - }; - - struct SignalInfo { - std::list<Callback> callbacks; -#ifndef SIGNAL_POLLING_UNSUPPORTED - struct sigaction old_action; -#endif - bool was_blocked : 1; - }; - class RunImpl; - - llvm::DenseMap<IOObject::WaitableHandle, Callback> m_read_fds; - llvm::DenseMap<int, SignalInfo> m_signals; - std::vector<Callback> m_pending_callbacks; -#if HAVE_SYS_EVENT_H - int m_kqueue; +using MainLoop = MainLoopWindows; +} +#else +#include "lldb/Host/posix/MainLoopPosix.h" +namespace lldb_private { +using MainLoop = MainLoopPosix; +} #endif - bool m_terminate_request : 1; -}; - -} // namespace lldb_private #endif // LLDB_HOST_MAINLOOP_H diff --git a/contrib/llvm-project/lldb/include/lldb/Host/MainLoopBase.h b/contrib/llvm-project/lldb/include/lldb/Host/MainLoopBase.h index 2a2899341a51..7365ee7a65ee 100644 --- a/contrib/llvm-project/lldb/include/lldb/Host/MainLoopBase.h +++ b/contrib/llvm-project/lldb/include/lldb/Host/MainLoopBase.h @@ -11,8 +11,10 @@ #include "lldb/Utility/IOObject.h" #include "lldb/Utility/Status.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/Support/ErrorHandling.h" #include <functional> +#include <mutex> namespace lldb_private { @@ -26,14 +28,17 @@ namespace lldb_private { // of the monitoring. When this handle is destroyed, the callback is // deregistered. // -// This class simply defines the interface common for all platforms, actual -// implementations are platform-specific. +// Since this class is primarily intended to be used for single-threaded +// processing, it does not attempt to perform any internal synchronisation and +// any concurrent accesses must be protected externally. However, it is +// perfectly legitimate to have more than one instance of this class running on +// separate threads, or even a single thread. class MainLoopBase { private: class ReadHandle; public: - MainLoopBase() = default; + MainLoopBase() : m_terminate_request(false) {} virtual ~MainLoopBase() = default; typedef std::unique_ptr<ReadHandle> ReadHandleUP; @@ -42,32 +47,37 @@ public: virtual ReadHandleUP RegisterReadObject(const lldb::IOObjectSP &object_sp, const Callback &callback, - Status &error) { - llvm_unreachable("Not implemented"); - } + Status &error) = 0; // Add a pending callback that will be executed once after all the pending // events are processed. The callback will be executed even if termination // was requested. - virtual void AddPendingCallback(const Callback &callback) { - llvm_unreachable("Not implemented"); - } + void AddPendingCallback(const Callback &callback); // Waits for registered events and invoke the proper callbacks. Returns when // all callbacks deregister themselves or when someone requests termination. virtual Status Run() { llvm_unreachable("Not implemented"); } - // Requests the exit of the Run() function. - virtual void RequestTermination() { llvm_unreachable("Not implemented"); } + // This should only be performed from a callback. Do not attempt to terminate + // the processing from another thread. + virtual void RequestTermination() { m_terminate_request = true; } protected: ReadHandleUP CreateReadHandle(const lldb::IOObjectSP &object_sp) { return ReadHandleUP(new ReadHandle(*this, object_sp->GetWaitableHandle())); } - virtual void UnregisterReadObject(IOObject::WaitableHandle handle) { - llvm_unreachable("Not implemented"); - } + virtual void UnregisterReadObject(IOObject::WaitableHandle handle) = 0; + + // Interrupt the loop that is currently waiting for events and execute + // the current pending callbacks immediately. + virtual void TriggerPendingCallbacks() = 0; + + void ProcessPendingCallbacks(); + + std::mutex m_callback_mutex; + std::vector<Callback> m_pending_callbacks; + bool m_terminate_request : 1; private: class ReadHandle { diff --git a/contrib/llvm-project/lldb/include/lldb/Host/common/NativeProcessProtocol.h b/contrib/llvm-project/lldb/include/lldb/Host/common/NativeProcessProtocol.h index 37dacca6ff81..057c07b1536f 100644 --- a/contrib/llvm-project/lldb/include/lldb/Host/common/NativeProcessProtocol.h +++ b/contrib/llvm-project/lldb/include/lldb/Host/common/NativeProcessProtocol.h @@ -27,6 +27,7 @@ #include "llvm/Support/Error.h" #include "llvm/Support/MemoryBuffer.h" #include <mutex> +#include <optional> #include <unordered_map> #include <vector> @@ -171,7 +172,7 @@ public: // Watchpoint functions virtual const NativeWatchpointList::WatchpointMap &GetWatchpointMap() const; - virtual llvm::Optional<std::pair<uint32_t, uint32_t>> + virtual std::optional<std::pair<uint32_t, uint32_t>> GetHardwareDebugSupportInfo() const; virtual Status SetWatchpoint(lldb::addr_t addr, size_t size, @@ -204,7 +205,7 @@ public: GetAuxvData() const = 0; // Exit Status - virtual llvm::Optional<WaitStatus> GetExitStatus(); + virtual std::optional<WaitStatus> GetExitStatus(); virtual bool SetExitStatus(WaitStatus status, bool bNotifyStateChange); @@ -422,7 +423,7 @@ protected: lldb::StateType m_state = lldb::eStateInvalid; mutable std::recursive_mutex m_state_mutex; - llvm::Optional<WaitStatus> m_exit_status; + std::optional<WaitStatus> m_exit_status; NativeDelegate &m_delegate; NativeWatchpointList m_watchpoint_list; diff --git a/contrib/llvm-project/lldb/include/lldb/Host/freebsd/HostInfoFreeBSD.h b/contrib/llvm-project/lldb/include/lldb/Host/freebsd/HostInfoFreeBSD.h index b2f3f08cd145..d265b8acf5a1 100644 --- a/contrib/llvm-project/lldb/include/lldb/Host/freebsd/HostInfoFreeBSD.h +++ b/contrib/llvm-project/lldb/include/lldb/Host/freebsd/HostInfoFreeBSD.h @@ -12,13 +12,14 @@ #include "lldb/Host/posix/HostInfoPosix.h" #include "lldb/Utility/FileSpec.h" #include "llvm/Support/VersionTuple.h" +#include <optional> namespace lldb_private { class HostInfoFreeBSD : public HostInfoPosix { public: static llvm::VersionTuple GetOSVersion(); - static llvm::Optional<std::string> GetOSBuildString(); + static std::optional<std::string> GetOSBuildString(); static FileSpec GetProgramFileSpec(); }; } diff --git a/contrib/llvm-project/lldb/include/lldb/Host/netbsd/HostInfoNetBSD.h b/contrib/llvm-project/lldb/include/lldb/Host/netbsd/HostInfoNetBSD.h index 32644ce79a69..01daefaedbad 100644 --- a/contrib/llvm-project/lldb/include/lldb/Host/netbsd/HostInfoNetBSD.h +++ b/contrib/llvm-project/lldb/include/lldb/Host/netbsd/HostInfoNetBSD.h @@ -12,13 +12,14 @@ #include "lldb/Host/posix/HostInfoPosix.h" #include "lldb/Utility/FileSpec.h" #include "llvm/Support/VersionTuple.h" +#include <optional> namespace lldb_private { class HostInfoNetBSD : public HostInfoPosix { public: static llvm::VersionTuple GetOSVersion(); - static llvm::Optional<std::string> GetOSBuildString(); + static std::optional<std::string> GetOSBuildString(); static FileSpec GetProgramFileSpec(); }; } diff --git a/contrib/llvm-project/lldb/include/lldb/Host/openbsd/HostInfoOpenBSD.h b/contrib/llvm-project/lldb/include/lldb/Host/openbsd/HostInfoOpenBSD.h index 01879ad5c0e4..ed8aa2a4d2cf 100644 --- a/contrib/llvm-project/lldb/include/lldb/Host/openbsd/HostInfoOpenBSD.h +++ b/contrib/llvm-project/lldb/include/lldb/Host/openbsd/HostInfoOpenBSD.h @@ -12,13 +12,14 @@ #include "lldb/Host/posix/HostInfoPosix.h" #include "lldb/Utility/FileSpec.h" #include "llvm/Support/VersionTuple.h" +#include <optional> namespace lldb_private { class HostInfoOpenBSD : public HostInfoPosix { public: static llvm::VersionTuple GetOSVersion(); - static llvm::Optional<std::string> GetOSBuildString(); + static std::optional<std::string> GetOSBuildString(); static FileSpec GetProgramFileSpec(); }; } diff --git a/contrib/llvm-project/lldb/include/lldb/Host/posix/Fcntl.h b/contrib/llvm-project/lldb/include/lldb/Host/posix/Fcntl.h deleted file mode 100644 index 31cc293dd37a..000000000000 --- a/contrib/llvm-project/lldb/include/lldb/Host/posix/Fcntl.h +++ /dev/null @@ -1,24 +0,0 @@ -//===-- Fcntl.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 -// -//===----------------------------------------------------------------------===// - -// This file defines fcntl functions & structures - -#ifndef liblldb_Host_posix_Fcntl_h_ -#define liblldb_Host_posix_Fcntl_h_ - -#ifdef __ANDROID__ -#include <android/api-level.h> -#endif - -#include <fcntl.h> - -#if defined(__ANDROID_API__) && __ANDROID_API__ < 21 -#define F_DUPFD_CLOEXEC (F_LINUX_SPECIFIC_BASE + 6) -#endif - -#endif // liblldb_Host_posix_Fcntl_h_ diff --git a/contrib/llvm-project/lldb/include/lldb/Host/posix/HostInfoPosix.h b/contrib/llvm-project/lldb/include/lldb/Host/posix/HostInfoPosix.h index f1ff6b860864..8d070d3ac1e6 100644 --- a/contrib/llvm-project/lldb/include/lldb/Host/posix/HostInfoPosix.h +++ b/contrib/llvm-project/lldb/include/lldb/Host/posix/HostInfoPosix.h @@ -11,6 +11,7 @@ #include "lldb/Host/HostInfoBase.h" #include "lldb/Utility/FileSpec.h" +#include <optional> namespace lldb_private { @@ -22,7 +23,7 @@ class HostInfoPosix : public HostInfoBase { public: static size_t GetPageSize(); static bool GetHostname(std::string &s); - static llvm::Optional<std::string> GetOSKernelDescription(); + static std::optional<std::string> GetOSKernelDescription(); static uint32_t GetUserID(); static uint32_t GetGroupID(); diff --git a/contrib/llvm-project/lldb/include/lldb/Host/posix/MainLoopPosix.h b/contrib/llvm-project/lldb/include/lldb/Host/posix/MainLoopPosix.h new file mode 100644 index 000000000000..07497b7b8c25 --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/Host/posix/MainLoopPosix.h @@ -0,0 +1,99 @@ +//===-- MainLoopPosix.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_HOST_POSIX_MAINLOOPPOSIX_H +#define LLDB_HOST_POSIX_MAINLOOPPOSIX_H + +#include "lldb/Host/Config.h" +#include "lldb/Host/MainLoopBase.h" +#include "lldb/Host/Pipe.h" +#include "llvm/ADT/DenseMap.h" +#include <atomic> +#include <csignal> +#include <list> +#include <vector> + +namespace lldb_private { + +// Implementation of the MainLoopBase class. It can monitor file descriptors for +// readability using ppoll, kqueue, or pselect. In addition to the common base, +// this class provides the ability to invoke a given handler when a signal is +// received. +class MainLoopPosix : public MainLoopBase { +private: + class SignalHandle; + +public: + typedef std::unique_ptr<SignalHandle> SignalHandleUP; + + MainLoopPosix(); + ~MainLoopPosix() override; + + ReadHandleUP RegisterReadObject(const lldb::IOObjectSP &object_sp, + const Callback &callback, + Status &error) override; + + // Listening for signals from multiple MainLoop instances is perfectly safe + // as long as they don't try to listen for the same signal. The callback + // function is invoked when the control returns to the Run() function, not + // when the hander is executed. This mean that you can treat the callback as + // a normal function and perform things which would not be safe in a signal + // handler. However, since the callback is not invoked synchronously, you + // cannot use this mechanism to handle SIGSEGV and the like. + SignalHandleUP RegisterSignal(int signo, const Callback &callback, + Status &error); + + Status Run() override; + +protected: + void UnregisterReadObject(IOObject::WaitableHandle handle) override; + void UnregisterSignal(int signo, std::list<Callback>::iterator callback_it); + + void TriggerPendingCallbacks() override; + +private: + void ProcessReadObject(IOObject::WaitableHandle handle); + void ProcessSignal(int signo); + + class SignalHandle { + public: + ~SignalHandle() { m_mainloop.UnregisterSignal(m_signo, m_callback_it); } + + private: + SignalHandle(MainLoopPosix &mainloop, int signo, + std::list<Callback>::iterator callback_it) + : m_mainloop(mainloop), m_signo(signo), m_callback_it(callback_it) {} + + MainLoopPosix &m_mainloop; + int m_signo; + std::list<Callback>::iterator m_callback_it; + + friend class MainLoopPosix; + SignalHandle(const SignalHandle &) = delete; + const SignalHandle &operator=(const SignalHandle &) = delete; + }; + + struct SignalInfo { + std::list<Callback> callbacks; + struct sigaction old_action; + bool was_blocked : 1; + }; + class RunImpl; + + llvm::DenseMap<IOObject::WaitableHandle, Callback> m_read_fds; + llvm::DenseMap<int, SignalInfo> m_signals; + Pipe m_trigger_pipe; + std::atomic<bool> m_triggering; +#if HAVE_SYS_EVENT_H + int m_kqueue; +#endif +}; + +} // namespace lldb_private + +#endif // LLDB_HOST_POSIX_MAINLOOPPOSIX_H diff --git a/contrib/llvm-project/lldb/include/lldb/Interpreter/CommandHistory.h b/contrib/llvm-project/lldb/include/lldb/Interpreter/CommandHistory.h index 12c170ba5eeb..aa3018573fdc 100644 --- a/contrib/llvm-project/lldb/include/lldb/Interpreter/CommandHistory.h +++ b/contrib/llvm-project/lldb/include/lldb/Interpreter/CommandHistory.h @@ -10,6 +10,7 @@ #define LLDB_INTERPRETER_COMMANDHISTORY_H #include <mutex> +#include <optional> #include <string> #include <vector> @@ -28,7 +29,7 @@ public: bool IsEmpty() const; - llvm::Optional<llvm::StringRef> FindString(llvm::StringRef input_str) const; + std::optional<llvm::StringRef> FindString(llvm::StringRef input_str) const; llvm::StringRef GetStringAtIndex(size_t idx) const; diff --git a/contrib/llvm-project/lldb/include/lldb/Interpreter/CommandInterpreter.h b/contrib/llvm-project/lldb/include/lldb/Interpreter/CommandInterpreter.h index 55971136b63b..38ff061612b1 100644 --- a/contrib/llvm-project/lldb/include/lldb/Interpreter/CommandInterpreter.h +++ b/contrib/llvm-project/lldb/include/lldb/Interpreter/CommandInterpreter.h @@ -26,6 +26,7 @@ #include "lldb/lldb-private.h" #include <mutex> +#include <optional> #include <stack> namespace lldb_private { @@ -239,6 +240,14 @@ public: eCommandTypesAllThem = 0xFFFF //< all commands }; + // The CommandAlias and CommandInterpreter both have a hand in + // substituting for alias commands. They work by writing special tokens + // in the template form of the Alias command, and then detecting them when the + // command is executed. These are the special tokens: + static const char *g_no_argument; + static const char *g_need_argument; + static const char *g_argument; + CommandInterpreter(Debugger &debugger, bool synchronous_execution); ~CommandInterpreter() override = default; @@ -398,7 +407,7 @@ public: /// Returns the auto-suggestion string that should be added to the given /// command line. - llvm::Optional<std::string> GetAutoSuggestionForCommand(llvm::StringRef line); + std::optional<std::string> GetAutoSuggestionForCommand(llvm::StringRef line); // This handles command line completion. void HandleCompletion(CompletionRequest &request); @@ -551,6 +560,9 @@ public: bool GetSaveSessionOnQuit() const; void SetSaveSessionOnQuit(bool enable); + bool GetOpenTranscriptInEditor() const; + void SetOpenTranscriptInEditor(bool enable); + FileSpec GetSaveSessionDirectory() const; void SetSaveSessionDirectory(llvm::StringRef path); @@ -588,7 +600,7 @@ public: /// \return True if the exit code was successfully set; false if the /// interpreter doesn't allow custom exit codes. /// \see AllowExitCodeOnQuit - LLVM_NODISCARD bool SetQuitExitCode(int exit_code); + [[nodiscard]] bool SetQuitExitCode(int exit_code); /// Returns the exit code that the user has specified when running the /// 'quit' command. @@ -616,7 +628,7 @@ public: /// \return \b true if the session transcript was successfully written to /// disk, \b false otherwise. bool SaveTranscript(CommandReturnObject &result, - llvm::Optional<std::string> output_file = llvm::None); + std::optional<std::string> output_file = std::nullopt); FileSpec GetCurrentSourceDir(); @@ -731,7 +743,7 @@ private: // The exit code the user has requested when calling the 'quit' command. // No value means the user hasn't set a custom exit code so far. - llvm::Optional<int> m_quit_exit_code; + std::optional<int> m_quit_exit_code; // If the driver is accepts custom exit codes for the 'quit' command. bool m_allow_exit_code = false; diff --git a/contrib/llvm-project/lldb/include/lldb/Interpreter/CommandObject.h b/contrib/llvm-project/lldb/include/lldb/Interpreter/CommandObject.h index ad5884e207a1..86750a49bd32 100644 --- a/contrib/llvm-project/lldb/include/lldb/Interpreter/CommandObject.h +++ b/contrib/llvm-project/lldb/include/lldb/Interpreter/CommandObject.h @@ -10,6 +10,8 @@ #define LLDB_INTERPRETER_COMMANDOBJECT_H #include <map> +#include <memory> +#include <optional> #include <string> #include <vector> @@ -64,7 +66,7 @@ size_t FindLongestCommandWord(std::map<std::string, ValueType> &dict) { return max_len; } -class CommandObject { +class CommandObject : public std::enable_shared_from_this<CommandObject> { public: typedef llvm::StringRef(ArgumentHelpCallbackFunction)(); @@ -272,13 +274,13 @@ public: /// The command arguments. /// /// \return - /// llvm::None if there is no special repeat command - it will use the + /// std::nullopt if there is no special repeat command - it will use the /// current command line. /// Otherwise a std::string containing the command to be repeated. /// If the string is empty, the command won't be allow repeating. - virtual llvm::Optional<std::string> + virtual std::optional<std::string> GetRepeatCommand(Args ¤t_command_args, uint32_t index) { - return llvm::None; + return std::nullopt; } bool HasOverrideCallback() const { diff --git a/contrib/llvm-project/lldb/include/lldb/Interpreter/CommandObjectMultiword.h b/contrib/llvm-project/lldb/include/lldb/Interpreter/CommandObjectMultiword.h index a8ab6e44954e..1c14b492c809 100644 --- a/contrib/llvm-project/lldb/include/lldb/Interpreter/CommandObjectMultiword.h +++ b/contrib/llvm-project/lldb/include/lldb/Interpreter/CommandObjectMultiword.h @@ -11,6 +11,7 @@ #include "lldb/Interpreter/CommandObject.h" #include "lldb/Utility/CompletionRequest.h" +#include <optional> namespace lldb_private { @@ -55,8 +56,8 @@ public: void HandleCompletion(CompletionRequest &request) override; - llvm::Optional<std::string> GetRepeatCommand(Args ¤t_command_args, - uint32_t index) override; + std::optional<std::string> GetRepeatCommand(Args ¤t_command_args, + uint32_t index) override; bool Execute(const char *args_string, CommandReturnObject &result) override; @@ -120,8 +121,8 @@ public: HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override; - llvm::Optional<std::string> GetRepeatCommand(Args ¤t_command_args, - uint32_t index) override; + std::optional<std::string> GetRepeatCommand(Args ¤t_command_args, + uint32_t index) override; /// \return /// An error message to be displayed when the command is executed (i.e. diff --git a/contrib/llvm-project/lldb/include/lldb/Interpreter/CommandOptionArgumentTable.h b/contrib/llvm-project/lldb/include/lldb/Interpreter/CommandOptionArgumentTable.h index c8ec3b941831..233ad34ff0f5 100644 --- a/contrib/llvm-project/lldb/include/lldb/Interpreter/CommandOptionArgumentTable.h +++ b/contrib/llvm-project/lldb/include/lldb/Interpreter/CommandOptionArgumentTable.h @@ -124,67 +124,6 @@ static constexpr OptionEnumValueElement g_log_handler_type[] = { }, }; -static constexpr OptionEnumValueElement g_reproducer_provider_type[] = { - { - eReproducerProviderCommands, - "commands", - "Command Interpreter Commands", - }, - { - eReproducerProviderFiles, - "files", - "Files", - }, - { - eReproducerProviderSymbolFiles, - "symbol-files", - "Symbol Files", - }, - { - eReproducerProviderGDB, - "gdb", - "GDB Remote Packets", - }, - { - eReproducerProviderProcessInfo, - "processes", - "Process Info", - }, - { - eReproducerProviderVersion, - "version", - "Version", - }, - { - eReproducerProviderWorkingDirectory, - "cwd", - "Working Directory", - }, - { - eReproducerProviderHomeDirectory, - "home", - "Home Directory", - }, - { - eReproducerProviderNone, - "none", - "None", - }, -}; - -static constexpr OptionEnumValueElement g_reproducer_signaltype[] = { - { - eReproducerCrashSigill, - "SIGILL", - "Illegal instruction", - }, - { - eReproducerCrashSigsegv, - "SIGSEGV", - "Segmentation fault", - }, -}; - static constexpr OptionEnumValueElement g_script_synchro_type[] = { { eScriptedCommandSynchronicitySynchronous, @@ -318,8 +257,6 @@ static constexpr CommandObject::ArgumentTableEntry g_argument_table[] = { { lldb::eArgTypeConnectURL, "process-connect-url", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "A URL-style specification for a remote connection." }, { lldb::eArgTypeTargetID, "target-id", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "The index ID for an lldb Target." }, { lldb::eArgTypeStopHookID, "stop-hook-id", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "The ID you receive when you create a stop-hook." }, - { lldb::eArgTypeReproducerProvider, "reproducer-provider", CommandCompletions::eNoCompletion, g_reproducer_provider_type, { nullptr, false }, "The reproducer provider." }, - { lldb::eArgTypeReproducerSignal, "reproducer-signal", CommandCompletions::eNoCompletion, g_reproducer_signaltype, { nullptr, false }, "The signal used to emulate a reproducer crash." }, // clang-format on }; diff --git a/contrib/llvm-project/lldb/include/lldb/Interpreter/OptionValue.h b/contrib/llvm-project/lldb/include/lldb/Interpreter/OptionValue.h index 277a5c9d30f0..3c842d1f5ce7 100644 --- a/contrib/llvm-project/lldb/include/lldb/Interpreter/OptionValue.h +++ b/contrib/llvm-project/lldb/include/lldb/Interpreter/OptionValue.h @@ -17,6 +17,7 @@ #include "lldb/lldb-defines.h" #include "lldb/lldb-private-enumerations.h" #include "lldb/lldb-private-interfaces.h" +#include "llvm/Support/JSON.h" namespace lldb_private { @@ -82,6 +83,16 @@ public: virtual void DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) = 0; + // TODO: make this function pure virtual after implementing it in all + // child classes. + virtual llvm::json::Value ToJSON(const ExecutionContext *exe_ctx) { + // Return nullptr which will create a llvm::json::Value() that is a NULL + // value. No setting should ever really have a NULL value in JSON. This + // indicates an error occurred and if/when we add a FromJSON() it will know + // to fail if someone tries to set it with a NULL JSON value. + return nullptr; + } + virtual Status SetValueFromString(llvm::StringRef value, VarSetOperationType op = eVarSetOperationAssign); diff --git a/contrib/llvm-project/lldb/include/lldb/Interpreter/OptionValueArray.h b/contrib/llvm-project/lldb/include/lldb/Interpreter/OptionValueArray.h index af43887635e9..147e15ef4335 100644 --- a/contrib/llvm-project/lldb/include/lldb/Interpreter/OptionValueArray.h +++ b/contrib/llvm-project/lldb/include/lldb/Interpreter/OptionValueArray.h @@ -29,6 +29,8 @@ public: void DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override; + llvm::json::Value ToJSON(const ExecutionContext *exe_ctx) override; + Status SetValueFromString(llvm::StringRef value, VarSetOperationType op = eVarSetOperationAssign) override; diff --git a/contrib/llvm-project/lldb/include/lldb/Interpreter/OptionValueBoolean.h b/contrib/llvm-project/lldb/include/lldb/Interpreter/OptionValueBoolean.h index fd15ccb12c40..01e7c6c09d8e 100644 --- a/contrib/llvm-project/lldb/include/lldb/Interpreter/OptionValueBoolean.h +++ b/contrib/llvm-project/lldb/include/lldb/Interpreter/OptionValueBoolean.h @@ -29,6 +29,10 @@ public: void DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override; + llvm::json::Value ToJSON(const ExecutionContext *exe_ctx) override { + return m_current_value; + } + Status SetValueFromString(llvm::StringRef value, VarSetOperationType op = eVarSetOperationAssign) override; diff --git a/contrib/llvm-project/lldb/include/lldb/Interpreter/OptionValueChar.h b/contrib/llvm-project/lldb/include/lldb/Interpreter/OptionValueChar.h index 6b8a314a7c99..32ec2bb59fc5 100644 --- a/contrib/llvm-project/lldb/include/lldb/Interpreter/OptionValueChar.h +++ b/contrib/llvm-project/lldb/include/lldb/Interpreter/OptionValueChar.h @@ -30,6 +30,10 @@ public: void DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override; + llvm::json::Value ToJSON(const ExecutionContext *exe_ctx) override { + return m_current_value; + } + Status SetValueFromString(llvm::StringRef value, VarSetOperationType op = eVarSetOperationAssign) override; diff --git a/contrib/llvm-project/lldb/include/lldb/Interpreter/OptionValueDictionary.h b/contrib/llvm-project/lldb/include/lldb/Interpreter/OptionValueDictionary.h index 4c6bcaecd4c7..1fdccdeccef5 100644 --- a/contrib/llvm-project/lldb/include/lldb/Interpreter/OptionValueDictionary.h +++ b/contrib/llvm-project/lldb/include/lldb/Interpreter/OptionValueDictionary.h @@ -34,6 +34,8 @@ public: void DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override; + llvm::json::Value ToJSON(const ExecutionContext *exe_ctx) override; + Status SetValueFromString(llvm::StringRef value, VarSetOperationType op = eVarSetOperationAssign) override; diff --git a/contrib/llvm-project/lldb/include/lldb/Interpreter/OptionValueFileSpec.h b/contrib/llvm-project/lldb/include/lldb/Interpreter/OptionValueFileSpec.h index 6648bbac93e3..b680a89688d9 100644 --- a/contrib/llvm-project/lldb/include/lldb/Interpreter/OptionValueFileSpec.h +++ b/contrib/llvm-project/lldb/include/lldb/Interpreter/OptionValueFileSpec.h @@ -35,6 +35,10 @@ public: void DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override; + llvm::json::Value ToJSON(const ExecutionContext *exe_ctx) override { + return m_current_value.GetPath(); + } + Status SetValueFromString(llvm::StringRef value, VarSetOperationType op = eVarSetOperationAssign) override; diff --git a/contrib/llvm-project/lldb/include/lldb/Interpreter/OptionValueFormat.h b/contrib/llvm-project/lldb/include/lldb/Interpreter/OptionValueFormat.h index 1f2c66b164d5..5be885fe4f70 100644 --- a/contrib/llvm-project/lldb/include/lldb/Interpreter/OptionValueFormat.h +++ b/contrib/llvm-project/lldb/include/lldb/Interpreter/OptionValueFormat.h @@ -31,6 +31,8 @@ public: void DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override; + llvm::json::Value ToJSON(const ExecutionContext *exe_ctx) override; + Status SetValueFromString(llvm::StringRef value, VarSetOperationType op = eVarSetOperationAssign) override; diff --git a/contrib/llvm-project/lldb/include/lldb/Interpreter/OptionValueFormatEntity.h b/contrib/llvm-project/lldb/include/lldb/Interpreter/OptionValueFormatEntity.h index cb8b2ef13fa4..b8ef03a44d03 100644 --- a/contrib/llvm-project/lldb/include/lldb/Interpreter/OptionValueFormatEntity.h +++ b/contrib/llvm-project/lldb/include/lldb/Interpreter/OptionValueFormatEntity.h @@ -28,6 +28,8 @@ public: void DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override; + llvm::json::Value ToJSON(const ExecutionContext *exe_ctx) override; + Status SetValueFromString(llvm::StringRef value, VarSetOperationType op = eVarSetOperationAssign) override; diff --git a/contrib/llvm-project/lldb/include/lldb/Interpreter/OptionValueLanguage.h b/contrib/llvm-project/lldb/include/lldb/Interpreter/OptionValueLanguage.h index c00f71ffff33..f20a2c64f698 100644 --- a/contrib/llvm-project/lldb/include/lldb/Interpreter/OptionValueLanguage.h +++ b/contrib/llvm-project/lldb/include/lldb/Interpreter/OptionValueLanguage.h @@ -33,6 +33,8 @@ public: void DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override; + llvm::json::Value ToJSON(const ExecutionContext *exe_ctx) override; + Status SetValueFromString(llvm::StringRef value, VarSetOperationType op = eVarSetOperationAssign) override; diff --git a/contrib/llvm-project/lldb/include/lldb/Interpreter/OptionValuePathMappings.h b/contrib/llvm-project/lldb/include/lldb/Interpreter/OptionValuePathMappings.h index 4bc65ce76c76..82a968a77c12 100644 --- a/contrib/llvm-project/lldb/include/lldb/Interpreter/OptionValuePathMappings.h +++ b/contrib/llvm-project/lldb/include/lldb/Interpreter/OptionValuePathMappings.h @@ -29,6 +29,8 @@ public: void DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override; + llvm::json::Value ToJSON(const ExecutionContext *exe_ctx) override; + Status SetValueFromString(llvm::StringRef value, VarSetOperationType op = eVarSetOperationAssign) override; diff --git a/contrib/llvm-project/lldb/include/lldb/Interpreter/OptionValueProperties.h b/contrib/llvm-project/lldb/include/lldb/Interpreter/OptionValueProperties.h index 14f496bca6cd..7c344dc23a0f 100644 --- a/contrib/llvm-project/lldb/include/lldb/Interpreter/OptionValueProperties.h +++ b/contrib/llvm-project/lldb/include/lldb/Interpreter/OptionValueProperties.h @@ -47,11 +47,13 @@ public: void DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override; + llvm::json::Value ToJSON(const ExecutionContext *exe_ctx) override; + ConstString GetName() const override { return m_name; } virtual Status DumpPropertyValue(const ExecutionContext *exe_ctx, Stream &strm, llvm::StringRef property_path, - uint32_t dump_mask); + uint32_t dump_mask, bool is_json = false); virtual void DumpAllDescriptions(CommandInterpreter &interpreter, Stream &strm) const; diff --git a/contrib/llvm-project/lldb/include/lldb/Interpreter/OptionValueRegex.h b/contrib/llvm-project/lldb/include/lldb/Interpreter/OptionValueRegex.h index 129987484f19..3c188003ceb2 100644 --- a/contrib/llvm-project/lldb/include/lldb/Interpreter/OptionValueRegex.h +++ b/contrib/llvm-project/lldb/include/lldb/Interpreter/OptionValueRegex.h @@ -28,6 +28,10 @@ public: void DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override; + llvm::json::Value ToJSON(const ExecutionContext *exe_ctx) override { + return m_regex.GetText(); + } + Status SetValueFromString(llvm::StringRef value, VarSetOperationType op = eVarSetOperationAssign) override; diff --git a/contrib/llvm-project/lldb/include/lldb/Interpreter/OptionValueSInt64.h b/contrib/llvm-project/lldb/include/lldb/Interpreter/OptionValueSInt64.h index 3493eb1037c0..5efae627758a 100644 --- a/contrib/llvm-project/lldb/include/lldb/Interpreter/OptionValueSInt64.h +++ b/contrib/llvm-project/lldb/include/lldb/Interpreter/OptionValueSInt64.h @@ -35,6 +35,10 @@ public: void DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override; + llvm::json::Value ToJSON(const ExecutionContext *exe_ctx) override { + return m_current_value; + } + Status SetValueFromString(llvm::StringRef value, VarSetOperationType op = eVarSetOperationAssign) override; diff --git a/contrib/llvm-project/lldb/include/lldb/Interpreter/OptionValueString.h b/contrib/llvm-project/lldb/include/lldb/Interpreter/OptionValueString.h index 820656d19e2c..becf35f8e88e 100644 --- a/contrib/llvm-project/lldb/include/lldb/Interpreter/OptionValueString.h +++ b/contrib/llvm-project/lldb/include/lldb/Interpreter/OptionValueString.h @@ -69,6 +69,10 @@ public: void DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override; + llvm::json::Value ToJSON(const ExecutionContext *exe_ctx) override { + return m_current_value; + } + Status SetValueFromString(llvm::StringRef value, VarSetOperationType op = eVarSetOperationAssign) override; @@ -109,7 +113,7 @@ public: bool IsCurrentValueEmpty() const { return m_current_value.empty(); } bool IsDefaultValueEmpty() const { return m_default_value.empty(); } - + void SetValidator(ValidatorCallback validator, void *baton = nullptr) { m_validator = validator; m_validator_baton = baton; diff --git a/contrib/llvm-project/lldb/include/lldb/Interpreter/OptionValueUInt64.h b/contrib/llvm-project/lldb/include/lldb/Interpreter/OptionValueUInt64.h index f212b2a19def..30c27bf73d99 100644 --- a/contrib/llvm-project/lldb/include/lldb/Interpreter/OptionValueUInt64.h +++ b/contrib/llvm-project/lldb/include/lldb/Interpreter/OptionValueUInt64.h @@ -38,6 +38,10 @@ public: void DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override; + llvm::json::Value ToJSON(const ExecutionContext *exe_ctx) override { + return m_current_value; + } + Status SetValueFromString(llvm::StringRef value, VarSetOperationType op = eVarSetOperationAssign) override; diff --git a/contrib/llvm-project/lldb/include/lldb/Interpreter/OptionValueUUID.h b/contrib/llvm-project/lldb/include/lldb/Interpreter/OptionValueUUID.h index 0ed490d1811d..e0e4235fdf07 100644 --- a/contrib/llvm-project/lldb/include/lldb/Interpreter/OptionValueUUID.h +++ b/contrib/llvm-project/lldb/include/lldb/Interpreter/OptionValueUUID.h @@ -29,6 +29,10 @@ public: void DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override; + llvm::json::Value ToJSON(const ExecutionContext *exe_ctx) override { + return m_uuid.GetAsString(); + } + Status SetValueFromString(llvm::StringRef value, VarSetOperationType op = eVarSetOperationAssign) override; diff --git a/contrib/llvm-project/lldb/include/lldb/Interpreter/ScriptInterpreter.h b/contrib/llvm-project/lldb/include/lldb/Interpreter/ScriptInterpreter.h index 83f784bde712..4d073995defb 100644 --- a/contrib/llvm-project/lldb/include/lldb/Interpreter/ScriptInterpreter.h +++ b/contrib/llvm-project/lldb/include/lldb/Interpreter/ScriptInterpreter.h @@ -13,16 +13,18 @@ #include "lldb/API/SBError.h" #include "lldb/API/SBMemoryRegionInfo.h" #include "lldb/Breakpoint/BreakpointOptions.h" -#include "lldb/Core/Communication.h" #include "lldb/Core/PluginInterface.h" #include "lldb/Core/SearchFilter.h" #include "lldb/Core/StreamFile.h" +#include "lldb/Core/ThreadedCommunication.h" #include "lldb/Host/PseudoTerminal.h" +#include "lldb/Interpreter/ScriptedPlatformInterface.h" #include "lldb/Interpreter/ScriptedProcessInterface.h" #include "lldb/Utility/Broadcaster.h" #include "lldb/Utility/Status.h" #include "lldb/Utility/StructuredData.h" #include "lldb/lldb-private.h" +#include <optional> namespace lldb_private { @@ -119,7 +121,7 @@ private: lldb::FileSP m_input_file_sp; lldb::StreamFileSP m_output_file_sp; lldb::StreamFileSP m_error_file_sp; - Communication m_communication; + ThreadedCommunication m_communication; bool m_disconnect; }; @@ -146,7 +148,9 @@ public: ScriptInterpreter( Debugger &debugger, lldb::ScriptLanguage script_lang, lldb::ScriptedProcessInterfaceUP scripted_process_interface_up = - std::make_unique<ScriptedProcessInterface>()); + std::make_unique<ScriptedProcessInterface>(), + lldb::ScriptedPlatformInterfaceUP scripted_platform_interface_up = + std::make_unique<ScriptedPlatformInterface>()); virtual StructuredData::DictionarySP GetInterpreterInfo(); @@ -418,6 +422,14 @@ public: return false; } + // Calls the specified formatter matching Python function and returns its + // result (true if it's a match, false if we should keep looking for a + // matching formatter). + virtual bool FormatterCallbackFunction(const char *function_name, + lldb::TypeImplSP type_impl_sp) { + return true; + } + virtual void Clear() { // Clean up any ref counts to SBObjects that might be in global variables } @@ -562,18 +574,23 @@ public: return *m_scripted_process_interface_up; } + ScriptedPlatformInterface &GetScriptedPlatformInterface() { + return *m_scripted_platform_interface_up; + } + lldb::DataExtractorSP GetDataExtractorFromSBData(const lldb::SBData &data) const; Status GetStatusFromSBError(const lldb::SBError &error) const; - llvm::Optional<MemoryRegionInfo> GetOpaqueTypeFromSBMemoryRegionInfo( + std::optional<MemoryRegionInfo> GetOpaqueTypeFromSBMemoryRegionInfo( const lldb::SBMemoryRegionInfo &mem_region) const; protected: Debugger &m_debugger; lldb::ScriptLanguage m_script_lang; lldb::ScriptedProcessInterfaceUP m_scripted_process_interface_up; + lldb::ScriptedPlatformInterfaceUP m_scripted_platform_interface_up; }; } // namespace lldb_private diff --git a/contrib/llvm-project/lldb/include/lldb/Interpreter/ScriptedMetadata.h b/contrib/llvm-project/lldb/include/lldb/Interpreter/ScriptedMetadata.h new file mode 100644 index 000000000000..00ebce323bf8 --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/Interpreter/ScriptedMetadata.h @@ -0,0 +1,45 @@ +//===-- ScriptedMetadata.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_INTERPRETER_SCRIPTEDMETADATA_H +#define LLDB_INTERPRETER_SCRIPTEDMETADATA_H + +#include "OptionGroupPythonClassWithDict.h" + +#include "lldb/Host/Host.h" +#include "lldb/Host/ProcessLaunchInfo.h" +#include "lldb/Utility/StructuredData.h" + +namespace lldb_private { +class ScriptedMetadata { +public: + ScriptedMetadata(llvm::StringRef class_name, + StructuredData::DictionarySP dict_sp) + : m_class_name(class_name.data()), m_args_sp(dict_sp) {} + + ScriptedMetadata(const ProcessLaunchInfo &launch_info) { + m_class_name = launch_info.GetScriptedProcessClassName(); + m_args_sp = launch_info.GetScriptedProcessDictionarySP(); + } + + ScriptedMetadata(const OptionGroupPythonClassWithDict &option_group) { + auto opt_group = const_cast<OptionGroupPythonClassWithDict &>(option_group); + m_class_name = opt_group.GetName(); + m_args_sp = opt_group.GetStructuredData(); + } + + llvm::StringRef GetClassName() const { return m_class_name; } + StructuredData::DictionarySP GetArgsSP() const { return m_args_sp; } + +private: + std::string m_class_name; + StructuredData::DictionarySP m_args_sp; +}; +} // namespace lldb_private + +#endif // LLDB_INTERPRETER_SCRIPTEDMETADATA_H diff --git a/contrib/llvm-project/lldb/include/lldb/Interpreter/ScriptedPlatformInterface.h b/contrib/llvm-project/lldb/include/lldb/Interpreter/ScriptedPlatformInterface.h new file mode 100644 index 000000000000..2db1fef0be72 --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/Interpreter/ScriptedPlatformInterface.h @@ -0,0 +1,49 @@ +//===-- ScriptedPlatformInterface.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_INTERPRETER_SCRIPTEDPLATFORMINTERFACE_H +#define LLDB_INTERPRETER_SCRIPTEDPLATFORMINTERFACE_H + +#include "lldb/Core/StructuredDataImpl.h" +#include "lldb/Interpreter/ScriptedInterface.h" + +#include "lldb/lldb-private.h" + +#include <string> + +namespace lldb_private { +class ScriptedPlatformInterface : virtual public ScriptedInterface { +public: + StructuredData::GenericSP + CreatePluginObject(llvm::StringRef class_name, ExecutionContext &exe_ctx, + StructuredData::DictionarySP args_sp, + StructuredData::Generic *script_obj = nullptr) override { + return {}; + } + + virtual StructuredData::DictionarySP ListProcesses() { return {}; } + + virtual StructuredData::DictionarySP GetProcessInfo(lldb::pid_t) { + return {}; + } + + virtual Status AttachToProcess(lldb::ProcessAttachInfoSP attach_info) { + return Status("ScriptedPlatformInterface cannot attach to a process"); + } + + virtual Status LaunchProcess(lldb::ProcessLaunchInfoSP launch_info) { + return Status("ScriptedPlatformInterface cannot launch process"); + } + + virtual Status KillProcess(lldb::pid_t pid) { + return Status("ScriptedPlatformInterface cannot kill process"); + } +}; +} // namespace lldb_private + +#endif // LLDB_INTERPRETER_SCRIPTEDPLATFORMINTERFACE_H diff --git a/contrib/llvm-project/lldb/include/lldb/Interpreter/ScriptedProcessInterface.h b/contrib/llvm-project/lldb/include/lldb/Interpreter/ScriptedProcessInterface.h index 905623e575f7..6d1860aa310a 100644 --- a/contrib/llvm-project/lldb/include/lldb/Interpreter/ScriptedProcessInterface.h +++ b/contrib/llvm-project/lldb/include/lldb/Interpreter/ScriptedProcessInterface.h @@ -15,6 +15,7 @@ #include "lldb/lldb-private.h" +#include <optional> #include <string> namespace lldb_private { @@ -24,7 +25,7 @@ public: CreatePluginObject(llvm::StringRef class_name, ExecutionContext &exe_ctx, StructuredData::DictionarySP args_sp, StructuredData::Generic *script_obj = nullptr) override { - return nullptr; + return {}; } virtual Status Launch() { return Status("ScriptedProcess did not launch"); } @@ -35,41 +36,43 @@ public: virtual Status Stop() { return Status("ScriptedProcess did not stop"); } - virtual llvm::Optional<MemoryRegionInfo> + virtual std::optional<MemoryRegionInfo> GetMemoryRegionContainingAddress(lldb::addr_t address, Status &error) { error.SetErrorString("ScriptedProcess have no memory region."); return {}; } - virtual StructuredData::DictionarySP GetThreadsInfo() { return nullptr; } + virtual StructuredData::DictionarySP GetThreadsInfo() { return {}; } virtual StructuredData::DictionarySP GetThreadWithID(lldb::tid_t tid) { - return nullptr; + return {}; } virtual StructuredData::DictionarySP GetRegistersForThread(lldb::tid_t tid) { - return nullptr; + return {}; } virtual lldb::DataExtractorSP ReadMemoryAtAddress(lldb::addr_t address, size_t size, Status &error) { - return nullptr; + return {}; } - virtual StructuredData::ArraySP GetLoadedImages() { return nullptr; } + virtual StructuredData::ArraySP GetLoadedImages() { return {}; } virtual lldb::pid_t GetProcessID() { return LLDB_INVALID_PROCESS_ID; } virtual bool IsAlive() { return true; } - virtual llvm::Optional<std::string> GetScriptedThreadPluginName() { - return llvm::None; + virtual std::optional<std::string> GetScriptedThreadPluginName() { + return std::nullopt; } + virtual StructuredData::DictionarySP GetMetadata() { return {}; } + protected: friend class ScriptedThread; virtual lldb::ScriptedThreadInterfaceSP CreateScriptedThreadInterface() { - return nullptr; + return {}; } }; @@ -79,26 +82,28 @@ public: CreatePluginObject(llvm::StringRef class_name, ExecutionContext &exe_ctx, StructuredData::DictionarySP args_sp, StructuredData::Generic *script_obj = nullptr) override { - return nullptr; + return {}; } virtual lldb::tid_t GetThreadID() { return LLDB_INVALID_THREAD_ID; } - virtual llvm::Optional<std::string> GetName() { return llvm::None; } + virtual std::optional<std::string> GetName() { return std::nullopt; } virtual lldb::StateType GetState() { return lldb::eStateInvalid; } - virtual llvm::Optional<std::string> GetQueue() { return llvm::None; } + virtual std::optional<std::string> GetQueue() { return std::nullopt; } - virtual StructuredData::DictionarySP GetStopReason() { return nullptr; } + virtual StructuredData::DictionarySP GetStopReason() { return {}; } - virtual StructuredData::ArraySP GetStackFrames() { return nullptr; } + virtual StructuredData::ArraySP GetStackFrames() { return {}; } - virtual StructuredData::DictionarySP GetRegisterInfo() { return nullptr; } + virtual StructuredData::DictionarySP GetRegisterInfo() { return {}; } - virtual llvm::Optional<std::string> GetRegisterContext() { - return llvm::None; + virtual std::optional<std::string> GetRegisterContext() { + return std::nullopt; } + + virtual StructuredData::ArraySP GetExtendedInfo() { return {}; } }; } // namespace lldb_private diff --git a/contrib/llvm-project/lldb/include/lldb/Symbol/CompilerType.h b/contrib/llvm-project/lldb/include/lldb/Symbol/CompilerType.h index aefd19d0a859..c96fc5a2b688 100644 --- a/contrib/llvm-project/lldb/include/lldb/Symbol/CompilerType.h +++ b/contrib/llvm-project/lldb/include/lldb/Symbol/CompilerType.h @@ -10,15 +10,18 @@ #define LLDB_SYMBOL_COMPILERTYPE_H #include <functional> +#include <optional> #include <string> #include <vector> #include "lldb/lldb-private.h" #include "llvm/ADT/APSInt.h" +#include "llvm/Support/Casting.h" namespace lldb_private { class DataExtractor; +class TypeSystem; /// Generic representation of a type in a programming language. /// @@ -38,38 +41,87 @@ public: /// implementation. /// /// \see lldb_private::TypeSystemClang::GetType(clang::QualType) - CompilerType(TypeSystem *type_system, lldb::opaque_compiler_type_t type) - : m_type(type), m_type_system(type_system) { + CompilerType(lldb::TypeSystemWP type_system, + lldb::opaque_compiler_type_t type) + : m_type_system(type_system), m_type(type) { + assert(Verify() && "verification failed"); + } + + /// This is a minimal wrapper of a TypeSystem shared pointer as + /// returned by CompilerType which conventien dyn_cast support. + class TypeSystemSPWrapper { + lldb::TypeSystemSP m_typesystem_sp; + + public: + TypeSystemSPWrapper() = default; + TypeSystemSPWrapper(lldb::TypeSystemSP typesystem_sp) + : m_typesystem_sp(typesystem_sp) {} + + template <class TypeSystemType> bool isa_and_nonnull() { + if (auto *ts = m_typesystem_sp.get()) + return llvm::isa<TypeSystemType>(ts); + return false; + } + + /// Return a shared_ptr<TypeSystemType> if dyn_cast succeeds. + template <class TypeSystemType> + std::shared_ptr<TypeSystemType> dyn_cast_or_null() { + if (isa_and_nonnull<TypeSystemType>()) + return std::shared_ptr<TypeSystemType>( + m_typesystem_sp, llvm::cast<TypeSystemType>(m_typesystem_sp.get())); + return nullptr; + } + + explicit operator bool() const { + return static_cast<bool>(m_typesystem_sp); + } + bool operator==(const TypeSystemSPWrapper &other) const; + bool operator!=(const TypeSystemSPWrapper &other) const { + return !(*this == other); + } + + /// Only to be used in a one-off situations like + /// if (typesystem && typesystem->method()) + /// Do not store this pointer! + TypeSystem *operator->() const; + + lldb::TypeSystemSP GetSharedPointer() const { return m_typesystem_sp; } + }; + + CompilerType(TypeSystemSPWrapper type_system, lldb::opaque_compiler_type_t type) + : m_type_system(type_system.GetSharedPointer()), m_type(type) { assert(Verify() && "verification failed"); } CompilerType(const CompilerType &rhs) - : m_type(rhs.m_type), m_type_system(rhs.m_type_system) {} + : m_type_system(rhs.m_type_system), m_type(rhs.m_type) {} CompilerType() = default; /// Operators. /// \{ const CompilerType &operator=(const CompilerType &rhs) { - m_type = rhs.m_type; m_type_system = rhs.m_type_system; + m_type = rhs.m_type; return *this; } bool operator<(const CompilerType &rhs) const { - if (m_type_system == rhs.m_type_system) + auto lts = m_type_system.lock(); + auto rts = rhs.m_type_system.lock(); + if (lts.get() == rts.get()) return m_type < rhs.m_type; - return m_type_system < rhs.m_type_system; + return lts.get() < rts.get(); } /// \} /// Tests. /// \{ explicit operator bool() const { - return m_type != nullptr && m_type_system != nullptr; + return m_type_system.lock() && m_type; } - bool IsValid() const { return m_type != nullptr && m_type_system != nullptr; } + bool IsValid() const { return (bool)*this; } bool IsArrayType(CompilerType *element_type = nullptr, uint64_t *size = nullptr, @@ -142,6 +194,8 @@ public: bool IsScalarType() const; + bool IsTemplateType() const; + bool IsTypedefType() const; bool IsVoidType() const; @@ -152,6 +206,8 @@ public: bool GetCompleteType() const; /// \} + bool IsForcefullyCompleted() const; + /// AST related queries. /// \{ size_t GetPointerByteSize() const; @@ -159,9 +215,12 @@ public: /// Accessors. /// \{ - TypeSystem *GetTypeSystem() const { return m_type_system; } - ConstString GetTypeName() const; + /// Returns a shared pointer to the type system. The + /// TypeSystem::TypeSystemSPWrapper can be compared for equality. + TypeSystemSPWrapper GetTypeSystem() const; + + ConstString GetTypeName(bool BaseOnly = false) const; ConstString GetDisplayTypeName() const; @@ -174,7 +233,9 @@ public: lldb::TypeClass GetTypeClass() const; - void SetCompilerType(TypeSystem *type_system, + void SetCompilerType(lldb::TypeSystemWP type_system, + lldb::opaque_compiler_type_t type); + void SetCompilerType(TypeSystemSPWrapper type_system, lldb::opaque_compiler_type_t type); unsigned GetTypeQualifiers() const; @@ -266,16 +327,15 @@ public: struct IntegralTemplateArgument; /// Return the size of the type in bytes. - llvm::Optional<uint64_t> GetByteSize(ExecutionContextScope *exe_scope) const; + std::optional<uint64_t> GetByteSize(ExecutionContextScope *exe_scope) const; /// Return the size of the type in bits. - llvm::Optional<uint64_t> GetBitSize(ExecutionContextScope *exe_scope) const; + std::optional<uint64_t> GetBitSize(ExecutionContextScope *exe_scope) const; lldb::Encoding GetEncoding(uint64_t &count) const; lldb::Format GetFormat() const; - llvm::Optional<size_t> - GetTypeBitAlign(ExecutionContextScope *exe_scope) const; + std::optional<size_t> GetTypeBitAlign(ExecutionContextScope *exe_scope) const; uint32_t GetNumChildren(bool omit_empty_base_classes, const ExecutionContext *exe_ctx) const; @@ -358,7 +418,7 @@ public: /// expanded to their supplied arguments. With expand_pack set to false, an /// arguement pack will count as 1 argument and it is invalid to call this /// method on the pack argument. - llvm::Optional<IntegralTemplateArgument> + std::optional<IntegralTemplateArgument> GetIntegralTemplateArgument(size_t idx, bool expand_pack = false) const; CompilerType GetTypeForFormatters() const; @@ -407,8 +467,8 @@ public: size_t data_byte_size, Scalar &value, ExecutionContextScope *exe_scope) const; void Clear() { + m_type_system = {}; m_type = nullptr; - m_type_system = nullptr; } private: @@ -419,8 +479,8 @@ private: bool Verify() const; #endif + lldb::TypeSystemWP m_type_system; lldb::opaque_compiler_type_t m_type = nullptr; - TypeSystem *m_type_system = nullptr; }; bool operator==(const CompilerType &lhs, const CompilerType &rhs); diff --git a/contrib/llvm-project/lldb/include/lldb/Symbol/DWARFCallFrameInfo.h b/contrib/llvm-project/lldb/include/lldb/Symbol/DWARFCallFrameInfo.h index 199d23eff9b6..ea5c325e11a3 100644 --- a/contrib/llvm-project/lldb/include/lldb/Symbol/DWARFCallFrameInfo.h +++ b/contrib/llvm-project/lldb/include/lldb/Symbol/DWARFCallFrameInfo.h @@ -11,6 +11,7 @@ #include <map> #include <mutex> +#include <optional> #include "lldb/Core/AddressRange.h" #include "lldb/Core/dwarf.h" @@ -122,7 +123,7 @@ private: bool IsEHFrame() const; - llvm::Optional<FDEEntryMap::Entry> + std::optional<FDEEntryMap::Entry> GetFirstFDEEntryInRange(const AddressRange &range); void GetFDEIndex(); diff --git a/contrib/llvm-project/lldb/include/lldb/Symbol/DebugMacros.h b/contrib/llvm-project/lldb/include/lldb/Symbol/DebugMacros.h index 0ea70f5deb84..fbc5be0ee601 100644 --- a/contrib/llvm-project/lldb/include/lldb/Symbol/DebugMacros.h +++ b/contrib/llvm-project/lldb/include/lldb/Symbol/DebugMacros.h @@ -39,7 +39,7 @@ public: static DebugMacroEntry CreateIndirectEntry(const DebugMacrosSP &debug_macros_sp); - DebugMacroEntry() : m_type(INVALID) {} + DebugMacroEntry() : m_type(INVALID), m_line(0), m_debug_line_file_idx(0) {} ~DebugMacroEntry() = default; diff --git a/contrib/llvm-project/lldb/include/lldb/Symbol/Function.h b/contrib/llvm-project/lldb/include/lldb/Symbol/Function.h index 3eb4f5d7dedf..2da13f878a79 100644 --- a/contrib/llvm-project/lldb/include/lldb/Symbol/Function.h +++ b/contrib/llvm-project/lldb/include/lldb/Symbol/Function.h @@ -485,7 +485,7 @@ public: llvm::ArrayRef<std::unique_ptr<CallEdge>> GetCallEdges(); /// Get the outgoing tail-calling edges from this function. If none exist, - /// return None. + /// return std::nullopt. llvm::ArrayRef<std::unique_ptr<CallEdge>> GetTailCallingEdges(); /// Get the outgoing call edge from this function which has the given return diff --git a/contrib/llvm-project/lldb/include/lldb/Symbol/LocateSymbolFile.h b/contrib/llvm-project/lldb/include/lldb/Symbol/LocateSymbolFile.h index f3d0feea4ecc..6f0506e671ce 100644 --- a/contrib/llvm-project/lldb/include/lldb/Symbol/LocateSymbolFile.h +++ b/contrib/llvm-project/lldb/include/lldb/Symbol/LocateSymbolFile.h @@ -14,6 +14,7 @@ #include "lldb/Core/FileSpecList.h" #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/Status.h" +#include "lldb/lldb-forward.h" namespace lldb_private { @@ -52,7 +53,15 @@ public: // static bool DownloadObjectAndSymbolFile(ModuleSpec &module_spec, Status &error, - bool force_lookup = true); + bool force_lookup = true, + bool copy_executable = true); + + /// Locate the symbol file for the given UUID on a background thread. This + /// function returns immediately. Under the hood it uses the debugger's + /// thread pool to call DownloadObjectAndSymbolFile. If a symbol file is + /// found, this will notify all target which contain the module with the + /// given UUID. + static void DownloadSymbolFileAsync(const UUID &uuid); }; } // namespace lldb_private diff --git a/contrib/llvm-project/lldb/include/lldb/Symbol/ObjectContainer.h b/contrib/llvm-project/lldb/include/lldb/Symbol/ObjectContainer.h index 4f0c73693295..cd4713b271c8 100644 --- a/contrib/llvm-project/lldb/include/lldb/Symbol/ObjectContainer.h +++ b/contrib/llvm-project/lldb/include/lldb/Symbol/ObjectContainer.h @@ -36,15 +36,7 @@ public: /// more than one architecture or object. ObjectContainer(const lldb::ModuleSP &module_sp, const FileSpec *file, lldb::offset_t file_offset, lldb::offset_t length, - lldb::DataBufferSP &data_sp, lldb::offset_t data_offset) - : ModuleChild(module_sp), - m_file(), // This file can be different than the module's file spec - m_offset(file_offset), m_length(length) { - if (file) - m_file = *file; - if (data_sp) - m_data.SetData(data_sp, data_offset, length); - } + lldb::DataBufferSP data_sp, lldb::offset_t data_offset); /// Destructor. /// @@ -52,16 +44,6 @@ public: /// from by the plug-in instance. ~ObjectContainer() override = default; - /// Dump a description of this object to a Stream. - /// - /// Dump a description of the current contents of this object to the - /// supplied stream \a s. The dumping should include the section list if it - /// has been parsed, and the symbol table if it has been parsed. - /// - /// \param[in] s - /// The stream to which to dump the object description. - virtual void Dump(Stream *s) const = 0; - /// Gets the architecture given an index. /// /// Copies the architecture specification for index \a idx. @@ -142,29 +124,23 @@ public: /// file exists in the container. virtual lldb::ObjectFileSP GetObjectFile(const FileSpec *file) = 0; - virtual bool ObjectAtIndexIsContainer(uint32_t object_idx) { return false; } + static lldb::ObjectContainerSP + FindPlugin(const lldb::ModuleSP &module_sp, const lldb::ProcessSP &process_sp, + lldb::addr_t header_addr, lldb::WritableDataBufferSP file_data_sp); - virtual ObjectFile *GetObjectFileAtIndex(uint32_t object_idx) { - return nullptr; - } +protected: + /// The file that represents this container objects (which can be different + /// from the module's file). + FileSpec m_file; - virtual ObjectContainer *GetObjectContainerAtIndex(uint32_t object_idx) { - return nullptr; - } + /// The offset in bytes into the file, or the address in memory + lldb::addr_t m_offset; - virtual const char *GetObjectNameAtIndex(uint32_t object_idx) const { - return nullptr; - } + /// The size in bytes if known (can be zero). + lldb::addr_t m_length; -protected: - // Member variables. - FileSpec m_file; ///< The file that represents this container objects (which - ///can be different from the module's file). - lldb::addr_t - m_offset; ///< The offset in bytes into the file, or the address in memory - lldb::addr_t m_length; ///< The size in bytes if known (can be zero). - DataExtractor - m_data; ///< The data for this object file so things can be parsed lazily. + /// The data for this object file so things can be parsed lazily. + DataExtractor m_data; private: ObjectContainer(const ObjectContainer &) = delete; diff --git a/contrib/llvm-project/lldb/include/lldb/Symbol/ObjectFile.h b/contrib/llvm-project/lldb/include/lldb/Symbol/ObjectFile.h index e51d50592c90..e2e0623c9f9e 100644 --- a/contrib/llvm-project/lldb/include/lldb/Symbol/ObjectFile.h +++ b/contrib/llvm-project/lldb/include/lldb/Symbol/ObjectFile.h @@ -19,9 +19,9 @@ #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/UUID.h" #include "lldb/lldb-private.h" -#include "llvm/ADT/Optional.h" #include "llvm/Support/Threading.h" #include "llvm/Support/VersionTuple.h" +#include <optional> namespace lldb_private { @@ -682,6 +682,10 @@ public: return symbol_name; } + /// Can we trust the address ranges accelerator associated with this object + /// file to be complete. + virtual bool CanTrustAddressRanges() { return false; } + static lldb::SymbolType GetSymbolTypeFromName( llvm::StringRef name, lldb::SymbolType symbol_type_hint = lldb::eSymbolTypeUndefined); @@ -723,6 +727,8 @@ public: /// file when storing cached data. uint32_t GetCacheHash(); + static lldb::DataBufferSP MapFileData(const FileSpec &file, uint64_t Size, + uint64_t Offset); protected: // Member variables. @@ -747,7 +753,7 @@ protected: /// need to use a std::unique_ptr to a llvm::once_flag so if we clear the /// symbol table, we can have a new once flag to use when it is created again. std::unique_ptr<llvm::once_flag> m_symtab_once_up; - llvm::Optional<uint32_t> m_cache_hash; + std::optional<uint32_t> m_cache_hash; /// Sets the architecture for a module. At present the architecture can /// only be set if it is invalid. It is not allowed to switch from one @@ -764,9 +770,6 @@ protected: /// The number of bytes to read when going through the plugins. static size_t g_initial_bytes_to_read; - static lldb::DataBufferSP MapFileData(const FileSpec &file, uint64_t Size, - uint64_t Offset); - private: ObjectFile(const ObjectFile &) = delete; const ObjectFile &operator=(const ObjectFile &) = delete; diff --git a/contrib/llvm-project/lldb/include/lldb/Symbol/Symbol.h b/contrib/llvm-project/lldb/include/lldb/Symbol/Symbol.h index 23a68090ff4d..164fafd437dc 100644 --- a/contrib/llvm-project/lldb/include/lldb/Symbol/Symbol.h +++ b/contrib/llvm-project/lldb/include/lldb/Symbol/Symbol.h @@ -85,6 +85,16 @@ public: return Address(); } + /// Get the raw value of the symbol from the symbol table. + /// + /// If the symbol's value is an address, return the file address, else return + /// the raw value that is stored in the m_addr_range. If the base address has + /// no section, then getting the file address will return the correct value + /// as it will return the offset in the base address which is the value. + uint64_t GetRawValue() const { + return m_addr_range.GetBaseAddress().GetFileAddress(); + } + // When a symbol's value isn't an address, we need to access the raw value. // This function will ensure this symbol's value isn't an address and return // the integer value if this checks out, otherwise it will return diff --git a/contrib/llvm-project/lldb/include/lldb/Symbol/SymbolFile.h b/contrib/llvm-project/lldb/include/lldb/Symbol/SymbolFile.h index ed0de1b5bce6..8548973bad3f 100644 --- a/contrib/llvm-project/lldb/include/lldb/Symbol/SymbolFile.h +++ b/contrib/llvm-project/lldb/include/lldb/Symbol/SymbolFile.h @@ -9,6 +9,7 @@ #ifndef LLDB_SYMBOL_SYMBOLFILE_H #define LLDB_SYMBOL_SYMBOLFILE_H +#include "lldb/Core/Module.h" #include "lldb/Core/ModuleList.h" #include "lldb/Core/PluginInterface.h" #include "lldb/Core/SourceLocationSpec.h" @@ -27,6 +28,7 @@ #include "llvm/Support/Errc.h" #include <mutex> +#include <optional> #if defined(LLDB_CONFIGURATION_DEBUG) #define ASSERT_MODULE_LOCK(expr) (expr->AssertModuleLock()) @@ -203,7 +205,7 @@ public: /// To support variable-length array types, this function takes an /// optional \p ExecutionContext. If \c exe_ctx is non-null, the /// dynamic characteristics for that context are returned. - virtual llvm::Optional<ArrayInfo> + virtual std::optional<ArrayInfo> GetDynamicArrayInfoForUID(lldb::user_id_t type_uid, const lldb_private::ExecutionContext *exe_ctx) = 0; @@ -221,6 +223,50 @@ public: virtual uint32_t ResolveSymbolContext(const Address &so_addr, lldb::SymbolContextItem resolve_scope, SymbolContext &sc) = 0; + + /// Get an error that describes why variables might be missing for a given + /// symbol context. + /// + /// If there is an error in the debug information that prevents variables from + /// being fetched, this error will get filled in. If there is no debug + /// informaiton, no error should be returned. But if there is debug + /// information and something prevents the variables from being available a + /// valid error should be returned. Valid cases include: + /// - compiler option that removes variables (-gline-tables-only) + /// - missing external files + /// - .dwo files in fission are not accessible or missing + /// - .o files on darwin when not using dSYM files that are not accessible + /// or missing + /// - mismatched exteral files + /// - .dwo files in fission where the DWO ID doesn't match + /// - .o files on darwin when modification timestamp doesn't match + /// - corrupted debug info + /// + /// \param[in] frame + /// The stack frame to use as a basis for the context to check. The frame + /// address can be used if there is not debug info due to it not being able + /// to be loaded, or if there is a debug info context, like a compile unit, + /// or function, it can be used to track down more information on why + /// variables are missing. + /// + /// \returns + /// An error specifying why there should have been debug info with variable + /// information but the variables were not able to be resolved. + Status GetFrameVariableError(StackFrame &frame) { + Status err = CalculateFrameVariableError(frame); + if (err.Fail()) + SetDebugInfoHadFrameVariableErrors(); + return err; + } + + /// Subclasses will override this function to for GetFrameVariableError(). + /// + /// This allows GetFrameVariableError() to set the member variable + /// m_debug_info_had_variable_errors correctly without users having to do it + /// manually which is error prone. + virtual Status CalculateFrameVariableError(StackFrame &frame) { + return Status(); + } virtual uint32_t ResolveSymbolContext(const SourceLocationSpec &src_location_spec, lldb::SymbolContextItem resolve_scope, @@ -234,9 +280,8 @@ public: virtual void FindGlobalVariables(const RegularExpression ®ex, uint32_t max_matches, VariableList &variables); - virtual void FindFunctions(ConstString name, + virtual void FindFunctions(const Module::LookupInfo &lookup_info, const CompilerDeclContext &parent_decl_ctx, - lldb::FunctionNameType name_type_mask, bool include_inlines, SymbolContextList &sc_list); virtual void FindFunctions(const RegularExpression ®ex, bool include_inlines, SymbolContextList &sc_list); @@ -266,7 +311,7 @@ public: virtual void PreloadSymbols(); - virtual llvm::Expected<lldb_private::TypeSystem &> + virtual llvm::Expected<lldb::TypeSystemSP> GetTypeSystemForLanguage(lldb::LanguageType language) = 0; virtual CompilerDeclContext @@ -361,6 +406,23 @@ public: virtual void SetDebugInfoIndexWasSavedToCache() = 0; /// \} + /// Accessors for the bool that indicates if there was debug info, but errors + /// stopped variables from being able to be displayed correctly. See + /// GetFrameVariableError() for details on what are considered errors. + virtual bool GetDebugInfoHadFrameVariableErrors() const = 0; + virtual void SetDebugInfoHadFrameVariableErrors() = 0; + + virtual lldb::TypeSP + MakeType(lldb::user_id_t uid, ConstString name, + std::optional<uint64_t> byte_size, SymbolContextScope *context, + lldb::user_id_t encoding_uid, + Type::EncodingDataType encoding_uid_type, const Declaration &decl, + const CompilerType &compiler_qual_type, + Type::ResolveState compiler_type_resolve_state, + uint32_t opaque_payload = 0) = 0; + + virtual lldb::TypeSP CopyType(const lldb::TypeSP &other_type) = 0; + protected: void AssertModuleLock(); @@ -415,7 +477,7 @@ public: uint32_t GetNumCompileUnits() override; lldb::CompUnitSP GetCompileUnitAtIndex(uint32_t idx) override; - llvm::Expected<lldb_private::TypeSystem &> + llvm::Expected<lldb::TypeSystemSP> GetTypeSystemForLanguage(lldb::LanguageType language) override; void Dump(Stream &s) override; @@ -434,6 +496,41 @@ public: void SetDebugInfoIndexWasSavedToCache() override { m_index_was_saved_to_cache = true; } + bool GetDebugInfoHadFrameVariableErrors() const override { + return m_debug_info_had_variable_errors; + } + void SetDebugInfoHadFrameVariableErrors() override { + m_debug_info_had_variable_errors = true; + } + + /// This function is used to create types that belong to a SymbolFile. The + /// symbol file will own a strong reference to the type in an internal type + /// list. + lldb::TypeSP MakeType(lldb::user_id_t uid, ConstString name, + std::optional<uint64_t> byte_size, + SymbolContextScope *context, + lldb::user_id_t encoding_uid, + Type::EncodingDataType encoding_uid_type, + const Declaration &decl, + const CompilerType &compiler_qual_type, + Type::ResolveState compiler_type_resolve_state, + uint32_t opaque_payload = 0) override { + lldb::TypeSP type_sp (new Type( + uid, this, name, byte_size, context, encoding_uid, + encoding_uid_type, decl, compiler_qual_type, + compiler_type_resolve_state, opaque_payload)); + m_type_list.Insert(type_sp); + return type_sp; + } + + lldb::TypeSP CopyType(const lldb::TypeSP &other_type) override { + // Make sure the real symbol file matches when copying types. + if (GetBackingSymbolFile() != other_type->GetSymbolFile()) + return lldb::TypeSP(); + lldb::TypeSP type_sp(new Type(*other_type)); + m_type_list.Insert(type_sp); + return type_sp; + } protected: virtual uint32_t CalculateNumCompileUnits() = 0; @@ -445,17 +542,24 @@ protected: // case it isn't the same as the module // object file (debug symbols in a separate // file) - llvm::Optional<std::vector<lldb::CompUnitSP>> m_compile_units; + std::optional<std::vector<lldb::CompUnitSP>> m_compile_units; TypeList m_type_list; - Symtab *m_symtab = nullptr; uint32_t m_abilities = 0; bool m_calculated_abilities = false; bool m_index_was_loaded_from_cache = false; bool m_index_was_saved_to_cache = false; + /// Set to true if any variable feteching errors have been found when calling + /// GetFrameVariableError(). This will be emitted in the "statistics dump" + /// information for a module. + bool m_debug_info_had_variable_errors = false; private: SymbolFileCommon(const SymbolFileCommon &) = delete; const SymbolFileCommon &operator=(const SymbolFileCommon &) = delete; + + /// Do not use m_symtab directly, as it may be freed. Use GetSymtab() + /// to access it instead. + Symtab *m_symtab = nullptr; }; } // namespace lldb_private diff --git a/contrib/llvm-project/lldb/include/lldb/Symbol/SymbolFileOnDemand.h b/contrib/llvm-project/lldb/include/lldb/Symbol/SymbolFileOnDemand.h index e47872c9761c..825fba755e99 100644 --- a/contrib/llvm-project/lldb/include/lldb/Symbol/SymbolFileOnDemand.h +++ b/contrib/llvm-project/lldb/include/lldb/Symbol/SymbolFileOnDemand.h @@ -10,6 +10,7 @@ #define LLDB_SYMBOL_SYMBOLFILEONDEMAND_H #include <mutex> +#include <optional> #include <vector> #include "lldb/Symbol/ObjectFile.h" @@ -96,7 +97,7 @@ public: ParseVariablesForContext(const lldb_private::SymbolContext &sc) override; lldb_private::Type *ResolveTypeUID(lldb::user_id_t type_uid) override; - llvm::Optional<ArrayInfo> GetDynamicArrayInfoForUID( + std::optional<ArrayInfo> GetDynamicArrayInfoForUID( lldb::user_id_t type_uid, const lldb_private::ExecutionContext *exe_ctx) override; @@ -117,6 +118,9 @@ public: lldb::SymbolContextItem resolve_scope, lldb_private::SymbolContext &sc) override; + lldb_private::Status + CalculateFrameVariableError(lldb_private::StackFrame &frame) override; + uint32_t ResolveSymbolContext( const lldb_private::SourceLocationSpec &src_location_spec, lldb::SymbolContextItem resolve_scope, @@ -135,9 +139,8 @@ public: uint32_t max_matches, lldb_private::VariableList &variables) override; - void FindFunctions(lldb_private::ConstString name, + void FindFunctions(const lldb_private::Module::LookupInfo &lookup_info, const lldb_private::CompilerDeclContext &parent_decl_ctx, - lldb::FunctionNameType name_type_mask, bool include_inlines, lldb_private::SymbolContextList &sc_list) override; @@ -165,7 +168,7 @@ public: lldb::TypeClass type_mask, lldb_private::TypeList &type_list) override; - llvm::Expected<lldb_private::TypeSystem &> + llvm::Expected<lldb::TypeSystemSP> GetTypeSystemForLanguage(lldb::LanguageType language) override; lldb_private::CompilerDeclContext FindNamespace( @@ -217,6 +220,30 @@ public: void SetDebugInfoIndexWasSavedToCache() override { m_sym_file_impl->SetDebugInfoIndexWasSavedToCache(); } + bool GetDebugInfoHadFrameVariableErrors() const override { + return m_sym_file_impl->GetDebugInfoHadFrameVariableErrors(); + } + void SetDebugInfoHadFrameVariableErrors() override { + return m_sym_file_impl->SetDebugInfoHadFrameVariableErrors(); + } + + lldb::TypeSP MakeType(lldb::user_id_t uid, ConstString name, + std::optional<uint64_t> byte_size, + SymbolContextScope *context, + lldb::user_id_t encoding_uid, + Type::EncodingDataType encoding_uid_type, + const Declaration &decl, + const CompilerType &compiler_qual_type, + Type::ResolveState compiler_type_resolve_state, + uint32_t opaque_payload = 0) override { + return m_sym_file_impl->MakeType( + uid, name, byte_size, context, encoding_uid, encoding_uid_type, decl, + compiler_qual_type, compiler_type_resolve_state, opaque_payload); + } + + lldb::TypeSP CopyType(const lldb::TypeSP &other_type) override { + return m_sym_file_impl->CopyType(other_type); + } private: Log *GetLog() const { return ::lldb_private::GetLog(LLDBLog::OnDemand); } diff --git a/contrib/llvm-project/lldb/include/lldb/Symbol/Symtab.h b/contrib/llvm-project/lldb/include/lldb/Symbol/Symtab.h index 504b49c02674..57627d2dde7d 100644 --- a/contrib/llvm-project/lldb/include/lldb/Symbol/Symtab.h +++ b/contrib/llvm-project/lldb/include/lldb/Symbol/Symtab.h @@ -89,14 +89,16 @@ public: Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t> &matches); - uint32_t - AppendSymbolIndexesMatchingRegExAndType(const RegularExpression ®ex, - lldb::SymbolType symbol_type, - std::vector<uint32_t> &indexes); + uint32_t AppendSymbolIndexesMatchingRegExAndType( + const RegularExpression ®ex, lldb::SymbolType symbol_type, + std::vector<uint32_t> &indexes, + Mangled::NamePreference name_preference = Mangled::ePreferDemangled); uint32_t AppendSymbolIndexesMatchingRegExAndType( const RegularExpression ®ex, lldb::SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, - std::vector<uint32_t> &indexes); + std::vector<uint32_t> &indexes, + Mangled::NamePreference name_preference = + Mangled::NamePreference::ePreferDemangled); void FindAllSymbolsWithNameAndType(ConstString name, lldb::SymbolType symbol_type, std::vector<uint32_t> &symbol_indexes); @@ -108,7 +110,8 @@ public: void FindAllSymbolsMatchingRexExAndType( const RegularExpression ®ex, lldb::SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, - std::vector<uint32_t> &symbol_indexes); + std::vector<uint32_t> &symbol_indexes, + Mangled::NamePreference name_preference = Mangled::ePreferDemangled); Symbol *FindFirstSymbolWithNameAndType(ConstString name, lldb::SymbolType symbol_type, Debug symbol_debug_type, diff --git a/contrib/llvm-project/lldb/include/lldb/Symbol/TaggedASTType.h b/contrib/llvm-project/lldb/include/lldb/Symbol/TaggedASTType.h index fe1a2c659d9f..e46cf1b47428 100644 --- a/contrib/llvm-project/lldb/include/lldb/Symbol/TaggedASTType.h +++ b/contrib/llvm-project/lldb/include/lldb/Symbol/TaggedASTType.h @@ -20,7 +20,8 @@ public: TaggedASTType(const CompilerType &compiler_type) : CompilerType(compiler_type) {} - TaggedASTType(lldb::opaque_compiler_type_t type, TypeSystem *type_system) + TaggedASTType(lldb::opaque_compiler_type_t type, + lldb::TypeSystemWP type_system) : CompilerType(type_system, type) {} TaggedASTType(const TaggedASTType<C> &tw) : CompilerType(tw) {} diff --git a/contrib/llvm-project/lldb/include/lldb/Symbol/Type.h b/contrib/llvm-project/lldb/include/lldb/Symbol/Type.h index 4b512de0fabf..046501931d21 100644 --- a/contrib/llvm-project/lldb/include/lldb/Symbol/Type.h +++ b/contrib/llvm-project/lldb/include/lldb/Symbol/Type.h @@ -18,9 +18,11 @@ #include "llvm/ADT/APSInt.h" +#include <optional> #include <set> namespace lldb_private { +class SymbolFileCommon; /// CompilerContext allows an array of these items to be passed to perform /// detailed lookups in SymbolVendor and SymbolFile functions. @@ -100,16 +102,6 @@ public: Full = 3 }; - Type(lldb::user_id_t uid, SymbolFile *symbol_file, ConstString name, - llvm::Optional<uint64_t> byte_size, SymbolContextScope *context, - lldb::user_id_t encoding_uid, EncodingDataType encoding_uid_type, - const Declaration &decl, const CompilerType &compiler_qual_type, - ResolveState compiler_type_resolve_state, uint32_t opaque_payload = 0); - - // This makes an invalid type. Used for functions that return a Type when - // they get an error. - Type(); - void Dump(Stream *s, bool show_context, lldb::DescriptionLevel level = lldb::eDescriptionLevelFull); @@ -123,7 +115,7 @@ public: /// GetModule may return module for compile unit's object file. /// GetExeModule returns module for executable object file that contains - /// compile unit where type was actualy defined. + /// compile unit where type was actually defined. /// GetModule and GetExeModule may return the same value. lldb::ModuleSP GetExeModule(); @@ -135,12 +127,17 @@ public: ConstString GetName(); - llvm::Optional<uint64_t> GetByteSize(ExecutionContextScope *exe_scope); + ConstString GetBaseName(); + + std::optional<uint64_t> GetByteSize(ExecutionContextScope *exe_scope); uint32_t GetNumChildren(bool omit_empty_base_classes); bool IsAggregateType(); + // Returns if the type is a templated decl. Does not look through typedefs. + bool IsTemplateType(); + bool IsValidType() { return m_encoding_uid_type != eEncodingInvalid; } bool IsTypedef() { return m_encoding_uid_type == eEncodingIsTypedefUID; } @@ -166,14 +163,6 @@ public: bool WriteToMemory(ExecutionContext *exe_ctx, lldb::addr_t address, AddressType address_type, DataExtractor &data); - bool GetIsDeclaration() const; - - void SetIsDeclaration(bool b); - - bool GetIsExternal() const; - - void SetIsExternal(bool b); - lldb::Format GetFormat(); lldb::Encoding GetEncoding(uint64_t &count); @@ -236,6 +225,30 @@ protected: Type *GetEncodingType(); bool ResolveCompilerType(ResolveState compiler_type_resolve_state); +private: + /// Only allow Symbol File to create types, as they should own them by keeping + /// them in their TypeList. \see SymbolFileCommon::MakeType() reference in the + /// header documentation here so users will know what function to use if the + /// get a compile error. + friend class lldb_private::SymbolFileCommon; + + Type(lldb::user_id_t uid, SymbolFile *symbol_file, ConstString name, + std::optional<uint64_t> byte_size, SymbolContextScope *context, + lldb::user_id_t encoding_uid, EncodingDataType encoding_uid_type, + const Declaration &decl, const CompilerType &compiler_qual_type, + ResolveState compiler_type_resolve_state, uint32_t opaque_payload = 0); + + // This makes an invalid type. Used for functions that return a Type when + // they get an error. + Type(); + + Type(Type &t) = default; + + Type(Type &&t) = default; + + Type &operator=(const Type &t) = default; + + Type &operator=(Type &&t) = default; }; // the two classes here are used by the public API as a backend to the SBType @@ -295,7 +308,7 @@ public: CompilerType GetCompilerType(bool prefer_dynamic); - TypeSystem *GetTypeSystem(bool prefer_dynamic); + CompilerType::TypeSystemSPWrapper GetTypeSystem(bool prefer_dynamic); bool GetDescription(lldb_private::Stream &strm, lldb::DescriptionLevel description_level); diff --git a/contrib/llvm-project/lldb/include/lldb/Symbol/TypeSystem.h b/contrib/llvm-project/lldb/include/lldb/Symbol/TypeSystem.h index 769449a4933b..a358d6fb13ad 100644 --- a/contrib/llvm-project/lldb/include/lldb/Symbol/TypeSystem.h +++ b/contrib/llvm-project/lldb/include/lldb/Symbol/TypeSystem.h @@ -10,15 +10,17 @@ #define LLDB_SYMBOL_TYPESYSTEM_H #include <functional> -#include <map> #include <mutex> +#include <optional> #include <string> #include "llvm/ADT/APFloat.h" #include "llvm/ADT/APSInt.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallBitVector.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Error.h" +#include "llvm/Support/JSON.h" #include "lldb/Core/PluginInterface.h" #include "lldb/Expression/Expression.h" @@ -31,6 +33,9 @@ class DWARFASTParser; class PDBASTParser; namespace lldb_private { +namespace npdb { + class PdbAstBuilder; +} // namespace npdb /// A SmallBitVector that represents a set of source languages (\p /// lldb::LanguageType). Each lldb::LanguageType is represented by @@ -42,7 +47,7 @@ struct LanguageSet { LanguageSet(); /// If the set contains a single language only, return it. - llvm::Optional<lldb::LanguageType> GetSingularLanguage(); + std::optional<lldb::LanguageType> GetSingularLanguage(); void Insert(lldb::LanguageType language); bool Empty() const; size_t Size() const; @@ -68,7 +73,8 @@ struct LanguageSet { /// \see lldb_private::CompilerType /// \see lldb_private::CompilerDecl /// \see lldb_private::CompilerDeclContext -class TypeSystem : public PluginInterface { +class TypeSystem : public PluginInterface, + public std::enable_shared_from_this<TypeSystem> { public: // Constructors and Destructors ~TypeSystem() override; @@ -82,12 +88,13 @@ public: static lldb::TypeSystemSP CreateInstance(lldb::LanguageType language, Target *target); - // Free up any resources associated with this TypeSystem. Done before - // removing all the TypeSystems from the TypeSystemMap. + /// Free up any resources associated with this TypeSystem. Done before + /// removing all the TypeSystems from the TypeSystemMap. virtual void Finalize() {} virtual DWARFASTParser *GetDWARFParser() { return nullptr; } virtual PDBASTParser *GetPDBParser() { return nullptr; } + virtual npdb::PdbAstBuilder *GetNativePDBParser() { return nullptr; } virtual SymbolFile *GetSymbolFile() const { return m_sym_file; } @@ -196,13 +203,18 @@ public: virtual bool GetCompleteType(lldb::opaque_compiler_type_t type) = 0; + virtual bool IsForcefullyCompleted(lldb::opaque_compiler_type_t type) { + return false; + } + // AST related queries virtual uint32_t GetPointerByteSize() = 0; // Accessors - virtual ConstString GetTypeName(lldb::opaque_compiler_type_t type) = 0; + virtual ConstString GetTypeName(lldb::opaque_compiler_type_t type, + bool BaseOnly) = 0; virtual ConstString GetDisplayTypeName(lldb::opaque_compiler_type_t type) = 0; @@ -274,7 +286,7 @@ public: virtual const llvm::fltSemantics &GetFloatTypeSemantics(size_t byte_size) = 0; - virtual llvm::Optional<uint64_t> + virtual std::optional<uint64_t> GetBitSize(lldb::opaque_compiler_type_t type, ExecutionContextScope *exe_scope) = 0; @@ -346,6 +358,8 @@ public: const char *name, bool omit_empty_base_classes, std::vector<uint32_t> &child_indexes) = 0; + virtual bool IsTemplateType(lldb::opaque_compiler_type_t type); + virtual size_t GetNumTemplateArguments(lldb::opaque_compiler_type_t type, bool expand_pack); @@ -355,7 +369,7 @@ public: virtual CompilerType GetTypeTemplateArgument(lldb::opaque_compiler_type_t type, size_t idx, bool expand_pack); - virtual llvm::Optional<CompilerType::IntegralTemplateArgument> + virtual std::optional<CompilerType::IntegralTemplateArgument> GetIntegralTemplateArgument(lldb::opaque_compiler_type_t type, size_t idx, bool expand_pack); @@ -366,7 +380,7 @@ public: LLVM_DUMP_METHOD virtual void dump(lldb::opaque_compiler_type_t type) const = 0; #endif - + virtual void DumpValue(lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, Stream *s, lldb::Format format, const DataExtractor &data, @@ -421,7 +435,7 @@ public: virtual bool IsCStringType(lldb::opaque_compiler_type_t type, uint32_t &length) = 0; - virtual llvm::Optional<size_t> + virtual std::optional<size_t> GetTypeBitAlign(lldb::opaque_compiler_type_t type, ExecutionContextScope *exe_scope) = 0; @@ -503,8 +517,15 @@ public: // meaningless type itself, instead preferring to use the dynamic type virtual bool IsMeaninglessWithoutDynamicResolution(void *type); + virtual std::optional<llvm::json::Value> ReportStatistics(); + + bool GetHasForcefullyCompletedTypes() const { + return m_has_forcefully_completed_types; + } protected: SymbolFile *m_sym_file = nullptr; + /// Used for reporting statistics. + bool m_has_forcefully_completed_types = false; }; class TypeSystemMap { @@ -518,39 +539,44 @@ public: // Iterate through all of the type systems that are created. Return true from // callback to keep iterating, false to stop iterating. - void ForEach(std::function<bool(TypeSystem *)> const &callback); + void ForEach(std::function<bool(lldb::TypeSystemSP)> const &callback); - llvm::Expected<TypeSystem &> + llvm::Expected<lldb::TypeSystemSP> GetTypeSystemForLanguage(lldb::LanguageType language, Module *module, bool can_create); - llvm::Expected<TypeSystem &> + llvm::Expected<lldb::TypeSystemSP> GetTypeSystemForLanguage(lldb::LanguageType language, Target *target, bool can_create); + /// Check all type systems in the map to see if any have forcefully completed + /// types; + bool GetHasForcefullyCompletedTypes() const; protected: - typedef std::map<lldb::LanguageType, lldb::TypeSystemSP> collection; + typedef llvm::DenseMap<uint16_t, lldb::TypeSystemSP> collection; mutable std::mutex m_mutex; ///< A mutex to keep this object happy in - ///multi-threaded environments. + /// multi-threaded environments. collection m_map; bool m_clear_in_progress = false; private: typedef llvm::function_ref<lldb::TypeSystemSP()> CreateCallback; /// Finds the type system for the given language. If no type system could be - /// found for a language and a CreateCallback was provided, the value returned - /// by the callback will be treated as the TypeSystem for the language. + /// found for a language and a CreateCallback was provided, the value + /// returned by the callback will be treated as the TypeSystem for the + /// language. /// /// \param language The language for which the type system should be found. /// \param create_callback A callback that will be called if no previously /// created TypeSystem that fits the given language /// could found. Can be omitted if a non-existent - /// type system should be treated as an error instead. + /// type system should be treated as an error + /// instead. /// \return The found type system or an error. - llvm::Expected<TypeSystem &> GetTypeSystemForLanguage( + llvm::Expected<lldb::TypeSystemSP> GetTypeSystemForLanguage( lldb::LanguageType language, - llvm::Optional<CreateCallback> create_callback = llvm::None); -}; + std::optional<CreateCallback> create_callback = std::nullopt); + }; } // namespace lldb_private diff --git a/contrib/llvm-project/lldb/include/lldb/Symbol/UnwindTable.h b/contrib/llvm-project/lldb/include/lldb/Symbol/UnwindTable.h index 9548b1f3fcec..a3026504dbdf 100644 --- a/contrib/llvm-project/lldb/include/lldb/Symbol/UnwindTable.h +++ b/contrib/llvm-project/lldb/include/lldb/Symbol/UnwindTable.h @@ -11,6 +11,7 @@ #include <map> #include <mutex> +#include <optional> #include "lldb/lldb-private.h" @@ -60,8 +61,8 @@ private: void Dump(Stream &s); void Initialize(); - llvm::Optional<AddressRange> GetAddressRange(const Address &addr, - SymbolContext &sc); + std::optional<AddressRange> GetAddressRange(const Address &addr, + SymbolContext &sc); typedef std::map<lldb::addr_t, lldb::FuncUnwindersSP> collection; typedef collection::iterator iterator; diff --git a/contrib/llvm-project/lldb/include/lldb/Target/DynamicLoader.h b/contrib/llvm-project/lldb/include/lldb/Target/DynamicLoader.h index 397b4aa30344..22d047ab4b61 100644 --- a/contrib/llvm-project/lldb/include/lldb/Target/DynamicLoader.h +++ b/contrib/llvm-project/lldb/include/lldb/Target/DynamicLoader.h @@ -210,6 +210,58 @@ public: lldb::addr_t base_addr, bool base_addr_is_offset); + /// Find/load a binary into lldb given a UUID and the address where it is + /// loaded in memory, or a slide to be applied to the file address. + /// May force an expensive search on the computer to find the binary by + /// UUID, should not be used for a large number of binaries - intended for + /// an environment where there may be one, or a few, binaries resident in + /// memory. + /// + /// Given a UUID, search for a binary and load it at the address provided, + /// or with the slide applied, or at the file address unslid. + /// + /// Given an address, try to read the binary out of memory, get the UUID, + /// find the file if possible and load it unslid, or add the memory module. + /// + /// \param[in] process + /// The process to add this binary to. + /// + /// \param[in] name + /// Name of the binary, if available. If this method cannot find a + /// matching binary on the debug host, it may create a memory module + /// out of live memory, and the provided name will be used. If an + /// empty StringRef is provided, a name will be constructed for the module + /// based on the address it is loaded at. + /// + /// \param[in] uuid + /// UUID of the binary to be loaded. UUID may be empty, and if a + /// load address is supplied, will read the binary from memory, get + /// a UUID and try to find a local binary. There is a performance + /// cost to doing this, it is not preferable. + /// + /// \param[in] value + /// Address where the binary should be loaded, or read out of memory. + /// Or a slide value, to be applied to the file addresses of the binary. + /// + /// \param[in] value_is_offset + /// A flag indicating that \p value is an address, or an offset to + /// be applied to the file addresses. + /// + /// \param[in] force_symbol_search + /// Allow the search to do a possibly expensive external search for + /// the ObjectFile and/or SymbolFile. + /// + /// \param[in] notify + /// Whether ModulesDidLoad should be called when a binary has been added + /// to the Target. The caller may prefer to batch up these when loading + /// multiple binaries. + /// + /// \return + /// Returns a shared pointer for the Module that has been added. + static lldb::ModuleSP LoadBinaryWithUUIDAndAddress( + Process *process, llvm::StringRef name, UUID uuid, lldb::addr_t value, + bool value_is_offset, bool force_symbol_search, bool notify); + /// Get information about the shared cache for a process, if possible. /// /// On some systems (e.g. Darwin based systems), a set of libraries that are diff --git a/contrib/llvm-project/lldb/include/lldb/Target/Language.h b/contrib/llvm-project/lldb/include/lldb/Target/Language.h index fa79aaee0574..8cc1e72e138a 100644 --- a/contrib/llvm-project/lldb/include/lldb/Target/Language.h +++ b/contrib/llvm-project/lldb/include/lldb/Target/Language.h @@ -175,7 +175,7 @@ public: virtual HardcodedFormatters::HardcodedSyntheticFinder GetHardcodedSynthetics(); - virtual std::vector<ConstString> + virtual std::vector<FormattersMatchCandidate> GetPossibleFormattersMatches(ValueObject &valobj, lldb::DynamicValueType use_dynamic); @@ -279,6 +279,16 @@ public: static void PrintAllLanguages(Stream &s, const char *prefix, const char *suffix); + /// Prints to the specified stream 's' each language type that the + /// current target supports for expression evaluation. + /// + /// \param[out] s Stream to which the language types are written. + /// \param[in] prefix String that is prepended to the language type. + /// \param[in] suffix String that is appended to the language type. + static void PrintSupportedLanguagesForExpressions(Stream &s, + llvm::StringRef prefix, + llvm::StringRef suffix); + // return false from callback to stop iterating static void ForAllLanguages(std::function<bool(lldb::LanguageType)> callback); diff --git a/contrib/llvm-project/lldb/include/lldb/Target/LanguageRuntime.h b/contrib/llvm-project/lldb/include/lldb/Target/LanguageRuntime.h index 0cdb02a44901..9cc79dc976c4 100644 --- a/contrib/llvm-project/lldb/include/lldb/Target/LanguageRuntime.h +++ b/contrib/llvm-project/lldb/include/lldb/Target/LanguageRuntime.h @@ -21,6 +21,7 @@ #include "lldb/Target/Runtime.h" #include "lldb/lldb-private.h" #include "lldb/lldb-public.h" +#include <optional> namespace lldb_private { @@ -150,8 +151,8 @@ public: /// from the user interface. virtual bool IsAllowedRuntimeValue(ConstString name) { return false; } - virtual llvm::Optional<CompilerType> GetRuntimeType(CompilerType base_type) { - return llvm::None; + virtual std::optional<CompilerType> GetRuntimeType(CompilerType base_type) { + return std::nullopt; } void ModulesDidLoad(const ModuleList &module_list) override {} diff --git a/contrib/llvm-project/lldb/include/lldb/Target/Memory.h b/contrib/llvm-project/lldb/include/lldb/Target/Memory.h index b3ad22aff16b..8c564e8f5a8c 100644 --- a/contrib/llvm-project/lldb/include/lldb/Target/Memory.h +++ b/contrib/llvm-project/lldb/include/lldb/Target/Memory.h @@ -116,7 +116,7 @@ public: ~AllocatedMemoryCache(); - void Clear(); + void Clear(bool deallocate_memory); lldb::addr_t AllocateMemory(size_t byte_size, uint32_t permissions, Status &error); diff --git a/contrib/llvm-project/lldb/include/lldb/Target/MemoryRegionInfo.h b/contrib/llvm-project/lldb/include/lldb/Target/MemoryRegionInfo.h index cf38b6ea3345..47d4c9d63987 100644 --- a/contrib/llvm-project/lldb/include/lldb/Target/MemoryRegionInfo.h +++ b/contrib/llvm-project/lldb/include/lldb/Target/MemoryRegionInfo.h @@ -10,11 +10,11 @@ #ifndef LLDB_TARGET_MEMORYREGIONINFO_H #define LLDB_TARGET_MEMORYREGIONINFO_H +#include <optional> #include <vector> #include "lldb/Utility/ConstString.h" #include "lldb/Utility/RangeMap.h" -#include "llvm/ADT/Optional.h" #include "llvm/Support/FormatProviders.h" namespace lldb_private { @@ -120,7 +120,7 @@ public: /// modified -- within this memory region. This is an Optional return /// value; it will only be available if the remote stub was able to /// detail this. - const llvm::Optional<std::vector<lldb::addr_t>> &GetDirtyPageList() const { + const std::optional<std::vector<lldb::addr_t>> &GetDirtyPageList() const { return m_dirty_pages; } @@ -132,7 +132,7 @@ public: void SetDirtyPageList(std::vector<lldb::addr_t> pagelist) { if (m_dirty_pages) - m_dirty_pages.value().clear(); + m_dirty_pages->clear(); m_dirty_pages = std::move(pagelist); } @@ -149,7 +149,7 @@ protected: OptionalBool m_memory_tagged = eDontKnow; OptionalBool m_is_stack_memory = eDontKnow; int m_pagesize = 0; - llvm::Optional<std::vector<lldb::addr_t>> m_dirty_pages; + std::optional<std::vector<lldb::addr_t>> m_dirty_pages; }; inline bool operator<(const MemoryRegionInfo &lhs, diff --git a/contrib/llvm-project/lldb/include/lldb/Target/MemoryTagMap.h b/contrib/llvm-project/lldb/include/lldb/Target/MemoryTagMap.h index acf3825bfb3f..272f722dbfb3 100644 --- a/contrib/llvm-project/lldb/include/lldb/Target/MemoryTagMap.h +++ b/contrib/llvm-project/lldb/include/lldb/Target/MemoryTagMap.h @@ -11,8 +11,8 @@ #include "lldb/Target/MemoryTagManager.h" #include "lldb/lldb-private.h" -#include "llvm/ADT/Optional.h" #include <map> +#include <optional> namespace lldb_private { @@ -64,10 +64,10 @@ public: /// /// If the range had no tags at all, the vector will be empty. /// If some of the range was tagged it will have items and some - /// of them may be llvm::None. - /// (this saves the caller checking whether all items are llvm::None) - std::vector<llvm::Optional<lldb::addr_t>> GetTags(lldb::addr_t addr, - size_t len) const; + /// of them may be std::nullopt. + /// (this saves the caller checking whether all items are std::nullopt) + std::vector<std::optional<lldb::addr_t>> GetTags(lldb::addr_t addr, + size_t len) const; private: /// Lookup the tag for address @@ -77,9 +77,9 @@ private: /// to a granule boundary. /// /// \return - /// The tag for the granule that address refers to, or llvm::None + /// The tag for the granule that address refers to, or std::nullopt /// if it has no memory tag. - llvm::Optional<lldb::addr_t> GetTag(lldb::addr_t addr) const; + std::optional<lldb::addr_t> GetTag(lldb::addr_t addr) const; // A map of granule aligned addresses to their memory tag std::map<lldb::addr_t, lldb::addr_t> m_addr_to_tag; @@ -87,7 +87,7 @@ private: // Memory tag manager used to align addresses and get granule size. // Ideally this would be a const& but only certain architectures will // have a memory tag manager class to provide here. So for a method - // returning a MemoryTagMap, Optional<MemoryTagMap> allows it to handle + // returning a MemoryTagMap, std::optional<MemoryTagMap> allows it to handle // architectures without memory tagging. Optionals cannot hold references // so we go with a pointer that we assume will be not be null. const MemoryTagManager *m_manager; diff --git a/contrib/llvm-project/lldb/include/lldb/Target/PathMappingList.h b/contrib/llvm-project/lldb/include/lldb/Target/PathMappingList.h index f1cc779ea50f..447fb43f4d6d 100644 --- a/contrib/llvm-project/lldb/include/lldb/Target/PathMappingList.h +++ b/contrib/llvm-project/lldb/include/lldb/Target/PathMappingList.h @@ -9,10 +9,12 @@ #ifndef LLDB_TARGET_PATHMAPPINGLIST_H #define LLDB_TARGET_PATHMAPPINGLIST_H -#include <map> -#include <vector> #include "lldb/Utility/ConstString.h" #include "lldb/Utility/Status.h" +#include "llvm/Support/JSON.h" +#include <map> +#include <optional> +#include <vector> namespace lldb_private { @@ -36,11 +38,18 @@ public: void Append(const PathMappingList &rhs, bool notify); + /// Append <path, replacement> pair without duplication. + /// \return whether appending suceeds without duplication or not. + bool AppendUnique(llvm::StringRef path, llvm::StringRef replacement, + bool notify); + void Clear(bool notify); // By default, dump all pairs. void Dump(Stream *s, int pair_index = -1); + llvm::json::Value ToJSON(); + bool IsEmpty() const { return m_pairs.empty(); } size_t GetSize() const { return m_pairs.size(); } @@ -73,19 +82,34 @@ public: /// \param[in] only_if_exists /// If \b true, besides matching \p path with the remapping rules, this /// tries to check with the filesystem that the remapped file exists. If - /// no valid file is found, \b None is returned. This might be expensive, - /// specially on a network. + /// no valid file is found, \b std::nullopt is returned. This might be + /// expensive, specially on a network. /// /// If \b false, then the existence of the returned remapping is not /// checked. /// /// \return /// The remapped filespec that may or may not exist on disk. - llvm::Optional<FileSpec> RemapPath(llvm::StringRef path, - bool only_if_exists = false) const; + std::optional<FileSpec> RemapPath(llvm::StringRef path, + bool only_if_exists = false) const; bool RemapPath(const char *, std::string &) const = delete; - bool ReverseRemapPath(const FileSpec &file, FileSpec &fixed) const; + /// Perform reverse source path remap for input \a file. + /// Source maps contains a list of <from_original_path, to_new_path> mappings. + /// Reverse remap means locating a matching entry prefix using "to_new_path" + /// part and replacing it with "from_original_path" part if found. + /// + /// \param[in] file + /// The source path to reverse remap. + /// \param[in] fixed + /// The reversed mapped new path. + /// + /// \return + /// std::nullopt if no remapping happens, otherwise, the matching source + /// map entry's ""to_new_pathto"" part (which is the prefix of \a file) is + /// returned. + std::optional<llvm::StringRef> ReverseRemapPath(const FileSpec &file, + FileSpec &fixed) const; /// Finds a source file given a file spec using the path remappings. /// @@ -100,7 +124,7 @@ public: /// /// \return /// The newly remapped filespec that is guaranteed to exist. - llvm::Optional<FileSpec> FindFile(const FileSpec &orig_spec) const; + std::optional<FileSpec> FindFile(const FileSpec &orig_spec) const; uint32_t FindIndexForPath(llvm::StringRef path) const; diff --git a/contrib/llvm-project/lldb/include/lldb/Target/Platform.h b/contrib/llvm-project/lldb/include/lldb/Target/Platform.h index aa09b345e4e1..08e47cc13247 100644 --- a/contrib/llvm-project/lldb/include/lldb/Target/Platform.h +++ b/contrib/llvm-project/lldb/include/lldb/Target/Platform.h @@ -13,6 +13,7 @@ #include <map> #include <memory> #include <mutex> +#include <optional> #include <string> #include <vector> @@ -203,9 +204,9 @@ public: bool SetOSVersion(llvm::VersionTuple os_version); - llvm::Optional<std::string> GetOSBuildString(); + std::optional<std::string> GetOSBuildString(); - llvm::Optional<std::string> GetOSKernelDescription(); + std::optional<std::string> GetOSKernelDescription(); // Returns the name of the platform llvm::StringRef GetName() { return GetPluginName(); } @@ -231,12 +232,12 @@ public: // HostInfo::GetOSVersion(). virtual bool GetRemoteOSVersion() { return false; } - virtual llvm::Optional<std::string> GetRemoteOSBuildString() { - return llvm::None; + virtual std::optional<std::string> GetRemoteOSBuildString() { + return std::nullopt; } - virtual llvm::Optional<std::string> GetRemoteOSKernelDescription() { - return llvm::None; + virtual std::optional<std::string> GetRemoteOSKernelDescription() { + return std::nullopt; } // Remote Platform subclasses need to override this function @@ -329,7 +330,7 @@ public: /// the target triple contained within. virtual bool IsCompatibleArchitecture(const ArchSpec &arch, const ArchSpec &process_host_arch, - bool exact_arch_match, + ArchSpec::MatchType match, ArchSpec *compatible_arch_ptr); /// Not all platforms will support debugging a process by spawning somehow @@ -846,6 +847,34 @@ public: return nullptr; } + /// Detect a binary in memory that will determine which Platform and + /// DynamicLoader should be used in this target/process, and update + /// the Platform/DynamicLoader. + /// The binary will be loaded into the Target, or will be registered with + /// the DynamicLoader so that it will be loaded at a later stage. Returns + /// true to indicate that this is a platform binary and has been + /// loaded/registered, no further action should be taken by the caller. + /// + /// \param[in] process + /// Process read memory from, a Process must be provided. + /// + /// \param[in] addr + /// Address of a binary in memory. + /// + /// \param[in] notify + /// Whether ModulesDidLoad should be called, if a binary is loaded. + /// Caller may prefer to call ModulesDidLoad for multiple binaries + /// that were loaded at the same time. + /// + /// \return + /// Returns true if the binary was loaded in the target (or will be + /// via a DynamicLoader). Returns false if the binary was not + /// loaded/registered, and the caller must load it into the target. + virtual bool LoadPlatformBinaryAndSetup(Process *process, lldb::addr_t addr, + bool notify) { + return false; + } + virtual CompilerType GetSiginfoType(const llvm::Triple &triple); virtual Args GetExtraStartupCommands(); @@ -1026,6 +1055,32 @@ public: lldb::PlatformSP Create(llvm::StringRef name); + /// Detect a binary in memory that will determine which Platform and + /// DynamicLoader should be used in this target/process, and update + /// the Platform/DynamicLoader. + /// The binary will be loaded into the Target, or will be registered with + /// the DynamicLoader so that it will be loaded at a later stage. Returns + /// true to indicate that this is a platform binary and has been + /// loaded/registered, no further action should be taken by the caller. + /// + /// \param[in] process + /// Process read memory from, a Process must be provided. + /// + /// \param[in] addr + /// Address of a binary in memory. + /// + /// \param[in] notify + /// Whether ModulesDidLoad should be called, if a binary is loaded. + /// Caller may prefer to call ModulesDidLoad for multiple binaries + /// that were loaded at the same time. + /// + /// \return + /// Returns true if the binary was loaded in the target (or will be + /// via a DynamicLoader). Returns false if the binary was not + /// loaded/registered, and the caller must load it into the target. + bool LoadPlatformBinaryAndSetup(Process *process, lldb::addr_t addr, + bool notify); + protected: typedef std::vector<lldb::PlatformSP> collection; mutable std::recursive_mutex m_mutex; diff --git a/contrib/llvm-project/lldb/include/lldb/Target/PostMortemProcess.h b/contrib/llvm-project/lldb/include/lldb/Target/PostMortemProcess.h index 353bfc0919ee..7207fc99ef29 100644 --- a/contrib/llvm-project/lldb/include/lldb/Target/PostMortemProcess.h +++ b/contrib/llvm-project/lldb/include/lldb/Target/PostMortemProcess.h @@ -21,9 +21,9 @@ namespace lldb_private { /// between these kinds of processes can have default implementations in this /// class. class PostMortemProcess : public Process { -public: using Process::Process; +public: bool IsLiveDebugSession() const override { return false; } }; diff --git a/contrib/llvm-project/lldb/include/lldb/Target/Process.h b/contrib/llvm-project/lldb/include/lldb/Target/Process.h index 505e211e09b6..ca7f4b545e31 100644 --- a/contrib/llvm-project/lldb/include/lldb/Target/Process.h +++ b/contrib/llvm-project/lldb/include/lldb/Target/Process.h @@ -22,10 +22,10 @@ #include <vector> #include "lldb/Breakpoint/BreakpointSiteList.h" -#include "lldb/Core/Communication.h" #include "lldb/Core/LoadedModuleInfoList.h" #include "lldb/Core/PluginInterface.h" #include "lldb/Core/ThreadSafeValue.h" +#include "lldb/Core/ThreadedCommunication.h" #include "lldb/Core/UserSettingsController.h" #include "lldb/Host/HostThread.h" #include "lldb/Host/ProcessLaunchInfo.h" @@ -475,15 +475,6 @@ public: const ProcessEventData &operator=(const ProcessEventData &) = delete; }; - /// Construct with a shared pointer to a target, and the Process listener. - /// Uses the Host UnixSignalsSP by default. - Process(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp); - - /// Construct with a shared pointer to a target, the Process listener, and - /// the appropriate UnixSignalsSP for the process. - Process(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp, - const lldb::UnixSignalsSP &unix_signals_sp); - /// Destructor. /// /// The destructor is virtual since this class is designed to be inherited @@ -650,6 +641,8 @@ public: /// plug-in. virtual DynamicLoader *GetDynamicLoader(); + void SetDynamicLoader(lldb::DynamicLoaderUP dyld); + // Returns AUXV structure found in many ELF-based environments. // // The default action is to return an empty data buffer. @@ -891,11 +884,26 @@ public: /// Called before attaching to a process. /// + /// \return + /// Returns an error object. + Status WillAttachToProcessWithID(lldb::pid_t pid); + + /// Called before attaching to a process. + /// /// Allow Process plug-ins to execute some code before attaching a process. /// /// \return /// Returns an error object. - virtual Status WillAttachToProcessWithID(lldb::pid_t pid) { return Status(); } + virtual Status DoWillAttachToProcessWithID(lldb::pid_t pid) { + return Status(); + } + + /// Called before attaching to a process. + /// + /// \return + /// Returns an error object. + Status WillAttachToProcessWithName(const char *process_name, + bool wait_for_launch); /// Called before attaching to a process. /// @@ -903,8 +911,8 @@ public: /// /// \return /// Returns an error object. - virtual Status WillAttachToProcessWithName(const char *process_name, - bool wait_for_launch) { + virtual Status DoWillAttachToProcessWithName(const char *process_name, + bool wait_for_launch) { return Status(); } @@ -997,12 +1005,17 @@ public: virtual void DidVForkDone() {} /// Called before launching to a process. + /// \return + /// Returns an error object. + Status WillLaunch(Module *module); + + /// Called before launching to a process. /// /// Allow Process plug-ins to execute some code before launching a process. /// /// \return /// Returns an error object. - virtual Status WillLaunch(Module *module) { return Status(); } + virtual Status DoWillLaunch(Module *module) { return Status(); } /// Launch a new process. /// @@ -1308,6 +1321,15 @@ public: return StructuredData::ObjectSP(); } + // Get information about the launch state of the process, if possible. + // + // On Darwin systems, libdyld can report on process state, most importantly + // the startup stages where the system library is not yet initialized. + virtual lldb_private::StructuredData::ObjectSP + GetDynamicLoaderProcessState() { + return {}; + } + /// Print a user-visible warning about a module being built with /// optimization /// @@ -2094,7 +2116,7 @@ public: // Queue Queries - void UpdateQueueListIfNeeded(); + virtual void UpdateQueueListIfNeeded(); QueueList &GetQueueList() { UpdateQueueListIfNeeded(); @@ -2410,6 +2432,13 @@ void PruneThreadPlans(); return Status("Not supported"); } + /// Fetch process defined metadata. + /// + /// \return + /// A StructuredDataSP object which, if non-empty, will contain the + /// information related to the process. + virtual StructuredData::DictionarySP GetMetadata() { return nullptr; } + size_t AddImageToken(lldb::addr_t image_ptr); lldb::addr_t GetImagePtrFromToken(size_t token) const; @@ -2499,6 +2528,16 @@ void PruneThreadPlans(); protected: friend class Trace; + + /// Construct with a shared pointer to a target, and the Process listener. + /// Uses the Host UnixSignalsSP by default. + Process(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp); + + /// Construct with a shared pointer to a target, the Process listener, and + /// the appropriate UnixSignalsSP for the process. + Process(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp, + const lldb::UnixSignalsSP &unix_signals_sp); + /// Get the processor tracing type supported for this process. /// Responses might be different depending on the architecture and /// capabilities of the underlying OS. @@ -2665,7 +2704,7 @@ protected: }; void SetNextEventAction(Process::NextEventAction *next_event_action) { - if (m_next_event_action_up.get()) + if (m_next_event_action_up) m_next_event_action_up->HandleBeingUnshipped(); m_next_event_action_up.reset(next_event_action); @@ -2882,7 +2921,7 @@ protected: m_unix_signals_sp; /// This is the current signal set for this process. lldb::ABISP m_abi_sp; lldb::IOHandlerSP m_process_input_reader; - Communication m_stdio_communication; + ThreadedCommunication m_stdio_communication; std::recursive_mutex m_stdio_communication_mutex; bool m_stdin_forward; /// Remember if stdin must be forwarded to remote debug /// server diff --git a/contrib/llvm-project/lldb/include/lldb/Target/ProcessStructReader.h b/contrib/llvm-project/lldb/include/lldb/Target/ProcessStructReader.h index 8046ef4958bb..4af51cac3289 100644 --- a/contrib/llvm-project/lldb/include/lldb/Target/ProcessStructReader.h +++ b/contrib/llvm-project/lldb/include/lldb/Target/ProcessStructReader.h @@ -39,7 +39,8 @@ protected: public: ProcessStructReader(Process *process, lldb::addr_t base_addr, - CompilerType struct_type) { + CompilerType struct_type) + : m_byte_order(lldb::eByteOrderInvalid), m_addr_byte_size(0) { if (!process) return; if (base_addr == 0 || base_addr == LLDB_INVALID_ADDRESS) diff --git a/contrib/llvm-project/lldb/include/lldb/Target/RemoteAwarePlatform.h b/contrib/llvm-project/lldb/include/lldb/Target/RemoteAwarePlatform.h index f2a4ffae2aae..d183815e1c8b 100644 --- a/contrib/llvm-project/lldb/include/lldb/Target/RemoteAwarePlatform.h +++ b/contrib/llvm-project/lldb/include/lldb/Target/RemoteAwarePlatform.h @@ -10,6 +10,7 @@ #define LLDB_TARGET_REMOTEAWAREPLATFORM_H #include "lldb/Target/Platform.h" +#include <optional> namespace lldb_private { @@ -64,8 +65,8 @@ public: FileSpec &local_file) override; bool GetRemoteOSVersion() override; - llvm::Optional<std::string> GetRemoteOSBuildString() override; - llvm::Optional<std::string> GetRemoteOSKernelDescription() override; + std::optional<std::string> GetRemoteOSBuildString() override; + std::optional<std::string> GetRemoteOSKernelDescription() override; ArchSpec GetRemoteSystemArchitecture() override; Status RunShellCommand(llvm::StringRef command, const FileSpec &working_dir, diff --git a/contrib/llvm-project/lldb/include/lldb/Target/StackFrame.h b/contrib/llvm-project/lldb/include/lldb/Target/StackFrame.h index 7c4340de4de0..6824d916030a 100644 --- a/contrib/llvm-project/lldb/include/lldb/Target/StackFrame.h +++ b/contrib/llvm-project/lldb/include/lldb/Target/StackFrame.h @@ -254,9 +254,14 @@ public: /// that are visible to the entire compilation unit (e.g. file /// static in C, globals that are homed in this CU). /// + /// \param [out] error_ptr + /// If there is an error in the debug information that prevents variables + /// from being fetched. \see SymbolFile::GetFrameVariableError() for full + /// details. + /// /// \return /// A pointer to a list of variables. - VariableList *GetVariableList(bool get_file_globals); + VariableList *GetVariableList(bool get_file_globals, Status *error_ptr); /// Retrieve the list of variables that are in scope at this StackFrame's /// pc. diff --git a/contrib/llvm-project/lldb/include/lldb/Target/StackFrameRecognizer.h b/contrib/llvm-project/lldb/include/lldb/Target/StackFrameRecognizer.h index 64be759dc79e..419f0c0aac1f 100644 --- a/contrib/llvm-project/lldb/include/lldb/Target/StackFrameRecognizer.h +++ b/contrib/llvm-project/lldb/include/lldb/Target/StackFrameRecognizer.h @@ -17,6 +17,7 @@ #include "lldb/lldb-private-forward.h" #include "lldb/lldb-public.h" +#include <optional> #include <vector> namespace lldb_private { @@ -154,7 +155,7 @@ class ValueObjectRecognizerSynthesizedValue : public ValueObject { SetName(parent.GetName()); } - llvm::Optional<uint64_t> GetByteSize() override { + std::optional<uint64_t> GetByteSize() override { return m_parent->GetByteSize(); } lldb::ValueType GetValueType() const override { return m_type; } diff --git a/contrib/llvm-project/lldb/include/lldb/Target/Statistics.h b/contrib/llvm-project/lldb/include/lldb/Target/Statistics.h index 9c0b3ea5ec05..f672786f58f8 100644 --- a/contrib/llvm-project/lldb/include/lldb/Target/Statistics.h +++ b/contrib/llvm-project/lldb/include/lldb/Target/Statistics.h @@ -12,9 +12,11 @@ #include "lldb/Utility/ConstString.h" #include "lldb/Utility/Stream.h" #include "lldb/lldb-forward.h" +#include "llvm/ADT/StringMap.h" #include "llvm/Support/JSON.h" #include <atomic> #include <chrono> +#include <optional> #include <ratio> #include <string> #include <vector> @@ -107,6 +109,7 @@ struct ModuleStats { // identifiers of these modules in the global module list. This allows us to // track down all of the stats that contribute to this module. std::vector<intptr_t> symfile_modules; + llvm::StringMap<llvm::json::Value> type_system_stats; double symtab_parse_time = 0.0; double symtab_index_time = 0.0; double debug_parse_time = 0.0; @@ -118,6 +121,8 @@ struct ModuleStats { bool debug_info_index_saved_to_cache = false; bool debug_info_enabled = true; bool symtab_stripped = false; + bool debug_info_had_variable_errors = false; + bool debug_info_had_incomplete_types = false; }; struct ConstStringStats { @@ -133,6 +138,7 @@ public: void SetLaunchOrAttachTime(); void SetFirstPrivateStopTime(); void SetFirstPublicStopTime(); + void IncreaseSourceMapDeduceCount(); StatsDuration &GetCreateTime() { return m_create_time; } StatsSuccessFail &GetExpressionStats() { return m_expr_eval; } @@ -140,12 +146,13 @@ public: protected: StatsDuration m_create_time; - llvm::Optional<StatsTimepoint> m_launch_or_attach_time; - llvm::Optional<StatsTimepoint> m_first_private_stop_time; - llvm::Optional<StatsTimepoint> m_first_public_stop_time; + std::optional<StatsTimepoint> m_launch_or_attach_time; + std::optional<StatsTimepoint> m_first_private_stop_time; + std::optional<StatsTimepoint> m_first_public_stop_time; StatsSuccessFail m_expr_eval{"expressionEvaluation"}; StatsSuccessFail m_frame_var{"frameVariable"}; std::vector<intptr_t> m_module_identifiers; + uint32_t m_source_map_deduce_count = 0; void CollectStats(Target &target); }; diff --git a/contrib/llvm-project/lldb/include/lldb/Target/StopInfo.h b/contrib/llvm-project/lldb/include/lldb/Target/StopInfo.h index cdb906dcd7ed..9527a6ea553e 100644 --- a/contrib/llvm-project/lldb/include/lldb/Target/StopInfo.h +++ b/contrib/llvm-project/lldb/include/lldb/Target/StopInfo.h @@ -17,7 +17,7 @@ namespace lldb_private { -class StopInfo { +class StopInfo : public std::enable_shared_from_this<StopInfo> { friend class Process::ProcessEventData; friend class ThreadPlanBase; diff --git a/contrib/llvm-project/lldb/include/lldb/Target/Target.h b/contrib/llvm-project/lldb/include/lldb/Target/Target.h index 294fd96bc313..09fbf45191d4 100644 --- a/contrib/llvm-project/lldb/include/lldb/Target/Target.h +++ b/contrib/llvm-project/lldb/include/lldb/Target/Target.h @@ -141,6 +141,8 @@ public: PathMappingList &GetSourcePathMap() const; + bool GetAutoSourceMapRelative() const; + FileSpecList GetExecutableSearchPaths(); void AppendExecutableSearchPaths(const FileSpec &); @@ -162,7 +164,7 @@ public: bool GetEnableNotifyAboutFixIts() const; FileSpec GetSaveJITObjectsDir() const; - + bool GetEnableSyntheticValue() const; uint32_t GetMaxZeroPaddingInFloatFormat() const; @@ -260,7 +262,7 @@ private: void DisableASLRValueChangedCallback(); void InheritTCCValueChangedCallback(); void DisableSTDIOValueChangedCallback(); - + // Settings checker for target.jit-save-objects-dir: void CheckJITObjectsDir(); @@ -453,7 +455,7 @@ private: lldb::DynamicValueType m_use_dynamic = lldb::eNoDynamicValues; Timeout<std::micro> m_timeout = default_timeout; - Timeout<std::micro> m_one_thread_timeout = llvm::None; + Timeout<std::micro> m_one_thread_timeout = std::nullopt; lldb::ExpressionCancelCallback m_cancel_callback = nullptr; void *m_cancel_callback_baton = nullptr; // If m_pound_line_file is not empty and m_pound_line_line is non-zero, use @@ -479,7 +481,8 @@ public: eBroadcastBitModulesLoaded = (1 << 1), eBroadcastBitModulesUnloaded = (1 << 2), eBroadcastBitWatchpointChanged = (1 << 3), - eBroadcastBitSymbolsLoaded = (1 << 4) + eBroadcastBitSymbolsLoaded = (1 << 4), + eBroadcastBitSymbolsChanged = (1 << 5), }; // These two functions fill out the Broadcaster interface: @@ -754,8 +757,7 @@ public: const BreakpointName::Permissions &permissions); void ApplyNameToBreakpoints(BreakpointName &bp_name); - // This takes ownership of the name obj passed in. - void AddBreakpointName(BreakpointName *bp_name); + void AddBreakpointName(std::unique_ptr<BreakpointName> bp_name); void GetBreakpointNames(std::vector<std::string> &names); @@ -779,6 +781,9 @@ public: bool RemoveBreakpointByID(lldb::break_id_t break_id); + /// Resets the hit count of all breakpoints. + void ResetBreakpointHitCounts(); + // The flag 'end_to_end', default to true, signifies that the operation is // performed end to end, for both the debugger and the debuggee. @@ -981,7 +986,7 @@ public: ModuleIsExcludedForUnconstrainedSearches(const lldb::ModuleSP &module_sp); const ArchSpec &GetArchitecture() const { return m_arch.GetSpec(); } - + /// Returns the name of the target's ABI plugin. llvm::StringRef GetABIName() const; @@ -1008,9 +1013,14 @@ public: /// currently selected platform isn't compatible (in case it might be /// manually set following this function call). /// + /// \param[in] merged + /// If true, arch_spec is merged with the current + /// architecture. Otherwise it's replaced. + /// /// \return /// \b true if the architecture was successfully set, \b false otherwise. - bool SetArchitecture(const ArchSpec &arch_spec, bool set_platform = false); + bool SetArchitecture(const ArchSpec &arch_spec, bool set_platform = false, + bool merge = true); bool MergeArchitecture(const ArchSpec &arch_spec); @@ -1108,11 +1118,12 @@ public: PathMappingList &GetImageSearchPathList(); - llvm::Expected<TypeSystem &> + llvm::Expected<lldb::TypeSystemSP> GetScratchTypeSystemForLanguage(lldb::LanguageType language, bool create_on_demand = true); - std::vector<TypeSystem *> GetScratchTypeSystems(bool create_on_demand = true); + std::vector<lldb::TypeSystemSP> + GetScratchTypeSystems(bool create_on_demand = true); PersistentExpressionState * GetPersistentExpressionStateForLanguage(lldb::LanguageType language); @@ -1425,30 +1436,30 @@ protected: LazyBool pass = eLazyBoolCalculate; LazyBool notify = eLazyBoolCalculate; LazyBool stop = eLazyBoolCalculate; - DummySignalValues(LazyBool pass, LazyBool notify, LazyBool stop) : - pass(pass), notify(notify), stop(stop) {} + DummySignalValues(LazyBool pass, LazyBool notify, LazyBool stop) + : pass(pass), notify(notify), stop(stop) {} DummySignalValues() = default; }; using DummySignalElement = llvm::StringMapEntry<DummySignalValues>; - static bool UpdateSignalFromDummy(lldb::UnixSignalsSP signals_sp, - const DummySignalElement &element); - static bool ResetSignalFromDummy(lldb::UnixSignalsSP signals_sp, - const DummySignalElement &element); + static bool UpdateSignalFromDummy(lldb::UnixSignalsSP signals_sp, + const DummySignalElement &element); + static bool ResetSignalFromDummy(lldb::UnixSignalsSP signals_sp, + const DummySignalElement &element); public: /// Add a signal to the Target's list of stored signals/actions. These /// values will get copied into any processes launched from /// this target. - void AddDummySignal(llvm::StringRef name, LazyBool pass, LazyBool print, + void AddDummySignal(llvm::StringRef name, LazyBool pass, LazyBool print, LazyBool stop); /// Updates the signals in signals_sp using the stored dummy signals. /// If warning_stream_sp is not null, if any stored signals are not found in /// the current process, a warning will be emitted here. - void UpdateSignalsFromDummy(lldb::UnixSignalsSP signals_sp, + void UpdateSignalsFromDummy(lldb::UnixSignalsSP signals_sp, lldb::StreamSP warning_stream_sp); /// Clear the dummy signals in signal_names from the target, or all signals /// if signal_names is empty. Also remove the behaviors they set from the - /// process's signals if it exists. + /// process's signals if it exists. void ClearDummySignals(Args &signal_names); /// Print all the signals set in this target. void PrintDummySignals(Stream &strm, Args &signals); @@ -1500,7 +1511,8 @@ protected: SectionLoadHistory m_section_load_history; BreakpointList m_breakpoint_list; BreakpointList m_internal_breakpoint_list; - using BreakpointNameList = std::map<ConstString, BreakpointName *>; + using BreakpointNameList = + std::map<ConstString, std::unique_ptr<BreakpointName>>; BreakpointNameList m_breakpoint_names; lldb::BreakpointSP m_last_created_breakpoint; @@ -1533,7 +1545,7 @@ protected: lldb::TraceSP m_trace_sp; /// Stores the frame recognizers of this target. lldb::StackFrameRecognizerManagerUP m_frame_recognizer_manager_up; - /// These are used to set the signal state when you don't have a process and + /// These are used to set the signal state when you don't have a process and /// more usefully in the Dummy target where you can't know exactly what /// signals you will have. llvm::StringMap<DummySignalValues> m_dummy_signals; diff --git a/contrib/llvm-project/lldb/include/lldb/Target/Thread.h b/contrib/llvm-project/lldb/include/lldb/Target/Thread.h index f5f024434c8e..efe82721a04e 100644 --- a/contrib/llvm-project/lldb/include/lldb/Target/Thread.h +++ b/contrib/llvm-project/lldb/include/lldb/Target/Thread.h @@ -240,6 +240,7 @@ public: // this just calls through to the ThreadSpec's ThreadPassesBasicTests method. virtual bool MatchesSpec(const ThreadSpec *spec); + // Get the current public stop info, calculating it if necessary. lldb::StopInfoSP GetStopInfo(); lldb::StopReason GetStopReason(); @@ -1121,7 +1122,7 @@ public: // "checkpointed and restored" stop info, so if it is still around it is // right even if you have not calculated this yourself, or if it disagrees // with what you might have calculated. - virtual lldb::StopInfoSP GetPrivateStopInfo(); + virtual lldb::StopInfoSP GetPrivateStopInfo(bool calculate = true); // Calculate the stop info that will be shown to lldb clients. For instance, // a "step out" is implemented by running to a breakpoint on the function @@ -1165,6 +1166,14 @@ public: void ResetStopInfo(); void SetShouldReportStop(Vote vote); + + void SetShouldRunBeforePublicStop(bool newval) { + m_should_run_before_public_stop = newval; + } + + bool ShouldRunBeforePublicStop() { + return m_should_run_before_public_stop; + } /// Sets the extended backtrace token for this thread /// @@ -1254,6 +1263,9 @@ protected: uint32_t m_stop_info_override_stop_id; // The stop ID containing the last time // the stop info was checked against // the stop info override + bool m_should_run_before_public_stop; // If this thread has "stop others" + // private work to do, then it will + // set this. const uint32_t m_index_id; ///< A unique 1 based index assigned to each thread /// for easy UI/command line access. lldb::RegisterContextSP m_reg_context_sp; ///< The register context for this diff --git a/contrib/llvm-project/lldb/include/lldb/Target/ThreadPlan.h b/contrib/llvm-project/lldb/include/lldb/Target/ThreadPlan.h index 616939f89fc8..bf68a42e54d1 100644 --- a/contrib/llvm-project/lldb/include/lldb/Target/ThreadPlan.h +++ b/contrib/llvm-project/lldb/include/lldb/Target/ThreadPlan.h @@ -384,6 +384,8 @@ public: virtual void SetStopOthers(bool new_value); virtual bool StopOthers(); + + virtual bool ShouldRunBeforePublicStop() { return false; } // This is the wrapper for DoWillResume that does generic ThreadPlan logic, // then calls DoWillResume. diff --git a/contrib/llvm-project/lldb/include/lldb/Target/Trace.h b/contrib/llvm-project/lldb/include/lldb/Target/Trace.h index beae9e28417d..fc67a0e05ab4 100644 --- a/contrib/llvm-project/lldb/include/lldb/Target/Trace.h +++ b/contrib/llvm-project/lldb/include/lldb/Target/Trace.h @@ -9,6 +9,7 @@ #ifndef LLDB_TARGET_TRACE_H #define LLDB_TARGET_TRACE_H +#include <optional> #include <unordered_map> #include "llvm/Support/JSON.h" @@ -169,9 +170,9 @@ public: /// Get a \a TraceCursor for the given thread's trace. /// /// \return - /// A \a TraceCursorUP. If the thread is not traced or its trace + /// A \a TraceCursorSP. If the thread is not traced or its trace /// information failed to load, an \a llvm::Error is returned. - virtual llvm::Expected<lldb::TraceCursorUP> + virtual llvm::Expected<lldb::TraceCursorSP> CreateNewCursor(Thread &thread) = 0; /// Dump general info about a given thread's trace. Each Trace plug-in @@ -464,19 +465,19 @@ protected: GetLiveProcessBinaryData(llvm::StringRef kind); /// Get the size of the data returned by \a GetLiveThreadBinaryData - llvm::Optional<uint64_t> GetLiveThreadBinaryDataSize(lldb::tid_t tid, - llvm::StringRef kind); + std::optional<uint64_t> GetLiveThreadBinaryDataSize(lldb::tid_t tid, + llvm::StringRef kind); /// Get the size of the data returned by \a GetLiveCpuBinaryData - llvm::Optional<uint64_t> GetLiveCpuBinaryDataSize(lldb::cpu_id_t cpu_id, - llvm::StringRef kind); + std::optional<uint64_t> GetLiveCpuBinaryDataSize(lldb::cpu_id_t cpu_id, + llvm::StringRef kind); /// Get the size of the data returned by \a GetLiveProcessBinaryData - llvm::Optional<uint64_t> GetLiveProcessBinaryDataSize(llvm::StringRef kind); + std::optional<uint64_t> GetLiveProcessBinaryDataSize(llvm::StringRef kind); /// Constructor for post mortem processes Trace(llvm::ArrayRef<lldb::ProcessSP> postmortem_processes, - llvm::Optional<std::vector<lldb::cpu_id_t>> postmortem_cpus); + std::optional<std::vector<lldb::cpu_id_t>> postmortem_cpus); /// Constructor for a live process Trace(Process &live_process) : m_live_process(&live_process) {} @@ -571,7 +572,7 @@ private: /// The list of cpus being traced. Might be \b None depending on the /// plug-in. - llvm::Optional<std::vector<lldb::cpu_id_t>> cpus; + std::optional<std::vector<lldb::cpu_id_t>> cpus; /// Postmortem traces can specific additional data files, which are /// represented in this variable using a data kind identifier for each file. @@ -587,7 +588,7 @@ private: /// \} - llvm::Optional<std::string> live_refresh_error; + std::optional<std::string> live_refresh_error; } m_storage; /// Get the storage after refreshing the data in the case of a live process. diff --git a/contrib/llvm-project/lldb/include/lldb/Target/TraceCursor.h b/contrib/llvm-project/lldb/include/lldb/Target/TraceCursor.h index 95b022331634..cfc25b0cedc9 100644 --- a/contrib/llvm-project/lldb/include/lldb/Target/TraceCursor.h +++ b/contrib/llvm-project/lldb/include/lldb/Target/TraceCursor.h @@ -12,6 +12,7 @@ #include "lldb/lldb-private.h" #include "lldb/Target/ExecutionContext.h" +#include <optional> namespace lldb_private { @@ -52,7 +53,7 @@ namespace lldb_private { /// /// Sample usage: /// -/// TraceCursorUP cursor = trace.GetTrace(thread); +/// TraceCursorSP cursor = trace.GetTrace(thread); /// /// for (; cursor->HasValue(); cursor->Next()) { /// TraceItemKind kind = cursor->GetItemKind(); @@ -92,18 +93,6 @@ namespace lldb_private { /// You can read more in the documentation of these methods. class TraceCursor { public: - /// Helper enum to indicate the reference point when invoking - /// \a TraceCursor::Seek(). - /// The following values are inspired by \a std::istream::seekg. - enum class SeekType { - /// The beginning of the trace, i.e the oldest item. - Beginning = 0, - /// The current position in the trace. - Current, - /// The end of the trace, i.e the most recent item. - End - }; - /// Create a cursor that initially points to the end of the trace, i.e. the /// most recent item. TraceCursor(lldb::ThreadSP thread_sp); @@ -208,7 +197,7 @@ public: /// /// \return /// \b true if and only if the cursor ends up pointing to a valid item. - virtual bool Seek(int64_t offset, SeekType origin) = 0; + virtual bool Seek(int64_t offset, lldb::TraceCursorSeekType origin) = 0; /// \return /// The \a ExecutionContextRef of the backing thread from the creation time @@ -235,8 +224,7 @@ public: bool IsEvent() const; /// \return - /// The specific kind of event the cursor is pointing at, or \b - /// TraceEvent::eTraceEventNone if the cursor not pointing to an event. + /// The specific kind of event the cursor is pointing at. virtual lldb::TraceEvent GetEventType() const = 0; /// \return @@ -261,9 +249,9 @@ public: /// whenever an eTraceEventCPUChanged event is fired. /// /// \return - /// The requested CPU id, or \a llvm::None if this information is + /// The requested CPU id, or LLDB_INVALID_CPU_ID if this information is /// not available for the current item. - virtual llvm::Optional<lldb::cpu_id_t> GetCPU() const = 0; + virtual lldb::cpu_id_t GetCPU() const = 0; /// Get the last hardware clock value that was emitted before the current /// trace item. @@ -272,18 +260,28 @@ public: /// whenever an eTraceEventHWClockTick event is fired. /// /// \return - /// The requested HW clock value, or \a llvm::None if this information is - /// not available for the current item. - virtual llvm::Optional<uint64_t> GetHWClock() const = 0; + /// The requested HW clock value, or \a std::nullopt if this information + /// is not available for the current item. + virtual std::optional<uint64_t> GetHWClock() const = 0; /// Get the approximate wall clock time in nanoseconds at which the current /// trace item was executed. Each trace plug-in has a different definition for /// what time 0 means. /// /// \return - /// The approximate wall clock time for the trace item, or \a llvm::None + /// The approximate wall clock time for the trace item, or \a std::nullopt /// if not available. - virtual llvm::Optional<double> GetWallClockTime() const = 0; + virtual std::optional<double> GetWallClockTime() const = 0; + + /// Get some metadata associated with a synchronization point event. As + /// different trace technologies might have different values for this, + /// we return a string for flexibility. + /// + /// \return + /// A string representing some metadata associated with a + /// \a eTraceEventSyncPoint event. \b std::nullopt if no metadata is + /// available. + virtual std::optional<std::string> GetSyncPointMetadata() const = 0; /// \} protected: diff --git a/contrib/llvm-project/lldb/include/lldb/Target/TraceDumper.h b/contrib/llvm-project/lldb/include/lldb/Target/TraceDumper.h index ada779990e07..ca3bf2c08808 100644 --- a/contrib/llvm-project/lldb/include/lldb/Target/TraceDumper.h +++ b/contrib/llvm-project/lldb/include/lldb/Target/TraceDumper.h @@ -6,9 +6,9 @@ // //===----------------------------------------------------------------------===// -#include "lldb/Target/TraceCursor.h" - #include "lldb/Symbol/SymbolContext.h" +#include "lldb/Target/TraceCursor.h" +#include <optional> #ifndef LLDB_TARGET_TRACE_INSTRUCTION_DUMPER_H #define LLDB_TARGET_TRACE_INSTRUCTION_DUMPER_H @@ -34,13 +34,15 @@ struct TraceDumperOptions { bool show_timestamps = false; /// Dump the events that happened between instructions. bool show_events = false; + /// Dump events and none of the instructions. + bool only_events = false; /// For each instruction, print the instruction kind. bool show_control_flow_kind = false; /// Optional custom id to start traversing from. - llvm::Optional<uint64_t> id = llvm::None; + std::optional<uint64_t> id; /// Optional number of instructions to skip from the starting position /// of the cursor. - llvm::Optional<size_t> skip = llvm::None; + std::optional<size_t> skip; }; /// Class used to dump the instructions of a \a TraceCursor using its current @@ -61,13 +63,313 @@ public: struct TraceItem { lldb::user_id_t id; lldb::addr_t load_address; - llvm::Optional<double> timestamp; - llvm::Optional<uint64_t> hw_clock; - llvm::Optional<llvm::StringRef> error; - llvm::Optional<lldb::TraceEvent> event; - llvm::Optional<SymbolInfo> symbol_info; - llvm::Optional<SymbolInfo> prev_symbol_info; - llvm::Optional<lldb::cpu_id_t> cpu_id; + std::optional<double> timestamp; + std::optional<uint64_t> hw_clock; + std::optional<std::string> sync_point_metadata; + std::optional<llvm::StringRef> error; + std::optional<lldb::TraceEvent> event; + std::optional<SymbolInfo> symbol_info; + std::optional<SymbolInfo> prev_symbol_info; + std::optional<lldb::cpu_id_t> cpu_id; + }; + + /// An object representing a traced function call. + /// + /// A function call is represented using segments and subcalls. + /// + /// TracedSegment: + /// A traced segment is a maximal list of consecutive traced instructions + /// that belong to the same function call. A traced segment will end in + /// three possible ways: + /// - With a call to a function deeper in the callstack. In this case, + /// most of the times this nested call will return + /// and resume with the next segment of this segment's owning function + /// call. More on this later. + /// - Abruptly due to end of trace. In this case, we weren't able to trace + /// the end of this function call. + /// - Simply a return higher in the callstack. + /// + /// In terms of implementation details, as segment can be represented with + /// the beginning and ending instruction IDs from the instruction trace. + /// + /// UntracedPrefixSegment: + /// It might happen that we didn't trace the beginning of a function and we + /// saw it for the first time as part of a return. As a way to signal these + /// cases, we have a placeholder UntracedPrefixSegment class that completes the + /// callgraph. + /// + /// Example: + /// We might have this piece of execution: + /// + /// main() [offset 0x00 to 0x20] [traced instruction ids 1 to 4] + /// foo() [offset 0x00 to 0x80] [traced instruction ids 5 to 20] # main + /// invoked foo + /// main() [offset 0x24 to 0x40] [traced instruction ids 21 to 30] + /// + /// In this case, our function main invokes foo. We have 3 segments: main + /// [offset 0x00 to 0x20], foo() [offset 0x00 to 0x80], and main() [offset + /// 0x24 to 0x40]. We also have the instruction ids from the corresponding + /// linear instruction trace for each segment. + /// + /// But what if we started tracing since the middle of foo? Then we'd have + /// an incomplete trace + /// + /// foo() [offset 0x30 to 0x80] [traced instruction ids 1 to 10] + /// main() [offset 0x24 to 0x40] [traced instruction ids 11 to 20] + /// + /// Notice that we changed the instruction ids because this is a new trace. + /// Here, in order to have a somewhat complete tree with good traversal + /// capabilities, we can create an UntracedPrefixSegment to signal the portion of + /// main() that we didn't trace. We don't know if this segment was in fact + /// multiple segments with many function calls. We'll never know. The + /// resulting tree looks like the following: + /// + /// main() [untraced] + /// foo() [offset 0x30 to 0x80] [traced instruction ids 1 to 10] + /// main() [offset 0x24 to 0x40] [traced instruction ids 11 to 20] + /// + /// And in pseudo-code: + /// + /// FunctionCall [ + /// UntracedPrefixSegment { + /// symbol: main() + /// nestedCall: FunctionCall [ # this untraced segment has a nested + /// call + /// TracedSegment { + /// symbol: foo() + /// fromInstructionId: 1 + /// toInstructionId: 10 + /// nestedCall: none # this doesn't have a nested call + /// } + /// } + /// ], + /// TracedSegment { + /// symbol: main() + /// fromInstructionId: 11 + /// toInstructionId: 20 + /// nestedCall: none # this also doesn't have a nested call + /// } + /// ] + /// + /// We can see the nested structure and how instructions are represented as + /// segments. + /// + /// + /// Returns: + /// Code doesn't always behave intuitively. Some interesting functions + /// might modify the stack and thus change the behavior of common + /// instructions like CALL and RET. We try to identify these cases, and + /// the result is that the return edge from a segment might connect with a + /// function call very high the stack. For example, you might have + /// + /// main() + /// foo() + /// bar() + /// # here bar modifies the stack and pops foo() from it. Then it + /// finished the a RET (return) + /// main() # we came back directly to main() + /// + /// I have observed some trampolines doing this, as well as some std + /// functions (like ostream functions). So consumers should be aware of + /// this. + /// + /// There are all sorts of "abnormal" behaviors you can see in code, and + /// whenever we fail at identifying what's going on, we prefer to create a + /// new tree. + /// + /// Function call forest: + /// A single tree would suffice if a trace didn't contain errors nor + /// abnormal behaviors that made our algorithms fail. Sadly these + /// anomalies exist and we prefer not to use too many heuristics and + /// probably end up lying to the user. So we create a new tree from the + /// point we can't continue using the previous tree. This results in + /// having a forest instead of a single tree. This is probably the best we + /// can do if we consumers want to use this data to perform performance + /// analysis or reverse debugging. + /// + /// Non-functions: + /// Not everything in a program is a function. There are blocks of + /// instructions that are simply labeled or even regions without symbol + /// information that we don't what they are. We treat all of them as + /// functions for simplicity. + /// + /// Errors: + /// Whenever an error is found, a new tree with a single segment is + /// created. All consecutive errors after the original one are then + /// appended to this segment. As a note, something that GDB does is to use + /// some heuristics to merge trees that were interrupted by errors. We are + /// leaving that out of scope until a feature like that one is really + /// needed. + + /// Forward declaration + class FunctionCall; + using FunctionCallUP = std::unique_ptr<FunctionCall>; + + class FunctionCall { + public: + class TracedSegment { + public: + /// \param[in] cursor_sp + /// A cursor pointing to the beginning of the segment. + /// + /// \param[in] symbol_info + /// The symbol information of the first instruction of the segment. + /// + /// \param[in] call + /// The FunctionCall object that owns this segment. + TracedSegment(const lldb::TraceCursorSP &cursor_sp, + const SymbolInfo &symbol_info, FunctionCall &owning_call) + : m_first_insn_id(cursor_sp->GetId()), + m_last_insn_id(cursor_sp->GetId()), + m_first_symbol_info(symbol_info), m_last_symbol_info(symbol_info), + m_owning_call(owning_call) {} + + /// \return + /// The chronologically first instruction ID in this segment. + lldb::user_id_t GetFirstInstructionID() const; + /// \return + /// The chronologically last instruction ID in this segment. + lldb::user_id_t GetLastInstructionID() const; + + /// \return + /// The symbol information of the chronologically first instruction ID + /// in this segment. + const SymbolInfo &GetFirstInstructionSymbolInfo() const; + + /// \return + /// The symbol information of the chronologically last instruction ID in + /// this segment. + const SymbolInfo &GetLastInstructionSymbolInfo() const; + + /// \return + /// Get the call that owns this segment. + const FunctionCall &GetOwningCall() const; + + /// Append a new instruction to this segment. + /// + /// \param[in] cursor_sp + /// A cursor pointing to the new instruction. + /// + /// \param[in] symbol_info + /// The symbol information of the new instruction. + void AppendInsn(const lldb::TraceCursorSP &cursor_sp, + const SymbolInfo &symbol_info); + + /// Create a nested call at the end of this segment. + /// + /// \param[in] cursor_sp + /// A cursor pointing to the first instruction of the nested call. + /// + /// \param[in] symbol_info + /// The symbol information of the first instruction of the nested call. + FunctionCall &CreateNestedCall(const lldb::TraceCursorSP &cursor_sp, + const SymbolInfo &symbol_info); + + /// Executed the given callback if there's a nested call at the end of + /// this segment. + void IfNestedCall(std::function<void(const FunctionCall &function_call)> + callback) const; + + private: + TracedSegment(const TracedSegment &) = delete; + TracedSegment &operator=(TracedSegment const &); + + /// Delimiting instruction IDs taken chronologically. + /// \{ + lldb::user_id_t m_first_insn_id; + lldb::user_id_t m_last_insn_id; + /// \} + /// An optional nested call starting at the end of this segment. + FunctionCallUP m_nested_call; + /// The symbol information of the delimiting instructions + /// \{ + SymbolInfo m_first_symbol_info; + SymbolInfo m_last_symbol_info; + /// \} + FunctionCall &m_owning_call; + }; + + class UntracedPrefixSegment { + public: + /// Note: Untraced segments can only exist if have also seen a traced + /// segment of the same function call. Thus, we can use those traced + /// segments if we want symbol information and such. + + UntracedPrefixSegment(FunctionCallUP &&nested_call) + : m_nested_call(std::move(nested_call)) {} + + const FunctionCall &GetNestedCall() const; + + private: + UntracedPrefixSegment(const UntracedPrefixSegment &) = delete; + UntracedPrefixSegment &operator=(UntracedPrefixSegment const &); + FunctionCallUP m_nested_call; + }; + + /// Create a new function call given an instruction. This will also create a + /// segment for that instruction. + /// + /// \param[in] cursor_sp + /// A cursor pointing to the first instruction of that function call. + /// + /// \param[in] symbol_info + /// The symbol information of that first instruction. + FunctionCall(const lldb::TraceCursorSP &cursor_sp, + const SymbolInfo &symbol_info); + + /// Append a new traced segment to this funciton call. + /// + /// \param[in] cursor_sp + /// A cursor pointing to the first instruction of the new segment. + /// + /// \param[in] symbol_info + /// The symbol information of that first instruction. + void AppendSegment(const lldb::TraceCursorSP &cursor_sp, + const SymbolInfo &symbol_info); + + /// \return + /// The symbol info of some traced instruction of this call. + const SymbolInfo &GetSymbolInfo() const; + + /// \return + /// \b true if and only if the instructions in this function call are + /// trace errors, in which case this function call is a fake one. + bool IsError() const; + + /// \return + /// The list of traced segments of this call. + const std::deque<TracedSegment> &GetTracedSegments() const; + + /// \return + /// A non-const reference to the most-recent traced segment. + TracedSegment &GetLastTracedSegment(); + + /// Create an untraced segment for this call that jumps to the provided + /// nested call. + void SetUntracedPrefixSegment(FunctionCallUP &&nested_call); + + /// \return + /// A optional to the untraced prefix segment of this call. + const std::optional<UntracedPrefixSegment> & + GetUntracedPrefixSegment() const; + + /// \return + /// A pointer to the parent call. It may be \b nullptr. + FunctionCall *GetParentCall() const; + + void SetParentCall(FunctionCall &parent_call); + + private: + /// An optional untraced segment that precedes all the traced segments. + std::optional<UntracedPrefixSegment> m_untraced_prefix_segment; + /// The traced segments in order. We used a deque to prevent moving these + /// objects when appending to the list, which would happen with vector. + std::deque<TracedSegment> m_traced_segments; + /// The parent call, which might be null. Useful for reconstructing + /// callstacks. + FunctionCall *m_parent_call = nullptr; + /// Whether this call represents a list of consecutive errors. + bool m_is_error; }; /// Interface used to abstract away the format in which the instruction @@ -81,6 +383,10 @@ public: /// Dump a trace item (instruction, error or event). virtual void TraceItem(const TraceItem &item) = 0; + + /// Dump a function call forest. + virtual void + FunctionCallForest(const std::vector<FunctionCallUP> &forest) = 0; }; /// Create a instruction dumper for the cursor. @@ -93,7 +399,7 @@ public: /// /// \param[in] options /// Additional options for configuring the dumping. - TraceDumper(lldb::TraceCursorUP &&cursor_up, Stream &s, + TraceDumper(lldb::TraceCursorSP cursor_sp, Stream &s, const TraceDumperOptions &options); /// Dump \a count instructions of the thread trace starting at the current @@ -106,15 +412,18 @@ public: /// The number of instructions to print. /// /// \return - /// The instruction id of the last traversed instruction, or \b llvm::None - /// if no instructions were visited. - llvm::Optional<lldb::user_id_t> DumpInstructions(size_t count); + /// The instruction id of the last traversed instruction, or \b + /// std::nullopt if no instructions were visited. + std::optional<lldb::user_id_t> DumpInstructions(size_t count); + + /// Dump all function calls forwards chronologically and hierarchically + void DumpFunctionCalls(); private: /// Create a trace item for the current position without symbol information. TraceItem CreatRawTraceItem(); - lldb::TraceCursorUP m_cursor_up; + lldb::TraceCursorSP m_cursor_sp; TraceDumperOptions m_options; std::unique_ptr<OutputWriter> m_writer_up; }; diff --git a/contrib/llvm-project/lldb/include/lldb/Target/UnixSignals.h b/contrib/llvm-project/lldb/include/lldb/Target/UnixSignals.h index 34f4e30d1350..ff9f1ac9be19 100644 --- a/contrib/llvm-project/lldb/include/lldb/Target/UnixSignals.h +++ b/contrib/llvm-project/lldb/include/lldb/Target/UnixSignals.h @@ -10,12 +10,12 @@ #define LLDB_TARGET_UNIXSIGNALS_H #include <map> +#include <optional> #include <string> #include <vector> #include "lldb/Utility/ConstString.h" #include "lldb/lldb-private.h" -#include "llvm/ADT/Optional.h" #include "llvm/Support/JSON.h" namespace lldb_private { @@ -101,12 +101,12 @@ public: uint64_t GetVersion() const; // Returns a vector of signals that meet criteria provided in arguments. Each - // should_[suppress|stop|notify] flag can be None - no filtering by this - // flag true - only signals that have it set to true are returned false - + // should_[suppress|stop|notify] flag can be std::nullopt - no filtering by + // this flag true - only signals that have it set to true are returned false - // only signals that have it set to true are returned - std::vector<int32_t> GetFilteredSignals(llvm::Optional<bool> should_suppress, - llvm::Optional<bool> should_stop, - llvm::Optional<bool> should_notify); + std::vector<int32_t> GetFilteredSignals(std::optional<bool> should_suppress, + std::optional<bool> should_stop, + std::optional<bool> should_notify); protected: // Classes that inherit from UnixSignals can see and modify these diff --git a/contrib/llvm-project/lldb/include/lldb/Utility/AnsiTerminal.h b/contrib/llvm-project/lldb/include/lldb/Utility/AnsiTerminal.h index caad56671537..67795971d2ca 100644 --- a/contrib/llvm-project/lldb/include/lldb/Utility/AnsiTerminal.h +++ b/contrib/llvm-project/lldb/include/lldb/Utility/AnsiTerminal.h @@ -137,7 +137,7 @@ inline std::string FormatAnsiTerminalCodes(llvm::StringRef format, #undef _TO_STR2 }; // clang-format on - auto codes = llvm::makeArrayRef(g_color_tokens); + auto codes = llvm::ArrayRef(g_color_tokens); static const char tok_hdr[] = "${ansi."; diff --git a/contrib/llvm-project/lldb/include/lldb/Utility/ArchSpec.h b/contrib/llvm-project/lldb/include/lldb/Utility/ArchSpec.h index f67acedf11c2..371607175b1d 100644 --- a/contrib/llvm-project/lldb/include/lldb/Utility/ArchSpec.h +++ b/contrib/llvm-project/lldb/include/lldb/Utility/ArchSpec.h @@ -16,7 +16,6 @@ #include "lldb/lldb-private-enumerations.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Triple.h" -#include "llvm/Support/YAMLTraits.h" #include <cstddef> #include <cstdint> #include <string> @@ -109,6 +108,12 @@ public: eRISCVSubType_riscv64, }; + enum LoongArchSubType { + eLoongArchSubType_unknown, + eLoongArchSubType_loongarch32, + eLoongArchSubType_loongarch64, + }; + enum Core { eCore_arm_generic, eCore_arm_armv4, @@ -205,6 +210,9 @@ public: eCore_riscv32, eCore_riscv64, + eCore_loongarch32, + eCore_loongarch64, + eCore_uknownMach32, eCore_uknownMach64, @@ -488,19 +496,25 @@ public: /// architecture and false otherwise. bool CharIsSignedByDefault() const; - /// Compare an ArchSpec to another ArchSpec, requiring an exact cpu type - /// match between them. e.g. armv7s is not an exact match with armv7 - this - /// would return false + enum MatchType : bool { CompatibleMatch, ExactMatch }; + + /// Compare this ArchSpec to another ArchSpec. \a match specifies the kind of + /// matching that is to be done. CompatibleMatch requires only a compatible + /// cpu type (e.g., armv7s is compatible with armv7). ExactMatch requires an + /// exact match (armv7s is not an exact match with armv7). /// /// \return true if the two ArchSpecs match. - bool IsExactMatch(const ArchSpec &rhs) const; + bool IsMatch(const ArchSpec &rhs, MatchType match) const; - /// Compare an ArchSpec to another ArchSpec, requiring a compatible cpu type - /// match between them. e.g. armv7s is compatible with armv7 - this method - /// would return true - /// - /// \return true if the two ArchSpecs are compatible - bool IsCompatibleMatch(const ArchSpec &rhs) const; + /// Shorthand for IsMatch(rhs, ExactMatch). + bool IsExactMatch(const ArchSpec &rhs) const { + return IsMatch(rhs, ExactMatch); + } + + /// Shorthand for IsMatch(rhs, CompatibleMatch). + bool IsCompatibleMatch(const ArchSpec &rhs) const { + return IsMatch(rhs, CompatibleMatch); + } bool IsFullySpecifiedTriple() const; @@ -529,7 +543,6 @@ public: void SetFlags(const std::string &elf_abi); protected: - bool IsEqualTo(const ArchSpec &rhs, bool exact_match) const; void UpdateCore(); llvm::Triple m_triple; @@ -563,16 +576,4 @@ bool ParseMachCPUDashSubtypeTriple(llvm::StringRef triple_str, ArchSpec &arch); } // namespace lldb_private -namespace llvm { -namespace yaml { -template <> struct ScalarTraits<lldb_private::ArchSpec> { - static void output(const lldb_private::ArchSpec &, void *, raw_ostream &); - static StringRef input(StringRef, void *, lldb_private::ArchSpec &); - static QuotingType mustQuote(StringRef S) { return QuotingType::Double; } -}; -} // namespace yaml -} // namespace llvm - -LLVM_YAML_IS_SEQUENCE_VECTOR(lldb_private::ArchSpec) - #endif // LLDB_UTILITY_ARCHSPEC_H diff --git a/contrib/llvm-project/lldb/include/lldb/Utility/Args.h b/contrib/llvm-project/lldb/include/lldb/Utility/Args.h index cecf6b1502b5..40b9358484b6 100644 --- a/contrib/llvm-project/lldb/include/lldb/Utility/Args.h +++ b/contrib/llvm-project/lldb/include/lldb/Utility/Args.h @@ -35,11 +35,9 @@ public: struct ArgEntry { private: friend class Args; - friend struct llvm::yaml::MappingTraits<Args>; - friend struct llvm::yaml::MappingTraits<Args::ArgEntry>; std::unique_ptr<char[]> ptr; - char quote; + char quote = '\0'; char *data() { return ptr.get(); } @@ -169,7 +167,7 @@ public: /// have a nullptr const char * at the end, as the size of the list is /// embedded in the ArrayRef object. llvm::ArrayRef<const char *> GetArgumentArrayRef() const { - return llvm::makeArrayRef(m_argv).drop_back(); + return llvm::ArrayRef(m_argv).drop_back(); } /// Appends a new argument to the end of the list argument list. @@ -287,8 +285,6 @@ public: char quote_char); private: - friend struct llvm::yaml::MappingTraits<Args>; - std::vector<ArgEntry> m_entries; /// The arguments as C strings with a trailing nullptr element. /// @@ -383,28 +379,4 @@ private: } // namespace lldb_private -namespace llvm { -namespace yaml { -template <> struct MappingTraits<lldb_private::Args::ArgEntry> { - class NormalizedArgEntry { - public: - NormalizedArgEntry(IO &) {} - NormalizedArgEntry(IO &, lldb_private::Args::ArgEntry &entry) - : value(entry.ref()), quote(entry.quote) {} - lldb_private::Args::ArgEntry denormalize(IO &) { - return lldb_private::Args::ArgEntry(value, quote); - } - StringRef value; - uint8_t quote; - }; - static void mapping(IO &io, lldb_private::Args::ArgEntry &v); -}; -template <> struct MappingTraits<lldb_private::Args> { - static void mapping(IO &io, lldb_private::Args &v); -}; -} // namespace yaml -} // namespace llvm - -LLVM_YAML_IS_SEQUENCE_VECTOR(lldb_private::Args::ArgEntry) - #endif // LLDB_UTILITY_ARGS_H diff --git a/contrib/llvm-project/lldb/include/lldb/Utility/ConstString.h b/contrib/llvm-project/lldb/include/lldb/Utility/ConstString.h index 31887d7f6115..fe23303e14da 100644 --- a/contrib/llvm-project/lldb/include/lldb/Utility/ConstString.h +++ b/contrib/llvm-project/lldb/include/lldb/Utility/ConstString.h @@ -12,7 +12,6 @@ #include "llvm/ADT/DenseMapInfo.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/FormatVariadic.h" -#include "llvm/Support/YAMLTraits.h" #include <cstddef> @@ -450,20 +449,10 @@ template <> struct DenseMapInfo<lldb_private::ConstString> { }; /// \} -namespace yaml { -template <> struct ScalarTraits<lldb_private::ConstString> { - static void output(const lldb_private::ConstString &, void *, raw_ostream &); - static StringRef input(StringRef, void *, lldb_private::ConstString &); - static QuotingType mustQuote(StringRef S) { return QuotingType::Double; } -}; -} // namespace yaml - inline raw_ostream &operator<<(raw_ostream &os, lldb_private::ConstString s) { os << s.GetStringRef(); return os; } } // namespace llvm -LLVM_YAML_IS_SEQUENCE_VECTOR(lldb_private::ConstString) - #endif // LLDB_UTILITY_CONSTSTRING_H diff --git a/contrib/llvm-project/lldb/include/lldb/Utility/Diagnostics.h b/contrib/llvm-project/lldb/include/lldb/Utility/Diagnostics.h new file mode 100644 index 000000000000..5d23fa8ae234 --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/Utility/Diagnostics.h @@ -0,0 +1,70 @@ +//===-- Diagnostics.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_UTILITY_DIAGNOSTICS_H +#define LLDB_UTILITY_DIAGNOSTICS_H + +#include "lldb/Utility/FileSpec.h" +#include "lldb/Utility/Log.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringSet.h" +#include "llvm/Support/Error.h" + +#include <functional> +#include <mutex> +#include <optional> +#include <vector> + +namespace lldb_private { + +/// Diagnostics are a collection of files to help investigate bugs and +/// troubleshoot issues. Any part of the debugger can register itself with the +/// help of a callback to emit one or more files into the diagnostic directory. +class Diagnostics { +public: + Diagnostics(); + ~Diagnostics(); + + /// Gather diagnostics in the given directory. + llvm::Error Create(const FileSpec &dir); + + /// Gather diagnostics and print a message to the given output stream. + /// @{ + bool Dump(llvm::raw_ostream &stream); + bool Dump(llvm::raw_ostream &stream, const FileSpec &dir); + /// @} + + void Report(llvm::StringRef message); + + using Callback = std::function<llvm::Error(const FileSpec &)>; + + void AddCallback(Callback callback); + + static Diagnostics &Instance(); + + static bool Enabled(); + static void Initialize(); + static void Terminate(); + + /// Create a unique diagnostic directory. + static llvm::Expected<FileSpec> CreateUniqueDirectory(); + +private: + static std::optional<Diagnostics> &InstanceImpl(); + + llvm::Error DumpDiangosticsLog(const FileSpec &dir) const; + + RotatingLogHandler m_log_handler; + + llvm::SmallVector<Callback, 4> m_callbacks; + std::mutex m_callbacks_mutex; +}; + +} // namespace lldb_private + +#endif diff --git a/contrib/llvm-project/lldb/include/lldb/Utility/Event.h b/contrib/llvm-project/lldb/include/lldb/Utility/Event.h index f533fc5c47fa..8d2d94fe3fdb 100644 --- a/contrib/llvm-project/lldb/include/lldb/Utility/Event.h +++ b/contrib/llvm-project/lldb/include/lldb/Utility/Event.h @@ -112,7 +112,7 @@ public: ConstString GetFlavor() const override { return GetFlavorString(); } - bool WaitForEventReceived(const Timeout<std::micro> &timeout = llvm::None) { + bool WaitForEventReceived(const Timeout<std::micro> &timeout = std::nullopt) { return m_predicate.WaitForValueEqualTo(true, timeout); } diff --git a/contrib/llvm-project/lldb/include/lldb/Utility/FileSpec.h b/contrib/llvm-project/lldb/include/lldb/Utility/FileSpec.h index ec473a2afeec..e4d3d12979c2 100644 --- a/contrib/llvm-project/lldb/include/lldb/Utility/FileSpec.h +++ b/contrib/llvm-project/lldb/include/lldb/Utility/FileSpec.h @@ -10,6 +10,7 @@ #define LLDB_UTILITY_FILESPEC_H #include <functional> +#include <optional> #include <string> #include "lldb/Utility/ConstString.h" @@ -18,7 +19,6 @@ #include "llvm/Support/FileSystem.h" #include "llvm/Support/FormatVariadic.h" #include "llvm/Support/Path.h" -#include "llvm/Support/YAMLTraits.h" #include <cstddef> #include <cstdint> @@ -191,11 +191,11 @@ public: static bool Match(const FileSpec &pattern, const FileSpec &file); /// Attempt to guess path style for a given path string. It returns a style, - /// if it was able to make a reasonable guess, or None if it wasn't. The guess - /// will be correct if the input path was a valid absolute path on the system - /// which produced it. On other paths the result of this function is - /// unreliable (e.g. "c:\foo.txt" is a valid relative posix path). - static llvm::Optional<Style> GuessPathStyle(llvm::StringRef absolute_path); + /// if it was able to make a reasonable guess, or std::nullopt if it wasn't. + /// The guess will be correct if the input path was a valid absolute path on + /// the system which produced it. On other paths the result of this function + /// is unreliable (e.g. "c:\foo.txt" is a valid relative posix path). + static std::optional<Style> GuessPathStyle(llvm::StringRef absolute_path); /// Case sensitivity of path. /// @@ -216,29 +216,38 @@ public: Style GetPathStyle() const; - /// Directory string get accessor. - /// - /// \return - /// A reference to the directory string object. - ConstString &GetDirectory(); - /// Directory string const get accessor. /// /// \return /// A const reference to the directory string object. - ConstString GetDirectory() const; + const ConstString &GetDirectory() const { return m_directory; } - /// Filename string get accessor. + /// Directory string set accessor. /// - /// \return - /// A reference to the filename string object. - ConstString &GetFilename(); + /// \param[in] directory + /// The value to replace the directory with. + void SetDirectory(ConstString directory); + void SetDirectory(llvm::StringRef directory); + + /// Clear the directory in this object. + void ClearDirectory(); + /// Filename string const get accessor. /// /// \return /// A const reference to the filename string object. - ConstString GetFilename() const; + const ConstString &GetFilename() const { return m_filename; } + + /// Filename string set accessor. + /// + /// \param[in] filename + /// The const string to replace the directory with. + void SetFilename(ConstString filename); + void SetFilename(llvm::StringRef filename); + + /// Clear the filename in this object. + void ClearFilename(); /// Returns true if the filespec represents an implementation source file /// (files with a ".c", ".cpp", ".m", ".mm" (many more) extension). @@ -299,7 +308,13 @@ public: /// concatenated. std::string GetPath(bool denormalize = true) const; - const char *GetCString(bool denormalize = true) const; + /// Get the full path as a ConstString. + /// + /// This method should only be used when you need a ConstString or the + /// const char * from a ConstString to ensure permanent lifetime of C string. + /// Anyone needing the path temporarily should use the GetPath() method that + /// returns a std:string. + ConstString GetPathAsConstString(bool denormalize = true) const; /// Extract the full path to the file. /// @@ -396,23 +411,32 @@ public: ConstString GetLastPathComponent() const; protected: - friend struct llvm::yaml::MappingTraits<FileSpec>; - // Convenience method for setting the file without changing the style. void SetFile(llvm::StringRef path); + /// Called anytime m_directory or m_filename is changed to clear any cached + /// state in this object. + void PathWasModified() { + m_is_resolved = false; + m_absolute = Absolute::Calculate; + } + + enum class Absolute : uint8_t { + Calculate, + Yes, + No + }; + // Member variables ConstString m_directory; ///< The uniqued directory path ConstString m_filename; ///< The uniqued filename path mutable bool m_is_resolved = false; ///< True if this path has been resolved. + mutable Absolute m_absolute = Absolute::Calculate; ///< Cache absoluteness. Style m_style; ///< The syntax that this path uses (e.g. Windows / Posix) }; /// Dump a FileSpec object to a stream Stream &operator<<(Stream &s, const FileSpec &f); - -/// Prevent ODR violations with traits for llvm::sys::path::Style. -LLVM_YAML_STRONG_TYPEDEF(FileSpec::Style, FileSpecStyle) } // namespace lldb_private namespace llvm { @@ -440,15 +464,6 @@ template <> struct format_provider<lldb_private::FileSpec> { StringRef Style); }; -namespace yaml { -template <> struct ScalarEnumerationTraits<lldb_private::FileSpecStyle> { - static void enumeration(IO &io, lldb_private::FileSpecStyle &style); -}; - -template <> struct MappingTraits<lldb_private::FileSpec> { - static void mapping(IO &io, lldb_private::FileSpec &f); -}; -} // namespace yaml } // namespace llvm #endif // LLDB_UTILITY_FILESPEC_H diff --git a/contrib/llvm-project/lldb/include/lldb/Utility/GDBRemote.h b/contrib/llvm-project/lldb/include/lldb/Utility/GDBRemote.h index e39bce5144cf..ab700c00474a 100644 --- a/contrib/llvm-project/lldb/include/lldb/Utility/GDBRemote.h +++ b/contrib/llvm-project/lldb/include/lldb/Utility/GDBRemote.h @@ -10,11 +10,9 @@ #define LLDB_UTILITY_GDBREMOTE_H #include "lldb/Utility/FileSpec.h" -#include "lldb/Utility/ReproducerProvider.h" #include "lldb/Utility/StreamString.h" #include "lldb/lldb-enumerations.h" #include "lldb/lldb-public.h" -#include "llvm/Support/YAMLTraits.h" #include "llvm/Support/raw_ostream.h" #include <cstddef> @@ -47,12 +45,10 @@ public: int PutEscapedBytes(const void *s, size_t src_len); }; -/// GDB remote packet as used by the reproducer and the GDB remote -/// communication history. Packets can be serialized to file. +/// GDB remote packet as used by the GDB remote communication history. Packets +/// can be serialized to file. struct GDBRemotePacket { - friend llvm::yaml::MappingTraits<GDBRemotePacket>; - enum Type { ePacketTypeInvalid = 0, ePacketTypeSend, ePacketTypeRecv }; GDBRemotePacket() = default; @@ -81,76 +77,6 @@ private: llvm::StringRef GetTypeStr() const; }; -namespace repro { -class PacketRecorder : public AbstractRecorder { -public: - PacketRecorder(const FileSpec &filename, std::error_code &ec) - : AbstractRecorder(filename, ec) {} - - static llvm::Expected<std::unique_ptr<PacketRecorder>> - Create(const FileSpec &filename); - - void Record(const GDBRemotePacket &packet); -}; - -class GDBRemoteProvider : public repro::Provider<GDBRemoteProvider> { -public: - struct Info { - static const char *name; - static const char *file; - }; - - GDBRemoteProvider(const FileSpec &directory) : Provider(directory) {} - - llvm::raw_ostream *GetHistoryStream(); - PacketRecorder *GetNewPacketRecorder(); - - void SetCallback(std::function<void()> callback) { - m_callback = std::move(callback); - } - - void Keep() override; - void Discard() override; - - static char ID; - -private: - std::function<void()> m_callback; - std::unique_ptr<llvm::raw_fd_ostream> m_stream_up; - std::vector<std::unique_ptr<PacketRecorder>> m_packet_recorders; -}; - -} // namespace repro } // namespace lldb_private -LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(lldb_private::GDBRemotePacket) -LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(std::vector<lldb_private::GDBRemotePacket>) - -namespace llvm { -namespace yaml { - -template <> -struct ScalarEnumerationTraits<lldb_private::GDBRemotePacket::Type> { - static void enumeration(IO &io, lldb_private::GDBRemotePacket::Type &value); -}; - -template <> struct ScalarTraits<lldb_private::GDBRemotePacket::BinaryData> { - static void output(const lldb_private::GDBRemotePacket::BinaryData &, void *, - raw_ostream &); - - static StringRef input(StringRef, void *, - lldb_private::GDBRemotePacket::BinaryData &); - - static QuotingType mustQuote(StringRef S) { return QuotingType::None; } -}; - -template <> struct MappingTraits<lldb_private::GDBRemotePacket> { - static void mapping(IO &io, lldb_private::GDBRemotePacket &Packet); - - static StringRef validate(IO &io, lldb_private::GDBRemotePacket &); -}; - -} // namespace yaml -} // namespace llvm - #endif // LLDB_UTILITY_GDBREMOTE_H diff --git a/contrib/llvm-project/lldb/include/lldb/Utility/LLDBLog.h b/contrib/llvm-project/lldb/include/lldb/Utility/LLDBLog.h index 63dbb63f6f56..a440a72df9ea 100644 --- a/contrib/llvm-project/lldb/include/lldb/Utility/LLDBLog.h +++ b/contrib/llvm-project/lldb/include/lldb/Utility/LLDBLog.h @@ -48,7 +48,7 @@ enum class LLDBLog : Log::MaskType { Unwind = Log::ChannelFlag<29>, Watchpoints = Log::ChannelFlag<30>, OnDemand = Log::ChannelFlag<31>, - LLVM_MARK_AS_BITMASK_ENUM(Watchpoints), + LLVM_MARK_AS_BITMASK_ENUM(OnDemand), }; LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); diff --git a/contrib/llvm-project/lldb/include/lldb/Utility/Log.h b/contrib/llvm-project/lldb/include/lldb/Utility/Log.h index 404cbed14c18..596bec21b6f1 100644 --- a/contrib/llvm-project/lldb/include/lldb/Utility/Log.h +++ b/contrib/llvm-project/lldb/include/lldb/Utility/Log.h @@ -137,7 +137,7 @@ public: llvm::StringLiteral description, Cat mask) : name(name), description(description), flag(MaskType(mask)) { static_assert( - std::is_same<Log::MaskType, std::underlying_type_t<Cat>>::value, ""); + std::is_same<Log::MaskType, std::underlying_type_t<Cat>>::value); } }; @@ -157,7 +157,7 @@ public: : log_ptr(nullptr), categories(categories), default_flags(MaskType(default_flags)) { static_assert( - std::is_same<Log::MaskType, std::underlying_type_t<Cat>>::value, ""); + std::is_same<Log::MaskType, std::underlying_type_t<Cat>>::value); } // This function is safe to call at any time. If the channel is disabled @@ -166,7 +166,7 @@ public: // output will be discarded. Log *GetLog(MaskType mask) { Log *log = log_ptr.load(std::memory_order_relaxed); - if (log && log->GetMask().AnySet(mask)) + if (log && ((log->GetMask() & mask) != 0)) return log; return nullptr; } @@ -243,7 +243,7 @@ public: const Flags GetOptions() const; - const Flags GetMask() const; + MaskType GetMask() const; bool GetVerbose() const; @@ -276,9 +276,9 @@ private: } void Enable(const std::shared_ptr<LogHandler> &handler_sp, uint32_t options, - uint32_t flags); + MaskType flags); - void Disable(uint32_t flags); + void Disable(MaskType flags); bool Dump(llvm::raw_ostream &stream); @@ -291,8 +291,9 @@ private: static void ListCategories(llvm::raw_ostream &stream, const ChannelMap::value_type &entry); - static uint32_t GetFlags(llvm::raw_ostream &stream, const ChannelMap::value_type &entry, - llvm::ArrayRef<const char *> categories); + static Log::MaskType GetFlags(llvm::raw_ostream &stream, + const ChannelMap::value_type &entry, + llvm::ArrayRef<const char *> categories); Log(const Log &) = delete; void operator=(const Log &) = delete; @@ -306,8 +307,8 @@ template <typename Cat> Log::Channel &LogChannelFor() = delete; /// Returns a valid Log object if any of the provided categories are enabled. /// Otherwise, returns nullptr. template <typename Cat> Log *GetLog(Cat mask) { - static_assert(std::is_same<Log::MaskType, std::underlying_type_t<Cat>>::value, - ""); + static_assert( + std::is_same<Log::MaskType, std::underlying_type_t<Cat>>::value); return LogChannelFor<Cat>().GetLog(Log::MaskType(mask)); } diff --git a/contrib/llvm-project/lldb/include/lldb/Utility/Predicate.h b/contrib/llvm-project/lldb/include/lldb/Utility/Predicate.h index e5d80acb11bc..3338d08ca520 100644 --- a/contrib/llvm-project/lldb/include/lldb/Utility/Predicate.h +++ b/contrib/llvm-project/lldb/include/lldb/Utility/Predicate.h @@ -14,6 +14,7 @@ #include <condition_variable> #include <mutex> +#include <optional> #include "lldb/Utility/Timeout.h" #include "lldb/lldb-defines.h" @@ -116,9 +117,10 @@ public: /// How long to wait for the condition to hold. /// /// \return - /// m_value if Cond(m_value) is true, None otherwise (timeout occurred). + /// m_value if Cond(m_value) is true, std::nullopt otherwise (timeout + /// occurred). template <typename C> - llvm::Optional<T> WaitFor(C Cond, const Timeout<std::micro> &timeout) { + std::optional<T> WaitFor(C Cond, const Timeout<std::micro> &timeout) { std::unique_lock<std::mutex> lock(m_mutex); auto RealCond = [&] { return Cond(m_value); }; if (!timeout) { @@ -127,7 +129,7 @@ public: } if (m_condition.wait_for(lock, *timeout, RealCond)) return m_value; - return llvm::None; + return std::nullopt; } /// Wait for \a m_value to be equal to \a value. /// @@ -152,9 +154,9 @@ public: /// true if the \a m_value is equal to \a value, false otherwise (timeout /// occurred). bool WaitForValueEqualTo(T value, - const Timeout<std::micro> &timeout = llvm::None) { + const Timeout<std::micro> &timeout = std::nullopt) { return WaitFor([&value](T current) { return value == current; }, timeout) != - llvm::None; + std::nullopt; } /// Wait for \a m_value to not be equal to \a value. @@ -177,10 +179,11 @@ public: /// How long to wait for the condition to hold. /// /// \return - /// m_value if m_value != value, None otherwise (timeout occurred). - llvm::Optional<T> + /// m_value if m_value != value, std::nullopt otherwise (timeout + /// occurred). + std::optional<T> WaitForValueNotEqualTo(T value, - const Timeout<std::micro> &timeout = llvm::None) { + const Timeout<std::micro> &timeout = std::nullopt) { return WaitFor([&value](T current) { return value != current; }, timeout); } diff --git a/contrib/llvm-project/lldb/include/lldb/Utility/ProcessInfo.h b/contrib/llvm-project/lldb/include/lldb/Utility/ProcessInfo.h index 42a851f034ed..cf07418bf1c3 100644 --- a/contrib/llvm-project/lldb/include/lldb/Utility/ProcessInfo.h +++ b/contrib/llvm-project/lldb/include/lldb/Utility/ProcessInfo.h @@ -14,7 +14,6 @@ #include "lldb/Utility/Environment.h" #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/NameMatches.h" -#include "llvm/Support/YAMLTraits.h" #include <vector> namespace lldb_private { @@ -88,7 +87,6 @@ public: const Environment &GetEnvironment() const { return m_environment; } protected: - template <class T> friend struct llvm::yaml::MappingTraits; FileSpec m_executable; std::string m_arg0; // argv[0] if supported. If empty, then use m_executable. // Not all process plug-ins support specifying an argv[0] that differs from @@ -148,7 +146,6 @@ public: bool verbose) const; protected: - friend struct llvm::yaml::MappingTraits<ProcessInstanceInfo>; uint32_t m_euid = UINT32_MAX; uint32_t m_egid = UINT32_MAX; lldb::pid_t m_parent_pid = LLDB_INVALID_PROCESS_ID; @@ -210,19 +207,6 @@ protected: bool m_match_all_users = false; }; -namespace repro { -llvm::Optional<ProcessInstanceInfoList> GetReplayProcessInstanceInfoList(); -} // namespace repro } // namespace lldb_private -LLVM_YAML_IS_SEQUENCE_VECTOR(lldb_private::ProcessInstanceInfo) - -namespace llvm { -namespace yaml { -template <> struct MappingTraits<lldb_private::ProcessInstanceInfo> { - static void mapping(IO &io, lldb_private::ProcessInstanceInfo &PII); -}; -} // namespace yaml -} // namespace llvm - #endif // LLDB_UTILITY_PROCESSINFO_H diff --git a/contrib/llvm-project/lldb/include/lldb/Utility/RangeMap.h b/contrib/llvm-project/lldb/include/lldb/Utility/RangeMap.h index 257b177c7092..49b7eebfea6f 100644 --- a/contrib/llvm-project/lldb/include/lldb/Utility/RangeMap.h +++ b/contrib/llvm-project/lldb/include/lldb/Utility/RangeMap.h @@ -49,6 +49,11 @@ template <typename B, typename S> struct Range { void Slide(BaseType slide) { base += slide; } + void ShrinkFront(S s) { + base += s; + size -= std::min(s, size); + } + bool Union(const Range &rhs) { if (DoesAdjoinOrIntersect(rhs)) { auto new_end = std::max<BaseType>(GetRangeEnd(), rhs.GetRangeEnd()); @@ -445,6 +450,13 @@ public: void Append(const Entry &entry) { m_entries.emplace_back(entry); } + bool Erase(uint32_t start, uint32_t end) { + if (start >= end || end > m_entries.size()) + return false; + m_entries.erase(begin() + start, begin() + end); + return true; + } + void Sort() { if (m_entries.size() > 1) std::stable_sort(m_entries.begin(), m_entries.end(), @@ -606,11 +618,10 @@ public: if (!m_entries.empty()) { typename Collection::const_iterator begin = m_entries.begin(); typename Collection::const_iterator end = m_entries.end(); - typename Collection::const_iterator pos = - std::lower_bound(m_entries.begin(), end, addr, - [](const Entry &lhs, B rhs_base) -> bool { - return lhs.GetRangeEnd() <= rhs_base; - }); + typename Collection::const_iterator pos = llvm::lower_bound( + m_entries, addr, [](const Entry &lhs, B rhs_base) -> bool { + return lhs.GetRangeEnd() <= rhs_base; + }); while (pos != begin && pos[-1].Contains(addr)) --pos; @@ -621,6 +632,17 @@ public: return nullptr; } + uint32_t FindEntryIndexThatContainsOrFollows(B addr) const { +#ifdef ASSERT_RANGEMAP_ARE_SORTED + assert(IsSorted()); +#endif + const AugmentedEntry *entry = static_cast<const AugmentedEntry *>( + FindEntryThatContainsOrFollows(addr)); + if (entry) + return std::distance(m_entries.begin(), entry); + return UINT32_MAX; + } + Entry *Back() { return (m_entries.empty() ? nullptr : &m_entries.back()); } const Entry *Back() const { @@ -771,7 +793,7 @@ public: typename Collection::iterator begin = m_entries.begin(); typename Collection::iterator end = m_entries.end(); typename Collection::iterator pos = - std::lower_bound(begin, end, entry, BaseLessThan); + llvm::lower_bound(m_entries, entry, BaseLessThan); while (pos != begin && pos[-1].addr == addr) --pos; diff --git a/contrib/llvm-project/lldb/include/lldb/Utility/RegisterValue.h b/contrib/llvm-project/lldb/include/lldb/Utility/RegisterValue.h index 1ece4f0eb79f..ff3dc9b3dda4 100644 --- a/contrib/llvm-project/lldb/include/lldb/Utility/RegisterValue.h +++ b/contrib/llvm-project/lldb/include/lldb/Utility/RegisterValue.h @@ -84,7 +84,7 @@ public: void SetType(RegisterValue::Type type) { m_type = type; } - RegisterValue::Type SetType(const RegisterInfo *reg_info); + RegisterValue::Type SetType(const RegisterInfo ®_info); bool GetData(DataExtractor &data) const; @@ -95,11 +95,11 @@ public: // value, or pad the destination with zeroes if the register byte size is // shorter that "dst_len" (all while correctly abiding the "dst_byte_order"). // Returns the number of bytes copied into "dst". - uint32_t GetAsMemoryData(const RegisterInfo *reg_info, void *dst, + uint32_t GetAsMemoryData(const RegisterInfo ®_info, void *dst, uint32_t dst_len, lldb::ByteOrder dst_byte_order, Status &error) const; - uint32_t SetFromMemoryData(const RegisterInfo *reg_info, const void *src, + uint32_t SetFromMemoryData(const RegisterInfo ®_info, const void *src, uint32_t src_len, lldb::ByteOrder src_byte_order, Status &error); @@ -238,7 +238,7 @@ public: Status SetValueFromString(const RegisterInfo *reg_info, const char *value_str) = delete; - Status SetValueFromData(const RegisterInfo *reg_info, DataExtractor &data, + Status SetValueFromData(const RegisterInfo ®_info, DataExtractor &data, lldb::offset_t offset, bool partial_data_ok); const void *GetBytes() const; @@ -263,8 +263,8 @@ protected: mutable uint8_t bytes[kMaxRegisterByteSize]; // This must be big enough to hold any // register for any supported target. - uint16_t length; - lldb::ByteOrder byte_order; + uint16_t length = 0; + lldb::ByteOrder byte_order = lldb::eByteOrderInvalid; } buffer; }; diff --git a/contrib/llvm-project/lldb/include/lldb/Utility/Reproducer.h b/contrib/llvm-project/lldb/include/lldb/Utility/Reproducer.h deleted file mode 100644 index e81abad2ec32..000000000000 --- a/contrib/llvm-project/lldb/include/lldb/Utility/Reproducer.h +++ /dev/null @@ -1,231 +0,0 @@ -//===-- Reproducer.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_UTILITY_REPRODUCER_H -#define LLDB_UTILITY_REPRODUCER_H - -#include "lldb/Utility/FileSpec.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/Support/Error.h" -#include "llvm/Support/VirtualFileSystem.h" -#include "llvm/Support/YAMLTraits.h" - -#include <mutex> -#include <string> -#include <utility> -#include <vector> - -namespace lldb_private { -class UUID; -namespace repro { - -class Reproducer; - -enum class ReproducerMode { - Capture, - Off, -}; - -/// The provider defines an interface for generating files needed for -/// reproducing. -/// -/// Different components will implement different providers. -class ProviderBase { -public: - virtual ~ProviderBase() = default; - - const FileSpec &GetRoot() const { return m_root; } - - /// The Keep method is called when it is decided that we need to keep the - /// data in order to provide a reproducer. - virtual void Keep(){}; - - /// The Discard method is called when it is decided that we do not need to - /// keep any information and will not generate a reproducer. - virtual void Discard(){}; - - // Returns the class ID for this type. - static const void *ClassID() { return &ID; } - - // Returns the class ID for the dynamic type of this Provider instance. - virtual const void *DynamicClassID() const = 0; - - virtual llvm::StringRef GetName() const = 0; - virtual llvm::StringRef GetFile() const = 0; - -protected: - ProviderBase(const FileSpec &root) : m_root(root) {} - -private: - /// Every provider knows where to dump its potential files. - FileSpec m_root; - - virtual void anchor(); - static char ID; -}; - -template <typename ThisProviderT> class Provider : public ProviderBase { -public: - static const void *ClassID() { return &ThisProviderT::ID; } - - const void *DynamicClassID() const override { return &ThisProviderT::ID; } - - llvm::StringRef GetName() const override { return ThisProviderT::Info::name; } - llvm::StringRef GetFile() const override { return ThisProviderT::Info::file; } - -protected: - using ProviderBase::ProviderBase; // Inherit constructor. -}; - -/// The generator is responsible for the logic needed to generate a -/// reproducer. For doing so it relies on providers, who serialize data that -/// is necessary for reproducing a failure. -class Generator final { - -public: - Generator(FileSpec root); - ~Generator(); - - /// Method to indicate we want to keep the reproducer. If reproducer - /// generation is disabled, this does nothing. - void Keep(); - - /// Method to indicate we do not want to keep the reproducer. This is - /// unaffected by whether or not generation reproduction is enabled, as we - /// might need to clean up files already written to disk. - void Discard(); - - /// Enable or disable auto generate. - void SetAutoGenerate(bool b); - - /// Return whether auto generate is enabled. - bool IsAutoGenerate() const; - - /// Create and register a new provider. - template <typename T> T *Create() { - std::unique_ptr<ProviderBase> provider = std::make_unique<T>(m_root); - return static_cast<T *>(Register(std::move(provider))); - } - - /// Get an existing provider. - template <typename T> T *Get() { - auto it = m_providers.find(T::ClassID()); - if (it == m_providers.end()) - return nullptr; - return static_cast<T *>(it->second.get()); - } - - /// Get a provider if it exists, otherwise create it. - template <typename T> T &GetOrCreate() { - auto *provider = Get<T>(); - if (provider) - return *provider; - return *Create<T>(); - } - - const FileSpec &GetRoot() const; - -private: - friend Reproducer; - - ProviderBase *Register(std::unique_ptr<ProviderBase> provider); - - /// Builds and index with provider info. - void AddProvidersToIndex(); - - /// Map of provider IDs to provider instances. - llvm::DenseMap<const void *, std::unique_ptr<ProviderBase>> m_providers; - std::mutex m_providers_mutex; - - /// The reproducer root directory. - FileSpec m_root; - - /// Flag to ensure that we never call both keep and discard. - bool m_done = false; - - /// Flag to auto generate a reproducer when it would otherwise be discarded. - bool m_auto_generate = false; -}; - -class Loader final { -public: - Loader(FileSpec root, bool passive = false); - - template <typename T> FileSpec GetFile() { - if (!HasFile(T::file)) - return {}; - - return GetRoot().CopyByAppendingPathComponent(T::file); - } - - template <typename T> llvm::Expected<std::string> LoadBuffer() { - FileSpec file = GetFile<typename T::Info>(); - llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> buffer = - llvm::vfs::getRealFileSystem()->getBufferForFile(file.GetPath()); - if (!buffer) - return llvm::errorCodeToError(buffer.getError()); - return (*buffer)->getBuffer().str(); - } - - llvm::Error LoadIndex(); - - const FileSpec &GetRoot() const { return m_root; } - -private: - bool HasFile(llvm::StringRef file); - - FileSpec m_root; - std::vector<std::string> m_files; - bool m_loaded; -}; - -/// The reproducer enables clients to obtain access to the Generator and -/// Loader. -class Reproducer { -public: - static Reproducer &Instance(); - static llvm::Error Initialize(ReproducerMode mode, - llvm::Optional<FileSpec> root); - static void Initialize(); - static bool Initialized(); - static void Terminate(); - - Reproducer() = default; - - Generator *GetGenerator(); - Loader *GetLoader(); - - const Generator *GetGenerator() const; - const Loader *GetLoader() const; - - FileSpec GetReproducerPath() const; - - bool IsCapturing() { return static_cast<bool>(m_generator); }; - -protected: - llvm::Error SetCapture(llvm::Optional<FileSpec> root); - -private: - static llvm::Optional<Reproducer> &InstanceImpl(); - - llvm::Optional<Generator> m_generator; - llvm::Optional<Loader> m_loader; - - mutable std::mutex m_mutex; -}; - -struct ReplayOptions { - bool verify = true; - bool check_version = true; -}; - -} // namespace repro -} // namespace lldb_private - -#endif // LLDB_UTILITY_REPRODUCER_H diff --git a/contrib/llvm-project/lldb/include/lldb/Utility/ReproducerProvider.h b/contrib/llvm-project/lldb/include/lldb/Utility/ReproducerProvider.h deleted file mode 100644 index 72ddf64f7ebc..000000000000 --- a/contrib/llvm-project/lldb/include/lldb/Utility/ReproducerProvider.h +++ /dev/null @@ -1,416 +0,0 @@ -//===-- Reproducer.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_UTILITY_REPRODUCER_PROVIDER_H -#define LLDB_UTILITY_REPRODUCER_PROVIDER_H - -#include "lldb/Utility/FileSpec.h" -#include "lldb/Utility/ProcessInfo.h" -#include "lldb/Utility/Reproducer.h" -#include "lldb/Utility/UUID.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/Support/Error.h" -#include "llvm/Support/FileCollector.h" -#include "llvm/Support/YAMLTraits.h" - -#include <string> -#include <utility> -#include <vector> - -namespace lldb_private { -namespace repro { - -/// The recorder is a small object handed out by a provider to record data. It -/// is commonly used in combination with a MultiProvider which is meant to -/// record information for multiple instances of the same source of data. -class AbstractRecorder { -protected: - AbstractRecorder(const FileSpec &filename, std::error_code &ec) - : m_filename(filename.GetFilename().GetStringRef()), - m_os(filename.GetPath(), ec, llvm::sys::fs::OF_TextWithCRLF), - m_record(true) {} - -public: - const FileSpec &GetFilename() { return m_filename; } - - void Stop() { - assert(m_record); - m_record = false; - } - -private: - FileSpec m_filename; - -protected: - llvm::raw_fd_ostream m_os; - bool m_record; -}; - -/// Recorder that records its data as text to a file. -class DataRecorder : public AbstractRecorder { -public: - DataRecorder(const FileSpec &filename, std::error_code &ec) - : AbstractRecorder(filename, ec) {} - - static llvm::Expected<std::unique_ptr<DataRecorder>> - Create(const FileSpec &filename); - - template <typename T> void Record(const T &t, bool newline = false) { - if (!m_record) - return; - m_os << t; - if (newline) - m_os << '\n'; - m_os.flush(); - } -}; - -/// Recorder that records its data as YAML to a file. -class YamlRecorder : public AbstractRecorder { -public: - YamlRecorder(const FileSpec &filename, std::error_code &ec) - : AbstractRecorder(filename, ec) {} - - static llvm::Expected<std::unique_ptr<YamlRecorder>> - Create(const FileSpec &filename); - - template <typename T> void Record(const T &t) { - if (!m_record) - return; - llvm::yaml::Output yout(m_os); - // The YAML traits are defined as non-const because they are used for - // serialization and deserialization. The cast is safe because - // serialization doesn't modify the object. - yout << const_cast<T &>(t); - m_os.flush(); - } -}; - -class FileProvider : public Provider<FileProvider> { -public: - struct Info { - static const char *name; - static const char *file; - }; - - FileProvider(const FileSpec &directory) : Provider(directory) { - m_collector = std::make_shared<llvm::FileCollector>( - directory.CopyByAppendingPathComponent("root").GetPath(), - directory.GetPath()); - } - - std::shared_ptr<llvm::FileCollector> GetFileCollector() { - return m_collector; - } - - void Keep() override; - - void RecordInterestingDirectory(const llvm::Twine &dir); - void RecordInterestingDirectoryRecursive(const llvm::Twine &dir); - - static char ID; - -private: - std::shared_ptr<llvm::FileCollector> m_collector; -}; - -/// Provider for the LLDB version number. -/// -/// When the reproducer is kept, it writes the lldb version to a file named -/// version.txt in the reproducer root. -class VersionProvider : public Provider<VersionProvider> { -public: - VersionProvider(const FileSpec &directory) : Provider(directory) {} - struct Info { - static const char *name; - static const char *file; - }; - void SetVersion(std::string version) { - assert(m_version.empty()); - m_version = std::move(version); - } - void Keep() override; - std::string m_version; - static char ID; -}; - -/// Abstract provider to storing directory paths. -template <typename T> class DirectoryProvider : public repro::Provider<T> { -public: - DirectoryProvider(const FileSpec &root) : Provider<T>(root) {} - void SetDirectory(std::string directory) { - m_directory = std::move(directory); - } - llvm::StringRef GetDirectory() { return m_directory; } - - void Keep() override { - FileSpec file = this->GetRoot().CopyByAppendingPathComponent(T::Info::file); - std::error_code ec; - llvm::raw_fd_ostream os(file.GetPath(), ec, llvm::sys::fs::OF_TextWithCRLF); - if (ec) - return; - os << m_directory << "\n"; - } - -protected: - std::string m_directory; -}; - -/// Provider for the current working directory. -/// -/// When the reproducer is kept, it writes lldb's current working directory to -/// a file named cwd.txt in the reproducer root. -class WorkingDirectoryProvider - : public DirectoryProvider<WorkingDirectoryProvider> { -public: - WorkingDirectoryProvider(const FileSpec &directory) - : DirectoryProvider(directory) { - llvm::SmallString<128> cwd; - if (std::error_code EC = llvm::sys::fs::current_path(cwd)) - return; - SetDirectory(std::string(cwd)); - } - struct Info { - static const char *name; - static const char *file; - }; - static char ID; -}; - -/// Provider for the home directory. -/// -/// When the reproducer is kept, it writes the user's home directory to a file -/// a file named home.txt in the reproducer root. -class HomeDirectoryProvider : public DirectoryProvider<HomeDirectoryProvider> { -public: - HomeDirectoryProvider(const FileSpec &directory) - : DirectoryProvider(directory) { - llvm::SmallString<128> home_dir; - llvm::sys::path::home_directory(home_dir); - SetDirectory(std::string(home_dir)); - } - struct Info { - static const char *name; - static const char *file; - }; - static char ID; -}; - -/// Provider for mapping UUIDs to symbol and executable files. -class SymbolFileProvider : public Provider<SymbolFileProvider> { -public: - SymbolFileProvider(const FileSpec &directory) : Provider(directory) {} - - void AddSymbolFile(const UUID *uuid, const FileSpec &module_path, - const FileSpec &symbol_path); - void Keep() override; - - struct Entry { - Entry() = default; - Entry(std::string uuid) : uuid(std::move(uuid)) {} - Entry(std::string uuid, std::string module_path, std::string symbol_path) - : uuid(std::move(uuid)), module_path(std::move(module_path)), - symbol_path(std::move(symbol_path)) {} - - bool operator==(const Entry &rhs) const { return uuid == rhs.uuid; } - bool operator<(const Entry &rhs) const { return uuid < rhs.uuid; } - - std::string uuid; - std::string module_path; - std::string symbol_path; - }; - - struct Info { - static const char *name; - static const char *file; - }; - static char ID; - -private: - std::vector<Entry> m_symbol_files; -}; - -/// The MultiProvider is a provider that hands out recorder which can be used -/// to capture data for different instances of the same object. The recorders -/// can be passed around or stored as an instance member. -/// -/// The Info::file for the MultiProvider contains an index of files for every -/// recorder. Use the MultiLoader to read the index and get the individual -/// files. -template <typename T, typename V> -class MultiProvider : public repro::Provider<V> { -public: - MultiProvider(const FileSpec &directory) : Provider<V>(directory) {} - - T *GetNewRecorder() { - std::size_t i = m_recorders.size() + 1; - std::string filename = (llvm::Twine(V::Info::name) + llvm::Twine("-") + - llvm::Twine(i) + llvm::Twine(".yaml")) - .str(); - auto recorder_or_error = - T::Create(this->GetRoot().CopyByAppendingPathComponent(filename)); - if (!recorder_or_error) { - llvm::consumeError(recorder_or_error.takeError()); - return nullptr; - } - - m_recorders.push_back(std::move(*recorder_or_error)); - return m_recorders.back().get(); - } - - void Keep() override { - std::vector<std::string> files; - for (auto &recorder : m_recorders) { - recorder->Stop(); - files.push_back(recorder->GetFilename().GetPath()); - } - - FileSpec file = this->GetRoot().CopyByAppendingPathComponent(V::Info::file); - std::error_code ec; - llvm::raw_fd_ostream os(file.GetPath(), ec, llvm::sys::fs::OF_TextWithCRLF); - if (ec) - return; - llvm::yaml::Output yout(os); - yout << files; - } - - void Discard() override { m_recorders.clear(); } - -private: - std::vector<std::unique_ptr<T>> m_recorders; -}; - -class CommandProvider : public MultiProvider<DataRecorder, CommandProvider> { -public: - struct Info { - static const char *name; - static const char *file; - }; - - CommandProvider(const FileSpec &directory) - : MultiProvider<DataRecorder, CommandProvider>(directory) {} - - static char ID; -}; - -class ProcessInfoRecorder : public AbstractRecorder { -public: - ProcessInfoRecorder(const FileSpec &filename, std::error_code &ec) - : AbstractRecorder(filename, ec) {} - - static llvm::Expected<std::unique_ptr<ProcessInfoRecorder>> - Create(const FileSpec &filename); - - void Record(const ProcessInstanceInfoList &process_infos); -}; - -class ProcessInfoProvider : public repro::Provider<ProcessInfoProvider> { -public: - struct Info { - static const char *name; - static const char *file; - }; - - ProcessInfoProvider(const FileSpec &directory) : Provider(directory) {} - - ProcessInfoRecorder *GetNewProcessInfoRecorder(); - - void Keep() override; - void Discard() override; - - static char ID; - -private: - std::unique_ptr<llvm::raw_fd_ostream> m_stream_up; - std::vector<std::unique_ptr<ProcessInfoRecorder>> m_process_info_recorders; -}; - -/// Loader for data captured with the MultiProvider. It will read the index and -/// return the path to the files in the index. -template <typename T> class MultiLoader { -public: - MultiLoader(std::vector<std::string> files) : m_files(std::move(files)) {} - - static std::unique_ptr<MultiLoader> Create(Loader *loader) { - if (!loader) - return {}; - - FileSpec file = loader->GetFile<typename T::Info>(); - if (!file) - return {}; - - auto error_or_file = llvm::MemoryBuffer::getFile(file.GetPath()); - if (auto err = error_or_file.getError()) - return {}; - - std::vector<std::string> files; - llvm::yaml::Input yin((*error_or_file)->getBuffer()); - yin >> files; - - if (auto err = yin.error()) - return {}; - - for (auto &file : files) { - FileSpec absolute_path = - loader->GetRoot().CopyByAppendingPathComponent(file); - file = absolute_path.GetPath(); - } - - return std::make_unique<MultiLoader<T>>(std::move(files)); - } - - llvm::Optional<std::string> GetNextFile() { - if (m_index >= m_files.size()) - return {}; - return m_files[m_index++]; - } - -private: - std::vector<std::string> m_files; - unsigned m_index = 0; -}; - -class SymbolFileLoader { -public: - SymbolFileLoader(Loader *loader); - std::pair<FileSpec, FileSpec> GetPaths(const UUID *uuid) const; - -private: - // Sorted list of UUID to path mappings. - std::vector<SymbolFileProvider::Entry> m_symbol_files; -}; - -/// Helper to read directories written by the DirectoryProvider. -template <typename T> -llvm::Expected<std::string> GetDirectoryFrom(repro::Loader *loader) { - llvm::Expected<std::string> dir = loader->LoadBuffer<T>(); - if (!dir) - return dir.takeError(); - return std::string(llvm::StringRef(*dir).rtrim()); -} - -} // namespace repro -} // namespace lldb_private - -LLVM_YAML_IS_SEQUENCE_VECTOR(lldb_private::repro::SymbolFileProvider::Entry) - -namespace llvm { -namespace yaml { -template <> -struct MappingTraits<lldb_private::repro::SymbolFileProvider::Entry> { - static void mapping(IO &io, - lldb_private::repro::SymbolFileProvider::Entry &entry) { - io.mapRequired("uuid", entry.uuid); - io.mapRequired("module-path", entry.module_path); - io.mapRequired("symbol-path", entry.symbol_path); - } -}; -} // namespace yaml -} // namespace llvm - -#endif // LLDB_UTILITY_REPRODUCER_PROVIDER_H diff --git a/contrib/llvm-project/lldb/include/lldb/Utility/Scalar.h b/contrib/llvm-project/lldb/include/lldb/Utility/Scalar.h index 2801b1bd6326..34c2111ae0ac 100644 --- a/contrib/llvm-project/lldb/include/lldb/Utility/Scalar.h +++ b/contrib/llvm-project/lldb/include/lldb/Utility/Scalar.h @@ -34,7 +34,7 @@ class Stream; class Scalar { template<typename T> static llvm::APSInt MakeAPSInt(T v) { - static_assert(std::is_integral<T>::value, ""); + static_assert(std::is_integral<T>::value); static_assert(sizeof(T) <= sizeof(uint64_t), "Conversion loses precision!"); return llvm::APSInt( llvm::APInt(sizeof(T) * 8, uint64_t(v), std::is_signed<T>::value), diff --git a/contrib/llvm-project/lldb/include/lldb/Utility/SelectHelper.h b/contrib/llvm-project/lldb/include/lldb/Utility/SelectHelper.h index 63f1fe6421cf..ea46c33c396f 100644 --- a/contrib/llvm-project/lldb/include/lldb/Utility/SelectHelper.h +++ b/contrib/llvm-project/lldb/include/lldb/Utility/SelectHelper.h @@ -13,9 +13,9 @@ #include "lldb/lldb-types.h" #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/Optional.h" #include <chrono> +#include <optional> class SelectHelper { public: @@ -65,7 +65,7 @@ protected: write_is_set : 1, error_is_set : 1; }; llvm::DenseMap<lldb::socket_t, FDInfo> m_fd_map; - llvm::Optional<std::chrono::steady_clock::time_point> m_end_time; + std::optional<std::chrono::steady_clock::time_point> m_end_time; }; #endif // LLDB_UTILITY_SELECTHELPER_H diff --git a/contrib/llvm-project/lldb/include/lldb/Utility/SharedCluster.h b/contrib/llvm-project/lldb/include/lldb/Utility/SharedCluster.h index b3f41dbaa64b..2992e6c9beec 100644 --- a/contrib/llvm-project/lldb/include/lldb/Utility/SharedCluster.h +++ b/contrib/llvm-project/lldb/include/lldb/Utility/SharedCluster.h @@ -11,7 +11,7 @@ #include "lldb/Utility/LLDBAssert.h" #include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/SmallPtrSet.h" #include <memory> #include <mutex> @@ -32,15 +32,16 @@ public: void ManageObject(T *new_object) { std::lock_guard<std::mutex> guard(m_mutex); - assert(!llvm::is_contained(m_objects, new_object) && - "ManageObject called twice for the same object?"); - m_objects.push_back(new_object); + auto ret = m_objects.insert(new_object); + assert(ret.second && "ManageObject called twice for the same object?"); + (void)ret; } std::shared_ptr<T> GetSharedPointer(T *desired_object) { std::lock_guard<std::mutex> guard(m_mutex); auto this_sp = this->shared_from_this(); - if (!llvm::is_contained(m_objects, desired_object)) { + size_t count = m_objects.count(desired_object); + if (count == 0) { lldbassert(false && "object not found in shared cluster when expected"); desired_object = nullptr; } @@ -49,8 +50,14 @@ public: private: ClusterManager() : m_objects() {} - - llvm::SmallVector<T *, 16> m_objects; + // The cluster manager is used primarily to manage the + // children of root ValueObjects. So it will always have + // one element - the root. Pointers will often have dynamic + // values, so having 2 entries is pretty common. It's also + // pretty common to have small (2,3) structs, so setting the + // static size to 4 will cover those cases with no allocations + // w/o wasting too much space. + llvm::SmallPtrSet<T *, 4> m_objects; std::mutex m_mutex; }; diff --git a/contrib/llvm-project/lldb/include/lldb/Utility/Status.h b/contrib/llvm-project/lldb/include/lldb/Utility/Status.h index bee2b57b6ea9..ac410552438e 100644 --- a/contrib/llvm-project/lldb/include/lldb/Utility/Status.h +++ b/contrib/llvm-project/lldb/include/lldb/Utility/Status.h @@ -64,6 +64,11 @@ public: explicit Status(const char *format, ...) __attribute__((format(printf, 2, 3))); + template <typename... Args> + static Status createWithFormat(const char *format, Args &&...args) { + return Status(llvm::formatv(format, std::forward<Args>(args)...)); + } + ~Status(); // llvm::Error support @@ -190,6 +195,11 @@ protected: lldb::ErrorType m_type = lldb::eErrorTypeInvalid; ///< The type of the above error code. mutable std::string m_string; ///< A string representation of the error code. +private: + explicit Status(const llvm::formatv_object_base &payload) { + SetErrorToGenericError(); + m_string = payload.str(); + } }; } // namespace lldb_private diff --git a/contrib/llvm-project/lldb/include/lldb/Utility/StringExtractorGDBRemote.h b/contrib/llvm-project/lldb/include/lldb/Utility/StringExtractorGDBRemote.h index d869950ab6dd..dd468ef5bdde 100644 --- a/contrib/llvm-project/lldb/include/lldb/Utility/StringExtractorGDBRemote.h +++ b/contrib/llvm-project/lldb/include/lldb/Utility/StringExtractorGDBRemote.h @@ -13,6 +13,7 @@ #include "lldb/Utility/StringExtractor.h" #include "llvm/ADT/StringRef.h" +#include <optional> #include <string> #include <cstddef> @@ -208,14 +209,14 @@ public: static constexpr lldb::tid_t AllThreads = UINT64_MAX; // Read thread-id from the packet. If the packet is valid, returns - // the pair (PID, TID), otherwise returns llvm::None. If the packet + // the pair (PID, TID), otherwise returns std::nullopt. If the packet // does not list a PID, default_pid is used. - llvm::Optional<std::pair<lldb::pid_t, lldb::tid_t>> + std::optional<std::pair<lldb::pid_t, lldb::tid_t>> GetPidTid(lldb::pid_t default_pid); protected: ResponseValidatorCallback m_validator = nullptr; - void *m_validator_baton; + void *m_validator_baton = nullptr; }; #endif // LLDB_UTILITY_STRINGEXTRACTORGDBREMOTE_H diff --git a/contrib/llvm-project/lldb/include/lldb/Utility/StructuredData.h b/contrib/llvm-project/lldb/include/lldb/Utility/StructuredData.h index 9f6300f4f115..5420c0dcf8d5 100644 --- a/contrib/llvm-project/lldb/include/lldb/Utility/StructuredData.h +++ b/contrib/llvm-project/lldb/include/lldb/Utility/StructuredData.h @@ -158,6 +158,12 @@ public: Serialize(jso); } + virtual void GetDescription(lldb_private::Stream &s) const { + s.IndentMore(); + Dump(s, false); + s.IndentLess(); + } + private: lldb::StructuredDataType m_type; }; @@ -277,6 +283,8 @@ public: void Serialize(llvm::json::OStream &s) const override; + void GetDescription(lldb_private::Stream &s) const override; + protected: typedef std::vector<ObjectSP> collection; collection m_items; @@ -295,6 +303,8 @@ public: void Serialize(llvm::json::OStream &s) const override; + void GetDescription(lldb_private::Stream &s) const override; + protected: uint64_t m_value; }; @@ -312,6 +322,8 @@ public: void Serialize(llvm::json::OStream &s) const override; + void GetDescription(lldb_private::Stream &s) const override; + protected: double m_value; }; @@ -329,6 +341,8 @@ public: void Serialize(llvm::json::OStream &s) const override; + void GetDescription(lldb_private::Stream &s) const override; + protected: bool m_value; }; @@ -345,6 +359,8 @@ public: void Serialize(llvm::json::OStream &s) const override; + void GetDescription(lldb_private::Stream &s) const override; + protected: std::string m_value; }; @@ -524,6 +540,8 @@ public: void Serialize(llvm::json::OStream &s) const override; + void GetDescription(lldb_private::Stream &s) const override; + protected: typedef std::map<ConstString, ObjectSP> collection; collection m_dict; @@ -538,6 +556,8 @@ public: bool IsValid() const override { return false; } void Serialize(llvm::json::OStream &s) const override; + + void GetDescription(lldb_private::Stream &s) const override; }; class Generic : public Object { @@ -553,12 +573,15 @@ public: void Serialize(llvm::json::OStream &s) const override; + void GetDescription(lldb_private::Stream &s) const override; + private: void *m_object; }; static ObjectSP ParseJSON(const std::string &json_text); static ObjectSP ParseJSONFromFile(const FileSpec &file, Status &error); + static bool IsRecordType(const ObjectSP object_sp); }; } // namespace lldb_private diff --git a/contrib/llvm-project/lldb/include/lldb/Utility/Timeout.h b/contrib/llvm-project/lldb/include/lldb/Utility/Timeout.h index 29f8c1bbee38..85128c557d9c 100644 --- a/contrib/llvm-project/lldb/include/lldb/Utility/Timeout.h +++ b/contrib/llvm-project/lldb/include/lldb/Utility/Timeout.h @@ -9,23 +9,23 @@ #ifndef LLDB_UTILITY_TIMEOUT_H #define LLDB_UTILITY_TIMEOUT_H -#include "llvm/ADT/Optional.h" #include "llvm/Support/Chrono.h" #include "llvm/Support/FormatProviders.h" +#include <optional> namespace lldb_private { // A general purpose class for representing timeouts for various APIs. It's -// basically an llvm::Optional<std::chrono::duration<int64_t, Ratio>>, but we +// basically an std::optional<std::chrono::duration<int64_t, Ratio>>, but we // customize it a bit to enable the standard chrono implicit conversions (e.g. // from Timeout<std::milli> to Timeout<std::micro>. // // The intended meaning of the values is: -// - llvm::None - no timeout, the call should wait forever - 0 - poll, only +// - std::nullopt - no timeout, the call should wait forever - 0 - poll, only // complete the call if it will not block - >0 - wait for a given number of // units for the result template <typename Ratio> -class Timeout : public llvm::Optional<std::chrono::duration<int64_t, Ratio>> { +class Timeout : public std::optional<std::chrono::duration<int64_t, Ratio>> { private: template <typename Ratio2> using Dur = std::chrono::duration<int64_t, Ratio2>; template <typename Rep2, typename Ratio2> @@ -33,15 +33,15 @@ private: std::is_convertible<std::chrono::duration<Rep2, Ratio2>, std::chrono::duration<int64_t, Ratio>>::value>; - using Base = llvm::Optional<Dur<Ratio>>; + using Base = std::optional<Dur<Ratio>>; public: - Timeout(llvm::NoneType none) : Base(none) {} + Timeout(std::nullopt_t none) : Base(none) {} template <typename Ratio2, typename = typename EnableIf<int64_t, Ratio2>::type> Timeout(const Timeout<Ratio2> &other) - : Base(other ? Base(Dur<Ratio>(*other)) : llvm::None) {} + : Base(other ? Base(Dur<Ratio>(*other)) : std::nullopt) {} template <typename Rep2, typename Ratio2, typename = typename EnableIf<Rep2, Ratio2>::type> diff --git a/contrib/llvm-project/lldb/include/lldb/Utility/TraceGDBRemotePackets.h b/contrib/llvm-project/lldb/include/lldb/Utility/TraceGDBRemotePackets.h index c6d3f524d1d1..96d3f70f4b5f 100644 --- a/contrib/llvm-project/lldb/include/lldb/Utility/TraceGDBRemotePackets.h +++ b/contrib/llvm-project/lldb/include/lldb/Utility/TraceGDBRemotePackets.h @@ -44,12 +44,12 @@ struct TraceStartRequest { /// Tracing technology name, e.g. intel-pt, arm-coresight. std::string type; - /// If \a llvm::None, then this starts tracing the whole process. Otherwise, + /// If \a std::nullopt, then this starts tracing the whole process. Otherwise, /// only tracing for the specified threads is enabled. - llvm::Optional<std::vector<lldb::tid_t>> tids; + std::optional<std::vector<lldb::tid_t>> tids; /// \return - /// \b true if \a tids is \a None, i.e. whole process tracing. + /// \b true if \a tids is \a std::nullopt, i.e. whole process tracing. bool IsProcessTracing() const; }; @@ -72,9 +72,9 @@ struct TraceStopRequest { /// Tracing technology name, e.g. intel-pt, arm-coresight. std::string type; - /// If \a llvm::None, then this stops tracing the whole process. Otherwise, + /// If \a std::nullopt, then this stops tracing the whole process. Otherwise, /// only tracing for the specified threads is stopped. - llvm::Optional<std::vector<lldb::tid_t>> tids; + std::optional<std::vector<lldb::tid_t>> tids; }; bool fromJSON(const llvm::json::Value &value, TraceStopRequest &packet, @@ -132,8 +132,8 @@ llvm::json::Value toJSON(const TraceCpuState &packet); struct TraceGetStateResponse { std::vector<TraceThreadState> traced_threads; std::vector<TraceBinaryData> process_binary_data; - llvm::Optional<std::vector<TraceCpuState>> cpus; - llvm::Optional<std::vector<std::string>> warnings; + std::optional<std::vector<TraceCpuState>> cpus; + std::optional<std::vector<std::string>> warnings; void AddWarning(llvm::StringRef warning); }; @@ -152,9 +152,9 @@ struct TraceGetBinaryDataRequest { /// Identifier for the data. std::string kind; /// Optional tid if the data is related to a thread. - llvm::Optional<lldb::tid_t> tid; + std::optional<lldb::tid_t> tid; /// Optional core id if the data is related to a cpu core. - llvm::Optional<lldb::cpu_id_t> cpu_id; + std::optional<lldb::cpu_id_t> cpu_id; }; bool fromJSON(const llvm::json::Value &value, diff --git a/contrib/llvm-project/lldb/include/lldb/Utility/TraceIntelPTGDBRemotePackets.h b/contrib/llvm-project/lldb/include/lldb/Utility/TraceIntelPTGDBRemotePackets.h index 5930cd9970e7..dd3dddadd0d3 100644 --- a/contrib/llvm-project/lldb/include/lldb/Utility/TraceIntelPTGDBRemotePackets.h +++ b/contrib/llvm-project/lldb/include/lldb/Utility/TraceIntelPTGDBRemotePackets.h @@ -14,6 +14,7 @@ #include "llvm/Support/JSON.h" #include <chrono> +#include <optional> /// See docs/lldb-gdb-remote.txt for more information. /// @@ -38,21 +39,21 @@ struct TraceIntelPTStartRequest : TraceStartRequest { bool enable_tsc; /// PSB packet period - llvm::Optional<uint64_t> psb_period; + std::optional<uint64_t> psb_period; /// Required when doing "process tracing". /// /// Limit in bytes on all the thread traces started by this "process trace" /// instance. When a thread is about to be traced and the limit would be hit, /// then a "tracing" stop event is triggered. - llvm::Optional<uint64_t> process_buffer_size_limit; + std::optional<uint64_t> process_buffer_size_limit; /// Whether to have a trace buffer per thread or per cpu cpu. - llvm::Optional<bool> per_cpu_tracing; + std::optional<bool> per_cpu_tracing; /// Disable the cgroup filtering that is automatically applied in per cpu /// mode. - llvm::Optional<bool> disable_cgroup_filtering; + std::optional<bool> disable_cgroup_filtering; bool IsPerCpuTracing() const; }; @@ -110,7 +111,7 @@ struct LinuxPerfZeroTscConversion { struct TraceIntelPTGetStateResponse : TraceGetStateResponse { /// The TSC to wall time conversion if it exists, otherwise \b nullptr. - llvm::Optional<LinuxPerfZeroTscConversion> tsc_perf_zero_conversion; + std::optional<LinuxPerfZeroTscConversion> tsc_perf_zero_conversion; bool using_cgroup_filtering = false; }; diff --git a/contrib/llvm-project/lldb/include/lldb/Utility/UUID.h b/contrib/llvm-project/lldb/include/lldb/Utility/UUID.h index 1c7c04758da0..56aa3fa8450b 100644 --- a/contrib/llvm-project/lldb/include/lldb/Utility/UUID.h +++ b/contrib/llvm-project/lldb/include/lldb/Utility/UUID.h @@ -21,8 +21,18 @@ namespace lldb_private { class Stream; class UUID { + // Represents UUID's of various sizes. In all cases, a uuid of all zeros is + // treated as an "Invalid UUID" marker, and the UUID created from such data + // will return false for IsValid. public: UUID() = default; + + /// Creates a uuid from the data pointed to by the bytes argument. + UUID(llvm::ArrayRef<uint8_t> bytes) : m_bytes(bytes.begin(), bytes.end()) { + if (llvm::all_of(m_bytes, [](uint8_t b) { return b == 0; })) { + Clear(); + } + } // Reference: // https://crashpad.chromium.org/doxygen/structcrashpad_1_1CodeViewRecordPDB70.html @@ -38,35 +48,15 @@ public: }; /// Create a UUID from CvRecordPdb70. - static UUID fromCvRecord(CvRecordPdb70 debug_info); - - /// Creates a UUID from the data pointed to by the bytes argument. No special - /// significance is attached to any of the values. - static UUID fromData(const void *bytes, uint32_t num_bytes) { - if (bytes) - return fromData({reinterpret_cast<const uint8_t *>(bytes), num_bytes}); - return UUID(); - } - - /// Creates a uuid from the data pointed to by the bytes argument. No special - /// significance is attached to any of the values. - static UUID fromData(llvm::ArrayRef<uint8_t> bytes) { return UUID(bytes); } - - /// Creates a UUID from the data pointed to by the bytes argument. Data - /// consisting purely of zero bytes is treated as an invalid UUID. - static UUID fromOptionalData(const void *bytes, uint32_t num_bytes) { - if (bytes) - return fromOptionalData( - {reinterpret_cast<const uint8_t *>(bytes), num_bytes}); - return UUID(); - } - - /// Creates a UUID from the data pointed to by the bytes argument. Data - /// consisting purely of zero bytes is treated as an invalid UUID. - static UUID fromOptionalData(llvm::ArrayRef<uint8_t> bytes) { - if (llvm::all_of(bytes, [](uint8_t b) { return b == 0; })) - return UUID(); - return UUID(bytes); + UUID(CvRecordPdb70 debug_info); + + /// Creates a UUID from the data pointed to by the bytes argument. + UUID(const void *bytes, uint32_t num_bytes) { + if (!bytes) + return; + *this + = UUID(llvm::ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(bytes), + num_bytes)); } void Clear() { m_bytes.clear(); } @@ -77,15 +67,11 @@ public: explicit operator bool() const { return IsValid(); } bool IsValid() const { return !m_bytes.empty(); } - + std::string GetAsString(llvm::StringRef separator = "-") const; bool SetFromStringRef(llvm::StringRef str); - // Same as SetFromStringRef, but if the resultant UUID is all 0 bytes, set the - // UUID to invalid. - bool SetFromOptionalStringRef(llvm::StringRef str); - /// Decode as many UUID bytes as possible from the C string \a cstr. /// /// \param[in] str @@ -103,8 +89,6 @@ public: llvm::SmallVectorImpl<uint8_t> &uuid_bytes); private: - UUID(llvm::ArrayRef<uint8_t> bytes) : m_bytes(bytes.begin(), bytes.end()) {} - // GNU ld generates 20-byte build-ids. Size chosen to avoid heap allocations // for this case. llvm::SmallVector<uint8_t, 20> m_bytes; diff --git a/contrib/llvm-project/lldb/include/lldb/Utility/UriParser.h b/contrib/llvm-project/lldb/include/lldb/Utility/UriParser.h index 3c0f8d2273d0..311cff9f4dfd 100644 --- a/contrib/llvm-project/lldb/include/lldb/Utility/UriParser.h +++ b/contrib/llvm-project/lldb/include/lldb/Utility/UriParser.h @@ -9,15 +9,19 @@ #ifndef LLDB_UTILITY_URIPARSER_H #define LLDB_UTILITY_URIPARSER_H -#include "llvm/ADT/Optional.h" #include "llvm/ADT/StringRef.h" +#include <optional> + +namespace llvm { +class raw_ostream; +} // namespace llvm namespace lldb_private { struct URI { llvm::StringRef scheme; llvm::StringRef hostname; - llvm::Optional<uint16_t> port; + std::optional<uint16_t> port; llvm::StringRef path; bool operator==(const URI &R) const { @@ -25,7 +29,7 @@ struct URI { path == R.path; } - static llvm::Optional<URI> Parse(llvm::StringRef uri); + static std::optional<URI> Parse(llvm::StringRef uri); }; llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const URI &U); diff --git a/contrib/llvm-project/lldb/include/lldb/Utility/UserIDResolver.h b/contrib/llvm-project/lldb/include/lldb/Utility/UserIDResolver.h index 15afafd65a1a..45dad6b3aef3 100644 --- a/contrib/llvm-project/lldb/include/lldb/Utility/UserIDResolver.h +++ b/contrib/llvm-project/lldb/include/lldb/Utility/UserIDResolver.h @@ -10,9 +10,9 @@ #define LLDB_UTILITY_USERIDRESOLVER_H #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/Optional.h" #include "llvm/ADT/StringRef.h" #include <mutex> +#include <optional> namespace lldb_private { @@ -25,10 +25,10 @@ public: typedef uint32_t id_t; virtual ~UserIDResolver(); // anchor - llvm::Optional<llvm::StringRef> GetUserName(id_t uid) { + std::optional<llvm::StringRef> GetUserName(id_t uid) { return Get(uid, m_uid_cache, &UserIDResolver::DoGetUserName); } - llvm::Optional<llvm::StringRef> GetGroupName(id_t gid) { + std::optional<llvm::StringRef> GetGroupName(id_t gid) { return Get(gid, m_gid_cache, &UserIDResolver::DoGetGroupName); } @@ -37,15 +37,15 @@ public: static UserIDResolver &GetNoopResolver(); protected: - virtual llvm::Optional<std::string> DoGetUserName(id_t uid) = 0; - virtual llvm::Optional<std::string> DoGetGroupName(id_t gid) = 0; + virtual std::optional<std::string> DoGetUserName(id_t uid) = 0; + virtual std::optional<std::string> DoGetGroupName(id_t gid) = 0; private: - using Map = llvm::DenseMap<id_t, llvm::Optional<std::string>>; + using Map = llvm::DenseMap<id_t, std::optional<std::string>>; - llvm::Optional<llvm::StringRef> + std::optional<llvm::StringRef> Get(id_t id, Map &cache, - llvm::Optional<std::string> (UserIDResolver::*do_get)(id_t)); + std::optional<std::string> (UserIDResolver::*do_get)(id_t)); std::mutex m_mutex; Map m_uid_cache; diff --git a/contrib/llvm-project/lldb/include/lldb/lldb-defines.h b/contrib/llvm-project/lldb/include/lldb/lldb-defines.h index 339071bbfc31..3d23d697b542 100644 --- a/contrib/llvm-project/lldb/include/lldb/lldb-defines.h +++ b/contrib/llvm-project/lldb/include/lldb/lldb-defines.h @@ -45,7 +45,7 @@ #define LLDB_WATCH_TYPE_READ (1u << 0) #define LLDB_WATCH_TYPE_WRITE (1u << 1) #define LLDB_WATCH_TYPE_IS_VALID(type) \ - ((type | LLDB_WATCH_TYPE_READ) || (type | LLDB_WATCH_TYPE_WRITE)) + ((type & LLDB_WATCH_TYPE_READ) || (type & LLDB_WATCH_TYPE_WRITE)) // Generic Register Numbers #define LLDB_REGNUM_GENERIC_PC 0 // Program Counter @@ -86,6 +86,7 @@ #define LLDB_INVALID_LINE_NUMBER UINT32_MAX #define LLDB_INVALID_COLUMN_NUMBER 0 #define LLDB_INVALID_QUEUE_ID 0 +#define LLDB_INVALID_CPU_ID UINT32_MAX /// CPU Type definitions #define LLDB_ARCH_DEFAULT "systemArch" diff --git a/contrib/llvm-project/lldb/include/lldb/lldb-enumerations.h b/contrib/llvm-project/lldb/include/lldb/lldb-enumerations.h index 80046e7e6bee..31c6d27240b3 100644 --- a/contrib/llvm-project/lldb/include/lldb/lldb-enumerations.h +++ b/contrib/llvm-project/lldb/include/lldb/lldb-enumerations.h @@ -9,6 +9,7 @@ #ifndef LLDB_LLDB_ENUMERATIONS_H #define LLDB_LLDB_ENUMERATIONS_H +#include <cstdint> #include <type_traits> #ifndef SWIG @@ -374,6 +375,9 @@ FLAGS_ENUM(SymbolContextItem){ /// from being used during frame PC lookups and many other /// potential address to symbol context lookups. eSymbolContextVariable = (1u << 7), + + // Keep this last and up-to-date for what the last enum value is. + eSymbolContextLastItem = eSymbolContextVariable, }; LLDB_MARK_AS_BITMASK_ENUM(SymbolContextItem) @@ -433,6 +437,9 @@ FLAGS_ENUM(WatchpointEventType){ /// specification for ease of use and consistency. /// The enum -> string code is in Language.cpp, don't change this /// table without updating that code as well. +/// +/// This datatype is used in SBExpressionOptions::SetLanguage() which +/// makes this type API. Do not change its underlying storage type! enum LanguageType { eLanguageTypeUnknown = 0x0000, ///< Unknown or invalid language value. eLanguageTypeC89 = 0x0001, ///< ISO C:1989. @@ -608,8 +615,6 @@ enum CommandArgumentType { eArgTypeConnectURL, eArgTypeTargetID, eArgTypeStopHookID, - eArgTypeReproducerProvider, - eArgTypeReproducerSignal, eArgTypeLastArg // Always keep this entry as the last entry in this // enumeration!! }; @@ -832,6 +837,16 @@ enum TemplateArgumentKind { eTemplateArgumentKindNullPtr, }; +/// Type of match to be performed when looking for a formatter for a data type. +/// Used by classes like SBTypeNameSpecifier or lldb_private::TypeMatcher. +enum FormatterMatchType { + eFormatterMatchExact, + eFormatterMatchRegex, + eFormatterMatchCallback, + + eLastFormatterMatchType = eFormatterMatchCallback, +}; + /// Options that can be set for a formatter to alter its behavior. Not /// all of these are applicable to all formatter types. FLAGS_ENUM(TypeOptions){eTypeOptionNone = (0u), @@ -1161,15 +1176,18 @@ enum SaveCoreStyle { /// Events that might happen during a trace session. enum TraceEvent { - /// Tracing was disabled for some time due to a software trigger + /// Tracing was disabled for some time due to a software trigger. eTraceEventDisabledSW, - /// Tracing was disable for some time due to a hardware trigger + /// Tracing was disable for some time due to a hardware trigger. eTraceEventDisabledHW, /// Event due to CPU change for a thread. This event is also fired when /// suddenly it's not possible to identify the cpu of a given thread. eTraceEventCPUChanged, - /// Event due to a CPU HW clock tick + /// Event due to a CPU HW clock tick. eTraceEventHWClockTick, + /// The underlying tracing technology emitted a synchronization event used by + /// trace processors. + eTraceEventSyncPoint, }; // Enum used to identify which kind of item a \a TraceCursor is pointing at @@ -1179,6 +1197,29 @@ enum TraceItemKind { eTraceItemKindInstruction, }; +/// Enum to indicate the reference point when invoking +/// \a TraceCursor::Seek(). +/// The following values are inspired by \a std::istream::seekg. +enum TraceCursorSeekType { + /// The beginning of the trace, i.e the oldest item. + eTraceCursorSeekTypeBeginning = 0, + /// The current position in the trace. + eTraceCursorSeekTypeCurrent, + /// The end of the trace, i.e the most recent item. + eTraceCursorSeekTypeEnd +}; + +/// Enum to control the verbosity level of `dwim-print` execution. +enum DWIMPrintVerbosity { + /// Run `dwim-print` with no verbosity. + eDWIMPrintVerbosityNone, + /// Print a message when `dwim-print` uses `expression` evaluation. + eDWIMPrintVerbosityExpression, + /// Always print a message indicating how `dwim-print` is evaluating its + /// expression. + eDWIMPrintVerbosityFull, +}; + } // namespace lldb #endif // LLDB_LLDB_ENUMERATIONS_H diff --git a/contrib/llvm-project/lldb/include/lldb/lldb-forward.h b/contrib/llvm-project/lldb/include/lldb/lldb-forward.h index c51e1850338f..f81852622e4f 100644 --- a/contrib/llvm-project/lldb/include/lldb/lldb-forward.h +++ b/contrib/llvm-project/lldb/include/lldb/lldb-forward.h @@ -161,6 +161,7 @@ class PersistentExpressionState; class Platform; class Process; class ProcessAttachInfo; +class ProcessLaunchInfo; class ProcessInfo; class ProcessInstanceInfo; class ProcessInstanceInfoMatch; @@ -180,6 +181,7 @@ class RichManglingContext; class Scalar; class ScriptInterpreter; class ScriptInterpreterLocker; +class ScriptedPlatformInterface; class ScriptedProcessInterface; class ScriptedThreadInterface; class ScriptedSyntheticChildren; @@ -236,6 +238,7 @@ class ThreadPlanStepThrough; class ThreadPlanTracer; class ThreadSpec; class ThreadPostMortemTrace; +class ThreadedCommunication; class Trace; class TraceCursor; class TraceExporter; @@ -257,6 +260,7 @@ class TypeNameSpecifierImpl; class TypeSummaryImpl; class TypeSummaryOptions; class TypeSystem; +class TypeSystemClang; class UUID; class UnixSignals; class Unwind; @@ -349,6 +353,7 @@ typedef std::shared_ptr<lldb_private::MemoryRegionInfo> MemoryRegionInfoSP; typedef std::shared_ptr<lldb_private::Module> ModuleSP; typedef std::weak_ptr<lldb_private::Module> ModuleWP; typedef std::shared_ptr<lldb_private::ObjectFile> ObjectFileSP; +typedef std::shared_ptr<lldb_private::ObjectContainer> ObjectContainerSP; typedef std::shared_ptr<lldb_private::ObjectFileJITDelegate> ObjectFileJITDelegateSP; typedef std::weak_ptr<lldb_private::ObjectFileJITDelegate> @@ -361,6 +366,7 @@ typedef std::shared_ptr<lldb_private::OptionValueProperties> typedef std::shared_ptr<lldb_private::Platform> PlatformSP; typedef std::shared_ptr<lldb_private::Process> ProcessSP; typedef std::shared_ptr<lldb_private::ProcessAttachInfo> ProcessAttachInfoSP; +typedef std::shared_ptr<lldb_private::ProcessLaunchInfo> ProcessLaunchInfoSP; typedef std::weak_ptr<lldb_private::Process> ProcessWP; typedef std::shared_ptr<lldb_private::RegisterCheckpoint> RegisterCheckpointSP; typedef std::shared_ptr<lldb_private::RegisterContext> RegisterContextSP; @@ -374,6 +380,8 @@ typedef std::shared_ptr<lldb_private::RecognizedStackFrame> typedef std::shared_ptr<lldb_private::ScriptSummaryFormat> ScriptSummaryFormatSP; typedef std::shared_ptr<lldb_private::ScriptInterpreter> ScriptInterpreterSP; +typedef std::unique_ptr<lldb_private::ScriptedPlatformInterface> + ScriptedPlatformInterfaceUP; typedef std::unique_ptr<lldb_private::ScriptedProcessInterface> ScriptedProcessInterfaceUP; typedef std::shared_ptr<lldb_private::ScriptedThreadInterface> @@ -420,7 +428,7 @@ typedef std::weak_ptr<lldb_private::ThreadPlan> ThreadPlanWP; typedef std::shared_ptr<lldb_private::ThreadPlanTracer> ThreadPlanTracerSP; typedef std::shared_ptr<lldb_private::Trace> TraceSP; typedef std::unique_ptr<lldb_private::TraceExporter> TraceExporterUP; -typedef std::unique_ptr<lldb_private::TraceCursor> TraceCursorUP; +typedef std::shared_ptr<lldb_private::TraceCursor> TraceCursorSP; typedef std::shared_ptr<lldb_private::Type> TypeSP; typedef std::weak_ptr<lldb_private::Type> TypeWP; typedef std::shared_ptr<lldb_private::TypeCategoryImpl> TypeCategoryImplSP; @@ -430,6 +438,8 @@ typedef std::shared_ptr<lldb_private::TypeMemberFunctionImpl> typedef std::shared_ptr<lldb_private::TypeEnumMemberImpl> TypeEnumMemberImplSP; typedef std::shared_ptr<lldb_private::TypeFilterImpl> TypeFilterImplSP; typedef std::shared_ptr<lldb_private::TypeSystem> TypeSystemSP; +typedef std::shared_ptr<lldb_private::TypeSystemClang> TypeSystemClangSP; +typedef std::weak_ptr<lldb_private::TypeSystem> TypeSystemWP; typedef std::shared_ptr<lldb_private::TypeFormatImpl> TypeFormatImplSP; typedef std::shared_ptr<lldb_private::TypeNameSpecifierImpl> TypeNameSpecifierImplSP; diff --git a/contrib/llvm-project/lldb/include/lldb/lldb-private-defines.h b/contrib/llvm-project/lldb/include/lldb/lldb-private-defines.h deleted file mode 100644 index d66e6ef1518d..000000000000 --- a/contrib/llvm-project/lldb/include/lldb/lldb-private-defines.h +++ /dev/null @@ -1,36 +0,0 @@ -//===-- lldb-private-defines.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_LLDB_PRIVATE_DEFINES_H -#define LLDB_LLDB_PRIVATE_DEFINES_H - -#if defined(__cplusplus) - -// Include Compiler.h here so we don't define LLVM_FALLTHROUGH and then -// Compiler.h later tries to redefine it. -#include "llvm/Support/Compiler.h" - -#ifndef LLVM_FALLTHROUGH - -#ifndef __has_cpp_attribute -#define __has_cpp_attribute(x) 0 -#endif - -/// \macro LLVM_FALLTHROUGH -/// Marks an empty statement preceding a deliberate switch fallthrough. -#if __has_cpp_attribute(clang::fallthrough) -#define LLVM_FALLTHROUGH [[clang::fallthrough]] -#else -#define LLVM_FALLTHROUGH -#endif - -#endif // ifndef LLVM_FALLTHROUGH - -#endif // #if defined(__cplusplus) - -#endif // LLDB_LLDB_PRIVATE_DEFINES_H diff --git a/contrib/llvm-project/lldb/include/lldb/lldb-private-enumerations.h b/contrib/llvm-project/lldb/include/lldb/lldb-private-enumerations.h index 310058495882..179b8b944cc6 100644 --- a/contrib/llvm-project/lldb/include/lldb/lldb-private-enumerations.h +++ b/contrib/llvm-project/lldb/include/lldb/lldb-private-enumerations.h @@ -128,16 +128,10 @@ enum InstructionType { /// Format category entry types enum FormatCategoryItem { - eFormatCategoryItemSummary = 0x0001, - eFormatCategoryItemRegexSummary = 0x0002, - eFormatCategoryItemFilter = 0x0004, - eFormatCategoryItemRegexFilter = 0x0008, - eFormatCategoryItemSynth = 0x0010, - eFormatCategoryItemRegexSynth = 0x0020, - eFormatCategoryItemValue = 0x0040, - eFormatCategoryItemRegexValue = 0x0080, - eFormatCategoryItemValidator = 0x0100, - eFormatCategoryItemRegexValidator = 0x0200 + eFormatCategoryItemSummary = 1, + eFormatCategoryItemFilter = 1 << 1, + eFormatCategoryItemSynth = 1 << 2, + eFormatCategoryItemFormat = 1 << 3, }; /// Expression execution policies @@ -231,23 +225,6 @@ enum LogHandlerKind { eLogHandlerDefault = eLogHandlerStream, }; -enum ReproducerProvider { - eReproducerProviderCommands, - eReproducerProviderFiles, - eReproducerProviderSymbolFiles, - eReproducerProviderGDB, - eReproducerProviderProcessInfo, - eReproducerProviderVersion, - eReproducerProviderWorkingDirectory, - eReproducerProviderHomeDirectory, - eReproducerProviderNone, -}; - -enum ReproducerCrashSignal { - eReproducerCrashSigill, - eReproducerCrashSigsegv, -}; - enum LoadDependentFiles { eLoadDependentsDefault, eLoadDependentsYes, diff --git a/contrib/llvm-project/lldb/include/lldb/lldb-private-interfaces.h b/contrib/llvm-project/lldb/include/lldb/lldb-private-interfaces.h index 41cc8bd389dc..1eb37c0c9f68 100644 --- a/contrib/llvm-project/lldb/include/lldb/lldb-private-interfaces.h +++ b/contrib/llvm-project/lldb/include/lldb/lldb-private-interfaces.h @@ -40,6 +40,9 @@ typedef ObjectContainer *(*ObjectContainerCreateInstance)( const lldb::ModuleSP &module_sp, lldb::DataBufferSP &data_sp, lldb::offset_t data_offset, const FileSpec *file, lldb::offset_t offset, lldb::offset_t length); +typedef ObjectContainer *(*ObjectContainerCreateMemoryInstance)( + const lldb::ModuleSP &module_sp, lldb::WritableDataBufferSP data_sp, + const lldb::ProcessSP &process_sp, lldb::addr_t offset); typedef size_t (*ObjectFileGetModuleSpecifications)( const FileSpec &file, lldb::DataBufferSP &data_sp, lldb::offset_t data_offset, lldb::offset_t file_offset, diff --git a/contrib/llvm-project/lldb/include/lldb/lldb-private-types.h b/contrib/llvm-project/lldb/include/lldb/lldb-private-types.h index 1b0d263e2073..edc1c78985bd 100644 --- a/contrib/llvm-project/lldb/include/lldb/lldb-private-types.h +++ b/contrib/llvm-project/lldb/include/lldb/lldb-private-types.h @@ -15,6 +15,8 @@ #include "llvm/ADT/ArrayRef.h" +#include <type_traits> + namespace llvm { namespace sys { class DynamicLibrary; @@ -70,6 +72,8 @@ struct RegisterInfo { byte_size); } }; +static_assert(std::is_trivial<RegisterInfo>::value, + "RegisterInfo must be trivial."); /// Registers are grouped into register sets struct RegisterSet { diff --git a/contrib/llvm-project/lldb/include/lldb/lldb-private.h b/contrib/llvm-project/lldb/include/lldb/lldb-private.h index ac07047fb4ed..f56af06ec597 100644 --- a/contrib/llvm-project/lldb/include/lldb/lldb-private.h +++ b/contrib/llvm-project/lldb/include/lldb/lldb-private.h @@ -11,7 +11,6 @@ #if defined(__cplusplus) -#include "lldb/lldb-private-defines.h" #include "lldb/lldb-private-enumerations.h" #include "lldb/lldb-private-interfaces.h" #include "lldb/lldb-private-types.h" diff --git a/contrib/llvm-project/lldb/include/lldb/module.modulemap b/contrib/llvm-project/lldb/include/lldb/module.modulemap index 303d6b15e808..c06e026076f4 100644 --- a/contrib/llvm-project/lldb/include/lldb/module.modulemap +++ b/contrib/llvm-project/lldb/include/lldb/module.modulemap @@ -134,7 +134,6 @@ module lldb_Utility { module lldb_enumerations { header "lldb-enumerations.h" export * } module lldb_forward { header "lldb-forward.h" export * } module lldb_private_enumerations { header "lldb-private-enumerations.h" export * } - module lldb_private_defines { header "lldb-private-defines.h" export * } module lldb_private_forward { header "lldb-private-forward.h" export * } module lldb_private { header "lldb-private.h" export * } module lldb_private_interfaces { header "lldb-private-interfaces.h" export * } diff --git a/contrib/llvm-project/lldb/source/API/SBBreakpointLocation.cpp b/contrib/llvm-project/lldb/source/API/SBBreakpointLocation.cpp index 914317437723..a253530f5718 100644 --- a/contrib/llvm-project/lldb/source/API/SBBreakpointLocation.cpp +++ b/contrib/llvm-project/lldb/source/API/SBBreakpointLocation.cpp @@ -28,6 +28,8 @@ #include "lldb/lldb-defines.h" #include "lldb/lldb-types.h" +#include "SBBreakpointOptionCommon.h" + using namespace lldb; using namespace lldb_private; @@ -198,6 +200,21 @@ bool SBBreakpointLocation::GetAutoContinue() { return false; } +void SBBreakpointLocation::SetCallback(SBBreakpointHitCallback callback, + void *baton) { + LLDB_INSTRUMENT_VA(this, callback, baton); + + BreakpointLocationSP loc_sp = GetSP(); + + if (loc_sp) { + std::lock_guard<std::recursive_mutex> guard( + loc_sp->GetTarget().GetAPIMutex()); + BatonSP baton_sp(new SBBreakpointCallbackBaton(callback, baton)); + loc_sp->SetCallback(SBBreakpointCallbackBaton::PrivateBreakpointHitCallback, + baton_sp, false); + } +} + void SBBreakpointLocation::SetScriptCallbackFunction( const char *callback_function_name) { LLDB_INSTRUMENT_VA(this, callback_function_name); @@ -374,7 +391,7 @@ const char *SBBreakpointLocation::GetQueueName() const { if (loc_sp) { std::lock_guard<std::recursive_mutex> guard( loc_sp->GetTarget().GetAPIMutex()); - loc_sp->GetQueueName(); + return loc_sp->GetQueueName(); } return nullptr; } diff --git a/contrib/llvm-project/lldb/source/API/SBCommandInterpreter.cpp b/contrib/llvm-project/lldb/source/API/SBCommandInterpreter.cpp index aa46f1085dc9..cd6ef3b23fd4 100644 --- a/contrib/llvm-project/lldb/source/API/SBCommandInterpreter.cpp +++ b/contrib/llvm-project/lldb/source/API/SBCommandInterpreter.cpp @@ -28,6 +28,7 @@ #include "lldb/API/SBTarget.h" #include <memory> +#include <optional> using namespace lldb; using namespace lldb_private; @@ -45,8 +46,8 @@ public: m_backend(backend) { m_auto_repeat_command = auto_repeat_command == nullptr - ? llvm::None - : llvm::Optional<std::string>(auto_repeat_command); + ? std::nullopt + : std::optional<std::string>(auto_repeat_command); // We don't know whether any given command coming from this interface takes // arguments or not so here we're just disabling the basic args check. CommandArgumentData none_arg{eArgTypeNone, eArgRepeatStar}; @@ -56,13 +57,13 @@ public: bool IsRemovable() const override { return true; } /// More documentation is available in lldb::CommandObject::GetRepeatCommand, - /// but in short, if llvm::None is returned, the previous command will be + /// but in short, if std::nullopt is returned, the previous command will be /// repeated, and if an empty string is returned, no commands will be /// executed. - llvm::Optional<std::string> GetRepeatCommand(Args ¤t_command_args, - uint32_t index) override { + std::optional<std::string> GetRepeatCommand(Args ¤t_command_args, + uint32_t index) override { if (!m_auto_repeat_command) - return llvm::None; + return std::nullopt; else return m_auto_repeat_command; } @@ -77,7 +78,7 @@ protected: return ret; } std::shared_ptr<lldb::SBCommandPluginInterface> m_backend; - llvm::Optional<std::string> m_auto_repeat_command; + std::optional<std::string> m_auto_repeat_command; }; SBCommandInterpreter::SBCommandInterpreter(CommandInterpreter *interpreter) diff --git a/contrib/llvm-project/lldb/source/API/SBCommunication.cpp b/contrib/llvm-project/lldb/source/API/SBCommunication.cpp index 0a1dad1e2e8f..f93898718be6 100644 --- a/contrib/llvm-project/lldb/source/API/SBCommunication.cpp +++ b/contrib/llvm-project/lldb/source/API/SBCommunication.cpp @@ -8,7 +8,7 @@ #include "lldb/API/SBCommunication.h" #include "lldb/API/SBBroadcaster.h" -#include "lldb/Core/Communication.h" +#include "lldb/Core/ThreadedCommunication.h" #include "lldb/Host/ConnectionFileDescriptor.h" #include "lldb/Host/Host.h" #include "lldb/Utility/Instrumentation.h" @@ -19,7 +19,8 @@ using namespace lldb_private; SBCommunication::SBCommunication() { LLDB_INSTRUMENT_VA(this); } SBCommunication::SBCommunication(const char *broadcaster_name) - : m_opaque(new Communication(broadcaster_name)), m_opaque_owned(true) { + : m_opaque(new ThreadedCommunication(broadcaster_name)), + m_opaque_owned(true) { LLDB_INSTRUMENT_VA(this, broadcaster_name); } @@ -106,7 +107,7 @@ size_t SBCommunication::Read(void *dst, size_t dst_len, uint32_t timeout_usec, size_t bytes_read = 0; Timeout<std::micro> timeout = timeout_usec == UINT32_MAX - ? Timeout<std::micro>(llvm::None) + ? Timeout<std::micro>(std::nullopt) : std::chrono::microseconds(timeout_usec); if (m_opaque) bytes_read = m_opaque->Read(dst, dst_len, timeout, status, nullptr); @@ -169,5 +170,5 @@ SBBroadcaster SBCommunication::GetBroadcaster() { const char *SBCommunication::GetBroadcasterClass() { LLDB_INSTRUMENT(); - return Communication::GetStaticBroadcasterClass().AsCString(); + return ThreadedCommunication::GetStaticBroadcasterClass().AsCString(); } diff --git a/contrib/llvm-project/lldb/source/API/SBDebugger.cpp b/contrib/llvm-project/lldb/source/API/SBDebugger.cpp index 0de934b2a9bd..851c80a21d8e 100644 --- a/contrib/llvm-project/lldb/source/API/SBDebugger.cpp +++ b/contrib/llvm-project/lldb/source/API/SBDebugger.cpp @@ -51,6 +51,7 @@ #include "lldb/Target/Process.h" #include "lldb/Target/TargetList.h" #include "lldb/Utility/Args.h" +#include "lldb/Utility/Diagnostics.h" #include "lldb/Utility/State.h" #include "lldb/Version/Version.h" @@ -218,6 +219,16 @@ void SBDebugger::PrintStackTraceOnError() { llvm::sys::PrintStackTraceOnErrorSignal(executable); } +static void DumpDiagnostics(void *cookie) { + Diagnostics::Instance().Dump(llvm::errs()); +} + +void SBDebugger::PrintDiagnosticsOnError() { + LLDB_INSTRUMENT(); + + llvm::sys::AddSignalHandler(&DumpDiagnostics, nullptr); +} + void SBDebugger::Terminate() { LLDB_INSTRUMENT(); @@ -377,7 +388,11 @@ SBError SBDebugger::SetInputFile(SBFile file) { error.ref().SetErrorString("invalid debugger"); return error; } - error.SetError(m_opaque_sp->SetInputFile(file.m_opaque_sp)); + if (!file) { + error.ref().SetErrorString("invalid file"); + return error; + } + m_opaque_sp->SetInputFile(file.m_opaque_sp); return error; } @@ -436,6 +451,29 @@ SBError SBDebugger::SetErrorFile(SBFile file) { return error; } +lldb::SBStructuredData SBDebugger::GetSetting(const char *setting) { + LLDB_INSTRUMENT_VA(this, setting); + + SBStructuredData data; + if (!m_opaque_sp) + return data; + + StreamString json_strm; + ExecutionContext exe_ctx( + m_opaque_sp->GetCommandInterpreter().GetExecutionContext()); + if (setting && strlen(setting) > 0) + m_opaque_sp->DumpPropertyValue(&exe_ctx, json_strm, setting, + /*dump_mask*/ 0, + /*is_json*/ true); + else + m_opaque_sp->DumpAllPropertyValues(&exe_ctx, json_strm, /*dump_mask*/ 0, + /*is_json*/ true); + + data.m_impl_up->SetObjectSP( + StructuredData::ParseJSON(json_strm.GetString().str())); + return data; +} + FILE *SBDebugger::GetInputFileHandle() { LLDB_INSTRUMENT_VA(this); if (m_opaque_sp) { @@ -1365,9 +1403,7 @@ void SBDebugger::SetPrompt(const char *prompt) { const char *SBDebugger::GetReproducerPath() const { LLDB_INSTRUMENT_VA(this); - return (m_opaque_sp - ? ConstString(m_opaque_sp->GetReproducerPath()).GetCString() - : nullptr); + return "GetReproducerPath has been deprecated"; } ScriptLanguage SBDebugger::GetScriptLanguage() const { @@ -1609,7 +1645,7 @@ static llvm::ArrayRef<const char *> GetCategoryArray(const char **categories) { size_t len = 0; while (categories[len] != nullptr) ++len; - return llvm::makeArrayRef(categories, len); + return llvm::ArrayRef(categories, len); } bool SBDebugger::EnableLog(const char *channel, const char **categories) { diff --git a/contrib/llvm-project/lldb/source/API/SBError.cpp b/contrib/llvm-project/lldb/source/API/SBError.cpp index ef4f7266f083..1a034154955d 100644 --- a/contrib/llvm-project/lldb/source/API/SBError.cpp +++ b/contrib/llvm-project/lldb/source/API/SBError.cpp @@ -25,6 +25,11 @@ SBError::SBError(const SBError &rhs) { m_opaque_up = clone(rhs.m_opaque_up); } +SBError::SBError(const lldb_private::Status &status) + : m_opaque_up(new Status(status)) { + LLDB_INSTRUMENT_VA(this, status); +} + SBError::~SBError() = default; const SBError &SBError::operator=(const SBError &rhs) { diff --git a/contrib/llvm-project/lldb/source/API/SBExpressionOptions.cpp b/contrib/llvm-project/lldb/source/API/SBExpressionOptions.cpp index 191e38fe5cfc..6ae57f24606a 100644 --- a/contrib/llvm-project/lldb/source/API/SBExpressionOptions.cpp +++ b/contrib/llvm-project/lldb/source/API/SBExpressionOptions.cpp @@ -94,7 +94,7 @@ uint32_t SBExpressionOptions::GetTimeoutInMicroSeconds() const { void SBExpressionOptions::SetTimeoutInMicroSeconds(uint32_t timeout) { LLDB_INSTRUMENT_VA(this, timeout); - m_opaque_up->SetTimeout(timeout == 0 ? Timeout<std::micro>(llvm::None) + m_opaque_up->SetTimeout(timeout == 0 ? Timeout<std::micro>(std::nullopt) : std::chrono::microseconds(timeout)); } @@ -110,7 +110,7 @@ void SBExpressionOptions::SetOneThreadTimeoutInMicroSeconds(uint32_t timeout) { LLDB_INSTRUMENT_VA(this, timeout); m_opaque_up->SetOneThreadTimeout(timeout == 0 - ? Timeout<std::micro>(llvm::None) + ? Timeout<std::micro>(std::nullopt) : std::chrono::microseconds(timeout)); } @@ -254,5 +254,5 @@ EvaluateExpressionOptions *SBExpressionOptions::get() const { } EvaluateExpressionOptions &SBExpressionOptions::ref() const { - return *(m_opaque_up.get()); + return *m_opaque_up; } diff --git a/contrib/llvm-project/lldb/source/API/SBFileSpec.cpp b/contrib/llvm-project/lldb/source/API/SBFileSpec.cpp index 2bec9a7a1e77..a7df9afc4b8e 100644 --- a/contrib/llvm-project/lldb/source/API/SBFileSpec.cpp +++ b/contrib/llvm-project/lldb/source/API/SBFileSpec.cpp @@ -115,26 +115,26 @@ const char *SBFileSpec::GetDirectory() const { LLDB_INSTRUMENT_VA(this); FileSpec directory{*m_opaque_up}; - directory.GetFilename().Clear(); - return directory.GetCString(); + directory.ClearFilename(); + return directory.GetPathAsConstString().GetCString(); } void SBFileSpec::SetFilename(const char *filename) { LLDB_INSTRUMENT_VA(this, filename); if (filename && filename[0]) - m_opaque_up->GetFilename().SetCString(filename); + m_opaque_up->SetFilename(filename); else - m_opaque_up->GetFilename().Clear(); + m_opaque_up->ClearFilename(); } void SBFileSpec::SetDirectory(const char *directory) { LLDB_INSTRUMENT_VA(this, directory); if (directory && directory[0]) - m_opaque_up->GetDirectory().SetCString(directory); + m_opaque_up->SetDirectory(directory); else - m_opaque_up->GetDirectory().Clear(); + m_opaque_up->ClearDirectory(); } uint32_t SBFileSpec::GetPath(char *dst_path, size_t dst_len) const { diff --git a/contrib/llvm-project/lldb/source/API/SBFrame.cpp b/contrib/llvm-project/lldb/source/API/SBFrame.cpp index ea9c2bb747e1..eb7ec3bbf8d6 100644 --- a/contrib/llvm-project/lldb/source/API/SBFrame.cpp +++ b/contrib/llvm-project/lldb/source/API/SBFrame.cpp @@ -602,7 +602,8 @@ SBValue SBFrame::FindValue(const char *name, ValueType value_type, &variable_list); if (value_type == eValueTypeVariableGlobal) { const bool get_file_globals = true; - VariableList *frame_vars = frame->GetVariableList(get_file_globals); + VariableList *frame_vars = frame->GetVariableList(get_file_globals, + nullptr); if (frame_vars) frame_vars->AppendVariablesIfUnique(variable_list); } @@ -739,7 +740,7 @@ SBValueList SBFrame::GetVariables(bool arguments, bool locals, bool statics, lldb::DynamicValueType use_dynamic = frame->CalculateTarget()->GetPreferDynamicValue(); const bool include_runtime_support_values = - target ? target->GetDisplayRuntimeSupportValues() : false; + target->GetDisplayRuntimeSupportValues(); SBVariablesOptions options; options.SetIncludeArguments(arguments); @@ -805,7 +806,10 @@ SBValueList SBFrame::GetVariables(const lldb::SBVariablesOptions &options) { frame = exe_ctx.GetFramePtr(); if (frame) { VariableList *variable_list = nullptr; - variable_list = frame->GetVariableList(true); + Status var_error; + variable_list = frame->GetVariableList(true, &var_error); + if (var_error.Fail()) + value_list.SetError(var_error); if (variable_list) { const size_t num_variables = variable_list->GetSize(); if (num_variables) { diff --git a/contrib/llvm-project/lldb/source/API/SBInstruction.cpp b/contrib/llvm-project/lldb/source/API/SBInstruction.cpp index ced22628a297..b03d8f73d66e 100644 --- a/contrib/llvm-project/lldb/source/API/SBInstruction.cpp +++ b/contrib/llvm-project/lldb/source/API/SBInstruction.cpp @@ -164,6 +164,25 @@ const char *SBInstruction::GetComment(SBTarget target) { return nullptr; } +lldb::InstructionControlFlowKind SBInstruction::GetControlFlowKind(lldb::SBTarget target) { + LLDB_INSTRUMENT_VA(this, target); + + lldb::InstructionSP inst_sp(GetOpaque()); + if (inst_sp) { + ExecutionContext exe_ctx; + TargetSP target_sp(target.GetSP()); + std::unique_lock<std::recursive_mutex> lock; + if (target_sp) { + lock = std::unique_lock<std::recursive_mutex>(target_sp->GetAPIMutex()); + + target_sp->CalculateExecutionContext(exe_ctx); + exe_ctx.SetProcessSP(target_sp->GetProcessSP()); + } + return inst_sp->GetControlFlowKind(&exe_ctx); + } + return lldb::eInstructionControlFlowKindUnknown; +} + size_t SBInstruction::GetByteSize() { LLDB_INSTRUMENT_VA(this); diff --git a/contrib/llvm-project/lldb/source/API/SBLaunchInfo.cpp b/contrib/llvm-project/lldb/source/API/SBLaunchInfo.cpp index 5149feba5e0b..ae191916b49e 100644 --- a/contrib/llvm-project/lldb/source/API/SBLaunchInfo.cpp +++ b/contrib/llvm-project/lldb/source/API/SBLaunchInfo.cpp @@ -207,7 +207,7 @@ void SBLaunchInfo::Clear() { const char *SBLaunchInfo::GetWorkingDirectory() const { LLDB_INSTRUMENT_VA(this); - return m_opaque_sp->GetWorkingDirectory().GetCString(); + return m_opaque_sp->GetWorkingDirectory().GetPathAsConstString().AsCString(); } void SBLaunchInfo::SetWorkingDirectory(const char *working_dir) { diff --git a/contrib/llvm-project/lldb/source/API/SBListener.cpp b/contrib/llvm-project/lldb/source/API/SBListener.cpp index a7008dc5224e..a4c847bec857 100644 --- a/contrib/llvm-project/lldb/source/API/SBListener.cpp +++ b/contrib/llvm-project/lldb/source/API/SBListener.cpp @@ -132,7 +132,7 @@ bool SBListener::WaitForEvent(uint32_t timeout_secs, SBEvent &event) { bool success = false; if (m_opaque_sp) { - Timeout<std::micro> timeout(llvm::None); + Timeout<std::micro> timeout(std::nullopt); if (timeout_secs != UINT32_MAX) { assert(timeout_secs != 0); // Take this out after all calls with timeout // set to zero have been removed.... @@ -156,7 +156,7 @@ bool SBListener::WaitForEventForBroadcaster(uint32_t num_seconds, LLDB_INSTRUMENT_VA(this, num_seconds, broadcaster, event); if (m_opaque_sp && broadcaster.IsValid()) { - Timeout<std::micro> timeout(llvm::None); + Timeout<std::micro> timeout(std::nullopt); if (num_seconds != UINT32_MAX) timeout = std::chrono::seconds(num_seconds); EventSP event_sp; @@ -176,7 +176,7 @@ bool SBListener::WaitForEventForBroadcasterWithType( LLDB_INSTRUMENT_VA(this, num_seconds, broadcaster, event_type_mask, event); if (m_opaque_sp && broadcaster.IsValid()) { - Timeout<std::micro> timeout(llvm::None); + Timeout<std::micro> timeout(std::nullopt); if (num_seconds != UINT32_MAX) timeout = std::chrono::seconds(num_seconds); EventSP event_sp; diff --git a/contrib/llvm-project/lldb/source/API/SBMemoryRegionInfo.cpp b/contrib/llvm-project/lldb/source/API/SBMemoryRegionInfo.cpp index 23d22fbe86c8..cd25be5d5276 100644 --- a/contrib/llvm-project/lldb/source/API/SBMemoryRegionInfo.cpp +++ b/contrib/llvm-project/lldb/source/API/SBMemoryRegionInfo.cpp @@ -14,6 +14,7 @@ #include "lldb/Target/MemoryRegionInfo.h" #include "lldb/Utility/Instrumentation.h" #include "lldb/Utility/StreamString.h" +#include <optional> using namespace lldb; using namespace lldb_private; @@ -133,10 +134,10 @@ uint32_t SBMemoryRegionInfo::GetNumDirtyPages() { LLDB_INSTRUMENT_VA(this); uint32_t num_dirty_pages = 0; - const llvm::Optional<std::vector<addr_t>> &dirty_page_list = + const std::optional<std::vector<addr_t>> &dirty_page_list = m_opaque_up->GetDirtyPageList(); if (dirty_page_list) - num_dirty_pages = dirty_page_list.value().size(); + num_dirty_pages = dirty_page_list->size(); return num_dirty_pages; } @@ -145,10 +146,10 @@ addr_t SBMemoryRegionInfo::GetDirtyPageAddressAtIndex(uint32_t idx) { LLDB_INSTRUMENT_VA(this, idx); addr_t dirty_page_addr = LLDB_INVALID_ADDRESS; - const llvm::Optional<std::vector<addr_t>> &dirty_page_list = + const std::optional<std::vector<addr_t>> &dirty_page_list = m_opaque_up->GetDirtyPageList(); - if (dirty_page_list && idx < dirty_page_list.value().size()) - dirty_page_addr = dirty_page_list.value()[idx]; + if (dirty_page_list && idx < dirty_page_list->size()) + dirty_page_addr = (*dirty_page_list)[idx]; return dirty_page_addr; } diff --git a/contrib/llvm-project/lldb/source/API/SBModule.cpp b/contrib/llvm-project/lldb/source/API/SBModule.cpp index c4e876eb15de..e7c2b451eb9d 100644 --- a/contrib/llvm-project/lldb/source/API/SBModule.cpp +++ b/contrib/llvm-project/lldb/source/API/SBModule.cpp @@ -436,26 +436,28 @@ lldb::SBValue SBModule::FindFirstGlobalVariable(lldb::SBTarget &target, lldb::SBType SBModule::FindFirstType(const char *name_cstr) { LLDB_INSTRUMENT_VA(this, name_cstr); - SBType sb_type; ModuleSP module_sp(GetSP()); - if (name_cstr && module_sp) { - SymbolContext sc; - const bool exact_match = false; - ConstString name(name_cstr); + if (!name_cstr || !module_sp) + return {}; + SymbolContext sc; + const bool exact_match = false; + ConstString name(name_cstr); - sb_type = SBType(module_sp->FindFirstType(sc, name, exact_match)); + SBType sb_type = SBType(module_sp->FindFirstType(sc, name, exact_match)); - if (!sb_type.IsValid()) { - auto type_system_or_err = - module_sp->GetTypeSystemForLanguage(eLanguageTypeC); - if (auto err = type_system_or_err.takeError()) { - llvm::consumeError(std::move(err)); - return SBType(); - } - sb_type = SBType(type_system_or_err->GetBuiltinTypeByName(name)); - } + if (sb_type.IsValid()) + return sb_type; + + auto type_system_or_err = module_sp->GetTypeSystemForLanguage(eLanguageTypeC); + if (auto err = type_system_or_err.takeError()) { + llvm::consumeError(std::move(err)); + return {}; } - return sb_type; + + if (auto ts = *type_system_or_err) + return SBType(ts->GetBuiltinTypeByName(name)); + + return {}; } lldb::SBType SBModule::GetBasicType(lldb::BasicType type) { @@ -468,7 +470,8 @@ lldb::SBType SBModule::GetBasicType(lldb::BasicType type) { if (auto err = type_system_or_err.takeError()) { llvm::consumeError(std::move(err)); } else { - return SBType(type_system_or_err->GetBasicTypeFromAST(type)); + if (auto ts = *type_system_or_err) + return SBType(ts->GetBasicTypeFromAST(type)); } } return SBType(); @@ -494,10 +497,9 @@ lldb::SBTypeList SBModule::FindTypes(const char *type) { if (auto err = type_system_or_err.takeError()) { llvm::consumeError(std::move(err)); } else { - CompilerType compiler_type = - type_system_or_err->GetBuiltinTypeByName(name); - if (compiler_type) - retval.Append(SBType(compiler_type)); + if (auto ts = *type_system_or_err) + if (CompilerType compiler_type = ts->GetBuiltinTypeByName(name)) + retval.Append(SBType(compiler_type)); } } else { for (size_t idx = 0; idx < type_list.GetSize(); idx++) { diff --git a/contrib/llvm-project/lldb/source/API/SBModuleSpec.cpp b/contrib/llvm-project/lldb/source/API/SBModuleSpec.cpp index 7deba8e971f8..83b1b6b74941 100644 --- a/contrib/llvm-project/lldb/source/API/SBModuleSpec.cpp +++ b/contrib/llvm-project/lldb/source/API/SBModuleSpec.cpp @@ -134,7 +134,7 @@ size_t SBModuleSpec::GetUUIDLength() { bool SBModuleSpec::SetUUIDBytes(const uint8_t *uuid, size_t uuid_len) { LLDB_INSTRUMENT_VA(this, uuid, uuid_len) - m_opaque_up->GetUUID() = UUID::fromOptionalData(uuid, uuid_len); + m_opaque_up->GetUUID() = UUID(uuid, uuid_len); return m_opaque_up->GetUUID().IsValid(); } diff --git a/contrib/llvm-project/lldb/source/API/SBPlatform.cpp b/contrib/llvm-project/lldb/source/API/SBPlatform.cpp index ba18ba6d187f..807d0085c7bc 100644 --- a/contrib/llvm-project/lldb/source/API/SBPlatform.cpp +++ b/contrib/llvm-project/lldb/source/API/SBPlatform.cpp @@ -69,7 +69,7 @@ struct PlatformShellCommand { std::string m_output; int m_status = 0; int m_signo = 0; - Timeout<std::ratio<1>> m_timeout = llvm::None; + Timeout<std::ratio<1>> m_timeout = std::nullopt; }; // SBPlatformConnectOptions SBPlatformConnectOptions::SBPlatformConnectOptions(const char *url) @@ -261,7 +261,7 @@ void SBPlatformShellCommand::SetTimeoutSeconds(uint32_t sec) { LLDB_INSTRUMENT_VA(this, sec); if (sec == UINT32_MAX) - m_opaque_ptr->m_timeout = llvm::None; + m_opaque_ptr->m_timeout = std::nullopt; else m_opaque_ptr->m_timeout = std::chrono::seconds(sec); } @@ -354,7 +354,7 @@ const char *SBPlatform::GetWorkingDirectory() { PlatformSP platform_sp(GetSP()); if (platform_sp) - return platform_sp->GetWorkingDirectory().GetCString(); + return platform_sp->GetWorkingDirectory().GetPathAsConstString().AsCString(); return nullptr; } @@ -547,14 +547,15 @@ SBError SBPlatform::Run(SBPlatformShellCommand &shell_command) { if (!command) return Status("invalid shell command (empty)"); - const char *working_dir = shell_command.GetWorkingDirectory(); - if (working_dir == nullptr) { - working_dir = platform_sp->GetWorkingDirectory().GetCString(); - if (working_dir) - shell_command.SetWorkingDirectory(working_dir); + if (shell_command.GetWorkingDirectory() == nullptr) { + std::string platform_working_dir = + platform_sp->GetWorkingDirectory().GetPath(); + if (!platform_working_dir.empty()) + shell_command.SetWorkingDirectory(platform_working_dir.c_str()); } return platform_sp->RunShellCommand( - shell_command.m_opaque_ptr->m_shell, command, FileSpec(working_dir), + shell_command.m_opaque_ptr->m_shell, command, + FileSpec(shell_command.GetWorkingDirectory()), &shell_command.m_opaque_ptr->m_status, &shell_command.m_opaque_ptr->m_signo, &shell_command.m_opaque_ptr->m_output, diff --git a/contrib/llvm-project/lldb/source/API/SBReproducer.cpp b/contrib/llvm-project/lldb/source/API/SBReproducer.cpp index 7431b49d3ea6..088dd25e3f1f 100644 --- a/contrib/llvm-project/lldb/source/API/SBReproducer.cpp +++ b/contrib/llvm-project/lldb/source/API/SBReproducer.cpp @@ -22,69 +22,49 @@ #include "lldb/API/SBHostOS.h" #include "lldb/Host/FileSystem.h" #include "lldb/Utility/Instrumentation.h" -#include "lldb/Utility/Reproducer.h" -#include "lldb/Utility/ReproducerProvider.h" #include "lldb/Version/Version.h" using namespace lldb; using namespace lldb_private; using namespace lldb_private::repro; -SBReplayOptions::SBReplayOptions() - : m_opaque_up(std::make_unique<ReplayOptions>()){} +SBReplayOptions::SBReplayOptions() {} -SBReplayOptions::SBReplayOptions(const SBReplayOptions &rhs) - : m_opaque_up(std::make_unique<ReplayOptions>(*rhs.m_opaque_up)) {} +SBReplayOptions::SBReplayOptions(const SBReplayOptions &rhs) {} SBReplayOptions::~SBReplayOptions() = default; SBReplayOptions &SBReplayOptions::operator=(const SBReplayOptions &rhs) { LLDB_INSTRUMENT_VA(this, rhs) - if (this == &rhs) - return *this; - *m_opaque_up = *rhs.m_opaque_up; return *this; } void SBReplayOptions::SetVerify(bool verify) { - LLDB_INSTRUMENT_VA(this, verify) m_opaque_up->verify = verify; + LLDB_INSTRUMENT_VA(this, verify); } bool SBReplayOptions::GetVerify() const { - LLDB_INSTRUMENT_VA(this) return m_opaque_up->verify; + LLDB_INSTRUMENT_VA(this); + return false; } void SBReplayOptions::SetCheckVersion(bool check) { - LLDB_INSTRUMENT_VA(this, check) - m_opaque_up->check_version = check; + LLDB_INSTRUMENT_VA(this, check); } bool SBReplayOptions::GetCheckVersion() const { - LLDB_INSTRUMENT_VA(this) - return m_opaque_up->check_version; + LLDB_INSTRUMENT_VA(this); + return false; } const char *SBReproducer::Capture() { LLDB_INSTRUMENT() - static std::string error; - if (auto e = Reproducer::Initialize(ReproducerMode::Capture, llvm::None)) { - error = llvm::toString(std::move(e)); - return error.c_str(); - } - - return nullptr; + return "Reproducer capture has been removed"; } const char *SBReproducer::Capture(const char *path) { LLDB_INSTRUMENT_VA(path) - static std::string error; - if (auto e = - Reproducer::Initialize(ReproducerMode::Capture, FileSpec(path))) { - error = llvm::toString(std::move(e)); - return error.c_str(); - } - - return nullptr; + return "Reproducer capture has been removed"; } const char *SBReproducer::PassiveReplay(const char *path) { @@ -99,13 +79,13 @@ const char *SBReproducer::Replay(const char *path) { const char *SBReproducer::Replay(const char *path, bool skip_version_check) { LLDB_INSTRUMENT_VA(path, skip_version_check) - return Replay(path); + return "Reproducer replay has been removed"; } const char *SBReproducer::Replay(const char *path, const SBReplayOptions &options) { LLDB_INSTRUMENT_VA(path, options) - return Replay(path); + return "Reproducer replay has been removed"; } const char *SBReproducer::Finalize(const char *path) { @@ -115,39 +95,19 @@ const char *SBReproducer::Finalize(const char *path) { bool SBReproducer::Generate() { LLDB_INSTRUMENT() - auto &r = Reproducer::Instance(); - if (auto generator = r.GetGenerator()) { - generator->Keep(); - return true; - } return false; } bool SBReproducer::SetAutoGenerate(bool b) { LLDB_INSTRUMENT_VA(b) - auto &r = Reproducer::Instance(); - if (auto generator = r.GetGenerator()) { - generator->SetAutoGenerate(b); - return true; - } return false; } const char *SBReproducer::GetPath() { LLDB_INSTRUMENT() - ConstString path; - auto &r = Reproducer::Instance(); - if (FileSpec reproducer_path = Reproducer::Instance().GetReproducerPath()) - path = ConstString(r.GetReproducerPath().GetCString()); - return path.GetCString(); + return "Reproducer GetPath has been removed"; } void SBReproducer::SetWorkingDirectory(const char *path) { LLDB_INSTRUMENT_VA(path) - if (auto *g = lldb_private::repro::Reproducer::Instance().GetGenerator()) { - auto &wp = g->GetOrCreate<repro::WorkingDirectoryProvider>(); - wp.SetDirectory(path); - auto &fp = g->GetOrCreate<repro::FileProvider>(); - fp.RecordInterestingDirectory(wp.GetDirectory()); - } } diff --git a/contrib/llvm-project/lldb/source/API/SBSourceManager.cpp b/contrib/llvm-project/lldb/source/API/SBSourceManager.cpp index 7729f5d9d69f..68815026c464 100644 --- a/contrib/llvm-project/lldb/source/API/SBSourceManager.cpp +++ b/contrib/llvm-project/lldb/source/API/SBSourceManager.cpp @@ -88,14 +88,14 @@ SBSourceManager::SBSourceManager(const SBSourceManager &rhs) { if (&rhs == this) return; - m_opaque_up = std::make_unique<SourceManagerImpl>(*(rhs.m_opaque_up.get())); + m_opaque_up = std::make_unique<SourceManagerImpl>(*rhs.m_opaque_up); } const lldb::SBSourceManager &SBSourceManager:: operator=(const lldb::SBSourceManager &rhs) { LLDB_INSTRUMENT_VA(this, rhs); - m_opaque_up = std::make_unique<SourceManagerImpl>(*(rhs.m_opaque_up.get())); + m_opaque_up = std::make_unique<SourceManagerImpl>(*rhs.m_opaque_up); return *this; } diff --git a/contrib/llvm-project/lldb/source/API/SBSymbol.cpp b/contrib/llvm-project/lldb/source/API/SBSymbol.cpp index b671f987dc99..3f940538d124 100644 --- a/contrib/llvm-project/lldb/source/API/SBSymbol.cpp +++ b/contrib/llvm-project/lldb/source/API/SBSymbol.cpp @@ -162,6 +162,20 @@ SBAddress SBSymbol::GetEndAddress() { return addr; } +uint64_t SBSymbol::GetValue() { + LLDB_INSTRUMENT_VA(this); + if (m_opaque_ptr) + return m_opaque_ptr->GetRawValue(); + return 0; +} + +uint64_t SBSymbol::GetSize() { + LLDB_INSTRUMENT_VA(this); + if (m_opaque_ptr && m_opaque_ptr->GetByteSizeIsValid()) + return m_opaque_ptr->GetByteSize(); + return 0; +} + uint32_t SBSymbol::GetPrologueByteSize() { LLDB_INSTRUMENT_VA(this); diff --git a/contrib/llvm-project/lldb/source/API/SBTarget.cpp b/contrib/llvm-project/lldb/source/API/SBTarget.cpp index bf64bb342aaf..cadaeb472e28 100644 --- a/contrib/llvm-project/lldb/source/API/SBTarget.cpp +++ b/contrib/llvm-project/lldb/source/API/SBTarget.cpp @@ -1766,7 +1766,7 @@ lldb::SBType SBTarget::FindFirstType(const char *typename_cstr) { } } - // Didn't find the type in the symbols; Try the loaded language runtimes + // Didn't find the type in the symbols; Try the loaded language runtimes. if (auto process_sp = target_sp->GetProcessSP()) { for (auto *runtime : process_sp->GetLanguageRuntimes()) { if (auto vendor = runtime->GetDeclVendor()) { @@ -1777,9 +1777,9 @@ lldb::SBType SBTarget::FindFirstType(const char *typename_cstr) { } } - // No matches, search for basic typename matches - for (auto *type_system : target_sp->GetScratchTypeSystems()) - if (auto type = type_system->GetBuiltinTypeByName(const_typename)) + // No matches, search for basic typename matches. + for (auto type_system_sp : target_sp->GetScratchTypeSystems()) + if (auto type = type_system_sp->GetBuiltinTypeByName(const_typename)) return SBType(type); } @@ -1791,8 +1791,8 @@ SBType SBTarget::GetBasicType(lldb::BasicType type) { TargetSP target_sp(GetSP()); if (target_sp) { - for (auto *type_system : target_sp->GetScratchTypeSystems()) - if (auto compiler_type = type_system->GetBasicTypeFromAST(type)) + for (auto type_system_sp : target_sp->GetScratchTypeSystems()) + if (auto compiler_type = type_system_sp->GetBasicTypeFromAST(type)) return SBType(compiler_type); } return SBType(); @@ -1832,9 +1832,9 @@ lldb::SBTypeList SBTarget::FindTypes(const char *typename_cstr) { if (sb_type_list.GetSize() == 0) { // No matches, search for basic typename matches - for (auto *type_system : target_sp->GetScratchTypeSystems()) + for (auto type_system_sp : target_sp->GetScratchTypeSystems()) if (auto compiler_type = - type_system->GetBuiltinTypeByName(const_typename)) + type_system_sp->GetBuiltinTypeByName(const_typename)) sb_type_list.Append(SBType(compiler_type)); } } diff --git a/contrib/llvm-project/lldb/source/API/SBThread.cpp b/contrib/llvm-project/lldb/source/API/SBThread.cpp index a08cb741814b..616f047f6888 100644 --- a/contrib/llvm-project/lldb/source/API/SBThread.cpp +++ b/contrib/llvm-project/lldb/source/API/SBThread.cpp @@ -837,7 +837,7 @@ SBError SBThread::StepOverUntil(lldb::SBFrame &sb_frame, const bool stop_other_threads = false; // TODO: Handle SourceLocationSpec column information SourceLocationSpec location_spec( - step_file_spec, line, /*column=*/llvm::None, /*check_inlines=*/true, + step_file_spec, line, /*column=*/std::nullopt, /*check_inlines=*/true, /*exact_match=*/false); SymbolContextList sc_list; diff --git a/contrib/llvm-project/lldb/source/API/SBTrace.cpp b/contrib/llvm-project/lldb/source/API/SBTrace.cpp index 2b1f140161b6..5e9d53e3d186 100644 --- a/contrib/llvm-project/lldb/source/API/SBTrace.cpp +++ b/contrib/llvm-project/lldb/source/API/SBTrace.cpp @@ -43,6 +43,27 @@ SBTrace SBTrace::LoadTraceFromFile(SBError &error, SBDebugger &debugger, return SBTrace(trace_or_err.get()); } +SBTraceCursor SBTrace::CreateNewCursor(SBError &error, SBThread &thread) { + LLDB_INSTRUMENT_VA(this, error, thread); + + if (!m_opaque_sp) { + error.SetErrorString("error: invalid trace"); + return SBTraceCursor(); + } + if (!thread.get()) { + error.SetErrorString("error: invalid thread"); + return SBTraceCursor(); + } + + if (llvm::Expected<lldb::TraceCursorSP> trace_cursor_sp = + m_opaque_sp->CreateNewCursor(*thread.get())) { + return SBTraceCursor(std::move(*trace_cursor_sp)); + } else { + error.SetErrorString(llvm::toString(trace_cursor_sp.takeError()).c_str()); + return SBTraceCursor(); + } +} + SBFileSpec SBTrace::SaveToDisk(SBError &error, const SBFileSpec &bundle_dir, bool compact) { LLDB_INSTRUMENT_VA(this, error, bundle_dir, compact); diff --git a/contrib/llvm-project/lldb/source/API/SBTraceCursor.cpp b/contrib/llvm-project/lldb/source/API/SBTraceCursor.cpp new file mode 100644 index 000000000000..f4ae31f616af --- /dev/null +++ b/contrib/llvm-project/lldb/source/API/SBTraceCursor.cpp @@ -0,0 +1,137 @@ +//===-- SBTraceCursor.cpp +//-------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lldb/API/SBTraceCursor.h" +#include "Utils.h" +#include "lldb/Utility/Instrumentation.h" +#include "lldb/Target/TraceCursor.h" + +using namespace lldb; +using namespace lldb_private; + +SBTraceCursor::SBTraceCursor() { LLDB_INSTRUMENT_VA(this); } + +SBTraceCursor::SBTraceCursor(TraceCursorSP trace_cursor_sp) + : m_opaque_sp{std::move(trace_cursor_sp)} { + LLDB_INSTRUMENT_VA(this, trace_cursor_sp); +} + +void SBTraceCursor::SetForwards(bool forwards) { + LLDB_INSTRUMENT_VA(this, forwards); + + m_opaque_sp->SetForwards(forwards); +} + +bool SBTraceCursor::IsForwards() const { + LLDB_INSTRUMENT_VA(this); + + return m_opaque_sp->IsForwards(); +} + +void SBTraceCursor::Next() { + LLDB_INSTRUMENT_VA(this); + + return m_opaque_sp->Next(); +} + +bool SBTraceCursor::HasValue() const { + LLDB_INSTRUMENT_VA(this); + + return m_opaque_sp->HasValue(); +} + +bool SBTraceCursor::GoToId(lldb::user_id_t id) { + LLDB_INSTRUMENT_VA(this, id); + + return m_opaque_sp->GoToId(id); +} + +bool SBTraceCursor::HasId(lldb::user_id_t id) const { + LLDB_INSTRUMENT_VA(this, id); + + return m_opaque_sp->HasId(id); +} + +lldb::user_id_t SBTraceCursor::GetId() const { + LLDB_INSTRUMENT_VA(this); + + return m_opaque_sp->GetId(); +} + +bool SBTraceCursor::Seek(int64_t offset, lldb::TraceCursorSeekType origin) { + LLDB_INSTRUMENT_VA(this, offset); + + return m_opaque_sp->Seek(offset, origin); +} + +lldb::TraceItemKind SBTraceCursor::GetItemKind() const { + LLDB_INSTRUMENT_VA(this); + + return m_opaque_sp->GetItemKind(); +} + +bool SBTraceCursor::IsError() const { + LLDB_INSTRUMENT_VA(this); + + return m_opaque_sp->IsError(); +} + +const char *SBTraceCursor::GetError() const { + LLDB_INSTRUMENT_VA(this); + + return m_opaque_sp->GetError(); +} + +bool SBTraceCursor::IsEvent() const { + LLDB_INSTRUMENT_VA(this); + + return m_opaque_sp->IsEvent(); +} + +lldb::TraceEvent SBTraceCursor::GetEventType() const { + LLDB_INSTRUMENT_VA(this); + + return m_opaque_sp->GetEventType(); +} + +const char *SBTraceCursor::GetEventTypeAsString() const { + LLDB_INSTRUMENT_VA(this); + + return m_opaque_sp->GetEventTypeAsString(); +} + +bool SBTraceCursor::IsInstruction() const { + LLDB_INSTRUMENT_VA(this); + + return m_opaque_sp->IsInstruction(); +} + +lldb::addr_t SBTraceCursor::GetLoadAddress() const { + LLDB_INSTRUMENT_VA(this); + + return m_opaque_sp->GetLoadAddress(); +} + +lldb::cpu_id_t SBTraceCursor::GetCPU() const { + LLDB_INSTRUMENT_VA(this); + + return m_opaque_sp->GetCPU(); +} + +bool SBTraceCursor::IsValid() const { + LLDB_INSTRUMENT_VA(this); + + return this->operator bool(); +} + +SBTraceCursor::operator bool() const { + LLDB_INSTRUMENT_VA(this); + + return m_opaque_sp.get() != nullptr; +} diff --git a/contrib/llvm-project/lldb/source/API/SBType.cpp b/contrib/llvm-project/lldb/source/API/SBType.cpp index adc60a084367..1ccc3b0c2dc9 100644 --- a/contrib/llvm-project/lldb/source/API/SBType.cpp +++ b/contrib/llvm-project/lldb/source/API/SBType.cpp @@ -22,15 +22,14 @@ #include "llvm/ADT/APSInt.h" #include <memory> +#include <optional> using namespace lldb; using namespace lldb_private; SBType::SBType() { LLDB_INSTRUMENT_VA(this); } -SBType::SBType(const CompilerType &type) - : m_opaque_sp(new TypeImpl( - CompilerType(type.GetTypeSystem(), type.GetOpaqueQualType()))) {} +SBType::SBType(const CompilerType &type) : m_opaque_sp(new TypeImpl(type)) {} SBType::SBType(const lldb::TypeSP &type_sp) : m_opaque_sp(new TypeImpl(type_sp)) {} @@ -122,7 +121,7 @@ uint64_t SBType::GetByteSize() { LLDB_INSTRUMENT_VA(this); if (IsValid()) - if (llvm::Optional<uint64_t> size = + if (std::optional<uint64_t> size = m_opaque_sp->GetCompilerType(false).GetByteSize(nullptr)) return *size; return 0; @@ -364,8 +363,8 @@ SBType SBType::GetBasicType(lldb::BasicType basic_type) { LLDB_INSTRUMENT_VA(this, basic_type); if (IsValid() && m_opaque_sp->IsValid()) - return SBType( - m_opaque_sp->GetTypeSystem(false)->GetBasicTypeFromAST(basic_type)); + if (auto ts = m_opaque_sp->GetTypeSystem(false)) + return SBType(ts->GetBasicTypeFromAST(basic_type)); return SBType(); } @@ -492,7 +491,12 @@ bool SBType::IsTypeComplete() { if (!IsValid()) return false; - return m_opaque_sp->GetCompilerType(false).IsCompleteType(); + CompilerType compiler_type = m_opaque_sp->GetCompilerType(false); + // Only return true if we have a complete type and it wasn't forcefully + // completed. + if (compiler_type.IsCompleteType()) + return !compiler_type.IsForcefullyCompleted(); + return false; } uint32_t SBType::GetTypeFlags() { diff --git a/contrib/llvm-project/lldb/source/API/SBTypeCategory.cpp b/contrib/llvm-project/lldb/source/API/SBTypeCategory.cpp index 7d929fe49795..e2911a4c50f6 100644 --- a/contrib/llvm-project/lldb/source/API/SBTypeCategory.cpp +++ b/contrib/llvm-project/lldb/source/API/SBTypeCategory.cpp @@ -105,8 +105,7 @@ uint32_t SBTypeCategory::GetNumFormats() { if (!IsValid()) return 0; - return m_opaque_sp->GetTypeFormatsContainer()->GetCount() + - m_opaque_sp->GetRegexTypeFormatsContainer()->GetCount(); + return m_opaque_sp->GetNumFormats(); } uint32_t SBTypeCategory::GetNumSummaries() { @@ -114,8 +113,7 @@ uint32_t SBTypeCategory::GetNumSummaries() { if (!IsValid()) return 0; - return m_opaque_sp->GetTypeSummariesContainer()->GetCount() + - m_opaque_sp->GetRegexTypeSummariesContainer()->GetCount(); + return m_opaque_sp->GetNumSummaries(); } uint32_t SBTypeCategory::GetNumFilters() { @@ -123,8 +121,7 @@ uint32_t SBTypeCategory::GetNumFilters() { if (!IsValid()) return 0; - return m_opaque_sp->GetTypeFiltersContainer()->GetCount() + - m_opaque_sp->GetRegexTypeFiltersContainer()->GetCount(); + return m_opaque_sp->GetNumFilters(); } uint32_t SBTypeCategory::GetNumSynthetics() { @@ -132,8 +129,7 @@ uint32_t SBTypeCategory::GetNumSynthetics() { if (!IsValid()) return 0; - return m_opaque_sp->GetTypeSyntheticsContainer()->GetCount() + - m_opaque_sp->GetRegexTypeSyntheticsContainer()->GetCount(); + return m_opaque_sp->GetNumSynthetics(); } lldb::SBTypeNameSpecifier @@ -185,14 +181,8 @@ SBTypeFilter SBTypeCategory::GetFilterForType(SBTypeNameSpecifier spec) { if (!spec.IsValid()) return SBTypeFilter(); - lldb::TypeFilterImplSP children_sp; - - if (spec.IsRegex()) - m_opaque_sp->GetRegexTypeFiltersContainer()->GetExact( - ConstString(spec.GetName()), children_sp); - else - m_opaque_sp->GetTypeFiltersContainer()->GetExact( - ConstString(spec.GetName()), children_sp); + lldb::TypeFilterImplSP children_sp = + m_opaque_sp->GetFilterForType(spec.GetSP()); if (!children_sp) return lldb::SBTypeFilter(); @@ -211,14 +201,8 @@ SBTypeFormat SBTypeCategory::GetFormatForType(SBTypeNameSpecifier spec) { if (!spec.IsValid()) return SBTypeFormat(); - lldb::TypeFormatImplSP format_sp; - - if (spec.IsRegex()) - m_opaque_sp->GetRegexTypeFormatsContainer()->GetExact( - ConstString(spec.GetName()), format_sp); - else - m_opaque_sp->GetTypeFormatsContainer()->GetExact( - ConstString(spec.GetName()), format_sp); + lldb::TypeFormatImplSP format_sp = + m_opaque_sp->GetFormatForType(spec.GetSP()); if (!format_sp) return lldb::SBTypeFormat(); @@ -235,14 +219,8 @@ SBTypeSummary SBTypeCategory::GetSummaryForType(SBTypeNameSpecifier spec) { if (!spec.IsValid()) return SBTypeSummary(); - lldb::TypeSummaryImplSP summary_sp; - - if (spec.IsRegex()) - m_opaque_sp->GetRegexTypeSummariesContainer()->GetExact( - ConstString(spec.GetName()), summary_sp); - else - m_opaque_sp->GetTypeSummariesContainer()->GetExact( - ConstString(spec.GetName()), summary_sp); + lldb::TypeSummaryImplSP summary_sp = + m_opaque_sp->GetSummaryForType(spec.GetSP()); if (!summary_sp) return lldb::SBTypeSummary(); @@ -259,14 +237,8 @@ SBTypeSynthetic SBTypeCategory::GetSyntheticForType(SBTypeNameSpecifier spec) { if (!spec.IsValid()) return SBTypeSynthetic(); - lldb::SyntheticChildrenSP children_sp; - - if (spec.IsRegex()) - m_opaque_sp->GetRegexTypeSyntheticsContainer()->GetExact( - ConstString(spec.GetName()), children_sp); - else - m_opaque_sp->GetTypeSyntheticsContainer()->GetExact( - ConstString(spec.GetName()), children_sp); + lldb::SyntheticChildrenSP children_sp = + m_opaque_sp->GetSyntheticForType(spec.GetSP()); if (!children_sp) return lldb::SBTypeSynthetic(); @@ -340,13 +312,7 @@ bool SBTypeCategory::AddTypeFormat(SBTypeNameSpecifier type_name, if (!format.IsValid()) return false; - if (type_name.IsRegex()) - m_opaque_sp->GetRegexTypeFormatsContainer()->Add( - RegularExpression(type_name.GetName()), format.GetSP()); - else - m_opaque_sp->GetTypeFormatsContainer()->Add( - ConstString(type_name.GetName()), format.GetSP()); - + m_opaque_sp->AddTypeFormat(type_name.GetSP(), format.GetSP()); return true; } @@ -359,12 +325,7 @@ bool SBTypeCategory::DeleteTypeFormat(SBTypeNameSpecifier type_name) { if (!type_name.IsValid()) return false; - if (type_name.IsRegex()) - return m_opaque_sp->GetRegexTypeFormatsContainer()->Delete( - ConstString(type_name.GetName())); - else - return m_opaque_sp->GetTypeFormatsContainer()->Delete( - ConstString(type_name.GetName())); + return m_opaque_sp->DeleteTypeFormat(type_name.GetSP()); } bool SBTypeCategory::AddTypeSummary(SBTypeNameSpecifier type_name, @@ -414,13 +375,7 @@ bool SBTypeCategory::AddTypeSummary(SBTypeNameSpecifier type_name, } } - if (type_name.IsRegex()) - m_opaque_sp->GetRegexTypeSummariesContainer()->Add( - RegularExpression(type_name.GetName()), summary.GetSP()); - else - m_opaque_sp->GetTypeSummariesContainer()->Add( - ConstString(type_name.GetName()), summary.GetSP()); - + m_opaque_sp->AddTypeSummary(type_name.GetSP(), summary.GetSP()); return true; } @@ -433,12 +388,7 @@ bool SBTypeCategory::DeleteTypeSummary(SBTypeNameSpecifier type_name) { if (!type_name.IsValid()) return false; - if (type_name.IsRegex()) - return m_opaque_sp->GetRegexTypeSummariesContainer()->Delete( - ConstString(type_name.GetName())); - else - return m_opaque_sp->GetTypeSummariesContainer()->Delete( - ConstString(type_name.GetName())); + return m_opaque_sp->DeleteTypeSummary(type_name.GetSP()); } bool SBTypeCategory::AddTypeFilter(SBTypeNameSpecifier type_name, @@ -454,13 +404,7 @@ bool SBTypeCategory::AddTypeFilter(SBTypeNameSpecifier type_name, if (!filter.IsValid()) return false; - if (type_name.IsRegex()) - m_opaque_sp->GetRegexTypeFiltersContainer()->Add( - RegularExpression(type_name.GetName()), filter.GetSP()); - else - m_opaque_sp->GetTypeFiltersContainer()->Add( - ConstString(type_name.GetName()), filter.GetSP()); - + m_opaque_sp->AddTypeFilter(type_name.GetSP(), filter.GetSP()); return true; } @@ -473,12 +417,7 @@ bool SBTypeCategory::DeleteTypeFilter(SBTypeNameSpecifier type_name) { if (!type_name.IsValid()) return false; - if (type_name.IsRegex()) - return m_opaque_sp->GetRegexTypeFiltersContainer()->Delete( - ConstString(type_name.GetName())); - else - return m_opaque_sp->GetTypeFiltersContainer()->Delete( - ConstString(type_name.GetName())); + return m_opaque_sp->DeleteTypeFilter(type_name.GetSP()); } bool SBTypeCategory::AddTypeSynthetic(SBTypeNameSpecifier type_name, @@ -528,13 +467,7 @@ bool SBTypeCategory::AddTypeSynthetic(SBTypeNameSpecifier type_name, } } - if (type_name.IsRegex()) - m_opaque_sp->GetRegexTypeSyntheticsContainer()->Add( - RegularExpression(type_name.GetName()), synth.GetSP()); - else - m_opaque_sp->GetTypeSyntheticsContainer()->Add( - ConstString(type_name.GetName()), synth.GetSP()); - + m_opaque_sp->AddTypeSynthetic(type_name.GetSP(), synth.GetSP()); return true; } @@ -547,12 +480,7 @@ bool SBTypeCategory::DeleteTypeSynthetic(SBTypeNameSpecifier type_name) { if (!type_name.IsValid()) return false; - if (type_name.IsRegex()) - return m_opaque_sp->GetRegexTypeSyntheticsContainer()->Delete( - ConstString(type_name.GetName())); - else - return m_opaque_sp->GetTypeSyntheticsContainer()->Delete( - ConstString(type_name.GetName())); + return m_opaque_sp->DeleteTypeSynthetic(type_name.GetSP()); } bool SBTypeCategory::GetDescription(lldb::SBStream &description, diff --git a/contrib/llvm-project/lldb/source/API/SBTypeNameSpecifier.cpp b/contrib/llvm-project/lldb/source/API/SBTypeNameSpecifier.cpp index bc83a1d664d0..8a6eb086a9b1 100644 --- a/contrib/llvm-project/lldb/source/API/SBTypeNameSpecifier.cpp +++ b/contrib/llvm-project/lldb/source/API/SBTypeNameSpecifier.cpp @@ -20,8 +20,15 @@ using namespace lldb_private; SBTypeNameSpecifier::SBTypeNameSpecifier() { LLDB_INSTRUMENT_VA(this); } SBTypeNameSpecifier::SBTypeNameSpecifier(const char *name, bool is_regex) - : m_opaque_sp(new TypeNameSpecifierImpl(name, is_regex)) { + : SBTypeNameSpecifier(name, is_regex ? eFormatterMatchRegex + : eFormatterMatchExact) { LLDB_INSTRUMENT_VA(this, name, is_regex); +} + +SBTypeNameSpecifier::SBTypeNameSpecifier(const char *name, + FormatterMatchType match_type) + : m_opaque_sp(new TypeNameSpecifierImpl(name, match_type)) { + LLDB_INSTRUMENT_VA(this, name, match_type); if (name == nullptr || (*name) == 0) m_opaque_sp.reset(); @@ -72,23 +79,34 @@ SBType SBTypeNameSpecifier::GetType() { return SBType(); } +FormatterMatchType SBTypeNameSpecifier::GetMatchType() { + LLDB_INSTRUMENT_VA(this); + if (!IsValid()) + return eFormatterMatchExact; + return m_opaque_sp->GetMatchType(); +} + bool SBTypeNameSpecifier::IsRegex() { LLDB_INSTRUMENT_VA(this); if (!IsValid()) return false; - return m_opaque_sp->IsRegex(); + return m_opaque_sp->GetMatchType() == eFormatterMatchRegex; } bool SBTypeNameSpecifier::GetDescription( lldb::SBStream &description, lldb::DescriptionLevel description_level) { LLDB_INSTRUMENT_VA(this, description, description_level); + lldb::FormatterMatchType match_type = GetMatchType(); + const char *match_type_str = + (match_type == eFormatterMatchExact ? "plain" + : match_type == eFormatterMatchRegex ? "regex" + : "callback"); if (!IsValid()) return false; - description.Printf("SBTypeNameSpecifier(%s,%s)", GetName(), - IsRegex() ? "regex" : "plain"); + description.Printf("SBTypeNameSpecifier(%s,%s)", GetName(), match_type_str); return true; } @@ -116,7 +134,7 @@ bool SBTypeNameSpecifier::IsEqualTo(lldb::SBTypeNameSpecifier &rhs) { if (!IsValid()) return !rhs.IsValid(); - if (IsRegex() != rhs.IsRegex()) + if (GetMatchType() != rhs.GetMatchType()) return false; if (GetName() == nullptr || rhs.GetName() == nullptr) return false; diff --git a/contrib/llvm-project/lldb/source/API/SBValueList.cpp b/contrib/llvm-project/lldb/source/API/SBValueList.cpp index 4b36b04c8d35..ba7e06971dc3 100644 --- a/contrib/llvm-project/lldb/source/API/SBValueList.cpp +++ b/contrib/llvm-project/lldb/source/API/SBValueList.cpp @@ -7,11 +7,12 @@ //===----------------------------------------------------------------------===// #include "lldb/API/SBValueList.h" +#include "lldb/API/SBError.h" #include "lldb/API/SBStream.h" #include "lldb/API/SBValue.h" #include "lldb/Core/ValueObjectList.h" #include "lldb/Utility/Instrumentation.h" - +#include "lldb/Utility/Status.h" #include <vector> using namespace lldb; @@ -27,6 +28,7 @@ public: if (this == &rhs) return *this; m_values = rhs.m_values; + m_error = rhs.m_error; return *this; } @@ -63,8 +65,13 @@ public: return lldb::SBValue(); } + const Status &GetError() const { return m_error; } + + void SetError(const Status &error) { m_error = error; } + private: std::vector<lldb::SBValue> m_values; + Status m_error; }; SBValueList::SBValueList() { LLDB_INSTRUMENT_VA(this); } @@ -193,3 +200,15 @@ ValueListImpl &SBValueList::ref() { CreateIfNeeded(); return *m_opaque_up; } + +lldb::SBError SBValueList::GetError() { + LLDB_INSTRUMENT_VA(this); + SBError sb_error; + if (m_opaque_up) + sb_error.SetError(m_opaque_up->GetError()); + return sb_error; +} + +void SBValueList::SetError(const lldb_private::Status &status) { + ref().SetError(status); +} diff --git a/contrib/llvm-project/lldb/source/API/SystemInitializerFull.cpp b/contrib/llvm-project/lldb/source/API/SystemInitializerFull.cpp index d662d370f813..521aecf36fd8 100644 --- a/contrib/llvm-project/lldb/source/API/SystemInitializerFull.cpp +++ b/contrib/llvm-project/lldb/source/API/SystemInitializerFull.cpp @@ -15,7 +15,6 @@ #include "lldb/Initialization/SystemInitializerCommon.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Target/ProcessTrace.h" -#include "lldb/Utility/Reproducer.h" #include "lldb/Utility/Timer.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/TargetSelect.h" diff --git a/contrib/llvm-project/lldb/source/Breakpoint/Breakpoint.cpp b/contrib/llvm-project/lldb/source/Breakpoint/Breakpoint.cpp index 578cf14283d9..aad01a2e6fb6 100644 --- a/contrib/llvm-project/lldb/source/Breakpoint/Breakpoint.cpp +++ b/contrib/llvm-project/lldb/source/Breakpoint/Breakpoint.cpp @@ -328,6 +328,11 @@ uint32_t Breakpoint::GetIgnoreCount() const { uint32_t Breakpoint::GetHitCount() const { return m_hit_counter.GetValue(); } +void Breakpoint::ResetHitCount() { + m_hit_counter.Reset(); + m_locations.ResetHitCount(); +} + bool Breakpoint::IsOneShot() const { return m_options.IsOneShot(); } void Breakpoint::SetOneShot(bool one_shot) { m_options.SetOneShot(one_shot); } diff --git a/contrib/llvm-project/lldb/source/Breakpoint/BreakpointID.cpp b/contrib/llvm-project/lldb/source/Breakpoint/BreakpointID.cpp index 245cf7913335..b4a0a22f66c1 100644 --- a/contrib/llvm-project/lldb/source/Breakpoint/BreakpointID.cpp +++ b/contrib/llvm-project/lldb/source/Breakpoint/BreakpointID.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include <cstdio> +#include <optional> #include "lldb/Breakpoint/Breakpoint.h" #include "lldb/Breakpoint/BreakpointID.h" @@ -37,7 +38,7 @@ bool BreakpointID::IsValidIDExpression(llvm::StringRef str) { } llvm::ArrayRef<llvm::StringRef> BreakpointID::GetRangeSpecifiers() { - return llvm::makeArrayRef(g_range_specifiers); + return llvm::ArrayRef(g_range_specifiers); } void BreakpointID::GetDescription(Stream *s, lldb::DescriptionLevel level) { @@ -62,27 +63,27 @@ void BreakpointID::GetCanonicalReference(Stream *s, break_id_t bp_id, s->Printf("%i.%i", bp_id, loc_id); } -llvm::Optional<BreakpointID> +std::optional<BreakpointID> BreakpointID::ParseCanonicalReference(llvm::StringRef input) { break_id_t bp_id; break_id_t loc_id = LLDB_INVALID_BREAK_ID; if (input.empty()) - return llvm::None; + return std::nullopt; // If it doesn't start with an integer, it's not valid. if (input.consumeInteger(0, bp_id)) - return llvm::None; + return std::nullopt; // period is optional, but if it exists, it must be followed by a number. if (input.consume_front(".")) { if (input.consumeInteger(0, loc_id)) - return llvm::None; + return std::nullopt; } // And at the end, the entire string must have been consumed. if (!input.empty()) - return llvm::None; + return std::nullopt; return BreakpointID(bp_id, loc_id); } diff --git a/contrib/llvm-project/lldb/source/Breakpoint/BreakpointList.cpp b/contrib/llvm-project/lldb/source/Breakpoint/BreakpointList.cpp index f4d4b2edbf08..f7c2cdb938e6 100644 --- a/contrib/llvm-project/lldb/source/Breakpoint/BreakpointList.cpp +++ b/contrib/llvm-project/lldb/source/Breakpoint/BreakpointList.cpp @@ -186,6 +186,12 @@ void BreakpointList::ClearAllBreakpointSites() { bp_sp->ClearAllBreakpointSites(); } +void BreakpointList::ResetHitCounts() { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + for (const auto &bp_sp : m_breakpoints) + bp_sp->ResetHitCount(); +} + void BreakpointList::GetListMutex( std::unique_lock<std::recursive_mutex> &lock) { lock = std::unique_lock<std::recursive_mutex>(m_mutex); diff --git a/contrib/llvm-project/lldb/source/Breakpoint/BreakpointLocationList.cpp b/contrib/llvm-project/lldb/source/Breakpoint/BreakpointLocationList.cpp index 46f66276d28d..e0f1b9b2c808 100644 --- a/contrib/llvm-project/lldb/source/Breakpoint/BreakpointLocationList.cpp +++ b/contrib/llvm-project/lldb/source/Breakpoint/BreakpointLocationList.cpp @@ -69,7 +69,7 @@ BreakpointLocationList::FindByID(lldb::break_id_t break_id) const { std::lock_guard<std::recursive_mutex> guard(m_mutex); collection::const_iterator end = m_locations.end(); collection::const_iterator pos = - std::lower_bound(m_locations.begin(), end, break_id, Compare); + llvm::lower_bound(m_locations, break_id, Compare); if (pos != end && (*pos)->GetID() == break_id) return *(pos); else @@ -176,6 +176,12 @@ uint32_t BreakpointLocationList::GetHitCount() const { return hit_count; } +void BreakpointLocationList::ResetHitCount() { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + for (auto &loc : m_locations) + loc->ResetHitCount(); +} + size_t BreakpointLocationList::GetNumResolvedLocations() const { std::lock_guard<std::recursive_mutex> guard(m_mutex); size_t resolve_count = 0; diff --git a/contrib/llvm-project/lldb/source/Breakpoint/BreakpointOptions.cpp b/contrib/llvm-project/lldb/source/Breakpoint/BreakpointOptions.cpp index 6fc6948aaccc..31779fbf693a 100644 --- a/contrib/llvm-project/lldb/source/Breakpoint/BreakpointOptions.cpp +++ b/contrib/llvm-project/lldb/source/Breakpoint/BreakpointOptions.cpp @@ -115,7 +115,8 @@ BreakpointOptions::BreakpointOptions(bool all_flags_set) : m_callback(BreakpointOptions::NullCallback), m_baton_is_command_baton(false), m_callback_is_synchronous(false), m_enabled(true), m_one_shot(false), m_ignore_count(0), - m_condition_text_hash(0), m_auto_continue(false), m_set_flags(0) { + m_condition_text_hash(0), m_inject_condition(false), + m_auto_continue(false), m_set_flags(0) { if (all_flags_set) m_set_flags.Set(~((Flags::ValueType)0)); } @@ -125,11 +126,9 @@ BreakpointOptions::BreakpointOptions(const char *condition, bool enabled, bool auto_continue) : m_callback(nullptr), m_baton_is_command_baton(false), m_callback_is_synchronous(false), m_enabled(enabled), - m_one_shot(one_shot), m_ignore_count(ignore), - m_condition_text_hash(0), m_auto_continue(auto_continue) -{ - m_set_flags.Set(eEnabled | eIgnoreCount | eOneShot - | eAutoContinue); + m_one_shot(one_shot), m_ignore_count(ignore), m_condition_text_hash(0), + m_inject_condition(false), m_auto_continue(auto_continue) { + m_set_flags.Set(eEnabled | eIgnoreCount | eOneShot | eAutoContinue); if (condition && *condition != '\0') { SetCondition(condition); } @@ -141,8 +140,8 @@ BreakpointOptions::BreakpointOptions(const BreakpointOptions &rhs) m_baton_is_command_baton(rhs.m_baton_is_command_baton), m_callback_is_synchronous(rhs.m_callback_is_synchronous), m_enabled(rhs.m_enabled), m_one_shot(rhs.m_one_shot), - m_ignore_count(rhs.m_ignore_count), m_auto_continue(rhs.m_auto_continue), - m_set_flags(rhs.m_set_flags) { + m_ignore_count(rhs.m_ignore_count), m_inject_condition(false), + m_auto_continue(rhs.m_auto_continue), m_set_flags(rhs.m_set_flags) { if (rhs.m_thread_spec_up != nullptr) m_thread_spec_up = std::make_unique<ThreadSpec>(*rhs.m_thread_spec_up); m_condition_text = rhs.m_condition_text; @@ -163,6 +162,7 @@ operator=(const BreakpointOptions &rhs) { m_thread_spec_up = std::make_unique<ThreadSpec>(*rhs.m_thread_spec_up); m_condition_text = rhs.m_condition_text; m_condition_text_hash = rhs.m_condition_text_hash; + m_inject_condition = rhs.m_inject_condition; m_auto_continue = rhs.m_auto_continue; m_set_flags = rhs.m_set_flags; return *this; diff --git a/contrib/llvm-project/lldb/source/Breakpoint/BreakpointResolver.cpp b/contrib/llvm-project/lldb/source/Breakpoint/BreakpointResolver.cpp index 71cbb2b2c666..5c03798a7427 100644 --- a/contrib/llvm-project/lldb/source/Breakpoint/BreakpointResolver.cpp +++ b/contrib/llvm-project/lldb/source/Breakpoint/BreakpointResolver.cpp @@ -28,6 +28,7 @@ #include "lldb/Utility/Log.h" #include "lldb/Utility/Stream.h" #include "lldb/Utility/StreamString.h" +#include <optional> using namespace lldb_private; using namespace lldb; @@ -180,7 +181,7 @@ namespace { struct SourceLoc { uint32_t line = UINT32_MAX; uint16_t column; - SourceLoc(uint32_t l, llvm::Optional<uint16_t> c) + SourceLoc(uint32_t l, std::optional<uint16_t> c) : line(l), column(c ? *c : LLDB_INVALID_COLUMN_NUMBER) {} SourceLoc(const SymbolContext &sc) : line(sc.line_entry.line), @@ -201,7 +202,7 @@ bool operator<(const SourceLoc lhs, const SourceLoc rhs) { void BreakpointResolver::SetSCMatchesByLine( SearchFilter &filter, SymbolContextList &sc_list, bool skip_prologue, - llvm::StringRef log_ident, uint32_t line, llvm::Optional<uint16_t> column) { + llvm::StringRef log_ident, uint32_t line, std::optional<uint16_t> column) { llvm::SmallVector<SymbolContext, 16> all_scs; for (uint32_t i = 0; i < sc_list.GetSize(); ++i) all_scs.push_back(sc_list[i]); diff --git a/contrib/llvm-project/lldb/source/Breakpoint/BreakpointResolverFileLine.cpp b/contrib/llvm-project/lldb/source/Breakpoint/BreakpointResolverFileLine.cpp index ff044526799c..890b38af5c88 100644 --- a/contrib/llvm-project/lldb/source/Breakpoint/BreakpointResolverFileLine.cpp +++ b/contrib/llvm-project/lldb/source/Breakpoint/BreakpointResolverFileLine.cpp @@ -12,9 +12,11 @@ #include "lldb/Core/Module.h" #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/Function.h" +#include "lldb/Target/Target.h" #include "lldb/Utility/LLDBLog.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/StreamString.h" +#include <optional> using namespace lldb; using namespace lldb_private; @@ -22,9 +24,11 @@ using namespace lldb_private; // BreakpointResolverFileLine: BreakpointResolverFileLine::BreakpointResolverFileLine( const BreakpointSP &bkpt, lldb::addr_t offset, bool skip_prologue, - const SourceLocationSpec &location_spec) + const SourceLocationSpec &location_spec, + std::optional<llvm::StringRef> removed_prefix_opt) : BreakpointResolver(bkpt, BreakpointResolver::FileLineResolver, offset), - m_location_spec(location_spec), m_skip_prologue(skip_prologue) {} + m_location_spec(location_spec), m_skip_prologue(skip_prologue), + m_removed_prefix_opt(removed_prefix_opt) {} BreakpointResolver *BreakpointResolverFileLine::CreateFromStructuredData( const BreakpointSP &bkpt, const StructuredData::Dictionary &options_dict, @@ -119,34 +123,14 @@ BreakpointResolverFileLine::SerializeToStructuredData() { // handling inlined functions -- in this case we need to make sure we look at // the declaration line of the inlined function, NOT the function it was // inlined into. -void BreakpointResolverFileLine::FilterContexts(SymbolContextList &sc_list, - bool is_relative) { +void BreakpointResolverFileLine::FilterContexts(SymbolContextList &sc_list) { if (m_location_spec.GetExactMatch()) return; // Nothing to do. Contexts are precise. - llvm::StringRef relative_path; - if (is_relative) - relative_path = m_location_spec.GetFileSpec().GetDirectory().GetStringRef(); - Log *log = GetLog(LLDBLog::Breakpoints); for(uint32_t i = 0; i < sc_list.GetSize(); ++i) { SymbolContext sc; sc_list.GetContextAtIndex(i, sc); - if (is_relative) { - // If the path was relative, make sure any matches match as long as the - // relative parts of the path match the path from support files - auto sc_dir = sc.line_entry.file.GetDirectory().GetStringRef(); - if (!sc_dir.endswith(relative_path)) { - // We had a relative path specified and the relative directory doesn't - // match so remove this one - LLDB_LOG(log, "removing not matching relative path {0} since it " - "doesn't end with {1}", sc_dir, relative_path); - sc_list.RemoveContextAtIndex(i); - --i; - continue; - } - } - if (!sc.block) continue; @@ -207,6 +191,85 @@ void BreakpointResolverFileLine::FilterContexts(SymbolContextList &sc_list, } } +void BreakpointResolverFileLine::DeduceSourceMapping( + SymbolContextList &sc_list) { + Target &target = GetBreakpoint()->GetTarget(); + if (!target.GetAutoSourceMapRelative()) + return; + + Log *log = GetLog(LLDBLog::Breakpoints); + const llvm::StringRef path_separator = llvm::sys::path::get_separator( + m_location_spec.GetFileSpec().GetPathStyle()); + // Check if "b" is a suffix of "a". + // And return std::nullopt if not or the new path + // of "a" after consuming "b" from the back. + auto check_suffix = + [path_separator](llvm::StringRef a, llvm::StringRef b, + bool case_sensitive) -> std::optional<llvm::StringRef> { + if (case_sensitive ? a.consume_back(b) : a.consume_back_insensitive(b)) { + if (a.empty() || a.endswith(path_separator)) { + return a; + } + } + return std::nullopt; + }; + + FileSpec request_file = m_location_spec.GetFileSpec(); + + // Only auto deduce source map if breakpoint is full path. + // Note: an existing source map reverse mapping (m_removed_prefix_opt has + // value) may make request_file relative. + if (!m_removed_prefix_opt.has_value() && request_file.IsRelative()) + return; + + const bool case_sensitive = request_file.IsCaseSensitive(); + for (uint32_t i = 0; i < sc_list.GetSize(); ++i) { + SymbolContext sc; + sc_list.GetContextAtIndex(i, sc); + + FileSpec sc_file = sc.line_entry.file; + + if (FileSpec::Equal(sc_file, request_file, /*full*/true)) + continue; + + llvm::StringRef sc_file_dir = sc_file.GetDirectory().GetStringRef(); + llvm::StringRef request_file_dir = + request_file.GetDirectory().GetStringRef(); + + llvm::StringRef new_mapping_from; + llvm::SmallString<256> new_mapping_to; + + // Adding back any potentially reverse mapping stripped prefix. + // for new_mapping_to. + if (m_removed_prefix_opt.has_value()) + llvm::sys::path::append(new_mapping_to, *m_removed_prefix_opt); + + std::optional<llvm::StringRef> new_mapping_from_opt = + check_suffix(sc_file_dir, request_file_dir, case_sensitive); + if (new_mapping_from_opt) { + new_mapping_from = *new_mapping_from_opt; + if (new_mapping_to.empty()) + new_mapping_to = "."; + } else { + std::optional<llvm::StringRef> new_mapping_to_opt = + check_suffix(request_file_dir, sc_file_dir, case_sensitive); + if (new_mapping_to_opt) { + new_mapping_from = "."; + llvm::sys::path::append(new_mapping_to, *new_mapping_to_opt); + } + } + + if (!new_mapping_from.empty() && !new_mapping_to.empty()) { + LLDB_LOG(log, "generating auto source map from {0} to {1}", + new_mapping_from, new_mapping_to); + if (target.GetSourcePathMap().AppendUnique(new_mapping_from, + new_mapping_to, + /*notify*/ true)) + target.GetStatistics().IncreaseSourceMapDeduceCount(); + } + } +} + Searcher::CallbackReturn BreakpointResolverFileLine::SearchCallback( SearchFilter &filter, SymbolContext &context, Address *addr) { SymbolContextList sc_list; @@ -228,31 +291,21 @@ Searcher::CallbackReturn BreakpointResolverFileLine::SearchCallback( // same file spec in their line_entry and treat each set separately. const uint32_t line = m_location_spec.GetLine().value_or(0); - const llvm::Optional<uint16_t> column = m_location_spec.GetColumn(); - - // We'll create a new SourceLocationSpec that can take into account the - // relative path case, and we'll use it to resolve the symbol context - // of the CUs. - FileSpec search_file_spec = m_location_spec.GetFileSpec(); - const bool is_relative = search_file_spec.IsRelative(); - if (is_relative) - search_file_spec.GetDirectory().Clear(); - SourceLocationSpec search_location_spec( - search_file_spec, m_location_spec.GetLine().value_or(0), - m_location_spec.GetColumn(), m_location_spec.GetCheckInlines(), - m_location_spec.GetExactMatch()); + const std::optional<uint16_t> column = m_location_spec.GetColumn(); const size_t num_comp_units = context.module_sp->GetNumCompileUnits(); for (size_t i = 0; i < num_comp_units; i++) { CompUnitSP cu_sp(context.module_sp->GetCompileUnitAtIndex(i)); if (cu_sp) { if (filter.CompUnitPasses(*cu_sp)) - cu_sp->ResolveSymbolContext(search_location_spec, - eSymbolContextEverything, sc_list); + cu_sp->ResolveSymbolContext(m_location_spec, eSymbolContextEverything, + sc_list); } } - FilterContexts(sc_list, is_relative); + FilterContexts(sc_list); + + DeduceSourceMapping(sc_list); StreamString s; s.Printf("for %s:%d ", diff --git a/contrib/llvm-project/lldb/source/Breakpoint/BreakpointResolverFileRegex.cpp b/contrib/llvm-project/lldb/source/Breakpoint/BreakpointResolverFileRegex.cpp index 4a11d82ecc6e..cb3ee5fb7427 100644 --- a/contrib/llvm-project/lldb/source/Breakpoint/BreakpointResolverFileRegex.cpp +++ b/contrib/llvm-project/lldb/source/Breakpoint/BreakpointResolverFileRegex.cpp @@ -109,7 +109,7 @@ Searcher::CallbackReturn BreakpointResolverFileRegex::SearchCallback( SymbolContextList sc_list; // TODO: Handle SourceLocationSpec column information SourceLocationSpec location_spec(cu_file_spec, line_matches[i], - /*column=*/llvm::None, + /*column=*/std::nullopt, /*check_inlines=*/false, m_exact_match); cu->ResolveSymbolContext(location_spec, eSymbolContextEverything, sc_list); // Find all the function names: diff --git a/contrib/llvm-project/lldb/source/Breakpoint/BreakpointResolverName.cpp b/contrib/llvm-project/lldb/source/Breakpoint/BreakpointResolverName.cpp index 24e36f35bef0..dbaeec9c9afb 100644 --- a/contrib/llvm-project/lldb/source/Breakpoint/BreakpointResolverName.cpp +++ b/contrib/llvm-project/lldb/source/Breakpoint/BreakpointResolverName.cpp @@ -274,9 +274,8 @@ BreakpointResolverName::SearchCallback(SearchFilter &filter, if (context.module_sp) { for (const auto &lookup : m_lookups) { const size_t start_func_idx = func_list.GetSize(); - context.module_sp->FindFunctions( - lookup.GetLookupName(), CompilerDeclContext(), - lookup.GetNameTypeMask(), function_options, func_list); + context.module_sp->FindFunctions(lookup, CompilerDeclContext(), + function_options, func_list); const size_t end_func_idx = func_list.GetSize(); diff --git a/contrib/llvm-project/lldb/source/Breakpoint/Watchpoint.cpp b/contrib/llvm-project/lldb/source/Breakpoint/Watchpoint.cpp index 933661ad7b15..0ad3498dac54 100644 --- a/contrib/llvm-project/lldb/source/Breakpoint/Watchpoint.cpp +++ b/contrib/llvm-project/lldb/source/Breakpoint/Watchpoint.cpp @@ -43,8 +43,12 @@ Watchpoint::Watchpoint(Target &target, lldb::addr_t addr, uint32_t size, LLDB_LOG_ERROR(GetLog(LLDBLog::Watchpoints), std::move(err), "Failed to set type."); } else { - m_type = type_system_or_err->GetBuiltinTypeForEncodingAndBitSize( - eEncodingUint, 8 * size); + if (auto ts = *type_system_or_err) + m_type = + ts->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 8 * size); + else + LLDB_LOG_ERROR(GetLog(LLDBLog::Watchpoints), std::move(err), + "Failed to set type. Typesystem is no longer live."); } } diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectBreakpoint.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectBreakpoint.cpp index 5d2141d767cb..8c31630231b5 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectBreakpoint.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectBreakpoint.cpp @@ -30,6 +30,7 @@ #include "lldb/Utility/StreamString.h" #include <memory> +#include <optional> #include <vector> using namespace lldb; @@ -55,7 +56,7 @@ public: ~BreakpointOptionGroup() override = default; llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_breakpoint_modify_options); + return llvm::ArrayRef(g_breakpoint_modify_options); } Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, @@ -110,24 +111,24 @@ public: } break; case 't': { lldb::tid_t thread_id = LLDB_INVALID_THREAD_ID; - if (option_arg[0] != '\0') { - if (option_arg == "current") { - if (!execution_context) { - error.SetErrorStringWithFormat("No context to determine current " - "thread"); + if (option_arg == "current") { + if (!execution_context) { + error.SetErrorStringWithFormat("No context to determine current " + "thread"); + } else { + ThreadSP ctx_thread_sp = execution_context->GetThreadSP(); + if (!ctx_thread_sp || !ctx_thread_sp->IsValid()) { + error.SetErrorStringWithFormat("No currently selected thread"); } else { - ThreadSP ctx_thread_sp = execution_context->GetThreadSP(); - if (!ctx_thread_sp || !ctx_thread_sp->IsValid()) { - error.SetErrorStringWithFormat("No currently selected thread"); - } else { - thread_id = ctx_thread_sp->GetID(); - } + thread_id = ctx_thread_sp->GetID(); } - } else if (option_arg.getAsInteger(0, thread_id)) - error.SetErrorStringWithFormat("invalid thread id string '%s'", - option_arg.str().c_str()); + } + } else if (option_arg.getAsInteger(0, thread_id)) { + error.SetErrorStringWithFormat("invalid thread id string '%s'", + option_arg.str().c_str()); } - m_bp_opts.SetThreadID(thread_id); + if (thread_id != LLDB_INVALID_THREAD_ID) + m_bp_opts.SetThreadID(thread_id); } break; case 'T': m_bp_opts.GetThreadSpec()->SetName(option_arg.str().c_str()); @@ -137,12 +138,12 @@ public: break; case 'x': { uint32_t thread_index = UINT32_MAX; - if (option_arg[0] != '\n') { - if (option_arg.getAsInteger(0, thread_index)) - error.SetErrorStringWithFormat("invalid thread index string '%s'", - option_arg.str().c_str()); + if (option_arg.getAsInteger(0, thread_index)) { + error.SetErrorStringWithFormat("invalid thread index string '%s'", + option_arg.str().c_str()); + } else { + m_bp_opts.GetThreadSpec()->SetIndex(thread_index); } - m_bp_opts.GetThreadSpec()->SetIndex(thread_index); } break; default: llvm_unreachable("Unimplemented option"); @@ -185,7 +186,7 @@ public: ~BreakpointDummyOptionGroup() override = default; llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_breakpoint_dummy_options); + return llvm::ArrayRef(g_breakpoint_dummy_options); } Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, @@ -496,7 +497,7 @@ public: } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_breakpoint_set_options); + return llvm::ArrayRef(g_breakpoint_set_options); } // Instance variables to hold the values for command options. @@ -1158,7 +1159,7 @@ public: } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_breakpoint_list_options); + return llvm::ArrayRef(g_breakpoint_list_options); } // Instance variables to hold the values for command options. @@ -1281,7 +1282,7 @@ public: } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_breakpoint_clear_options); + return llvm::ArrayRef(g_breakpoint_clear_options); } // Instance variables to hold the values for command options. @@ -1438,7 +1439,7 @@ public: } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_breakpoint_delete_options); + return llvm::ArrayRef(g_breakpoint_delete_options); } // Instance variables to hold the values for command options. @@ -1564,7 +1565,7 @@ public: ~BreakpointNameOptionGroup() override = default; llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_breakpoint_name_options); + return llvm::ArrayRef(g_breakpoint_name_options); } Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, @@ -1624,7 +1625,7 @@ public: ~BreakpointAccessOptionGroup() override = default; llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_breakpoint_access_options); + return llvm::ArrayRef(g_breakpoint_access_options); } Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, ExecutionContext *execution_context) override { @@ -2187,7 +2188,7 @@ public: } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_breakpoint_read_options); + return llvm::ArrayRef(g_breakpoint_read_options); } void HandleOptionArgumentCompletion( @@ -2204,7 +2205,7 @@ public: break; case 'N': - llvm::Optional<FileSpec> file_spec; + std::optional<FileSpec> file_spec; const llvm::StringRef dash_f("-f"); for (int arg_idx = 0; arg_idx < opt_arg_pos; arg_idx++) { if (dash_f == request.GetParsedLine().GetArgumentAtIndex(arg_idx)) { @@ -2376,7 +2377,7 @@ public: } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_breakpoint_write_options); + return llvm::ArrayRef(g_breakpoint_write_options); } // Instance variables to hold the values for command options. diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectBreakpointCommand.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectBreakpointCommand.cpp index 499bc550af45..921243829fc6 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectBreakpointCommand.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectBreakpointCommand.cpp @@ -317,7 +317,7 @@ are no syntax errors may indicate that a function was declared but never called. } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_breakpoint_command_add_options); + return llvm::ArrayRef(g_breakpoint_command_add_options); } // Instance variables to hold the values for command options. @@ -498,7 +498,7 @@ public: } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_breakpoint_command_delete_options); + return llvm::ArrayRef(g_breakpoint_command_delete_options); } // Instance variables to hold the values for command options. diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectCommands.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectCommands.cpp index 97a883314917..7a5755d8d235 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectCommands.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectCommands.cpp @@ -24,6 +24,7 @@ #include "lldb/Utility/Args.h" #include "lldb/Utility/StringList.h" #include "llvm/ADT/StringRef.h" +#include <optional> using namespace lldb; using namespace lldb_private; @@ -57,8 +58,8 @@ public: ~CommandObjectCommandsSource() override = default; - llvm::Optional<std::string> GetRepeatCommand(Args ¤t_command_args, - uint32_t index) override { + std::optional<std::string> GetRepeatCommand(Args ¤t_command_args, + uint32_t index) override { return std::string(""); } @@ -118,7 +119,7 @@ protected: } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_source_options); + return llvm::ArrayRef(g_source_options); } // Instance variables to hold the values for command options. @@ -201,7 +202,7 @@ protected: static const char *g_python_command_instructions = "Enter your Python command(s). Type 'DONE' to end.\n" "You must define a Python function with this signature:\n" - "def my_command_impl(debugger, args, result, internal_dict):\n"; + "def my_command_impl(debugger, args, exe_ctx, result, internal_dict):\n"; class CommandObjectCommandsAlias : public CommandObjectRaw { protected: @@ -212,7 +213,7 @@ protected: ~CommandOptions() override = default; llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_alias_options); + return llvm::ArrayRef(g_alias_options); } Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value, @@ -485,29 +486,31 @@ protected: OptionArgVectorSP(new OptionArgVector); const bool include_aliases = true; - if (CommandObjectSP cmd_obj_sp = m_interpreter.GetCommandSPExact( - cmd_obj.GetCommandName(), include_aliases)) { - if (m_interpreter.AliasExists(alias_command) || - m_interpreter.UserCommandExists(alias_command)) { - result.AppendWarningWithFormat( - "Overwriting existing definition for '%s'.\n", - alias_command.str().c_str()); - } - if (CommandAlias *alias = m_interpreter.AddAlias( - alias_command, cmd_obj_sp, raw_command_string)) { - if (m_command_options.m_help.OptionWasSet()) - alias->SetHelp(m_command_options.m_help.GetCurrentValue()); - if (m_command_options.m_long_help.OptionWasSet()) - alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue()); - result.SetStatus(eReturnStatusSuccessFinishNoResult); - } else { - result.AppendError("Unable to create requested alias.\n"); - } + // Look up the command using command's name first. This is to resolve + // aliases when you are making nested aliases. But if you don't find + // it that way, then it wasn't an alias and we can just use the object + // we were passed in. + CommandObjectSP cmd_obj_sp = m_interpreter.GetCommandSPExact( + cmd_obj.GetCommandName(), include_aliases); + if (!cmd_obj_sp) + cmd_obj_sp = cmd_obj.shared_from_this(); + if (m_interpreter.AliasExists(alias_command) || + m_interpreter.UserCommandExists(alias_command)) { + result.AppendWarningWithFormat( + "Overwriting existing definition for '%s'.\n", + alias_command.str().c_str()); + } + if (CommandAlias *alias = m_interpreter.AddAlias( + alias_command, cmd_obj_sp, raw_command_string)) { + if (m_command_options.m_help.OptionWasSet()) + alias->SetHelp(m_command_options.m_help.GetCurrentValue()); + if (m_command_options.m_long_help.OptionWasSet()) + alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue()); + result.SetStatus(eReturnStatusSuccessFinishNoResult); } else { result.AppendError("Unable to create requested alias.\n"); } - return result.Succeeded(); } @@ -891,7 +894,7 @@ protected: llvm::StringRef(), // Continuation prompt multiple_lines, color_prompt, 0, // Don't show line numbers - *this, nullptr)); + *this)); if (io_handler_sp) { debugger.RunIOHandlerAsync(io_handler_sp); @@ -1054,7 +1057,7 @@ private: } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_regex_options); + return llvm::ArrayRef(g_regex_options); } llvm::StringRef GetHelp() { return m_help; } @@ -1301,7 +1304,7 @@ protected: } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_script_import_options); + return llvm::ArrayRef(g_script_import_options); } bool relative_to_command_file = false; bool silent = false; @@ -1452,7 +1455,7 @@ protected: } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_script_add_options); + return llvm::ArrayRef(g_script_add_options); } // Instance variables to hold the values for command options. @@ -1895,7 +1898,7 @@ protected: } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_container_add_options); + return llvm::ArrayRef(g_container_add_options); } // Instance variables to hold the values for command options. diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectDWIMPrint.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectDWIMPrint.cpp new file mode 100644 index 000000000000..e15e723de588 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectDWIMPrint.cpp @@ -0,0 +1,80 @@ +//===-- CommandObjectDWIMPrint.cpp ------------------------------*- 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 +// +//===----------------------------------------------------------------------===// + +#include "CommandObjectDWIMPrint.h" + +#include "lldb/Core/ValueObject.h" +#include "lldb/Interpreter/CommandInterpreter.h" +#include "lldb/Interpreter/CommandObject.h" +#include "lldb/Interpreter/CommandReturnObject.h" +#include "lldb/Target/StackFrame.h" +#include "lldb/Utility/ConstString.h" +#include "lldb/lldb-enumerations.h" +#include "lldb/lldb-forward.h" + +using namespace llvm; +using namespace lldb; +using namespace lldb_private; + +CommandObjectDWIMPrint::CommandObjectDWIMPrint(CommandInterpreter &interpreter) + : CommandObjectRaw(interpreter, "dwim-print", + "Print a variable or expression.", + "dwim-print [<variable-name> | <expression>]", + eCommandProcessMustBePaused | eCommandTryTargetAPILock) { +} + +bool CommandObjectDWIMPrint::DoExecute(StringRef expr, + CommandReturnObject &result) { + // Ignore leading and trailing whitespace. + expr = expr.trim(); + + if (expr.empty()) { + result.AppendErrorWithFormatv("'{0}' takes a variable or expression", + m_cmd_name); + return false; + } + + auto verbosity = GetDebugger().GetDWIMPrintVerbosity(); + + // First, try `expr` as the name of a frame variable. + if (StackFrame *frame = m_exe_ctx.GetFramePtr()) { + auto valobj_sp = frame->FindVariable(ConstString(expr)); + if (valobj_sp && valobj_sp->GetError().Success()) { + if (verbosity == eDWIMPrintVerbosityFull) + result.AppendMessageWithFormatv("note: ran `frame variable {0}`", expr); + valobj_sp->Dump(result.GetOutputStream()); + result.SetStatus(eReturnStatusSuccessFinishResult); + return true; + } + } + + // Second, also lastly, try `expr` as a source expression to evaluate. + { + Target *target_ptr = m_exe_ctx.GetTargetPtr(); + // Fallback to the dummy target, which can allow for expression evaluation. + Target &target = target_ptr ? *target_ptr : GetDummyTarget(); + + auto *exe_scope = m_exe_ctx.GetBestExecutionContextScope(); + ValueObjectSP valobj_sp; + if (target.EvaluateExpression(expr, exe_scope, valobj_sp) == + eExpressionCompleted) { + if (verbosity != eDWIMPrintVerbosityNone) + result.AppendMessageWithFormatv("note: ran `expression -- {0}`", expr); + valobj_sp->Dump(result.GetOutputStream()); + result.SetStatus(eReturnStatusSuccessFinishResult); + return true; + } else { + if (valobj_sp) + result.SetError(valobj_sp->GetError()); + else + result.AppendErrorWithFormatv( + "unknown error evaluating expression `{0}`", expr); + return false; + } + } +} diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectDWIMPrint.h b/contrib/llvm-project/lldb/source/Commands/CommandObjectDWIMPrint.h new file mode 100644 index 000000000000..1284949aed3a --- /dev/null +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectDWIMPrint.h @@ -0,0 +1,40 @@ +//===-- CommandObjectDWIMPrint.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_SOURCE_COMMANDS_COMMANDOBJECTDWIMPRINT_H +#define LLDB_SOURCE_COMMANDS_COMMANDOBJECTDWIMPRINT_H + +#include "lldb/Interpreter/CommandObject.h" + +namespace lldb_private { + +/// Implements `dwim-print`, a printing command that chooses the most direct, +/// efficient, and resilient means of printing a given expression. +/// +/// DWIM is an acronym for Do What I Mean. From Wikipedia, DWIM is described as: +/// +/// > attempt to anticipate what users intend to do, correcting trivial errors +/// > automatically rather than blindly executing users' explicit but +/// > potentially incorrect input +/// +/// The `dwim-print` command serves as a single print command for users who +/// don't yet know, or perfer not to know, the various lldb commands that can be +/// used to print, and when to use them. +class CommandObjectDWIMPrint : public CommandObjectRaw { +public: + CommandObjectDWIMPrint(CommandInterpreter &interpreter); + + ~CommandObjectDWIMPrint() override = default; + +private: + bool DoExecute(llvm::StringRef command, CommandReturnObject &result) override; +}; + +} // namespace lldb_private + +#endif diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectDiagnostics.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectDiagnostics.cpp new file mode 100644 index 000000000000..dfde50a236ab --- /dev/null +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectDiagnostics.cpp @@ -0,0 +1,114 @@ +//===-- CommandObjectDiagnostics.cpp --------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "CommandObjectDiagnostics.h" +#include "lldb/Host/OptionParser.h" +#include "lldb/Interpreter/CommandOptionArgumentTable.h" +#include "lldb/Interpreter/CommandReturnObject.h" +#include "lldb/Interpreter/OptionArgParser.h" +#include "lldb/Interpreter/OptionValueEnumeration.h" +#include "lldb/Interpreter/OptionValueUInt64.h" +#include "lldb/Interpreter/Options.h" +#include "lldb/Utility/Diagnostics.h" + +using namespace lldb; +using namespace lldb_private; + +#define LLDB_OPTIONS_diagnostics_dump +#include "CommandOptions.inc" + +class CommandObjectDiagnosticsDump : public CommandObjectParsed { +public: + // Constructors and Destructors + CommandObjectDiagnosticsDump(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "diagnostics dump", + "Dump diagnostics to disk", nullptr) {} + + ~CommandObjectDiagnosticsDump() override = default; + + class CommandOptions : public Options { + public: + CommandOptions() = default; + + ~CommandOptions() override = default; + + Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, + ExecutionContext *execution_context) override { + Status error; + const int short_option = m_getopt_table[option_idx].val; + + switch (short_option) { + case 'd': + directory.SetDirectory(option_arg); + break; + default: + llvm_unreachable("Unimplemented option"); + } + return error; + } + + void OptionParsingStarting(ExecutionContext *execution_context) override { + directory.Clear(); + } + + llvm::ArrayRef<OptionDefinition> GetDefinitions() override { + return llvm::ArrayRef(g_diagnostics_dump_options); + } + + FileSpec directory; + }; + + Options *GetOptions() override { return &m_options; } + +protected: + llvm::Expected<FileSpec> GetDirectory() { + if (m_options.directory) { + auto ec = + llvm::sys::fs::create_directories(m_options.directory.GetPath()); + if (ec) + return llvm::errorCodeToError(ec); + return m_options.directory; + } + return Diagnostics::CreateUniqueDirectory(); + } + + bool DoExecute(Args &args, CommandReturnObject &result) override { + llvm::Expected<FileSpec> directory = GetDirectory(); + + if (!directory) { + result.AppendError(llvm::toString(directory.takeError())); + return result.Succeeded(); + } + + llvm::Error error = Diagnostics::Instance().Create(*directory); + if (error) { + result.AppendErrorWithFormat("failed to write diagnostics to %s", + directory->GetPath().c_str()); + result.AppendError(llvm::toString(std::move(error))); + return result.Succeeded(); + } + + result.GetOutputStream() << "diagnostics written to " << *directory << '\n'; + + result.SetStatus(eReturnStatusSuccessFinishResult); + return result.Succeeded(); + } + + CommandOptions m_options; +}; + +CommandObjectDiagnostics::CommandObjectDiagnostics( + CommandInterpreter &interpreter) + : CommandObjectMultiword(interpreter, "diagnostics", + "Commands controlling LLDB diagnostics.", + "diagnostics <subcommand> [<command-options>]") { + LoadSubCommand( + "dump", CommandObjectSP(new CommandObjectDiagnosticsDump(interpreter))); +} + +CommandObjectDiagnostics::~CommandObjectDiagnostics() = default; diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectDiagnostics.h b/contrib/llvm-project/lldb/source/Commands/CommandObjectDiagnostics.h new file mode 100644 index 000000000000..d28282b85023 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectDiagnostics.h @@ -0,0 +1,29 @@ +//===-- CommandObjectDiagnostics.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_SOURCE_COMMANDS_COMMANDOBJECTDIAGNOSTICS_H +#define LLDB_SOURCE_COMMANDS_COMMANDOBJECTDIAGNOSTICS_H + +#include "lldb/Interpreter/CommandObjectMultiword.h" + +namespace lldb_private { + +class CommandObjectDiagnostics : public CommandObjectMultiword { +public: + CommandObjectDiagnostics(CommandInterpreter &interpreter); + ~CommandObjectDiagnostics() override; + +private: + CommandObjectDiagnostics(const CommandObjectDiagnostics &) = delete; + const CommandObjectDiagnostics & + operator=(const CommandObjectDiagnostics &) = delete; +}; + +} // namespace lldb_private + +#endif // LLDB_SOURCE_COMMANDS_COMMANDOBJECTDIAGNOSTICS_H diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectDisassemble.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectDisassemble.cpp index e65e12fe557a..6f78fc9f6287 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectDisassemble.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectDisassemble.cpp @@ -204,7 +204,7 @@ Status CommandObjectDisassemble::CommandOptions::OptionParsingFinished( llvm::ArrayRef<OptionDefinition> CommandObjectDisassemble::CommandOptions::GetDefinitions() { - return llvm::makeArrayRef(g_disassemble_options); + return llvm::ArrayRef(g_disassemble_options); } // CommandObjectDisassemble diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectExpression.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectExpression.cpp index 083309121b66..9cce009f853e 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectExpression.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectExpression.cpp @@ -42,10 +42,15 @@ Status CommandObjectExpression::CommandOptions::SetOptionValue( switch (short_option) { case 'l': language = Language::GetLanguageTypeFromString(option_arg); - if (language == eLanguageTypeUnknown) - error.SetErrorStringWithFormat( - "unknown language type: '%s' for expression", - option_arg.str().c_str()); + if (language == eLanguageTypeUnknown) { + StreamString sstr; + sstr.Printf("unknown language type: '%s' for expression. " + "List of supported languages:\n", + option_arg.str().c_str()); + + Language::PrintSupportedLanguagesForExpressions(sstr, " ", "\n"); + error.SetErrorString(sstr.GetString()); + } break; case 'a': { @@ -172,7 +177,7 @@ void CommandObjectExpression::CommandOptions::OptionParsingStarting( llvm::ArrayRef<OptionDefinition> CommandObjectExpression::CommandOptions::GetDefinitions() { - return llvm::makeArrayRef(g_expression_options); + return llvm::ArrayRef(g_expression_options); } CommandObjectExpression::CommandObjectExpression( @@ -374,7 +379,7 @@ CommandObjectExpression::GetEvalOptions(const Target &target) { if (m_command_options.timeout > 0) options.SetTimeout(std::chrono::microseconds(m_command_options.timeout)); else - options.SetTimeout(llvm::None); + options.SetTimeout(std::nullopt); return options; } @@ -461,6 +466,8 @@ bool CommandObjectExpression::EvaluateExpression(llvm::StringRef expr, result.SetStatus(eReturnStatusFailed); } } + } else { + error_stream.Printf("error: unknown error\n"); } return (success != eExpressionSetupError && @@ -509,7 +516,7 @@ void CommandObjectExpression::GetMultilineExpression() { llvm::StringRef(), // Continuation prompt multiple_lines, color_prompt, 1, // Show line numbers starting at 1 - *this, nullptr)); + *this)); StreamFileSP output_sp = io_handler_sp->GetOutputStreamFileSP(); if (output_sp) { @@ -538,7 +545,7 @@ GetExprOptions(ExecutionContext &ctx, if (command_options.timeout > 0) expr_options.SetTimeout(std::chrono::microseconds(command_options.timeout)); else - expr_options.SetTimeout(llvm::None); + expr_options.SetTimeout(std::nullopt); return expr_options; } diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectFrame.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectFrame.cpp index 23954dd3c9fd..4a0d75202797 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectFrame.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectFrame.cpp @@ -32,6 +32,7 @@ #include "lldb/Utility/Args.h" #include <memory> +#include <optional> #include <string> using namespace lldb; @@ -95,13 +96,13 @@ public: } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_frame_diag_options); + return llvm::ArrayRef(g_frame_diag_options); } // Options. - llvm::Optional<lldb::addr_t> address; - llvm::Optional<ConstString> reg; - llvm::Optional<int64_t> offset; + std::optional<lldb::addr_t> address; + std::optional<ConstString> reg; + std::optional<int64_t> offset; }; CommandObjectFrameDiagnose(CommandInterpreter &interpreter) @@ -144,10 +145,10 @@ protected: "`frame diagnose --address` is incompatible with other arguments."); return false; } - valobj_sp = frame_sp->GuessValueForAddress(m_options.address.value()); + valobj_sp = frame_sp->GuessValueForAddress(*m_options.address); } else if (m_options.reg) { valobj_sp = frame_sp->GuessValueForRegisterAndOffset( - m_options.reg.value(), m_options.offset.value_or(0)); + *m_options.reg, m_options.offset.value_or(0)); } else { StopInfoSP stop_info_sp = thread->GetStopInfo(); if (!stop_info_sp) { @@ -253,10 +254,10 @@ public: } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_frame_select_options); + return llvm::ArrayRef(g_frame_select_options); } - llvm::Optional<int32_t> relative_frame_offset; + std::optional<int32_t> relative_frame_offset; }; CommandObjectFrameSelect(CommandInterpreter &interpreter) @@ -483,9 +484,14 @@ protected: // might clear the StackFrameList for the thread. So hold onto a shared // pointer to the frame so it stays alive. + Status error; VariableList *variable_list = - frame->GetVariableList(m_option_variable.show_globals); + frame->GetVariableList(m_option_variable.show_globals, &error); + if (error.Fail() && (!variable_list || variable_list->GetSize() == 0)) { + result.AppendError(error.AsCString()); + + } VariableSP var_sp; ValueObjectSP valobj_sp; @@ -772,7 +778,7 @@ private: } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_frame_recognizer_add_options); + return llvm::ArrayRef(g_frame_recognizer_add_options); } // Instance variables to hold the values for command options. @@ -814,7 +820,8 @@ functions 'read', 'write' and 'close' follows: def get_recognized_arguments(self, frame): if frame.name in ["read", "write", "close"]: fd = frame.EvaluateExpression("$arg1").unsigned - value = lldb.target.CreateValueFromExpression("fd", "(int)%d" % fd) + target = frame.thread.process.target + value = target.CreateValueFromExpression("fd", "(int)%d" % fd) return [value] return [] diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectHelp.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectHelp.cpp index c7a3bce1408b..10aa49ae01ba 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectHelp.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectHelp.cpp @@ -71,7 +71,7 @@ CommandObjectHelp::~CommandObjectHelp() = default; llvm::ArrayRef<OptionDefinition> CommandObjectHelp::CommandOptions::GetDefinitions() { - return llvm::makeArrayRef(g_help_options); + return llvm::ArrayRef(g_help_options); } bool CommandObjectHelp::DoExecute(Args &command, CommandReturnObject &result) { diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectLog.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectLog.cpp index 89bc3e0f1b7d..c63d8ce4f9e4 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectLog.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectLog.cpp @@ -146,7 +146,7 @@ public: } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_log_enable_options); + return llvm::ArrayRef(g_log_enable_options); } FileSpec log_file; @@ -371,7 +371,7 @@ public: } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_log_dump_options); + return llvm::ArrayRef(g_log_dump_options); } FileSpec log_file; @@ -401,7 +401,7 @@ protected: m_options.log_file, flags, lldb::eFilePermissionsFileDefault, false); if (!file) { result.AppendErrorWithFormat("Unable to open log file '%s': %s", - m_options.log_file.GetCString(), + m_options.log_file.GetPath().c_str(), llvm::toString(file.takeError()).c_str()); return false; } diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectMemory.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectMemory.cpp index 5051f9aeec85..6606f4564dc8 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectMemory.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectMemory.cpp @@ -39,6 +39,7 @@ #include "llvm/Support/MathExtras.h" #include <cinttypes> #include <memory> +#include <optional> using namespace lldb; using namespace lldb_private; @@ -55,7 +56,7 @@ public: ~OptionGroupReadMemory() override = default; llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_memory_read_options); + return llvm::ArrayRef(g_memory_read_options); } Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value, @@ -341,8 +342,8 @@ public: Options *GetOptions() override { return &m_option_group; } - llvm::Optional<std::string> GetRepeatCommand(Args ¤t_command_args, - uint32_t index) override { + std::optional<std::string> GetRepeatCommand(Args ¤t_command_args, + uint32_t index) override { return m_cmd_name; } @@ -427,7 +428,7 @@ protected: switch (type_str[type_str.size() - 1]) { case '*': ++pointer_count; - LLVM_FALLTHROUGH; + [[fallthrough]]; case ' ': case '\t': type_str.erase(type_str.size() - 1); @@ -476,7 +477,7 @@ protected: for (auto lang : languages_to_check) { if (auto *persistent_vars = target->GetPersistentExpressionStateForLanguage(lang)) { - if (llvm::Optional<CompilerType> type = + if (std::optional<CompilerType> type = persistent_vars->GetCompilerTypeFromPersistentDecl( lookup_type_name)) { user_defined_types.emplace(*type); @@ -521,7 +522,7 @@ protected: --pointer_count; } - llvm::Optional<uint64_t> size = compiler_type.GetByteSize(nullptr); + std::optional<uint64_t> size = compiler_type.GetByteSize(nullptr); if (!size) { result.AppendErrorWithFormat( "unable to get the byte size of the type '%s'\n", @@ -650,7 +651,7 @@ protected: if (!m_format_options.GetFormatValue().OptionWasSet()) m_format_options.GetFormatValue().SetCurrentValue(eFormatDefault); - llvm::Optional<uint64_t> size = compiler_type.GetByteSize(nullptr); + std::optional<uint64_t> size = compiler_type.GetByteSize(nullptr); if (!size) { result.AppendError("can't get size of type"); return false; @@ -903,7 +904,7 @@ public: ~OptionGroupFindMemory() override = default; llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_memory_find_options); + return llvm::ArrayRef(g_memory_find_options); } Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value, @@ -1075,7 +1076,7 @@ protected: m_memory_options.m_expr.GetStringValue(), frame, result_sp)) && result_sp) { uint64_t value = result_sp->GetValueAsUnsigned(0); - llvm::Optional<uint64_t> size = + std::optional<uint64_t> size = result_sp->GetCompilerType().GetByteSize(nullptr); if (!size) return false; @@ -1206,7 +1207,7 @@ public: ~OptionGroupWriteMemory() override = default; llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_memory_write_options); + return llvm::ArrayRef(g_memory_write_options); } Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value, @@ -1600,8 +1601,8 @@ public: ~CommandObjectMemoryHistory() override = default; - llvm::Optional<std::string> GetRepeatCommand(Args ¤t_command_args, - uint32_t index) override { + std::optional<std::string> GetRepeatCommand(Args ¤t_command_args, + uint32_t index) override { return m_cmd_name; } @@ -1664,7 +1665,7 @@ public: ~OptionGroupMemoryRegion() override = default; llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_memory_region_options); + return llvm::ArrayRef(g_memory_region_options); } Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value, @@ -1736,10 +1737,10 @@ protected: if (memory_tagged == MemoryRegionInfo::OptionalBool::eYes) result.AppendMessage("memory tagging: enabled"); - const llvm::Optional<std::vector<addr_t>> &dirty_page_list = + const std::optional<std::vector<addr_t>> &dirty_page_list = range_info.GetDirtyPageList(); if (dirty_page_list) { - const size_t page_count = dirty_page_list.value().size(); + const size_t page_count = dirty_page_list->size(); result.AppendMessageWithFormat( "Modified memory (dirty) page list provided, %zu entries.\n", page_count); @@ -1821,7 +1822,7 @@ protected: // When there are non-address bits the last range will not extend // to LLDB_INVALID_ADDRESS but to the max virtual address. // This prevents us looping forever if that is the case. - (abi && (abi->FixAnyAddress(addr) == addr))) { + (!abi || (abi->FixAnyAddress(addr) == addr))) { lldb_private::MemoryRegionInfo region_info; error = process_sp->GetMemoryRegionInfo(addr, region_info); @@ -1830,9 +1831,6 @@ protected: addr = region_info.GetRange().GetRangeEnd(); } } - - // Even if we read nothing, don't error for --all - error.Clear(); } else { lldb_private::MemoryRegionInfo region_info; error = process_sp->GetMemoryRegionInfo(load_addr, region_info); @@ -1854,8 +1852,8 @@ protected: return false; } - llvm::Optional<std::string> GetRepeatCommand(Args ¤t_command_args, - uint32_t index) override { + std::optional<std::string> GetRepeatCommand(Args ¤t_command_args, + uint32_t index) override { // If we repeat this command, repeat it without any arguments so we can // show the next memory range return m_cmd_name; diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectMemoryTag.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectMemoryTag.cpp index 98ab6201711d..fd0fd2919c95 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectMemoryTag.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectMemoryTag.cpp @@ -144,7 +144,7 @@ public: ~OptionGroupTagWrite() override = default; llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_memory_tag_write_options); + return llvm::ArrayRef(g_memory_tag_write_options); } Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value, diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectMultiword.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectMultiword.cpp index e4fdb7365e72..bae2717ffe68 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectMultiword.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectMultiword.cpp @@ -10,6 +10,7 @@ #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Interpreter/Options.h" +#include <optional> using namespace lldb; using namespace lldb_private; @@ -173,11 +174,6 @@ bool CommandObjectMultiword::Execute(const char *args_string, return result.Succeeded(); } - if (sub_command.equals_insensitive("help")) { - this->CommandObject::GenerateHelpText(result); - return result.Succeeded(); - } - if (m_subcommand_dict.empty()) { result.AppendErrorWithFormat("'%s' does not have any subcommands.\n", GetCommandName().str().c_str()); @@ -290,16 +286,16 @@ void CommandObjectMultiword::HandleCompletion(CompletionRequest &request) { sub_command_object->HandleCompletion(request); } -llvm::Optional<std::string> +std::optional<std::string> CommandObjectMultiword::GetRepeatCommand(Args ¤t_command_args, uint32_t index) { index++; if (current_command_args.GetArgumentCount() <= index) - return llvm::None; + return std::nullopt; CommandObject *sub_command_object = GetSubcommandObject(current_command_args[index].ref()); if (sub_command_object == nullptr) - return llvm::None; + return std::nullopt; return sub_command_object->GetRepeatCommand(current_command_args, index); } @@ -420,13 +416,13 @@ void CommandObjectProxy::HandleArgumentCompletion( proxy_command->HandleArgumentCompletion(request, opt_element_vector); } -llvm::Optional<std::string> +std::optional<std::string> CommandObjectProxy::GetRepeatCommand(Args ¤t_command_args, uint32_t index) { CommandObject *proxy_command = GetProxyCommandObject(); if (proxy_command) return proxy_command->GetRepeatCommand(current_command_args, index); - return llvm::None; + return std::nullopt; } llvm::StringRef CommandObjectProxy::GetUnsupportedError() { diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectPlatform.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectPlatform.cpp index 98c6a3b2dd30..1ab218fa6fb2 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectPlatform.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectPlatform.cpp @@ -126,7 +126,7 @@ public: } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_permissions_options); + return llvm::ArrayRef(g_permissions_options); } // Instance variables to hold the values for command options. @@ -379,8 +379,7 @@ class CommandObjectPlatformSettings : public CommandObjectParsed { public: CommandObjectPlatformSettings(CommandInterpreter &interpreter) : CommandObjectParsed(interpreter, "platform settings", - "Set settings for the current target's platform, " - "or for a platform by name.", + "Set settings for the current target's platform.", "platform settings", 0), m_option_working_dir(LLDB_OPT_SET_1, false, "working-dir", 'w', CommandCompletions::eRemoteDiskDirectoryCompletion, @@ -456,12 +455,13 @@ public: Options *GetOptions() override { if (!m_options.DidFinalize()) { - m_options.Append(new OptionPermissions()); + m_options.Append(&m_option_permissions); m_options.Finalize(); } return &m_options; } + OptionPermissions m_option_permissions; OptionGroupOptions m_options; }; @@ -519,12 +519,13 @@ public: Options *GetOptions() override { if (!m_options.DidFinalize()) { - m_options.Append(new OptionPermissions()); + m_options.Append(&m_option_permissions); m_options.Finalize(); } return &m_options; } + OptionPermissions m_option_permissions; OptionGroupOptions m_options; }; @@ -651,7 +652,7 @@ protected: } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_platform_fread_options); + return llvm::ArrayRef(g_platform_fread_options); } // Instance variables to hold the values for command options. @@ -744,7 +745,7 @@ protected: } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_platform_fwrite_options); + return llvm::ArrayRef(g_platform_fwrite_options); } // Instance variables to hold the values for command options. @@ -1466,7 +1467,7 @@ protected: } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_platform_process_list_options); + return llvm::ArrayRef(g_platform_process_list_options); } // Instance variables to hold the values for command options. @@ -1620,7 +1621,7 @@ public: } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_platform_process_attach_options); + return llvm::ArrayRef(g_platform_process_attach_options); } // Options table: Required for subclasses of Options. @@ -1706,7 +1707,7 @@ public: ~CommandOptions() override = default; llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_platform_shell_options); + return llvm::ArrayRef(g_platform_shell_options); } Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectProcess.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectProcess.cpp index 28a99ea3d94a..a45371f824b1 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectProcess.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectProcess.cpp @@ -36,6 +36,7 @@ #include "llvm/ADT/ScopeExit.h" #include <bitset> +#include <optional> using namespace lldb; using namespace lldb_private; @@ -151,8 +152,8 @@ public: Options *GetOptions() override { return &m_all_options; } - llvm::Optional<std::string> GetRepeatCommand(Args ¤t_command_args, - uint32_t index) override { + std::optional<std::string> GetRepeatCommand(Args ¤t_command_args, + uint32_t index) override { // No repeat for "process launch"... return std::string(""); } @@ -360,7 +361,7 @@ public: } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_process_attach_options); + return llvm::ArrayRef(g_process_attach_options); } ProcessAttachInfo attach_info; @@ -543,7 +544,7 @@ protected: } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_process_continue_options); + return llvm::ArrayRef(g_process_continue_options); } uint32_t m_ignore = 0; @@ -837,7 +838,7 @@ public: } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_process_detach_options); + return llvm::ArrayRef(g_process_detach_options); } // Instance variables to hold the values for command options. @@ -920,7 +921,7 @@ public: } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_process_connect_options); + return llvm::ArrayRef(g_process_connect_options); } // Instance variables to hold the values for command options. @@ -1045,7 +1046,7 @@ public: } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_process_load_options); + return llvm::ArrayRef(g_process_load_options); } // Instance variables to hold the values for command options. @@ -1361,7 +1362,7 @@ public: ~CommandOptions() override = default; llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_process_save_core_options); + return llvm::ArrayRef(g_process_save_core_options); } Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, @@ -1483,7 +1484,7 @@ public: } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_process_status_options); + return llvm::ArrayRef(g_process_status_options); } // Instance variables to hold the values for command options. @@ -1537,8 +1538,9 @@ protected: StructuredData::DictionarySP crash_info_sp = *expected_crash_info; if (crash_info_sp) { + strm.EOL(); strm.PutCString("Extended Crash Information:\n"); - crash_info_sp->Dump(strm); + crash_info_sp->GetDescription(strm); } } @@ -1603,7 +1605,7 @@ public: } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_process_handle_options); + return llvm::ArrayRef(g_process_handle_options); } // Instance variables to hold the values for command options. diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectRegister.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectRegister.cpp index 56cbacbebec5..c61a1f6e865a 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectRegister.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectRegister.cpp @@ -94,7 +94,8 @@ public: bool prefix_with_altname = (bool)m_command_options.alternate_name; bool prefix_with_name = !prefix_with_altname; DumpRegisterValue(reg_value, &strm, reg_info, prefix_with_name, - prefix_with_altname, m_format_options.GetFormat(), 8); + prefix_with_altname, m_format_options.GetFormat(), 8, + exe_ctx.GetBestExecutionContextScope()); if ((reg_info->encoding == eEncodingUint) || (reg_info->encoding == eEncodingSint)) { Process *process = exe_ctx.GetProcessPtr(); @@ -239,7 +240,7 @@ protected: ~CommandOptions() override = default; llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_register_read_options); + return llvm::ArrayRef(g_register_read_options); } void OptionParsingStarting(ExecutionContext *execution_context) override { diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectReproducer.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectReproducer.cpp deleted file mode 100644 index 6160a83b4d09..000000000000 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectReproducer.cpp +++ /dev/null @@ -1,503 +0,0 @@ -//===-- CommandObjectReproducer.cpp ---------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "CommandObjectReproducer.h" - -#include "lldb/Host/HostInfo.h" -#include "lldb/Host/OptionParser.h" -#include "lldb/Interpreter/CommandInterpreter.h" -#include "lldb/Interpreter/CommandOptionArgumentTable.h" -#include "lldb/Interpreter/CommandReturnObject.h" -#include "lldb/Interpreter/OptionArgParser.h" -#include "lldb/Utility/GDBRemote.h" -#include "lldb/Utility/ProcessInfo.h" -#include "lldb/Utility/Reproducer.h" - -#include <csignal> - -using namespace lldb; -using namespace llvm; -using namespace lldb_private; -using namespace lldb_private::repro; - -#define LLDB_OPTIONS_reproducer_dump -#include "CommandOptions.inc" - -#define LLDB_OPTIONS_reproducer_xcrash -#include "CommandOptions.inc" - -#define LLDB_OPTIONS_reproducer_verify -#include "CommandOptions.inc" - -template <typename T> -llvm::Expected<T> static ReadFromYAML(StringRef filename) { - auto error_or_file = MemoryBuffer::getFile(filename); - if (auto err = error_or_file.getError()) { - return errorCodeToError(err); - } - - T t; - yaml::Input yin((*error_or_file)->getBuffer()); - yin >> t; - - if (auto err = yin.error()) { - return errorCodeToError(err); - } - - return t; -} - -static void SetError(CommandReturnObject &result, Error err) { - result.AppendError(toString(std::move(err))); -} - -/// Create a loader from the given path if specified. Otherwise use the current -/// loader used for replay. -static Loader * -GetLoaderFromPathOrCurrent(llvm::Optional<Loader> &loader_storage, - CommandReturnObject &result, - FileSpec reproducer_path) { - if (reproducer_path) { - loader_storage.emplace(reproducer_path); - Loader *loader = &(*loader_storage); - if (Error err = loader->LoadIndex()) { - // This is a hard error and will set the result to eReturnStatusFailed. - SetError(result, std::move(err)); - return nullptr; - } - return loader; - } - - if (Loader *loader = Reproducer::Instance().GetLoader()) - return loader; - - // This is a soft error because this is expected to fail during capture. - result.AppendError( - "Not specifying a reproducer is only support during replay."); - result.SetStatus(eReturnStatusSuccessFinishNoResult); - return nullptr; -} - -class CommandObjectReproducerGenerate : public CommandObjectParsed { -public: - CommandObjectReproducerGenerate(CommandInterpreter &interpreter) - : CommandObjectParsed( - interpreter, "reproducer generate", - "Generate reproducer on disk. When the debugger is in capture " - "mode, this command will output the reproducer to a directory on " - "disk and quit. In replay mode this command in a no-op.", - nullptr) {} - - ~CommandObjectReproducerGenerate() override = default; - -protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { - auto &r = Reproducer::Instance(); - if (auto generator = r.GetGenerator()) { - generator->Keep(); - } else { - result.AppendErrorWithFormat("Unable to get the reproducer generator"); - return false; - } - - result.GetOutputStream() - << "Reproducer written to '" << r.GetReproducerPath() << "'\n"; - result.GetOutputStream() - << "Please have a look at the directory to assess if you're willing to " - "share the contained information.\n"; - - m_interpreter.BroadcastEvent( - CommandInterpreter::eBroadcastBitQuitCommandReceived); - result.SetStatus(eReturnStatusQuit); - return result.Succeeded(); - } -}; - -class CommandObjectReproducerXCrash : public CommandObjectParsed { -public: - CommandObjectReproducerXCrash(CommandInterpreter &interpreter) - : CommandObjectParsed(interpreter, "reproducer xcrash", - "Intentionally force the debugger to crash in " - "order to trigger and test reproducer generation.", - nullptr) {} - - ~CommandObjectReproducerXCrash() override = default; - - Options *GetOptions() override { return &m_options; } - - class CommandOptions : public Options { - public: - CommandOptions() = default; - - ~CommandOptions() override = default; - - Status SetOptionValue(uint32_t option_idx, StringRef option_arg, - ExecutionContext *execution_context) override { - Status error; - const int short_option = m_getopt_table[option_idx].val; - - switch (short_option) { - case 's': - signal = (ReproducerCrashSignal)OptionArgParser::ToOptionEnum( - option_arg, GetDefinitions()[option_idx].enum_values, 0, error); - if (!error.Success()) - error.SetErrorStringWithFormat("unrecognized value for signal '%s'", - option_arg.str().c_str()); - break; - default: - llvm_unreachable("Unimplemented option"); - } - - return error; - } - - void OptionParsingStarting(ExecutionContext *execution_context) override { - signal = eReproducerCrashSigsegv; - } - - ArrayRef<OptionDefinition> GetDefinitions() override { - return makeArrayRef(g_reproducer_xcrash_options); - } - - ReproducerCrashSignal signal = eReproducerCrashSigsegv; - }; - -protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { - auto &r = Reproducer::Instance(); - - if (!r.IsCapturing()) { - result.AppendError( - "forcing a crash is only supported when capturing a reproducer."); - result.SetStatus(eReturnStatusSuccessFinishNoResult); - return false; - } - - switch (m_options.signal) { - case eReproducerCrashSigill: - std::raise(SIGILL); - break; - case eReproducerCrashSigsegv: - std::raise(SIGSEGV); - break; - } - - result.SetStatus(eReturnStatusQuit); - return result.Succeeded(); - } - -private: - CommandOptions m_options; -}; - -class CommandObjectReproducerStatus : public CommandObjectParsed { -public: - CommandObjectReproducerStatus(CommandInterpreter &interpreter) - : CommandObjectParsed( - interpreter, "reproducer status", - "Show the current reproducer status. In capture mode the " - "debugger " - "is collecting all the information it needs to create a " - "reproducer. In replay mode the reproducer is replaying a " - "reproducer. When the reproducers are off, no data is collected " - "and no reproducer can be generated.", - nullptr) {} - - ~CommandObjectReproducerStatus() override = default; - -protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { - auto &r = Reproducer::Instance(); - if (r.IsCapturing()) { - result.GetOutputStream() << "Reproducer is in capture mode.\n"; - result.GetOutputStream() - << "Path: " << r.GetReproducerPath().GetPath() << '\n'; - } else { - result.GetOutputStream() << "Reproducer is off.\n"; - } - - // Auto generate is hidden unless enabled because this is mostly for - // development and testing. - if (Generator *g = r.GetGenerator()) { - if (g->IsAutoGenerate()) - result.GetOutputStream() << "Auto generate: on\n"; - } - - result.SetStatus(eReturnStatusSuccessFinishResult); - return result.Succeeded(); - } -}; - -class CommandObjectReproducerDump : public CommandObjectParsed { -public: - CommandObjectReproducerDump(CommandInterpreter &interpreter) - : CommandObjectParsed(interpreter, "reproducer dump", - "Dump the information contained in a reproducer. " - "If no reproducer is specified during replay, it " - "dumps the content of the current reproducer.", - nullptr) {} - - ~CommandObjectReproducerDump() override = default; - - Options *GetOptions() override { return &m_options; } - - class CommandOptions : public Options { - public: - CommandOptions() = default; - - ~CommandOptions() override = default; - - Status SetOptionValue(uint32_t option_idx, StringRef option_arg, - ExecutionContext *execution_context) override { - Status error; - const int short_option = m_getopt_table[option_idx].val; - - switch (short_option) { - case 'f': - file.SetFile(option_arg, FileSpec::Style::native); - FileSystem::Instance().Resolve(file); - break; - case 'p': - provider = (ReproducerProvider)OptionArgParser::ToOptionEnum( - option_arg, GetDefinitions()[option_idx].enum_values, 0, error); - if (!error.Success()) - error.SetErrorStringWithFormat("unrecognized value for provider '%s'", - option_arg.str().c_str()); - break; - default: - llvm_unreachable("Unimplemented option"); - } - - return error; - } - - void OptionParsingStarting(ExecutionContext *execution_context) override { - file.Clear(); - provider = eReproducerProviderNone; - } - - ArrayRef<OptionDefinition> GetDefinitions() override { - return makeArrayRef(g_reproducer_dump_options); - } - - FileSpec file; - ReproducerProvider provider = eReproducerProviderNone; - }; - -protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { - llvm::Optional<Loader> loader_storage; - Loader *loader = - GetLoaderFromPathOrCurrent(loader_storage, result, m_options.file); - if (!loader) - return false; - - switch (m_options.provider) { - case eReproducerProviderFiles: { - FileSpec vfs_mapping = loader->GetFile<FileProvider::Info>(); - - // Read the VFS mapping. - ErrorOr<std::unique_ptr<MemoryBuffer>> buffer = - vfs::getRealFileSystem()->getBufferForFile(vfs_mapping.GetPath()); - if (!buffer) { - SetError(result, errorCodeToError(buffer.getError())); - return false; - } - - // Initialize a VFS from the given mapping. - IntrusiveRefCntPtr<vfs::FileSystem> vfs = vfs::getVFSFromYAML( - std::move(buffer.get()), nullptr, vfs_mapping.GetPath()); - - // Dump the VFS to a buffer. - std::string str; - raw_string_ostream os(str); - static_cast<vfs::RedirectingFileSystem &>(*vfs).print(os); - os.flush(); - - // Return the string. - result.AppendMessage(str); - result.SetStatus(eReturnStatusSuccessFinishResult); - return true; - } - case eReproducerProviderSymbolFiles: { - Expected<std::string> symbol_files = - loader->LoadBuffer<SymbolFileProvider>(); - if (!symbol_files) { - SetError(result, symbol_files.takeError()); - return false; - } - - std::vector<SymbolFileProvider::Entry> entries; - llvm::yaml::Input yin(*symbol_files); - yin >> entries; - - for (const auto &entry : entries) { - result.AppendMessageWithFormat("- uuid: %s\n", - entry.uuid.c_str()); - result.AppendMessageWithFormat(" module path: %s\n", - entry.module_path.c_str()); - result.AppendMessageWithFormat(" symbol path: %s\n", - entry.symbol_path.c_str()); - } - result.SetStatus(eReturnStatusSuccessFinishResult); - return true; - } - case eReproducerProviderVersion: { - Expected<std::string> version = loader->LoadBuffer<VersionProvider>(); - if (!version) { - SetError(result, version.takeError()); - return false; - } - result.AppendMessage(*version); - result.SetStatus(eReturnStatusSuccessFinishResult); - return true; - } - case eReproducerProviderWorkingDirectory: { - Expected<std::string> cwd = - repro::GetDirectoryFrom<WorkingDirectoryProvider>(loader); - if (!cwd) { - SetError(result, cwd.takeError()); - return false; - } - result.AppendMessage(*cwd); - result.SetStatus(eReturnStatusSuccessFinishResult); - return true; - } - case eReproducerProviderHomeDirectory: { - Expected<std::string> home = - repro::GetDirectoryFrom<HomeDirectoryProvider>(loader); - if (!home) { - SetError(result, home.takeError()); - return false; - } - result.AppendMessage(*home); - result.SetStatus(eReturnStatusSuccessFinishResult); - return true; - } - case eReproducerProviderCommands: { - std::unique_ptr<repro::MultiLoader<repro::CommandProvider>> multi_loader = - repro::MultiLoader<repro::CommandProvider>::Create(loader); - if (!multi_loader) { - SetError(result, - make_error<StringError>("Unable to create command loader.", - llvm::inconvertibleErrorCode())); - return false; - } - - // Iterate over the command files and dump them. - llvm::Optional<std::string> command_file; - while ((command_file = multi_loader->GetNextFile())) { - if (!command_file) - break; - - auto command_buffer = llvm::MemoryBuffer::getFile(*command_file); - if (auto err = command_buffer.getError()) { - SetError(result, errorCodeToError(err)); - return false; - } - result.AppendMessage((*command_buffer)->getBuffer()); - } - - result.SetStatus(eReturnStatusSuccessFinishResult); - return true; - } - case eReproducerProviderGDB: { - std::unique_ptr<repro::MultiLoader<repro::GDBRemoteProvider>> - multi_loader = - repro::MultiLoader<repro::GDBRemoteProvider>::Create(loader); - - if (!multi_loader) { - SetError(result, - make_error<StringError>("Unable to create GDB loader.", - llvm::inconvertibleErrorCode())); - return false; - } - - llvm::Optional<std::string> gdb_file; - while ((gdb_file = multi_loader->GetNextFile())) { - if (llvm::Expected<std::vector<GDBRemotePacket>> packets = - ReadFromYAML<std::vector<GDBRemotePacket>>(*gdb_file)) { - for (GDBRemotePacket &packet : *packets) { - packet.Dump(result.GetOutputStream()); - } - } else { - SetError(result, packets.takeError()); - return false; - } - } - - result.SetStatus(eReturnStatusSuccessFinishResult); - return true; - } - case eReproducerProviderProcessInfo: { - std::unique_ptr<repro::MultiLoader<repro::ProcessInfoProvider>> - multi_loader = - repro::MultiLoader<repro::ProcessInfoProvider>::Create(loader); - - if (!multi_loader) { - SetError(result, make_error<StringError>( - llvm::inconvertibleErrorCode(), - "Unable to create process info loader.")); - return false; - } - - llvm::Optional<std::string> process_file; - while ((process_file = multi_loader->GetNextFile())) { - if (llvm::Expected<ProcessInstanceInfoList> infos = - ReadFromYAML<ProcessInstanceInfoList>(*process_file)) { - for (ProcessInstanceInfo info : *infos) - info.Dump(result.GetOutputStream(), HostInfo::GetUserIDResolver()); - } else { - SetError(result, infos.takeError()); - return false; - } - } - - result.SetStatus(eReturnStatusSuccessFinishResult); - return true; - } - case eReproducerProviderNone: - result.AppendError("No valid provider specified."); - return false; - } - - result.SetStatus(eReturnStatusSuccessFinishNoResult); - return result.Succeeded(); - } - -private: - CommandOptions m_options; -}; - -CommandObjectReproducer::CommandObjectReproducer( - CommandInterpreter &interpreter) - : CommandObjectMultiword( - interpreter, "reproducer", - "Commands for manipulating reproducers. Reproducers make it " - "possible " - "to capture full debug sessions with all its dependencies. The " - "resulting reproducer is used to replay the debug session while " - "debugging the debugger.\n" - "Because reproducers need the whole the debug session from " - "beginning to end, you need to launch the debugger in capture or " - "replay mode, commonly though the command line driver.\n" - "Reproducers are unrelated record-replay debugging, as you cannot " - "interact with the debugger during replay.\n", - "reproducer <subcommand> [<subcommand-options>]") { - LoadSubCommand( - "generate", - CommandObjectSP(new CommandObjectReproducerGenerate(interpreter))); - LoadSubCommand("status", CommandObjectSP( - new CommandObjectReproducerStatus(interpreter))); - LoadSubCommand("dump", - CommandObjectSP(new CommandObjectReproducerDump(interpreter))); - LoadSubCommand("xcrash", CommandObjectSP( - new CommandObjectReproducerXCrash(interpreter))); -} - -CommandObjectReproducer::~CommandObjectReproducer() = default; diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectReproducer.h b/contrib/llvm-project/lldb/source/Commands/CommandObjectReproducer.h deleted file mode 100644 index bdee8053549f..000000000000 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectReproducer.h +++ /dev/null @@ -1,27 +0,0 @@ -//===-- CommandObjectReproducer.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_SOURCE_COMMANDS_COMMANDOBJECTREPRODUCER_H -#define LLDB_SOURCE_COMMANDS_COMMANDOBJECTREPRODUCER_H - -#include "lldb/Interpreter/CommandObjectMultiword.h" - -namespace lldb_private { - -// CommandObjectReproducer - -class CommandObjectReproducer : public CommandObjectMultiword { -public: - CommandObjectReproducer(CommandInterpreter &interpreter); - - ~CommandObjectReproducer() override; -}; - -} // namespace lldb_private - -#endif // LLDB_SOURCE_COMMANDS_COMMANDOBJECTREPRODUCER_H diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectScript.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectScript.cpp index 2ed03e85b2d7..7e4f18a0d510 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectScript.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectScript.cpp @@ -53,7 +53,7 @@ void CommandObjectScript::CommandOptions::OptionParsingStarting( llvm::ArrayRef<OptionDefinition> CommandObjectScript::CommandOptions::GetDefinitions() { - return llvm::makeArrayRef(g_script_options); + return llvm::ArrayRef(g_script_options); } CommandObjectScript::CommandObjectScript(CommandInterpreter &interpreter) diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectSession.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectSession.cpp index f9ef1eb93443..7c7236e9793b 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectSession.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectSession.cpp @@ -117,7 +117,7 @@ protected: } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_history_options); + return llvm::ArrayRef(g_history_options); } // Instance variables to hold the values for command options. diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectSettings.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectSettings.cpp index 86194664bf5d..d658e137a4fd 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectSettings.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectSettings.cpp @@ -120,7 +120,7 @@ insert-before or insert-after."); } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_settings_set_options); + return llvm::ArrayRef(g_settings_set_options); } // Instance variables to hold the values for command options. @@ -154,7 +154,7 @@ insert-before or insert-after."); return; // Complete option name - if (arg[0] != '-') + if (arg[0] == '-') return; // Complete setting value @@ -359,7 +359,7 @@ public: } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_settings_write_options); + return llvm::ArrayRef(g_settings_write_options); } // Instance variables to hold the values for command options. @@ -453,7 +453,7 @@ public: } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_settings_read_options); + return llvm::ArrayRef(g_settings_read_options); } // Instance variables to hold the values for command options. @@ -1083,7 +1083,7 @@ public: } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_settings_clear_options); + return llvm::ArrayRef(g_settings_clear_options); } bool m_clear_all = false; diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectSource.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectSource.cpp index fd028d4f62f2..44561cfd736e 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectSource.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectSource.cpp @@ -25,6 +25,7 @@ #include "lldb/Target/SectionLoadList.h" #include "lldb/Target/StackFrame.h" #include "lldb/Utility/FileSpec.h" +#include <optional> using namespace lldb; using namespace lldb_private; @@ -98,7 +99,7 @@ class CommandObjectSourceInfo : public CommandObjectParsed { } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_source_info_options); + return llvm::ArrayRef(g_source_info_options); } // Instance variables to hold the values for command options. @@ -695,7 +696,7 @@ class CommandObjectSourceList : public CommandObjectParsed { } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_source_list_options); + return llvm::ArrayRef(g_source_list_options); } // Instance variables to hold the values for command options. @@ -721,8 +722,8 @@ public: Options *GetOptions() override { return &m_options; } - llvm::Optional<std::string> GetRepeatCommand(Args ¤t_command_args, - uint32_t index) override { + std::optional<std::string> GetRepeatCommand(Args ¤t_command_args, + uint32_t index) override { // This is kind of gross, but the command hasn't been parsed yet so we // can't look at the option values for this invocation... I have to scan // the arguments directly. diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectStats.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectStats.cpp index c0f8ff4b0b58..b0b497cd80ba 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectStats.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectStats.cpp @@ -88,7 +88,7 @@ class CommandObjectStatsDump : public CommandObjectParsed { } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_statistics_dump_options); + return llvm::ArrayRef(g_statistics_dump_options); } bool m_all_targets = false; diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectTarget.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectTarget.cpp index 3dcb35557bfe..3d53de1d2d2b 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectTarget.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectTarget.cpp @@ -153,7 +153,7 @@ public: ~OptionGroupDependents() override = default; llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_target_dependents_options); + return llvm::ArrayRef(g_target_dependents_options); } Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value, @@ -406,7 +406,7 @@ protected: if (core_file) { FileSpec core_file_dir; - core_file_dir.GetDirectory() = core_file.GetDirectory(); + core_file_dir.SetDirectory(core_file.GetDirectory()); target_sp->AppendExecutableSearchPaths(core_file_dir); ProcessSP process_sp(target_sp->CreateProcess( @@ -1541,10 +1541,25 @@ static uint32_t LookupSymbolInModule(CommandInterpreter &interpreter, strm.IndentMore(); for (uint32_t i = 0; i < num_matches; ++i) { Symbol *symbol = symtab->SymbolAtIndex(match_indexes[i]); - if (symbol && symbol->ValueIsAddress()) { - DumpAddress( - interpreter.GetExecutionContext().GetBestExecutionContextScope(), - symbol->GetAddressRef(), verbose, all_ranges, strm); + if (symbol) { + if (symbol->ValueIsAddress()) { + DumpAddress( + interpreter.GetExecutionContext().GetBestExecutionContextScope(), + symbol->GetAddressRef(), verbose, all_ranges, strm); + strm.EOL(); + } else { + strm.IndentMore(); + strm.Indent(" Name: "); + strm.PutCString(symbol->GetDisplayName().GetStringRef()); + strm.EOL(); + strm.Indent(" Value: "); + strm.Printf("0x%16.16" PRIx64 "\n", symbol->GetRawValue()); + if (symbol->GetByteSizeIsValid()) { + strm.Indent(" Size: "); + strm.Printf("0x%16.16" PRIx64 "\n", symbol->GetByteSize()); + } + strm.IndentLess(); + } } } strm.IndentLess(); @@ -1648,8 +1663,8 @@ static size_t LookupTypeInModule(Target *target, typedef_type_sp = typedefed_type_sp; typedefed_type_sp = typedef_type_sp->GetTypedefType(); } + strm.EOL(); } - strm.EOL(); } return type_list.GetSize(); } @@ -1955,7 +1970,7 @@ public: } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_target_modules_dump_symtab_options); + return llvm::ArrayRef(g_target_modules_dump_symtab_options); } SortOrder m_sort_order = eSortOrderNone; @@ -2407,7 +2422,7 @@ protected: } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_target_modules_dump_options); + return llvm::ArrayRef(g_target_modules_dump_options); } bool m_verbose; @@ -2917,7 +2932,7 @@ public: } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_target_modules_list_options); + return llvm::ArrayRef(g_target_modules_list_options); } // Instance variables to hold the values for command options. @@ -3273,7 +3288,7 @@ public: } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_target_modules_show_unwind_options); + return llvm::ArrayRef(g_target_modules_show_unwind_options); } // Instance variables to hold the values for command options. @@ -3685,7 +3700,7 @@ public: } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_target_modules_lookup_options); + return llvm::ArrayRef(g_target_modules_lookup_options); } int m_type; // Should be a eLookupTypeXXX enum after parsing options @@ -4072,7 +4087,7 @@ protected: if (!module_spec.GetUUID().IsValid()) { if (!module_spec.GetFileSpec() && !module_spec.GetPlatformFileSpec()) - module_spec.GetFileSpec().GetFilename() = symbol_fspec.GetFilename(); + module_spec.GetFileSpec().SetFilename(symbol_fspec.GetFilename()); } // Now module_spec represents a symbol file for a module that might exist @@ -4136,7 +4151,7 @@ protected: break; // Replace basename with one fewer extension - module_spec.GetFileSpec().GetFilename() = filename_no_extension; + module_spec.GetFileSpec().SetFilename(filename_no_extension); target->GetImages().FindModules(module_spec, matching_modules); } @@ -4514,7 +4529,7 @@ public: ~CommandOptions() override = default; llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_target_stop_hook_add_options); + return llvm::ArrayRef(g_target_stop_hook_add_options); } Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, @@ -5078,8 +5093,9 @@ public: protected: bool DoExecute(Args &command, CommandReturnObject &result) override { // Go over every scratch TypeSystem and dump to the command output. - for (TypeSystem *ts : GetSelectedTarget().GetScratchTypeSystems()) - ts->Dump(result.GetOutputStream().AsRawOstream()); + for (lldb::TypeSystemSP ts : GetSelectedTarget().GetScratchTypeSystems()) + if (ts) + ts->Dump(result.GetOutputStream().AsRawOstream()); result.SetStatus(eReturnStatusSuccessFinishResult); return result.Succeeded(); diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectThread.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectThread.cpp index fe0cb0945cde..411f28d84a21 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectThread.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectThread.cpp @@ -9,6 +9,7 @@ #include "CommandObjectThread.h" #include <memory> +#include <optional> #include <sstream> #include "CommandObjectThreadUtil.h" @@ -62,15 +63,13 @@ public: const int short_option = m_getopt_table[option_idx].val; switch (short_option) { - case 'c': { - int32_t input_count = 0; + case 'c': if (option_arg.getAsInteger(0, m_count)) { m_count = UINT32_MAX; error.SetErrorStringWithFormat( "invalid integer value for option '%c'", short_option); - } else if (input_count < 0) - m_count = UINT32_MAX; - } break; + } + break; case 's': if (option_arg.getAsInteger(0, m_start)) error.SetErrorStringWithFormat( @@ -97,7 +96,7 @@ public: } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_thread_backtrace_options); + return llvm::ArrayRef(g_thread_backtrace_options); } // Instance variables to hold the values for command options. @@ -126,8 +125,8 @@ public: Options *GetOptions() override { return &m_options; } - llvm::Optional<std::string> GetRepeatCommand(Args ¤t_args, - uint32_t idx) override { + std::optional<std::string> GetRepeatCommand(Args ¤t_args, + uint32_t idx) override { llvm::StringRef count_opt("--count"); llvm::StringRef start_opt("--start"); @@ -149,21 +148,21 @@ public: if (arg_string.equals("-c") || count_opt.startswith(arg_string)) { idx++; if (idx == num_entries) - return llvm::None; + return std::nullopt; count_idx = idx; if (copy_args[idx].ref().getAsInteger(0, count_val)) - return llvm::None; + return std::nullopt; } else if (arg_string.equals("-s") || start_opt.startswith(arg_string)) { idx++; if (idx == num_entries) - return llvm::None; + return std::nullopt; start_idx = idx; if (copy_args[idx].ref().getAsInteger(0, start_val)) - return llvm::None; + return std::nullopt; } } if (count_idx == 0) - return llvm::None; + return std::nullopt; std::string new_start_val = llvm::formatv("{0}", start_val + count_val); if (start_idx == 0) { @@ -174,7 +173,7 @@ public: } std::string repeat_command; if (!copy_args.GetQuotedCommandString(repeat_command)) - return llvm::None; + return std::nullopt; return repeat_command; } @@ -191,6 +190,7 @@ protected: if (ext_thread_sp && ext_thread_sp->IsValid()) { const uint32_t num_frames_with_source = 0; const bool stop_format = false; + strm.PutChar('\n'); if (ext_thread_sp->GetStatus(strm, m_options.m_start, m_options.m_count, num_frames_with_source, stop_format)) { @@ -254,7 +254,7 @@ public: ~ThreadStepScopeOptionGroup() override = default; llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_thread_step_scope_options); + return llvm::ArrayRef(g_thread_step_scope_options); } Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, @@ -874,7 +874,7 @@ public: } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_thread_until_options); + return llvm::ArrayRef(g_thread_until_options); } uint32_t m_step_thread_idx = LLDB_INVALID_THREAD_ID; @@ -991,7 +991,7 @@ protected: } LineEntry function_start; - uint32_t index_ptr = 0, end_ptr; + uint32_t index_ptr = 0, end_ptr = UINT32_MAX; std::vector<addr_t> address_list; // Find the beginning & end index of the function, but first make @@ -1270,7 +1270,7 @@ public: } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_thread_info_options); + return llvm::ArrayRef(g_thread_info_options); } bool m_json_thread; @@ -1468,7 +1468,7 @@ public: } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_thread_return_options); + return llvm::ArrayRef(g_thread_return_options); } bool m_from_expression = false; @@ -1640,7 +1640,7 @@ public: } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_thread_jump_options); + return llvm::ArrayRef(g_thread_jump_options); } FileSpecList m_filenames; @@ -1774,7 +1774,7 @@ public: } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_thread_plan_list_options); + return llvm::ArrayRef(g_thread_plan_list_options); } // Instance variables to hold the values for command options. @@ -2092,6 +2092,132 @@ public: } }; +static ThreadSP GetSingleThreadFromArgs(ExecutionContext &exe_ctx, Args &args, + CommandReturnObject &result) { + if (args.GetArgumentCount() == 0) + return exe_ctx.GetThreadSP(); + + const char *arg = args.GetArgumentAtIndex(0); + uint32_t thread_idx; + + if (!llvm::to_integer(arg, thread_idx)) { + result.AppendErrorWithFormat("invalid thread specification: \"%s\"\n", arg); + return nullptr; + } + ThreadSP thread_sp = + exe_ctx.GetProcessRef().GetThreadList().FindThreadByIndexID(thread_idx); + if (!thread_sp) + result.AppendErrorWithFormat("no thread with index: \"%s\"\n", arg); + return thread_sp; +} + +// CommandObjectTraceDumpFunctionCalls +#define LLDB_OPTIONS_thread_trace_dump_function_calls +#include "CommandOptions.inc" + +class CommandObjectTraceDumpFunctionCalls : public CommandObjectParsed { +public: + class CommandOptions : public Options { + public: + CommandOptions() { OptionParsingStarting(nullptr); } + + ~CommandOptions() override = default; + + Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, + ExecutionContext *execution_context) override { + Status error; + const int short_option = m_getopt_table[option_idx].val; + + switch (short_option) { + case 'j': { + m_dumper_options.json = true; + break; + } + case 'J': { + m_dumper_options.json = true; + m_dumper_options.pretty_print_json = true; + break; + } + case 'F': { + m_output_file.emplace(option_arg); + break; + } + default: + llvm_unreachable("Unimplemented option"); + } + return error; + } + + void OptionParsingStarting(ExecutionContext *execution_context) override { + m_dumper_options = {}; + m_output_file = std::nullopt; + } + + llvm::ArrayRef<OptionDefinition> GetDefinitions() override { + return llvm::ArrayRef(g_thread_trace_dump_function_calls_options); + } + + static const size_t kDefaultCount = 20; + + // Instance variables to hold the values for command options. + TraceDumperOptions m_dumper_options; + std::optional<FileSpec> m_output_file; + }; + + CommandObjectTraceDumpFunctionCalls(CommandInterpreter &interpreter) + : CommandObjectParsed( + interpreter, "thread trace dump function-calls", + "Dump the traced function-calls for one thread. If no " + "thread is specified, the current thread is used.", + nullptr, + eCommandRequiresProcess | eCommandRequiresThread | + eCommandTryTargetAPILock | eCommandProcessMustBeLaunched | + eCommandProcessMustBePaused | eCommandProcessMustBeTraced) { + CommandArgumentData thread_arg{eArgTypeThreadIndex, eArgRepeatOptional}; + m_arguments.push_back({thread_arg}); + } + + ~CommandObjectTraceDumpFunctionCalls() override = default; + + Options *GetOptions() override { return &m_options; } + +protected: + bool DoExecute(Args &args, CommandReturnObject &result) override { + ThreadSP thread_sp = GetSingleThreadFromArgs(m_exe_ctx, args, result); + if (!thread_sp) { + result.AppendError("invalid thread\n"); + return false; + } + + llvm::Expected<TraceCursorSP> cursor_or_error = + m_exe_ctx.GetTargetSP()->GetTrace()->CreateNewCursor(*thread_sp); + + if (!cursor_or_error) { + result.AppendError(llvm::toString(cursor_or_error.takeError())); + return false; + } + TraceCursorSP &cursor_sp = *cursor_or_error; + + std::optional<StreamFile> out_file; + if (m_options.m_output_file) { + out_file.emplace(m_options.m_output_file->GetPath().c_str(), + File::eOpenOptionWriteOnly | File::eOpenOptionCanCreate | + File::eOpenOptionTruncate); + } + + m_options.m_dumper_options.forwards = true; + + TraceDumper dumper(std::move(cursor_sp), + out_file ? *out_file : result.GetOutputStream(), + m_options.m_dumper_options); + + dumper.DumpFunctionCalls(); + return true; + } + + CommandOptions m_options; +}; + // CommandObjectTraceDumpInstructions #define LLDB_OPTIONS_thread_trace_dump_instructions #include "CommandOptions.inc" @@ -2178,6 +2304,11 @@ public: m_dumper_options.json = true; break; } + case 'E': { + m_dumper_options.only_events = true; + m_dumper_options.show_events = true; + break; + } case 'C': { m_continue = true; break; @@ -2191,12 +2322,12 @@ public: void OptionParsingStarting(ExecutionContext *execution_context) override { m_count = kDefaultCount; m_continue = false; - m_output_file = llvm::None; + m_output_file = std::nullopt; m_dumper_options = {}; } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_thread_trace_dump_instructions_options); + return llvm::ArrayRef(g_thread_trace_dump_instructions_options); } static const size_t kDefaultCount = 20; @@ -2204,7 +2335,7 @@ public: // Instance variables to hold the values for command options. size_t m_count; size_t m_continue; - llvm::Optional<FileSpec> m_output_file; + std::optional<FileSpec> m_output_file; TraceDumperOptions m_dumper_options; }; @@ -2225,8 +2356,8 @@ public: Options *GetOptions() override { return &m_options; } - llvm::Optional<std::string> GetRepeatCommand(Args ¤t_command_args, - uint32_t index) override { + std::optional<std::string> GetRepeatCommand(Args ¤t_command_args, + uint32_t index) override { std::string cmd; current_command_args.GetCommandString(cmd); if (cmd.find(" --continue") == std::string::npos) @@ -2235,28 +2366,8 @@ public: } protected: - ThreadSP GetThread(Args &args, CommandReturnObject &result) { - if (args.GetArgumentCount() == 0) - return m_exe_ctx.GetThreadSP(); - - const char *arg = args.GetArgumentAtIndex(0); - uint32_t thread_idx; - - if (!llvm::to_integer(arg, thread_idx)) { - result.AppendErrorWithFormat("invalid thread specification: \"%s\"\n", - arg); - return nullptr; - } - ThreadSP thread_sp = - m_exe_ctx.GetProcessRef().GetThreadList().FindThreadByIndexID( - thread_idx); - if (!thread_sp) - result.AppendErrorWithFormat("no thread with index: \"%s\"\n", arg); - return thread_sp; - } - bool DoExecute(Args &args, CommandReturnObject &result) override { - ThreadSP thread_sp = GetThread(args, result); + ThreadSP thread_sp = GetSingleThreadFromArgs(m_exe_ctx, args, result); if (!thread_sp) { result.AppendError("invalid thread\n"); return false; @@ -2269,36 +2380,36 @@ protected: m_options.m_dumper_options.id = m_last_id; } - llvm::Expected<TraceCursorUP> cursor_or_error = + llvm::Expected<TraceCursorSP> cursor_or_error = m_exe_ctx.GetTargetSP()->GetTrace()->CreateNewCursor(*thread_sp); if (!cursor_or_error) { result.AppendError(llvm::toString(cursor_or_error.takeError())); return false; } - TraceCursorUP &cursor_up = *cursor_or_error; + TraceCursorSP &cursor_sp = *cursor_or_error; if (m_options.m_dumper_options.id && - !cursor_up->HasId(*m_options.m_dumper_options.id)) { + !cursor_sp->HasId(*m_options.m_dumper_options.id)) { result.AppendError("invalid instruction id\n"); return false; } - llvm::Optional<StreamFile> out_file; + std::optional<StreamFile> out_file; if (m_options.m_output_file) { out_file.emplace(m_options.m_output_file->GetPath().c_str(), - File::eOpenOptionWriteOnly | File::eOpenOptionCanCreate, - lldb::eFilePermissionsFileDefault); + File::eOpenOptionWriteOnly | File::eOpenOptionCanCreate | + File::eOpenOptionTruncate); } if (m_options.m_continue && !m_last_id) { // We need to stop processing data when we already ran out of instructions // in a previous command. We can fake this by setting the cursor past the // end of the trace. - cursor_up->Seek(1, TraceCursor::SeekType::End); + cursor_sp->Seek(1, lldb::eTraceCursorSeekTypeEnd); } - TraceDumper dumper(std::move(cursor_up), + TraceDumper dumper(std::move(cursor_sp), out_file ? *out_file : result.GetOutputStream(), m_options.m_dumper_options); @@ -2309,7 +2420,7 @@ protected: CommandOptions m_options; // Last traversed id used to continue a repeat command. None means // that all the trace has been consumed. - llvm::Optional<lldb::user_id_t> m_last_id; + std::optional<lldb::user_id_t> m_last_id; }; // CommandObjectTraceDumpInfo @@ -2350,7 +2461,7 @@ public: } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_thread_trace_dump_info_options); + return llvm::ArrayRef(g_thread_trace_dump_info_options); } // Instance variables to hold the values for command options. @@ -2399,6 +2510,9 @@ public: "instructions", CommandObjectSP(new CommandObjectTraceDumpInstructions(interpreter))); LoadSubCommand( + "function-calls", + CommandObjectSP(new CommandObjectTraceDumpFunctionCalls(interpreter))); + LoadSubCommand( "info", CommandObjectSP(new CommandObjectTraceDumpInfo(interpreter))); } ~CommandObjectMultiwordTraceDump() override = default; diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectTrace.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectTrace.cpp index eaf99a46b5c2..ba8289cb68d3 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectTrace.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectTrace.cpp @@ -64,7 +64,7 @@ public: }; llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_trace_save_options); + return llvm::ArrayRef(g_trace_save_options); }; bool m_compact; @@ -168,7 +168,7 @@ public: } ArrayRef<OptionDefinition> GetDefinitions() override { - return makeArrayRef(g_trace_load_options); + return ArrayRef(g_trace_load_options); } bool m_verbose; // Enable verbose logging for debugging purposes. @@ -262,7 +262,7 @@ public: } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_trace_dump_options); + return llvm::ArrayRef(g_trace_dump_options); } bool m_verbose; // Enable verbose logging for debugging purposes. @@ -327,7 +327,7 @@ public: } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_trace_schema_options); + return llvm::ArrayRef(g_trace_schema_options); } bool m_verbose; // Enable verbose logging for debugging purposes. diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectType.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectType.cpp index 11acbb5c627f..1120caa1da4c 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectType.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectType.cpp @@ -11,6 +11,7 @@ #include "lldb/Core/Debugger.h" #include "lldb/Core/IOHandler.h" #include "lldb/DataFormatters/DataVisualization.h" +#include "lldb/DataFormatters/FormatClasses.h" #include "lldb/Host/Config.h" #include "lldb/Host/OptionParser.h" #include "lldb/Interpreter/CommandInterpreter.h" @@ -48,13 +49,15 @@ class ScriptAddOptions { public: TypeSummaryImpl::Flags m_flags; StringList m_target_types; - bool m_regex; + FormatterMatchType m_match_type; ConstString m_name; std::string m_category; - ScriptAddOptions(const TypeSummaryImpl::Flags &flags, bool regx, - ConstString name, std::string catg) - : m_flags(flags), m_regex(regx), m_name(name), m_category(catg) {} + ScriptAddOptions(const TypeSummaryImpl::Flags &flags, + FormatterMatchType match_type, ConstString name, + std::string catg) + : m_flags(flags), m_match_type(match_type), m_name(name), + m_category(catg) {} typedef std::shared_ptr<ScriptAddOptions> SharedPointer; }; @@ -64,13 +67,14 @@ public: bool m_skip_pointers; bool m_skip_references; bool m_cascade; - bool m_regex; + FormatterMatchType m_match_type; StringList m_target_types; std::string m_category; - SynthAddOptions(bool sptr, bool sref, bool casc, bool regx, std::string catg) + SynthAddOptions(bool sptr, bool sref, bool casc, + FormatterMatchType match_type, std::string catg) : m_skip_pointers(sptr), m_skip_references(sref), m_cascade(casc), - m_regex(regx), m_category(catg) {} + m_match_type(match_type), m_category(catg) {} typedef std::shared_ptr<SynthAddOptions> SharedPointer; }; @@ -114,13 +118,13 @@ private: void OptionParsingStarting(ExecutionContext *execution_context) override; llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_type_summary_add_options); + return llvm::ArrayRef(g_type_summary_add_options); } // Instance variables to hold the values for command options. TypeSummaryImpl::Flags m_flags; - bool m_regex = false; + FormatterMatchType m_match_type = eFormatterMatchExact; std::string m_format_string; ConstString m_name; std::string m_python_script; @@ -138,8 +142,6 @@ private: bool Execute_StringSummary(Args &command, CommandReturnObject &result); public: - enum SummaryFormatType { eRegularSummary, eRegexSummary, eNamedSummary }; - CommandObjectTypeSummaryAdd(CommandInterpreter &interpreter); ~CommandObjectTypeSummaryAdd() override = default; @@ -197,12 +199,9 @@ public: Status error; for (const std::string &type_name : options->m_target_types) { - CommandObjectTypeSummaryAdd::AddSummary( - ConstString(type_name), script_format, - (options->m_regex - ? CommandObjectTypeSummaryAdd::eRegexSummary - : CommandObjectTypeSummaryAdd::eRegularSummary), - options->m_category, &error); + AddSummary(ConstString(type_name), script_format, + options->m_match_type, options->m_category, + &error); if (error.Fail()) { error_sp->Printf("error: %s", error.AsCString()); error_sp->Flush(); @@ -210,15 +209,11 @@ public: } if (options->m_name) { - CommandObjectTypeSummaryAdd::AddSummary( - options->m_name, script_format, - CommandObjectTypeSummaryAdd::eNamedSummary, - options->m_category, &error); + CommandObjectTypeSummaryAdd::AddNamedSummary( + options->m_name, script_format, &error); if (error.Fail()) { - CommandObjectTypeSummaryAdd::AddSummary( - options->m_name, script_format, - CommandObjectTypeSummaryAdd::eNamedSummary, - options->m_category, &error); + CommandObjectTypeSummaryAdd::AddNamedSummary( + options->m_name, script_format, &error); if (error.Fail()) { error_sp->Printf("error: %s", error.AsCString()); error_sp->Flush(); @@ -260,9 +255,12 @@ public: io_handler.SetIsDone(true); } - static bool AddSummary(ConstString type_name, lldb::TypeSummaryImplSP entry, - SummaryFormatType type, std::string category, - Status *error = nullptr); + bool AddSummary(ConstString type_name, lldb::TypeSummaryImplSP entry, + FormatterMatchType match_type, std::string category, + Status *error = nullptr); + + bool AddNamedSummary(ConstString summary_name, lldb::TypeSummaryImplSP entry, + Status *error = nullptr); protected: bool DoExecute(Args &command, CommandReturnObject &result) override; @@ -321,7 +319,18 @@ private: m_category = std::string(option_arg); break; case 'x': - m_regex = true; + if (m_match_type == eFormatterMatchCallback) + error.SetErrorString( + "can't use --regex and --recognizer-function at the same time"); + else + m_match_type = eFormatterMatchRegex; + break; + case '\x01': + if (m_match_type == eFormatterMatchRegex) + error.SetErrorString( + "can't use --regex and --recognizer-function at the same time"); + else + m_match_type = eFormatterMatchCallback; break; default: llvm_unreachable("Unimplemented option"); @@ -338,11 +347,11 @@ private: m_category = "default"; is_class_based = false; handwrite_python = false; - m_regex = false; + m_match_type = eFormatterMatchExact; } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_type_synth_add_options); + return llvm::ArrayRef(g_type_synth_add_options); } // Instance variables to hold the values for command options. @@ -355,7 +364,7 @@ private: std::string m_category; bool is_class_based; bool handwrite_python; - bool m_regex; + FormatterMatchType m_match_type; }; CommandOptions m_options; @@ -435,12 +444,9 @@ protected: for (const std::string &type_name : options->m_target_types) { if (!type_name.empty()) { - if (!CommandObjectTypeSynthAdd::AddSynth( - ConstString(type_name), synth_provider, - options->m_regex - ? CommandObjectTypeSynthAdd::eRegexSynth - : CommandObjectTypeSynthAdd::eRegularSynth, - options->m_category, &error)) { + if (AddSynth(ConstString(type_name), synth_provider, + options->m_match_type, options->m_category, + &error)) { error_sp->Printf("error: %s\n", error.AsCString()); error_sp->Flush(); break; @@ -479,15 +485,13 @@ protected: } public: - enum SynthFormatType { eRegularSynth, eRegexSynth }; - CommandObjectTypeSynthAdd(CommandInterpreter &interpreter); ~CommandObjectTypeSynthAdd() override = default; - static bool AddSynth(ConstString type_name, lldb::SyntheticChildrenSP entry, - SynthFormatType type, std::string category_name, - Status *error); + bool AddSynth(ConstString type_name, lldb::SyntheticChildrenSP entry, + FormatterMatchType match_type, std::string category_name, + Status *error); }; // CommandObjectTypeFormatAdd @@ -504,7 +508,7 @@ private: ~CommandOptions() override = default; llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_type_format_add_options); + return llvm::ArrayRef(g_type_format_add_options); } void OptionParsingStarting(ExecutionContext *execution_context) override { @@ -681,19 +685,17 @@ protected: return false; } - ConstString typeCS(arg_entry.ref()); + FormatterMatchType match_type = eFormatterMatchExact; if (m_command_options.m_regex) { + match_type = eFormatterMatchRegex; RegularExpression typeRX(arg_entry.ref()); if (!typeRX.IsValid()) { result.AppendError( "regex format error (maybe this is not really a regex?)"); return false; } - category_sp->GetRegexTypeSummariesContainer()->Delete(typeCS); - category_sp->GetRegexTypeFormatsContainer()->Add(std::move(typeRX), - entry); - } else - category_sp->GetTypeFormatsContainer()->Add(std::move(typeCS), entry); + } + category_sp->AddTypeFormat(arg_entry.ref(), match_type, entry); } result.SetStatus(eReturnStatusSuccessFinishNoResult); @@ -741,7 +743,7 @@ protected: } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_type_formatter_delete_options); + return llvm::ArrayRef(g_type_formatter_delete_options); } // Instance variables to hold the values for command options. @@ -783,27 +785,7 @@ public: DataVisualization::Categories::ForEach( [this, &request](const lldb::TypeCategoryImplSP &category_sp) { - if (CHECK_FORMATTER_KIND_MASK(eFormatCategoryItemValue)) - category_sp->GetTypeFormatsContainer()->AutoComplete(request); - if (CHECK_FORMATTER_KIND_MASK(eFormatCategoryItemRegexValue)) - category_sp->GetRegexTypeFormatsContainer()->AutoComplete(request); - - if (CHECK_FORMATTER_KIND_MASK(eFormatCategoryItemSummary)) - category_sp->GetTypeSummariesContainer()->AutoComplete(request); - if (CHECK_FORMATTER_KIND_MASK(eFormatCategoryItemRegexSummary)) - category_sp->GetRegexTypeSummariesContainer()->AutoComplete( - request); - - if (CHECK_FORMATTER_KIND_MASK(eFormatCategoryItemFilter)) - category_sp->GetTypeFiltersContainer()->AutoComplete(request); - if (CHECK_FORMATTER_KIND_MASK(eFormatCategoryItemRegexFilter)) - category_sp->GetRegexTypeFiltersContainer()->AutoComplete(request); - - if (CHECK_FORMATTER_KIND_MASK(eFormatCategoryItemSynth)) - category_sp->GetTypeSyntheticsContainer()->AutoComplete(request); - if (CHECK_FORMATTER_KIND_MASK(eFormatCategoryItemRegexSynth)) - category_sp->GetRegexTypeSyntheticsContainer()->AutoComplete( - request); + category_sp->AutoComplete(request, m_formatter_kind_mask); return true; }); } @@ -898,7 +880,7 @@ private: } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_type_formatter_clear_options); + return llvm::ArrayRef(g_type_formatter_clear_options); } // Instance variables to hold the values for command options. @@ -958,9 +940,7 @@ class CommandObjectTypeFormatDelete : public CommandObjectTypeFormatterDelete { public: CommandObjectTypeFormatDelete(CommandInterpreter &interpreter) : CommandObjectTypeFormatterDelete( - interpreter, - eFormatCategoryItemValue | eFormatCategoryItemRegexValue, - "type format delete", + interpreter, eFormatCategoryItemFormat, "type format delete", "Delete an existing formatting style for a type.") {} ~CommandObjectTypeFormatDelete() override = default; @@ -971,10 +951,9 @@ public: class CommandObjectTypeFormatClear : public CommandObjectTypeFormatterClear { public: CommandObjectTypeFormatClear(CommandInterpreter &interpreter) - : CommandObjectTypeFormatterClear( - interpreter, - eFormatCategoryItemValue | eFormatCategoryItemRegexValue, - "type format clear", "Delete all existing format styles.") {} + : CommandObjectTypeFormatterClear(interpreter, eFormatCategoryItemFormat, + "type format clear", + "Delete all existing format styles.") {} }; #define LLDB_OPTIONS_type_formatter_list @@ -1020,7 +999,7 @@ class CommandObjectTypeFormatterList : public CommandObjectParsed { } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_type_formatter_list_options); + return llvm::ArrayRef(g_type_formatter_list_options); } // Instance variables to hold the values for command options. @@ -1100,36 +1079,20 @@ protected: "-----------------------\nCategory: %s%s\n-----------------------\n", category->GetName(), category->IsEnabled() ? "" : " (disabled)"); - TypeCategoryImpl::ForEachCallbacks<FormatterType> foreach; - foreach - .SetExact([&result, &formatter_regex, &any_printed]( - const TypeMatcher &type_matcher, - const FormatterSharedPointer &format_sp) -> bool { - if (ShouldListItem(type_matcher.GetMatchString().GetStringRef(), - formatter_regex.get())) { - any_printed = true; - result.GetOutputStream().Printf( - "%s: %s\n", type_matcher.GetMatchString().GetCString(), - format_sp->GetDescription().c_str()); - } - return true; - }); - - foreach - .SetWithRegex([&result, &formatter_regex, &any_printed]( - const TypeMatcher &type_matcher, - const FormatterSharedPointer &format_sp) -> bool { - if (ShouldListItem(type_matcher.GetMatchString().GetStringRef(), - formatter_regex.get())) { - any_printed = true; - result.GetOutputStream().Printf( - "%s: %s\n", type_matcher.GetMatchString().GetCString(), - format_sp->GetDescription().c_str()); - } - return true; - }); - - category->ForEach(foreach); + TypeCategoryImpl::ForEachCallback<FormatterType> print_formatter = + [&result, &formatter_regex, + &any_printed](const TypeMatcher &type_matcher, + const FormatterSharedPointer &format_sp) -> bool { + if (ShouldListItem(type_matcher.GetMatchString().GetStringRef(), + formatter_regex.get())) { + any_printed = true; + result.GetOutputStream().Printf( + "%s: %s\n", type_matcher.GetMatchString().GetCString(), + format_sp->GetDescription().c_str()); + } + return true; + }; + category->ForEach(print_formatter); }; if (m_options.m_category_language.OptionWasSet()) { @@ -1207,7 +1170,18 @@ Status CommandObjectTypeSummaryAdd::CommandOptions::SetOptionValue( m_flags.SetSkipReferences(true); break; case 'x': - m_regex = true; + if (m_match_type == eFormatterMatchCallback) + error.SetErrorString( + "can't use --regex and --recognizer-function at the same time"); + else + m_match_type = eFormatterMatchRegex; + break; + case '\x01': + if (m_match_type == eFormatterMatchRegex) + error.SetErrorString( + "can't use --regex and --recognizer-function at the same time"); + else + m_match_type = eFormatterMatchCallback; break; case 'n': m_name.SetString(option_arg); @@ -1244,7 +1218,7 @@ void CommandObjectTypeSummaryAdd::CommandOptions::OptionParsingStarting( .SetSkipReferences(false) .SetHideItemNames(false); - m_regex = false; + m_match_type = eFormatterMatchExact; m_name.Clear(); m_python_script = ""; m_python_function = ""; @@ -1318,7 +1292,7 @@ bool CommandObjectTypeSummaryAdd::Execute_ScriptSummary( } else { // Use an IOHandler to grab Python code from the user auto options = std::make_unique<ScriptAddOptions>( - m_options.m_flags, m_options.m_regex, m_options.m_name, + m_options.m_flags, m_options.m_match_type, m_options.m_name, m_options.m_category); for (auto &entry : command.entries()) { @@ -1346,10 +1320,8 @@ bool CommandObjectTypeSummaryAdd::Execute_ScriptSummary( Status error; for (auto &entry : command.entries()) { - CommandObjectTypeSummaryAdd::AddSummary( - ConstString(entry.ref()), script_format, - (m_options.m_regex ? eRegexSummary : eRegularSummary), - m_options.m_category, &error); + AddSummary(ConstString(entry.ref()), script_format, m_options.m_match_type, + m_options.m_category, &error); if (error.Fail()) { result.AppendError(error.AsCString()); return false; @@ -1357,8 +1329,7 @@ bool CommandObjectTypeSummaryAdd::Execute_ScriptSummary( } if (m_options.m_name) { - AddSummary(m_options.m_name, script_format, eNamedSummary, - m_options.m_category, &error); + AddNamedSummary(m_options.m_name, script_format, &error); if (error.Fail()) { result.AppendError(error.AsCString()); result.AppendError("added to types, but not given a name"); @@ -1419,9 +1390,8 @@ bool CommandObjectTypeSummaryAdd::Execute_StringSummary( } ConstString typeCS(arg_entry.ref()); - AddSummary(typeCS, entry, - (m_options.m_regex ? eRegexSummary : eRegularSummary), - m_options.m_category, &error); + AddSummary(typeCS, entry, m_options.m_match_type, m_options.m_category, + &error); if (error.Fail()) { result.AppendError(error.AsCString()); @@ -1430,8 +1400,7 @@ bool CommandObjectTypeSummaryAdd::Execute_StringSummary( } if (m_options.m_name) { - AddSummary(m_options.m_name, entry, eNamedSummary, m_options.m_category, - &error); + AddNamedSummary(m_options.m_name, entry, &error); if (error.Fail()) { result.AppendError(error.AsCString()); result.AppendError("added to types, but not given a name"); @@ -1586,21 +1555,30 @@ static bool FixArrayTypeNameWithRegex(ConstString &type_name) { return false; } +bool CommandObjectTypeSummaryAdd::AddNamedSummary(ConstString summary_name, + TypeSummaryImplSP entry, + Status *error) { + // system named summaries do not exist (yet?) + DataVisualization::NamedSummaryFormats::Add(summary_name, entry); + return true; +} + bool CommandObjectTypeSummaryAdd::AddSummary(ConstString type_name, TypeSummaryImplSP entry, - SummaryFormatType type, + FormatterMatchType match_type, std::string category_name, Status *error) { lldb::TypeCategoryImplSP category; DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()), category); - if (type == eRegularSummary) { + if (match_type == eFormatterMatchExact) { if (FixArrayTypeNameWithRegex(type_name)) - type = eRegexSummary; + match_type = eFormatterMatchRegex; } - if (type == eRegexSummary) { + if (match_type == eFormatterMatchRegex) { + match_type = eFormatterMatchRegex; RegularExpression typeRX(type_name.GetStringRef()); if (!typeRX.IsValid()) { if (error) @@ -1608,19 +1586,21 @@ bool CommandObjectTypeSummaryAdd::AddSummary(ConstString type_name, "regex format error (maybe this is not really a regex?)"); return false; } + } - category->GetRegexTypeSummariesContainer()->Delete(type_name); - category->GetRegexTypeSummariesContainer()->Add(std::move(typeRX), entry); - - return true; - } else if (type == eNamedSummary) { - // system named summaries do not exist (yet?) - DataVisualization::NamedSummaryFormats::Add(type_name, entry); - return true; - } else { - category->GetTypeSummariesContainer()->Add(std::move(type_name), entry); - return true; + if (match_type == eFormatterMatchCallback) { + const char *function_name = type_name.AsCString(); + ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter(); + if (interpreter && !interpreter->CheckObjectExists(function_name)) { + error->SetErrorStringWithFormat( + "The provided recognizer function \"%s\" does not exist - " + "please define it before attempting to use this summary.\n", + function_name); + return false; + } } + category->AddTypeSummary(type_name.GetStringRef(), match_type, entry); + return true; } // CommandObjectTypeSummaryDelete @@ -1629,9 +1609,8 @@ class CommandObjectTypeSummaryDelete : public CommandObjectTypeFormatterDelete { public: CommandObjectTypeSummaryDelete(CommandInterpreter &interpreter) : CommandObjectTypeFormatterDelete( - interpreter, - eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary, - "type summary delete", "Delete an existing summary for a type.") {} + interpreter, eFormatCategoryItemSummary, "type summary delete", + "Delete an existing summary for a type.") {} ~CommandObjectTypeSummaryDelete() override = default; @@ -1646,10 +1625,9 @@ protected: class CommandObjectTypeSummaryClear : public CommandObjectTypeFormatterClear { public: CommandObjectTypeSummaryClear(CommandInterpreter &interpreter) - : CommandObjectTypeFormatterClear( - interpreter, - eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary, - "type summary clear", "Delete all existing summaries.") {} + : CommandObjectTypeFormatterClear(interpreter, eFormatCategoryItemSummary, + "type summary clear", + "Delete all existing summaries.") {} protected: void FormatterSpecificDeletion() override { @@ -1722,7 +1700,7 @@ class CommandObjectTypeCategoryDefine : public CommandObjectParsed { } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_type_category_define_options); + return llvm::ArrayRef(g_type_category_define_options); } // Instance variables to hold the values for command options. @@ -1825,7 +1803,7 @@ class CommandObjectTypeCategoryEnable : public CommandObjectParsed { } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_type_category_enable_options); + return llvm::ArrayRef(g_type_category_enable_options); } // Instance variables to hold the values for command options. @@ -2002,7 +1980,7 @@ class CommandObjectTypeCategoryDisable : public CommandObjectParsed { } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_type_category_disable_options); + return llvm::ArrayRef(g_type_category_disable_options); } // Instance variables to hold the values for command options. @@ -2181,9 +2159,8 @@ class CommandObjectTypeFilterDelete : public CommandObjectTypeFormatterDelete { public: CommandObjectTypeFilterDelete(CommandInterpreter &interpreter) : CommandObjectTypeFormatterDelete( - interpreter, - eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter, - "type filter delete", "Delete an existing filter for a type.") {} + interpreter, eFormatCategoryItemFilter, "type filter delete", + "Delete an existing filter for a type.") {} ~CommandObjectTypeFilterDelete() override = default; }; @@ -2196,9 +2173,7 @@ class CommandObjectTypeSynthDelete : public CommandObjectTypeFormatterDelete { public: CommandObjectTypeSynthDelete(CommandInterpreter &interpreter) : CommandObjectTypeFormatterDelete( - interpreter, - eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth, - "type synthetic delete", + interpreter, eFormatCategoryItemSynth, "type synthetic delete", "Delete an existing synthetic provider for a type.") {} ~CommandObjectTypeSynthDelete() override = default; @@ -2211,10 +2186,9 @@ public: class CommandObjectTypeFilterClear : public CommandObjectTypeFormatterClear { public: CommandObjectTypeFilterClear(CommandInterpreter &interpreter) - : CommandObjectTypeFormatterClear( - interpreter, - eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter, - "type filter clear", "Delete all existing filter.") {} + : CommandObjectTypeFormatterClear(interpreter, eFormatCategoryItemFilter, + "type filter clear", + "Delete all existing filter.") {} }; #if LLDB_ENABLE_PYTHON @@ -2224,9 +2198,7 @@ class CommandObjectTypeSynthClear : public CommandObjectTypeFormatterClear { public: CommandObjectTypeSynthClear(CommandInterpreter &interpreter) : CommandObjectTypeFormatterClear( - interpreter, - eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth, - "type synthetic clear", + interpreter, eFormatCategoryItemSynth, "type synthetic clear", "Delete all existing synthetic providers.") {} }; @@ -2234,7 +2206,7 @@ bool CommandObjectTypeSynthAdd::Execute_HandwritePython( Args &command, CommandReturnObject &result) { auto options = std::make_unique<SynthAddOptions>( m_options.m_skip_pointers, m_options.m_skip_references, - m_options.m_cascade, m_options.m_regex, m_options.m_category); + m_options.m_cascade, m_options.m_match_type, m_options.m_category); for (auto &entry : command.entries()) { if (entry.ref().empty()) { @@ -2304,9 +2276,8 @@ bool CommandObjectTypeSynthAdd::Execute_PythonClass( } ConstString typeCS(arg_entry.ref()); - if (!AddSynth(typeCS, entry, - m_options.m_regex ? eRegexSynth : eRegularSynth, - m_options.m_category, &error)) { + if (!AddSynth(typeCS, entry, m_options.m_match_type, m_options.m_category, + &error)) { result.AppendError(error.AsCString()); return false; } @@ -2334,29 +2305,38 @@ CommandObjectTypeSynthAdd::CommandObjectTypeSynthAdd( bool CommandObjectTypeSynthAdd::AddSynth(ConstString type_name, SyntheticChildrenSP entry, - SynthFormatType type, + FormatterMatchType match_type, std::string category_name, Status *error) { lldb::TypeCategoryImplSP category; DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()), category); - if (type == eRegularSynth) { + if (match_type == eFormatterMatchExact) { if (FixArrayTypeNameWithRegex(type_name)) - type = eRegexSynth; - } - - if (category->AnyMatches( - type_name, eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter, - false)) { - if (error) - error->SetErrorStringWithFormat("cannot add synthetic for type %s when " - "filter is defined in same category!", - type_name.AsCString()); - return false; + match_type = eFormatterMatchRegex; + } + + // Only check for conflicting filters in the same category if `type_name` is + // an actual type name. Matching a regex string against registered regexes + // doesn't work. + if (match_type == eFormatterMatchExact) { + // It's not generally possible to get a type object here. For example, this + // command can be run before loading any binaries. Do just a best-effort + // name-based lookup here to try to prevent conflicts. + FormattersMatchCandidate candidate_type(type_name, nullptr, TypeImpl(), + FormattersMatchCandidate::Flags()); + if (category->AnyMatches(candidate_type, eFormatCategoryItemFilter, + false)) { + if (error) + error->SetErrorStringWithFormat("cannot add synthetic for type %s when " + "filter is defined in same category!", + type_name.AsCString()); + return false; + } } - if (type == eRegexSynth) { + if (match_type == eFormatterMatchRegex) { RegularExpression typeRX(type_name.GetStringRef()); if (!typeRX.IsValid()) { if (error) @@ -2364,15 +2344,22 @@ bool CommandObjectTypeSynthAdd::AddSynth(ConstString type_name, "regex format error (maybe this is not really a regex?)"); return false; } + } - category->GetRegexTypeSyntheticsContainer()->Delete(type_name); - category->GetRegexTypeSyntheticsContainer()->Add(std::move(typeRX), entry); - - return true; - } else { - category->GetTypeSyntheticsContainer()->Add(std::move(type_name), entry); - return true; + if (match_type == eFormatterMatchCallback) { + const char *function_name = type_name.AsCString(); + ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter(); + if (interpreter && !interpreter->CheckObjectExists(function_name)) { + error->SetErrorStringWithFormat( + "The provided recognizer function \"%s\" does not exist - " + "please define it before attempting to use this summary.\n", + function_name); + return false; + } } + + category->AddTypeSynthetic(type_name.GetStringRef(), match_type, entry); + return true; } #endif @@ -2436,7 +2423,7 @@ private: } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_type_filter_add_options); + return llvm::ArrayRef(g_type_filter_add_options); } // Instance variables to hold the values for command options. @@ -2471,18 +2458,30 @@ private: type = eRegexFilter; } - if (category->AnyMatches( - type_name, eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth, - false)) { - if (error) - error->SetErrorStringWithFormat("cannot add filter for type %s when " - "synthetic is defined in same " - "category!", - type_name.AsCString()); - return false; + // Only check for conflicting synthetic child providers in the same category + // if `type_name` is an actual type name. Matching a regex string against + // registered regexes doesn't work. + if (type == eRegularFilter) { + // It's not generally possible to get a type object here. For example, + // this command can be run before loading any binaries. Do just a + // best-effort name-based lookup here to try to prevent conflicts. + FormattersMatchCandidate candidate_type( + type_name, nullptr, TypeImpl(), FormattersMatchCandidate::Flags()); + lldb::SyntheticChildrenSP entry; + if (category->AnyMatches(candidate_type, eFormatCategoryItemSynth, + false)) { + if (error) + error->SetErrorStringWithFormat("cannot add filter for type %s when " + "synthetic is defined in same " + "category!", + type_name.AsCString()); + return false; + } } + FormatterMatchType match_type = eFormatterMatchExact; if (type == eRegexFilter) { + match_type = eFormatterMatchRegex; RegularExpression typeRX(type_name.GetStringRef()); if (!typeRX.IsValid()) { if (error) @@ -2490,15 +2489,9 @@ private: "regex format error (maybe this is not really a regex?)"); return false; } - - category->GetRegexTypeFiltersContainer()->Delete(type_name); - category->GetRegexTypeFiltersContainer()->Add(std::move(typeRX), entry); - - return true; - } else { - category->GetTypeFiltersContainer()->Add(std::move(type_name), entry); - return true; } + category->AddTypeFilter(type_name.GetStringRef(), match_type, entry); + return true; } public: @@ -2646,7 +2639,7 @@ protected: ~CommandOptions() override = default; llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_type_lookup_options); + return llvm::ArrayRef(g_type_lookup_options); } Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value, diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectWatchpoint.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectWatchpoint.cpp index f87a171daca6..8df8aca04e4a 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectWatchpoint.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectWatchpoint.cpp @@ -196,7 +196,7 @@ public: } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_watchpoint_list_options); + return llvm::ArrayRef(g_watchpoint_list_options); } // Instance variables to hold the values for command options. @@ -479,7 +479,7 @@ public: } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_watchpoint_delete_options); + return llvm::ArrayRef(g_watchpoint_delete_options); } // Instance variables to hold the values for command options. @@ -605,7 +605,7 @@ public: } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_watchpoint_ignore_options); + return llvm::ArrayRef(g_watchpoint_ignore_options); } // Instance variables to hold the values for command options. @@ -730,7 +730,7 @@ public: } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_watchpoint_modify_options); + return llvm::ArrayRef(g_watchpoint_modify_options); } // Instance variables to hold the values for command options. @@ -1083,7 +1083,7 @@ protected: options.SetUnwindOnError(true); options.SetKeepInMemory(false); options.SetTryAllThreads(true); - options.SetTimeout(llvm::None); + options.SetTimeout(std::nullopt); ExpressionResults expr_result = target->EvaluateExpression(expr, frame, valobj_sp, options); diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectWatchpointCommand.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectWatchpointCommand.cpp index 3264813b3d53..b33f403a6964 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectWatchpointCommand.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectWatchpointCommand.cpp @@ -349,7 +349,7 @@ are no syntax errors may indicate that a function was declared but never called. } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_watchpoint_command_add_options); + return llvm::ArrayRef(g_watchpoint_command_add_options); } // Instance variables to hold the values for command options. diff --git a/contrib/llvm-project/lldb/source/Commands/CommandOptionsProcessLaunch.cpp b/contrib/llvm-project/lldb/source/Commands/CommandOptionsProcessLaunch.cpp index 3c7f4b6c7585..85ad8ff5e071 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandOptionsProcessLaunch.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandOptionsProcessLaunch.cpp @@ -145,5 +145,5 @@ Status CommandOptionsProcessLaunch::SetOptionValue( } llvm::ArrayRef<OptionDefinition> CommandOptionsProcessLaunch::GetDefinitions() { - return llvm::makeArrayRef(g_process_launch_options); + return llvm::ArrayRef(g_process_launch_options); } diff --git a/contrib/llvm-project/lldb/source/Commands/Options.td b/contrib/llvm-project/lldb/source/Commands/Options.td index cc47db575306..6aee2ac22804 100644 --- a/contrib/llvm-project/lldb/source/Commands/Options.td +++ b/contrib/llvm-project/lldb/source/Commands/Options.td @@ -343,6 +343,11 @@ let Command = "disassemble" in { Desc<"Force disassembly of large functions.">; } +let Command = "diagnostics dump" in { + def diagnostics_dump_directory : Option<"directory", "d">, Group<1>, + Arg<"Path">, Desc<"Dump the diagnostics to the given directory.">; +} + let Command = "expression" in { def expression_options_all_threads : Option<"all-threads", "a">, Groups<[1,2]>, Arg<"Boolean">, Desc<"Should we run all threads if the " @@ -466,27 +471,6 @@ let Command = "log dump" in { Desc<"Set the destination file to dump to.">; } -let Command = "reproducer dump" in { - def reproducer_provider : Option<"provider", "p">, Group<1>, - EnumArg<"ReproducerProvider">, - Required, Desc<"The reproducer provider to dump.">; - def reproducer_file : Option<"file", "f">, Group<1>, Arg<"Filename">, - Desc<"The reproducer path. If a reproducer is replayed and no path is " - "provided, that reproducer is dumped.">; -} - -let Command = "reproducer verify" in { - def reproducer_verify_file : Option<"file", "f">, Group<1>, Arg<"Filename">, - Desc<"The reproducer path. If a reproducer is replayed and no path is " - "provided, that reproducer is dumped.">; -} - -let Command = "reproducer xcrash" in { - def reproducer_signal : Option<"signal", "s">, Group<1>, - EnumArg<"ReproducerSignal">, - Required, Desc<"The signal to crash the debugger.">; -} - let Command = "memory read" in { def memory_read_num_per_line : Option<"num-per-line", "l">, Group<1>, Arg<"NumberPerLine">, Desc<"The number of items per line to display.">; @@ -1114,6 +1098,19 @@ let Command = "thread plan list" in { Desc<"Display thread plans for unreported threads">; } +let Command = "thread trace dump function calls" in { + def thread_trace_dump_function_calls_file : Option<"file", "F">, Group<1>, + Arg<"Filename">, + Desc<"Dump the function calls to a file instead of the standard output.">; + def thread_trace_dump_function_calls_json: Option<"json", "j">, + Group<1>, + Desc<"Dump in simple JSON format.">; + def thread_trace_dump_function_calls_pretty_json: Option<"pretty-json", "J">, + Group<1>, + Desc<"Dump in JSON format but pretty printing the output for easier " + "readability.">; +} + let Command = "thread trace dump instructions" in { def thread_trace_dump_instructions_forwards: Option<"forwards", "f">, Group<1>, @@ -1160,6 +1157,10 @@ let Command = "thread trace dump instructions" in { def thread_trace_dump_instructions_show_events : Option<"events", "e">, Group<1>, Desc<"Dump the events that happened during the execution of the target.">; + def thread_trace_dump_instruction_only_events : Option<"only-events", "E">, + Group<1>, + Desc<"Dump only the events that happened during the execution of the " + "target. No instrutions are dumped.">; def thread_trace_dump_instructions_continue: Option<"continue", "C">, Group<1>, Desc<"Continue dumping instructions right where the previous invocation of " @@ -1188,6 +1189,11 @@ let Command = "type summary add" in { Desc<"Don't use this format for references-to-type objects.">; def type_summary_add_regex : Option<"regex", "x">, Desc<"Type names are actually regular expressions.">; + def type_summary_add_recognizer_function : + Option<"recognizer-function", "\\x01">, + Desc<"The names in the argument list are actually the names of python " + "functions that decide whether to use this summary for any given type. " + "Cannot be specified at the same time as --regex (-x).">; def type_summary_add_inline_children : Option<"inline-children", "c">, Group<1>, Required, Desc<"If true, inline all child values into summary string.">; @@ -1229,6 +1235,11 @@ let Command = "type synth add" in { "children.">; def type_synth_add_regex : Option<"regex", "x">, Desc<"Type names are actually regular expressions.">; + def type_synth_add_recognizer_function : + Option<"recognizer-function", "\\x01">, + Desc<"The names in the argument list are actually the names of python " + "functions that decide whether to use this summary for any given type. " + "Cannot be specified at the same time as --regex (-x).">; } let Command = "type format add" in { diff --git a/contrib/llvm-project/lldb/source/Core/Address.cpp b/contrib/llvm-project/lldb/source/Core/Address.cpp index b84e1ac8e169..5969cf11d865 100644 --- a/contrib/llvm-project/lldb/source/Core/Address.cpp +++ b/contrib/llvm-project/lldb/source/Core/Address.cpp @@ -451,7 +451,7 @@ bool Address::Dump(Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, else s->Printf("%s[", "<Unknown>"); } - LLVM_FALLTHROUGH; + [[fallthrough]]; case DumpStyleFileAddress: { addr_t file_addr = GetFileAddress(); if (file_addr == LLDB_INVALID_ADDRESS) { diff --git a/contrib/llvm-project/lldb/source/Core/AddressRange.cpp b/contrib/llvm-project/lldb/source/Core/AddressRange.cpp index 66dcda574890..1830f2ccd47f 100644 --- a/contrib/llvm-project/lldb/source/Core/AddressRange.cpp +++ b/contrib/llvm-project/lldb/source/Core/AddressRange.cpp @@ -169,7 +169,7 @@ bool AddressRange::Dump(Stream *s, Target *target, Address::DumpStyle style, case Address::DumpStyleModuleWithFileAddress: show_module = true; - LLVM_FALLTHROUGH; + [[fallthrough]]; case Address::DumpStyleFileAddress: vmaddr = m_base_addr.GetFileAddress(); break; diff --git a/contrib/llvm-project/lldb/source/Core/Communication.cpp b/contrib/llvm-project/lldb/source/Core/Communication.cpp index f41ce46ede88..5d890632ccc6 100644 --- a/contrib/llvm-project/lldb/source/Core/Communication.cpp +++ b/contrib/llvm-project/lldb/source/Core/Communication.cpp @@ -8,22 +8,14 @@ #include "lldb/Core/Communication.h" -#include "lldb/Host/HostThread.h" -#include "lldb/Host/ThreadLauncher.h" #include "lldb/Utility/Connection.h" -#include "lldb/Utility/ConstString.h" -#include "lldb/Utility/Event.h" #include "lldb/Utility/LLDBLog.h" -#include "lldb/Utility/Listener.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/Status.h" -#include "llvm/ADT/None.h" -#include "llvm/ADT/Optional.h" #include "llvm/Support/Compiler.h" #include <algorithm> -#include <chrono> #include <cstring> #include <memory> @@ -34,42 +26,15 @@ using namespace lldb; using namespace lldb_private; -ConstString &Communication::GetStaticBroadcasterClass() { - static ConstString class_name("lldb.communication"); - return class_name; -} - -Communication::Communication(const char *name) - : Broadcaster(nullptr, name), m_connection_sp(), - m_read_thread_enabled(false), m_read_thread_did_exit(false), m_bytes(), - m_bytes_mutex(), m_write_mutex(), m_synchronize_mutex(), - m_callback(nullptr), m_callback_baton(nullptr), m_close_on_eof(true) - -{ - - LLDB_LOG(GetLog(LLDBLog::Object | LLDBLog::Communication), - "{0} Communication::Communication (name = {1})", this, name); - - SetEventName(eBroadcastBitDisconnected, "disconnected"); - SetEventName(eBroadcastBitReadThreadGotBytes, "got bytes"); - SetEventName(eBroadcastBitReadThreadDidExit, "read thread did exit"); - SetEventName(eBroadcastBitReadThreadShouldExit, "read thread should exit"); - SetEventName(eBroadcastBitPacketAvailable, "packet available"); - SetEventName(eBroadcastBitNoMorePendingInput, "no more pending input"); - - CheckInWithManager(); +Communication::Communication() + : m_connection_sp(), m_write_mutex(), m_close_on_eof(true) { } Communication::~Communication() { - LLDB_LOG(GetLog(LLDBLog::Object | LLDBLog::Communication), - "{0} Communication::~Communication (name = {1})", this, - GetBroadcasterName().AsCString()); Clear(); } void Communication::Clear() { - SetReadThreadBytesReceivedCallback(nullptr, nullptr); - StopReadThread(nullptr); Disconnect(nullptr); } @@ -91,8 +56,6 @@ ConnectionStatus Communication::Disconnect(Status *error_ptr) { LLDB_LOG(GetLog(LLDBLog::Communication), "{0} Communication::Disconnect ()", this); - assert((!m_read_thread_enabled || m_read_thread_did_exit) && - "Disconnecting while the read thread is running is racy!"); lldb::ConnectionSP connection_sp(m_connection_sp); if (connection_sp) { ConnectionStatus status = connection_sp->Disconnect(error_ptr); @@ -129,42 +92,6 @@ size_t Communication::Read(void *dst, size_t dst_len, "this = {0}, dst = {1}, dst_len = {2}, timeout = {3}, connection = {4}", this, dst, dst_len, timeout, m_connection_sp.get()); - if (m_read_thread_enabled) { - // We have a dedicated read thread that is getting data for us - size_t cached_bytes = GetCachedBytes(dst, dst_len); - if (cached_bytes > 0 || (timeout && timeout->count() == 0)) { - status = eConnectionStatusSuccess; - return cached_bytes; - } - - if (!m_connection_sp) { - if (error_ptr) - error_ptr->SetErrorString("Invalid connection."); - status = eConnectionStatusNoConnection; - return 0; - } - - ListenerSP listener_sp(Listener::MakeListener("Communication::Read")); - listener_sp->StartListeningForEvents( - this, eBroadcastBitReadThreadGotBytes | eBroadcastBitReadThreadDidExit); - EventSP event_sp; - while (listener_sp->GetEvent(event_sp, timeout)) { - const uint32_t event_type = event_sp->GetType(); - if (event_type & eBroadcastBitReadThreadGotBytes) { - return GetCachedBytes(dst, dst_len); - } - - if (event_type & eBroadcastBitReadThreadDidExit) { - if (GetCloseOnEOF()) - Disconnect(nullptr); - break; - } - } - return 0; - } - - // We aren't using a read thread, just read the data synchronously in this - // thread. return ReadFromConnection(dst, dst_len, timeout, status, error_ptr); } @@ -197,104 +124,6 @@ size_t Communication::WriteAll(const void *src, size_t src_len, return total_written; } -bool Communication::StartReadThread(Status *error_ptr) { - if (error_ptr) - error_ptr->Clear(); - - if (m_read_thread.IsJoinable()) - return true; - - LLDB_LOG(GetLog(LLDBLog::Communication), - "{0} Communication::StartReadThread ()", this); - - const std::string thread_name = - llvm::formatv("<lldb.comm.{0}>", GetBroadcasterName()); - - m_read_thread_enabled = true; - m_read_thread_did_exit = false; - auto maybe_thread = ThreadLauncher::LaunchThread( - thread_name, [this] { return ReadThread(); }); - if (maybe_thread) { - m_read_thread = *maybe_thread; - } else { - if (error_ptr) - *error_ptr = Status(maybe_thread.takeError()); - else { - LLDB_LOG(GetLog(LLDBLog::Host), "failed to launch host thread: {}", - llvm::toString(maybe_thread.takeError())); - } - } - - if (!m_read_thread.IsJoinable()) - m_read_thread_enabled = false; - - return m_read_thread_enabled; -} - -bool Communication::StopReadThread(Status *error_ptr) { - if (!m_read_thread.IsJoinable()) - return true; - - LLDB_LOG(GetLog(LLDBLog::Communication), - "{0} Communication::StopReadThread ()", this); - - m_read_thread_enabled = false; - - BroadcastEvent(eBroadcastBitReadThreadShouldExit, nullptr); - - // error = m_read_thread.Cancel(); - - Status error = m_read_thread.Join(nullptr); - return error.Success(); -} - -bool Communication::JoinReadThread(Status *error_ptr) { - if (!m_read_thread.IsJoinable()) - return true; - - Status error = m_read_thread.Join(nullptr); - return error.Success(); -} - -size_t Communication::GetCachedBytes(void *dst, size_t dst_len) { - std::lock_guard<std::recursive_mutex> guard(m_bytes_mutex); - if (!m_bytes.empty()) { - // If DST is nullptr and we have a thread, then return the number of bytes - // that are available so the caller can call again - if (dst == nullptr) - return m_bytes.size(); - - const size_t len = std::min<size_t>(dst_len, m_bytes.size()); - - ::memcpy(dst, m_bytes.c_str(), len); - m_bytes.erase(m_bytes.begin(), m_bytes.begin() + len); - - return len; - } - return 0; -} - -void Communication::AppendBytesToCache(const uint8_t *bytes, size_t len, - bool broadcast, - ConnectionStatus status) { - LLDB_LOG(GetLog(LLDBLog::Communication), - "{0} Communication::AppendBytesToCache (src = {1}, src_len = {2}, " - "broadcast = {3})", - this, bytes, (uint64_t)len, broadcast); - if ((bytes == nullptr || len == 0) && - (status != lldb::eConnectionStatusEndOfFile)) - return; - if (m_callback) { - // If the user registered a callback, then call it and do not broadcast - m_callback(m_callback_baton, bytes, len); - } else if (bytes != nullptr && len > 0) { - std::lock_guard<std::recursive_mutex> guard(m_bytes_mutex); - m_bytes.append((const char *)bytes, len); - if (broadcast) - BroadcastEventIfUnique(eBroadcastBitReadThreadGotBytes); - } -} - size_t Communication::ReadFromConnection(void *dst, size_t dst_len, const Timeout<std::micro> &timeout, ConnectionStatus &status, @@ -309,114 +138,8 @@ size_t Communication::ReadFromConnection(void *dst, size_t dst_len, return 0; } -bool Communication::ReadThreadIsRunning() { return m_read_thread_enabled; } - -lldb::thread_result_t Communication::ReadThread() { - Log *log = GetLog(LLDBLog::Communication); - - LLDB_LOG(log, "Communication({0}) thread starting...", this); - - uint8_t buf[1024]; - - Status error; - ConnectionStatus status = eConnectionStatusSuccess; - bool done = false; - bool disconnect = false; - while (!done && m_read_thread_enabled) { - size_t bytes_read = ReadFromConnection( - buf, sizeof(buf), std::chrono::seconds(5), status, &error); - if (bytes_read > 0 || status == eConnectionStatusEndOfFile) - AppendBytesToCache(buf, bytes_read, true, status); - - switch (status) { - case eConnectionStatusSuccess: - break; - - case eConnectionStatusEndOfFile: - done = true; - disconnect = GetCloseOnEOF(); - break; - case eConnectionStatusError: // Check GetError() for details - if (error.GetType() == eErrorTypePOSIX && error.GetError() == EIO) { - // EIO on a pipe is usually caused by remote shutdown - disconnect = GetCloseOnEOF(); - done = true; - } - if (error.Fail()) - LLDB_LOG(log, "error: {0}, status = {1}", error, - Communication::ConnectionStatusAsString(status)); - break; - case eConnectionStatusInterrupted: // Synchronization signal from - // SynchronizeWithReadThread() - // The connection returns eConnectionStatusInterrupted only when there is - // no input pending to be read, so we can signal that. - BroadcastEvent(eBroadcastBitNoMorePendingInput); - break; - case eConnectionStatusNoConnection: // No connection - case eConnectionStatusLostConnection: // Lost connection while connected to - // a valid connection - done = true; - LLVM_FALLTHROUGH; - case eConnectionStatusTimedOut: // Request timed out - if (error.Fail()) - LLDB_LOG(log, "error: {0}, status = {1}", error, - Communication::ConnectionStatusAsString(status)); - break; - } - } - log = GetLog(LLDBLog::Communication); - LLDB_LOG(log, "Communication({0}) thread exiting...", this); - - // Handle threads wishing to synchronize with us. - { - // Prevent new ones from showing up. - m_read_thread_did_exit = true; - - // Unblock any existing thread waiting for the synchronization signal. - BroadcastEvent(eBroadcastBitNoMorePendingInput); - - // Wait for the thread to finish... - std::lock_guard<std::mutex> guard(m_synchronize_mutex); - // ... and disconnect. - if (disconnect) - Disconnect(); - } - - // Let clients know that this thread is exiting - BroadcastEvent(eBroadcastBitReadThreadDidExit); - return {}; -} - -void Communication::SetReadThreadBytesReceivedCallback( - ReadThreadBytesReceived callback, void *callback_baton) { - m_callback = callback; - m_callback_baton = callback_baton; -} - -void Communication::SynchronizeWithReadThread() { - // Only one thread can do the synchronization dance at a time. - std::lock_guard<std::mutex> guard(m_synchronize_mutex); - - // First start listening for the synchronization event. - ListenerSP listener_sp( - Listener::MakeListener("Communication::SyncronizeWithReadThread")); - listener_sp->StartListeningForEvents(this, eBroadcastBitNoMorePendingInput); - - // If the thread is not running, there is no point in synchronizing. - if (!m_read_thread_enabled || m_read_thread_did_exit) - return; - - // Notify the read thread. - m_connection_sp->InterruptRead(); - - // Wait for the synchronization event. - EventSP event_sp; - listener_sp->GetEvent(event_sp, llvm::None); -} - void Communication::SetConnection(std::unique_ptr<Connection> connection) { Disconnect(nullptr); - StopReadThread(nullptr); m_connection_sp = std::move(connection); } diff --git a/contrib/llvm-project/lldb/source/Core/CoreProperties.td b/contrib/llvm-project/lldb/source/Core/CoreProperties.td index 46eeb1b5ed70..a4a6213e1447 100644 --- a/contrib/llvm-project/lldb/source/Core/CoreProperties.td +++ b/contrib/llvm-project/lldb/source/Core/CoreProperties.td @@ -5,6 +5,10 @@ let Definition = "modulelist" in { Global, DefaultTrue, Desc<"Control the use of external tools and repositories to locate symbol files. Directories listed in target.debug-file-search-paths and directory of the executable are always checked first for separate debug info files. Then depending on this setting: On macOS, Spotlight would be also used to locate a matching .dSYM bundle based on the UUID of the executable. On NetBSD, directory /usr/libdata/debug would be also searched. On platforms other than NetBSD directory /usr/lib/debug would be also searched.">; + def EnableBackgroundLookup: Property<"enable-background-lookup", "Boolean">, + Global, + DefaultFalse, + Desc<"On macOS, enable calling dsymForUUID (or an equivalent script/binary) in the background to locate symbol files that weren't found.">; def ClangModulesCachePath: Property<"clang-modules-cache-path", "FileSpec">, Global, DefaultStringValue<"">, @@ -174,7 +178,7 @@ let Definition = "debugger" in { def FrameFormatUnique: Property<"frame-format-unique", "FormatEntity">, Global, DefaultStringValue<"frame #${frame.index}: ${ansi.fg.yellow}${frame.pc}${ansi.normal}{ ${module.file.basename}{`${function.name-without-args}{${frame.no-debug}${function.pc-offset}}}}{ at ${ansi.fg.cyan}${line.file.basename}${ansi.normal}:${ansi.fg.yellow}${line.number}${ansi.normal}{:${ansi.fg.yellow}${line.column}${ansi.normal}}}{${function.is-optimized} [opt]}{${frame.is-artificial} [artificial]}\\\\n">, - Desc<"The default frame format string to use when displaying stack frameinformation for threads from thread backtrace unique.">; + Desc<"The default frame format string to use when displaying stack frame information for threads from thread backtrace unique.">; def ShowAutosuggestion: Property<"show-autosuggestion", "Boolean">, Global, DefaultFalse, @@ -187,4 +191,9 @@ let Definition = "debugger" in { Global, DefaultStringValue<"${ansi.normal}">, Desc<"When displaying suggestion in a color-enabled terminal, use the ANSI terminal code specified in this format immediately after the suggestion.">; + def DWIMPrintVerbosity: Property<"dwim-print-verbosity", "Enum">, + Global, + DefaultEnumValue<"eDWIMPrintVerbosityExpression">, + EnumValues<"OptionEnumValues(g_dwim_print_verbosities)">, + Desc<"The verbosity level used by dwim-print.">; } diff --git a/contrib/llvm-project/lldb/source/Core/DataFileCache.cpp b/contrib/llvm-project/lldb/source/Core/DataFileCache.cpp index b38adfda169a..b29327db5ca3 100644 --- a/contrib/llvm-project/lldb/source/Core/DataFileCache.cpp +++ b/contrib/llvm-project/lldb/source/Core/DataFileCache.cpp @@ -15,30 +15,37 @@ #include "lldb/Utility/LLDBLog.h" #include "lldb/Utility/Log.h" #include "llvm/Support/CachePruning.h" -#include "llvm/Support/MemoryBuffer.h" using namespace lldb_private; -DataFileCache::DataFileCache(llvm::StringRef path) { - m_cache_dir.SetPath(path); - // Prune the cache based off of the LLDB settings each time we create a cache - // object. - ModuleListProperties &properties = - ModuleList::GetGlobalModuleListProperties(); - llvm::CachePruningPolicy policy; - // Only scan once an hour. If we have lots of debug sessions we don't want - // to scan this directory too often. A timestamp file is written to the - // directory to ensure different processes don't scan the directory too often. - // This setting doesn't mean that a thread will continually scan the cache - // directory within this process. - policy.Interval = std::chrono::hours(1); - // Get the user settings for pruning. - policy.MaxSizeBytes = properties.GetLLDBIndexCacheMaxByteSize(); - policy.MaxSizePercentageOfAvailableSpace = - properties.GetLLDBIndexCacheMaxPercent(); - policy.Expiration = - std::chrono::hours(properties.GetLLDBIndexCacheExpirationDays() * 24); +llvm::CachePruningPolicy DataFileCache::GetLLDBIndexCachePolicy() { + static llvm::CachePruningPolicy policy; + static llvm::once_flag once_flag; + + llvm::call_once(once_flag, []() { + // Prune the cache based off of the LLDB settings each time we create a + // cache object. + ModuleListProperties &properties = + ModuleList::GetGlobalModuleListProperties(); + // Only scan once an hour. If we have lots of debug sessions we don't want + // to scan this directory too often. A timestamp file is written to the + // directory to ensure different processes don't scan the directory too + // often. This setting doesn't mean that a thread will continually scan the + // cache directory within this process. + policy.Interval = std::chrono::hours(1); + // Get the user settings for pruning. + policy.MaxSizeBytes = properties.GetLLDBIndexCacheMaxByteSize(); + policy.MaxSizePercentageOfAvailableSpace = + properties.GetLLDBIndexCacheMaxPercent(); + policy.Expiration = + std::chrono::hours(properties.GetLLDBIndexCacheExpirationDays() * 24); + }); + return policy; +} + +DataFileCache::DataFileCache(llvm::StringRef path, llvm::CachePruningPolicy policy) { + m_cache_dir.SetPath(path); pruneCache(path, policy); // This lambda will get called when the data is gotten from the cache and @@ -47,7 +54,8 @@ DataFileCache::DataFileCache(llvm::StringRef path) { // m_take_ownership member variable to indicate if we need to take // ownership. - auto add_buffer = [this](unsigned task, std::unique_ptr<llvm::MemoryBuffer> m) { + auto add_buffer = [this](unsigned task, const llvm::Twine &moduleName, + std::unique_ptr<llvm::MemoryBuffer> m) { if (m_take_ownership) m_mem_buff_up = std::move(m); }; @@ -73,7 +81,7 @@ DataFileCache::GetCachedData(llvm::StringRef key) { // turn take ownership of the member buffer that is passed to the callback and // put it into a member variable. llvm::Expected<llvm::AddStreamFn> add_stream_or_err = - m_cache_callback(task, key); + m_cache_callback(task, key, ""); m_take_ownership = false; // At this point we either already called the "add_buffer" lambda with // the data or we haven't. We can tell if we got the cached data by checking @@ -105,7 +113,7 @@ bool DataFileCache::SetCachedData(llvm::StringRef key, // add_buffer lambda function from the constructor which will ignore the // data. llvm::Expected<llvm::AddStreamFn> add_stream_or_err = - m_cache_callback(task, key); + m_cache_callback(task, key, ""); // If we reach this code then we either already called the callback with // the data or we haven't. We can tell if we had the cached data by checking // the CacheAddStream function pointer value below. @@ -120,7 +128,7 @@ bool DataFileCache::SetCachedData(llvm::StringRef key, // want to write the data. if (add_stream) { llvm::Expected<std::unique_ptr<llvm::CachedFileStream>> file_or_err = - add_stream(task); + add_stream(task, ""); if (file_or_err) { llvm::CachedFileStream *cfs = file_or_err->get(); cfs->OS->write((const char *)data.data(), data.size()); @@ -230,7 +238,7 @@ bool CacheSignature::Decode(const lldb_private::DataExtractor &data, const uint8_t length = data.GetU8(offset_ptr); const uint8_t *bytes = (const uint8_t *)data.GetData(offset_ptr, length); if (bytes != nullptr && length > 0) - m_uuid = UUID::fromData(llvm::ArrayRef<uint8_t>(bytes, length)); + m_uuid = UUID(llvm::ArrayRef<uint8_t>(bytes, length)); } break; case eSignatureModTime: { uint32_t mod_time = data.GetU32(offset_ptr); @@ -311,3 +319,4 @@ llvm::StringRef StringTableReader::Get(uint32_t offset) const { return llvm::StringRef(); return llvm::StringRef(m_data.data() + offset); } + diff --git a/contrib/llvm-project/lldb/source/Core/Debugger.cpp b/contrib/llvm-project/lldb/source/Core/Debugger.cpp index 62857c181af8..8a8a01c70ce6 100644 --- a/contrib/llvm-project/lldb/source/Core/Debugger.cpp +++ b/contrib/llvm-project/lldb/source/Core/Debugger.cpp @@ -13,6 +13,7 @@ #include "lldb/Core/FormatEntity.h" #include "lldb/Core/Mangled.h" #include "lldb/Core/ModuleList.h" +#include "lldb/Core/ModuleSpec.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/StreamAsynchronousIO.h" #include "lldb/Core/StreamFile.h" @@ -43,22 +44,21 @@ #include "lldb/Target/Thread.h" #include "lldb/Target/ThreadList.h" #include "lldb/Utility/AnsiTerminal.h" +#include "lldb/Utility/Diagnostics.h" #include "lldb/Utility/Event.h" #include "lldb/Utility/LLDBLog.h" #include "lldb/Utility/Listener.h" #include "lldb/Utility/Log.h" -#include "lldb/Utility/Reproducer.h" -#include "lldb/Utility/ReproducerProvider.h" #include "lldb/Utility/State.h" #include "lldb/Utility/Stream.h" #include "lldb/Utility/StreamString.h" +#include "lldb/lldb-enumerations.h" #if defined(_WIN32) #include "lldb/Host/windows/PosixApi.h" #include "lldb/Host/windows/windows.h" #endif -#include "llvm/ADT/None.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/iterator.h" @@ -75,6 +75,7 @@ #include <list> #include <memory> #include <mutex> +#include <optional> #include <set> #include <string> #include <system_error> @@ -104,6 +105,7 @@ static std::recursive_mutex *g_debugger_list_mutex_ptr = nullptr; // NOTE: intentional leak to avoid issues with C++ destructor chain static DebuggerList *g_debugger_list_ptr = nullptr; // NOTE: intentional leak to avoid issues with C++ destructor chain +static llvm::ThreadPool *g_thread_pool = nullptr; static constexpr OptionEnumValueElement g_show_disassembly_enum_values[] = { { @@ -148,6 +150,16 @@ static constexpr OptionEnumValueElement g_language_enumerators[] = { }, }; +static constexpr OptionEnumValueElement g_dwim_print_verbosities[] = { + {eDWIMPrintVerbosityNone, "none", + "Use no verbosity when running dwim-print."}, + {eDWIMPrintVerbosityExpression, "expression", + "Use partial verbosity when running dwim-print - display a message when " + "`expression` evaluation is used."}, + {eDWIMPrintVerbosityFull, "full", + "Use full verbosity when running dwim-print."}, +}; + static constexpr OptionEnumValueElement s_stop_show_column_values[] = { { eStopShowColumnAnsiOrCaret, @@ -201,7 +213,7 @@ Status Debugger::SetPropertyValue(const ExecutionContext *exe_ctx, } TargetSP target_sp; - LoadScriptFromSymFile load_script_old_value; + LoadScriptFromSymFile load_script_old_value = eLoadScriptFromSymFileFalse; if (is_load_script && exe_ctx->GetTargetSP()) { target_sp = exe_ctx->GetTargetSP(); load_script_old_value = @@ -300,11 +312,6 @@ void Debugger::SetPrompt(llvm::StringRef p) { GetCommandInterpreter().UpdatePrompt(new_prompt); } -llvm::StringRef Debugger::GetReproducerPath() const { - auto &r = repro::Reproducer::Instance(); - return r.GetReproducerPath().GetCString(); -} - const FormatEntity::Entry *Debugger::GetThreadFormat() const { const uint32_t idx = ePropertyThreadFormat; return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx); @@ -524,6 +531,13 @@ bool Debugger::SetTabSize(uint32_t tab_size) { return m_collection_sp->SetPropertyAtIndexAsUInt64(nullptr, idx, tab_size); } +lldb::DWIMPrintVerbosity Debugger::GetDWIMPrintVerbosity() const { + const uint32_t idx = ePropertyDWIMPrintVerbosity; + return (lldb::DWIMPrintVerbosity) + m_collection_sp->GetPropertyAtIndexAsEnumeration( + nullptr, idx, g_debugger_properties[idx].default_uint_value); +} + #pragma mark Debugger // const DebuggerPropertiesSP & @@ -538,6 +552,7 @@ void Debugger::Initialize(LoadPluginCallbackType load_plugin_callback) { "Debugger::Initialize called more than once!"); g_debugger_list_mutex_ptr = new std::recursive_mutex(); g_debugger_list_ptr = new DebuggerList(); + g_thread_pool = new llvm::ThreadPool(llvm::optimal_concurrency()); g_load_plugin_callback = load_plugin_callback; } @@ -545,6 +560,11 @@ void Debugger::Terminate() { assert(g_debugger_list_ptr && "Debugger::Terminate called without a matching Debugger::Initialize!"); + if (g_thread_pool) { + // The destructor will wait for all the threads to complete. + delete g_thread_pool; + } + if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) { // Clear our global list of debugger objects { @@ -916,42 +936,12 @@ Status Debugger::SetInputString(const char *data) { return result; } - return SetInputFile( - (FileSP)std::make_shared<NativeFile>(commands_file, true)); -} - -Status Debugger::SetInputFile(FileSP file_sp) { - Status error; - repro::DataRecorder *recorder = nullptr; - if (repro::Generator *g = repro::Reproducer::Instance().GetGenerator()) - recorder = g->GetOrCreate<repro::CommandProvider>().GetNewRecorder(); - - static std::unique_ptr<repro::MultiLoader<repro::CommandProvider>> loader = - repro::MultiLoader<repro::CommandProvider>::Create( - repro::Reproducer::Instance().GetLoader()); - if (loader) { - llvm::Optional<std::string> nextfile = loader->GetNextFile(); - FILE *fh = nextfile ? FileSystem::Instance().Fopen(nextfile->c_str(), "r") - : nullptr; - // FIXME Jonas Devlieghere: shouldn't this error be propagated out to the - // reproducer somehow if fh is NULL? - if (fh) { - file_sp = std::make_shared<NativeFile>(fh, true); - } - } - - if (!file_sp || !file_sp->IsValid()) { - error.SetErrorString("invalid file"); - return error; - } - - SetInputFile(file_sp, recorder); - return error; + SetInputFile((FileSP)std::make_shared<NativeFile>(commands_file, true)); + return result; } -void Debugger::SetInputFile(FileSP file_sp, repro::DataRecorder *recorder) { +void Debugger::SetInputFile(FileSP file_sp) { assert(file_sp && file_sp->IsValid()); - m_input_recorder = recorder; m_input_file_sp = std::move(file_sp); // Save away the terminal state if that is relevant, so that we can restore // it in RestoreInputState. @@ -1311,7 +1301,7 @@ static void PrivateReportProgress(Debugger &debugger, uint64_t progress_id, void Debugger::ReportProgress(uint64_t progress_id, const std::string &message, uint64_t completed, uint64_t total, - llvm::Optional<lldb::user_id_t> debugger_id) { + std::optional<lldb::user_id_t> debugger_id) { // Check if this progress is for a specific debugger. if (debugger_id) { // It is debugger specific, grab it and deliver the event if the debugger @@ -1339,6 +1329,9 @@ static void PrivateReportDiagnostic(Debugger &debugger, bool debugger_specific) { uint32_t event_type = 0; switch (type) { + case DiagnosticEventData::Type::Info: + assert(false && "DiagnosticEventData::Type::Info should not be broadcast"); + return; case DiagnosticEventData::Type::Warning: event_type = Debugger::eBroadcastBitWarning; break; @@ -1364,10 +1357,19 @@ static void PrivateReportDiagnostic(Debugger &debugger, void Debugger::ReportDiagnosticImpl(DiagnosticEventData::Type type, std::string message, - llvm::Optional<lldb::user_id_t> debugger_id, + std::optional<lldb::user_id_t> debugger_id, std::once_flag *once) { auto ReportDiagnosticLambda = [&]() { - // Check if this progress is for a specific debugger. + // The diagnostic subsystem is optional but we still want to broadcast + // events when it's disabled. + if (Diagnostics::Enabled()) + Diagnostics::Instance().Report(message); + + // We don't broadcast info events. + if (type == DiagnosticEventData::Type::Info) + return; + + // Check if this diagnostic is for a specific debugger. if (debugger_id) { // It is debugger specific, grab it and deliver the event if the debugger // still exists. @@ -1376,8 +1378,8 @@ void Debugger::ReportDiagnosticImpl(DiagnosticEventData::Type type, PrivateReportDiagnostic(*debugger_sp, type, std::move(message), true); return; } - // The progress event is not debugger specific, iterate over all debuggers - // and deliver a progress event to each one. + // The diagnostic event is not debugger specific, iterate over all debuggers + // and deliver a diagnostic event to each one. if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) { std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); for (const auto &debugger : *g_debugger_list_ptr) @@ -1392,20 +1394,38 @@ void Debugger::ReportDiagnosticImpl(DiagnosticEventData::Type type, } void Debugger::ReportWarning(std::string message, - llvm::Optional<lldb::user_id_t> debugger_id, + std::optional<lldb::user_id_t> debugger_id, std::once_flag *once) { ReportDiagnosticImpl(DiagnosticEventData::Type::Warning, std::move(message), debugger_id, once); } void Debugger::ReportError(std::string message, - llvm::Optional<lldb::user_id_t> debugger_id, + std::optional<lldb::user_id_t> debugger_id, std::once_flag *once) { - ReportDiagnosticImpl(DiagnosticEventData::Type::Error, std::move(message), debugger_id, once); } +void Debugger::ReportInfo(std::string message, + std::optional<lldb::user_id_t> debugger_id, + std::once_flag *once) { + ReportDiagnosticImpl(DiagnosticEventData::Type::Info, std::move(message), + debugger_id, once); +} + +void Debugger::ReportSymbolChange(const ModuleSpec &module_spec) { + if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) { + std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); + for (DebuggerSP debugger_sp : *g_debugger_list_ptr) { + EventSP event_sp = std::make_shared<Event>( + Debugger::eBroadcastSymbolChange, + new SymbolChangeEventData(debugger_sp, module_spec)); + debugger_sp->GetBroadcaster().BroadcastEvent(event_sp); + } + } +} + static std::shared_ptr<LogHandler> CreateLogHandler(LogHandlerKind log_handler_kind, int fd, bool should_close, size_t buffer_size) { @@ -1474,7 +1494,7 @@ bool Debugger::EnableLog(llvm::StringRef channel, ScriptInterpreter * Debugger::GetScriptInterpreter(bool can_create, - llvm::Optional<lldb::ScriptLanguage> language) { + std::optional<lldb::ScriptLanguage> language) { std::lock_guard<std::recursive_mutex> locker(m_script_interpreter_mutex); lldb::ScriptLanguage script_language = language ? *language : GetScriptLanguage(); @@ -1702,8 +1722,8 @@ lldb::thread_result_t Debugger::DefaultEventHandler() { CommandInterpreter::eBroadcastBitAsynchronousErrorData); listener_sp->StartListeningForEvents( - &m_broadcaster, - eBroadcastBitProgress | eBroadcastBitWarning | eBroadcastBitError); + &m_broadcaster, eBroadcastBitProgress | eBroadcastBitWarning | + eBroadcastBitError | eBroadcastSymbolChange); // Let the thread that spawned us know that we have started up and that we // are now listening to all required events so no events get missed @@ -1712,7 +1732,7 @@ lldb::thread_result_t Debugger::DefaultEventHandler() { bool done = false; while (!done) { EventSP event_sp; - if (listener_sp->GetEvent(event_sp, llvm::None)) { + if (listener_sp->GetEvent(event_sp, std::nullopt)) { if (event_sp) { Broadcaster *broadcaster = event_sp->GetBroadcaster(); if (broadcaster) { @@ -1807,7 +1827,7 @@ bool Debugger::StartEventHandlerThread() { // event, we just need to wait an infinite amount of time for it (nullptr // timeout as the first parameter) lldb::EventSP event_sp; - listener_sp->GetEvent(event_sp, llvm::None); + listener_sp->GetEvent(event_sp, std::nullopt); } return m_event_handler_thread.IsJoinable(); } @@ -2005,11 +2025,7 @@ Status Debugger::RunREPL(LanguageType language, const char *repl_options) { } llvm::ThreadPool &Debugger::GetThreadPool() { - // NOTE: intentional leak to avoid issues with C++ destructor chain - static llvm::ThreadPool *g_thread_pool = nullptr; - static llvm::once_flag g_once_flag; - llvm::call_once(g_once_flag, []() { - g_thread_pool = new llvm::ThreadPool(llvm::optimal_concurrency()); - }); + assert(g_thread_pool && + "Debugger::GetThreadPool called before Debugger::Initialize"); return *g_thread_pool; } diff --git a/contrib/llvm-project/lldb/source/Core/DebuggerEvents.cpp b/contrib/llvm-project/lldb/source/Core/DebuggerEvents.cpp index 19693e91ab23..6b33af9e0ee1 100644 --- a/contrib/llvm-project/lldb/source/Core/DebuggerEvents.cpp +++ b/contrib/llvm-project/lldb/source/Core/DebuggerEvents.cpp @@ -7,9 +7,12 @@ //===----------------------------------------------------------------------===// #include "lldb/Core/DebuggerEvents.h" +#include "lldb/Core/Debugger.h" +#include "lldb/Core/Module.h" #include "llvm/Support/WithColor.h" using namespace lldb_private; +using namespace lldb; template <typename T> static const T *GetEventDataFromEventImpl(const Event *event_ptr) { @@ -48,6 +51,8 @@ ProgressEventData::GetEventDataFromEvent(const Event *event_ptr) { llvm::StringRef DiagnosticEventData::GetPrefix() const { switch (m_type) { + case Type::Info: + return "info"; case Type::Warning: return "warning"; case Type::Error: @@ -79,3 +84,37 @@ const DiagnosticEventData * DiagnosticEventData::GetEventDataFromEvent(const Event *event_ptr) { return GetEventDataFromEventImpl<DiagnosticEventData>(event_ptr); } + +ConstString SymbolChangeEventData::GetFlavorString() { + static ConstString g_flavor("SymbolChangeEventData"); + return g_flavor; +} + +ConstString SymbolChangeEventData::GetFlavor() const { + return SymbolChangeEventData::GetFlavorString(); +} + +const SymbolChangeEventData * +SymbolChangeEventData::GetEventDataFromEvent(const Event *event_ptr) { + return GetEventDataFromEventImpl<SymbolChangeEventData>(event_ptr); +} + +void SymbolChangeEventData::DoOnRemoval(Event *event_ptr) { + DebuggerSP debugger_sp(m_debugger_wp.lock()); + if (!debugger_sp) + return; + + for (TargetSP target_sp : debugger_sp->GetTargetList().Targets()) { + if (ModuleSP module_sp = + target_sp->GetImages().FindModule(m_module_spec.GetUUID())) { + { + std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); + if (!module_sp->GetSymbolFileFileSpec()) + module_sp->SetSymbolFileFileSpec(m_module_spec.GetSymbolFileSpec()); + } + ModuleList module_list; + module_list.Append(module_sp); + target_sp->SymbolsDidLoad(module_list); + } + } +} diff --git a/contrib/llvm-project/lldb/source/Core/DumpDataExtractor.cpp b/contrib/llvm-project/lldb/source/Core/DumpDataExtractor.cpp index c48250b07d16..7f6108f40c59 100644 --- a/contrib/llvm-project/lldb/source/Core/DumpDataExtractor.cpp +++ b/contrib/llvm-project/lldb/source/Core/DumpDataExtractor.cpp @@ -30,7 +30,6 @@ #include "llvm/ADT/APFloat.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallVector.h" #include <limits> @@ -43,6 +42,7 @@ #include <cmath> #include <bitset> +#include <optional> #include <sstream> using namespace lldb_private; @@ -50,30 +50,11 @@ using namespace lldb; #define NON_PRINTABLE_CHAR '.' -static float half2float(uint16_t half) { - union { - float f; - uint32_t u; - } u; - // Sign extend to 4 byte. - int32_t sign_extended = static_cast<int16_t>(half); - uint32_t v = static_cast<uint32_t>(sign_extended); - - if (0 == (v & 0x7c00)) { - u.u = v & 0x80007FFFU; - return u.f * ldexpf(1, 125); - } - - v <<= 13; - u.u = v | 0x70000000U; - return u.f * ldexpf(1, -112); -} - -static llvm::Optional<llvm::APInt> GetAPInt(const DataExtractor &data, - lldb::offset_t *offset_ptr, - lldb::offset_t byte_size) { +static std::optional<llvm::APInt> GetAPInt(const DataExtractor &data, + lldb::offset_t *offset_ptr, + lldb::offset_t byte_size) { if (byte_size == 0) - return llvm::None; + return std::nullopt; llvm::SmallVector<uint64_t, 2> uint64_array; lldb::offset_t bytes_left = byte_size; @@ -111,15 +92,15 @@ static llvm::Optional<llvm::APInt> GetAPInt(const DataExtractor &data, *offset_ptr += byte_size; return llvm::APInt(byte_size * 8, llvm::ArrayRef<uint64_t>(uint64_array)); } - return llvm::None; + return std::nullopt; } static lldb::offset_t DumpAPInt(Stream *s, const DataExtractor &data, lldb::offset_t offset, lldb::offset_t byte_size, bool is_signed, unsigned radix) { - llvm::Optional<llvm::APInt> apint = GetAPInt(data, &offset, byte_size); + std::optional<llvm::APInt> apint = GetAPInt(data, &offset, byte_size); if (apint) { - std::string apint_str = toString(apint.value(), radix, is_signed); + std::string apint_str = toString(*apint, radix, is_signed); switch (radix) { case 2: s->Write("0b", 2); @@ -257,27 +238,27 @@ void DumpFloatingPoint(std::ostringstream &ss, FloatT f) { ss << f; } -static llvm::Optional<MemoryTagMap> +static std::optional<MemoryTagMap> GetMemoryTags(lldb::addr_t addr, size_t length, ExecutionContextScope *exe_scope) { assert(addr != LLDB_INVALID_ADDRESS); if (!exe_scope) - return llvm::None; + return std::nullopt; TargetSP target_sp = exe_scope->CalculateTarget(); if (!target_sp) - return llvm::None; + return std::nullopt; ProcessSP process_sp = target_sp->CalculateProcess(); if (!process_sp) - return llvm::None; + return std::nullopt; llvm::Expected<const MemoryTagManager *> tag_manager_or_err = process_sp->GetMemoryTagManager(); if (!tag_manager_or_err) { llvm::consumeError(tag_manager_or_err.takeError()); - return llvm::None; + return std::nullopt; } MemoryRegionInfos memory_regions; @@ -291,10 +272,10 @@ GetMemoryTags(lldb::addr_t addr, size_t length, // for an error. if (!tagged_ranges_or_err) { llvm::consumeError(tagged_ranges_or_err.takeError()); - return llvm::None; + return std::nullopt; } if (tagged_ranges_or_err->empty()) - return llvm::None; + return std::nullopt; MemoryTagMap memory_tag_map(*tag_manager_or_err); for (const MemoryTagManager::TagRange &range : *tagged_ranges_or_err) { @@ -308,16 +289,15 @@ GetMemoryTags(lldb::addr_t addr, size_t length, } if (memory_tag_map.Empty()) - return llvm::None; + return std::nullopt; return memory_tag_map; } -static void -printMemoryTags(const DataExtractor &DE, Stream *s, lldb::addr_t addr, - size_t len, - const llvm::Optional<MemoryTagMap> &memory_tag_map) { - std::vector<llvm::Optional<lldb::addr_t>> tags = +static void printMemoryTags(const DataExtractor &DE, Stream *s, + lldb::addr_t addr, size_t len, + const std::optional<MemoryTagMap> &memory_tag_map) { + std::vector<std::optional<lldb::addr_t>> tags = memory_tag_map->GetTags(addr, len); // Only print if there is at least one tag for this line @@ -336,6 +316,28 @@ printMemoryTags(const DataExtractor &DE, Stream *s, lldb::addr_t addr, s->PutCString(")"); } +static const llvm::fltSemantics &GetFloatSemantics(const TargetSP &target_sp, + size_t byte_size) { + if (target_sp) { + auto type_system_or_err = + target_sp->GetScratchTypeSystemForLanguage(eLanguageTypeC); + if (!type_system_or_err) + llvm::consumeError(type_system_or_err.takeError()); + else if (auto ts = *type_system_or_err) + return ts->GetFloatTypeSemantics(byte_size); + } + // No target, just make a reasonable guess + switch(byte_size) { + case 2: + return llvm::APFloat::IEEEhalf(); + case 4: + return llvm::APFloat::IEEEsingle(); + case 8: + return llvm::APFloat::IEEEdouble(); + } + return llvm::APFloat::Bogus(); +} + lldb::offset_t lldb_private::DumpDataExtractor( const DataExtractor &DE, Stream *s, offset_t start_offset, lldb::Format item_format, size_t item_byte_size, size_t item_count, @@ -355,7 +357,7 @@ lldb::offset_t lldb_private::DumpDataExtractor( offset_t offset = start_offset; - llvm::Optional<MemoryTagMap> memory_tag_map = llvm::None; + std::optional<MemoryTagMap> memory_tag_map; if (show_memory_tags && base_addr != LLDB_INVALID_ADDRESS) memory_tag_map = GetMemoryTags(base_addr, DE.GetByteSize() - offset, exe_scope); @@ -645,70 +647,38 @@ lldb::offset_t lldb_private::DumpDataExtractor( case eFormatFloat: { TargetSP target_sp; - bool used_upfloat = false; if (exe_scope) target_sp = exe_scope->CalculateTarget(); - if (target_sp) { - auto type_system_or_err = - target_sp->GetScratchTypeSystemForLanguage(eLanguageTypeC); - if (!type_system_or_err) { - llvm::consumeError(type_system_or_err.takeError()); - } else { - auto &type_system = *type_system_or_err; - llvm::SmallVector<char, 256> sv; - // Show full precision when printing float values - const unsigned format_precision = 0; - const unsigned format_max_padding = - target_sp->GetMaxZeroPaddingInFloatFormat(); - - const auto &semantics = - type_system.GetFloatTypeSemantics(item_byte_size); - - // Recalculate the byte size in case of a difference. This is possible - // when item_byte_size is 16 (128-bit), because you could get back the - // x87DoubleExtended semantics which has a byte size of 10 (80-bit). - const size_t semantics_byte_size = - (llvm::APFloat::getSizeInBits(semantics) + 7) / 8; - llvm::Optional<llvm::APInt> apint = - GetAPInt(DE, &offset, semantics_byte_size); - if (apint) { - llvm::APFloat apfloat(semantics, apint.value()); - apfloat.toString(sv, format_precision, format_max_padding); - if (!sv.empty()) { - s->Printf("%*.*s", (int)sv.size(), (int)sv.size(), sv.data()); - used_upfloat = true; - } - } - } - } - if (!used_upfloat) { - std::ostringstream ss; - if (item_byte_size == sizeof(float) || item_byte_size == 2) { - float f; - if (item_byte_size == 2) { - uint16_t half = DE.GetU16(&offset); - f = half2float(half); - } else { - f = DE.GetFloat(&offset); - } - ss.precision(std::numeric_limits<float>::digits10); - DumpFloatingPoint(ss, f); - } else if (item_byte_size == sizeof(double)) { - ss.precision(std::numeric_limits<double>::digits10); - DumpFloatingPoint(ss, DE.GetDouble(&offset)); - } else if (item_byte_size == sizeof(long double) || - item_byte_size == 10) { - ss.precision(std::numeric_limits<long double>::digits10); - DumpFloatingPoint(ss, DE.GetLongDouble(&offset)); - } else { - s->Printf("error: unsupported byte size (%" PRIu64 - ") for float format", - (uint64_t)item_byte_size); - return offset; - } - ss.flush(); - s->Printf("%s", ss.str().c_str()); + std::optional<unsigned> format_max_padding; + if (target_sp) + format_max_padding = target_sp->GetMaxZeroPaddingInFloatFormat(); + + // Show full precision when printing float values + const unsigned format_precision = 0; + + const llvm::fltSemantics &semantics = + GetFloatSemantics(target_sp, item_byte_size); + + // Recalculate the byte size in case of a difference. This is possible + // when item_byte_size is 16 (128-bit), because you could get back the + // x87DoubleExtended semantics which has a byte size of 10 (80-bit). + const size_t semantics_byte_size = + (llvm::APFloat::getSizeInBits(semantics) + 7) / 8; + std::optional<llvm::APInt> apint = + GetAPInt(DE, &offset, semantics_byte_size); + if (apint) { + llvm::APFloat apfloat(semantics, *apint); + llvm::SmallVector<char, 256> sv; + if (format_max_padding) + apfloat.toString(sv, format_precision, *format_max_padding); + else + apfloat.toString(sv, format_precision); + s->AsRawOstream() << sv; + } else { + s->Format("error: unsupported byte size ({0}) for float format", + item_byte_size); + return offset; } } break; diff --git a/contrib/llvm-project/lldb/source/Core/DumpRegisterValue.cpp b/contrib/llvm-project/lldb/source/Core/DumpRegisterValue.cpp index 2018d618f1d1..14659e03f18b 100644 --- a/contrib/llvm-project/lldb/source/Core/DumpRegisterValue.cpp +++ b/contrib/llvm-project/lldb/source/Core/DumpRegisterValue.cpp @@ -15,64 +15,65 @@ using namespace lldb; -bool lldb_private::DumpRegisterValue(const RegisterValue ®_val, Stream *s, +void lldb_private::DumpRegisterValue(const RegisterValue ®_val, Stream *s, const RegisterInfo *reg_info, bool prefix_with_name, bool prefix_with_alt_name, Format format, - uint32_t reg_name_right_align_at) { + uint32_t reg_name_right_align_at, + ExecutionContextScope *exe_scope) { DataExtractor data; - if (reg_val.GetData(data)) { - bool name_printed = false; - // For simplicity, alignment of the register name printing applies only in - // the most common case where: - // - // prefix_with_name^prefix_with_alt_name is true - // - StreamString format_string; - if (reg_name_right_align_at && (prefix_with_name ^ prefix_with_alt_name)) - format_string.Printf("%%%us", reg_name_right_align_at); - else - format_string.Printf("%%s"); - std::string fmt = std::string(format_string.GetString()); - if (prefix_with_name) { - if (reg_info->name) { - s->Printf(fmt.c_str(), reg_info->name); - name_printed = true; - } else if (reg_info->alt_name) { - s->Printf(fmt.c_str(), reg_info->alt_name); - prefix_with_alt_name = false; - name_printed = true; - } - } - if (prefix_with_alt_name) { - if (name_printed) - s->PutChar('/'); - if (reg_info->alt_name) { - s->Printf(fmt.c_str(), reg_info->alt_name); - name_printed = true; - } else if (!name_printed) { - // No alternate name but we were asked to display a name, so show the - // main name - s->Printf(fmt.c_str(), reg_info->name); - name_printed = true; - } + if (!reg_val.GetData(data)) + return; + + bool name_printed = false; + // For simplicity, alignment of the register name printing applies only in + // the most common case where: + // + // prefix_with_name^prefix_with_alt_name is true + // + StreamString format_string; + if (reg_name_right_align_at && (prefix_with_name ^ prefix_with_alt_name)) + format_string.Printf("%%%us", reg_name_right_align_at); + else + format_string.Printf("%%s"); + std::string fmt = std::string(format_string.GetString()); + if (prefix_with_name) { + if (reg_info->name) { + s->Printf(fmt.c_str(), reg_info->name); + name_printed = true; + } else if (reg_info->alt_name) { + s->Printf(fmt.c_str(), reg_info->alt_name); + prefix_with_alt_name = false; + name_printed = true; } + } + if (prefix_with_alt_name) { if (name_printed) - s->PutCString(" = "); + s->PutChar('/'); + if (reg_info->alt_name) { + s->Printf(fmt.c_str(), reg_info->alt_name); + name_printed = true; + } else if (!name_printed) { + // No alternate name but we were asked to display a name, so show the + // main name + s->Printf(fmt.c_str(), reg_info->name); + name_printed = true; + } + } + if (name_printed) + s->PutCString(" = "); - if (format == eFormatDefault) - format = reg_info->format; + if (format == eFormatDefault) + format = reg_info->format; - DumpDataExtractor(data, s, - 0, // Offset in "data" - format, // Format to use when dumping - reg_info->byte_size, // item_byte_size - 1, // item_count - UINT32_MAX, // num_per_line - LLDB_INVALID_ADDRESS, // base_addr - 0, // item_bit_size - 0); // item_bit_offset - return true; - } - return false; + DumpDataExtractor(data, s, + 0, // Offset in "data" + format, // Format to use when dumping + reg_info->byte_size, // item_byte_size + 1, // item_count + UINT32_MAX, // num_per_line + LLDB_INVALID_ADDRESS, // base_addr + 0, // item_bit_size + 0, // item_bit_offset + exe_scope); } diff --git a/contrib/llvm-project/lldb/source/Core/DynamicLoader.cpp b/contrib/llvm-project/lldb/source/Core/DynamicLoader.cpp index 96e0d4ec6555..8849ccedbd48 100644 --- a/contrib/llvm-project/lldb/source/Core/DynamicLoader.cpp +++ b/contrib/llvm-project/lldb/source/Core/DynamicLoader.cpp @@ -13,11 +13,15 @@ #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/Section.h" +#include "lldb/Symbol/LocateSymbolFile.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Target/MemoryRegionInfo.h" +#include "lldb/Target/Platform.h" #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" #include "lldb/Utility/ConstString.h" +#include "lldb/Utility/LLDBLog.h" +#include "lldb/Utility/Log.h" #include "lldb/lldb-private-interfaces.h" #include "llvm/ADT/StringRef.h" @@ -58,7 +62,7 @@ DynamicLoader *DynamicLoader::FindPlugin(Process *process, DynamicLoader::DynamicLoader(Process *process) : m_process(process) {} -// Accessosors to the global setting as to whether to stop at image (shared +// Accessors to the global setting as to whether to stop at image (shared // library) loading/unloading. bool DynamicLoader::GetStopWhenImagesChange() const { @@ -171,6 +175,106 @@ ModuleSP DynamicLoader::LoadModuleAtAddress(const FileSpec &file, return nullptr; } +static ModuleSP ReadUnnamedMemoryModule(Process *process, addr_t addr, + llvm::StringRef name) { + char namebuf[80]; + if (name.empty()) { + snprintf(namebuf, sizeof(namebuf), "memory-image-0x%" PRIx64, addr); + name = namebuf; + } + return process->ReadModuleFromMemory(FileSpec(name), addr); +} + +ModuleSP DynamicLoader::LoadBinaryWithUUIDAndAddress( + Process *process, llvm::StringRef name, UUID uuid, addr_t value, + bool value_is_offset, bool force_symbol_search, bool notify) { + ModuleSP memory_module_sp; + ModuleSP module_sp; + PlatformSP platform_sp = process->GetTarget().GetPlatform(); + Target &target = process->GetTarget(); + Status error; + ModuleSpec module_spec; + module_spec.GetUUID() = uuid; + + if (!uuid.IsValid() && !value_is_offset) { + memory_module_sp = ReadUnnamedMemoryModule(process, value, name); + + if (memory_module_sp) + uuid = memory_module_sp->GetUUID(); + } + + if (uuid.IsValid()) { + ModuleSpec module_spec; + module_spec.GetUUID() = uuid; + + if (!module_sp) + module_sp = target.GetOrCreateModule(module_spec, false, &error); + + // If we haven't found a binary, or we don't have a SymbolFile, see + // if there is an external search tool that can find it. + if (force_symbol_search && + (!module_sp || !module_sp->GetSymbolFileFileSpec())) { + Symbols::DownloadObjectAndSymbolFile(module_spec, error, true); + if (FileSystem::Instance().Exists(module_spec.GetFileSpec())) { + module_sp = std::make_shared<Module>(module_spec); + } + } + } + + // If we couldn't find the binary anywhere else, as a last resort, + // read it out of memory. + if (!module_sp.get() && value != LLDB_INVALID_ADDRESS && !value_is_offset) { + if (!memory_module_sp) + memory_module_sp = ReadUnnamedMemoryModule(process, value, name); + if (memory_module_sp) + module_sp = memory_module_sp; + } + + Log *log = GetLog(LLDBLog::DynamicLoader); + if (module_sp.get()) { + // Ensure the Target has an architecture set in case + // we need it while processing this binary/eh_frame/debug info. + if (!target.GetArchitecture().IsValid()) + target.SetArchitecture(module_sp->GetArchitecture()); + target.GetImages().AppendIfNeeded(module_sp, false); + + bool changed = false; + if (module_sp->GetObjectFile()) { + if (value != LLDB_INVALID_ADDRESS) { + LLDB_LOGF(log, "Loading binary UUID %s at %s 0x%" PRIx64, + uuid.GetAsString().c_str(), + value_is_offset ? "offset" : "address", value); + module_sp->SetLoadAddress(target, value, value_is_offset, changed); + } else { + // No address/offset/slide, load the binary at file address, + // offset 0. + LLDB_LOGF(log, "Loading binary UUID %s at file address", + uuid.GetAsString().c_str()); + module_sp->SetLoadAddress(target, 0, true /* value_is_slide */, + changed); + } + } else { + // In-memory image, load at its true address, offset 0. + LLDB_LOGF(log, "Loading binary UUID %s from memory at address 0x%" PRIx64, + uuid.GetAsString().c_str(), value); + module_sp->SetLoadAddress(target, 0, true /* value_is_slide */, changed); + } + + if (notify) { + ModuleList added_module; + added_module.Append(module_sp, false); + target.ModulesDidLoad(added_module); + } + } else { + LLDB_LOGF(log, "Unable to find binary with UUID %s and load it at " + "%s 0x%" PRIx64, + uuid.GetAsString().c_str(), + value_is_offset ? "offset" : "address", value); + } + + return module_sp; +} + int64_t DynamicLoader::ReadUnsignedIntWithSizeInBytes(addr_t addr, int size_in_bytes) { Status error; diff --git a/contrib/llvm-project/lldb/source/Core/EmulateInstruction.cpp b/contrib/llvm-project/lldb/source/Core/EmulateInstruction.cpp index c352b0129382..ca830ccc04bc 100644 --- a/contrib/llvm-project/lldb/source/Core/EmulateInstruction.cpp +++ b/contrib/llvm-project/lldb/source/Core/EmulateInstruction.cpp @@ -29,6 +29,7 @@ #include <cstring> #include <memory> +#include <optional> #include <cinttypes> #include <cstdio> @@ -72,20 +73,29 @@ EmulateInstruction::FindPlugin(const ArchSpec &arch, EmulateInstruction::EmulateInstruction(const ArchSpec &arch) : m_arch(arch) {} -bool EmulateInstruction::ReadRegister(const RegisterInfo *reg_info, - RegisterValue ®_value) { - if (m_read_reg_callback != nullptr) - return m_read_reg_callback(this, m_baton, reg_info, reg_value); - return false; +std::optional<RegisterValue> +EmulateInstruction::ReadRegister(const RegisterInfo ®_info) { + if (m_read_reg_callback == nullptr) + return {}; + + RegisterValue reg_value; + bool success = m_read_reg_callback(this, m_baton, ®_info, reg_value); + if (success) + return reg_value; + return {}; } bool EmulateInstruction::ReadRegister(lldb::RegisterKind reg_kind, uint32_t reg_num, RegisterValue ®_value) { - RegisterInfo reg_info; - if (GetRegisterInfo(reg_kind, reg_num, reg_info)) - return ReadRegister(®_info, reg_value); - return false; + std::optional<RegisterInfo> reg_info = GetRegisterInfo(reg_kind, reg_num); + if (!reg_info) + return false; + + std::optional<RegisterValue> value = ReadRegister(*reg_info); + if (value) + reg_value = *value; + return value.has_value(); } uint64_t EmulateInstruction::ReadRegisterUnsigned(lldb::RegisterKind reg_kind, @@ -100,22 +110,24 @@ uint64_t EmulateInstruction::ReadRegisterUnsigned(lldb::RegisterKind reg_kind, return fail_value; } -uint64_t EmulateInstruction::ReadRegisterUnsigned(const RegisterInfo *reg_info, +uint64_t EmulateInstruction::ReadRegisterUnsigned(const RegisterInfo ®_info, uint64_t fail_value, bool *success_ptr) { - RegisterValue reg_value; - if (ReadRegister(reg_info, reg_value)) - return reg_value.GetAsUInt64(fail_value, success_ptr); - if (success_ptr) - *success_ptr = false; - return fail_value; + std::optional<RegisterValue> reg_value = ReadRegister(reg_info); + if (!reg_value) { + if (success_ptr) + *success_ptr = false; + return fail_value; + } + + return reg_value->GetAsUInt64(fail_value, success_ptr); } bool EmulateInstruction::WriteRegister(const Context &context, - const RegisterInfo *reg_info, + const RegisterInfo ®_info, const RegisterValue ®_value) { if (m_write_reg_callback != nullptr) - return m_write_reg_callback(this, m_baton, context, reg_info, reg_value); + return m_write_reg_callback(this, m_baton, context, ®_info, reg_value); return false; } @@ -123,9 +135,9 @@ bool EmulateInstruction::WriteRegister(const Context &context, lldb::RegisterKind reg_kind, uint32_t reg_num, const RegisterValue ®_value) { - RegisterInfo reg_info; - if (GetRegisterInfo(reg_kind, reg_num, reg_info)) - return WriteRegister(context, ®_info, reg_value); + std::optional<RegisterInfo> reg_info = GetRegisterInfo(reg_kind, reg_num); + if (reg_info) + return WriteRegister(context, *reg_info, reg_value); return false; } @@ -133,23 +145,21 @@ bool EmulateInstruction::WriteRegisterUnsigned(const Context &context, lldb::RegisterKind reg_kind, uint32_t reg_num, uint64_t uint_value) { - RegisterInfo reg_info; - if (GetRegisterInfo(reg_kind, reg_num, reg_info)) { + std::optional<RegisterInfo> reg_info = GetRegisterInfo(reg_kind, reg_num); + if (reg_info) { RegisterValue reg_value; - if (reg_value.SetUInt(uint_value, reg_info.byte_size)) - return WriteRegister(context, ®_info, reg_value); + if (reg_value.SetUInt(uint_value, reg_info->byte_size)) + return WriteRegister(context, *reg_info, reg_value); } return false; } bool EmulateInstruction::WriteRegisterUnsigned(const Context &context, - const RegisterInfo *reg_info, + const RegisterInfo ®_info, uint64_t uint_value) { - if (reg_info != nullptr) { - RegisterValue reg_value; - if (reg_value.SetUInt(uint_value, reg_info->byte_size)) - return WriteRegister(context, reg_info, reg_value); - } + RegisterValue reg_value; + if (reg_value.SetUInt(uint_value, reg_info.byte_size)) + return WriteRegister(context, reg_info, reg_value); return false; } @@ -440,7 +450,7 @@ void EmulateInstruction::Context::Dump(Stream &strm, break; } - switch (info_type) { + switch (GetInfoType()) { case eInfoTypeRegisterPlusOffset: strm.Printf(" (reg_plus_offset = %s%+" PRId64 ")", info.RegisterPlusOffset.reg.name, diff --git a/contrib/llvm-project/lldb/source/Core/FileSpecList.cpp b/contrib/llvm-project/lldb/source/Core/FileSpecList.cpp index 8eec8f499352..7fa511176e46 100644 --- a/contrib/llvm-project/lldb/source/Core/FileSpecList.cpp +++ b/contrib/llvm-project/lldb/source/Core/FileSpecList.cpp @@ -81,6 +81,58 @@ size_t FileSpecList::FindFileIndex(size_t start_idx, const FileSpec &file_spec, return UINT32_MAX; } +size_t FileSpecList::FindCompatibleIndex(size_t start_idx, + const FileSpec &file_spec) const { + const size_t num_files = m_files.size(); + if (start_idx >= num_files) + return UINT32_MAX; + + const bool file_spec_relative = file_spec.IsRelative(); + const bool file_spec_case_sensitive = file_spec.IsCaseSensitive(); + // When looking for files, we will compare only the filename if the directory + // argument is empty in file_spec + const bool full = !file_spec.GetDirectory().IsEmpty(); + + for (size_t idx = start_idx; idx < num_files; ++idx) { + const FileSpec &curr_file = m_files[idx]; + + // Always start by matching the filename first + if (!curr_file.FileEquals(file_spec)) + continue; + + // Only compare the full name if the we were asked to and if the current + // file entry has the a directory. If it doesn't have a directory then we + // only compare the filename. + if (FileSpec::Equal(curr_file, file_spec, full)) { + return idx; + } else if (curr_file.IsRelative() || file_spec_relative) { + llvm::StringRef curr_file_dir = curr_file.GetDirectory().GetStringRef(); + if (curr_file_dir.empty()) + return idx; // Basename match only for this file in the list + + // Check if we have a relative path in our file list, or if "file_spec" is + // relative, if so, check if either ends with the other. + llvm::StringRef file_spec_dir = file_spec.GetDirectory().GetStringRef(); + // We have a relative path in our file list, it matches if the + // specified path ends with this path, but we must ensure the full + // component matches (we don't want "foo/bar.cpp" to match "oo/bar.cpp"). + auto is_suffix = [](llvm::StringRef a, llvm::StringRef b, + bool case_sensitive) -> bool { + if (case_sensitive ? a.consume_back(b) : a.consume_back_insensitive(b)) + return a.empty() || a.endswith("/"); + return false; + }; + const bool case_sensitive = + file_spec_case_sensitive || curr_file.IsCaseSensitive(); + if (is_suffix(curr_file_dir, file_spec_dir, case_sensitive) || + is_suffix(file_spec_dir, curr_file_dir, case_sensitive)) + return idx; + } + } + + // We didn't find the file, return an invalid index + return UINT32_MAX; +} // Returns the FileSpec object at index "idx". If "idx" is out of range, then // an empty FileSpec object will be returned. const FileSpec &FileSpecList::GetFileSpecAtIndex(size_t idx) const { diff --git a/contrib/llvm-project/lldb/source/Core/FormatEntity.cpp b/contrib/llvm-project/lldb/source/Core/FormatEntity.cpp index 6e7f44e461fa..4f615a110652 100644 --- a/contrib/llvm-project/lldb/source/Core/FormatEntity.cpp +++ b/contrib/llvm-project/lldb/source/Core/FormatEntity.cpp @@ -618,11 +618,8 @@ static bool DumpRegister(Stream &s, StackFrame *frame, RegisterKind reg_kind, static ValueObjectSP ExpandIndexedExpression(ValueObject *valobj, size_t index, bool deref_pointer) { Log *log = GetLog(LLDBLog::DataFormatters); - const char *ptr_deref_format = "[%d]"; - std::string ptr_deref_buffer(10, 0); - ::sprintf(&ptr_deref_buffer[0], ptr_deref_format, index); - LLDB_LOGF(log, "[ExpandIndexedExpression] name to deref: %s", - ptr_deref_buffer.c_str()); + std::string name_to_deref = llvm::formatv("[{0}]", index); + LLDB_LOG(log, "[ExpandIndexedExpression] name to deref: {0}", name_to_deref); ValueObject::GetValueForExpressionPathOptions options; ValueObject::ExpressionPathEndResultType final_value_type; ValueObject::ExpressionPathScanEndReason reason_to_stop; @@ -630,8 +627,7 @@ static ValueObjectSP ExpandIndexedExpression(ValueObject *valobj, size_t index, (deref_pointer ? ValueObject::eExpressionPathAftermathDereference : ValueObject::eExpressionPathAftermathNothing); ValueObjectSP item = valobj->GetValueForExpressionPath( - ptr_deref_buffer.c_str(), &reason_to_stop, &final_value_type, options, - &what_next); + name_to_deref, &reason_to_stop, &final_value_type, options, &what_next); if (!item) { LLDB_LOGF(log, "[ExpandIndexedExpression] ERROR: why stopping = %d," @@ -696,7 +692,7 @@ static bool DumpValue(Stream &s, const SymbolContext *sc, case FormatEntity::Entry::Type::ScriptVariableSynthetic: is_script = true; - LLVM_FALLTHROUGH; + [[fallthrough]]; case FormatEntity::Entry::Type::VariableSynthetic: custom_format = entry.fmt; val_obj_display = (ValueObject::ValueObjectRepresentationStyle)entry.number; @@ -711,9 +707,6 @@ static bool DumpValue(Stream &s, const SymbolContext *sc, return false; } - if (valobj == nullptr) - return false; - ValueObject::ExpressionPathAftermath what_next = (do_deref_pointer ? ValueObject::eExpressionPathAftermathDereference : ValueObject::eExpressionPathAftermathNothing); @@ -828,7 +821,7 @@ static bool DumpValue(Stream &s, const SymbolContext *sc, bitfield_name.Printf("%s:%d", target->GetTypeName().AsCString(), target->GetBitfieldBitSize()); auto type_sp = std::make_shared<TypeNameSpecifierImpl>( - bitfield_name.GetString(), false); + bitfield_name.GetString(), lldb::eFormatterMatchExact); if (val_obj_display == ValueObject::eValueObjectRepresentationStyleSummary && !DataVisualization::GetSummaryForType(type_sp)) @@ -1042,6 +1035,71 @@ static inline bool IsToken(const char *var_name_begin, const char *var) { return (::strncmp(var_name_begin, var, strlen(var)) == 0); } +/// Parses the basename out of a demangled function name +/// that may include function arguments. Supports +/// template functions. +/// +/// Returns pointers to the opening and closing parenthesis of +/// `full_name`. Can return nullptr for either parenthesis if +/// none is exists. +static std::pair<char const *, char const *> +ParseBaseName(char const *full_name) { + const char *open_paren = strchr(full_name, '('); + const char *close_paren = nullptr; + const char *generic = strchr(full_name, '<'); + // if before the arguments list begins there is a template sign + // then scan to the end of the generic args before you try to find + // the arguments list + if (generic && open_paren && generic < open_paren) { + int generic_depth = 1; + ++generic; + for (; *generic && generic_depth > 0; generic++) { + if (*generic == '<') + generic_depth++; + if (*generic == '>') + generic_depth--; + } + if (*generic) + open_paren = strchr(generic, '('); + else + open_paren = nullptr; + } + + if (open_paren) { + if (IsToken(open_paren, "(anonymous namespace)")) { + open_paren = strchr(open_paren + strlen("(anonymous namespace)"), '('); + if (open_paren) + close_paren = strchr(open_paren, ')'); + } else + close_paren = strchr(open_paren, ')'); + } + + return {open_paren, close_paren}; +} + +/// Writes out the function name in 'full_name' to 'out_stream' +/// but replaces each argument type with the variable name +/// and the corresponding pretty-printed value +static void PrettyPrintFunctionNameWithArgs(Stream &out_stream, + char const *full_name, + ExecutionContextScope *exe_scope, + VariableList const &args) { + auto [open_paren, close_paren] = ParseBaseName(full_name); + if (open_paren) + out_stream.Write(full_name, open_paren - full_name + 1); + else { + out_stream.PutCString(full_name); + out_stream.PutChar('('); + } + + FormatEntity::PrettyPrintFunctionArguments(out_stream, args, exe_scope); + + if (close_paren) + out_stream.PutCString(close_paren); + else + out_stream.PutChar(')'); +} + bool FormatEntity::FormatStringRef(const llvm::StringRef &format_str, Stream &s, const SymbolContext *sc, const ExecutionContext *exe_ctx, @@ -1648,100 +1706,7 @@ bool FormatEntity::Format(const Entry &entry, Stream &s, variable_list_sp->AppendVariablesWithScope( eValueTypeVariableArgument, args); if (args.GetSize() > 0) { - const char *open_paren = strchr(cstr, '('); - const char *close_paren = nullptr; - const char *generic = strchr(cstr, '<'); - // if before the arguments list begins there is a template sign - // then scan to the end of the generic args before you try to find - // the arguments list - if (generic && open_paren && generic < open_paren) { - int generic_depth = 1; - ++generic; - for (; *generic && generic_depth > 0; generic++) { - if (*generic == '<') - generic_depth++; - if (*generic == '>') - generic_depth--; - } - if (*generic) - open_paren = strchr(generic, '('); - else - open_paren = nullptr; - } - if (open_paren) { - if (IsToken(open_paren, "(anonymous namespace)")) { - open_paren = - strchr(open_paren + strlen("(anonymous namespace)"), '('); - if (open_paren) - close_paren = strchr(open_paren, ')'); - } else - close_paren = strchr(open_paren, ')'); - } - - if (open_paren) - s.Write(cstr, open_paren - cstr + 1); - else { - s.PutCString(cstr); - s.PutChar('('); - } - const size_t num_args = args.GetSize(); - for (size_t arg_idx = 0; arg_idx < num_args; ++arg_idx) { - std::string buffer; - - VariableSP var_sp(args.GetVariableAtIndex(arg_idx)); - ValueObjectSP var_value_sp( - ValueObjectVariable::Create(exe_scope, var_sp)); - StreamString ss; - llvm::StringRef var_representation; - const char *var_name = var_value_sp->GetName().GetCString(); - if (var_value_sp->GetCompilerType().IsValid()) { - if (var_value_sp && exe_scope->CalculateTarget()) - var_value_sp = - var_value_sp->GetQualifiedRepresentationIfAvailable( - exe_scope->CalculateTarget() - ->TargetProperties::GetPreferDynamicValue(), - exe_scope->CalculateTarget() - ->TargetProperties::GetEnableSyntheticValue()); - if (var_value_sp->GetCompilerType().IsAggregateType() && - DataVisualization::ShouldPrintAsOneLiner(*var_value_sp)) { - static StringSummaryFormat format( - TypeSummaryImpl::Flags() - .SetHideItemNames(false) - .SetShowMembersOneLiner(true), - ""); - format.FormatObject(var_value_sp.get(), buffer, - TypeSummaryOptions()); - var_representation = buffer; - } else - var_value_sp->DumpPrintableRepresentation( - ss, - ValueObject::ValueObjectRepresentationStyle:: - eValueObjectRepresentationStyleSummary, - eFormatDefault, - ValueObject::PrintableRepresentationSpecialCases::eAllow, - false); - } - - if (!ss.GetString().empty()) - var_representation = ss.GetString(); - if (arg_idx > 0) - s.PutCString(", "); - if (var_value_sp->GetError().Success()) { - if (!var_representation.empty()) - s.Printf("%s=%s", var_name, var_representation.str().c_str()); - else - s.Printf("%s=%s at %s", var_name, - var_value_sp->GetTypeName().GetCString(), - var_value_sp->GetLocationAsCString()); - } else - s.Printf("%s=<unavailable>", var_name); - } - - if (close_paren) - s.PutCString(close_paren); - else - s.PutChar(')'); - + PrettyPrintFunctionNameWithArgs(s, cstr, exe_scope, args); } else { s.PutCString(cstr); } @@ -2450,3 +2415,55 @@ void FormatEntity::AutoComplete(CompletionRequest &request) { request.AddCompletions(new_matches); } } + +void FormatEntity::PrettyPrintFunctionArguments( + Stream &out_stream, VariableList const &args, + ExecutionContextScope *exe_scope) { + const size_t num_args = args.GetSize(); + for (size_t arg_idx = 0; arg_idx < num_args; ++arg_idx) { + std::string buffer; + + VariableSP var_sp(args.GetVariableAtIndex(arg_idx)); + ValueObjectSP var_value_sp(ValueObjectVariable::Create(exe_scope, var_sp)); + StreamString ss; + llvm::StringRef var_representation; + const char *var_name = var_value_sp->GetName().GetCString(); + if (var_value_sp->GetCompilerType().IsValid()) { + if (exe_scope && exe_scope->CalculateTarget()) + var_value_sp = var_value_sp->GetQualifiedRepresentationIfAvailable( + exe_scope->CalculateTarget() + ->TargetProperties::GetPreferDynamicValue(), + exe_scope->CalculateTarget() + ->TargetProperties::GetEnableSyntheticValue()); + if (var_value_sp->GetCompilerType().IsAggregateType() && + DataVisualization::ShouldPrintAsOneLiner(*var_value_sp)) { + static StringSummaryFormat format(TypeSummaryImpl::Flags() + .SetHideItemNames(false) + .SetShowMembersOneLiner(true), + ""); + format.FormatObject(var_value_sp.get(), buffer, TypeSummaryOptions()); + var_representation = buffer; + } else + var_value_sp->DumpPrintableRepresentation( + ss, + ValueObject::ValueObjectRepresentationStyle:: + eValueObjectRepresentationStyleSummary, + eFormatDefault, + ValueObject::PrintableRepresentationSpecialCases::eAllow, false); + } + + if (!ss.GetString().empty()) + var_representation = ss.GetString(); + if (arg_idx > 0) + out_stream.PutCString(", "); + if (var_value_sp->GetError().Success()) { + if (!var_representation.empty()) + out_stream.Printf("%s=%s", var_name, var_representation.str().c_str()); + else + out_stream.Printf("%s=%s at %s", var_name, + var_value_sp->GetTypeName().GetCString(), + var_value_sp->GetLocationAsCString()); + } else + out_stream.Printf("%s=<unavailable>", var_name); + } +} diff --git a/contrib/llvm-project/lldb/source/Core/Highlighter.cpp b/contrib/llvm-project/lldb/source/Core/Highlighter.cpp index 04d993b8305c..f49b778baba8 100644 --- a/contrib/llvm-project/lldb/source/Core/Highlighter.cpp +++ b/contrib/llvm-project/lldb/source/Core/Highlighter.cpp @@ -11,6 +11,7 @@ #include "lldb/Target/Language.h" #include "lldb/Utility/AnsiTerminal.h" #include "lldb/Utility/StreamString.h" +#include <optional> using namespace lldb_private; using namespace lldb_private::ansi; @@ -27,7 +28,7 @@ void HighlightStyle::ColorStyle::Set(llvm::StringRef prefix, void DefaultHighlighter::Highlight(const HighlightStyle &options, llvm::StringRef line, - llvm::Optional<size_t> cursor_pos, + std::optional<size_t> cursor_pos, llvm::StringRef previous_lines, Stream &s) const { // If we don't have a valid cursor, then we just print the line as-is. @@ -72,7 +73,7 @@ HighlighterManager::getHighlighterFor(lldb::LanguageType language_type, std::string Highlighter::Highlight(const HighlightStyle &options, llvm::StringRef line, - llvm::Optional<size_t> cursor_pos, + std::optional<size_t> cursor_pos, llvm::StringRef previous_lines) const { StreamString s; Highlight(options, line, cursor_pos, previous_lines, s); diff --git a/contrib/llvm-project/lldb/source/Core/IOHandler.cpp b/contrib/llvm-project/lldb/source/Core/IOHandler.cpp index db388ab48275..95957b6948fc 100644 --- a/contrib/llvm-project/lldb/source/Core/IOHandler.cpp +++ b/contrib/llvm-project/lldb/source/Core/IOHandler.cpp @@ -19,7 +19,6 @@ #include "lldb/Host/File.h" #include "lldb/Utility/AnsiTerminal.h" #include "lldb/Utility/Predicate.h" -#include "lldb/Utility/ReproducerProvider.h" #include "lldb/Utility/Status.h" #include "lldb/Utility/StreamString.h" #include "lldb/Utility/StringList.h" @@ -38,6 +37,7 @@ #include <memory> #include <mutex> +#include <optional> #include <cassert> #include <cctype> @@ -50,8 +50,6 @@ using namespace lldb; using namespace lldb_private; -using llvm::None; -using llvm::Optional; using llvm::StringRef; IOHandler::IOHandler(Debugger &debugger, IOHandler::Type type) @@ -59,19 +57,17 @@ IOHandler::IOHandler(Debugger &debugger, IOHandler::Type type) FileSP(), // Adopt STDIN from top input reader StreamFileSP(), // Adopt STDOUT from top input reader StreamFileSP(), // Adopt STDERR from top input reader - 0, // Flags - nullptr // Shadow file recorder + 0 // Flags + ) {} IOHandler::IOHandler(Debugger &debugger, IOHandler::Type type, const lldb::FileSP &input_sp, const lldb::StreamFileSP &output_sp, - const lldb::StreamFileSP &error_sp, uint32_t flags, - repro::DataRecorder *data_recorder) + const lldb::StreamFileSP &error_sp, uint32_t flags) : m_debugger(debugger), m_input_sp(input_sp), m_output_sp(output_sp), - m_error_sp(error_sp), m_data_recorder(data_recorder), m_popped(false), - m_flags(flags), m_type(type), m_user_data(nullptr), m_done(false), - m_active(false) { + m_error_sp(error_sp), m_popped(false), m_flags(flags), m_type(type), + m_user_data(nullptr), m_done(false), m_active(false) { // If any files are not specified, then adopt them from the top input reader. if (!m_input_sp || !m_output_sp || !m_error_sp) debugger.AdoptTopIOHandlerFilesIfInvalid(m_input_sp, m_output_sp, @@ -146,7 +142,7 @@ IOHandlerConfirm::IOHandlerConfirm(Debugger &debugger, llvm::StringRef prompt, llvm::StringRef(), // No continuation prompt false, // Multi-line false, // Don't colorize the prompt (i.e. the confirm message.) - 0, *this, nullptr), + 0, *this), m_default_response(default_response), m_user_response(default_response) { StreamString prompt_stream; prompt_stream.PutCString(prompt); @@ -202,7 +198,7 @@ void IOHandlerConfirm::IOHandlerInputComplete(IOHandler &io_handler, } } -llvm::Optional<std::string> +std::optional<std::string> IOHandlerDelegate::IOHandlerSuggestion(IOHandler &io_handler, llvm::StringRef line) { return io_handler.GetDebugger() @@ -231,7 +227,7 @@ IOHandlerEditline::IOHandlerEditline( const char *editline_name, // Used for saving history files llvm::StringRef prompt, llvm::StringRef continuation_prompt, bool multi_line, bool color_prompts, uint32_t line_number_start, - IOHandlerDelegate &delegate, repro::DataRecorder *data_recorder) + IOHandlerDelegate &delegate) : IOHandlerEditline(debugger, type, FileSP(), // Inherit input from top input reader StreamFileSP(), // Inherit output from top input reader @@ -239,7 +235,7 @@ IOHandlerEditline::IOHandlerEditline( 0, // Flags editline_name, // Used for saving history files prompt, continuation_prompt, multi_line, color_prompts, - line_number_start, delegate, data_recorder) {} + line_number_start, delegate) {} IOHandlerEditline::IOHandlerEditline( Debugger &debugger, IOHandler::Type type, const lldb::FileSP &input_sp, @@ -248,9 +244,8 @@ IOHandlerEditline::IOHandlerEditline( const char *editline_name, // Used for saving history files llvm::StringRef prompt, llvm::StringRef continuation_prompt, bool multi_line, bool color_prompts, uint32_t line_number_start, - IOHandlerDelegate &delegate, repro::DataRecorder *data_recorder) - : IOHandler(debugger, type, input_sp, output_sp, error_sp, flags, - data_recorder), + IOHandlerDelegate &delegate) + : IOHandler(debugger, type, input_sp, output_sp, error_sp, flags), #if LLDB_ENABLE_LIBEDIT m_editline_up(), #endif @@ -331,10 +326,10 @@ void IOHandlerEditline::TerminalSizeChanged() { } // Split out a line from the buffer, if there is a full one to get. -static Optional<std::string> SplitLine(std::string &line_buffer) { +static std::optional<std::string> SplitLine(std::string &line_buffer) { size_t pos = line_buffer.find('\n'); if (pos == std::string::npos) - return None; + return std::nullopt; std::string line = std::string(StringRef(line_buffer.c_str(), pos).rtrim("\n\r")); line_buffer = line_buffer.substr(pos + 1); @@ -343,9 +338,9 @@ static Optional<std::string> SplitLine(std::string &line_buffer) { // If the final line of the file ends without a end-of-line, return // it as a line anyway. -static Optional<std::string> SplitLineEOF(std::string &line_buffer) { +static std::optional<std::string> SplitLineEOF(std::string &line_buffer) { if (llvm::all_of(line_buffer, llvm::isSpace)) - return None; + return std::nullopt; std::string line = std::move(line_buffer); line_buffer.clear(); return line; @@ -354,10 +349,7 @@ static Optional<std::string> SplitLineEOF(std::string &line_buffer) { bool IOHandlerEditline::GetLine(std::string &line, bool &interrupted) { #if LLDB_ENABLE_LIBEDIT if (m_editline_up) { - bool b = m_editline_up->GetLine(line, interrupted); - if (b && m_data_recorder) - m_data_recorder->Record(line, true); - return b; + return m_editline_up->GetLine(line, interrupted); } #endif @@ -380,7 +372,7 @@ bool IOHandlerEditline::GetLine(std::string &line, bool &interrupted) { } } - Optional<std::string> got_line = SplitLine(m_line_buffer); + std::optional<std::string> got_line = SplitLine(m_line_buffer); if (!got_line && !m_input_sp) { // No more input file, we are done... @@ -437,8 +429,6 @@ bool IOHandlerEditline::GetLine(std::string &line, bool &interrupted) { if (got_line) { line = *got_line; - if (m_data_recorder) - m_data_recorder->Record(line, true); } return (bool)got_line; @@ -456,7 +446,7 @@ int IOHandlerEditline::FixIndentationCallback(Editline *editline, return m_delegate.IOHandlerFixIndentation(*this, lines, cursor_position); } -llvm::Optional<std::string> +std::optional<std::string> IOHandlerEditline::SuggestionCallback(llvm::StringRef line) { return m_delegate.IOHandlerSuggestion(*this, line); } diff --git a/contrib/llvm-project/lldb/source/Core/IOHandlerCursesGUI.cpp b/contrib/llvm-project/lldb/source/Core/IOHandlerCursesGUI.cpp index 0151255631bf..18d8affd58d8 100644 --- a/contrib/llvm-project/lldb/source/Core/IOHandlerCursesGUI.cpp +++ b/contrib/llvm-project/lldb/source/Core/IOHandlerCursesGUI.cpp @@ -75,6 +75,7 @@ #include <cstdio> #include <cstring> #include <functional> +#include <optional> #include <type_traits> using namespace lldb; @@ -588,9 +589,10 @@ public: } Window(const char *name, const Rect &bounds) - : Surface(Surface::Type::Window), m_name(name), m_parent(nullptr), - m_subwindows(), m_delegate_sp(), m_curr_active_window_idx(UINT32_MAX), - m_prev_active_window_idx(UINT32_MAX), m_delete(true), + : Surface(Surface::Type::Window), m_name(name), m_panel(nullptr), + m_parent(nullptr), m_subwindows(), m_delegate_sp(), + m_curr_active_window_idx(UINT32_MAX), + m_prev_active_window_idx(UINT32_MAX), m_delete(false), m_needs_update(true), m_can_activate(true), m_is_subwin(false) { Reset(::newwin(bounds.size.height, bounds.size.width, bounds.origin.y, bounds.origin.y)); @@ -3111,11 +3113,11 @@ public: static constexpr const char *kLoadDependentFilesExecOnly = "Executable only"; std::vector<std::string> GetLoadDependentFilesChoices() { - std::vector<std::string> load_depentents_options; - load_depentents_options.push_back(kLoadDependentFilesExecOnly); - load_depentents_options.push_back(kLoadDependentFilesYes); - load_depentents_options.push_back(kLoadDependentFilesNo); - return load_depentents_options; + std::vector<std::string> load_dependents_options; + load_dependents_options.push_back(kLoadDependentFilesExecOnly); + load_dependents_options.push_back(kLoadDependentFilesYes); + load_dependents_options.push_back(kLoadDependentFilesNo); + return load_dependents_options; } LoadDependentFiles GetLoadDependentFiles() { @@ -3170,7 +3172,7 @@ public: FileSpec core_file_spec = m_core_file_field->GetResolvedFileSpec(); FileSpec core_file_directory_spec; - core_file_directory_spec.GetDirectory() = core_file_spec.GetDirectory(); + core_file_directory_spec.SetDirectory(core_file_spec.GetDirectory()); target_sp->AppendExecutableSearchPaths(core_file_directory_spec); ProcessSP process_sp(target_sp->CreateProcess( @@ -3499,19 +3501,19 @@ public: FileAction action; if (m_standard_input_field->IsSpecified()) { - action.Open(STDIN_FILENO, m_standard_input_field->GetFileSpec(), true, - false); - launch_info.AppendFileAction(action); + if (action.Open(STDIN_FILENO, m_standard_input_field->GetFileSpec(), true, + false)) + launch_info.AppendFileAction(action); } if (m_standard_output_field->IsSpecified()) { - action.Open(STDOUT_FILENO, m_standard_output_field->GetFileSpec(), false, - true); - launch_info.AppendFileAction(action); + if (action.Open(STDOUT_FILENO, m_standard_output_field->GetFileSpec(), + false, true)) + launch_info.AppendFileAction(action); } if (m_standard_error_field->IsSpecified()) { - action.Open(STDERR_FILENO, m_standard_error_field->GetFileSpec(), false, - true); - launch_info.AppendFileAction(action); + if (action.Open(STDERR_FILENO, m_standard_error_field->GetFileSpec(), + false, true)) + launch_info.AppendFileAction(action); } } @@ -5702,8 +5704,8 @@ protected: uint32_t m_selected_row_idx = 0; uint32_t m_first_visible_row = 0; uint32_t m_num_rows = 0; - int m_min_x; - int m_min_y; + int m_min_x = 0; + int m_min_y = 0; int m_max_x = 0; int m_max_y = 0; @@ -5907,7 +5909,7 @@ public: if (m_frame_block != frame_block) { m_frame_block = frame_block; - VariableList *locals = frame->GetVariableList(true); + VariableList *locals = frame->GetVariableList(true, nullptr); if (locals) { const DynamicValueType use_dynamic = eDynamicDontRunTarget; for (const VariableSP &local_sp : *locals) { @@ -6820,7 +6822,7 @@ public: bool set_selected_line_to_pc = false; if (update_location) { - const bool process_alive = process ? process->IsAlive() : false; + const bool process_alive = process->IsAlive(); bool thread_changed = false; if (process_alive) { thread = exe_ctx.GetThreadPtr(); @@ -7023,7 +7025,7 @@ public: StreamString lineStream; - llvm::Optional<size_t> column; + std::optional<size_t> column; if (is_pc_line && m_sc.line_entry.IsValid() && m_sc.line_entry.column) column = m_sc.line_entry.column - 1; m_file_sp->DisplaySourceLines(curr_line + 1, column, 0, 0, @@ -7208,8 +7210,10 @@ public: window.Printf("%*s", desc_x - window.GetCursorX(), ""); window.MoveCursor(window_width - stop_description_len - 15, line_y); - window.PrintfTruncated(1, "<<< Thread %u: %s ", - thread->GetIndexID(), stop_description); + if (thread) + window.PrintfTruncated(1, "<<< Thread %u: %s ", + thread->GetIndexID(), + stop_description); } } else { window.Printf("%*s", window_width - window.GetCursorX() - 1, ""); diff --git a/contrib/llvm-project/lldb/source/Core/Module.cpp b/contrib/llvm-project/lldb/source/Core/Module.cpp index 893e20837124..8f9defabd76f 100644 --- a/contrib/llvm-project/lldb/source/Core/Module.cpp +++ b/contrib/llvm-project/lldb/source/Core/Module.cpp @@ -24,6 +24,7 @@ #include "lldb/Interpreter/ScriptInterpreter.h" #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/Function.h" +#include "lldb/Symbol/LocateSymbolFile.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/Symbol.h" #include "lldb/Symbol/SymbolContext.h" @@ -69,6 +70,7 @@ #include <cstdint> #include <cstring> #include <map> +#include <optional> #include <type_traits> #include <utility> @@ -363,11 +365,16 @@ void Module::SetUUID(const lldb_private::UUID &uuid) { } } -llvm::Expected<TypeSystem &> +llvm::Expected<TypeSystemSP> Module::GetTypeSystemForLanguage(LanguageType language) { return m_type_system_map.GetTypeSystemForLanguage(language, this, true); } +void Module::ForEachTypeSystem( + llvm::function_ref<bool(lldb::TypeSystemSP)> callback) { + m_type_system_map.ForEach(callback); +} + void Module::ParseAllDebugSymbols() { std::lock_guard<std::recursive_mutex> guard(m_mutex); size_t num_comp_units = GetNumCompileUnits(); @@ -413,8 +420,6 @@ void Module::DumpSymbolContext(Stream *s) { size_t Module::GetNumCompileUnits() { std::lock_guard<std::recursive_mutex> guard(m_mutex); - LLDB_SCOPED_TIMERF("Module::GetNumCompileUnits (module = %p)", - static_cast<void *>(this)); if (SymbolFile *symbols = GetSymbolFile()) return symbols->GetNumCompileUnits(); return 0; @@ -592,7 +597,7 @@ uint32_t Module::ResolveSymbolContextsForFileSpec( if (SymbolFile *symbols = GetSymbolFile()) { // TODO: Handle SourceLocationSpec column information - SourceLocationSpec location_spec(file_spec, line, /*column=*/llvm::None, + SourceLocationSpec location_spec(file_spec, line, /*column=*/std::nullopt, check_inlines, /*exact_match=*/false); symbols->ResolveSymbolContext(location_spec, resolve_scope, sc_list); @@ -727,6 +732,41 @@ Module::LookupInfo::LookupInfo(ConstString name, } } +bool Module::LookupInfo::NameMatchesLookupInfo( + ConstString function_name, LanguageType language_type) const { + // We always keep unnamed symbols + if (!function_name) + return true; + + // If we match exactly, we can return early + if (m_name == function_name) + return true; + + // If function_name is mangled, we'll need to demangle it. + // In the pathologial case where the function name "looks" mangled but is + // actually demangled (e.g. a method named _Zonk), this operation should be + // relatively inexpensive since no demangling is actually occuring. See + // Mangled::SetValue for more context. + const bool function_name_may_be_mangled = + Mangled::GetManglingScheme(function_name.GetStringRef()) != + Mangled::eManglingSchemeNone; + ConstString demangled_function_name = function_name; + if (function_name_may_be_mangled) { + Mangled mangled_function_name(function_name); + demangled_function_name = mangled_function_name.GetDemangledName(); + } + + // If the symbol has a language, then let the language make the match. + // Otherwise just check that the demangled function name contains the + // demangled user-provided name. + if (Language *language = Language::FindPlugin(language_type)) + return language->DemangledNameContainsPath(m_name.GetStringRef(), + demangled_function_name); + + llvm::StringRef function_name_ref = demangled_function_name.GetStringRef(); + return function_name_ref.contains(m_name.GetStringRef()); +} + void Module::LookupInfo::Prune(SymbolContextList &sc_list, size_t start_idx) const { if (m_match_name_after_lookup && m_name) { @@ -735,21 +775,9 @@ void Module::LookupInfo::Prune(SymbolContextList &sc_list, while (i < sc_list.GetSize()) { if (!sc_list.GetContextAtIndex(i, sc)) break; - - llvm::StringRef user_name = m_name.GetStringRef(); - bool keep_it = true; - Language *language = Language::FindPlugin(sc.GetLanguage()); - // If the symbol has a language, then let the language make the match. - // Otherwise just check that the demangled name contains the user name. - if (language) - keep_it = language->DemangledNameContainsPath(m_name.GetStringRef(), - sc.GetFunctionName()); - else { - llvm::StringRef full_name = sc.GetFunctionName().GetStringRef(); - // We always keep unnamed symbols: - if (!full_name.empty()) - keep_it = full_name.contains(user_name); - } + + bool keep_it = + NameMatchesLookupInfo(sc.GetFunctionName(), sc.GetLanguage()); if (keep_it) ++i; else @@ -798,51 +826,37 @@ void Module::LookupInfo::Prune(SymbolContextList &sc_list, } } -void Module::FindFunctions(ConstString name, +void Module::FindFunctions(const Module::LookupInfo &lookup_info, const CompilerDeclContext &parent_decl_ctx, - FunctionNameType name_type_mask, const ModuleFunctionSearchOptions &options, SymbolContextList &sc_list) { - const size_t old_size = sc_list.GetSize(); - // Find all the functions (not symbols, but debug information functions... - SymbolFile *symbols = GetSymbolFile(); - - if (name_type_mask & eFunctionNameTypeAuto) { - LookupInfo lookup_info(name, name_type_mask, eLanguageTypeUnknown); - - if (symbols) { - symbols->FindFunctions(lookup_info.GetLookupName(), parent_decl_ctx, - lookup_info.GetNameTypeMask(), - options.include_inlines, sc_list); - - // Now check our symbol table for symbols that are code symbols if - // requested - if (options.include_symbols) { - Symtab *symtab = symbols->GetSymtab(); - if (symtab) - symtab->FindFunctionSymbols(lookup_info.GetLookupName(), - lookup_info.GetNameTypeMask(), sc_list); + if (SymbolFile *symbols = GetSymbolFile()) { + symbols->FindFunctions(lookup_info, parent_decl_ctx, + options.include_inlines, sc_list); + // Now check our symbol table for symbols that are code symbols if + // requested + if (options.include_symbols) { + if (Symtab *symtab = symbols->GetSymtab()) { + symtab->FindFunctionSymbols(lookup_info.GetLookupName(), + lookup_info.GetNameTypeMask(), sc_list); } } + } +} +void Module::FindFunctions(ConstString name, + const CompilerDeclContext &parent_decl_ctx, + FunctionNameType name_type_mask, + const ModuleFunctionSearchOptions &options, + SymbolContextList &sc_list) { + const size_t old_size = sc_list.GetSize(); + LookupInfo lookup_info(name, name_type_mask, eLanguageTypeUnknown); + FindFunctions(lookup_info, parent_decl_ctx, options, sc_list); + if (name_type_mask & eFunctionNameTypeAuto) { const size_t new_size = sc_list.GetSize(); - if (old_size < new_size) lookup_info.Prune(sc_list, old_size); - } else { - if (symbols) { - symbols->FindFunctions(name, parent_decl_ctx, name_type_mask, - options.include_inlines, sc_list); - - // Now check our symbol table for symbols that are code symbols if - // requested - if (options.include_symbols) { - Symtab *symtab = symbols->GetSymtab(); - if (symtab) - symtab->FindFunctionSymbols(name, name_type_mask, sc_list); - } - } } } @@ -924,7 +938,7 @@ void Module::FindAddressesForLine(const lldb::TargetSP target_sp, SearchFilterByModule filter(target_sp, m_file); // TODO: Handle SourceLocationSpec column information - SourceLocationSpec location_spec(file, line, /*column=*/llvm::None, + SourceLocationSpec location_spec(file, line, /*column=*/std::nullopt, /*check_inlines=*/true, /*exact_match=*/false); AddressResolverFileLine resolver(location_spec); @@ -1112,7 +1126,7 @@ bool Module::FileHasChanged() const { } void Module::ReportWarningOptimization( - llvm::Optional<lldb::user_id_t> debugger_id) { + std::optional<lldb::user_id_t> debugger_id) { ConstString file_name = GetFileSpec().GetFilename(); if (file_name.IsEmpty()) return; @@ -1126,7 +1140,7 @@ void Module::ReportWarningOptimization( } void Module::ReportWarningUnsupportedLanguage( - LanguageType language, llvm::Optional<lldb::user_id_t> debugger_id) { + LanguageType language, std::optional<lldb::user_id_t> debugger_id) { StreamString ss; ss << "This version of LLDB has no plugin for the language \"" << Language::GetNameForLanguageType(language) @@ -1136,95 +1150,60 @@ void Module::ReportWarningUnsupportedLanguage( &m_language_warning); } -void Module::ReportErrorIfModifyDetected(const char *format, ...) { +void Module::ReportErrorIfModifyDetected( + const llvm::formatv_object_base &payload) { if (!m_first_file_changed_log) { if (FileHasChanged()) { m_first_file_changed_log = true; - if (format) { - StreamString strm; - strm.PutCString("the object file "); - GetDescription(strm.AsRawOstream(), lldb::eDescriptionLevelFull); - strm.PutCString(" has been modified\n"); - - va_list args; - va_start(args, format); - strm.PrintfVarArg(format, args); - va_end(args); - - const int format_len = strlen(format); - if (format_len > 0) { - const char last_char = format[format_len - 1]; - if (last_char != '\n' && last_char != '\r') - strm.EOL(); - } - strm.PutCString("The debug session should be aborted as the original " - "debug information has been overwritten."); - Debugger::ReportError(std::string(strm.GetString())); - } + StreamString strm; + strm.PutCString("the object file "); + GetDescription(strm.AsRawOstream(), lldb::eDescriptionLevelFull); + strm.PutCString(" has been modified\n"); + strm.PutCString(payload.str()); + strm.PutCString("The debug session should be aborted as the original " + "debug information has been overwritten."); + Debugger::ReportError(std::string(strm.GetString())); } } } -void Module::ReportError(const char *format, ...) { - if (format && format[0]) { - StreamString strm; - GetDescription(strm.AsRawOstream(), lldb::eDescriptionLevelBrief); - strm.PutChar(' '); - - va_list args; - va_start(args, format); - strm.PrintfVarArg(format, args); - va_end(args); - - Debugger::ReportError(std::string(strm.GetString())); - } -} - -void Module::ReportWarning(const char *format, ...) { - if (format && format[0]) { - StreamString strm; - GetDescription(strm.AsRawOstream(), lldb::eDescriptionLevelFull); - strm.PutChar(' '); - - va_list args; - va_start(args, format); - strm.PrintfVarArg(format, args); - va_end(args); - - Debugger::ReportWarning(std::string(strm.GetString())); - } -} - -void Module::LogMessage(Log *log, const char *format, ...) { - if (log != nullptr) { - StreamString log_message; - GetDescription(log_message.AsRawOstream(), lldb::eDescriptionLevelFull); - log_message.PutCString(": "); - va_list args; - va_start(args, format); - log_message.PrintfVarArg(format, args); - va_end(args); - log->PutCString(log_message.GetData()); - } -} - -void Module::LogMessageVerboseBacktrace(Log *log, const char *format, ...) { - if (log != nullptr) { - StreamString log_message; - GetDescription(log_message.AsRawOstream(), lldb::eDescriptionLevelFull); - log_message.PutCString(": "); - va_list args; - va_start(args, format); - log_message.PrintfVarArg(format, args); - va_end(args); - if (log->GetVerbose()) { - std::string back_trace; - llvm::raw_string_ostream stream(back_trace); - llvm::sys::PrintStackTrace(stream); - log_message.PutCString(back_trace); - } - log->PutCString(log_message.GetData()); +void Module::ReportError(const llvm::formatv_object_base &payload) { + StreamString strm; + GetDescription(strm.AsRawOstream(), lldb::eDescriptionLevelBrief); + strm.PutChar(' '); + strm.PutCString(payload.str()); + Debugger::ReportError(strm.GetString().str()); +} + +void Module::ReportWarning(const llvm::formatv_object_base &payload) { + StreamString strm; + GetDescription(strm.AsRawOstream(), lldb::eDescriptionLevelFull); + strm.PutChar(' '); + strm.PutCString(payload.str()); + Debugger::ReportWarning(std::string(strm.GetString())); +} + +void Module::LogMessage(Log *log, const llvm::formatv_object_base &payload) { + StreamString log_message; + GetDescription(log_message.AsRawOstream(), lldb::eDescriptionLevelFull); + log_message.PutCString(": "); + log_message.PutCString(payload.str()); + log->PutCString(log_message.GetData()); +} + +void Module::LogMessageVerboseBacktrace( + Log *log, const llvm::formatv_object_base &payload) { + StreamString log_message; + GetDescription(log_message.AsRawOstream(), lldb::eDescriptionLevelFull); + log_message.PutCString(": "); + log_message.PutCString(payload.str()); + if (log->GetVerbose()) { + std::string back_trace; + llvm::raw_string_ostream stream(back_trace); + llvm::sys::PrintStackTrace(stream); + log_message.PutCString(back_trace); } + log->PutCString(log_message.GetData()); } void Module::Dump(Stream *s) { @@ -1280,7 +1259,7 @@ ObjectFile *Module::GetObjectFile() { // those values that overwrite unspecified unknown values. m_arch.MergeFrom(m_objfile_sp->GetArchitecture()); } else { - ReportError("failed to load objfile for %s", + ReportError("failed to load objfile for {0}", GetFileSpec().GetPath().c_str()); } } @@ -1308,8 +1287,11 @@ void Module::SectionFileAddressesChanged() { } UnwindTable &Module::GetUnwindTable() { - if (!m_unwind_table) + if (!m_unwind_table) { m_unwind_table.emplace(*this); + if (!m_symfile_spec) + Symbols::DownloadSymbolFileAsync(GetUUID()); + } return *m_unwind_table; } @@ -1367,9 +1349,9 @@ void Module::FindSymbolsWithNameAndType(ConstString name, } } -void Module::FindSymbolsMatchingRegExAndType(const RegularExpression ®ex, - SymbolType symbol_type, - SymbolContextList &sc_list) { +void Module::FindSymbolsMatchingRegExAndType( + const RegularExpression ®ex, SymbolType symbol_type, + SymbolContextList &sc_list, Mangled::NamePreference mangling_preference) { // No need to protect this call using m_mutex all other method calls are // already thread safe. LLDB_SCOPED_TIMERF( @@ -1379,7 +1361,7 @@ void Module::FindSymbolsMatchingRegExAndType(const RegularExpression ®ex, std::vector<uint32_t> symbol_indexes; symtab->FindAllSymbolsMatchingRexExAndType( regex, symbol_type, Symtab::eDebugAny, Symtab::eVisibilityAny, - symbol_indexes); + symbol_indexes, mangling_preference); SymbolIndicesToSymbolContextList(symtab, symbol_indexes, sc_list); } } @@ -1618,8 +1600,7 @@ bool Module::FindSourceFile(const FileSpec &orig_spec, return false; } -llvm::Optional<std::string> -Module::RemapSourceFile(llvm::StringRef path) const { +std::optional<std::string> Module::RemapSourceFile(llvm::StringRef path) const { std::lock_guard<std::recursive_mutex> guard(m_mutex); if (auto remapped = m_source_mappings.RemapPath(path)) return remapped->GetPath(); @@ -1629,7 +1610,15 @@ Module::RemapSourceFile(llvm::StringRef path) const { void Module::RegisterXcodeSDK(llvm::StringRef sdk_name, llvm::StringRef sysroot) { XcodeSDK sdk(sdk_name.str()); - llvm::StringRef sdk_path(HostInfo::GetXcodeSDKPath(sdk)); + auto sdk_path_or_err = HostInfo::GetXcodeSDKPath(sdk); + + if (!sdk_path_or_err) { + Debugger::ReportError("Error while searching for Xcode SDK: " + + toString(sdk_path_or_err.takeError())); + return; + } + + auto sdk_path = *sdk_path_or_err; if (sdk_path.empty()) return; // If the SDK changed for a previously registered source path, update it. diff --git a/contrib/llvm-project/lldb/source/Core/ModuleList.cpp b/contrib/llvm-project/lldb/source/Core/ModuleList.cpp index 1692a3710a3d..5aa58d9bba6b 100644 --- a/contrib/llvm-project/lldb/source/Core/ModuleList.cpp +++ b/contrib/llvm-project/lldb/source/Core/ModuleList.cpp @@ -106,6 +106,12 @@ bool ModuleListProperties::SetEnableExternalLookup(bool new_value) { nullptr, ePropertyEnableExternalLookup, new_value); } +bool ModuleListProperties::GetEnableBackgroundLookup() const { + const uint32_t idx = ePropertyEnableBackgroundLookup; + return m_collection_sp->GetPropertyAtIndexAsBoolean( + nullptr, idx, g_modulelist_properties[idx].default_uint_value != 0); +} + FileSpec ModuleListProperties::GetClangModulesCachePath() const { return m_collection_sp ->GetPropertyAtIndexAsOptionValueFileSpec(nullptr, false, @@ -425,9 +431,8 @@ void ModuleList::FindFunctions(ConstString name, std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); for (const ModuleSP &module_sp : m_modules) { - module_sp->FindFunctions(lookup_info.GetLookupName(), - CompilerDeclContext(), - lookup_info.GetNameTypeMask(), options, sc_list); + module_sp->FindFunctions(lookup_info, CompilerDeclContext(), options, + sc_list); } const size_t new_size = sc_list.GetSize(); @@ -769,6 +774,10 @@ void ModuleList::FindSharedModules(const ModuleSpec &module_spec, GetSharedModuleList().FindModules(module_spec, matching_module_list); } +lldb::ModuleSP ModuleList::FindSharedModule(const UUID &uuid) { + return GetSharedModuleList().FindModule(uuid); +} + size_t ModuleList::RemoveOrphanSharedModules(bool mandatory) { return GetSharedModuleList().RemoveOrphans(mandatory); } @@ -1058,9 +1067,23 @@ bool ModuleList::LoadScriptingResourcesInTarget(Target *target, void ModuleList::ForEach( std::function<bool(const ModuleSP &module_sp)> const &callback) const { std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); - for (const auto &module : m_modules) { + 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)) + if (!callback(module_sp)) break; } } + +bool ModuleList::AnyOf( + std::function<bool(lldb_private::Module &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 (callback(*module_sp)) + return true; + } + + return false; +} diff --git a/contrib/llvm-project/lldb/source/Core/PluginManager.cpp b/contrib/llvm-project/lldb/source/Core/PluginManager.cpp index 38a9573411f4..05ca0ff1e1ec 100644 --- a/contrib/llvm-project/lldb/source/Core/PluginManager.cpp +++ b/contrib/llvm-project/lldb/source/Core/PluginManager.cpp @@ -724,11 +724,14 @@ struct ObjectContainerInstance ObjectContainerInstance( llvm::StringRef name, llvm::StringRef description, CallbackType create_callback, + ObjectContainerCreateMemoryInstance create_memory_callback, ObjectFileGetModuleSpecifications get_module_specifications) : PluginInstance<ObjectContainerCreateInstance>(name, description, create_callback), + create_memory_callback(create_memory_callback), get_module_specifications(get_module_specifications) {} + ObjectContainerCreateMemoryInstance create_memory_callback; ObjectFileGetModuleSpecifications get_module_specifications; }; typedef PluginInstances<ObjectContainerInstance> ObjectContainerInstances; @@ -741,9 +744,11 @@ static ObjectContainerInstances &GetObjectContainerInstances() { bool PluginManager::RegisterPlugin( llvm::StringRef name, llvm::StringRef description, ObjectContainerCreateInstance create_callback, - ObjectFileGetModuleSpecifications get_module_specifications) { + ObjectFileGetModuleSpecifications get_module_specifications, + ObjectContainerCreateMemoryInstance create_memory_callback) { return GetObjectContainerInstances().RegisterPlugin( - name, description, create_callback, get_module_specifications); + name, description, create_callback, create_memory_callback, + get_module_specifications); } bool PluginManager::UnregisterPlugin( @@ -756,6 +761,14 @@ PluginManager::GetObjectContainerCreateCallbackAtIndex(uint32_t idx) { return GetObjectContainerInstances().GetCallbackAtIndex(idx); } +ObjectContainerCreateMemoryInstance +PluginManager::GetObjectContainerCreateMemoryCallbackAtIndex(uint32_t idx) { + const auto &instances = GetObjectContainerInstances().GetInstances(); + if (idx < instances.size()) + return instances[idx].create_memory_callback; + return nullptr; +} + ObjectFileGetModuleSpecifications PluginManager::GetObjectContainerGetModuleSpecificationsCallbackAtIndex( uint32_t idx) { @@ -1038,9 +1051,10 @@ struct TraceInstance llvm::StringRef name, llvm::StringRef description, CallbackType create_callback_from_bundle, TraceCreateInstanceForLiveProcess create_callback_for_live_process, - llvm::StringRef schema) + llvm::StringRef schema, DebuggerInitializeCallback debugger_init_callback) : PluginInstance<TraceCreateInstanceFromBundle>( - name, description, create_callback_from_bundle), + name, description, create_callback_from_bundle, + debugger_init_callback), schema(schema), create_callback_for_live_process(create_callback_for_live_process) {} @@ -1059,10 +1073,10 @@ bool PluginManager::RegisterPlugin( llvm::StringRef name, llvm::StringRef description, TraceCreateInstanceFromBundle create_callback_from_bundle, TraceCreateInstanceForLiveProcess create_callback_for_live_process, - llvm::StringRef schema) { + llvm::StringRef schema, DebuggerInitializeCallback debugger_init_callback) { return GetTracePluginInstances().RegisterPlugin( name, description, create_callback_from_bundle, - create_callback_for_live_process, schema); + create_callback_for_live_process, schema, debugger_init_callback); } bool PluginManager::UnregisterPlugin( @@ -1493,6 +1507,7 @@ CreateSettingForPlugin(Debugger &debugger, ConstString plugin_type_name, static const char *kDynamicLoaderPluginName("dynamic-loader"); static const char *kPlatformPluginName("platform"); static const char *kProcessPluginName("process"); +static const char *kTracePluginName("trace"); static const char *kObjectFilePluginName("object-file"); static const char *kSymbolFilePluginName("symbol-file"); static const char *kJITLoaderPluginName("jit-loader"); @@ -1546,6 +1561,14 @@ bool PluginManager::CreateSettingForProcessPlugin( properties_sp, description, is_global_property); } +bool PluginManager::CreateSettingForTracePlugin( + Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp, + ConstString description, bool is_global_property) { + return CreateSettingForPlugin(debugger, ConstString(kTracePluginName), + ConstString("Settings for trace plug-ins"), + properties_sp, description, is_global_property); +} + lldb::OptionValuePropertiesSP PluginManager::GetSettingForObjectFilePlugin(Debugger &debugger, ConstString setting_name) { diff --git a/contrib/llvm-project/lldb/source/Core/RichManglingContext.cpp b/contrib/llvm-project/lldb/source/Core/RichManglingContext.cpp index 64b18b401f2d..08c9b280b8cc 100644 --- a/contrib/llvm-project/lldb/source/Core/RichManglingContext.cpp +++ b/contrib/llvm-project/lldb/source/Core/RichManglingContext.cpp @@ -24,7 +24,7 @@ RichManglingContext::~RichManglingContext() { void RichManglingContext::ResetCxxMethodParser() { // If we want to support parsers for other languages some day, we need a // switch here to delete the correct parser type. - if (m_cxx_method_parser.hasValue()) { + if (m_cxx_method_parser.has_value()) { assert(m_provider == PluginCxxLanguage); delete get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser); m_cxx_method_parser.reset(); diff --git a/contrib/llvm-project/lldb/source/Core/SourceLocationSpec.cpp b/contrib/llvm-project/lldb/source/Core/SourceLocationSpec.cpp index c83d2d89370d..805291f7d59a 100644 --- a/contrib/llvm-project/lldb/source/Core/SourceLocationSpec.cpp +++ b/contrib/llvm-project/lldb/source/Core/SourceLocationSpec.cpp @@ -8,12 +8,13 @@ #include "lldb/Core/SourceLocationSpec.h" #include "lldb/Utility/StreamString.h" +#include <optional> using namespace lldb; using namespace lldb_private; SourceLocationSpec::SourceLocationSpec(FileSpec file_spec, uint32_t line, - llvm::Optional<uint16_t> column, + std::optional<uint16_t> column, bool check_inlines, bool exact_match) : m_declaration(file_spec, line, column.value_or(LLDB_INVALID_COLUMN_NUMBER)), @@ -66,16 +67,16 @@ std::string SourceLocationSpec::GetString() const { return ss.GetString().str(); } -llvm::Optional<uint32_t> SourceLocationSpec::GetLine() const { +std::optional<uint32_t> SourceLocationSpec::GetLine() const { uint32_t line = m_declaration.GetLine(); if (line == 0 || line == LLDB_INVALID_LINE_NUMBER) - return llvm::None; + return std::nullopt; return line; } -llvm::Optional<uint16_t> SourceLocationSpec::GetColumn() const { +std::optional<uint16_t> SourceLocationSpec::GetColumn() const { uint16_t column = m_declaration.GetColumn(); if (column == LLDB_INVALID_COLUMN_NUMBER) - return llvm::None; + return std::nullopt; return column; } diff --git a/contrib/llvm-project/lldb/source/Core/SourceManager.cpp b/contrib/llvm-project/lldb/source/Core/SourceManager.cpp index 0e2157f377e0..72fabb42507c 100644 --- a/contrib/llvm-project/lldb/source/Core/SourceManager.cpp +++ b/contrib/llvm-project/lldb/source/Core/SourceManager.cpp @@ -32,6 +32,7 @@ #include "llvm/ADT/Twine.h" #include <memory> +#include <optional> #include <utility> #include <cassert> @@ -222,7 +223,7 @@ size_t SourceManager::DisplaySourceLinesWithLineNumbersUsingLastFile( // So far we treated column 0 as a special 'no column value', but // DisplaySourceLines starts counting columns from 0 (and no column is // expressed by passing an empty optional). - llvm::Optional<size_t> columnToHighlight; + std::optional<size_t> columnToHighlight; if (line == curr_line && column) columnToHighlight = column - 1; @@ -557,7 +558,7 @@ void SourceManager::File::UpdateIfNeeded() { } size_t SourceManager::File::DisplaySourceLines(uint32_t line, - llvm::Optional<size_t> column, + std::optional<size_t> column, uint32_t context_before, uint32_t context_after, Stream *s) { diff --git a/contrib/llvm-project/lldb/source/Core/ThreadedCommunication.cpp b/contrib/llvm-project/lldb/source/Core/ThreadedCommunication.cpp new file mode 100644 index 000000000000..d547c858f0f5 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Core/ThreadedCommunication.cpp @@ -0,0 +1,371 @@ +//===-- ThreadedCommunication.cpp -----------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lldb/Core/ThreadedCommunication.h" + +#include "lldb/Host/ThreadLauncher.h" +#include "lldb/Utility/Connection.h" +#include "lldb/Utility/ConstString.h" +#include "lldb/Utility/Event.h" +#include "lldb/Utility/LLDBLog.h" +#include "lldb/Utility/Listener.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/Status.h" + +#include "llvm/Support/Compiler.h" + +#include <algorithm> +#include <chrono> +#include <cstring> +#include <memory> + +#include <cerrno> +#include <cinttypes> +#include <cstdio> + +using namespace lldb; +using namespace lldb_private; + +ConstString &ThreadedCommunication::GetStaticBroadcasterClass() { + static ConstString class_name("lldb.communication"); + return class_name; +} + +ThreadedCommunication::ThreadedCommunication(const char *name) + : Communication(), Broadcaster(nullptr, name), m_read_thread_enabled(false), + m_read_thread_did_exit(false), m_bytes(), m_bytes_mutex(), + m_synchronize_mutex(), m_callback(nullptr), m_callback_baton(nullptr) { + LLDB_LOG(GetLog(LLDBLog::Object | LLDBLog::Communication), + "{0} ThreadedCommunication::ThreadedCommunication (name = {1})", + this, name); + + SetEventName(eBroadcastBitDisconnected, "disconnected"); + SetEventName(eBroadcastBitReadThreadGotBytes, "got bytes"); + SetEventName(eBroadcastBitReadThreadDidExit, "read thread did exit"); + SetEventName(eBroadcastBitReadThreadShouldExit, "read thread should exit"); + SetEventName(eBroadcastBitPacketAvailable, "packet available"); + SetEventName(eBroadcastBitNoMorePendingInput, "no more pending input"); + + CheckInWithManager(); +} + +ThreadedCommunication::~ThreadedCommunication() { + LLDB_LOG(GetLog(LLDBLog::Object | LLDBLog::Communication), + "{0} ThreadedCommunication::~ThreadedCommunication (name = {1})", + this, GetBroadcasterName().AsCString()); +} + +void ThreadedCommunication::Clear() { + SetReadThreadBytesReceivedCallback(nullptr, nullptr); + StopReadThread(nullptr); + Communication::Clear(); +} + +ConnectionStatus ThreadedCommunication::Disconnect(Status *error_ptr) { + assert((!m_read_thread_enabled || m_read_thread_did_exit) && + "Disconnecting while the read thread is running is racy!"); + return Communication::Disconnect(error_ptr); +} + +size_t ThreadedCommunication::Read(void *dst, size_t dst_len, + const Timeout<std::micro> &timeout, + ConnectionStatus &status, + Status *error_ptr) { + Log *log = GetLog(LLDBLog::Communication); + LLDB_LOG( + log, + "this = {0}, dst = {1}, dst_len = {2}, timeout = {3}, connection = {4}", + this, dst, dst_len, timeout, m_connection_sp.get()); + + if (m_read_thread_enabled) { + // We have a dedicated read thread that is getting data for us + size_t cached_bytes = GetCachedBytes(dst, dst_len); + if (cached_bytes > 0) { + status = eConnectionStatusSuccess; + return cached_bytes; + } + if (timeout && timeout->count() == 0) { + if (error_ptr) + error_ptr->SetErrorString("Timed out."); + status = eConnectionStatusTimedOut; + return 0; + } + + if (!m_connection_sp) { + if (error_ptr) + error_ptr->SetErrorString("Invalid connection."); + status = eConnectionStatusNoConnection; + return 0; + } + + // No data yet, we have to start listening. + ListenerSP listener_sp( + Listener::MakeListener("ThreadedCommunication::Read")); + listener_sp->StartListeningForEvents( + this, eBroadcastBitReadThreadGotBytes | eBroadcastBitReadThreadDidExit); + + // Re-check for data, as it might have arrived while we were setting up our + // listener. + cached_bytes = GetCachedBytes(dst, dst_len); + if (cached_bytes > 0) { + status = eConnectionStatusSuccess; + return cached_bytes; + } + + EventSP event_sp; + // Explicitly check for the thread exit, for the same reason. + if (m_read_thread_did_exit) { + // We've missed the event, lets just conjure one up. + event_sp = std::make_shared<Event>(eBroadcastBitReadThreadDidExit); + } else { + if (!listener_sp->GetEvent(event_sp, timeout)) { + if (error_ptr) + error_ptr->SetErrorString("Timed out."); + status = eConnectionStatusTimedOut; + return 0; + } + } + const uint32_t event_type = event_sp->GetType(); + if (event_type & eBroadcastBitReadThreadGotBytes) { + return GetCachedBytes(dst, dst_len); + } + + if (event_type & eBroadcastBitReadThreadDidExit) { + // If the thread exited of its own accord, it either means it + // hit an end-of-file condition or an error. + status = m_pass_status; + if (error_ptr) + *error_ptr = std::move(m_pass_error); + + if (GetCloseOnEOF()) + Disconnect(nullptr); + return 0; + } + llvm_unreachable("Got unexpected event type!"); + } + + // We aren't using a read thread, just read the data synchronously in this + // thread. + return Communication::Read(dst, dst_len, timeout, status, error_ptr); +} + +bool ThreadedCommunication::StartReadThread(Status *error_ptr) { + if (error_ptr) + error_ptr->Clear(); + + if (m_read_thread.IsJoinable()) + return true; + + LLDB_LOG(GetLog(LLDBLog::Communication), + "{0} ThreadedCommunication::StartReadThread ()", this); + + const std::string thread_name = + llvm::formatv("<lldb.comm.{0}>", GetBroadcasterName()); + + m_read_thread_enabled = true; + m_read_thread_did_exit = false; + auto maybe_thread = ThreadLauncher::LaunchThread( + thread_name, [this] { return ReadThread(); }); + if (maybe_thread) { + m_read_thread = *maybe_thread; + } else { + if (error_ptr) + *error_ptr = Status(maybe_thread.takeError()); + else { + LLDB_LOG(GetLog(LLDBLog::Host), "failed to launch host thread: {}", + llvm::toString(maybe_thread.takeError())); + } + } + + if (!m_read_thread.IsJoinable()) + m_read_thread_enabled = false; + + return m_read_thread_enabled; +} + +bool ThreadedCommunication::StopReadThread(Status *error_ptr) { + if (!m_read_thread.IsJoinable()) + return true; + + LLDB_LOG(GetLog(LLDBLog::Communication), + "{0} ThreadedCommunication::StopReadThread ()", this); + + m_read_thread_enabled = false; + + BroadcastEvent(eBroadcastBitReadThreadShouldExit, nullptr); + + // error = m_read_thread.Cancel(); + + Status error = m_read_thread.Join(nullptr); + return error.Success(); +} + +bool ThreadedCommunication::JoinReadThread(Status *error_ptr) { + if (!m_read_thread.IsJoinable()) + return true; + + Status error = m_read_thread.Join(nullptr); + return error.Success(); +} + +size_t ThreadedCommunication::GetCachedBytes(void *dst, size_t dst_len) { + std::lock_guard<std::recursive_mutex> guard(m_bytes_mutex); + if (!m_bytes.empty()) { + // If DST is nullptr and we have a thread, then return the number of bytes + // that are available so the caller can call again + if (dst == nullptr) + return m_bytes.size(); + + const size_t len = std::min<size_t>(dst_len, m_bytes.size()); + + ::memcpy(dst, m_bytes.c_str(), len); + m_bytes.erase(m_bytes.begin(), m_bytes.begin() + len); + + return len; + } + return 0; +} + +void ThreadedCommunication::AppendBytesToCache(const uint8_t *bytes, size_t len, + bool broadcast, + ConnectionStatus status) { + LLDB_LOG(GetLog(LLDBLog::Communication), + "{0} ThreadedCommunication::AppendBytesToCache (src = {1}, src_len " + "= {2}, " + "broadcast = {3})", + this, bytes, (uint64_t)len, broadcast); + if ((bytes == nullptr || len == 0) && + (status != lldb::eConnectionStatusEndOfFile)) + return; + if (m_callback) { + // If the user registered a callback, then call it and do not broadcast + m_callback(m_callback_baton, bytes, len); + } else if (bytes != nullptr && len > 0) { + std::lock_guard<std::recursive_mutex> guard(m_bytes_mutex); + m_bytes.append((const char *)bytes, len); + if (broadcast) + BroadcastEventIfUnique(eBroadcastBitReadThreadGotBytes); + } +} + +bool ThreadedCommunication::ReadThreadIsRunning() { + return m_read_thread_enabled; +} + +lldb::thread_result_t ThreadedCommunication::ReadThread() { + Log *log = GetLog(LLDBLog::Communication); + + LLDB_LOG(log, "Communication({0}) thread starting...", this); + + uint8_t buf[1024]; + + Status error; + ConnectionStatus status = eConnectionStatusSuccess; + bool done = false; + bool disconnect = false; + while (!done && m_read_thread_enabled) { + size_t bytes_read = ReadFromConnection( + buf, sizeof(buf), std::chrono::seconds(5), status, &error); + if (bytes_read > 0 || status == eConnectionStatusEndOfFile) + AppendBytesToCache(buf, bytes_read, true, status); + + switch (status) { + case eConnectionStatusSuccess: + break; + + case eConnectionStatusEndOfFile: + done = true; + disconnect = GetCloseOnEOF(); + break; + case eConnectionStatusError: // Check GetError() for details + if (error.GetType() == eErrorTypePOSIX && error.GetError() == EIO) { + // EIO on a pipe is usually caused by remote shutdown + disconnect = GetCloseOnEOF(); + done = true; + } + if (error.Fail()) + LLDB_LOG(log, "error: {0}, status = {1}", error, + ThreadedCommunication::ConnectionStatusAsString(status)); + break; + case eConnectionStatusInterrupted: // Synchronization signal from + // SynchronizeWithReadThread() + // The connection returns eConnectionStatusInterrupted only when there is + // no input pending to be read, so we can signal that. + BroadcastEvent(eBroadcastBitNoMorePendingInput); + break; + case eConnectionStatusNoConnection: // No connection + case eConnectionStatusLostConnection: // Lost connection while connected to + // a valid connection + done = true; + [[fallthrough]]; + case eConnectionStatusTimedOut: // Request timed out + if (error.Fail()) + LLDB_LOG(log, "error: {0}, status = {1}", error, + ThreadedCommunication::ConnectionStatusAsString(status)); + break; + } + } + m_pass_status = status; + m_pass_error = std::move(error); + LLDB_LOG(log, "Communication({0}) thread exiting...", this); + + // Start shutting down. We need to do this in a very specific order to ensure + // we don't race with threads wanting to read/synchronize with us. + + // First, we signal our intent to exit. This ensures no new thread start + // waiting on events from us. + m_read_thread_did_exit = true; + + // Unblock any existing thread waiting for the synchronization signal. + BroadcastEvent(eBroadcastBitNoMorePendingInput); + + { + // Wait for the synchronization thread to finish... + std::lock_guard<std::mutex> guard(m_synchronize_mutex); + // ... and disconnect. + if (disconnect) + Disconnect(); + } + + // Finally, unblock any readers waiting for us to exit. + BroadcastEvent(eBroadcastBitReadThreadDidExit); + return {}; +} + +void ThreadedCommunication::SetReadThreadBytesReceivedCallback( + ReadThreadBytesReceived callback, void *callback_baton) { + m_callback = callback; + m_callback_baton = callback_baton; +} + +void ThreadedCommunication::SynchronizeWithReadThread() { + // Only one thread can do the synchronization dance at a time. + std::lock_guard<std::mutex> guard(m_synchronize_mutex); + + // First start listening for the synchronization event. + ListenerSP listener_sp(Listener::MakeListener( + "ThreadedCommunication::SyncronizeWithReadThread")); + listener_sp->StartListeningForEvents(this, eBroadcastBitNoMorePendingInput); + + // If the thread is not running, there is no point in synchronizing. + if (!m_read_thread_enabled || m_read_thread_did_exit) + return; + + // Notify the read thread. + m_connection_sp->InterruptRead(); + + // Wait for the synchronization event. + EventSP event_sp; + listener_sp->GetEvent(event_sp, std::nullopt); +} + +void ThreadedCommunication::SetConnection( + std::unique_ptr<Connection> connection) { + StopReadThread(nullptr); + Communication::SetConnection(std::move(connection)); +} diff --git a/contrib/llvm-project/lldb/source/Core/UserSettingsController.cpp b/contrib/llvm-project/lldb/source/Core/UserSettingsController.cpp index b9f7d5eaa687..9ea4f78ddd06 100644 --- a/contrib/llvm-project/lldb/source/Core/UserSettingsController.cpp +++ b/contrib/llvm-project/lldb/source/Core/UserSettingsController.cpp @@ -53,10 +53,17 @@ Status Properties::SetPropertyValue(const ExecutionContext *exe_ctx, } void Properties::DumpAllPropertyValues(const ExecutionContext *exe_ctx, - Stream &strm, uint32_t dump_mask) { + Stream &strm, uint32_t dump_mask, + bool is_json) { OptionValuePropertiesSP properties_sp(GetValueProperties()); - if (properties_sp) - return properties_sp->DumpValue(exe_ctx, strm, dump_mask); + if (!properties_sp) + return; + + if (is_json) { + llvm::json::Value json = properties_sp->ToJSON(exe_ctx); + strm.Printf("%s", llvm::formatv("{0:2}", json).str().c_str()); + } else + properties_sp->DumpValue(exe_ctx, strm, dump_mask); } void Properties::DumpAllDescriptions(CommandInterpreter &interpreter, @@ -71,11 +78,11 @@ void Properties::DumpAllDescriptions(CommandInterpreter &interpreter, Status Properties::DumpPropertyValue(const ExecutionContext *exe_ctx, Stream &strm, llvm::StringRef property_path, - uint32_t dump_mask) { + uint32_t dump_mask, bool is_json) { OptionValuePropertiesSP properties_sp(GetValueProperties()); if (properties_sp) { return properties_sp->DumpPropertyValue(exe_ctx, strm, property_path, - dump_mask); + dump_mask, is_json); } Status error; error.SetErrorString("empty property list"); diff --git a/contrib/llvm-project/lldb/source/Core/Value.cpp b/contrib/llvm-project/lldb/source/Core/Value.cpp index 2b60dd6f00fa..ccd36096b545 100644 --- a/contrib/llvm-project/lldb/source/Core/Value.cpp +++ b/contrib/llvm-project/lldb/source/Core/Value.cpp @@ -31,6 +31,7 @@ #include "lldb/lldb-types.h" #include <memory> +#include <optional> #include <string> #include <cinttypes> @@ -206,7 +207,7 @@ uint64_t Value::GetValueByteSize(Status *error_ptr, ExecutionContext *exe_ctx) { case ContextType::Variable: // Variable * { auto *scope = exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr; - if (llvm::Optional<uint64_t> size = GetCompilerType().GetByteSize(scope)) { + if (std::optional<uint64_t> size = GetCompilerType().GetByteSize(scope)) { if (error_ptr) error_ptr->Clear(); return *size; @@ -304,7 +305,7 @@ Status Value::GetValueAsData(ExecutionContext *exe_ctx, DataExtractor &data, AddressType address_type = eAddressTypeFile; Address file_so_addr; const CompilerType &ast_type = GetCompilerType(); - llvm::Optional<uint64_t> type_size = ast_type.GetByteSize( + std::optional<uint64_t> type_size = ast_type.GetByteSize( exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr); // Nothing to be done for a zero-sized type. if (type_size && *type_size == 0) diff --git a/contrib/llvm-project/lldb/source/Core/ValueObject.cpp b/contrib/llvm-project/lldb/source/Core/ValueObject.cpp index d80139ab1840..38645b087435 100644 --- a/contrib/llvm-project/lldb/source/Core/ValueObject.cpp +++ b/contrib/llvm-project/lldb/source/Core/ValueObject.cpp @@ -55,6 +55,7 @@ #include <cstdint> #include <cstdlib> #include <memory> +#include <optional> #include <tuple> #include <cassert> @@ -263,7 +264,7 @@ CompilerType ValueObject::MaybeCalculateCompleteType() { if (auto *runtime = process_sp->GetLanguageRuntime(GetObjectRuntimeLanguage())) { - if (llvm::Optional<CompilerType> complete_type = + if (std::optional<CompilerType> complete_type = runtime->GetRuntimeType(compiler_type)) { m_override_type = *complete_type; if (m_override_type.IsValid()) @@ -594,6 +595,14 @@ bool ValueObject::GetSummaryAsCString(TypeSummaryImpl *summary_ptr, const TypeSummaryOptions &options) { destination.clear(); + // If we have a forcefully completed type, don't try and show a summary from + // a valid summary string or function because the type is not complete and + // no member variables or member functions will be available. + if (GetCompilerType().IsForcefullyCompleted()) { + destination = "<incomplete type>"; + return true; + } + // ideally we would like to bail out if passing NULL, but if we do so we end // up not providing the summary for function pointers anymore if (/*summary_ptr == NULL ||*/ m_flags.m_is_getting_summary) @@ -674,7 +683,7 @@ size_t ValueObject::GetPointeeData(DataExtractor &data, uint32_t item_idx, ExecutionContext exe_ctx(GetExecutionContextRef()); - llvm::Optional<uint64_t> item_type_size = + std::optional<uint64_t> item_type_size = pointee_or_element_compiler_type.GetByteSize( exe_ctx.GetBestExecutionContextScope()); if (!item_type_size) @@ -1697,7 +1706,7 @@ ValueObjectSP ValueObject::GetSyntheticChildAtOffset( return {}; ExecutionContext exe_ctx(GetExecutionContextRef()); - llvm::Optional<uint64_t> size = + std::optional<uint64_t> size = type.GetByteSize(exe_ctx.GetBestExecutionContextScope()); if (!size) return {}; @@ -1739,7 +1748,7 @@ ValueObjectSP ValueObject::GetSyntheticBase(uint32_t offset, const bool is_base_class = true; ExecutionContext exe_ctx(GetExecutionContextRef()); - llvm::Optional<uint64_t> size = + std::optional<uint64_t> size = type.GetByteSize(exe_ctx.GetBestExecutionContextScope()); if (!size) return {}; @@ -2113,7 +2122,7 @@ ValueObjectSP ValueObject::GetValueForExpressionPath_Impl( return ValueObjectSP(); } } - LLVM_FALLTHROUGH; + [[fallthrough]]; case '.': // or fallthrough from -> { if (options.m_check_dot_vs_arrow_syntax && @@ -2673,7 +2682,10 @@ ValueObjectSP ValueObject::Dereference(Status &error) { // In case of incomplete child compiler type, use the pointee type and try // to recreate a new ValueObjectChild using it. if (!m_deref_valobj) { - if (HasSyntheticValue()) { + // FIXME(#59012): C++ stdlib formatters break with incomplete types (e.g. + // `std::vector<int> &`). Remove ObjC restriction once that's resolved. + if (Language::LanguageIsObjC(GetPreferredDisplayLanguage()) && + HasSyntheticValue()) { child_compiler_type = compiler_type.GetPointeeType(); if (child_compiler_type) { diff --git a/contrib/llvm-project/lldb/source/Core/ValueObjectCast.cpp b/contrib/llvm-project/lldb/source/Core/ValueObjectCast.cpp index 9f803912d0ca..0882d4b36776 100644 --- a/contrib/llvm-project/lldb/source/Core/ValueObjectCast.cpp +++ b/contrib/llvm-project/lldb/source/Core/ValueObjectCast.cpp @@ -14,6 +14,7 @@ #include "lldb/Target/ExecutionContext.h" #include "lldb/Utility/Scalar.h" #include "lldb/Utility/Status.h" +#include <optional> namespace lldb_private { class ConstString; @@ -47,7 +48,7 @@ size_t ValueObjectCast::CalculateNumChildren(uint32_t max) { return children_count <= max ? children_count : max; } -llvm::Optional<uint64_t> ValueObjectCast::GetByteSize() { +std::optional<uint64_t> ValueObjectCast::GetByteSize() { ExecutionContext exe_ctx(GetExecutionContextRef()); return m_value.GetValueByteSize(nullptr, &exe_ctx); } diff --git a/contrib/llvm-project/lldb/source/Core/ValueObjectChild.cpp b/contrib/llvm-project/lldb/source/Core/ValueObjectChild.cpp index ec29c029c174..39067387dc97 100644 --- a/contrib/llvm-project/lldb/source/Core/ValueObjectChild.cpp +++ b/contrib/llvm-project/lldb/source/Core/ValueObjectChild.cpp @@ -83,7 +83,7 @@ ConstString ValueObjectChild::GetDisplayTypeName() { LazyBool ValueObjectChild::CanUpdateWithInvalidExecutionContext() { if (m_can_update_with_invalid_exe_ctx) - return m_can_update_with_invalid_exe_ctx.value(); + return *m_can_update_with_invalid_exe_ctx; if (m_parent) { ValueObject *opinionated_parent = m_parent->FollowParentChain([](ValueObject *valobj) -> bool { @@ -91,13 +91,11 @@ LazyBool ValueObjectChild::CanUpdateWithInvalidExecutionContext() { eLazyBoolCalculate); }); if (opinionated_parent) - return (m_can_update_with_invalid_exe_ctx = - opinionated_parent->CanUpdateWithInvalidExecutionContext()) - .value(); + return *(m_can_update_with_invalid_exe_ctx = + opinionated_parent->CanUpdateWithInvalidExecutionContext()); } - return (m_can_update_with_invalid_exe_ctx = - this->ValueObject::CanUpdateWithInvalidExecutionContext()) - .value(); + return *(m_can_update_with_invalid_exe_ctx = + this->ValueObject::CanUpdateWithInvalidExecutionContext()); } bool ValueObjectChild::UpdateValue() { diff --git a/contrib/llvm-project/lldb/source/Core/ValueObjectConstResult.cpp b/contrib/llvm-project/lldb/source/Core/ValueObjectConstResult.cpp index 174b9359d52d..640abdddfcad 100644 --- a/contrib/llvm-project/lldb/source/Core/ValueObjectConstResult.cpp +++ b/contrib/llvm-project/lldb/source/Core/ValueObjectConstResult.cpp @@ -17,6 +17,7 @@ #include "lldb/Utility/DataBufferHeap.h" #include "lldb/Utility/DataExtractor.h" #include "lldb/Utility/Scalar.h" +#include <optional> namespace lldb_private { class Module; @@ -203,7 +204,7 @@ lldb::ValueType ValueObjectConstResult::GetValueType() const { return eValueTypeConstResult; } -llvm::Optional<uint64_t> ValueObjectConstResult::GetByteSize() { +std::optional<uint64_t> ValueObjectConstResult::GetByteSize() { ExecutionContext exe_ctx(GetExecutionContextRef()); if (!m_byte_size) { if (auto size = diff --git a/contrib/llvm-project/lldb/source/Core/ValueObjectConstResultImpl.cpp b/contrib/llvm-project/lldb/source/Core/ValueObjectConstResultImpl.cpp index fee1da138bbc..e2db3ace1924 100644 --- a/contrib/llvm-project/lldb/source/Core/ValueObjectConstResultImpl.cpp +++ b/contrib/llvm-project/lldb/source/Core/ValueObjectConstResultImpl.cpp @@ -89,13 +89,20 @@ ValueObject *ValueObjectConstResultImpl::CreateChildAtIndex( if (!child_name_str.empty()) child_name.SetCString(child_name_str.c_str()); + lldb::addr_t child_live_addr = LLDB_INVALID_ADDRESS; + // Transfer the live address (with offset) to the child. But if + // the parent is a pointer, the live address is where that pointer + // value lives in memory, so the children live addresses aren't + // offsets from that value, they are just other load addresses that + // are recorded in the Value of the child ValueObjects. + if (m_live_address != LLDB_INVALID_ADDRESS) { + if (!compiler_type.IsPointerType()) + child_live_addr = m_live_address + child_byte_offset; + } valobj = new ValueObjectConstResultChild( *m_impl_backend, child_compiler_type, child_name, child_byte_size, child_byte_offset, child_bitfield_bit_size, child_bitfield_bit_offset, - child_is_base_class, child_is_deref_of_parent, - m_live_address == LLDB_INVALID_ADDRESS - ? m_live_address - : m_live_address + child_byte_offset, + child_is_base_class, child_is_deref_of_parent, child_live_addr, language_flags); } diff --git a/contrib/llvm-project/lldb/source/Core/ValueObjectDynamicValue.cpp b/contrib/llvm-project/lldb/source/Core/ValueObjectDynamicValue.cpp index cc5c481cdbb5..0659c771918a 100644 --- a/contrib/llvm-project/lldb/source/Core/ValueObjectDynamicValue.cpp +++ b/contrib/llvm-project/lldb/source/Core/ValueObjectDynamicValue.cpp @@ -23,6 +23,7 @@ #include "lldb/lldb-types.h" #include <cstring> +#include <optional> namespace lldb_private { class Declaration; } @@ -94,7 +95,7 @@ size_t ValueObjectDynamicValue::CalculateNumChildren(uint32_t max) { return m_parent->GetNumChildren(max); } -llvm::Optional<uint64_t> ValueObjectDynamicValue::GetByteSize() { +std::optional<uint64_t> ValueObjectDynamicValue::GetByteSize() { const bool success = UpdateValueIfNeeded(false); if (success && m_dynamic_type_info.HasType()) { ExecutionContext exe_ctx(GetExecutionContextRef()); diff --git a/contrib/llvm-project/lldb/source/Core/ValueObjectMemory.cpp b/contrib/llvm-project/lldb/source/Core/ValueObjectMemory.cpp index af039ee4040b..3f125a7bee8c 100644 --- a/contrib/llvm-project/lldb/source/Core/ValueObjectMemory.cpp +++ b/contrib/llvm-project/lldb/source/Core/ValueObjectMemory.cpp @@ -20,6 +20,7 @@ #include <cassert> #include <memory> +#include <optional> namespace lldb_private { class ExecutionContextScope; @@ -83,8 +84,7 @@ ValueObjectMemory::ValueObjectMemory(ExecutionContextScope *exe_scope, : ValueObject(exe_scope, manager), m_address(address), m_type_sp(), m_compiler_type(ast_type) { // Do not attempt to construct one of these objects with no variable! - assert(m_compiler_type.GetTypeSystem()); - assert(m_compiler_type.GetOpaqueQualType()); + assert(m_compiler_type.IsValid()); TargetSP target_sp(GetTargetSP()); @@ -139,7 +139,7 @@ size_t ValueObjectMemory::CalculateNumChildren(uint32_t max) { return child_count <= max ? child_count : max; } -llvm::Optional<uint64_t> ValueObjectMemory::GetByteSize() { +std::optional<uint64_t> ValueObjectMemory::GetByteSize() { ExecutionContext exe_ctx(GetExecutionContextRef()); if (m_type_sp) return m_type_sp->GetByteSize(exe_ctx.GetBestExecutionContextScope()); diff --git a/contrib/llvm-project/lldb/source/Core/ValueObjectRegister.cpp b/contrib/llvm-project/lldb/source/Core/ValueObjectRegister.cpp index 2aa0c68ba40f..a0fbf9a7d25b 100644 --- a/contrib/llvm-project/lldb/source/Core/ValueObjectRegister.cpp +++ b/contrib/llvm-project/lldb/source/Core/ValueObjectRegister.cpp @@ -28,6 +28,7 @@ #include <cassert> #include <memory> +#include <optional> namespace lldb_private { class ExecutionContextScope; @@ -82,7 +83,7 @@ size_t ValueObjectRegisterSet::CalculateNumChildren(uint32_t max) { return 0; } -llvm::Optional<uint64_t> ValueObjectRegisterSet::GetByteSize() { return 0; } +std::optional<uint64_t> ValueObjectRegisterSet::GetByteSize() { return 0; } bool ValueObjectRegisterSet::UpdateValue() { m_error.Clear(); @@ -206,9 +207,9 @@ CompilerType ValueObjectRegister::GetCompilerTypeImpl() { LLDB_LOG_ERROR(GetLog(LLDBLog::Types), std::move(err), "Unable to get CompilerType from TypeSystem"); } else { - m_compiler_type = - type_system_or_err->GetBuiltinTypeForEncodingAndBitSize( - m_reg_info.encoding, m_reg_info.byte_size * 8); + if (auto ts = *type_system_or_err) + m_compiler_type = ts->GetBuiltinTypeForEncodingAndBitSize( + m_reg_info.encoding, m_reg_info.byte_size * 8); } } } @@ -228,7 +229,7 @@ size_t ValueObjectRegister::CalculateNumChildren(uint32_t max) { return children_count <= max ? children_count : max; } -llvm::Optional<uint64_t> ValueObjectRegister::GetByteSize() { +std::optional<uint64_t> ValueObjectRegister::GetByteSize() { return m_reg_info.byte_size; } @@ -282,7 +283,7 @@ bool ValueObjectRegister::SetValueFromCString(const char *value_str, } bool ValueObjectRegister::SetData(DataExtractor &data, Status &error) { - error = m_reg_value.SetValueFromData(&m_reg_info, data, 0, false); + error = m_reg_value.SetValueFromData(m_reg_info, data, 0, false); if (!error.Success()) return false; diff --git a/contrib/llvm-project/lldb/source/Core/ValueObjectSyntheticFilter.cpp b/contrib/llvm-project/lldb/source/Core/ValueObjectSyntheticFilter.cpp index a1001b396912..bd83d5908992 100644 --- a/contrib/llvm-project/lldb/source/Core/ValueObjectSyntheticFilter.cpp +++ b/contrib/llvm-project/lldb/source/Core/ValueObjectSyntheticFilter.cpp @@ -17,6 +17,7 @@ #include "lldb/Utility/Status.h" #include "llvm/ADT/STLExtras.h" +#include <optional> namespace lldb_private { class Declaration; @@ -121,7 +122,7 @@ bool ValueObjectSynthetic::MightHaveChildren() { return (m_might_have_children != eLazyBoolNo); } -llvm::Optional<uint64_t> ValueObjectSynthetic::GetByteSize() { +std::optional<uint64_t> ValueObjectSynthetic::GetByteSize() { return m_parent->GetByteSize(); } diff --git a/contrib/llvm-project/lldb/source/Core/ValueObjectVariable.cpp b/contrib/llvm-project/lldb/source/Core/ValueObjectVariable.cpp index 4e2bd12c1053..9f8df847f28a 100644 --- a/contrib/llvm-project/lldb/source/Core/ValueObjectVariable.cpp +++ b/contrib/llvm-project/lldb/source/Core/ValueObjectVariable.cpp @@ -35,6 +35,7 @@ #include <cassert> #include <memory> +#include <optional> namespace lldb_private { class ExecutionContextScope; @@ -105,7 +106,7 @@ size_t ValueObjectVariable::CalculateNumChildren(uint32_t max) { return child_count <= max ? child_count : max; } -llvm::Optional<uint64_t> ValueObjectVariable::GetByteSize() { +std::optional<uint64_t> ValueObjectVariable::GetByteSize() { ExecutionContext exe_ctx(GetExecutionContextRef()); CompilerType type(GetCompilerType()); @@ -398,7 +399,7 @@ bool ValueObjectVariable::SetData(DataExtractor &data, Status &error) { error.SetErrorString("unable to retrieve register info"); return false; } - error = reg_value.SetValueFromData(reg_info, data, 0, true); + error = reg_value.SetValueFromData(*reg_info, data, 0, true); if (error.Fail()) return false; if (reg_ctx->WriteRegister(reg_info, reg_value)) { diff --git a/contrib/llvm-project/lldb/source/DataFormatters/DataVisualization.cpp b/contrib/llvm-project/lldb/source/DataFormatters/DataVisualization.cpp index ded8bbd90391..036c9372baf8 100644 --- a/contrib/llvm-project/lldb/source/DataFormatters/DataVisualization.cpp +++ b/contrib/llvm-project/lldb/source/DataFormatters/DataVisualization.cpp @@ -66,10 +66,11 @@ DataVisualization::GetSyntheticForType(lldb::TypeNameSpecifierImplSP type_sp) { } bool DataVisualization::AnyMatches( - ConstString type_name, TypeCategoryImpl::FormatCategoryItems items, - bool only_enabled, const char **matching_category, + const FormattersMatchCandidate &candidate_type, + TypeCategoryImpl::FormatCategoryItems items, bool only_enabled, + const char **matching_category, TypeCategoryImpl::FormatCategoryItems *matching_type) { - return GetFormatManager().AnyMatches(type_name, items, only_enabled, + return GetFormatManager().AnyMatches(candidate_type, items, only_enabled, matching_category, matching_type); } @@ -102,8 +103,7 @@ void DataVisualization::Categories::Clear() { } void DataVisualization::Categories::Clear(ConstString category) { - GetFormatManager().GetCategory(category)->Clear( - eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary); + GetFormatManager().GetCategory(category)->Clear(eFormatCategoryItemSummary); } void DataVisualization::Categories::Enable(ConstString category, diff --git a/contrib/llvm-project/lldb/source/DataFormatters/FormatManager.cpp b/contrib/llvm-project/lldb/source/DataFormatters/FormatManager.cpp index a8390c5d79c6..166264df9933 100644 --- a/contrib/llvm-project/lldb/source/DataFormatters/FormatManager.cpp +++ b/contrib/llvm-project/lldb/source/DataFormatters/FormatManager.cpp @@ -11,6 +11,7 @@ #include "lldb/Core/Debugger.h" #include "lldb/DataFormatters/FormattersHelpers.h" #include "lldb/DataFormatters/LanguageCategory.h" +#include "lldb/Interpreter/ScriptInterpreter.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Language.h" #include "lldb/Utility/LLDBLog.h" @@ -76,7 +77,7 @@ static_assert((sizeof(g_format_infos) / sizeof(g_format_infos[0])) == kNumFormats, "All formats must have a corresponding info entry."); -static uint32_t g_num_format_infos = llvm::array_lengthof(g_format_infos); +static uint32_t g_num_format_infos = std::size(g_format_infos); static bool GetFormatFromFormatChar(char format_char, Format &format) { for (uint32_t i = 0; i < g_num_format_infos; ++i) { @@ -175,60 +176,56 @@ void FormatManager::DisableAllCategories() { void FormatManager::GetPossibleMatches( ValueObject &valobj, CompilerType compiler_type, lldb::DynamicValueType use_dynamic, FormattersMatchVector &entries, - bool did_strip_ptr, bool did_strip_ref, bool did_strip_typedef, - bool root_level) { + FormattersMatchCandidate::Flags current_flags, bool root_level) { compiler_type = compiler_type.GetTypeForFormatters(); ConstString type_name(compiler_type.GetTypeName()); + ScriptInterpreter *script_interpreter = + valobj.GetTargetSP()->GetDebugger().GetScriptInterpreter(); if (valobj.GetBitfieldBitSize() > 0) { StreamString sstring; sstring.Printf("%s:%d", type_name.AsCString(), valobj.GetBitfieldBitSize()); ConstString bitfieldname(sstring.GetString()); - entries.push_back( - {bitfieldname, did_strip_ptr, did_strip_ref, did_strip_typedef}); + entries.push_back({bitfieldname, script_interpreter, + TypeImpl(compiler_type), current_flags}); } if (!compiler_type.IsMeaninglessWithoutDynamicResolution()) { - entries.push_back( - {type_name, did_strip_ptr, did_strip_ref, did_strip_typedef}); + entries.push_back({type_name, script_interpreter, TypeImpl(compiler_type), + current_flags}); ConstString display_type_name(compiler_type.GetTypeName()); if (display_type_name != type_name) - entries.push_back({display_type_name, did_strip_ptr, - did_strip_ref, did_strip_typedef}); + entries.push_back({display_type_name, script_interpreter, + TypeImpl(compiler_type), current_flags}); } for (bool is_rvalue_ref = true, j = true; j && compiler_type.IsReferenceType(nullptr, &is_rvalue_ref); j = false) { CompilerType non_ref_type = compiler_type.GetNonReferenceType(); - GetPossibleMatches( - valobj, non_ref_type, - use_dynamic, entries, did_strip_ptr, true, did_strip_typedef); + GetPossibleMatches(valobj, non_ref_type, use_dynamic, entries, + current_flags.WithStrippedReference()); if (non_ref_type.IsTypedefType()) { CompilerType deffed_referenced_type = non_ref_type.GetTypedefedType(); deffed_referenced_type = is_rvalue_ref ? deffed_referenced_type.GetRValueReferenceType() : deffed_referenced_type.GetLValueReferenceType(); + // this is not exactly the usual meaning of stripping typedefs GetPossibleMatches( valobj, deffed_referenced_type, - use_dynamic, entries, did_strip_ptr, did_strip_ref, - true); // this is not exactly the usual meaning of stripping typedefs + use_dynamic, entries, current_flags.WithStrippedTypedef()); } } if (compiler_type.IsPointerType()) { CompilerType non_ptr_type = compiler_type.GetPointeeType(); - GetPossibleMatches( - valobj, non_ptr_type, - use_dynamic, entries, true, did_strip_ref, did_strip_typedef); + GetPossibleMatches(valobj, non_ptr_type, use_dynamic, entries, + current_flags.WithStrippedPointer()); if (non_ptr_type.IsTypedefType()) { CompilerType deffed_pointed_type = non_ptr_type.GetTypedefedType().GetPointerType(); - const bool stripped_typedef = true; - GetPossibleMatches( - valobj, deffed_pointed_type, - use_dynamic, entries, did_strip_ptr, did_strip_ref, - stripped_typedef); // this is not exactly the usual meaning of - // stripping typedefs + // this is not exactly the usual meaning of stripping typedefs + GetPossibleMatches(valobj, deffed_pointed_type, use_dynamic, entries, + current_flags.WithStrippedTypedef()); } } @@ -244,23 +241,19 @@ void FormatManager::GetPossibleMatches( // from it. CompilerType deffed_array_type = element_type.GetTypedefedType().GetArrayType(array_size); - const bool stripped_typedef = true; + // this is not exactly the usual meaning of stripping typedefs GetPossibleMatches( valobj, deffed_array_type, - use_dynamic, entries, did_strip_ptr, did_strip_ref, - stripped_typedef); // this is not exactly the usual meaning of - // stripping typedefs + use_dynamic, entries, current_flags.WithStrippedTypedef()); } } for (lldb::LanguageType language_type : GetCandidateLanguages(valobj.GetObjectRuntimeLanguage())) { if (Language *language = Language::FindPlugin(language_type)) { - for (ConstString candidate : + for (const FormattersMatchCandidate& candidate : language->GetPossibleFormattersMatches(valobj, use_dynamic)) { - entries.push_back( - {candidate, - did_strip_ptr, did_strip_ref, did_strip_typedef}); + entries.push_back(candidate); } } } @@ -268,9 +261,8 @@ void FormatManager::GetPossibleMatches( // try to strip typedef chains if (compiler_type.IsTypedefType()) { CompilerType deffed_type = compiler_type.GetTypedefedType(); - GetPossibleMatches( - valobj, deffed_type, - use_dynamic, entries, did_strip_ptr, did_strip_ref, true); + GetPossibleMatches(valobj, deffed_type, use_dynamic, entries, + current_flags.WithStrippedTypedef()); } if (root_level) { @@ -284,19 +276,17 @@ void FormatManager::GetPossibleMatches( break; if (unqual_compiler_ast_type.GetOpaqueQualType() != compiler_type.GetOpaqueQualType()) - GetPossibleMatches(valobj, unqual_compiler_ast_type, - use_dynamic, entries, did_strip_ptr, did_strip_ref, - did_strip_typedef); + GetPossibleMatches(valobj, unqual_compiler_ast_type, use_dynamic, + entries, current_flags); } while (false); // if all else fails, go to static type if (valobj.IsDynamic()) { lldb::ValueObjectSP static_value_sp(valobj.GetStaticValue()); if (static_value_sp) - GetPossibleMatches( - *static_value_sp.get(), static_value_sp->GetCompilerType(), - use_dynamic, entries, did_strip_ptr, did_strip_ref, - did_strip_typedef, true); + GetPossibleMatches(*static_value_sp.get(), + static_value_sp->GetCompilerType(), use_dynamic, + entries, current_flags, true); } } } @@ -723,16 +713,14 @@ void FormatManager::LoadSystemFormatters() { lldb::TypeSummaryImplSP string_array_format( new StringSummaryFormat(string_array_flags, "${var%char[]}")); - RegularExpression any_size_char_arr(R"(^((un)?signed )?char ?\[[0-9]+\]$)"); - TypeCategoryImpl::SharedPointer sys_category_sp = GetCategory(m_system_category_name); - sys_category_sp->GetRegexTypeSummariesContainer()->Add( - RegularExpression(R"(^(unsigned )?char ?(\*|\[\])$)"), string_format); + sys_category_sp->AddTypeSummary(R"(^(unsigned )?char ?(\*|\[\])$)", + eFormatterMatchRegex, string_format); - sys_category_sp->GetRegexTypeSummariesContainer()->Add( - std::move(any_size_char_arr), string_array_format); + sys_category_sp->AddTypeSummary(R"(^((un)?signed )?char ?\[[0-9]+\]$)", + eFormatterMatchRegex, string_array_format); lldb::TypeSummaryImplSP ostype_summary( new StringSummaryFormat(TypeSummaryImpl::Flags() @@ -745,8 +733,8 @@ void FormatManager::LoadSystemFormatters() { .SetHideItemNames(false), "${var%O}")); - sys_category_sp->GetTypeSummariesContainer()->Add(ConstString("OSType"), - ostype_summary); + sys_category_sp->AddTypeSummary("OSType", eFormatterMatchExact, + ostype_summary); TypeFormatImpl::Flags fourchar_flags; fourchar_flags.SetCascades(true).SetSkipPointers(true).SetSkipReferences( diff --git a/contrib/llvm-project/lldb/source/DataFormatters/FormattersHelpers.cpp b/contrib/llvm-project/lldb/source/DataFormatters/FormattersHelpers.cpp index b9c6b017e293..1f10166d1bc9 100644 --- a/contrib/llvm-project/lldb/source/DataFormatters/FormattersHelpers.cpp +++ b/contrib/llvm-project/lldb/source/DataFormatters/FormattersHelpers.cpp @@ -26,23 +26,17 @@ void lldb_private::formatters::AddFormat( ConstString type_name, TypeFormatImpl::Flags flags, bool regex) { lldb::TypeFormatImplSP format_sp(new TypeFormatImpl_Format(format, flags)); - if (regex) - category_sp->GetRegexTypeFormatsContainer()->Add( - RegularExpression(type_name.GetStringRef()), format_sp); - else - category_sp->GetTypeFormatsContainer()->Add(std::move(type_name), - format_sp); + FormatterMatchType match_type = + regex ? eFormatterMatchRegex : eFormatterMatchExact; + category_sp->AddTypeFormat(type_name.GetStringRef(), match_type, format_sp); } void lldb_private::formatters::AddSummary( TypeCategoryImpl::SharedPointer category_sp, TypeSummaryImplSP summary_sp, ConstString type_name, bool regex) { - if (regex) - category_sp->GetRegexTypeSummariesContainer()->Add( - RegularExpression(type_name.GetStringRef()), summary_sp); - else - category_sp->GetTypeSummariesContainer()->Add(std::move(type_name), - summary_sp); + FormatterMatchType match_type = + regex ? eFormatterMatchRegex : eFormatterMatchExact; + category_sp->AddTypeSummary(type_name.GetStringRef(), match_type, summary_sp); } void lldb_private::formatters::AddStringSummary( @@ -50,12 +44,9 @@ void lldb_private::formatters::AddStringSummary( ConstString type_name, TypeSummaryImpl::Flags flags, bool regex) { lldb::TypeSummaryImplSP summary_sp(new StringSummaryFormat(flags, string)); - if (regex) - category_sp->GetRegexTypeSummariesContainer()->Add( - RegularExpression(type_name.GetStringRef()), summary_sp); - else - category_sp->GetTypeSummariesContainer()->Add(std::move(type_name), - summary_sp); + FormatterMatchType match_type = + regex ? eFormatterMatchRegex : eFormatterMatchExact; + category_sp->AddTypeSummary(type_name.GetStringRef(), match_type, summary_sp); } void lldb_private::formatters::AddOneLineSummary( @@ -64,12 +55,9 @@ void lldb_private::formatters::AddOneLineSummary( flags.SetShowMembersOneLiner(true); lldb::TypeSummaryImplSP summary_sp(new StringSummaryFormat(flags, "")); - if (regex) - category_sp->GetRegexTypeSummariesContainer()->Add( - RegularExpression(type_name.GetStringRef()), summary_sp); - else - category_sp->GetTypeSummariesContainer()->Add(std::move(type_name), - summary_sp); + FormatterMatchType match_type = + regex ? eFormatterMatchRegex : eFormatterMatchExact; + category_sp->AddTypeSummary(type_name.GetStringRef(), match_type, summary_sp); } void lldb_private::formatters::AddCXXSummary( @@ -78,12 +66,10 @@ void lldb_private::formatters::AddCXXSummary( ConstString type_name, TypeSummaryImpl::Flags flags, bool regex) { lldb::TypeSummaryImplSP summary_sp( new CXXFunctionSummaryFormat(flags, funct, description)); - if (regex) - category_sp->GetRegexTypeSummariesContainer()->Add( - RegularExpression(type_name.GetStringRef()), summary_sp); - else - category_sp->GetTypeSummariesContainer()->Add(std::move(type_name), - summary_sp); + + FormatterMatchType match_type = + regex ? eFormatterMatchRegex : eFormatterMatchExact; + category_sp->AddTypeSummary(type_name.GetStringRef(), match_type, summary_sp); } void lldb_private::formatters::AddCXXSynthetic( @@ -93,12 +79,9 @@ void lldb_private::formatters::AddCXXSynthetic( ScriptedSyntheticChildren::Flags flags, bool regex) { lldb::SyntheticChildrenSP synth_sp( new CXXSyntheticChildren(flags, description, generator)); - if (regex) - category_sp->GetRegexTypeSyntheticsContainer()->Add( - RegularExpression(type_name.GetStringRef()), synth_sp); - else - category_sp->GetTypeSyntheticsContainer()->Add(std::move(type_name), - synth_sp); + FormatterMatchType match_type = + regex ? eFormatterMatchRegex : eFormatterMatchExact; + category_sp->AddTypeSynthetic(type_name.GetStringRef(), match_type, synth_sp); } void lldb_private::formatters::AddFilter( @@ -108,12 +91,9 @@ void lldb_private::formatters::AddFilter( TypeFilterImplSP filter_sp(new TypeFilterImpl(flags)); for (auto child : children) filter_sp->AddExpressionPath(child); - if (regex) - category_sp->GetRegexTypeFiltersContainer()->Add( - RegularExpression(type_name.GetStringRef()), filter_sp); - else - category_sp->GetTypeFiltersContainer()->Add(std::move(type_name), - filter_sp); + FormatterMatchType match_type = + regex ? eFormatterMatchRegex : eFormatterMatchExact; + category_sp->AddTypeFilter(type_name.GetStringRef(), match_type, filter_sp); } size_t lldb_private::formatters::ExtractIndexFromString(const char *item_name) { diff --git a/contrib/llvm-project/lldb/source/DataFormatters/TypeCategory.cpp b/contrib/llvm-project/lldb/source/DataFormatters/TypeCategory.cpp index f1c6210edd1a..4d8663ea9c03 100644 --- a/contrib/llvm-project/lldb/source/DataFormatters/TypeCategory.cpp +++ b/contrib/llvm-project/lldb/source/DataFormatters/TypeCategory.cpp @@ -87,10 +87,7 @@ bool TypeCategoryImpl::Get(lldb::LanguageType lang, lldb::TypeFormatImplSP &entry) { if (!IsEnabled() || !IsApplicable(lang)) return false; - if (GetTypeFormatsContainer()->Get(candidates, entry)) - return true; - bool regex = GetRegexTypeFormatsContainer()->Get(candidates, entry); - return regex; + return m_format_cont.Get(candidates, entry); } bool TypeCategoryImpl::Get(lldb::LanguageType lang, @@ -98,10 +95,7 @@ bool TypeCategoryImpl::Get(lldb::LanguageType lang, lldb::TypeSummaryImplSP &entry) { if (!IsEnabled() || !IsApplicable(lang)) return false; - if (GetTypeSummariesContainer()->Get(candidates, entry)) - return true; - bool regex = GetRegexTypeSummariesContainer()->Get(candidates, entry); - return regex; + return m_summary_cont.Get(candidates, entry); } bool TypeCategoryImpl::Get(lldb::LanguageType lang, @@ -109,30 +103,29 @@ bool TypeCategoryImpl::Get(lldb::LanguageType lang, lldb::SyntheticChildrenSP &entry) { if (!IsEnabled() || !IsApplicable(lang)) return false; - TypeFilterImpl::SharedPointer filter_sp; + // first find both Filter and Synth, and then check which is most recent + bool pick_synth = false; - if (!GetTypeFiltersContainer()->Get(candidates, filter_sp)) - GetRegexTypeFiltersContainer()->Get(candidates, filter_sp); + TypeFilterImpl::SharedPointer filter_sp; + m_filter_cont.Get(candidates, filter_sp); - bool pick_synth = false; - ScriptedSyntheticChildren::SharedPointer synth; - if (!GetTypeSyntheticsContainer()->Get(candidates, synth)) - GetRegexTypeSyntheticsContainer()->Get(candidates, synth); - if (!filter_sp.get() && !synth.get()) + ScriptedSyntheticChildren::SharedPointer synth_sp; + m_synth_cont.Get(candidates, synth_sp); + + if (!filter_sp.get() && !synth_sp.get()) return false; - else if (!filter_sp.get() && synth.get()) + else if (!filter_sp.get() && synth_sp.get()) pick_synth = true; - - else if (filter_sp.get() && !synth.get()) + else if (filter_sp.get() && !synth_sp.get()) pick_synth = false; - - else /*if (filter_sp.get() && synth.get())*/ + else /*if (filter_sp.get() && synth_sp.get())*/ { - pick_synth = filter_sp->GetRevision() <= synth->GetRevision(); + pick_synth = filter_sp->GetRevision() <= synth_sp->GetRevision(); } + if (pick_synth) { - entry = synth; + entry = synth_sp; return true; } else { entry = filter_sp; @@ -142,53 +135,33 @@ bool TypeCategoryImpl::Get(lldb::LanguageType lang, } void TypeCategoryImpl::Clear(FormatCategoryItems items) { - if ((items & eFormatCategoryItemValue) == eFormatCategoryItemValue) - GetTypeFormatsContainer()->Clear(); - if ((items & eFormatCategoryItemRegexValue) == eFormatCategoryItemRegexValue) - GetRegexTypeFormatsContainer()->Clear(); - - if ((items & eFormatCategoryItemSummary) == eFormatCategoryItemSummary) - GetTypeSummariesContainer()->Clear(); - if ((items & eFormatCategoryItemRegexSummary) == - eFormatCategoryItemRegexSummary) - GetRegexTypeSummariesContainer()->Clear(); - - if ((items & eFormatCategoryItemFilter) == eFormatCategoryItemFilter) - GetTypeFiltersContainer()->Clear(); - if ((items & eFormatCategoryItemRegexFilter) == - eFormatCategoryItemRegexFilter) - GetRegexTypeFiltersContainer()->Clear(); - - if ((items & eFormatCategoryItemSynth) == eFormatCategoryItemSynth) - GetTypeSyntheticsContainer()->Clear(); - if ((items & eFormatCategoryItemRegexSynth) == eFormatCategoryItemRegexSynth) - GetRegexTypeSyntheticsContainer()->Clear(); + if (items & eFormatCategoryItemFormat) + m_format_cont.Clear(); + + if (items & eFormatCategoryItemSummary) + m_summary_cont.Clear(); + + if (items & eFormatCategoryItemFilter) + m_filter_cont.Clear(); + + if (items & eFormatCategoryItemSynth) + m_synth_cont.Clear(); } bool TypeCategoryImpl::Delete(ConstString name, FormatCategoryItems items) { bool success = false; - if ((items & eFormatCategoryItemValue) == eFormatCategoryItemValue) - success = GetTypeFormatsContainer()->Delete(name) || success; - if ((items & eFormatCategoryItemRegexValue) == eFormatCategoryItemRegexValue) - success = GetRegexTypeFormatsContainer()->Delete(name) || success; + if (items & eFormatCategoryItemFormat) + success = m_format_cont.Delete(name) || success; - if ((items & eFormatCategoryItemSummary) == eFormatCategoryItemSummary) - success = GetTypeSummariesContainer()->Delete(name) || success; - if ((items & eFormatCategoryItemRegexSummary) == - eFormatCategoryItemRegexSummary) - success = GetRegexTypeSummariesContainer()->Delete(name) || success; + if (items & eFormatCategoryItemSummary) + success = m_summary_cont.Delete(name) || success; - if ((items & eFormatCategoryItemFilter) == eFormatCategoryItemFilter) - success = GetTypeFiltersContainer()->Delete(name) || success; - if ((items & eFormatCategoryItemRegexFilter) == - eFormatCategoryItemRegexFilter) - success = GetRegexTypeFiltersContainer()->Delete(name) || success; + if (items & eFormatCategoryItemFilter) + success = m_filter_cont.Delete(name) || success; - if ((items & eFormatCategoryItemSynth) == eFormatCategoryItemSynth) - success = GetTypeSyntheticsContainer()->Delete(name) || success; - if ((items & eFormatCategoryItemRegexSynth) == eFormatCategoryItemRegexSynth) - success = GetRegexTypeSyntheticsContainer()->Delete(name) || success; + if (items & eFormatCategoryItemSynth) + success = m_synth_cont.Delete(name) || success; return success; } @@ -196,65 +169,40 @@ bool TypeCategoryImpl::Delete(ConstString name, FormatCategoryItems items) { uint32_t TypeCategoryImpl::GetCount(FormatCategoryItems items) { uint32_t count = 0; - if ((items & eFormatCategoryItemValue) == eFormatCategoryItemValue) - count += GetTypeFormatsContainer()->GetCount(); - if ((items & eFormatCategoryItemRegexValue) == eFormatCategoryItemRegexValue) - count += GetRegexTypeFormatsContainer()->GetCount(); + if (items & eFormatCategoryItemFormat) + count += m_format_cont.GetCount(); - if ((items & eFormatCategoryItemSummary) == eFormatCategoryItemSummary) - count += GetTypeSummariesContainer()->GetCount(); - if ((items & eFormatCategoryItemRegexSummary) == - eFormatCategoryItemRegexSummary) - count += GetRegexTypeSummariesContainer()->GetCount(); + if (items & eFormatCategoryItemSummary) + count += m_summary_cont.GetCount(); - if ((items & eFormatCategoryItemFilter) == eFormatCategoryItemFilter) - count += GetTypeFiltersContainer()->GetCount(); - if ((items & eFormatCategoryItemRegexFilter) == - eFormatCategoryItemRegexFilter) - count += GetRegexTypeFiltersContainer()->GetCount(); + if (items & eFormatCategoryItemFilter) + count += m_filter_cont.GetCount(); - if ((items & eFormatCategoryItemSynth) == eFormatCategoryItemSynth) - count += GetTypeSyntheticsContainer()->GetCount(); - if ((items & eFormatCategoryItemRegexSynth) == eFormatCategoryItemRegexSynth) - count += GetRegexTypeSyntheticsContainer()->GetCount(); + if (items & eFormatCategoryItemSynth) + count += m_synth_cont.GetCount(); return count; } -bool TypeCategoryImpl::AnyMatches(ConstString type_name, - FormatCategoryItems items, bool only_enabled, - const char **matching_category, - FormatCategoryItems *matching_type) { +bool TypeCategoryImpl::AnyMatches( + const FormattersMatchCandidate &candidate_type, FormatCategoryItems items, + bool only_enabled, const char **matching_category, + FormatCategoryItems *matching_type) { if (!IsEnabled() && only_enabled) return false; - lldb::TypeFormatImplSP format_sp; - lldb::TypeSummaryImplSP summary_sp; - TypeFilterImpl::SharedPointer filter_sp; - ScriptedSyntheticChildren::SharedPointer synth_sp; - - if ((items & eFormatCategoryItemValue) == eFormatCategoryItemValue) { - if (GetTypeFormatsContainer()->Get(type_name, format_sp)) { - if (matching_category) - *matching_category = m_name.GetCString(); - if (matching_type) - *matching_type = eFormatCategoryItemValue; - return true; - } - } - if ((items & eFormatCategoryItemRegexValue) == - eFormatCategoryItemRegexValue) { - if (GetRegexTypeFormatsContainer()->Get(type_name, format_sp)) { + if (items & eFormatCategoryItemFormat) { + if (m_format_cont.AnyMatches(candidate_type)) { if (matching_category) *matching_category = m_name.GetCString(); if (matching_type) - *matching_type = eFormatCategoryItemRegexValue; + *matching_type = eFormatCategoryItemFormat; return true; } } - if ((items & eFormatCategoryItemSummary) == eFormatCategoryItemSummary) { - if (GetTypeSummariesContainer()->Get(type_name, summary_sp)) { + if (items & eFormatCategoryItemSummary) { + if (m_summary_cont.AnyMatches(candidate_type)) { if (matching_category) *matching_category = m_name.GetCString(); if (matching_type) @@ -262,19 +210,9 @@ bool TypeCategoryImpl::AnyMatches(ConstString type_name, return true; } } - if ((items & eFormatCategoryItemRegexSummary) == - eFormatCategoryItemRegexSummary) { - if (GetRegexTypeSummariesContainer()->Get(type_name, summary_sp)) { - if (matching_category) - *matching_category = m_name.GetCString(); - if (matching_type) - *matching_type = eFormatCategoryItemRegexSummary; - return true; - } - } - if ((items & eFormatCategoryItemFilter) == eFormatCategoryItemFilter) { - if (GetTypeFiltersContainer()->Get(type_name, filter_sp)) { + if (items & eFormatCategoryItemFilter) { + if (m_filter_cont.AnyMatches(candidate_type)) { if (matching_category) *matching_category = m_name.GetCString(); if (matching_type) @@ -282,19 +220,9 @@ bool TypeCategoryImpl::AnyMatches(ConstString type_name, return true; } } - if ((items & eFormatCategoryItemRegexFilter) == - eFormatCategoryItemRegexFilter) { - if (GetRegexTypeFiltersContainer()->Get(type_name, filter_sp)) { - if (matching_category) - *matching_category = m_name.GetCString(); - if (matching_type) - *matching_type = eFormatCategoryItemRegexFilter; - return true; - } - } - if ((items & eFormatCategoryItemSynth) == eFormatCategoryItemSynth) { - if (GetTypeSyntheticsContainer()->Get(type_name, synth_sp)) { + if (items & eFormatCategoryItemSynth) { + if (m_synth_cont.AnyMatches(candidate_type)) { if (matching_category) *matching_category = m_name.GetCString(); if (matching_type) @@ -302,154 +230,80 @@ bool TypeCategoryImpl::AnyMatches(ConstString type_name, return true; } } - if ((items & eFormatCategoryItemRegexSynth) == - eFormatCategoryItemRegexSynth) { - if (GetRegexTypeSyntheticsContainer()->Get(type_name, synth_sp)) { - if (matching_category) - *matching_category = m_name.GetCString(); - if (matching_type) - *matching_type = eFormatCategoryItemRegexSynth; - return true; - } - } return false; } +void TypeCategoryImpl::AutoComplete(CompletionRequest &request, + FormatCategoryItems items) { + if (items & eFormatCategoryItemFormat) + m_format_cont.AutoComplete(request); + if (items & eFormatCategoryItemSummary) + m_summary_cont.AutoComplete(request); + if (items & eFormatCategoryItemFilter) + m_filter_cont.AutoComplete(request); + if (items & eFormatCategoryItemSynth) + m_synth_cont.AutoComplete(request); +} + TypeCategoryImpl::FormatContainer::MapValueType TypeCategoryImpl::GetFormatForType(lldb::TypeNameSpecifierImplSP type_sp) { - FormatContainer::MapValueType retval; - - if (type_sp) { - if (type_sp->IsRegex()) - GetRegexTypeFormatsContainer()->GetExact(ConstString(type_sp->GetName()), - retval); - else - GetTypeFormatsContainer()->GetExact(ConstString(type_sp->GetName()), - retval); - } - - return retval; + return m_format_cont.GetForTypeNameSpecifier(type_sp); } TypeCategoryImpl::SummaryContainer::MapValueType TypeCategoryImpl::GetSummaryForType(lldb::TypeNameSpecifierImplSP type_sp) { - SummaryContainer::MapValueType retval; - - if (type_sp) { - if (type_sp->IsRegex()) - GetRegexTypeSummariesContainer()->GetExact( - ConstString(type_sp->GetName()), retval); - else - GetTypeSummariesContainer()->GetExact(ConstString(type_sp->GetName()), - retval); - } - - return retval; + return m_summary_cont.GetForTypeNameSpecifier(type_sp); } TypeCategoryImpl::FilterContainer::MapValueType TypeCategoryImpl::GetFilterForType(lldb::TypeNameSpecifierImplSP type_sp) { - FilterContainer::MapValueType retval; - - if (type_sp) { - if (type_sp->IsRegex()) - GetRegexTypeFiltersContainer()->GetExact(ConstString(type_sp->GetName()), - retval); - else - GetTypeFiltersContainer()->GetExact(ConstString(type_sp->GetName()), - retval); - } - - return retval; + return m_filter_cont.GetForTypeNameSpecifier(type_sp); } TypeCategoryImpl::SynthContainer::MapValueType TypeCategoryImpl::GetSyntheticForType(lldb::TypeNameSpecifierImplSP type_sp) { - SynthContainer::MapValueType retval; - - if (type_sp) { - if (type_sp->IsRegex()) - GetRegexTypeSyntheticsContainer()->GetExact( - ConstString(type_sp->GetName()), retval); - else - GetTypeSyntheticsContainer()->GetExact(ConstString(type_sp->GetName()), - retval); - } - - return retval; -} - -lldb::TypeNameSpecifierImplSP -TypeCategoryImpl::GetTypeNameSpecifierForSummaryAtIndex(size_t index) { - if (index < GetTypeSummariesContainer()->GetCount()) - return GetTypeSummariesContainer()->GetTypeNameSpecifierAtIndex(index); - else - return GetRegexTypeSummariesContainer()->GetTypeNameSpecifierAtIndex( - index - GetTypeSummariesContainer()->GetCount()); + return m_synth_cont.GetForTypeNameSpecifier(type_sp); } TypeCategoryImpl::FormatContainer::MapValueType TypeCategoryImpl::GetFormatAtIndex(size_t index) { - if (index < GetTypeFormatsContainer()->GetCount()) - return GetTypeFormatsContainer()->GetAtIndex(index); - else - return GetRegexTypeFormatsContainer()->GetAtIndex( - index - GetTypeFormatsContainer()->GetCount()); + return m_format_cont.GetAtIndex(index); } TypeCategoryImpl::SummaryContainer::MapValueType TypeCategoryImpl::GetSummaryAtIndex(size_t index) { - if (index < GetTypeSummariesContainer()->GetCount()) - return GetTypeSummariesContainer()->GetAtIndex(index); - else - return GetRegexTypeSummariesContainer()->GetAtIndex( - index - GetTypeSummariesContainer()->GetCount()); + return m_summary_cont.GetAtIndex(index); } TypeCategoryImpl::FilterContainer::MapValueType TypeCategoryImpl::GetFilterAtIndex(size_t index) { - if (index < GetTypeFiltersContainer()->GetCount()) - return GetTypeFiltersContainer()->GetAtIndex(index); - else - return GetRegexTypeFiltersContainer()->GetAtIndex( - index - GetTypeFiltersContainer()->GetCount()); + return m_filter_cont.GetAtIndex(index); +} + +TypeCategoryImpl::SynthContainer::MapValueType +TypeCategoryImpl::GetSyntheticAtIndex(size_t index) { + return m_synth_cont.GetAtIndex(index); } lldb::TypeNameSpecifierImplSP TypeCategoryImpl::GetTypeNameSpecifierForFormatAtIndex(size_t index) { - if (index < GetTypeFormatsContainer()->GetCount()) - return GetTypeFormatsContainer()->GetTypeNameSpecifierAtIndex(index); - else - return GetRegexTypeFormatsContainer()->GetTypeNameSpecifierAtIndex( - index - GetTypeFormatsContainer()->GetCount()); + return m_format_cont.GetTypeNameSpecifierAtIndex(index); } lldb::TypeNameSpecifierImplSP -TypeCategoryImpl::GetTypeNameSpecifierForFilterAtIndex(size_t index) { - if (index < GetTypeFiltersContainer()->GetCount()) - return GetTypeFiltersContainer()->GetTypeNameSpecifierAtIndex(index); - else - return GetRegexTypeFiltersContainer()->GetTypeNameSpecifierAtIndex( - index - GetTypeFiltersContainer()->GetCount()); +TypeCategoryImpl::GetTypeNameSpecifierForSummaryAtIndex(size_t index) { + return m_summary_cont.GetTypeNameSpecifierAtIndex(index); } -TypeCategoryImpl::SynthContainer::MapValueType -TypeCategoryImpl::GetSyntheticAtIndex(size_t index) { - if (index < GetTypeSyntheticsContainer()->GetCount()) - return GetTypeSyntheticsContainer()->GetAtIndex(index); - else - return GetRegexTypeSyntheticsContainer()->GetAtIndex( - index - GetTypeSyntheticsContainer()->GetCount()); +lldb::TypeNameSpecifierImplSP +TypeCategoryImpl::GetTypeNameSpecifierForFilterAtIndex(size_t index) { + return m_filter_cont.GetTypeNameSpecifierAtIndex(index); } lldb::TypeNameSpecifierImplSP TypeCategoryImpl::GetTypeNameSpecifierForSyntheticAtIndex(size_t index) { - if (index < GetTypeSyntheticsContainer()->GetCount()) - return GetTypeSyntheticsContainer()->GetTypeNameSpecifierAtIndex(index); - else - return GetRegexTypeSyntheticsContainer()->GetTypeNameSpecifierAtIndex( - index - GetTypeSyntheticsContainer()->GetCount()); + return m_synth_cont.GetTypeNameSpecifierAtIndex(index); } void TypeCategoryImpl::Enable(bool value, uint32_t position) { diff --git a/contrib/llvm-project/lldb/source/DataFormatters/TypeCategoryMap.cpp b/contrib/llvm-project/lldb/source/DataFormatters/TypeCategoryMap.cpp index aa8387b4deec..55635173cc8c 100644 --- a/contrib/llvm-project/lldb/source/DataFormatters/TypeCategoryMap.cpp +++ b/contrib/llvm-project/lldb/source/DataFormatters/TypeCategoryMap.cpp @@ -154,14 +154,15 @@ bool TypeCategoryMap::Get(uint32_t pos, ValueSP &entry) { } bool TypeCategoryMap::AnyMatches( - ConstString type_name, TypeCategoryImpl::FormatCategoryItems items, - bool only_enabled, const char **matching_category, + const FormattersMatchCandidate &candidate_type, + TypeCategoryImpl::FormatCategoryItems items, bool only_enabled, + const char **matching_category, TypeCategoryImpl::FormatCategoryItems *matching_type) { std::lock_guard<std::recursive_mutex> guard(m_map_mutex); MapIterator pos, end = m_map.end(); for (pos = m_map.begin(); pos != end; pos++) { - if (pos->second->AnyMatches(type_name, items, only_enabled, + if (pos->second->AnyMatches(candidate_type, items, only_enabled, matching_category, matching_type)) return true; } diff --git a/contrib/llvm-project/lldb/source/DataFormatters/TypeFormat.cpp b/contrib/llvm-project/lldb/source/DataFormatters/TypeFormat.cpp index ae9d8d806a5b..5ee89fc0d5eb 100644 --- a/contrib/llvm-project/lldb/source/DataFormatters/TypeFormat.cpp +++ b/contrib/llvm-project/lldb/source/DataFormatters/TypeFormat.cpp @@ -23,6 +23,7 @@ #include "lldb/Target/Target.h" #include "lldb/Utility/DataExtractor.h" #include "lldb/Utility/StreamString.h" +#include <optional> using namespace lldb; using namespace lldb_private; @@ -95,7 +96,7 @@ bool TypeFormatImpl_Format::FormatObject(ValueObject *valobj, ExecutionContextScope *exe_scope = exe_ctx.GetBestExecutionContextScope(); - llvm::Optional<uint64_t> size = compiler_type.GetByteSize(exe_scope); + std::optional<uint64_t> size = compiler_type.GetByteSize(exe_scope); if (!size) return false; StreamString sstr; diff --git a/contrib/llvm-project/lldb/source/DataFormatters/VectorType.cpp b/contrib/llvm-project/lldb/source/DataFormatters/VectorType.cpp index e35ed881db08..4afcfa2e8e49 100644 --- a/contrib/llvm-project/lldb/source/DataFormatters/VectorType.cpp +++ b/contrib/llvm-project/lldb/source/DataFormatters/VectorType.cpp @@ -16,6 +16,7 @@ #include "lldb/Utility/LLDBAssert.h" #include "lldb/Utility/Log.h" +#include <optional> using namespace lldb; using namespace lldb_private; @@ -23,8 +24,10 @@ using namespace lldb_private::formatters; static CompilerType GetCompilerTypeForFormat(lldb::Format format, CompilerType element_type, - TypeSystem *type_system) { + TypeSystemSP type_system) { lldbassert(type_system && "type_system needs to be not NULL"); + if (!type_system) + return {}; switch (format) { case lldb::eFormatAddressInfo: @@ -171,9 +174,9 @@ static size_t CalculateNumChildren( lldb_private::ExecutionContextScope *exe_scope = nullptr // does not matter here because all we trade in are basic types ) { - llvm::Optional<uint64_t> container_size = + std::optional<uint64_t> container_size = container_type.GetByteSize(exe_scope); - llvm::Optional<uint64_t> element_size = element_type.GetByteSize(exe_scope); + std::optional<uint64_t> element_size = element_type.GetByteSize(exe_scope); if (container_size && element_size && *element_size) { if (*container_size % *element_size) @@ -198,7 +201,7 @@ public: lldb::ValueObjectSP GetChildAtIndex(size_t idx) override { if (idx >= CalculateNumChildren()) return {}; - llvm::Optional<uint64_t> size = m_child_type.GetByteSize(nullptr); + std::optional<uint64_t> size = m_child_type.GetByteSize(nullptr); if (!size) return {}; auto offset = idx * *size; @@ -219,8 +222,9 @@ public: CompilerType parent_type(m_backend.GetCompilerType()); CompilerType element_type; parent_type.IsVectorType(&element_type); - m_child_type = ::GetCompilerTypeForFormat(m_parent_format, element_type, - parent_type.GetTypeSystem()); + m_child_type = ::GetCompilerTypeForFormat( + m_parent_format, element_type, + parent_type.GetTypeSystem().GetSharedPointer()); m_num_children = ::CalculateNumChildren(parent_type, m_child_type); m_item_format = GetItemFormatForFormat(m_parent_format, m_child_type); return false; diff --git a/contrib/llvm-project/lldb/source/Expression/DWARFExpression.cpp b/contrib/llvm-project/lldb/source/Expression/DWARFExpression.cpp index 25f6a46d805b..47cef1b35180 100644 --- a/contrib/llvm-project/lldb/source/Expression/DWARFExpression.cpp +++ b/contrib/llvm-project/lldb/source/Expression/DWARFExpression.cpp @@ -10,6 +10,7 @@ #include <cinttypes> +#include <optional> #include <vector> #include "lldb/Core/Module.h" @@ -69,9 +70,21 @@ void DWARFExpression::UpdateValue(uint64_t const_value, void DWARFExpression::DumpLocation(Stream *s, lldb::DescriptionLevel level, ABI *abi) const { + auto *MCRegInfo = abi ? &abi->GetMCRegisterInfo() : nullptr; + auto GetRegName = [&MCRegInfo](uint64_t DwarfRegNum, + bool IsEH) -> llvm::StringRef { + if (!MCRegInfo) + return {}; + if (std::optional<unsigned> LLVMRegNum = + MCRegInfo->getLLVMRegNum(DwarfRegNum, IsEH)) + if (const char *RegName = MCRegInfo->getName(*LLVMRegNum)) + return llvm::StringRef(RegName); + return {}; + }; + llvm::DIDumpOptions DumpOpts; + DumpOpts.GetNameForDWARFReg = GetRegName; llvm::DWARFExpression(m_data.GetAsLLVM(), m_data.GetAddressByteSize()) - .print(s->AsRawOstream(), llvm::DIDumpOptions(), - abi ? &abi->GetMCRegisterInfo() : nullptr, nullptr); + .print(s->AsRawOstream(), DumpOpts, nullptr); } RegisterKind DWARFExpression::GetRegisterKind() const { return m_reg_kind; } @@ -131,7 +144,7 @@ static bool ReadRegisterValueAsScalar(RegisterContext *reg_ctx, /// are made on the state of \p data after this call. static offset_t GetOpcodeDataSize(const DataExtractor &data, const lldb::offset_t data_offset, - const uint8_t op) { + const uint8_t op, const DWARFUnit *dwarf_cu) { lldb::offset_t offset = data_offset; switch (op) { case DW_OP_addr: @@ -333,9 +346,12 @@ static offset_t GetOpcodeDataSize(const DataExtractor &data, } default: - break; + if (!dwarf_cu) { + return LLDB_INVALID_OFFSET; + } + return dwarf_cu->GetSymbolFileDWARF().GetVendorDWARFOpcodeSize( + data, data_offset, op); } - return LLDB_INVALID_OFFSET; } lldb::addr_t DWARFExpression::GetLocation_DW_OP_addr(const DWARFUnit *dwarf_cu, @@ -364,7 +380,8 @@ lldb::addr_t DWARFExpression::GetLocation_DW_OP_addr(const DWARFUnit *dwarf_cu, } ++curr_op_addr_idx; } else { - const offset_t op_arg_size = GetOpcodeDataSize(m_data, offset, op); + const offset_t op_arg_size = + GetOpcodeDataSize(m_data, offset, op, dwarf_cu); if (op_arg_size == LLDB_INVALID_OFFSET) { error = true; break; @@ -375,7 +392,8 @@ lldb::addr_t DWARFExpression::GetLocation_DW_OP_addr(const DWARFUnit *dwarf_cu, return LLDB_INVALID_ADDRESS; } -bool DWARFExpression::Update_DW_OP_addr(lldb::addr_t file_addr) { +bool DWARFExpression::Update_DW_OP_addr(const DWARFUnit *dwarf_cu, + lldb::addr_t file_addr) { lldb::offset_t offset = 0; while (m_data.ValidOffset(offset)) { const uint8_t op = m_data.GetU8(&offset); @@ -402,7 +420,8 @@ bool DWARFExpression::Update_DW_OP_addr(lldb::addr_t file_addr) { m_data.SetData(encoder.GetDataBuffer()); return true; } else { - const offset_t op_arg_size = GetOpcodeDataSize(m_data, offset, op); + const offset_t op_arg_size = + GetOpcodeDataSize(m_data, offset, op, dwarf_cu); if (op_arg_size == LLDB_INVALID_OFFSET) break; offset += op_arg_size; @@ -411,14 +430,16 @@ bool DWARFExpression::Update_DW_OP_addr(lldb::addr_t file_addr) { return false; } -bool DWARFExpression::ContainsThreadLocalStorage() const { +bool DWARFExpression::ContainsThreadLocalStorage( + const DWARFUnit *dwarf_cu) const { lldb::offset_t offset = 0; while (m_data.ValidOffset(offset)) { const uint8_t op = m_data.GetU8(&offset); if (op == DW_OP_form_tls_address || op == DW_OP_GNU_push_tls_address) return true; - const offset_t op_arg_size = GetOpcodeDataSize(m_data, offset, op); + const offset_t op_arg_size = + GetOpcodeDataSize(m_data, offset, op, dwarf_cu); if (op_arg_size == LLDB_INVALID_OFFSET) return false; offset += op_arg_size; @@ -426,6 +447,7 @@ bool DWARFExpression::ContainsThreadLocalStorage() const { return false; } bool DWARFExpression::LinkThreadLocalStorage( + const DWARFUnit *dwarf_cu, std::function<lldb::addr_t(lldb::addr_t file_addr)> const &link_address_callback) { const uint32_t addr_byte_size = m_data.GetAddressByteSize(); @@ -471,7 +493,7 @@ bool DWARFExpression::LinkThreadLocalStorage( // by a file address on the stack. We assume that DW_OP_const4u or // DW_OP_const8u is used for these values, and we check that the last // opcode we got before either of these was DW_OP_const4u or - // DW_OP_const8u. If so, then we can link the value accodingly. For + // DW_OP_const8u. If so, then we can link the value accordingly. For // Darwin, the value in the DW_OP_const4u or DW_OP_const8u is the file // address of a structure that contains a function pointer, the pthread // key and the offset into the data pointed to by the pthread key. So we @@ -496,7 +518,8 @@ bool DWARFExpression::LinkThreadLocalStorage( } if (!decoded_data) { - const offset_t op_arg_size = GetOpcodeDataSize(m_data, offset, op); + const offset_t op_arg_size = + GetOpcodeDataSize(m_data, offset, op, dwarf_cu); if (op_arg_size == LLDB_INVALID_OFFSET) return false; else @@ -735,7 +758,7 @@ void UpdateValueTypeFromLocationDescription(Log *log, const DWARFUnit *dwarf_cu, Value *value = nullptr) { // Note that this function is conflating DWARF expressions with // DWARF location descriptions. Perhaps it would be better to define - // a wrapper for DWARFExpresssion::Eval() that deals with DWARF + // a wrapper for DWARFExpression::Eval() that deals with DWARF // location descriptions (which consist of one or more DWARF // expressions). But doing this would mean we'd also need factor the // handling of DW_OP_(bit_)piece out of this function. @@ -773,18 +796,18 @@ void UpdateValueTypeFromLocationDescription(Log *log, const DWARFUnit *dwarf_cu, /// \param dw_op_type C-style string used to vary the error output /// \param file_addr the file address we are trying to resolve and turn into a /// load address -/// \param so_addr out parameter, will be set to load addresss or section offset +/// \param so_addr out parameter, will be set to load address or section offset /// \param check_sectionoffset bool which determines if having a section offset /// but not a load address is considerd a success -/// \returns llvm::Optional containing the load address if resolving and getting +/// \returns std::optional containing the load address if resolving and getting /// the load address succeed or an empty Optinal otherwise. If /// check_sectionoffset is true we consider LLDB_INVALID_ADDRESS a /// success if so_addr.IsSectionOffset() is true. -static llvm::Optional<lldb::addr_t> +static std::optional<lldb::addr_t> ResolveLoadAddress(ExecutionContext *exe_ctx, lldb::ModuleSP &module_sp, - Status *error_ptr, const char *dw_op_type, - lldb::addr_t file_addr, Address &so_addr, - bool check_sectionoffset = false) { + Status *error_ptr, const char *dw_op_type, + lldb::addr_t file_addr, Address &so_addr, + bool check_sectionoffset = false) { if (!module_sp) { if (error_ptr) error_ptr->SetErrorStringWithFormat( @@ -847,10 +870,12 @@ bool DWARFExpression::Evaluate( Process *process = nullptr; StackFrame *frame = nullptr; + Target *target = nullptr; if (exe_ctx) { process = exe_ctx->GetProcessPtr(); frame = exe_ctx->GetFramePtr(); + target = exe_ctx->GetTargetPtr(); } if (reg_ctx == nullptr && frame) reg_ctx = frame->GetRegisterContext().get(); @@ -906,12 +931,14 @@ bool DWARFExpression::Evaluate( // address and whose size is the size of an address on the target machine. case DW_OP_addr: stack.push_back(Scalar(opcodes.GetAddress(&offset))); - stack.back().SetValueType(Value::ValueType::FileAddress); - // Convert the file address to a load address, so subsequent - // DWARF operators can operate on it. - if (frame) - stack.back().ConvertToLoadAddress(module_sp.get(), - frame->CalculateTarget().get()); + if (target && + target->GetArchitecture().GetCore() == ArchSpec::eCore_wasm32) { + // wasm file sections aren't mapped into memory, therefore addresses can + // never point into a file section and are always LoadAddresses. + stack.back().SetValueType(Value::ValueType::LoadAddress); + } else { + stack.back().SetValueType(Value::ValueType::FileAddress); + } break; // The DW_OP_addr_sect_offset4 is used for any location expressions in @@ -985,11 +1012,12 @@ bool DWARFExpression::Evaluate( stack.back().GetScalar() = *maybe_load_addr; // Fall through to load address promotion code below. - } LLVM_FALLTHROUGH; + } + [[fallthrough]]; case Value::ValueType::Scalar: // Promote Scalar to LoadAddress and fall through. stack.back().SetValueType(Value::ValueType::LoadAddress); - LLVM_FALLTHROUGH; + [[fallthrough]]; case Value::ValueType::LoadAddress: if (exe_ctx) { if (process) { @@ -1134,7 +1162,7 @@ bool DWARFExpression::Evaluate( // Fall through to load address promotion code below. } - LLVM_FALLTHROUGH; + [[fallthrough]]; case Value::ValueType::Scalar: case Value::ValueType::LoadAddress: if (exe_ctx) { @@ -2373,9 +2401,11 @@ bool DWARFExpression::Evaluate( return false; } } else { - // Retrieve the type DIE that the value is being converted to. + // Retrieve the type DIE that the value is being converted to. This + // offset is compile unit relative so we need to fix it up. + const uint64_t abs_die_offset = die_offset + dwarf_cu->GetOffset(); // FIXME: the constness has annoying ripple effects. - DWARFDIE die = const_cast<DWARFUnit *>(dwarf_cu)->GetDIE(die_offset); + DWARFDIE die = const_cast<DWARFUnit *>(dwarf_cu)->GetDIE(abs_die_offset); if (!die) { if (error_ptr) error_ptr->SetErrorString("Cannot resolve DW_OP_convert type DIE"); @@ -2504,7 +2534,14 @@ bool DWARFExpression::Evaluate( uint64_t index = opcodes.GetULEB128(&offset); lldb::addr_t value = dwarf_cu->ReadAddressFromDebugAddrSection(index); stack.push_back(Scalar(value)); - stack.back().SetValueType(Value::ValueType::FileAddress); + if (target && + target->GetArchitecture().GetCore() == ArchSpec::eCore_wasm32) { + // wasm file sections aren't mapped into memory, therefore addresses can + // never point into a file section and are always LoadAddresses. + stack.back().SetValueType(Value::ValueType::LoadAddress); + } else { + stack.back().SetValueType(Value::ValueType::FileAddress); + } } break; // OPCODE: DW_OP_GNU_const_index @@ -2538,6 +2575,12 @@ bool DWARFExpression::Evaluate( } default: + if (dwarf_cu) { + if (dwarf_cu->GetSymbolFileDWARF().ParseVendorDWARFOpcode( + op, opcodes, offset, stack)) { + break; + } + } if (error_ptr) error_ptr->SetErrorStringWithFormatv( "Unhandled opcode {0} in DWARFExpression", LocationAtom(op)); @@ -2583,10 +2626,10 @@ bool DWARFExpression::ParseDWARFLocationList( dwarf_cu->GetLocationTable(data); Log *log = GetLog(LLDBLog::Expressions); auto lookup_addr = - [&](uint32_t index) -> llvm::Optional<llvm::object::SectionedAddress> { + [&](uint32_t index) -> std::optional<llvm::object::SectionedAddress> { addr_t address = dwarf_cu->ReadAddressFromDebugAddrSection(index); if (address == LLDB_INVALID_ADDRESS) - return llvm::None; + return std::nullopt; return llvm::object::SectionedAddress{address}; }; auto process_list = [&](llvm::Expected<llvm::DWARFLocationExpression> loc) { diff --git a/contrib/llvm-project/lldb/source/Expression/DWARFExpressionList.cpp b/contrib/llvm-project/lldb/source/Expression/DWARFExpressionList.cpp index 5cf722c42fa9..cba4e4e5858a 100644 --- a/contrib/llvm-project/lldb/source/Expression/DWARFExpressionList.cpp +++ b/contrib/llvm-project/lldb/source/Expression/DWARFExpressionList.cpp @@ -90,7 +90,7 @@ bool DWARFExpressionList::ContainsThreadLocalStorage() const { return false; const DWARFExpression &expr = m_exprs.GetEntryRef(0).data; - return expr.ContainsThreadLocalStorage(); + return expr.ContainsThreadLocalStorage(m_dwarf_cu); } bool DWARFExpressionList::LinkThreadLocalStorage( @@ -107,7 +107,7 @@ bool DWARFExpressionList::LinkThreadLocalStorage( // If we linked the TLS address correctly, update the module so that when the // expression is evaluated it can resolve the file address to a load address // and read the TLS data - if (expr.LinkThreadLocalStorage(link_address_callback)) + if (expr.LinkThreadLocalStorage(m_dwarf_cu, link_address_callback)) m_module_wp = new_module_sp; return true; } diff --git a/contrib/llvm-project/lldb/source/Expression/ExpressionVariable.cpp b/contrib/llvm-project/lldb/source/Expression/ExpressionVariable.cpp index da2f3b2a83fb..a397a34601d0 100644 --- a/contrib/llvm-project/lldb/source/Expression/ExpressionVariable.cpp +++ b/contrib/llvm-project/lldb/source/Expression/ExpressionVariable.cpp @@ -11,13 +11,14 @@ #include "lldb/Target/Target.h" #include "lldb/Utility/LLDBLog.h" #include "lldb/Utility/Log.h" +#include <optional> using namespace lldb_private; ExpressionVariable::~ExpressionVariable() = default; uint8_t *ExpressionVariable::GetValueBytes() { - llvm::Optional<uint64_t> byte_size = m_frozen_sp->GetByteSize(); + std::optional<uint64_t> byte_size = m_frozen_sp->GetByteSize(); if (byte_size && *byte_size) { if (m_frozen_sp->GetDataExtractor().GetByteSize() < *byte_size) { m_frozen_sp->GetValue().ResizeData(*byte_size); diff --git a/contrib/llvm-project/lldb/source/Expression/FunctionCaller.cpp b/contrib/llvm-project/lldb/source/Expression/FunctionCaller.cpp index 307bed1ee3fd..ffadbf9b32ec 100644 --- a/contrib/llvm-project/lldb/source/Expression/FunctionCaller.cpp +++ b/contrib/llvm-project/lldb/source/Expression/FunctionCaller.cpp @@ -44,7 +44,8 @@ FunctionCaller::FunctionCaller(ExecutionContextScope &exe_scope, m_function_return_type(return_type), m_wrapper_function_name("__lldb_caller_function"), m_wrapper_struct_name("__lldb_caller_struct"), m_wrapper_args_addrs(), - m_struct_valid(false), m_arg_values(arg_value_list), m_compiled(false), + m_struct_valid(false), m_struct_size(0), m_return_size(0), + m_return_offset(0), m_arg_values(arg_value_list), m_compiled(false), m_JITted(false) { m_jit_process_wp = lldb::ProcessWP(exe_scope.CalculateProcess()); // Can't make a FunctionCaller without a process. @@ -65,17 +66,31 @@ bool FunctionCaller::WriteFunctionWrapper( ExecutionContext &exe_ctx, DiagnosticManager &diagnostic_manager) { Process *process = exe_ctx.GetProcessPtr(); - if (!process) + if (!process) { + diagnostic_manager.Printf(eDiagnosticSeverityError, "no process."); return false; - + } + lldb::ProcessSP jit_process_sp(m_jit_process_wp.lock()); - if (process != jit_process_sp.get()) + if (process != jit_process_sp.get()) { + diagnostic_manager.Printf(eDiagnosticSeverityError, + "process does not match the stored process."); return false; - - if (!m_compiled) + } + + if (process->GetState() != lldb::eStateStopped) { + diagnostic_manager.Printf(eDiagnosticSeverityError, + "process is not stopped"); return false; + } + if (!m_compiled) { + diagnostic_manager.Printf(eDiagnosticSeverityError, + "function not compiled"); + return false; + } + if (m_JITted) return true; @@ -98,10 +113,10 @@ bool FunctionCaller::WriteFunctionWrapper( if (jit_module_sp) { ConstString const_func_name(FunctionName()); FileSpec jit_file; - jit_file.GetFilename() = const_func_name; + jit_file.SetFilename(const_func_name); jit_module_sp->SetFileSpecAndObjectName(jit_file, ConstString()); m_jit_module_wp = jit_module_sp; - process->GetTarget().GetImages().Append(jit_module_sp, + process->GetTarget().GetImages().Append(jit_module_sp, true /* notify */); } } @@ -212,6 +227,17 @@ bool FunctionCaller::WriteFunctionArguments( bool FunctionCaller::InsertFunction(ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref, DiagnosticManager &diagnostic_manager) { + // Since we might need to call allocate memory and maybe call code to make + // the caller, we need to be stopped. + Process *process = exe_ctx.GetProcessPtr(); + if (!process) { + diagnostic_manager.PutString(eDiagnosticSeverityError, "no process"); + return false; + } + if (process->GetState() != lldb::eStateStopped) { + diagnostic_manager.PutString(eDiagnosticSeverityError, "process running"); + return false; + } if (CompileFunction(exe_ctx.GetThreadSP(), diagnostic_manager) != 0) return false; if (!WriteFunctionWrapper(exe_ctx, diagnostic_manager)) diff --git a/contrib/llvm-project/lldb/source/Expression/IRExecutionUnit.cpp b/contrib/llvm-project/lldb/source/Expression/IRExecutionUnit.cpp index 6b710084faf7..c8068eca5c1b 100644 --- a/contrib/llvm-project/lldb/source/Expression/IRExecutionUnit.cpp +++ b/contrib/llvm-project/lldb/source/Expression/IRExecutionUnit.cpp @@ -37,6 +37,7 @@ #include "lldb/Utility/Log.h" #include "lldb/../../source/Plugins/ObjectFile/JIT/ObjectFileJIT.h" +#include <optional> using namespace lldb_private; @@ -702,9 +703,9 @@ public: LoadAddressResolver(Target *target, bool &symbol_was_missing_weak) : m_target(target), m_symbol_was_missing_weak(symbol_was_missing_weak) {} - llvm::Optional<lldb::addr_t> Resolve(SymbolContextList &sc_list) { + std::optional<lldb::addr_t> Resolve(SymbolContextList &sc_list) { if (sc_list.IsEmpty()) - return llvm::None; + return std::nullopt; lldb::addr_t load_address = LLDB_INVALID_ADDRESS; @@ -758,7 +759,7 @@ public: if (m_symbol_was_missing_weak) return 0; - return llvm::None; + return std::nullopt; } lldb::addr_t GetBestInternalLoadAddress() const { diff --git a/contrib/llvm-project/lldb/source/Expression/IRInterpreter.cpp b/contrib/llvm-project/lldb/source/Expression/IRInterpreter.cpp index a6efeb3f960f..36a8a74ed9ef 100644 --- a/contrib/llvm-project/lldb/source/Expression/IRInterpreter.cpp +++ b/contrib/llvm-project/lldb/source/Expression/IRInterpreter.cpp @@ -167,6 +167,18 @@ public: const Constant *constant = dyn_cast<Constant>(value); if (constant) { + if (constant->getValueID() == Value::ConstantFPVal) { + if (auto *cfp = dyn_cast<ConstantFP>(constant)) { + if (cfp->getType()->isDoubleTy()) + scalar = cfp->getValueAPF().convertToDouble(); + else if (cfp->getType()->isFloatTy()) + scalar = cfp->getValueAPF().convertToFloat(); + else + return false; + return true; + } + return false; + } APInt value_apint; if (!ResolveConstantValue(value_apint, constant)) @@ -189,9 +201,18 @@ public: lldb::offset_t offset = 0; if (value_size <= 8) { - uint64_t u64value = value_extractor.GetMaxU64(&offset, value_size); - return AssignToMatchType(scalar, llvm::APInt(64, u64value), - value->getType()); + Type *ty = value->getType(); + if (ty->isDoubleTy()) { + scalar = value_extractor.GetDouble(&offset); + return true; + } else if (ty->isFloatTy()) { + scalar = value_extractor.GetFloat(&offset); + return true; + } else { + uint64_t u64value = value_extractor.GetMaxU64(&offset, value_size); + return AssignToMatchType(scalar, llvm::APInt(64, u64value), + value->getType()); + } } return false; @@ -205,11 +226,15 @@ public: return false; lldb_private::Scalar cast_scalar; - - scalar.MakeUnsigned(); - if (!AssignToMatchType(cast_scalar, scalar.UInt128(llvm::APInt()), - value->getType())) - return false; + Type *vty = value->getType(); + if (vty->isFloatTy() || vty->isDoubleTy()) { + cast_scalar = scalar; + } else { + scalar.MakeUnsigned(); + if (!AssignToMatchType(cast_scalar, scalar.UInt128(llvm::APInt()), + value->getType())) + return false; + } size_t value_byte_size = m_target_data.getTypeStoreSize(value->getType()); @@ -383,7 +408,7 @@ public: lldb_private::Status alloc_error; return Malloc(m_target_data.getTypeAllocSize(type), - m_target_data.getPrefTypeAlignment(type)); + m_target_data.getPrefTypeAlign(type).value()); } std::string PrintData(lldb::addr_t addr, llvm::Type *type) { @@ -506,6 +531,7 @@ bool IRInterpreter::CanInterpret(llvm::Module &module, llvm::Function &function, return false; } saw_function_with_body = true; + LLDB_LOGF(log, "Saw function with body: %s", f.getName().str().c_str()); } } @@ -543,16 +569,17 @@ bool IRInterpreter::CanInterpret(llvm::Module &module, llvm::Function &function, } break; case Instruction::GetElementPtr: break; + case Instruction::FCmp: case Instruction::ICmp: { - ICmpInst *icmp_inst = dyn_cast<ICmpInst>(&ii); + CmpInst *cmp_inst = dyn_cast<CmpInst>(&ii); - if (!icmp_inst) { + if (!cmp_inst) { error.SetErrorToGenericError(); error.SetErrorString(interpreter_internal_error); return false; } - switch (icmp_inst->getPredicate()) { + switch (cmp_inst->getPredicate()) { default: { LLDB_LOGF(log, "Unsupported ICmp predicate: %s", PrintValue(&ii).c_str()); @@ -561,11 +588,17 @@ bool IRInterpreter::CanInterpret(llvm::Module &module, llvm::Function &function, error.SetErrorString(unsupported_opcode_error); return false; } + case CmpInst::FCMP_OEQ: case CmpInst::ICMP_EQ: + case CmpInst::FCMP_UNE: case CmpInst::ICMP_NE: + case CmpInst::FCMP_OGT: case CmpInst::ICMP_UGT: + case CmpInst::FCMP_OGE: case CmpInst::ICMP_UGE: + case CmpInst::FCMP_OLT: case CmpInst::ICMP_ULT: + case CmpInst::FCMP_OLE: case CmpInst::ICMP_ULE: case CmpInst::ICMP_SGT: case CmpInst::ICMP_SGE: @@ -595,6 +628,11 @@ bool IRInterpreter::CanInterpret(llvm::Module &module, llvm::Function &function, case Instruction::Xor: case Instruction::ZExt: break; + case Instruction::FAdd: + case Instruction::FSub: + case Instruction::FMul: + case Instruction::FDiv: + break; } for (unsigned oi = 0, oe = ii.getNumOperands(); oi != oe; ++oi) { @@ -709,7 +747,11 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, case Instruction::AShr: case Instruction::And: case Instruction::Or: - case Instruction::Xor: { + case Instruction::Xor: + case Instruction::FAdd: + case Instruction::FSub: + case Instruction::FMul: + case Instruction::FDiv: { const BinaryOperator *bin_op = dyn_cast<BinaryOperator>(inst); if (!bin_op) { @@ -748,12 +790,15 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, default: break; case Instruction::Add: + case Instruction::FAdd: result = L + R; break; case Instruction::Mul: + case Instruction::FMul: result = L * R; break; case Instruction::Sub: + case Instruction::FSub: result = L - R; break; case Instruction::SDiv: @@ -766,6 +811,9 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, R.MakeUnsigned(); result = L / R; break; + case Instruction::FDiv: + result = L / R; + break; case Instruction::SRem: L.MakeSigned(); R.MakeSigned(); @@ -1028,8 +1076,9 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, LLDB_LOGF(log, " Poffset : %s", frame.SummarizeValue(inst).c_str()); } } break; + case Instruction::FCmp: case Instruction::ICmp: { - const ICmpInst *icmp_inst = cast<ICmpInst>(inst); + const CmpInst *icmp_inst = cast<CmpInst>(inst); CmpInst::Predicate predicate = icmp_inst->getPredicate(); @@ -1059,9 +1108,11 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, default: return false; case CmpInst::ICMP_EQ: + case CmpInst::FCMP_OEQ: result = (L == R); break; case CmpInst::ICMP_NE: + case CmpInst::FCMP_UNE: result = (L != R); break; case CmpInst::ICMP_UGT: @@ -1074,16 +1125,28 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, R.MakeUnsigned(); result = (L >= R); break; + case CmpInst::FCMP_OGE: + result = (L >= R); + break; + case CmpInst::FCMP_OGT: + result = (L > R); + break; case CmpInst::ICMP_ULT: L.MakeUnsigned(); R.MakeUnsigned(); result = (L < R); break; + case CmpInst::FCMP_OLT: + result = (L < R); + break; case CmpInst::ICMP_ULE: L.MakeUnsigned(); R.MakeUnsigned(); result = (L <= R); break; + case CmpInst::FCMP_OLE: + result = (L <= R); + break; case CmpInst::ICMP_SGT: L.MakeSigned(); R.MakeSigned(); diff --git a/contrib/llvm-project/lldb/source/Expression/IRMemoryMap.cpp b/contrib/llvm-project/lldb/source/Expression/IRMemoryMap.cpp index 6b8f7babc6f0..3c102dd4eaef 100644 --- a/contrib/llvm-project/lldb/source/Expression/IRMemoryMap.cpp +++ b/contrib/llvm-project/lldb/source/Expression/IRMemoryMap.cpp @@ -143,7 +143,7 @@ lldb::addr_t IRMemoryMap::FindSpace(size_t size) { if (address_byte_size != UINT32_MAX) { switch (address_byte_size) { case 8: - ret = 0xffffffff00000000ull; + ret = 0xdead0fff00000000ull; break; case 4: ret = 0xee000000ull; diff --git a/contrib/llvm-project/lldb/source/Expression/LLVMUserExpression.cpp b/contrib/llvm-project/lldb/source/Expression/LLVMUserExpression.cpp index d67660812150..6d11abbf876f 100644 --- a/contrib/llvm-project/lldb/source/Expression/LLVMUserExpression.cpp +++ b/contrib/llvm-project/lldb/source/Expression/LLVMUserExpression.cpp @@ -48,8 +48,8 @@ LLVMUserExpression::LLVMUserExpression(ExecutionContextScope &exe_scope, m_stack_frame_bottom(LLDB_INVALID_ADDRESS), m_stack_frame_top(LLDB_INVALID_ADDRESS), m_allow_cxx(false), m_allow_objc(false), m_transformed_text(), m_execution_unit_sp(), - m_materializer_up(), m_jit_module_wp(), m_can_interpret(false), - m_materialized_address(LLDB_INVALID_ADDRESS) {} + m_materializer_up(), m_jit_module_wp(), m_target(nullptr), + m_can_interpret(false), m_materialized_address(LLDB_INVALID_ADDRESS) {} LLVMUserExpression::~LLVMUserExpression() { if (m_target) { diff --git a/contrib/llvm-project/lldb/source/Expression/Materializer.cpp b/contrib/llvm-project/lldb/source/Expression/Materializer.cpp index 946ae10d69c2..0932dc6f95b1 100644 --- a/contrib/llvm-project/lldb/source/Expression/Materializer.cpp +++ b/contrib/llvm-project/lldb/source/Expression/Materializer.cpp @@ -25,6 +25,7 @@ #include "lldb/lldb-forward.h" #include <memory> +#include <optional> using namespace lldb_private; @@ -543,7 +544,7 @@ public: return; } - llvm::Optional<size_t> opt_bit_align = GetTypeBitAlign(scope); + std::optional<size_t> opt_bit_align = GetTypeBitAlign(scope); if (!opt_bit_align) { err.SetErrorStringWithFormat("can't get the type alignment for %s", GetName().AsCString()); @@ -773,8 +774,8 @@ private: /// Returns size in bytes of the type associated with this variable /// /// \returns On success, returns byte size of the type associated - /// with this variable. Returns NoneType otherwise. - virtual llvm::Optional<uint64_t> + /// with this variable. Returns std::nullopt otherwise. + virtual std::optional<uint64_t> GetByteSize(ExecutionContextScope *scope) const = 0; /// Returns 'true' if the location expression associated with this variable @@ -784,8 +785,8 @@ private: /// Returns alignment of the type associated with this variable in bits. /// /// \returns On success, returns alignment in bits for the type associated - /// with this variable. Returns NoneType otherwise. - virtual llvm::Optional<size_t> + /// with this variable. Returns std::nullopt otherwise. + virtual std::optional<size_t> GetTypeBitAlign(ExecutionContextScope *scope) const = 0; protected: @@ -815,7 +816,7 @@ public: return ValueObjectVariable::Create(scope, m_variable_sp); } - llvm::Optional<uint64_t> + std::optional<uint64_t> GetByteSize(ExecutionContextScope *scope) const override { return m_variable_sp->GetType()->GetByteSize(scope); } @@ -824,7 +825,7 @@ public: return m_variable_sp->LocationExpressionList().IsValid(); } - llvm::Optional<size_t> + std::optional<size_t> GetTypeBitAlign(ExecutionContextScope *scope) const override { return m_variable_sp->GetType()->GetLayoutCompilerType().GetTypeBitAlign( scope); @@ -858,7 +859,7 @@ public: return m_valobj_sp; } - llvm::Optional<uint64_t> + std::optional<uint64_t> GetByteSize(ExecutionContextScope *scope) const override { if (m_valobj_sp) return m_valobj_sp->GetCompilerType().GetByteSize(scope); @@ -873,7 +874,7 @@ public: return false; } - llvm::Optional<size_t> + std::optional<size_t> GetTypeBitAlign(ExecutionContextScope *scope) const override { if (m_valobj_sp) return m_valobj_sp->GetCompilerType().GetTypeBitAlign(scope); @@ -934,14 +935,14 @@ public: if (!exe_scope) exe_scope = map.GetBestExecutionContextScope(); - llvm::Optional<uint64_t> byte_size = m_type.GetByteSize(exe_scope); + std::optional<uint64_t> byte_size = m_type.GetByteSize(exe_scope); if (!byte_size) { err.SetErrorStringWithFormat("can't get size of type \"%s\"", m_type.GetTypeName().AsCString()); return; } - llvm::Optional<size_t> opt_bit_align = m_type.GetTypeBitAlign(exe_scope); + std::optional<size_t> opt_bit_align = m_type.GetTypeBitAlign(exe_scope); if (!opt_bit_align) { err.SetErrorStringWithFormat("can't get the alignment of type \"%s\"", m_type.GetTypeName().AsCString()); @@ -1023,8 +1024,15 @@ public: llvm::toString(std::move(error)).c_str()); return; } + auto ts = *type_system_or_err; + if (!ts) { + err.SetErrorStringWithFormat("Couldn't dematerialize a result variable: " + "couldn't corresponding type system is " + "no longer live."); + return; + } PersistentExpressionState *persistent_state = - type_system_or_err->GetPersistentExpressionState(); + ts->GetPersistentExpressionState(); if (!persistent_state) { err.SetErrorString("Couldn't dematerialize a result variable: " diff --git a/contrib/llvm-project/lldb/source/Expression/REPL.cpp b/contrib/llvm-project/lldb/source/Expression/REPL.cpp index d7582af9b2ea..ae80f9ad97dc 100644 --- a/contrib/llvm-project/lldb/source/Expression/REPL.cpp +++ b/contrib/llvm-project/lldb/source/Expression/REPL.cpp @@ -58,7 +58,7 @@ std::string REPL::GetSourcePath() { ConstString file_basename = GetSourceFileBasename(); FileSpec tmpdir_file_spec = HostInfo::GetProcessTempDir(); if (tmpdir_file_spec) { - tmpdir_file_spec.GetFilename() = file_basename; + tmpdir_file_spec.SetFilename(file_basename); m_repl_source_path = tmpdir_file_spec.GetPath(); } else { tmpdir_file_spec = FileSpec("/tmp"); @@ -79,7 +79,7 @@ lldb::IOHandlerSP REPL::GetIOHandler() { true, // Multi-line true, // The REPL prompt is always colored 1, // Line number - *this, nullptr); + *this); // Don't exit if CTRL+C is pressed static_cast<IOHandlerEditline *>(m_io_handler_sp.get()) @@ -378,7 +378,7 @@ void REPL::IOHandlerInputComplete(IOHandler &io_handler, std::string &code) { case lldb::eExpressionSetupError: case lldb::eExpressionParseError: add_to_code = false; - LLVM_FALLTHROUGH; + [[fallthrough]]; case lldb::eExpressionDiscarded: error_sp->Printf("%s\n", error.AsCString()); break; diff --git a/contrib/llvm-project/lldb/source/Expression/UserExpression.cpp b/contrib/llvm-project/lldb/source/Expression/UserExpression.cpp index 186e414e6879..c1515b0ace81 100644 --- a/contrib/llvm-project/lldb/source/Expression/UserExpression.cpp +++ b/contrib/llvm-project/lldb/source/Expression/UserExpression.cpp @@ -194,16 +194,22 @@ UserExpression::Evaluate(ExecutionContext &exe_ctx, Process *process = exe_ctx.GetProcessPtr(); - if (process == nullptr || process->GetState() != lldb::eStateStopped) { - if (execution_policy == eExecutionPolicyAlways) { - LLDB_LOG(log, "== [UserExpression::Evaluate] Expression may not run, but " - "is not constant =="); + if (process == nullptr && execution_policy == eExecutionPolicyAlways) { + LLDB_LOG(log, "== [UserExpression::Evaluate] No process, but the policy is " + "eExecutionPolicyAlways"); - error.SetErrorString("expression needed to run but couldn't"); + error.SetErrorString("expression needed to run but couldn't: no process"); - return execution_results; - } + return execution_results; } + // Since we might need to call allocate memory and maybe call code to make + // the caller, we need to be stopped. + if (process != nullptr && process->GetState() != lldb::eStateStopped) { + error.SetErrorString("Can't make a function caller while the process is " + "running"); + return execution_results; + } + // Explicitly force the IR interpreter to evaluate the expression when the // there is no process that supports running the expression for us. Don't diff --git a/contrib/llvm-project/lldb/source/Expression/UtilityFunction.cpp b/contrib/llvm-project/lldb/source/Expression/UtilityFunction.cpp index 1a4df9722706..5d55d9a5c2c1 100644 --- a/contrib/llvm-project/lldb/source/Expression/UtilityFunction.cpp +++ b/contrib/llvm-project/lldb/source/Expression/UtilityFunction.cpp @@ -64,6 +64,13 @@ FunctionCaller *UtilityFunction::MakeFunctionCaller( error.SetErrorString("Can't make a function caller without a process."); return nullptr; } + // Since we might need to call allocate memory and maybe call code to make + // the caller, we need to be stopped. + if (process_sp->GetState() != lldb::eStateStopped) { + error.SetErrorString("Can't make a function caller while the process is " + "running"); + return nullptr; + } Address impl_code_address; impl_code_address.SetOffset(StartAddress()); diff --git a/contrib/llvm-project/lldb/source/Host/common/Editline.cpp b/contrib/llvm-project/lldb/source/Host/common/Editline.cpp index ea0f06f63707..544804db3879 100644 --- a/contrib/llvm-project/lldb/source/Host/common/Editline.cpp +++ b/contrib/llvm-project/lldb/source/Host/common/Editline.cpp @@ -8,6 +8,7 @@ #include <climits> #include <iomanip> +#include <optional> #include "lldb/Host/Editline.h" @@ -582,12 +583,12 @@ int Editline::GetCharacter(EditLineGetCharType *c) { // interrupted. m_output_mutex.unlock(); int read_count = - m_input_connection.Read(&ch, 1, llvm::None, status, nullptr); + m_input_connection.Read(&ch, 1, std::nullopt, status, nullptr); m_output_mutex.lock(); if (m_editor_status == EditorStatus::Interrupted) { while (read_count > 0 && status == lldb::eConnectionStatusSuccess) read_count = - m_input_connection.Read(&ch, 1, llvm::None, status, nullptr); + m_input_connection.Read(&ch, 1, std::nullopt, status, nullptr); lldbassert(status == lldb::eConnectionStatusInterrupted); return 0; } @@ -1062,7 +1063,7 @@ unsigned char Editline::ApplyAutosuggestCommand(int ch) { llvm::StringRef line(line_info->buffer, line_info->lastchar - line_info->buffer); - if (llvm::Optional<std::string> to_add = m_suggestion_callback(line)) + if (std::optional<std::string> to_add = m_suggestion_callback(line)) el_insertstr(m_editline, to_add->c_str()); return CC_REDISPLAY; @@ -1085,8 +1086,8 @@ unsigned char Editline::TypedCharacter(int ch) { const char *ansi_suffix = m_color_prompts ? m_suggestion_ansi_suffix.c_str() : ""; - if (llvm::Optional<std::string> to_add = m_suggestion_callback(line)) { - std::string to_add_color = ansi_prefix + to_add.getValue() + ansi_suffix; + if (std::optional<std::string> to_add = m_suggestion_callback(line)) { + std::string to_add_color = ansi_prefix + to_add.value() + ansi_suffix; fputs(typed.c_str(), m_output_file); fputs(to_add_color.c_str(), m_output_file); size_t new_autosuggestion_size = line.size() + to_add->length(); @@ -1609,7 +1610,7 @@ bool Editline::CompleteCharacter(char ch, EditLineGetCharType &out) { switch (cvt.in(state, input.begin(), input.end(), from_next, &out, &out + 1, to_next)) { case std::codecvt_base::ok: - return out != (int)WEOF; + return out != (EditLineGetCharType)WEOF; case std::codecvt_base::error: case std::codecvt_base::noconv: diff --git a/contrib/llvm-project/lldb/source/Host/common/File.cpp b/contrib/llvm-project/lldb/source/Host/common/File.cpp index ce5283a61375..15e7a211e353 100644 --- a/contrib/llvm-project/lldb/source/Host/common/File.cpp +++ b/contrib/llvm-project/lldb/source/Host/common/File.cpp @@ -13,6 +13,7 @@ #include <cstdarg> #include <cstdio> #include <fcntl.h> +#include <optional> #ifdef _WIN32 #include "lldb/Host/windows/windows.h" @@ -777,13 +778,13 @@ SerialPort::OptionsFromURL(llvm::StringRef urlqs) { serial_options.BaudRate = baud_rate; } else if (x.consume_front("parity=")) { serial_options.Parity = - llvm::StringSwitch<llvm::Optional<Terminal::Parity>>(x) + llvm::StringSwitch<std::optional<Terminal::Parity>>(x) .Case("no", Terminal::Parity::No) .Case("even", Terminal::Parity::Even) .Case("odd", Terminal::Parity::Odd) .Case("mark", Terminal::Parity::Mark) .Case("space", Terminal::Parity::Space) - .Default(llvm::None); + .Default(std::nullopt); if (!serial_options.Parity) return llvm::createStringError( llvm::inconvertibleErrorCode(), @@ -791,14 +792,14 @@ SerialPort::OptionsFromURL(llvm::StringRef urlqs) { x.str().c_str()); } else if (x.consume_front("parity-check=")) { serial_options.ParityCheck = - llvm::StringSwitch<llvm::Optional<Terminal::ParityCheck>>(x) + llvm::StringSwitch<std::optional<Terminal::ParityCheck>>(x) .Case("no", Terminal::ParityCheck::No) .Case("replace", Terminal::ParityCheck::ReplaceWithNUL) .Case("ignore", Terminal::ParityCheck::Ignore) // "mark" mode is not currently supported as it requires special // input processing // .Case("mark", Terminal::ParityCheck::Mark) - .Default(llvm::None); + .Default(std::nullopt); if (!serial_options.ParityCheck) return llvm::createStringError( llvm::inconvertibleErrorCode(), @@ -833,20 +834,19 @@ SerialPort::Create(int fd, OpenOptions options, Options serial_options, if (llvm::Error error = term.SetRaw()) return std::move(error); if (serial_options.BaudRate) { - if (llvm::Error error = term.SetBaudRate(serial_options.BaudRate.value())) + if (llvm::Error error = term.SetBaudRate(*serial_options.BaudRate)) return std::move(error); } if (serial_options.Parity) { - if (llvm::Error error = term.SetParity(serial_options.Parity.value())) + if (llvm::Error error = term.SetParity(*serial_options.Parity)) return std::move(error); } if (serial_options.ParityCheck) { - if (llvm::Error error = - term.SetParityCheck(serial_options.ParityCheck.value())) + if (llvm::Error error = term.SetParityCheck(*serial_options.ParityCheck)) return std::move(error); } if (serial_options.StopBits) { - if (llvm::Error error = term.SetStopBits(serial_options.StopBits.value())) + if (llvm::Error error = term.SetStopBits(*serial_options.StopBits)) return std::move(error); } diff --git a/contrib/llvm-project/lldb/source/Host/common/FileAction.cpp b/contrib/llvm-project/lldb/source/Host/common/FileAction.cpp index e399c7ec47cd..f980d3224640 100644 --- a/contrib/llvm-project/lldb/source/Host/common/FileAction.cpp +++ b/contrib/llvm-project/lldb/source/Host/common/FileAction.cpp @@ -25,7 +25,9 @@ void FileAction::Clear() { m_file_spec.Clear(); } -llvm::StringRef FileAction::GetPath() const { return m_file_spec.GetCString(); } +llvm::StringRef FileAction::GetPath() const { + return m_file_spec.GetPathAsConstString().AsCString(); +} const FileSpec &FileAction::GetFileSpec() const { return m_file_spec; } @@ -81,7 +83,7 @@ void FileAction::Dump(Stream &stream) const { break; case eFileActionOpen: stream.Printf("open fd %d with '%s', OFLAGS = 0x%x", m_fd, - m_file_spec.GetCString(), m_arg); + m_file_spec.GetPath().c_str(), m_arg); break; } } diff --git a/contrib/llvm-project/lldb/source/Host/common/FileSystem.cpp b/contrib/llvm-project/lldb/source/Host/common/FileSystem.cpp index 501062f99a53..96ff1bf13bd7 100644 --- a/contrib/llvm-project/lldb/source/Host/common/FileSystem.cpp +++ b/contrib/llvm-project/lldb/source/Host/common/FileSystem.cpp @@ -37,6 +37,7 @@ #include <algorithm> #include <fstream> +#include <optional> #include <vector> using namespace lldb; @@ -60,8 +61,8 @@ void FileSystem::Terminate() { InstanceImpl().reset(); } -Optional<FileSystem> &FileSystem::InstanceImpl() { - static Optional<FileSystem> g_fs; +std::optional<FileSystem> &FileSystem::InstanceImpl() { + static std::optional<FileSystem> g_fs; return g_fs; } @@ -267,7 +268,7 @@ void FileSystem::Resolve(FileSpec &file_spec) { // Update the FileSpec with the resolved path. if (file_spec.GetFilename().IsEmpty()) - file_spec.GetDirectory().SetString(path); + file_spec.SetDirectory(path); else file_spec.SetPath(path); file_spec.SetIsResolved(true); diff --git a/contrib/llvm-project/lldb/source/Host/common/Host.cpp b/contrib/llvm-project/lldb/source/Host/common/Host.cpp index 4a0f0240bd19..33b550008b74 100644 --- a/contrib/llvm-project/lldb/source/Host/common/Host.cpp +++ b/contrib/llvm-project/lldb/source/Host/common/Host.cpp @@ -60,11 +60,9 @@ #include "lldb/Utility/LLDBLog.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/Predicate.h" -#include "lldb/Utility/ReproducerProvider.h" #include "lldb/Utility/Status.h" #include "lldb/lldb-private-forward.h" #include "llvm/ADT/SmallString.h" -#include "llvm/ADT/StringSwitch.h" #include "llvm/Support/Errno.h" #include "llvm/Support/FileSystem.h" @@ -614,22 +612,7 @@ void llvm::format_provider<WaitStatus>::format(const WaitStatus &WS, uint32_t Host::FindProcesses(const ProcessInstanceInfoMatch &match_info, ProcessInstanceInfoList &process_infos) { - - if (llvm::Optional<ProcessInstanceInfoList> infos = - repro::GetReplayProcessInstanceInfoList()) { - process_infos = *infos; - return process_infos.size(); - } - - uint32_t result = FindProcessesImpl(match_info, process_infos); - - if (repro::Generator *g = repro::Reproducer::Instance().GetGenerator()) { - g->GetOrCreate<repro::ProcessInfoProvider>() - .GetNewProcessInfoRecorder() - ->Record(process_infos); - } - - return result; + return FindProcessesImpl(match_info, process_infos); } char SystemLogHandler::ID; diff --git a/contrib/llvm-project/lldb/source/Host/common/HostInfoBase.cpp b/contrib/llvm-project/lldb/source/Host/common/HostInfoBase.cpp index 22c0403006e9..d5e5628e5559 100644 --- a/contrib/llvm-project/lldb/source/Host/common/HostInfoBase.cpp +++ b/contrib/llvm-project/lldb/source/Host/common/HostInfoBase.cpp @@ -26,6 +26,7 @@ #include "llvm/Support/raw_ostream.h" #include <mutex> +#include <optional> #include <thread> using namespace lldb; @@ -107,13 +108,13 @@ const ArchSpec &HostInfoBase::GetArchitecture(ArchitectureKind arch_kind) { : g_fields->m_host_arch_32; } -llvm::Optional<HostInfoBase::ArchitectureKind> +std::optional<HostInfoBase::ArchitectureKind> HostInfoBase::ParseArchitectureKind(llvm::StringRef kind) { - return llvm::StringSwitch<llvm::Optional<ArchitectureKind>>(kind) + return llvm::StringSwitch<std::optional<ArchitectureKind>>(kind) .Case(LLDB_ARCH_DEFAULT, eArchKindDefault) .Case(LLDB_ARCH_DEFAULT_32BIT, eArchKind32) .Case(LLDB_ARCH_DEFAULT_64BIT, eArchKind64) - .Default(llvm::None); + .Default(std::nullopt); } FileSpec HostInfoBase::GetShlibDir() { @@ -242,7 +243,7 @@ bool HostInfoBase::ComputePathRelativeToLibrary(FileSpec &file_spec, raw_path = (parent_path + dir).str(); LLDB_LOGF(log, "HostInfo::%s() derived the path as: %s", __FUNCTION__, raw_path.c_str()); - file_spec.GetDirectory().SetString(raw_path); + file_spec.SetDirectory(raw_path); return (bool)file_spec.GetDirectory(); } @@ -258,7 +259,7 @@ bool HostInfoBase::ComputeSharedLibraryDirectory(FileSpec &file_spec) { g_shlib_dir_helper(lldb_file_spec); // Remove the filename so that this FileSpec only represents the directory. - file_spec.GetDirectory() = lldb_file_spec.GetDirectory(); + file_spec.SetDirectory(lldb_file_spec.GetDirectory()); return (bool)file_spec.GetDirectory(); } @@ -278,7 +279,7 @@ bool HostInfoBase::ComputeProcessTempFileDirectory(FileSpec &file_spec) { if (llvm::sys::fs::create_directory(temp_file_spec.GetPath())) return false; - file_spec.GetDirectory().SetCString(temp_file_spec.GetCString()); + file_spec.SetDirectory(temp_file_spec.GetPathAsConstString()); return true; } @@ -301,7 +302,7 @@ bool HostInfoBase::ComputeGlobalTempFileDirectory(FileSpec &file_spec) { if (llvm::sys::fs::create_directory(temp_file_spec.GetPath())) return false; - file_spec.GetDirectory().SetCString(temp_file_spec.GetCString()); + file_spec.SetDirectory(temp_file_spec.GetPathAsConstString()); return true; } @@ -339,6 +340,8 @@ void HostInfoBase::ComputeHostArchitectureSupport(ArchSpec &arch_32, case llvm::Triple::ppc64: case llvm::Triple::ppc64le: case llvm::Triple::x86_64: + case llvm::Triple::riscv64: + case llvm::Triple::loongarch64: arch_64.SetTriple(triple); arch_32.SetTriple(triple.get32BitArchVariant()); break; diff --git a/contrib/llvm-project/lldb/source/Host/common/MainLoopBase.cpp b/contrib/llvm-project/lldb/source/Host/common/MainLoopBase.cpp new file mode 100644 index 000000000000..030a4f037168 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Host/common/MainLoopBase.cpp @@ -0,0 +1,33 @@ +//===-- MainLoopBase.cpp --------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lldb/Host/MainLoopBase.h" + +using namespace lldb; +using namespace lldb_private; + +void MainLoopBase::AddPendingCallback(const Callback &callback) { + { + std::lock_guard<std::mutex> lock{m_callback_mutex}; + m_pending_callbacks.push_back(callback); + } + TriggerPendingCallbacks(); +} + +void MainLoopBase::ProcessPendingCallbacks() { + // Move the callbacks to a local vector to avoid keeping m_pending_callbacks + // locked throughout the calls. + std::vector<Callback> pending_callbacks; + { + std::lock_guard<std::mutex> lock{m_callback_mutex}; + pending_callbacks = std::move(m_pending_callbacks); + } + + for (const Callback &callback : pending_callbacks) + callback(*this); +} diff --git a/contrib/llvm-project/lldb/source/Host/common/NativeProcessProtocol.cpp b/contrib/llvm-project/lldb/source/Host/common/NativeProcessProtocol.cpp index be521a31cb37..975b3d0f7d53 100644 --- a/contrib/llvm-project/lldb/source/Host/common/NativeProcessProtocol.cpp +++ b/contrib/llvm-project/lldb/source/Host/common/NativeProcessProtocol.cpp @@ -18,6 +18,7 @@ #include "lldb/lldb-enumerations.h" #include "llvm/Support/Process.h" +#include <optional> using namespace lldb; using namespace lldb_private; @@ -66,11 +67,11 @@ NativeProcessProtocol::WriteMemoryTags(int32_t type, lldb::addr_t addr, return Status("not implemented"); } -llvm::Optional<WaitStatus> NativeProcessProtocol::GetExitStatus() { +std::optional<WaitStatus> NativeProcessProtocol::GetExitStatus() { if (m_state == lldb::eStateExited) return m_exit_status; - return llvm::None; + return std::nullopt; } bool NativeProcessProtocol::SetExitStatus(WaitStatus status, @@ -127,7 +128,7 @@ NativeProcessProtocol::GetWatchpointMap() const { return m_watchpoint_list.GetWatchpointMap(); } -llvm::Optional<std::pair<uint32_t, uint32_t>> +std::optional<std::pair<uint32_t, uint32_t>> NativeProcessProtocol::GetHardwareDebugSupportInfo() const { Log *log = GetLog(LLDBLog::Process); @@ -136,7 +137,7 @@ NativeProcessProtocol::GetHardwareDebugSupportInfo() const { const_cast<NativeProcessProtocol *>(this)->GetThreadAtIndex(0)); if (!thread) { LLDB_LOG(log, "failed to find a thread to grab a NativeRegisterContext!"); - return llvm::None; + return std::nullopt; } NativeRegisterContext ®_ctx = thread->GetRegisterContext(); @@ -245,7 +246,7 @@ Status NativeProcessProtocol::SetHardwareBreakpoint(lldb::addr_t addr, // Exit here if target does not have required hardware breakpoint capability. auto hw_debug_cap = GetHardwareDebugSupportInfo(); - if (hw_debug_cap == llvm::None || hw_debug_cap->first == 0 || + if (hw_debug_cap == std::nullopt || hw_debug_cap->first == 0 || hw_debug_cap->first <= m_hw_breakpoints_map.size()) return Status("Target does not have required no of hardware breakpoints"); @@ -382,7 +383,7 @@ Status NativeProcessProtocol::RemoveSoftwareBreakpoint(lldb::addr_t addr) { } const auto &saved = it->second.saved_opcodes; // Make sure the breakpoint opcode exists at this address - if (makeArrayRef(curr_break_op) != it->second.breakpoint_opcodes) { + if (llvm::ArrayRef(curr_break_op) != it->second.breakpoint_opcodes) { if (curr_break_op != it->second.saved_opcodes) return Status("Original breakpoint trap is no longer in memory."); LLDB_LOG(log, @@ -482,7 +483,7 @@ NativeProcessProtocol::EnableSoftwareBreakpoint(lldb::addr_t addr, verify_bp_opcode_bytes.size(), verify_bytes_read); } - if (llvm::makeArrayRef(verify_bp_opcode_bytes.data(), verify_bytes_read) != + if (llvm::ArrayRef(verify_bp_opcode_bytes.data(), verify_bytes_read) != *expected_trap) { return llvm::createStringError( llvm::inconvertibleErrorCode(), @@ -503,35 +504,49 @@ NativeProcessProtocol::GetSoftwareBreakpointTrapOpcode(size_t size_hint) { static const uint8_t g_mips64_opcode[] = {0x00, 0x00, 0x00, 0x0d}; static const uint8_t g_mips64el_opcode[] = {0x0d, 0x00, 0x00, 0x00}; static const uint8_t g_s390x_opcode[] = {0x00, 0x01}; - static const uint8_t g_ppc_opcode[] = {0x7f, 0xe0, 0x00, 0x08}; // trap + static const uint8_t g_ppc_opcode[] = {0x7f, 0xe0, 0x00, 0x08}; // trap static const uint8_t g_ppcle_opcode[] = {0x08, 0x00, 0xe0, 0x7f}; // trap + static const uint8_t g_riscv_opcode[] = {0x73, 0x00, 0x10, 0x00}; // ebreak + static const uint8_t g_riscv_opcode_c[] = {0x02, 0x90}; // c.ebreak + static const uint8_t g_loongarch_opcode[] = {0x05, 0x00, 0x2a, + 0x00}; // break 0x5 switch (GetArchitecture().GetMachine()) { case llvm::Triple::aarch64: case llvm::Triple::aarch64_32: - return llvm::makeArrayRef(g_aarch64_opcode); + return llvm::ArrayRef(g_aarch64_opcode); case llvm::Triple::x86: case llvm::Triple::x86_64: - return llvm::makeArrayRef(g_i386_opcode); + return llvm::ArrayRef(g_i386_opcode); case llvm::Triple::mips: case llvm::Triple::mips64: - return llvm::makeArrayRef(g_mips64_opcode); + return llvm::ArrayRef(g_mips64_opcode); case llvm::Triple::mipsel: case llvm::Triple::mips64el: - return llvm::makeArrayRef(g_mips64el_opcode); + return llvm::ArrayRef(g_mips64el_opcode); case llvm::Triple::systemz: - return llvm::makeArrayRef(g_s390x_opcode); + return llvm::ArrayRef(g_s390x_opcode); case llvm::Triple::ppc: case llvm::Triple::ppc64: - return llvm::makeArrayRef(g_ppc_opcode); + return llvm::ArrayRef(g_ppc_opcode); case llvm::Triple::ppc64le: - return llvm::makeArrayRef(g_ppcle_opcode); + return llvm::ArrayRef(g_ppcle_opcode); + + case llvm::Triple::riscv32: + case llvm::Triple::riscv64: { + return size_hint == 2 ? llvm::ArrayRef(g_riscv_opcode_c) + : llvm::ArrayRef(g_riscv_opcode); + } + + case llvm::Triple::loongarch32: + case llvm::Triple::loongarch64: + return llvm::ArrayRef(g_loongarch_opcode); default: return llvm::createStringError(llvm::inconvertibleErrorCode(), @@ -557,6 +572,10 @@ size_t NativeProcessProtocol::GetSoftwareBreakpointPCOffset() { case llvm::Triple::ppc: case llvm::Triple::ppc64: case llvm::Triple::ppc64le: + case llvm::Triple::riscv32: + case llvm::Triple::riscv64: + case llvm::Triple::loongarch32: + case llvm::Triple::loongarch64: // On these architectures the PC doesn't get updated for breakpoint hits. return 0; @@ -630,11 +649,10 @@ Status NativeProcessProtocol::ReadMemoryWithoutTrap(lldb::addr_t addr, if (error.Fail()) return error; - auto data = - llvm::makeMutableArrayRef(static_cast<uint8_t *>(buf), bytes_read); + llvm::MutableArrayRef data(static_cast<uint8_t *>(buf), bytes_read); for (const auto &pair : m_software_breakpoints) { lldb::addr_t bp_addr = pair.first; - auto saved_opcodes = makeArrayRef(pair.second.saved_opcodes); + auto saved_opcodes = llvm::ArrayRef(pair.second.saved_opcodes); if (bp_addr + saved_opcodes.size() < addr || addr + bytes_read <= bp_addr) continue; // Breakpoint not in range, ignore diff --git a/contrib/llvm-project/lldb/source/Host/common/NativeRegisterContext.cpp b/contrib/llvm-project/lldb/source/Host/common/NativeRegisterContext.cpp index 7e4ffe8dfa18..1be519d129ee 100644 --- a/contrib/llvm-project/lldb/source/Host/common/NativeRegisterContext.cpp +++ b/contrib/llvm-project/lldb/source/Host/common/NativeRegisterContext.cpp @@ -376,7 +376,7 @@ Status NativeRegisterContext::ReadRegisterValueFromMemory( // TODO: we might need to add a parameter to this function in case the byte // order of the memory data doesn't match the process. For now we are // assuming they are the same. - reg_value.SetFromMemoryData(reg_info, src, src_len, process.GetByteOrder(), + reg_value.SetFromMemoryData(*reg_info, src, src_len, process.GetByteOrder(), error); return error; @@ -385,18 +385,20 @@ Status NativeRegisterContext::ReadRegisterValueFromMemory( Status NativeRegisterContext::WriteRegisterValueToMemory( const RegisterInfo *reg_info, lldb::addr_t dst_addr, size_t dst_len, const RegisterValue ®_value) { - - uint8_t dst[RegisterValue::kMaxRegisterByteSize]; - Status error; + if (reg_info == nullptr) { + error.SetErrorString("Invalid register info argument."); + return error; + } + uint8_t dst[RegisterValue::kMaxRegisterByteSize]; NativeProcessProtocol &process = m_thread.GetProcess(); // TODO: we might need to add a parameter to this function in case the byte // order of the memory data doesn't match the process. For now we are // assuming they are the same. const size_t bytes_copied = reg_value.GetAsMemoryData( - reg_info, dst, dst_len, process.GetByteOrder(), error); + *reg_info, dst, dst_len, process.GetByteOrder(), error); if (error.Success()) { if (bytes_copied == 0) { diff --git a/contrib/llvm-project/lldb/source/Host/common/ProcessRunLock.cpp b/contrib/llvm-project/lldb/source/Host/common/ProcessRunLock.cpp index aee15779d919..da59f4057697 100644 --- a/contrib/llvm-project/lldb/source/Host/common/ProcessRunLock.cpp +++ b/contrib/llvm-project/lldb/source/Host/common/ProcessRunLock.cpp @@ -24,6 +24,7 @@ ProcessRunLock::~ProcessRunLock() { bool ProcessRunLock::ReadTryLock() { ::pthread_rwlock_rdlock(&m_rwlock); if (!m_running) { + // coverity[missing_unlock] return true; } ::pthread_rwlock_unlock(&m_rwlock); diff --git a/contrib/llvm-project/lldb/source/Host/common/TCPSocket.cpp b/contrib/llvm-project/lldb/source/Host/common/TCPSocket.cpp index eabc9fef8a66..82b00ac561f9 100644 --- a/contrib/llvm-project/lldb/source/Host/common/TCPSocket.cpp +++ b/contrib/llvm-project/lldb/source/Host/common/TCPSocket.cpp @@ -167,14 +167,17 @@ Status TCPSocket::Connect(llvm::StringRef name) { address.SetPort(host_port->port); - if (-1 == llvm::sys::RetryAfterSignal(-1, ::connect, GetNativeSocket(), - &address.sockaddr(), - address.GetLength())) { + if (llvm::sys::RetryAfterSignal(-1, ::connect, GetNativeSocket(), + &address.sockaddr(), + address.GetLength()) == -1) { Close(); continue; } - SetOptionNoDelay(); + if (SetOptionNoDelay() == -1) { + Close(); + continue; + } error.Clear(); return error; @@ -200,15 +203,18 @@ Status TCPSocket::Listen(llvm::StringRef name, int backlog) { for (SocketAddress &address : addresses) { int fd = Socket::CreateSocket(address.GetFamily(), kType, IPPROTO_TCP, m_child_processes_inherit, error); - if (error.Fail()) + if (error.Fail() || fd < 0) continue; // enable local address reuse int option_value = 1; set_socket_option_arg_type option_value_p = reinterpret_cast<set_socket_option_arg_type>(&option_value); - ::setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, option_value_p, - sizeof(option_value)); + if (::setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, option_value_p, + sizeof(option_value)) == -1) { + CLOSE_SOCKET(fd); + continue; + } SocketAddress listen_address = address; if(!listen_address.IsLocalhost()) @@ -218,10 +224,10 @@ Status TCPSocket::Listen(llvm::StringRef name, int backlog) { int err = ::bind(fd, &listen_address.sockaddr(), listen_address.GetLength()); - if (-1 != err) + if (err != -1) err = ::listen(fd, backlog); - if (-1 == err) { + if (err == -1) { error = GetLastSocketError(); CLOSE_SOCKET(fd); continue; @@ -255,8 +261,8 @@ Status TCPSocket::Accept(Socket *&conn_socket) { return error; } - int sock = -1; - int listen_sock = -1; + NativeSocket sock = kInvalidSocketValue; + NativeSocket listen_sock = kInvalidSocketValue; lldb_private::SocketAddress AcceptAddr; MainLoop accept_loop; std::vector<MainLoopBase::ReadHandleUP> handles; @@ -288,7 +294,10 @@ Status TCPSocket::Accept(Socket *&conn_socket) { lldb_private::SocketAddress &AddrIn = m_listen_sockets[listen_sock]; if (!AddrIn.IsAnyAddr() && AcceptAddr != AddrIn) { - CLOSE_SOCKET(sock); + if (sock != kInvalidSocketValue) { + CLOSE_SOCKET(sock); + sock = kInvalidSocketValue; + } llvm::errs() << llvm::formatv( "error: rejecting incoming connection from {0} (expecting {1})", AcceptAddr.GetIPAddress(), AddrIn.GetIPAddress()); diff --git a/contrib/llvm-project/lldb/source/Host/common/Terminal.cpp b/contrib/llvm-project/lldb/source/Host/common/Terminal.cpp index 5da5ee8f1468..436dfd8130d9 100644 --- a/contrib/llvm-project/lldb/source/Host/common/Terminal.cpp +++ b/contrib/llvm-project/lldb/source/Host/common/Terminal.cpp @@ -14,6 +14,7 @@ #include <csignal> #include <fcntl.h> +#include <optional> #if LLDB_ENABLE_TERMIOS #include <termios.h> @@ -125,7 +126,7 @@ llvm::Error Terminal::SetRaw() { } #if LLDB_ENABLE_TERMIOS -static llvm::Optional<speed_t> baudRateToConst(unsigned int baud_rate) { +static std::optional<speed_t> baudRateToConst(unsigned int baud_rate) { switch (baud_rate) { #if defined(B50) case 50: @@ -264,7 +265,7 @@ static llvm::Optional<speed_t> baudRateToConst(unsigned int baud_rate) { return B4000000; #endif default: - return llvm::None; + return std::nullopt; } } #endif @@ -276,16 +277,16 @@ llvm::Error Terminal::SetBaudRate(unsigned int baud_rate) { return data.takeError(); struct termios &fd_termios = data->m_termios; - llvm::Optional<speed_t> val = baudRateToConst(baud_rate); + std::optional<speed_t> val = baudRateToConst(baud_rate); if (!val) // invalid value return llvm::createStringError(llvm::inconvertibleErrorCode(), "baud rate %d unsupported by the platform", baud_rate); - if (::cfsetispeed(&fd_termios, val.value()) != 0) + if (::cfsetispeed(&fd_termios, *val) != 0) return llvm::createStringError( std::error_code(errno, std::generic_category()), "setting input baud rate failed"); - if (::cfsetospeed(&fd_termios, val.value()) != 0) + if (::cfsetospeed(&fd_termios, *val) != 0) return llvm::createStringError( std::error_code(errno, std::generic_category()), "setting output baud rate failed"); diff --git a/contrib/llvm-project/lldb/source/Host/freebsd/HostInfoFreeBSD.cpp b/contrib/llvm-project/lldb/source/Host/freebsd/HostInfoFreeBSD.cpp index f9ff45666c1e..9832a3f07849 100644 --- a/contrib/llvm-project/lldb/source/Host/freebsd/HostInfoFreeBSD.cpp +++ b/contrib/llvm-project/lldb/source/Host/freebsd/HostInfoFreeBSD.cpp @@ -10,6 +10,7 @@ #include "llvm/Support/FormatVariadic.h" #include <cstdio> #include <cstring> +#include <optional> #include <sys/sysctl.h> #include <sys/types.h> #include <sys/utsname.h> @@ -30,7 +31,7 @@ llvm::VersionTuple HostInfoFreeBSD::GetOSVersion() { return llvm::VersionTuple(); } -llvm::Optional<std::string> HostInfoFreeBSD::GetOSBuildString() { +std::optional<std::string> HostInfoFreeBSD::GetOSBuildString() { int mib[2] = {CTL_KERN, KERN_OSREV}; uint32_t osrev = 0; size_t osrev_len = sizeof(osrev); @@ -38,7 +39,7 @@ llvm::Optional<std::string> HostInfoFreeBSD::GetOSBuildString() { if (::sysctl(mib, 2, &osrev, &osrev_len, NULL, 0) == 0) return llvm::formatv("{0,8:8}", osrev).str(); - return llvm::None; + return std::nullopt; } FileSpec HostInfoFreeBSD::GetProgramFileSpec() { diff --git a/contrib/llvm-project/lldb/source/Host/netbsd/HostInfoNetBSD.cpp b/contrib/llvm-project/lldb/source/Host/netbsd/HostInfoNetBSD.cpp index 234dd3d5e103..0de4f2530bba 100644 --- a/contrib/llvm-project/lldb/source/Host/netbsd/HostInfoNetBSD.cpp +++ b/contrib/llvm-project/lldb/source/Host/netbsd/HostInfoNetBSD.cpp @@ -12,6 +12,7 @@ #include <climits> #include <cstdio> #include <cstring> +#include <optional> #include <pthread.h> #include <sys/sysctl.h> #include <sys/types.h> @@ -42,7 +43,7 @@ llvm::VersionTuple HostInfoNetBSD::GetOSVersion() { return llvm::VersionTuple(); } -llvm::Optional<std::string> HostInfoNetBSD::GetOSBuildString() { +std::optional<std::string> HostInfoNetBSD::GetOSBuildString() { int mib[2] = {CTL_KERN, KERN_OSREV}; char osrev_str[12]; int osrev = 0; @@ -51,7 +52,7 @@ llvm::Optional<std::string> HostInfoNetBSD::GetOSBuildString() { if (::sysctl(mib, 2, &osrev, &osrev_len, NULL, 0) == 0) return llvm::formatv("{0,10:10}", osrev).str(); - return llvm::None; + return std::nullopt; } FileSpec HostInfoNetBSD::GetProgramFileSpec() { diff --git a/contrib/llvm-project/lldb/source/Host/openbsd/HostInfoOpenBSD.cpp b/contrib/llvm-project/lldb/source/Host/openbsd/HostInfoOpenBSD.cpp index 5db843ff628d..43f22be51ef9 100644 --- a/contrib/llvm-project/lldb/source/Host/openbsd/HostInfoOpenBSD.cpp +++ b/contrib/llvm-project/lldb/source/Host/openbsd/HostInfoOpenBSD.cpp @@ -10,6 +10,7 @@ #include <cstdio> #include <cstring> +#include <optional> #include <sys/sysctl.h> #include <sys/types.h> #include <sys/utsname.h> @@ -29,7 +30,7 @@ llvm::VersionTuple HostInfoOpenBSD::GetOSVersion() { return llvm::VersionTuple(); } -llvm::Optional<std::string> HostInfoOpenBSD::GetOSBuildString() { +std::optional<std::string> HostInfoOpenBSD::GetOSBuildString() { int mib[2] = {CTL_KERN, KERN_OSREV}; char osrev_str[12]; uint32_t osrev = 0; @@ -38,7 +39,7 @@ llvm::Optional<std::string> HostInfoOpenBSD::GetOSBuildString() { if (::sysctl(mib, 2, &osrev, &osrev_len, NULL, 0) == 0) return llvm::formatv("{0,8:8}", osrev).str(); - return llvm::None; + return std::nullopt; } FileSpec HostInfoOpenBSD::GetProgramFileSpec() { diff --git a/contrib/llvm-project/lldb/source/Host/posix/FileSystemPosix.cpp b/contrib/llvm-project/lldb/source/Host/posix/FileSystemPosix.cpp index 3660f67895a4..26a266e86382 100644 --- a/contrib/llvm-project/lldb/source/Host/posix/FileSystemPosix.cpp +++ b/contrib/llvm-project/lldb/source/Host/posix/FileSystemPosix.cpp @@ -35,7 +35,7 @@ const char *FileSystem::DEV_NULL = "/dev/null"; Status FileSystem::Symlink(const FileSpec &src, const FileSpec &dst) { Status error; - if (::symlink(dst.GetCString(), src.GetCString()) == -1) + if (::symlink(dst.GetPath().c_str(), src.GetPath().c_str()) == -1) error.SetErrorToErrno(); return error; } @@ -56,7 +56,8 @@ Status FileSystem::Readlink(const FileSpec &src, FileSpec &dst) { Status FileSystem::ResolveSymbolicLink(const FileSpec &src, FileSpec &dst) { char resolved_path[PATH_MAX]; if (!src.GetPath(resolved_path, sizeof(resolved_path))) { - return Status("Couldn't get the canonical path for %s", src.GetCString()); + return Status("Couldn't get the canonical path for %s", + src.GetPath().c_str()); } char real_path[PATH_MAX + 1]; diff --git a/contrib/llvm-project/lldb/source/Host/posix/HostInfoPosix.cpp b/contrib/llvm-project/lldb/source/Host/posix/HostInfoPosix.cpp index 63553590dff5..731a7dee2e62 100644 --- a/contrib/llvm-project/lldb/source/Host/posix/HostInfoPosix.cpp +++ b/contrib/llvm-project/lldb/source/Host/posix/HostInfoPosix.cpp @@ -19,6 +19,7 @@ #include <cstdlib> #include <grp.h> #include <mutex> +#include <optional> #include <pwd.h> #include <sys/types.h> #include <sys/utsname.h> @@ -38,10 +39,10 @@ bool HostInfoPosix::GetHostname(std::string &s) { return false; } -llvm::Optional<std::string> HostInfoPosix::GetOSKernelDescription() { +std::optional<std::string> HostInfoPosix::GetOSKernelDescription() { struct utsname un; if (uname(&un) < 0) - return llvm::None; + return std::nullopt; return std::string(un.version); } @@ -56,8 +57,8 @@ llvm::Optional<std::string> HostInfoPosix::GetOSKernelDescription() { namespace { class PosixUserIDResolver : public UserIDResolver { protected: - llvm::Optional<std::string> DoGetUserName(id_t uid) override; - llvm::Optional<std::string> DoGetGroupName(id_t gid) override; + std::optional<std::string> DoGetUserName(id_t uid) override; + std::optional<std::string> DoGetGroupName(id_t gid) override; }; } // namespace @@ -66,7 +67,7 @@ struct PasswdEntry { std::string shell; }; -static llvm::Optional<PasswdEntry> GetPassword(id_t uid) { +static std::optional<PasswdEntry> GetPassword(id_t uid) { #ifdef USE_GETPWUID // getpwuid_r is missing from android-9 // The caller should provide some thread safety by making sure no one calls @@ -85,16 +86,16 @@ static llvm::Optional<PasswdEntry> GetPassword(id_t uid) { return PasswdEntry{user_info_ptr->pw_name, user_info_ptr->pw_shell}; } #endif - return llvm::None; + return std::nullopt; } -llvm::Optional<std::string> PosixUserIDResolver::DoGetUserName(id_t uid) { - if (llvm::Optional<PasswdEntry> password = GetPassword(uid)) +std::optional<std::string> PosixUserIDResolver::DoGetUserName(id_t uid) { + if (std::optional<PasswdEntry> password = GetPassword(uid)) return password->username; - return llvm::None; + return std::nullopt; } -llvm::Optional<std::string> PosixUserIDResolver::DoGetGroupName(id_t gid) { +std::optional<std::string> PosixUserIDResolver::DoGetGroupName(id_t gid) { #ifndef __ANDROID__ char group_buffer[PATH_MAX]; size_t group_buffer_size = sizeof(group_buffer); @@ -113,7 +114,7 @@ llvm::Optional<std::string> PosixUserIDResolver::DoGetGroupName(id_t gid) { return std::string(group_info_ptr->gr_name); } #endif - return llvm::None; + return std::nullopt; } static llvm::ManagedStatic<PosixUserIDResolver> g_user_id_resolver; @@ -133,7 +134,7 @@ uint32_t HostInfoPosix::GetEffectiveGroupID() { return getegid(); } FileSpec HostInfoPosix::GetDefaultShell() { if (const char *v = ::getenv("SHELL")) return FileSpec(v); - if (llvm::Optional<PasswdEntry> password = GetPassword(::geteuid())) + if (std::optional<PasswdEntry> password = GetPassword(::geteuid())) return FileSpec(password->shell); return FileSpec("/bin/sh"); } @@ -144,7 +145,7 @@ bool HostInfoPosix::ComputeSupportExeDirectory(FileSpec &file_spec) { bool HostInfoPosix::ComputeHeaderDirectory(FileSpec &file_spec) { FileSpec temp_file("/opt/local/include/lldb"); - file_spec.GetDirectory().SetCString(temp_file.GetPath().c_str()); + file_spec.SetDirectory(temp_file.GetPath()); return true; } diff --git a/contrib/llvm-project/lldb/source/Host/common/MainLoop.cpp b/contrib/llvm-project/lldb/source/Host/posix/MainLoopPosix.cpp index 8e384c9266b6..b185c3d3b707 100644 --- a/contrib/llvm-project/lldb/source/Host/common/MainLoop.cpp +++ b/contrib/llvm-project/lldb/source/Host/posix/MainLoopPosix.cpp @@ -1,4 +1,4 @@ -//===-- MainLoop.cpp ------------------------------------------------------===// +//===-- MainLoopPosix.cpp -------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,12 +6,12 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Config/llvm-config.h" +#include "lldb/Host/posix/MainLoopPosix.h" #include "lldb/Host/Config.h" - -#include "lldb/Host/MainLoop.h" #include "lldb/Host/PosixApi.h" #include "lldb/Utility/Status.h" +#include "llvm/Config/llvm-config.h" +#include "llvm/Support/Errno.h" #include <algorithm> #include <cassert> #include <cerrno> @@ -26,59 +26,32 @@ #if HAVE_SYS_EVENT_H #include <sys/event.h> -#elif defined(_WIN32) -#include <winsock2.h> #elif defined(__ANDROID__) #include <sys/syscall.h> #else #include <poll.h> #endif -#ifdef _WIN32 -#define POLL WSAPoll -#else -#define POLL poll -#endif - -#if SIGNAL_POLLING_UNSUPPORTED -#ifdef _WIN32 -typedef int sigset_t; -typedef int siginfo_t; -#endif - -int ppoll(struct pollfd *fds, size_t nfds, const struct timespec *timeout_ts, - const sigset_t *) { - int timeout = - (timeout_ts == nullptr) - ? -1 - : (timeout_ts->tv_sec * 1000 + timeout_ts->tv_nsec / 1000000); - return POLL(fds, nfds, timeout); -} - -#endif - using namespace lldb; using namespace lldb_private; static sig_atomic_t g_signal_flags[NSIG]; -#ifndef SIGNAL_POLLING_UNSUPPORTED static void SignalHandler(int signo, siginfo_t *info, void *) { assert(signo < NSIG); g_signal_flags[signo] = 1; } -#endif -class MainLoop::RunImpl { +class MainLoopPosix::RunImpl { public: - RunImpl(MainLoop &loop); + RunImpl(MainLoopPosix &loop); ~RunImpl() = default; Status Poll(); void ProcessEvents(); private: - MainLoop &loop; + MainLoopPosix &loop; #if HAVE_SYS_EVENT_H std::vector<struct kevent> in_events; @@ -97,18 +70,18 @@ private: }; #if HAVE_SYS_EVENT_H -MainLoop::RunImpl::RunImpl(MainLoop &loop) : loop(loop) { +MainLoopPosix::RunImpl::RunImpl(MainLoopPosix &loop) : loop(loop) { in_events.reserve(loop.m_read_fds.size()); } -Status MainLoop::RunImpl::Poll() { +Status MainLoopPosix::RunImpl::Poll() { in_events.resize(loop.m_read_fds.size()); unsigned i = 0; for (auto &fd : loop.m_read_fds) EV_SET(&in_events[i++], fd.first, EVFILT_READ, EV_ADD, 0, 0, 0); num_events = kevent(loop.m_kqueue, in_events.data(), in_events.size(), - out_events, llvm::array_lengthof(out_events), nullptr); + out_events, std::size(out_events), nullptr); if (num_events < 0) { if (errno == EINTR) { @@ -121,7 +94,7 @@ Status MainLoop::RunImpl::Poll() { return Status(); } -void MainLoop::RunImpl::ProcessEvents() { +void MainLoopPosix::RunImpl::ProcessEvents() { assert(num_events >= 0); for (int i = 0; i < num_events; ++i) { if (loop.m_terminate_request) @@ -139,31 +112,25 @@ void MainLoop::RunImpl::ProcessEvents() { } } #else -MainLoop::RunImpl::RunImpl(MainLoop &loop) : loop(loop) { +MainLoopPosix::RunImpl::RunImpl(MainLoopPosix &loop) : loop(loop) { #ifndef __ANDROID__ read_fds.reserve(loop.m_read_fds.size()); #endif } -sigset_t MainLoop::RunImpl::get_sigmask() { +sigset_t MainLoopPosix::RunImpl::get_sigmask() { sigset_t sigmask; -#if defined(_WIN32) - sigmask = 0; -#elif SIGNAL_POLLING_UNSUPPORTED - sigemptyset(&sigmask); -#else int ret = pthread_sigmask(SIG_SETMASK, nullptr, &sigmask); assert(ret == 0); - (void) ret; + (void)ret; for (const auto &sig : loop.m_signals) sigdelset(&sigmask, sig.first); -#endif return sigmask; } #ifdef __ANDROID__ -Status MainLoop::RunImpl::Poll() { +Status MainLoopPosix::RunImpl::Poll() { // ppoll(2) is not supported on older all android versions. Also, older // versions android (API <= 19) implemented pselect in a non-atomic way, as a // combination of pthread_sigmask and select. This is not sufficient for us, @@ -196,7 +163,7 @@ Status MainLoop::RunImpl::Poll() { return Status(); } #else -Status MainLoop::RunImpl::Poll() { +Status MainLoopPosix::RunImpl::Poll() { read_fds.clear(); sigset_t sigmask = get_sigmask(); @@ -217,7 +184,7 @@ Status MainLoop::RunImpl::Poll() { } #endif -void MainLoop::RunImpl::ProcessEvents() { +void MainLoopPosix::RunImpl::ProcessEvents() { #ifdef __ANDROID__ // Collect first all readable file descriptors into a separate vector and // then iterate over it to invoke callbacks. Iterating directly over @@ -255,29 +222,38 @@ void MainLoop::RunImpl::ProcessEvents() { } #endif -MainLoop::MainLoop() { +MainLoopPosix::MainLoopPosix() : m_triggering(false) { + Status error = m_trigger_pipe.CreateNew(/*child_process_inherit=*/false); + assert(error.Success()); + const int trigger_pipe_fd = m_trigger_pipe.GetReadFileDescriptor(); + m_read_fds.insert({trigger_pipe_fd, [trigger_pipe_fd](MainLoopBase &loop) { + char c; + ssize_t bytes_read = llvm::sys::RetryAfterSignal( + -1, ::read, trigger_pipe_fd, &c, 1); + assert(bytes_read == 1); + UNUSED_IF_ASSERT_DISABLED(bytes_read); + // NB: This implicitly causes another loop iteration + // and therefore the execution of pending callbacks. + }}); #if HAVE_SYS_EVENT_H m_kqueue = kqueue(); assert(m_kqueue >= 0); #endif } -MainLoop::~MainLoop() { + +MainLoopPosix::~MainLoopPosix() { #if HAVE_SYS_EVENT_H close(m_kqueue); #endif - assert(m_read_fds.size() == 0); + m_read_fds.erase(m_trigger_pipe.GetReadFileDescriptor()); + m_trigger_pipe.Close(); + assert(m_read_fds.size() == 0); assert(m_signals.size() == 0); } -MainLoop::ReadHandleUP MainLoop::RegisterReadObject(const IOObjectSP &object_sp, - const Callback &callback, - Status &error) { -#ifdef _WIN32 - if (object_sp->GetFdType() != IOObject:: eFDTypeSocket) { - error.SetErrorString("MainLoop: non-socket types unsupported on Windows"); - return nullptr; - } -#endif +MainLoopPosix::ReadHandleUP +MainLoopPosix::RegisterReadObject(const IOObjectSP &object_sp, + const Callback &callback, Status &error) { if (!object_sp || !object_sp->IsValid()) { error.SetErrorString("IO object is not valid."); return nullptr; @@ -296,12 +272,9 @@ MainLoop::ReadHandleUP MainLoop::RegisterReadObject(const IOObjectSP &object_sp, // We shall block the signal, then install the signal handler. The signal will // be unblocked in the Run() function to check for signal delivery. -MainLoop::SignalHandleUP -MainLoop::RegisterSignal(int signo, const Callback &callback, Status &error) { -#ifdef SIGNAL_POLLING_UNSUPPORTED - error.SetErrorString("Signal polling is not supported on this platform."); - return nullptr; -#else +MainLoopPosix::SignalHandleUP +MainLoopPosix::RegisterSignal(int signo, const Callback &callback, + Status &error) { auto signal_it = m_signals.find(signo); if (signal_it != m_signals.end()) { auto callback_it = signal_it->second.callbacks.insert( @@ -344,24 +317,16 @@ MainLoop::RegisterSignal(int signo, const Callback &callback, Status &error) { return SignalHandleUP(new SignalHandle( *this, signo, insert_ret.first->second.callbacks.begin())); -#endif -} - -void MainLoop::AddPendingCallback(const Callback &callback) { - m_pending_callbacks.push_back(callback); } -void MainLoop::UnregisterReadObject(IOObject::WaitableHandle handle) { +void MainLoopPosix::UnregisterReadObject(IOObject::WaitableHandle handle) { bool erased = m_read_fds.erase(handle); UNUSED_IF_ASSERT_DISABLED(erased); assert(erased); } -void MainLoop::UnregisterSignal(int signo, - std::list<Callback>::iterator callback_it) { -#if SIGNAL_POLLING_UNSUPPORTED - Status("Signal polling is not supported on this platform."); -#else +void MainLoopPosix::UnregisterSignal( + int signo, std::list<Callback>::iterator callback_it) { auto it = m_signals.find(signo); assert(it != m_signals.end()); @@ -388,32 +353,37 @@ void MainLoop::UnregisterSignal(int signo, #endif m_signals.erase(it); -#endif } -Status MainLoop::Run() { +Status MainLoopPosix::Run() { m_terminate_request = false; Status error; RunImpl impl(*this); // run until termination or until we run out of things to listen to - while (!m_terminate_request && (!m_read_fds.empty() || !m_signals.empty())) { - + // (m_read_fds will always contain m_trigger_pipe fd, so check for > 1) + while (!m_terminate_request && + (m_read_fds.size() > 1 || !m_signals.empty())) { error = impl.Poll(); if (error.Fail()) return error; impl.ProcessEvents(); - for (const Callback &callback : m_pending_callbacks) - callback(*this); - m_pending_callbacks.clear(); + m_triggering = false; + ProcessPendingCallbacks(); } return Status(); } -void MainLoop::ProcessSignal(int signo) { +void MainLoopPosix::ProcessReadObject(IOObject::WaitableHandle handle) { + auto it = m_read_fds.find(handle); + if (it != m_read_fds.end()) + it->second(*this); // Do the work +} + +void MainLoopPosix::ProcessSignal(int signo) { auto it = m_signals.find(signo); if (it != m_signals.end()) { // The callback may actually register/unregister signal handlers, @@ -425,8 +395,14 @@ void MainLoop::ProcessSignal(int signo) { } } -void MainLoop::ProcessReadObject(IOObject::WaitableHandle handle) { - auto it = m_read_fds.find(handle); - if (it != m_read_fds.end()) - it->second(*this); // Do the work +void MainLoopPosix::TriggerPendingCallbacks() { + if (m_triggering.exchange(true)) + return; + + char c = '.'; + size_t bytes_written; + Status error = m_trigger_pipe.Write(&c, 1, bytes_written); + assert(error.Success()); + UNUSED_IF_ASSERT_DISABLED(error); + assert(bytes_written == 1); } diff --git a/contrib/llvm-project/lldb/source/Host/posix/ProcessLauncherPosixFork.cpp b/contrib/llvm-project/lldb/source/Host/posix/ProcessLauncherPosixFork.cpp index 635dbb14a027..a148c110e87b 100644 --- a/contrib/llvm-project/lldb/source/Host/posix/ProcessLauncherPosixFork.cpp +++ b/contrib/llvm-project/lldb/source/Host/posix/ProcessLauncherPosixFork.cpp @@ -282,10 +282,19 @@ ProcessLauncherPosixFork::LaunchProcess(const ProcessLaunchInfo &launch_info, // parent process pipe.CloseWriteFileDescriptor(); - char buf[1000]; - int r = read(pipe.GetReadFileDescriptor(), buf, sizeof buf); - - if (r == 0) + llvm::SmallString<0> buf; + size_t pos = 0; + ssize_t r = 0; + do { + pos += r; + buf.resize_for_overwrite(pos + 100); + r = llvm::sys::RetryAfterSignal(-1, read, pipe.GetReadFileDescriptor(), + buf.begin() + pos, buf.size() - pos); + } while (r > 0); + assert(r != -1); + + buf.resize(pos); + if (buf.empty()) return HostProcess(pid); // No error. We're done. error.SetErrorString(buf); diff --git a/contrib/llvm-project/lldb/source/Initialization/SystemInitializerCommon.cpp b/contrib/llvm-project/lldb/source/Initialization/SystemInitializerCommon.cpp index b14218442cec..40e54cd7f0e0 100644 --- a/contrib/llvm-project/lldb/source/Initialization/SystemInitializerCommon.cpp +++ b/contrib/llvm-project/lldb/source/Initialization/SystemInitializerCommon.cpp @@ -12,8 +12,9 @@ #include "lldb/Host/FileSystem.h" #include "lldb/Host/Host.h" #include "lldb/Host/Socket.h" +#include "lldb/Target/Statistics.h" +#include "lldb/Utility/Diagnostics.h" #include "lldb/Utility/LLDBLog.h" -#include "lldb/Utility/ReproducerProvider.h" #include "lldb/Utility/Timer.h" #include "lldb/Version/Version.h" @@ -32,7 +33,6 @@ #include <string> using namespace lldb_private; -using namespace lldb_private::repro; SystemInitializerCommon::SystemInitializerCommon( HostInfo::SharedLibraryDirectoryHelper *helper) @@ -40,31 +40,6 @@ SystemInitializerCommon::SystemInitializerCommon( SystemInitializerCommon::~SystemInitializerCommon() = default; -/// Initialize the FileSystem based on the current reproducer mode. -static llvm::Error InitializeFileSystem() { - auto &r = repro::Reproducer::Instance(); - - if (repro::Generator *g = r.GetGenerator()) { - repro::VersionProvider &vp = g->GetOrCreate<repro::VersionProvider>(); - vp.SetVersion(lldb_private::GetVersion()); - - repro::FileProvider &fp = g->GetOrCreate<repro::FileProvider>(); - - FileSystem::Initialize(llvm::FileCollector::createCollectorVFS( - llvm::vfs::getRealFileSystem(), fp.GetFileCollector())); - - fp.RecordInterestingDirectory( - g->GetOrCreate<repro::WorkingDirectoryProvider>().GetDirectory()); - fp.RecordInterestingDirectory( - g->GetOrCreate<repro::HomeDirectoryProvider>().GetDirectory()); - - return llvm::Error::success(); - } - - FileSystem::Initialize(); - return llvm::Error::success(); -} - llvm::Error SystemInitializerCommon::Initialize() { #if defined(_WIN32) const char *disable_crash_dialog_var = getenv("LLDB_DISABLE_CRASH_DIALOG"); @@ -88,17 +63,10 @@ llvm::Error SystemInitializerCommon::Initialize() { } #endif - // If the reproducer wasn't initialized before, we can safely assume it's - // off. - if (!Reproducer::Initialized()) { - if (auto e = Reproducer::Initialize(ReproducerMode::Off, llvm::None)) - return e; - } - - if (auto e = InitializeFileSystem()) - return e; - InitializeLldbChannel(); + + Diagnostics::Initialize(); + FileSystem::Initialize(); HostInfo::Initialize(m_shlib_dir_helper); llvm::Error error = Socket::Initialize(); @@ -130,5 +98,5 @@ void SystemInitializerCommon::Terminate() { HostInfo::Terminate(); Log::DisableAllLogChannels(); FileSystem::Terminate(); - Reproducer::Terminate(); + Diagnostics::Terminate(); } diff --git a/contrib/llvm-project/lldb/source/Interpreter/CommandAlias.cpp b/contrib/llvm-project/lldb/source/Interpreter/CommandAlias.cpp index d55b3fdd44fa..e36edcac15a5 100644 --- a/contrib/llvm-project/lldb/source/Interpreter/CommandAlias.cpp +++ b/contrib/llvm-project/lldb/source/Interpreter/CommandAlias.cpp @@ -60,11 +60,12 @@ static bool ProcessAliasOptionsArgs(lldb::CommandObjectSP &cmd_obj_sp, if (!options_string.empty()) { if (cmd_obj_sp->WantsRawCommandString()) - option_arg_vector->emplace_back("<argument>", -1, options_string); + option_arg_vector->emplace_back(CommandInterpreter::g_argument, + -1, options_string); else { for (auto &entry : args.entries()) { if (!entry.ref().empty()) - option_arg_vector->emplace_back(std::string("<argument>"), -1, + option_arg_vector->emplace_back(std::string(CommandInterpreter::g_argument), -1, std::string(entry.ref())); } } @@ -153,11 +154,12 @@ void CommandAlias::GetAliasExpansion(StreamString &help_string) const { for (const auto &opt_entry : *options) { std::tie(opt, std::ignore, value) = opt_entry; - if (opt == "<argument>") { + if (opt == CommandInterpreter::g_argument) { help_string.Printf(" %s", value.c_str()); } else { help_string.Printf(" %s", opt.c_str()); - if ((value != "<no-argument>") && (value != "<need-argument")) { + if ((value != CommandInterpreter::g_no_argument) + && (value != CommandInterpreter::g_need_argument)) { help_string.Printf(" %s", value.c_str()); } } @@ -178,7 +180,7 @@ bool CommandAlias::IsDashDashCommand() { for (const auto &opt_entry : *GetOptionArguments()) { std::tie(opt, std::ignore, value) = opt_entry; - if (opt == "<argument>" && !value.empty() && + if (opt == CommandInterpreter::g_argument && !value.empty() && llvm::StringRef(value).endswith("--")) { m_is_dashdash_alias = eLazyBoolYes; break; @@ -206,6 +208,8 @@ std::pair<lldb::CommandObjectSP, OptionArgVectorSP> CommandAlias::Desugar() { return {nullptr, nullptr}; if (underlying->IsAlias()) { + // FIXME: This doesn't work if the original alias fills a slot in the + // underlying alias, since this just appends the two lists. auto desugared = ((CommandAlias *)underlying.get())->Desugar(); auto options = GetOptionArguments(); options->insert(options->begin(), desugared.second->begin(), diff --git a/contrib/llvm-project/lldb/source/Interpreter/CommandHistory.cpp b/contrib/llvm-project/lldb/source/Interpreter/CommandHistory.cpp index 8f399840b802..f5dbcb675030 100644 --- a/contrib/llvm-project/lldb/source/Interpreter/CommandHistory.cpp +++ b/contrib/llvm-project/lldb/source/Interpreter/CommandHistory.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include <cinttypes> +#include <optional> #include "lldb/Interpreter/CommandHistory.h" @@ -23,18 +24,18 @@ bool CommandHistory::IsEmpty() const { return m_history.empty(); } -llvm::Optional<llvm::StringRef> +std::optional<llvm::StringRef> CommandHistory::FindString(llvm::StringRef input_str) const { std::lock_guard<std::recursive_mutex> guard(m_mutex); if (input_str.size() < 2) - return llvm::None; + return std::nullopt; if (input_str[0] != g_repeat_char) - return llvm::None; + return std::nullopt; if (input_str[1] == g_repeat_char) { if (m_history.empty()) - return llvm::None; + return std::nullopt; return llvm::StringRef(m_history.back()); } @@ -43,15 +44,15 @@ CommandHistory::FindString(llvm::StringRef input_str) const { size_t idx = 0; if (input_str.front() == '-') { if (input_str.drop_front(1).getAsInteger(0, idx)) - return llvm::None; + return std::nullopt; if (idx >= m_history.size()) - return llvm::None; + return std::nullopt; idx = m_history.size() - idx; } else { if (input_str.getAsInteger(0, idx)) - return llvm::None; + return std::nullopt; if (idx >= m_history.size()) - return llvm::None; + return std::nullopt; } return llvm::StringRef(m_history[idx]); diff --git a/contrib/llvm-project/lldb/source/Interpreter/CommandInterpreter.cpp b/contrib/llvm-project/lldb/source/Interpreter/CommandInterpreter.cpp index 6ef209b20fc6..8b24c72d7733 100644 --- a/contrib/llvm-project/lldb/source/Interpreter/CommandInterpreter.cpp +++ b/contrib/llvm-project/lldb/source/Interpreter/CommandInterpreter.cpp @@ -9,12 +9,15 @@ #include <cstdlib> #include <limits> #include <memory> +#include <optional> #include <string> #include <vector> #include "Commands/CommandObjectApropos.h" #include "Commands/CommandObjectBreakpoint.h" #include "Commands/CommandObjectCommands.h" +#include "Commands/CommandObjectDWIMPrint.h" +#include "Commands/CommandObjectDiagnostics.h" #include "Commands/CommandObjectDisassemble.h" #include "Commands/CommandObjectExpression.h" #include "Commands/CommandObjectFrame.h" @@ -29,7 +32,6 @@ #include "Commands/CommandObjectQuit.h" #include "Commands/CommandObjectRegexCommand.h" #include "Commands/CommandObjectRegister.h" -#include "Commands/CommandObjectReproducer.h" #include "Commands/CommandObjectScript.h" #include "Commands/CommandObjectSession.h" #include "Commands/CommandObjectSettings.h" @@ -47,7 +49,6 @@ #include "lldb/Core/StreamFile.h" #include "lldb/Utility/LLDBLog.h" #include "lldb/Utility/Log.h" -#include "lldb/Utility/Reproducer.h" #include "lldb/Utility/State.h" #include "lldb/Utility/Stream.h" #include "lldb/Utility/Timer.h" @@ -105,6 +106,11 @@ static constexpr const char *InitFileWarning = "and\n" "accept the security risk."; +const char *CommandInterpreter::g_no_argument = "<no-argument>"; +const char *CommandInterpreter::g_need_argument = "<need-argument>"; +const char *CommandInterpreter::g_argument = "<argument>"; + + #define LLDB_PROPERTIES_interpreter #include "InterpreterProperties.inc" @@ -166,6 +172,17 @@ void CommandInterpreter::SetSaveSessionOnQuit(bool enable) { m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, enable); } +bool CommandInterpreter::GetOpenTranscriptInEditor() const { + const uint32_t idx = ePropertyOpenTranscriptInEditor; + return m_collection_sp->GetPropertyAtIndexAsBoolean( + nullptr, idx, g_interpreter_properties[idx].default_uint_value != 0); +} + +void CommandInterpreter::SetOpenTranscriptInEditor(bool enable) { + const uint32_t idx = ePropertyOpenTranscriptInEditor; + m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, enable); +} + FileSpec CommandInterpreter::GetSaveSessionDirectory() const { const uint32_t idx = ePropertySaveSessionDirectory; return m_collection_sp->GetPropertyAtIndexAsFileSpec(nullptr, idx); @@ -515,7 +532,9 @@ void CommandInterpreter::LoadCommandDictionary() { REGISTER_COMMAND_OBJECT("apropos", CommandObjectApropos); REGISTER_COMMAND_OBJECT("breakpoint", CommandObjectMultiwordBreakpoint); REGISTER_COMMAND_OBJECT("command", CommandObjectMultiwordCommands); + REGISTER_COMMAND_OBJECT("diagnostics", CommandObjectDiagnostics); REGISTER_COMMAND_OBJECT("disassemble", CommandObjectDisassemble); + REGISTER_COMMAND_OBJECT("dwim-print", CommandObjectDWIMPrint); REGISTER_COMMAND_OBJECT("expression", CommandObjectExpression); REGISTER_COMMAND_OBJECT("frame", CommandObjectMultiwordFrame); REGISTER_COMMAND_OBJECT("gui", CommandObjectGUI); @@ -527,7 +546,6 @@ void CommandInterpreter::LoadCommandDictionary() { REGISTER_COMMAND_OBJECT("process", CommandObjectMultiwordProcess); REGISTER_COMMAND_OBJECT("quit", CommandObjectQuit); REGISTER_COMMAND_OBJECT("register", CommandObjectRegister); - REGISTER_COMMAND_OBJECT("reproducer", CommandObjectReproducer); REGISTER_COMMAND_OBJECT("script", CommandObjectScript); REGISTER_COMMAND_OBJECT("settings", CommandObjectMultiwordSettings); REGISTER_COMMAND_OBJECT("session", CommandObjectSession); @@ -561,7 +579,7 @@ void CommandInterpreter::LoadCommandDictionary() { "breakpoint set --name '%1'"}}; // clang-format on - size_t num_regexes = llvm::array_lengthof(break_regexes); + size_t num_regexes = std::size(break_regexes); std::unique_ptr<CommandObjectRegexCommand> break_regex_cmd_up( new CommandObjectRegexCommand( @@ -1634,7 +1652,7 @@ CommandObject *CommandInterpreter::BuildAliasResult( std::string value; for (const auto &entry : *option_arg_vector) { std::tie(option, value_type, value) = entry; - if (option == "<argument>") { + if (option == g_argument) { result_str.Printf(" %s", value.c_str()); continue; } @@ -1656,11 +1674,33 @@ CommandObject *CommandInterpreter::BuildAliasResult( index); return nullptr; } else { - size_t strpos = raw_input_string.find(cmd_args.GetArgumentAtIndex(index)); - if (strpos != std::string::npos) + const Args::ArgEntry &entry = cmd_args[index]; + size_t strpos = raw_input_string.find(entry.c_str()); + const char quote_char = entry.GetQuoteChar(); + if (strpos != std::string::npos) { + const size_t start_fudge = quote_char == '\0' ? 0 : 1; + const size_t len_fudge = quote_char == '\0' ? 0 : 2; + + // Make sure we aren't going outside the bounds of the cmd string: + if (strpos < start_fudge) { + result.AppendError("Unmatched quote at command beginning."); + return nullptr; + } + llvm::StringRef arg_text = entry.ref(); + if (strpos - start_fudge + arg_text.size() + len_fudge + > raw_input_string.size()) { + result.AppendError("Unmatched quote at command end."); + return nullptr; + } raw_input_string = raw_input_string.erase( - strpos, strlen(cmd_args.GetArgumentAtIndex(index))); - result_str.Printf("%s", cmd_args.GetArgumentAtIndex(index)); + strpos - start_fudge, + strlen(cmd_args.GetArgumentAtIndex(index)) + len_fudge); + } + if (quote_char == '\0') + result_str.Printf("%s", cmd_args.GetArgumentAtIndex(index)); + else + result_str.Printf("%c%s%c", quote_char, + entry.c_str(), quote_char); } } @@ -1725,7 +1765,7 @@ Status CommandInterpreter::PreprocessCommand(std::string &command) { options.SetIgnoreBreakpoints(true); options.SetKeepInMemory(false); options.SetTryAllThreads(true); - options.SetTimeout(llvm::None); + options.SetTimeout(std::nullopt); ExpressionResults expr_result = target.EvaluateExpression(expr_str.c_str(), exe_ctx.GetFramePtr(), @@ -1911,13 +1951,6 @@ bool CommandInterpreter::HandleCommand(const char *command_line, return true; } - Status error(PreprocessCommand(command_string)); - - if (error.Fail()) { - result.AppendError(error.AsCString()); - return false; - } - // Phase 1. // Before we do ANY kind of argument processing, we need to figure out what @@ -1935,6 +1968,20 @@ bool CommandInterpreter::HandleCommand(const char *command_line, CommandObject *cmd_obj = ResolveCommandImpl(command_string, result); + // We have to preprocess the whole command string for Raw commands, since we + // don't know the structure of the command. For parsed commands, we only + // treat backticks as quote characters specially. + // FIXME: We probably want to have raw commands do their own preprocessing. + // For instance, I don't think people expect substitution in expr expressions. + if (cmd_obj && cmd_obj->WantsRawCommandString()) { + Status error(PreprocessCommand(command_string)); + + if (error.Fail()) { + result.AppendError(error.AsCString()); + return false; + } + } + // Although the user may have abbreviated the command, the command_string now // has the command expanded to the full name. For example, if the input was // "br s -n main", command_string is now "breakpoint set -n main". @@ -1960,7 +2007,7 @@ bool CommandInterpreter::HandleCommand(const char *command_line, // repeat command, even though we don't add repeat commands to the history. if (add_to_history || empty_command) { Args command_args(command_string); - llvm::Optional<std::string> repeat_command = + std::optional<std::string> repeat_command = cmd_obj->GetRepeatCommand(command_args, 0); if (repeat_command) m_repeat_command.assign(*repeat_command); @@ -2064,17 +2111,17 @@ void CommandInterpreter::HandleCompletion(CompletionRequest &request) { HandleCompletionMatches(request); } -llvm::Optional<std::string> +std::optional<std::string> CommandInterpreter::GetAutoSuggestionForCommand(llvm::StringRef line) { if (line.empty()) - return llvm::None; + return std::nullopt; const size_t s = m_command_history.GetSize(); for (int i = s - 1; i >= 0; --i) { llvm::StringRef entry = m_command_history.GetStringAtIndex(i); if (entry.consume_front(line)) return entry.str(); } - return llvm::None; + return std::nullopt; } void CommandInterpreter::UpdatePrompt(llvm::StringRef new_prompt) { @@ -2163,7 +2210,7 @@ void CommandInterpreter::BuildAliasCommandArgs(CommandObject *alias_cmd_obj, std::string value; for (const auto &option_entry : *option_arg_vector) { std::tie(option, value_type, value) = option_entry; - if (option == "<argument>") { + if (option == g_argument) { if (!wants_raw_input || (value != "--")) { // Since we inserted this above, make sure we don't insert it twice new_args.AppendArgument(value); @@ -2174,7 +2221,7 @@ void CommandInterpreter::BuildAliasCommandArgs(CommandObject *alias_cmd_obj, if (value_type != OptionParser::eOptionalArgument) new_args.AppendArgument(option); - if (value == "<no-argument>") + if (value == g_no_argument) continue; int index = GetOptionArgumentPosition(value.c_str()); @@ -2440,8 +2487,12 @@ bool CommandInterpreter::DidProcessStopAbnormally() const { for (const auto &thread_sp : process_sp->GetThreadList().Threads()) { StopInfoSP stop_info = thread_sp->GetStopInfo(); - if (!stop_info) - return false; + if (!stop_info) { + // If there's no stop_info, keep iterating through the other threads; + // it's enough that any thread has got a stop_info that indicates + // an abnormal stop, to consider the process to be stopped abnormally. + continue; + } const StopReason reason = stop_info->GetStopReason(); if (reason == eStopReasonException || @@ -2742,7 +2793,7 @@ void CommandInterpreter::HandleCommandsFromFile(FileSpec &cmd_file, // or written debugger.GetPrompt(), llvm::StringRef(), false, // Not multi-line - debugger.GetUseColor(), 0, *this, nullptr)); + debugger.GetUseColor(), 0, *this)); const bool old_async_execution = debugger.GetAsyncExecution(); // Set synchronous execution if we are not stopping on continue @@ -2766,9 +2817,6 @@ void CommandInterpreter::HandleCommandsFromFile(FileSpec &cmd_file, bool CommandInterpreter::GetSynchronous() { return m_synchronous_execution; } void CommandInterpreter::SetSynchronous(bool value) { - // Asynchronous mode is not supported during reproducer replay. - if (repro::Reproducer::Instance().GetLoader()) - return; m_synchronous_execution = value; } @@ -3144,8 +3192,8 @@ bool CommandInterpreter::IOHandlerInterrupt(IOHandler &io_handler) { } bool CommandInterpreter::SaveTranscript( - CommandReturnObject &result, llvm::Optional<std::string> output_file) { - if (output_file == llvm::None || output_file->empty()) { + CommandReturnObject &result, std::optional<std::string> output_file) { + if (output_file == std::nullopt || output_file->empty()) { std::string now = llvm::to_string(std::chrono::system_clock::now()); std::replace(now.begin(), now.end(), ' ', '_'); const std::string file_name = "lldb_session_" + now + ".log"; @@ -3192,6 +3240,13 @@ bool CommandInterpreter::SaveTranscript( result.AppendMessageWithFormat("Session's transcripts saved to %s\n", output_file->c_str()); + if (GetOpenTranscriptInEditor() && Host::IsInteractiveGraphicSession()) { + const FileSpec file_spec; + error = file->GetFileSpec(const_cast<FileSpec &>(file_spec)); + if (error.Success()) + Host::OpenFileInExternalEditor(file_spec, 1); + } + return true; } @@ -3215,9 +3270,8 @@ void CommandInterpreter::GetLLDBCommandsFromIOHandler( llvm::StringRef(), // Continuation prompt true, // Get multiple lines debugger.GetUseColor(), - 0, // Don't show line numbers - delegate, // IOHandlerDelegate - nullptr)); // FileShadowCollector + 0, // Don't show line numbers + delegate)); // IOHandlerDelegate if (io_handler_sp) { io_handler_sp->SetUserData(baton); @@ -3235,9 +3289,8 @@ void CommandInterpreter::GetPythonCommandsFromIOHandler( llvm::StringRef(), // Continuation prompt true, // Get multiple lines debugger.GetUseColor(), - 0, // Don't show line numbers - delegate, // IOHandlerDelegate - nullptr)); // FileShadowCollector + 0, // Don't show line numbers + delegate)); // IOHandlerDelegate if (io_handler_sp) { io_handler_sp->SetUserData(baton); @@ -3288,9 +3341,8 @@ CommandInterpreter::GetIOHandler(bool force_create, llvm::StringRef(), // Continuation prompt false, // Don't enable multiple line input, just single line commands m_debugger.GetUseColor(), - 0, // Don't show line numbers - *this, // IOHandlerDelegate - GetDebugger().GetInputRecorder()); + 0, // Don't show line numbers + *this); // IOHandlerDelegate } return m_command_io_handler_sp; } diff --git a/contrib/llvm-project/lldb/source/Interpreter/CommandObject.cpp b/contrib/llvm-project/lldb/source/Interpreter/CommandObject.cpp index 719cfbc9e802..4500378c6229 100644 --- a/contrib/llvm-project/lldb/source/Interpreter/CommandObject.cpp +++ b/contrib/llvm-project/lldb/source/Interpreter/CommandObject.cpp @@ -727,7 +727,7 @@ bool CommandObjectParsed::Execute(const char *args_string, } if (!handled) { for (auto entry : llvm::enumerate(cmd_args.entries())) { - if (!entry.value().ref().empty() && entry.value().ref().front() == '`') { + if (!entry.value().ref().empty() && entry.value().GetQuoteChar() == '`') { cmd_args.ReplaceArgumentAtIndex( entry.index(), m_interpreter.ProcessEmbeddedScriptCommands(entry.value().c_str())); @@ -741,6 +741,7 @@ bool CommandObjectParsed::Execute(const char *args_string, if (cmd_args.GetArgumentCount() != 0 && m_arguments.empty()) { result.AppendErrorWithFormatv("'{0}' doesn't take any arguments.", GetCommandName()); + Cleanup(); return false; } handled = DoExecute(cmd_args, result); diff --git a/contrib/llvm-project/lldb/source/Interpreter/InterpreterProperties.td b/contrib/llvm-project/lldb/source/Interpreter/InterpreterProperties.td index c0acc044fb7f..2155ee61ccff 100644 --- a/contrib/llvm-project/lldb/source/Interpreter/InterpreterProperties.td +++ b/contrib/llvm-project/lldb/source/Interpreter/InterpreterProperties.td @@ -13,6 +13,10 @@ let Definition = "interpreter" in { Global, DefaultFalse, Desc<"If true, LLDB will save the session's transcripts before quitting.">; + def OpenTranscriptInEditor: Property<"open-transcript-in-editor", "Boolean">, + Global, + DefaultTrue, + Desc<"If true, LLDB will open the saved session's transcripts in the external editor.">; def SaveSessionDirectory: Property<"save-session-directory", "FileSpec">, DefaultStringValue<"">, Desc<"A path where LLDB will save the session's transcripts. This is particularly useful when you can't set the session file, for example when using `save-session-on-quit`.">; diff --git a/contrib/llvm-project/lldb/source/Interpreter/OptionArgParser.cpp b/contrib/llvm-project/lldb/source/Interpreter/OptionArgParser.cpp index 93b01abde4bb..63ca0f9d3d4d 100644 --- a/contrib/llvm-project/lldb/source/Interpreter/OptionArgParser.cpp +++ b/contrib/llvm-project/lldb/source/Interpreter/OptionArgParser.cpp @@ -8,6 +8,7 @@ #include "lldb/Interpreter/OptionArgParser.h" #include "lldb/DataFormatters/FormatManager.h" +#include "lldb/Target/ABI.h" #include "lldb/Target/Target.h" #include "lldb/Utility/Status.h" #include "lldb/Utility/StreamString.h" @@ -157,6 +158,10 @@ lldb::addr_t OptionArgParser::ToAddress(const ExecutionContext *exe_ctx, if (!s.getAsInteger(0, addr)) { if (error_ptr) error_ptr->Clear(); + Process *process = exe_ctx->GetProcessPtr(); + if (process) + if (ABISP abi_sp = process->GetABI()) + addr = abi_sp->FixCodeAddress(addr); return addr; } diff --git a/contrib/llvm-project/lldb/source/Interpreter/OptionGroupArchitecture.cpp b/contrib/llvm-project/lldb/source/Interpreter/OptionGroupArchitecture.cpp index 00541b7198d2..3925f835885f 100644 --- a/contrib/llvm-project/lldb/source/Interpreter/OptionGroupArchitecture.cpp +++ b/contrib/llvm-project/lldb/source/Interpreter/OptionGroupArchitecture.cpp @@ -20,7 +20,7 @@ static constexpr OptionDefinition g_option_table[] = { }; llvm::ArrayRef<OptionDefinition> OptionGroupArchitecture::GetDefinitions() { - return llvm::makeArrayRef(g_option_table); + return llvm::ArrayRef(g_option_table); } bool OptionGroupArchitecture::GetArchitecture(Platform *platform, diff --git a/contrib/llvm-project/lldb/source/Interpreter/OptionGroupFormat.cpp b/contrib/llvm-project/lldb/source/Interpreter/OptionGroupFormat.cpp index a2ca9ff39818..6b56ad2ea819 100644 --- a/contrib/llvm-project/lldb/source/Interpreter/OptionGroupFormat.cpp +++ b/contrib/llvm-project/lldb/source/Interpreter/OptionGroupFormat.cpp @@ -37,7 +37,7 @@ OptionGroupFormat::OptionGroupFormat( : m_format(default_format, default_format), m_byte_size(default_byte_size, default_byte_size), m_count(default_count, default_count), m_prev_gdb_format('x'), - m_prev_gdb_size('w') { + m_prev_gdb_size('w'), m_has_gdb_format(false) { // Copy the default option definitions. std::copy(std::begin(g_default_option_definitions), std::end(g_default_option_definitions), @@ -58,7 +58,7 @@ OptionGroupFormat::OptionGroupFormat( } llvm::ArrayRef<OptionDefinition> OptionGroupFormat::GetDefinitions() { - auto result = llvm::makeArrayRef(m_option_definitions); + auto result = llvm::ArrayRef(m_option_definitions); if (m_byte_size.GetDefaultValue() < UINT64_MAX) { if (m_count.GetDefaultValue() < UINT64_MAX) return result; diff --git a/contrib/llvm-project/lldb/source/Interpreter/OptionGroupMemoryTag.cpp b/contrib/llvm-project/lldb/source/Interpreter/OptionGroupMemoryTag.cpp index 6752b6c8acf2..c6efab7c3871 100644 --- a/contrib/llvm-project/lldb/source/Interpreter/OptionGroupMemoryTag.cpp +++ b/contrib/llvm-project/lldb/source/Interpreter/OptionGroupMemoryTag.cpp @@ -32,7 +32,7 @@ OptionGroupMemoryTag::OptionGroupMemoryTag(bool note_binary /*=false*/) : "Include memory tags in output."} {} llvm::ArrayRef<OptionDefinition> OptionGroupMemoryTag::GetDefinitions() { - return llvm::makeArrayRef(m_option_definition); + return llvm::ArrayRef(m_option_definition); } Status diff --git a/contrib/llvm-project/lldb/source/Interpreter/OptionGroupOutputFile.cpp b/contrib/llvm-project/lldb/source/Interpreter/OptionGroupOutputFile.cpp index 6a626bd63014..f0044606e1de 100644 --- a/contrib/llvm-project/lldb/source/Interpreter/OptionGroupOutputFile.cpp +++ b/contrib/llvm-project/lldb/source/Interpreter/OptionGroupOutputFile.cpp @@ -27,7 +27,7 @@ static constexpr OptionDefinition g_option_table[] = { }; llvm::ArrayRef<OptionDefinition> OptionGroupOutputFile::GetDefinitions() { - return llvm::makeArrayRef(g_option_table); + return llvm::ArrayRef(g_option_table); } Status diff --git a/contrib/llvm-project/lldb/source/Interpreter/OptionGroupPlatform.cpp b/contrib/llvm-project/lldb/source/Interpreter/OptionGroupPlatform.cpp index acdf3f293496..60107eb28806 100644 --- a/contrib/llvm-project/lldb/source/Interpreter/OptionGroupPlatform.cpp +++ b/contrib/llvm-project/lldb/source/Interpreter/OptionGroupPlatform.cpp @@ -30,8 +30,9 @@ PlatformSP OptionGroupPlatform::CreatePlatformWithOptions( m_platform_name); } if (platform_sp) { - if (platform_arch.IsValid() && !platform_sp->IsCompatibleArchitecture( - arch, {}, false, &platform_arch)) { + if (platform_arch.IsValid() && + !platform_sp->IsCompatibleArchitecture( + arch, {}, ArchSpec::CompatibleMatch, &platform_arch)) { error.SetErrorStringWithFormatv("platform '{0}' doesn't support '{1}'", platform_sp->GetPluginName(), arch.GetTriple().getTriple()); diff --git a/contrib/llvm-project/lldb/source/Interpreter/OptionGroupUUID.cpp b/contrib/llvm-project/lldb/source/Interpreter/OptionGroupUUID.cpp index 5b4c24a0a32b..7a0efbab0398 100644 --- a/contrib/llvm-project/lldb/source/Interpreter/OptionGroupUUID.cpp +++ b/contrib/llvm-project/lldb/source/Interpreter/OptionGroupUUID.cpp @@ -19,7 +19,7 @@ static constexpr OptionDefinition g_option_table[] = { }; llvm::ArrayRef<OptionDefinition> OptionGroupUUID::GetDefinitions() { - return llvm::makeArrayRef(g_option_table); + return llvm::ArrayRef(g_option_table); } Status OptionGroupUUID::SetOptionValue(uint32_t option_idx, diff --git a/contrib/llvm-project/lldb/source/Interpreter/OptionGroupValueObjectDisplay.cpp b/contrib/llvm-project/lldb/source/Interpreter/OptionGroupValueObjectDisplay.cpp index 57b593020b14..294665fa6b45 100644 --- a/contrib/llvm-project/lldb/source/Interpreter/OptionGroupValueObjectDisplay.cpp +++ b/contrib/llvm-project/lldb/source/Interpreter/OptionGroupValueObjectDisplay.cpp @@ -62,7 +62,7 @@ static const OptionDefinition g_option_table[] = { llvm::ArrayRef<OptionDefinition> OptionGroupValueObjectDisplay::GetDefinitions() { - return llvm::makeArrayRef(g_option_table); + return llvm::ArrayRef(g_option_table); } Status OptionGroupValueObjectDisplay::SetOptionValue( diff --git a/contrib/llvm-project/lldb/source/Interpreter/OptionGroupVariable.cpp b/contrib/llvm-project/lldb/source/Interpreter/OptionGroupVariable.cpp index 20a521b8e44f..0e35a641361b 100644 --- a/contrib/llvm-project/lldb/source/Interpreter/OptionGroupVariable.cpp +++ b/contrib/llvm-project/lldb/source/Interpreter/OptionGroupVariable.cpp @@ -67,8 +67,10 @@ static Status ValidateSummaryString(const char *str, void *) { } OptionGroupVariable::OptionGroupVariable(bool show_frame_options) - : include_frame_options(show_frame_options), summary(ValidateNamedSummary), - summary_string(ValidateSummaryString) {} + : include_frame_options(show_frame_options), show_args(false), + show_recognized_args(false), show_locals(false), show_globals(false), + use_regex(false), show_scope(false), show_decl(false), + summary(ValidateNamedSummary), summary_string(ValidateSummaryString) {} Status OptionGroupVariable::SetOptionValue(uint32_t option_idx, @@ -129,7 +131,7 @@ void OptionGroupVariable::OptionParsingStarting( #define NUM_FRAME_OPTS 3 llvm::ArrayRef<OptionDefinition> OptionGroupVariable::GetDefinitions() { - auto result = llvm::makeArrayRef(g_variable_options); + auto result = llvm::ArrayRef(g_variable_options); // Show the "--no-args", "--no-locals" and "--show-globals" options if we are // showing frame specific options if (include_frame_options) diff --git a/contrib/llvm-project/lldb/source/Interpreter/OptionGroupWatchpoint.cpp b/contrib/llvm-project/lldb/source/Interpreter/OptionGroupWatchpoint.cpp index eb9842add28c..5559e82d4722 100644 --- a/contrib/llvm-project/lldb/source/Interpreter/OptionGroupWatchpoint.cpp +++ b/contrib/llvm-project/lldb/source/Interpreter/OptionGroupWatchpoint.cpp @@ -111,5 +111,5 @@ void OptionGroupWatchpoint::OptionParsingStarting( } llvm::ArrayRef<OptionDefinition> OptionGroupWatchpoint::GetDefinitions() { - return llvm::makeArrayRef(g_option_table); + return llvm::ArrayRef(g_option_table); } diff --git a/contrib/llvm-project/lldb/source/Interpreter/OptionValueArray.cpp b/contrib/llvm-project/lldb/source/Interpreter/OptionValueArray.cpp index c202a188fe2a..40357d5f4b06 100644 --- a/contrib/llvm-project/lldb/source/Interpreter/OptionValueArray.cpp +++ b/contrib/llvm-project/lldb/source/Interpreter/OptionValueArray.cpp @@ -75,6 +75,14 @@ void OptionValueArray::DumpValue(const ExecutionContext *exe_ctx, Stream &strm, } } +llvm::json::Value OptionValueArray::ToJSON(const ExecutionContext *exe_ctx) { + llvm::json::Array json_array; + const uint32_t size = m_values.size(); + for (uint32_t i = 0; i < size; ++i) + json_array.emplace_back(m_values[i]->ToJSON(exe_ctx)); + return json_array; +} + Status OptionValueArray::SetValueFromString(llvm::StringRef value, VarSetOperationType op) { Args args(value.str()); @@ -279,7 +287,7 @@ Status OptionValueArray::SetArgs(const Args &args, VarSetOperationType op) { case eVarSetOperationAssign: m_values.clear(); // Fall through to append case - LLVM_FALLTHROUGH; + [[fallthrough]]; case eVarSetOperationAppend: for (size_t i = 0; i < argc; ++i) { lldb::OptionValueSP value_sp(CreateValueFromCStringForTypeMask( diff --git a/contrib/llvm-project/lldb/source/Interpreter/OptionValueBoolean.cpp b/contrib/llvm-project/lldb/source/Interpreter/OptionValueBoolean.cpp index 62845c14bd13..4ac2ed5efe75 100644 --- a/contrib/llvm-project/lldb/source/Interpreter/OptionValueBoolean.cpp +++ b/contrib/llvm-project/lldb/source/Interpreter/OptionValueBoolean.cpp @@ -72,7 +72,7 @@ void OptionValueBoolean::AutoComplete(CommandInterpreter &interpreter, llvm::StringRef autocomplete_entries[] = {"true", "false", "on", "off", "yes", "no", "1", "0"}; - auto entries = llvm::makeArrayRef(autocomplete_entries); + auto entries = llvm::ArrayRef(autocomplete_entries); // only suggest "true" or "false" by default if (request.GetCursorArgumentPrefix().empty()) diff --git a/contrib/llvm-project/lldb/source/Interpreter/OptionValueDictionary.cpp b/contrib/llvm-project/lldb/source/Interpreter/OptionValueDictionary.cpp index 6baafc9213e1..d18510166eeb 100644 --- a/contrib/llvm-project/lldb/source/Interpreter/OptionValueDictionary.cpp +++ b/contrib/llvm-project/lldb/source/Interpreter/OptionValueDictionary.cpp @@ -83,6 +83,15 @@ void OptionValueDictionary::DumpValue(const ExecutionContext *exe_ctx, } } +llvm::json::Value +OptionValueDictionary::ToJSON(const ExecutionContext *exe_ctx) { + llvm::json::Object dict; + for (const auto &value : m_values) { + dict.try_emplace(value.first.GetCString(), value.second->ToJSON(exe_ctx)); + } + return dict; +} + size_t OptionValueDictionary::GetArgs(Args &args) const { args.Clear(); collection::const_iterator pos, end = m_values.end(); diff --git a/contrib/llvm-project/lldb/source/Interpreter/OptionValueFileSpecList.cpp b/contrib/llvm-project/lldb/source/Interpreter/OptionValueFileSpecList.cpp index 9b4114e2ceb2..b47feb9989dd 100644 --- a/contrib/llvm-project/lldb/source/Interpreter/OptionValueFileSpecList.cpp +++ b/contrib/llvm-project/lldb/source/Interpreter/OptionValueFileSpecList.cpp @@ -81,7 +81,7 @@ Status OptionValueFileSpecList::SetValueFromString(llvm::StringRef value, case eVarSetOperationAssign: m_current_value.Clear(); // Fall through to append case - LLVM_FALLTHROUGH; + [[fallthrough]]; case eVarSetOperationAppend: if (argc > 0) { m_value_was_set = true; diff --git a/contrib/llvm-project/lldb/source/Interpreter/OptionValueFormat.cpp b/contrib/llvm-project/lldb/source/Interpreter/OptionValueFormat.cpp index 76a446d1c3bc..ab89f673e96f 100644 --- a/contrib/llvm-project/lldb/source/Interpreter/OptionValueFormat.cpp +++ b/contrib/llvm-project/lldb/source/Interpreter/OptionValueFormat.cpp @@ -26,6 +26,10 @@ void OptionValueFormat::DumpValue(const ExecutionContext *exe_ctx, Stream &strm, } } +llvm::json::Value OptionValueFormat::ToJSON(const ExecutionContext *exe_ctx) { + return FormatManager::GetFormatAsCString(m_current_value); +} + Status OptionValueFormat::SetValueFromString(llvm::StringRef value, VarSetOperationType op) { Status error; diff --git a/contrib/llvm-project/lldb/source/Interpreter/OptionValueFormatEntity.cpp b/contrib/llvm-project/lldb/source/Interpreter/OptionValueFormatEntity.cpp index 64fcaf2cbc85..98216e13ad83 100644 --- a/contrib/llvm-project/lldb/source/Interpreter/OptionValueFormatEntity.cpp +++ b/contrib/llvm-project/lldb/source/Interpreter/OptionValueFormatEntity.cpp @@ -60,6 +60,13 @@ void OptionValueFormatEntity::DumpValue(const ExecutionContext *exe_ctx, } } +llvm::json::Value +OptionValueFormatEntity::ToJSON(const ExecutionContext *exe_ctx) { + std::string escaped; + EscapeBackticks(m_current_format, escaped); + return escaped; +} + Status OptionValueFormatEntity::SetValueFromString(llvm::StringRef value_str, VarSetOperationType op) { Status error; diff --git a/contrib/llvm-project/lldb/source/Interpreter/OptionValueLanguage.cpp b/contrib/llvm-project/lldb/source/Interpreter/OptionValueLanguage.cpp index d2fbe248300d..1be8a5585bc4 100644 --- a/contrib/llvm-project/lldb/source/Interpreter/OptionValueLanguage.cpp +++ b/contrib/llvm-project/lldb/source/Interpreter/OptionValueLanguage.cpp @@ -29,6 +29,10 @@ void OptionValueLanguage::DumpValue(const ExecutionContext *exe_ctx, } } +llvm::json::Value OptionValueLanguage::ToJSON(const ExecutionContext *exe_ctx) { + return Language::GetNameForLanguageType(m_current_value); +} + Status OptionValueLanguage::SetValueFromString(llvm::StringRef value, VarSetOperationType op) { Status error; diff --git a/contrib/llvm-project/lldb/source/Interpreter/OptionValuePathMappings.cpp b/contrib/llvm-project/lldb/source/Interpreter/OptionValuePathMappings.cpp index 6096f4564629..7cfc445f5580 100644 --- a/contrib/llvm-project/lldb/source/Interpreter/OptionValuePathMappings.cpp +++ b/contrib/llvm-project/lldb/source/Interpreter/OptionValuePathMappings.cpp @@ -34,6 +34,11 @@ void OptionValuePathMappings::DumpValue(const ExecutionContext *exe_ctx, } } +llvm::json::Value +OptionValuePathMappings::ToJSON(const ExecutionContext *exe_ctx) { + return m_path_mappings.ToJSON(); +} + Status OptionValuePathMappings::SetValueFromString(llvm::StringRef value, VarSetOperationType op) { Status error; @@ -91,7 +96,7 @@ Status OptionValuePathMappings::SetValueFromString(llvm::StringRef value, } m_path_mappings.Clear(m_notify_changes); // Fall through to append case - LLVM_FALLTHROUGH; + [[fallthrough]]; case eVarSetOperationAppend: if (argc < 2 || (argc & 1)) { error.SetErrorString("append operation takes one or more path pairs"); diff --git a/contrib/llvm-project/lldb/source/Interpreter/OptionValueProperties.cpp b/contrib/llvm-project/lldb/source/Interpreter/OptionValueProperties.cpp index b216557b808f..62590bb18869 100644 --- a/contrib/llvm-project/lldb/source/Interpreter/OptionValueProperties.cpp +++ b/contrib/llvm-project/lldb/source/Interpreter/OptionValueProperties.cpp @@ -248,16 +248,22 @@ bool OptionValueProperties::GetPropertyAtIndexAsArgs( return false; const OptionValueArgs *arguments = value->GetAsArgs(); - if (arguments) - return arguments->GetArgs(args); + if (arguments) { + arguments->GetArgs(args); + return true; + } const OptionValueArray *array = value->GetAsArray(); - if (array) - return array->GetArgs(args); + if (array) { + array->GetArgs(args); + return true; + } const OptionValueDictionary *dict = value->GetAsDictionary(); - if (dict) - return dict->GetArgs(args); + if (dict) { + dict->GetArgs(args); + return true; + } return false; } @@ -545,10 +551,26 @@ void OptionValueProperties::DumpValue(const ExecutionContext *exe_ctx, } } +llvm::json::Value +OptionValueProperties::ToJSON(const ExecutionContext *exe_ctx) { + llvm::json::Object json_properties; + const size_t num_properties = m_properties.size(); + for (size_t i = 0; i < num_properties; ++i) { + const Property *property = GetPropertyAtIndex(exe_ctx, false, i); + if (property) { + OptionValue *option_value = property->GetValue().get(); + assert(option_value); + json_properties.try_emplace(property->GetName(), + option_value->ToJSON(exe_ctx)); + } + } + return json_properties; +} + Status OptionValueProperties::DumpPropertyValue(const ExecutionContext *exe_ctx, Stream &strm, llvm::StringRef property_path, - uint32_t dump_mask) { + uint32_t dump_mask, bool is_json) { Status error; const bool will_modify = false; lldb::OptionValueSP value_sp( @@ -560,7 +582,10 @@ Status OptionValueProperties::DumpPropertyValue(const ExecutionContext *exe_ctx, if (dump_mask & ~eDumpOptionName) strm.PutChar(' '); } - value_sp->DumpValue(exe_ctx, strm, dump_mask); + if (is_json) { + strm.Printf("%s", llvm::formatv("{0:2}", value_sp->ToJSON(exe_ctx)).str().c_str()); + } else + value_sp->DumpValue(exe_ctx, strm, dump_mask); } return error; } diff --git a/contrib/llvm-project/lldb/source/Interpreter/Options.cpp b/contrib/llvm-project/lldb/source/Interpreter/Options.cpp index 26d9d2a17867..8cb386f95f43 100644 --- a/contrib/llvm-project/lldb/source/Interpreter/Options.cpp +++ b/contrib/llvm-project/lldb/source/Interpreter/Options.cpp @@ -238,7 +238,7 @@ Option *Options::GetLongOptions() { llvm::formatv( "option[{0}] --{1} has a short option {2:x} that " "conflicts with option[{3}] --{4}, short option won't " - "be used for --{5}n", + "be used for --{5}", (int)i, defs[i].long_option, short_opt, pos->second, m_getopt_table[pos->second].definition->long_option, defs[i].long_option) @@ -988,10 +988,10 @@ llvm::Expected<Args> Options::ParseAlias(const Args &args, .str(), llvm::inconvertibleErrorCode()); } - LLVM_FALLTHROUGH; + [[fallthrough]]; case OptionParser::eOptionalArgument: option_arg = OptionParser::GetOptionArgument(); - LLVM_FALLTHROUGH; + [[fallthrough]]; case OptionParser::eNoArgument: break; default: @@ -1002,37 +1002,50 @@ llvm::Expected<Args> Options::ParseAlias(const Args &args, .str(), llvm::inconvertibleErrorCode()); } - if (!option_arg) - option_arg = "<no-argument>"; - option_arg_vector->emplace_back(std::string(option_str.GetString()), - has_arg, std::string(option_arg)); - // Find option in the argument list; also see if it was supposed to take an // argument and if one was supplied. Remove option (and argument, if // given) from the argument list. Also remove them from the // raw_input_string, if one was passed in. + // Note: We also need to preserve any option argument values that were + // surrounded by backticks, as we lose track of them in the + // option_args_vector. size_t idx = FindArgumentIndexForOption(args_copy, long_options[long_options_index]); + std::string option_to_insert; + if (option_arg) { + if (idx != size_t(-1) && has_arg) { + bool arg_has_backtick = args_copy[idx + 1].GetQuoteChar() == '`'; + if (arg_has_backtick) + option_to_insert = "`"; + option_to_insert += option_arg; + if (arg_has_backtick) + option_to_insert += "`"; + } else + option_to_insert = option_arg; + } else + option_to_insert = CommandInterpreter::g_no_argument; + + option_arg_vector->emplace_back(std::string(option_str.GetString()), + has_arg, option_to_insert); + if (idx == size_t(-1)) continue; if (!input_line.empty()) { - auto tmp_arg = args_copy[idx].ref(); + llvm::StringRef tmp_arg = args_copy[idx].ref(); size_t pos = input_line.find(std::string(tmp_arg)); if (pos != std::string::npos) input_line.erase(pos, tmp_arg.size()); } args_copy.DeleteArgumentAtIndex(idx); - if ((long_options[long_options_index].definition->option_has_arg != - OptionParser::eNoArgument) && + if ((option_to_insert != CommandInterpreter::g_no_argument) && (OptionParser::GetOptionArgument() != nullptr) && (idx < args_copy.GetArgumentCount()) && (args_copy[idx].ref() == OptionParser::GetOptionArgument())) { if (input_line.size() > 0) { - auto tmp_arg = args_copy[idx].ref(); - size_t pos = input_line.find(std::string(tmp_arg)); + size_t pos = input_line.find(option_to_insert); if (pos != std::string::npos) - input_line.erase(pos, tmp_arg.size()); + input_line.erase(pos, option_to_insert.size()); } args_copy.DeleteArgumentAtIndex(idx); } @@ -1326,7 +1339,7 @@ llvm::Expected<Args> Options::Parse(const Args &args, // If the Option setting returned an error, we should stop parsing // and return the error. if (error.Fail()) - break; + break; } else { error.SetErrorStringWithFormat("invalid option with value '%i'", val); } diff --git a/contrib/llvm-project/lldb/source/Interpreter/ScriptInterpreter.cpp b/contrib/llvm-project/lldb/source/Interpreter/ScriptInterpreter.cpp index bc8a542afc87..2722666439bf 100644 --- a/contrib/llvm-project/lldb/source/Interpreter/ScriptInterpreter.cpp +++ b/contrib/llvm-project/lldb/source/Interpreter/ScriptInterpreter.cpp @@ -21,6 +21,7 @@ #include <cstdio> #include <cstdlib> #include <memory> +#include <optional> #include <string> using namespace lldb; @@ -28,10 +29,12 @@ using namespace lldb_private; ScriptInterpreter::ScriptInterpreter( Debugger &debugger, lldb::ScriptLanguage script_lang, - lldb::ScriptedProcessInterfaceUP scripted_process_interface_up) + lldb::ScriptedProcessInterfaceUP scripted_process_interface_up, + lldb::ScriptedPlatformInterfaceUP scripted_platform_interface_up) : m_debugger(debugger), m_script_lang(script_lang), - m_scripted_process_interface_up( - std::move(scripted_process_interface_up)) {} + m_scripted_process_interface_up(std::move(scripted_process_interface_up)), + m_scripted_platform_interface_up( + std::move(scripted_platform_interface_up)) {} void ScriptInterpreter::CollectDataForBreakpointCommandCallback( std::vector<std::reference_wrapper<BreakpointOptions>> &bp_options_vec, @@ -82,16 +85,16 @@ ScriptInterpreter::GetDataExtractorFromSBData(const lldb::SBData &data) const { Status ScriptInterpreter::GetStatusFromSBError(const lldb::SBError &error) const { if (error.m_opaque_up) - return *error.m_opaque_up.get(); + return *error.m_opaque_up; return Status(); } -llvm::Optional<MemoryRegionInfo> +std::optional<MemoryRegionInfo> ScriptInterpreter::GetOpaqueTypeFromSBMemoryRegionInfo( const lldb::SBMemoryRegionInfo &mem_region) const { if (!mem_region.m_opaque_up) - return llvm::None; + return std::nullopt; return *mem_region.m_opaque_up.get(); } diff --git a/contrib/llvm-project/lldb/source/Plugins/ABI/AArch64/ABIAArch64.cpp b/contrib/llvm-project/lldb/source/Plugins/ABI/AArch64/ABIAArch64.cpp index 6eba8afc8afd..9baab3a10c1f 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ABI/AArch64/ABIAArch64.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ABI/AArch64/ABIAArch64.cpp @@ -16,6 +16,7 @@ #include "lldb/Target/Process.h" #include <bitset> +#include <optional> LLDB_PLUGIN_DEFINE(ABIAArch64) @@ -81,11 +82,11 @@ uint32_t ABIAArch64::GetGenericNum(llvm::StringRef name) { static void addPartialRegisters( std::vector<lldb_private::DynamicRegisterInfo::Register> ®s, - llvm::ArrayRef<llvm::Optional<uint32_t>> full_reg_indices, + llvm::ArrayRef<std::optional<uint32_t>> full_reg_indices, uint32_t full_reg_size, const char *partial_reg_format, uint32_t partial_reg_size, lldb::Encoding encoding, lldb::Format format) { for (auto it : llvm::enumerate(full_reg_indices)) { - llvm::Optional<uint32_t> full_reg_index = it.value(); + std::optional<uint32_t> full_reg_index = it.value(); if (!full_reg_index || regs[*full_reg_index].byte_size != full_reg_size) return; @@ -114,8 +115,8 @@ void ABIAArch64::AugmentRegisterInfo( lldb_private::ConstString sp_string{"sp"}; - std::array<llvm::Optional<uint32_t>, 32> x_regs; - std::array<llvm::Optional<uint32_t>, 32> v_regs; + std::array<std::optional<uint32_t>, 32> x_regs; + std::array<std::optional<uint32_t>, 32> v_regs; for (auto it : llvm::enumerate(regs)) { lldb_private::DynamicRegisterInfo::Register &info = it.value(); diff --git a/contrib/llvm-project/lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.cpp b/contrib/llvm-project/lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.cpp index 9dfc50564e64..cce7c81bb06c 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.cpp @@ -8,6 +8,7 @@ #include "ABIMacOSX_arm64.h" +#include <optional> #include <vector> #include "llvm/ADT/STLExtras.h" @@ -141,7 +142,7 @@ bool ABIMacOSX_arm64::GetArgumentValues(Thread &thread, return false; CompilerType value_type = value->GetCompilerType(); - llvm::Optional<uint64_t> bit_size = value_type.GetBitSize(&thread); + std::optional<uint64_t> bit_size = value_type.GetBitSize(&thread); if (!bit_size) return false; @@ -304,7 +305,7 @@ ABIMacOSX_arm64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, if (byte_size <= 16) { if (byte_size <= RegisterValue::GetMaxByteSize()) { RegisterValue reg_value; - error = reg_value.SetValueFromData(v0_info, data, 0, true); + error = reg_value.SetValueFromData(*v0_info, data, 0, true); if (error.Success()) { if (!reg_ctx->WriteRegister(v0_info, reg_value)) error.SetErrorString("failed to write register v0"); @@ -331,7 +332,7 @@ ABIMacOSX_arm64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, if (v0_info) { if (byte_size <= v0_info->byte_size) { RegisterValue reg_value; - error = reg_value.SetValueFromData(v0_info, data, 0, true); + error = reg_value.SetValueFromData(*v0_info, data, 0, true); if (error.Success()) { if (!reg_ctx->WriteRegister(v0_info, reg_value)) error.SetErrorString("failed to write register v0"); @@ -494,7 +495,7 @@ static bool LoadValueFromConsecutiveGPRRegisters( uint32_t &NGRN, // NGRN (see ABI documentation) uint32_t &NSRN, // NSRN (see ABI documentation) DataExtractor &data) { - llvm::Optional<uint64_t> byte_size = + std::optional<uint64_t> byte_size = value_type.GetByteSize(exe_ctx.GetBestExecutionContextScope()); if (!byte_size || *byte_size == 0) return false; @@ -512,7 +513,7 @@ static bool LoadValueFromConsecutiveGPRRegisters( if (NSRN < 8 && (8 - NSRN) >= homogeneous_count) { if (!base_type) return false; - llvm::Optional<uint64_t> base_byte_size = + std::optional<uint64_t> base_byte_size = base_type.GetByteSize(exe_ctx.GetBestExecutionContextScope()); if (!base_byte_size) return false; @@ -537,8 +538,8 @@ static bool LoadValueFromConsecutiveGPRRegisters( // Make sure we have enough room in "heap_data_up" if ((data_offset + *base_byte_size) <= heap_data_up->GetByteSize()) { const size_t bytes_copied = reg_value.GetAsMemoryData( - reg_info, heap_data_up->GetBytes() + data_offset, *base_byte_size, - byte_order, error); + *reg_info, heap_data_up->GetBytes() + data_offset, + *base_byte_size, byte_order, error); if (bytes_copied != *base_byte_size) return false; data_offset += bytes_copied; @@ -577,7 +578,7 @@ static bool LoadValueFromConsecutiveGPRRegisters( const size_t curr_byte_size = std::min<size_t>(8, bytes_left); const size_t bytes_copied = reg_value.GetAsMemoryData( - reg_info, heap_data_up->GetBytes() + data_offset, curr_byte_size, + *reg_info, heap_data_up->GetBytes() + data_offset, curr_byte_size, byte_order, error); if (bytes_copied == 0) return false; @@ -612,9 +613,6 @@ static bool LoadValueFromConsecutiveGPRRegisters( ++NGRN; } - if (reg_info == nullptr) - return false; - const lldb::addr_t value_addr = reg_ctx->ReadRegisterAsUnsigned(reg_info, LLDB_INVALID_ADDRESS); @@ -650,8 +648,7 @@ ValueObjectSP ABIMacOSX_arm64::GetReturnValueObjectImpl( if (!reg_ctx) return return_valobj_sp; - llvm::Optional<uint64_t> byte_size = - return_compiler_type.GetByteSize(&thread); + std::optional<uint64_t> byte_size = return_compiler_type.GetByteSize(&thread); if (!byte_size) return return_valobj_sp; @@ -692,10 +689,10 @@ ValueObjectSP ABIMacOSX_arm64::GetReturnValueObjectImpl( reg_ctx->ReadRegister(x1_reg_info, x1_reg_value)) { Status error; if (x0_reg_value.GetAsMemoryData( - x0_reg_info, heap_data_up->GetBytes() + 0, 8, + *x0_reg_info, heap_data_up->GetBytes() + 0, 8, byte_order, error) && x1_reg_value.GetAsMemoryData( - x1_reg_info, heap_data_up->GetBytes() + 8, 8, + *x1_reg_info, heap_data_up->GetBytes() + 8, 8, byte_order, error)) { DataExtractor data( DataBufferSP(heap_data_up.release()), byte_order, @@ -788,7 +785,7 @@ ValueObjectSP ABIMacOSX_arm64::GetReturnValueObjectImpl( RegisterValue reg_value; if (reg_ctx->ReadRegister(v0_info, reg_value)) { Status error; - if (reg_value.GetAsMemoryData(v0_info, heap_data_up->GetBytes(), + if (reg_value.GetAsMemoryData(*v0_info, heap_data_up->GetBytes(), heap_data_up->GetByteSize(), byte_order, error)) { DataExtractor data(DataBufferSP(heap_data_up.release()), diff --git a/contrib/llvm-project/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.cpp b/contrib/llvm-project/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.cpp index 2896f5920db9..d46545a93583 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.cpp @@ -8,6 +8,7 @@ #include "ABISysV_arm64.h" +#include <optional> #include <vector> #include "llvm/ADT/STLExtras.h" @@ -146,7 +147,7 @@ bool ABISysV_arm64::GetArgumentValues(Thread &thread, ValueList &values) const { if (value_type) { bool is_signed = false; size_t bit_width = 0; - llvm::Optional<uint64_t> bit_size = value_type.GetBitSize(&thread); + std::optional<uint64_t> bit_size = value_type.GetBitSize(&thread); if (!bit_size) return false; if (value_type.IsIntegerOrEnumerationType(is_signed)) { @@ -277,7 +278,7 @@ Status ABISysV_arm64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, if (byte_size <= 16) { if (byte_size <= RegisterValue::GetMaxByteSize()) { RegisterValue reg_value; - error = reg_value.SetValueFromData(v0_info, data, 0, true); + error = reg_value.SetValueFromData(*v0_info, data, 0, true); if (error.Success()) { if (!reg_ctx->WriteRegister(v0_info, reg_value)) error.SetErrorString("failed to write register v0"); @@ -304,7 +305,7 @@ Status ABISysV_arm64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, if (v0_info) { if (byte_size <= v0_info->byte_size) { RegisterValue reg_value; - error = reg_value.SetValueFromData(v0_info, data, 0, true); + error = reg_value.SetValueFromData(*v0_info, data, 0, true); if (error.Success()) { if (!reg_ctx->WriteRegister(v0_info, reg_value)) error.SetErrorString("failed to write register v0"); @@ -468,7 +469,7 @@ static bool LoadValueFromConsecutiveGPRRegisters( uint32_t &NGRN, // NGRN (see ABI documentation) uint32_t &NSRN, // NSRN (see ABI documentation) DataExtractor &data) { - llvm::Optional<uint64_t> byte_size = + std::optional<uint64_t> byte_size = value_type.GetByteSize(exe_ctx.GetBestExecutionContextScope()); if (byte_size || *byte_size == 0) @@ -487,7 +488,7 @@ static bool LoadValueFromConsecutiveGPRRegisters( if (NSRN < 8 && (8 - NSRN) >= homogeneous_count) { if (!base_type) return false; - llvm::Optional<uint64_t> base_byte_size = + std::optional<uint64_t> base_byte_size = base_type.GetByteSize(exe_ctx.GetBestExecutionContextScope()); if (!base_byte_size) return false; @@ -512,8 +513,8 @@ static bool LoadValueFromConsecutiveGPRRegisters( // Make sure we have enough room in "heap_data_up" if ((data_offset + *base_byte_size) <= heap_data_up->GetByteSize()) { const size_t bytes_copied = reg_value.GetAsMemoryData( - reg_info, heap_data_up->GetBytes() + data_offset, *base_byte_size, - byte_order, error); + *reg_info, heap_data_up->GetBytes() + data_offset, + *base_byte_size, byte_order, error); if (bytes_copied != *base_byte_size) return false; data_offset += bytes_copied; @@ -548,7 +549,7 @@ static bool LoadValueFromConsecutiveGPRRegisters( const size_t curr_byte_size = std::min<size_t>(8, bytes_left); const size_t bytes_copied = reg_value.GetAsMemoryData( - reg_info, heap_data_up->GetBytes() + data_offset, curr_byte_size, + *reg_info, heap_data_up->GetBytes() + data_offset, curr_byte_size, byte_order, error); if (bytes_copied == 0) return false; @@ -582,9 +583,6 @@ static bool LoadValueFromConsecutiveGPRRegisters( ++NGRN; } - if (reg_info == nullptr) - return false; - const lldb::addr_t value_addr = reg_ctx->ReadRegisterAsUnsigned(reg_info, LLDB_INVALID_ADDRESS); @@ -620,8 +618,7 @@ ValueObjectSP ABISysV_arm64::GetReturnValueObjectImpl( if (!reg_ctx) return return_valobj_sp; - llvm::Optional<uint64_t> byte_size = - return_compiler_type.GetByteSize(&thread); + std::optional<uint64_t> byte_size = return_compiler_type.GetByteSize(&thread); if (!byte_size) return return_valobj_sp; @@ -664,10 +661,10 @@ ValueObjectSP ABISysV_arm64::GetReturnValueObjectImpl( reg_ctx->ReadRegister(x1_reg_info, x1_reg_value)) { Status error; if (x0_reg_value.GetAsMemoryData( - x0_reg_info, heap_data_up->GetBytes() + 0, 8, + *x0_reg_info, heap_data_up->GetBytes() + 0, 8, byte_order, error) && x1_reg_value.GetAsMemoryData( - x1_reg_info, heap_data_up->GetBytes() + 8, 8, + *x1_reg_info, heap_data_up->GetBytes() + 8, 8, byte_order, error)) { DataExtractor data( DataBufferSP(heap_data_up.release()), byte_order, @@ -758,7 +755,7 @@ ValueObjectSP ABISysV_arm64::GetReturnValueObjectImpl( RegisterValue reg_value; if (reg_ctx->ReadRegister(v0_info, reg_value)) { Status error; - if (reg_value.GetAsMemoryData(v0_info, heap_data_up->GetBytes(), + if (reg_value.GetAsMemoryData(*v0_info, heap_data_up->GetBytes(), heap_data_up->GetByteSize(), byte_order, error)) { DataExtractor data(DataBufferSP(heap_data_up.release()), byte_order, diff --git a/contrib/llvm-project/lldb/source/Plugins/ABI/ARC/ABISysV_arc.cpp b/contrib/llvm-project/lldb/source/Plugins/ABI/ARC/ABISysV_arc.cpp index a9c7af145338..3386acd9080f 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ABI/ARC/ABISysV_arc.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ABI/ARC/ABISysV_arc.cpp @@ -151,7 +151,7 @@ bool ABISysV_arc::IsRegisterFileReduced(RegisterContext ®_ctx) const { /*fail_value*/ 0); // RF_BUILD "Number of Entries" bit. const uint32_t rf_entries_bit = 1U << 9U; - m_is_reg_file_reduced = (reg_value | rf_entries_bit) != 0; + m_is_reg_file_reduced = (reg_value & rf_entries_bit) != 0; } return m_is_reg_file_reduced.value_or(false); @@ -271,7 +271,7 @@ bool ABISysV_arc::PrepareTrivialCall(Thread &thread, addr_t sp, addr_t pc, reg_value[byte_index++] = 0; } - RegisterValue reg_val_obj(llvm::makeArrayRef(reg_value, reg_size), + RegisterValue reg_val_obj(llvm::ArrayRef(reg_value, reg_size), eByteOrderLittle); if (!reg_ctx->WriteRegister( reg_ctx->GetRegisterInfo(eRegisterKindGeneric, reg_index), diff --git a/contrib/llvm-project/lldb/source/Plugins/ABI/ARC/ABISysV_arc.h b/contrib/llvm-project/lldb/source/Plugins/ABI/ARC/ABISysV_arc.h index 9bf75dfe6add..de513453f2a2 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ABI/ARC/ABISysV_arc.h +++ b/contrib/llvm-project/lldb/source/Plugins/ABI/ARC/ABISysV_arc.h @@ -10,7 +10,7 @@ #define liblldb_ABISysV_arc_h_ // Other libraries and framework includes -#include <llvm/ADT/Optional.h> +#include <optional> // Project includes #include "lldb/Target/ABI.h" @@ -97,7 +97,7 @@ private: using lldb_private::RegInfoBasedABI::RegInfoBasedABI; // Call CreateInstance instead. - using RegisterFileFlag = llvm::Optional<bool>; + using RegisterFileFlag = std::optional<bool>; mutable RegisterFileFlag m_is_reg_file_reduced; }; diff --git a/contrib/llvm-project/lldb/source/Plugins/ABI/ARM/ABIMacOSX_arm.cpp b/contrib/llvm-project/lldb/source/Plugins/ABI/ARM/ABIMacOSX_arm.cpp index a8d1cbc675e3..3b6c0955371e 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ABI/ARM/ABIMacOSX_arm.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ABI/ARM/ABIMacOSX_arm.cpp @@ -8,6 +8,7 @@ #include "ABIMacOSX_arm.h" +#include <optional> #include <vector> #include "llvm/ADT/STLExtras.h" @@ -1186,8 +1187,7 @@ static const RegisterInfo g_register_infos[] = { nullptr, }}; -static const uint32_t k_num_register_infos = - llvm::array_lengthof(g_register_infos); +static const uint32_t k_num_register_infos = std::size(g_register_infos); const lldb_private::RegisterInfo * ABIMacOSX_arm::GetRegisterInfoArray(uint32_t &count) { @@ -1235,7 +1235,7 @@ bool ABIMacOSX_arm::PrepareTrivialCall(Thread &thread, addr_t sp, llvm::ArrayRef<addr_t>::iterator ai = args.begin(), ae = args.end(); - for (size_t i = 0; i < llvm::array_lengthof(reg_names); ++i) { + for (size_t i = 0; i < std::size(reg_names); ++i) { if (ai == ae) break; @@ -1349,7 +1349,7 @@ bool ABIMacOSX_arm::GetArgumentValues(Thread &thread, ValueList &values) const { if (compiler_type) { bool is_signed = false; size_t bit_width = 0; - llvm::Optional<uint64_t> bit_size = compiler_type.GetBitSize(&thread); + std::optional<uint64_t> bit_size = compiler_type.GetBitSize(&thread); if (!bit_size) return false; if (compiler_type.IsIntegerOrEnumerationType(is_signed)) @@ -1455,7 +1455,7 @@ ValueObjectSP ABIMacOSX_arm::GetReturnValueObjectImpl( const RegisterInfo *r0_reg_info = reg_ctx->GetRegisterInfoByName("r0", 0); if (compiler_type.IsIntegerOrEnumerationType(is_signed)) { - llvm::Optional<uint64_t> bit_width = compiler_type.GetBitSize(&thread); + std::optional<uint64_t> bit_width = compiler_type.GetBitSize(&thread); if (!bit_width) return return_valobj_sp; @@ -1475,7 +1475,7 @@ ValueObjectSP ABIMacOSX_arm::GetReturnValueObjectImpl( const RegisterInfo *r3_reg_info = reg_ctx->GetRegisterInfoByName("r3", 0); if (r1_reg_info && r2_reg_info && r3_reg_info) { - llvm::Optional<uint64_t> byte_size = + std::optional<uint64_t> byte_size = compiler_type.GetByteSize(&thread); if (!byte_size) return return_valobj_sp; @@ -1496,16 +1496,16 @@ ValueObjectSP ABIMacOSX_arm::GetReturnValueObjectImpl( reg_ctx->ReadRegister(r2_reg_info, r2_reg_value) && reg_ctx->ReadRegister(r3_reg_info, r3_reg_value)) { Status error; - if (r0_reg_value.GetAsMemoryData(r0_reg_info, + if (r0_reg_value.GetAsMemoryData(*r0_reg_info, heap_data_up->GetBytes() + 0, 4, byte_order, error) && - r1_reg_value.GetAsMemoryData(r1_reg_info, + r1_reg_value.GetAsMemoryData(*r1_reg_info, heap_data_up->GetBytes() + 4, 4, byte_order, error) && - r2_reg_value.GetAsMemoryData(r2_reg_info, + r2_reg_value.GetAsMemoryData(*r2_reg_info, heap_data_up->GetBytes() + 8, 4, byte_order, error) && - r3_reg_value.GetAsMemoryData(r3_reg_info, + r3_reg_value.GetAsMemoryData(*r3_reg_info, heap_data_up->GetBytes() + 12, 4, byte_order, error)) { DataExtractor data(DataBufferSP(heap_data_up.release()), diff --git a/contrib/llvm-project/lldb/source/Plugins/ABI/ARM/ABISysV_arm.cpp b/contrib/llvm-project/lldb/source/Plugins/ABI/ARM/ABISysV_arm.cpp index ecc5f6ffd288..218af1dca2c0 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ABI/ARM/ABISysV_arm.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ABI/ARM/ABISysV_arm.cpp @@ -8,6 +8,7 @@ #include "ABISysV_arm.h" +#include <optional> #include <vector> #include "llvm/ADT/STLExtras.h" @@ -1189,8 +1190,7 @@ static const RegisterInfo g_register_infos[] = { nullptr, }}; -static const uint32_t k_num_register_infos = - llvm::array_lengthof(g_register_infos); +static const uint32_t k_num_register_infos = std::size(g_register_infos); const lldb_private::RegisterInfo * ABISysV_arm::GetRegisterInfoArray(uint32_t &count) { @@ -1240,7 +1240,7 @@ bool ABISysV_arm::PrepareTrivialCall(Thread &thread, addr_t sp, llvm::ArrayRef<addr_t>::iterator ai = args.begin(), ae = args.end(); - for (size_t i = 0; i < llvm::array_lengthof(reg_names); ++i) { + for (size_t i = 0; i < std::size(reg_names); ++i) { if (ai == ae) break; @@ -1354,7 +1354,7 @@ bool ABISysV_arm::GetArgumentValues(Thread &thread, ValueList &values) const { size_t bit_width = 0; if (compiler_type.IsIntegerOrEnumerationType(is_signed) || compiler_type.IsPointerOrReferenceType()) { - if (llvm::Optional<uint64_t> size = compiler_type.GetBitSize(&thread)) + if (std::optional<uint64_t> size = compiler_type.GetBitSize(&thread)) bit_width = *size; } else { // We only handle integer, pointer and reference types currently... @@ -1461,8 +1461,8 @@ ValueObjectSP ABISysV_arm::GetReturnValueObjectImpl( const RegisterInfo *r0_reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1); - llvm::Optional<uint64_t> bit_width = compiler_type.GetBitSize(&thread); - llvm::Optional<uint64_t> byte_size = compiler_type.GetByteSize(&thread); + std::optional<uint64_t> bit_width = compiler_type.GetBitSize(&thread); + std::optional<uint64_t> byte_size = compiler_type.GetByteSize(&thread); if (!bit_width || !byte_size) return return_valobj_sp; @@ -1539,7 +1539,7 @@ ValueObjectSP ABISysV_arm::GetReturnValueObjectImpl( default: return return_valobj_sp; case 64: { - static_assert(sizeof(double) == sizeof(uint64_t), ""); + static_assert(sizeof(double) == sizeof(uint64_t)); if (IsArmHardFloat(thread)) { RegisterValue reg_value; @@ -1563,7 +1563,7 @@ ValueObjectSP ABISysV_arm::GetReturnValueObjectImpl( } case 16: // Half precision returned after a conversion to single precision case 32: { - static_assert(sizeof(float) == sizeof(uint32_t), ""); + static_assert(sizeof(float) == sizeof(uint32_t)); if (IsArmHardFloat(thread)) { RegisterValue reg_value; @@ -1598,8 +1598,7 @@ ValueObjectSP ABISysV_arm::GetReturnValueObjectImpl( compiler_type.IsHomogeneousAggregate(&base_type); if (homogeneous_count > 0 && homogeneous_count <= 4) { - llvm::Optional<uint64_t> base_byte_size = - base_type.GetByteSize(&thread); + std::optional<uint64_t> base_byte_size = base_type.GetByteSize(&thread); if (base_type.IsVectorType()) { if (base_byte_size && (*base_byte_size == 8 || *base_byte_size == 16)) { @@ -1627,7 +1626,7 @@ ValueObjectSP ABISysV_arm::GetReturnValueObjectImpl( nullptr, nullptr); if (base_type.IsFloatingPointType(float_count, is_complex)) { - llvm::Optional<uint64_t> base_byte_size = + std::optional<uint64_t> base_byte_size = base_type.GetByteSize(&thread); if (float_count == 2 && is_complex) { if (index != 0 && base_byte_size && @@ -1694,7 +1693,7 @@ ValueObjectSP ABISysV_arm::GetReturnValueObjectImpl( if ((data_offset + vfp_byte_size) <= data_sp->GetByteSize()) { Status error; const size_t bytes_copied = reg_value.GetAsMemoryData( - reg_info, data_sp->GetBytes() + data_offset, vfp_byte_size, + *reg_info, data_sp->GetBytes() + data_offset, vfp_byte_size, byte_order, error); if (bytes_copied != vfp_byte_size) break; diff --git a/contrib/llvm-project/lldb/source/Plugins/ABI/Mips/ABISysV_mips.cpp b/contrib/llvm-project/lldb/source/Plugins/ABI/Mips/ABISysV_mips.cpp index 9d8ef339432d..a94be159cbbd 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ABI/Mips/ABISysV_mips.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ABI/Mips/ABISysV_mips.cpp @@ -29,6 +29,7 @@ #include "lldb/Utility/Log.h" #include "lldb/Utility/RegisterValue.h" #include "lldb/Utility/Status.h" +#include <optional> using namespace lldb; using namespace lldb_private; @@ -503,8 +504,7 @@ static const RegisterInfo g_register_infos[] = { }, }; -static const uint32_t k_num_register_infos = - llvm::array_lengthof(g_register_infos); +static const uint32_t k_num_register_infos = std::size(g_register_infos); const lldb_private::RegisterInfo * ABISysV_mips::GetRegisterInfoArray(uint32_t &count) { @@ -560,7 +560,7 @@ bool ABISysV_mips::PrepareTrivialCall(Thread &thread, addr_t sp, llvm::ArrayRef<addr_t>::iterator ai = args.begin(), ae = args.end(); // Write arguments to registers - for (size_t i = 0; i < llvm::array_lengthof(reg_names); ++i) { + for (size_t i = 0; i < std::size(reg_names); ++i) { if (ai == ae) break; @@ -768,7 +768,7 @@ ValueObjectSP ABISysV_mips::GetReturnValueObjectImpl( // In MIPS register "r2" (v0) holds the integer function return values const RegisterInfo *r2_reg_info = reg_ctx->GetRegisterInfoByName("r2", 0); - llvm::Optional<uint64_t> bit_width = return_compiler_type.GetBitSize(&thread); + std::optional<uint64_t> bit_width = return_compiler_type.GetBitSize(&thread); if (!bit_width) return return_valobj_sp; if (return_compiler_type.IsIntegerOrEnumerationType(is_signed)) { @@ -835,11 +835,11 @@ ValueObjectSP ABISysV_mips::GetReturnValueObjectImpl( default: return return_valobj_sp; case 32: - static_assert(sizeof(float) == sizeof(uint32_t), ""); + static_assert(sizeof(float) == sizeof(uint32_t)); value.GetScalar() = *((float *)(&raw_value)); break; case 64: - static_assert(sizeof(double) == sizeof(uint64_t), ""); + static_assert(sizeof(double) == sizeof(uint64_t)); const RegisterInfo *r3_reg_info = reg_ctx->GetRegisterInfoByName("r3", 0); if (target_byte_order == eByteOrderLittle) @@ -867,7 +867,7 @@ ValueObjectSP ABISysV_mips::GetReturnValueObjectImpl( default: return return_valobj_sp; case 64: { - static_assert(sizeof(double) == sizeof(uint64_t), ""); + static_assert(sizeof(double) == sizeof(uint64_t)); const RegisterInfo *f1_info = reg_ctx->GetRegisterInfoByName("f1", 0); RegisterValue f1_value; DataExtractor f1_data; @@ -899,7 +899,7 @@ ValueObjectSP ABISysV_mips::GetReturnValueObjectImpl( break; } case 32: { - static_assert(sizeof(float) == sizeof(uint32_t), ""); + static_assert(sizeof(float) == sizeof(uint32_t)); value.GetScalar() = (float)f0_data.GetFloat(&offset); break; } diff --git a/contrib/llvm-project/lldb/source/Plugins/ABI/Mips/ABISysV_mips64.cpp b/contrib/llvm-project/lldb/source/Plugins/ABI/Mips/ABISysV_mips64.cpp index 24571ead527f..97b8e61a9b92 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ABI/Mips/ABISysV_mips64.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ABI/Mips/ABISysV_mips64.cpp @@ -29,6 +29,7 @@ #include "lldb/Utility/Log.h" #include "lldb/Utility/RegisterValue.h" #include "lldb/Utility/Status.h" +#include <optional> using namespace lldb; using namespace lldb_private; @@ -503,8 +504,7 @@ static const RegisterInfo g_register_infos_mips64[] = { }, }; -static const uint32_t k_num_register_infos = - llvm::array_lengthof(g_register_infos_mips64); +static const uint32_t k_num_register_infos = std::size(g_register_infos_mips64); const lldb_private::RegisterInfo * ABISysV_mips64::GetRegisterInfoArray(uint32_t &count) { @@ -715,8 +715,7 @@ ValueObjectSP ABISysV_mips64::GetReturnValueObjectImpl( Target *target = exe_ctx.GetTargetPtr(); const ArchSpec target_arch = target->GetArchitecture(); ByteOrder target_byte_order = target_arch.GetByteOrder(); - llvm::Optional<uint64_t> byte_size = - return_compiler_type.GetByteSize(&thread); + std::optional<uint64_t> byte_size = return_compiler_type.GetByteSize(&thread); if (!byte_size) return return_valobj_sp; const uint32_t type_flags = return_compiler_type.GetTypeInfo(nullptr); @@ -725,6 +724,7 @@ ValueObjectSP ABISysV_mips64::GetReturnValueObjectImpl( const RegisterInfo *r2_info = reg_ctx->GetRegisterInfoByName("r2", 0); const RegisterInfo *r3_info = reg_ctx->GetRegisterInfoByName("r3", 0); + assert(r2_info && r3_info && "Basic registers should always be present."); if (type_flags & eTypeIsScalar || type_flags & eTypeIsPointer) { value.SetValueType(Value::ValueType::Scalar); @@ -924,7 +924,7 @@ ValueObjectSP ABISysV_mips64::GetReturnValueObjectImpl( CompilerType field_compiler_type = return_compiler_type.GetFieldAtIndex( idx, name, &field_bit_offset, nullptr, nullptr); - llvm::Optional<uint64_t> field_byte_width = + std::optional<uint64_t> field_byte_width = field_compiler_type.GetByteSize(&thread); if (!field_byte_width) return return_valobj_sp; @@ -996,7 +996,7 @@ ValueObjectSP ABISysV_mips64::GetReturnValueObjectImpl( CompilerType field_compiler_type = return_compiler_type.GetFieldAtIndex( idx, name, &field_bit_offset, nullptr, nullptr); - llvm::Optional<uint64_t> field_byte_width = + std::optional<uint64_t> field_byte_width = field_compiler_type.GetByteSize(&thread); // if we don't know the size of the field (e.g. invalid type), just @@ -1055,8 +1055,8 @@ ValueObjectSP ABISysV_mips64::GetReturnValueObjectImpl( reg_ctx->ReadRegister(r2_info, r2_value); const size_t bytes_copied = r2_value.GetAsMemoryData( - r2_info, data_sp->GetBytes(), r2_info->byte_size, target_byte_order, - error); + *r2_info, data_sp->GetBytes(), r2_info->byte_size, + target_byte_order, error); if (bytes_copied != r2_info->byte_size) return return_valobj_sp; sucess = true; @@ -1064,7 +1064,7 @@ ValueObjectSP ABISysV_mips64::GetReturnValueObjectImpl( if (use_r3) { reg_ctx->ReadRegister(r3_info, r3_value); const size_t bytes_copied = r3_value.GetAsMemoryData( - r3_info, data_sp->GetBytes() + r2_info->byte_size, + *r3_info, data_sp->GetBytes() + r2_info->byte_size, r3_info->byte_size, target_byte_order, error); if (bytes_copied != r3_info->byte_size) diff --git a/contrib/llvm-project/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc.cpp b/contrib/llvm-project/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc.cpp index 1ef3b8ca3961..8879b57bed0c 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc.cpp @@ -29,6 +29,7 @@ #include "lldb/Utility/Log.h" #include "lldb/Utility/RegisterValue.h" #include "lldb/Utility/Status.h" +#include <optional> using namespace lldb; using namespace lldb_private; @@ -204,8 +205,7 @@ static const RegisterInfo g_register_infos[] = { nullptr, }}; -static const uint32_t k_num_register_infos = - llvm::array_lengthof(g_register_infos); +static const uint32_t k_num_register_infos = std::size(g_register_infos); const lldb_private::RegisterInfo * ABISysV_ppc::GetRegisterInfoArray(uint32_t &count) { @@ -394,7 +394,7 @@ bool ABISysV_ppc::GetArgumentValues(Thread &thread, ValueList &values) const { // We currently only support extracting values with Clang QualTypes. Do we // care about others? CompilerType compiler_type = value->GetCompilerType(); - llvm::Optional<uint64_t> bit_size = compiler_type.GetBitSize(&thread); + std::optional<uint64_t> bit_size = compiler_type.GetBitSize(&thread); if (!bit_size) return false; bool is_signed; @@ -462,7 +462,7 @@ Status ABISysV_ppc::SetReturnValueObject(lldb::StackFrameSP &frame_sp, error.SetErrorString( "We don't support returning complex values at present"); else { - llvm::Optional<uint64_t> bit_width = + std::optional<uint64_t> bit_width = compiler_type.GetBitSize(frame_sp.get()); if (!bit_width) { error.SetErrorString("can't get type size"); @@ -526,7 +526,7 @@ ValueObjectSP ABISysV_ppc::GetReturnValueObjectSimple( if (type_flags & eTypeIsInteger) { // Extract the register context so we can read arguments from registers - llvm::Optional<uint64_t> byte_size = + std::optional<uint64_t> byte_size = return_compiler_type.GetByteSize(&thread); if (!byte_size) return return_valobj_sp; @@ -573,7 +573,7 @@ ValueObjectSP ABISysV_ppc::GetReturnValueObjectSimple( if (type_flags & eTypeIsComplex) { // Don't handle complex yet. } else { - llvm::Optional<uint64_t> byte_size = + std::optional<uint64_t> byte_size = return_compiler_type.GetByteSize(&thread); if (byte_size && *byte_size <= sizeof(long double)) { const RegisterInfo *f1_info = reg_ctx->GetRegisterInfoByName("f1", 0); @@ -607,7 +607,7 @@ ValueObjectSP ABISysV_ppc::GetReturnValueObjectSimple( return_valobj_sp = ValueObjectConstResult::Create( thread.GetStackFrameAtIndex(0).get(), value, ConstString("")); } else if (type_flags & eTypeIsVector) { - llvm::Optional<uint64_t> byte_size = + std::optional<uint64_t> byte_size = return_compiler_type.GetByteSize(&thread); if (byte_size && *byte_size > 0) { const RegisterInfo *altivec_reg = reg_ctx->GetRegisterInfoByName("v2", 0); @@ -622,7 +622,7 @@ ValueObjectSP ABISysV_ppc::GetReturnValueObjectSimple( if (reg_ctx->ReadRegister(altivec_reg, reg_value)) { Status error; if (reg_value.GetAsMemoryData( - altivec_reg, heap_data_up->GetBytes(), + *altivec_reg, heap_data_up->GetBytes(), heap_data_up->GetByteSize(), byte_order, error)) { DataExtractor data(DataBufferSP(heap_data_up.release()), byte_order, @@ -658,7 +658,7 @@ ValueObjectSP ABISysV_ppc::GetReturnValueObjectImpl( if (!reg_ctx_sp) return return_valobj_sp; - llvm::Optional<uint64_t> bit_width = return_compiler_type.GetBitSize(&thread); + std::optional<uint64_t> bit_width = return_compiler_type.GetBitSize(&thread); if (!bit_width) return return_valobj_sp; if (return_compiler_type.IsAggregateType()) { @@ -700,7 +700,7 @@ ValueObjectSP ABISysV_ppc::GetReturnValueObjectImpl( CompilerType field_compiler_type = return_compiler_type.GetFieldAtIndex( idx, name, &field_bit_offset, nullptr, nullptr); - llvm::Optional<uint64_t> field_bit_width = + std::optional<uint64_t> field_bit_width = field_compiler_type.GetBitSize(&thread); if (!field_bit_width) return return_valobj_sp; diff --git a/contrib/llvm-project/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc64.cpp b/contrib/llvm-project/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc64.cpp index e6f030891d1f..bb4b4e037774 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc64.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc64.cpp @@ -44,6 +44,7 @@ #define DECLARE_REGISTER_INFOS_PPC64LE_STRUCT #include "Plugins/Process/Utility/RegisterInfos_ppc64le.h" #undef DECLARE_REGISTER_INFOS_PPC64LE_STRUCT +#include <optional> using namespace lldb; using namespace lldb_private; @@ -53,10 +54,10 @@ LLDB_PLUGIN_DEFINE(ABISysV_ppc64) const lldb_private::RegisterInfo * ABISysV_ppc64::GetRegisterInfoArray(uint32_t &count) { if (GetByteOrder() == lldb::eByteOrderLittle) { - count = llvm::array_lengthof(g_register_infos_ppc64le); + count = std::size(g_register_infos_ppc64le); return g_register_infos_ppc64le; } else { - count = llvm::array_lengthof(g_register_infos_ppc64); + count = std::size(g_register_infos_ppc64); return g_register_infos_ppc64; } } @@ -271,7 +272,7 @@ bool ABISysV_ppc64::GetArgumentValues(Thread &thread, ValueList &values) const { // We currently only support extracting values with Clang QualTypes. Do we // care about others? CompilerType compiler_type = value->GetCompilerType(); - llvm::Optional<uint64_t> bit_size = compiler_type.GetBitSize(&thread); + std::optional<uint64_t> bit_size = compiler_type.GetBitSize(&thread); if (!bit_size) return false; bool is_signed; @@ -341,7 +342,7 @@ Status ABISysV_ppc64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, error.SetErrorString( "We don't support returning complex values at present"); else { - llvm::Optional<uint64_t> bit_width = + std::optional<uint64_t> bit_width = compiler_type.GetBitSize(frame_sp.get()); if (!bit_width) { error.SetErrorString("can't get size of type"); @@ -463,7 +464,7 @@ class ReturnValueExtractor { Status error; uint32_t rc = reg_val.GetAsMemoryData( - reg_info, &raw_data, sizeof(raw_data), m_byte_order, error); + *reg_info, &raw_data, sizeof(raw_data), m_byte_order, error); if (rc != sizeof(raw_data)) { LLDB_LOG(m_log, LOG_PREFIX "GetAsMemoryData() failed"); return false; @@ -643,7 +644,7 @@ private: DataExtractor de(&raw_data, sizeof(raw_data), m_byte_order, m_addr_size); offset_t offset = 0; - llvm::Optional<uint64_t> byte_size = type.GetByteSize(m_process_sp.get()); + std::optional<uint64_t> byte_size = type.GetByteSize(m_process_sp.get()); if (!byte_size) return {}; switch (*byte_size) { @@ -727,7 +728,7 @@ private: LLDB_LOG(m_log, LOG_PREFIX "Failed to read vector register contents"); return ValueObjectSP(); } - if (!vr_val[i].GetAsMemoryData(vr[i], vr_data->GetBytes() + i * vr_size, + if (!vr_val[i].GetAsMemoryData(*vr[i], vr_data->GetBytes() + i * vr_size, vr_size, m_byte_order, error)) { LLDB_LOG(m_log, LOG_PREFIX "Failed to extract vector register bytes"); return ValueObjectSP(); @@ -777,7 +778,7 @@ private: CompilerType elem_type; if (m_type.IsHomogeneousAggregate(&elem_type)) { uint32_t type_flags = elem_type.GetTypeInfo(); - llvm::Optional<uint64_t> elem_size = + std::optional<uint64_t> elem_size = elem_type.GetByteSize(m_process_sp.get()); if (!elem_size) return {}; @@ -809,8 +810,7 @@ private: // case 3: get from GPRs // first, check if this is a packed struct or not - TypeSystemClang *ast = - llvm::dyn_cast<TypeSystemClang>(m_type.GetTypeSystem()); + auto ast = m_type.GetTypeSystem().dyn_cast_or_null<TypeSystemClang>(); if (ast) { clang::RecordDecl *record_decl = TypeSystemClang::GetAsRecordDecl(m_type); diff --git a/contrib/llvm-project/lldb/source/Plugins/ABI/SystemZ/ABISysV_s390x.cpp b/contrib/llvm-project/lldb/source/Plugins/ABI/SystemZ/ABISysV_s390x.cpp index f66143152576..4436bcd37503 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ABI/SystemZ/ABISysV_s390x.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ABI/SystemZ/ABISysV_s390x.cpp @@ -29,6 +29,7 @@ #include "lldb/Utility/Log.h" #include "lldb/Utility/RegisterValue.h" #include "lldb/Utility/Status.h" +#include <optional> using namespace lldb; using namespace lldb_private; @@ -172,8 +173,7 @@ static const RegisterInfo g_register_infos[] = { DEFINE_REG(f15, 8, nullptr, LLDB_INVALID_REGNUM), }; -static const uint32_t k_num_register_infos = - llvm::array_lengthof(g_register_infos); +static const uint32_t k_num_register_infos = std::size(g_register_infos); const lldb_private::RegisterInfo * ABISysV_s390x::GetRegisterInfoArray(uint32_t &count) { @@ -356,7 +356,7 @@ bool ABISysV_s390x::GetArgumentValues(Thread &thread, ValueList &values) const { // We currently only support extracting values with Clang QualTypes. Do we // care about others? CompilerType compiler_type = value->GetCompilerType(); - llvm::Optional<uint64_t> bit_size = compiler_type.GetBitSize(&thread); + std::optional<uint64_t> bit_size = compiler_type.GetBitSize(&thread); if (!bit_size) return false; bool is_signed; @@ -426,7 +426,7 @@ Status ABISysV_s390x::SetReturnValueObject(lldb::StackFrameSP &frame_sp, error.SetErrorString( "We don't support returning complex values at present"); else { - llvm::Optional<uint64_t> bit_width = + std::optional<uint64_t> bit_width = compiler_type.GetBitSize(frame_sp.get()); if (!bit_width) { error.SetErrorString("can't get type size"); @@ -493,7 +493,7 @@ ValueObjectSP ABISysV_s390x::GetReturnValueObjectSimple( bool success = false; if (type_flags & eTypeIsInteger) { // Extract the register context so we can read arguments from registers. - llvm::Optional<uint64_t> byte_size = + std::optional<uint64_t> byte_size = return_compiler_type.GetByteSize(&thread); if (!byte_size) return return_valobj_sp; @@ -540,7 +540,7 @@ ValueObjectSP ABISysV_s390x::GetReturnValueObjectSimple( if (type_flags & eTypeIsComplex) { // Don't handle complex yet. } else { - llvm::Optional<uint64_t> byte_size = + std::optional<uint64_t> byte_size = return_compiler_type.GetByteSize(&thread); if (byte_size && *byte_size <= sizeof(long double)) { const RegisterInfo *f0_info = reg_ctx->GetRegisterInfoByName("f0", 0); diff --git a/contrib/llvm-project/lldb/source/Plugins/ABI/X86/ABIMacOSX_i386.cpp b/contrib/llvm-project/lldb/source/Plugins/ABI/X86/ABIMacOSX_i386.cpp index 69adeee4742b..4d2e16da4cda 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ABI/X86/ABIMacOSX_i386.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ABI/X86/ABIMacOSX_i386.cpp @@ -8,6 +8,7 @@ #include "ABIMacOSX_i386.h" +#include <optional> #include <vector> #include "llvm/ADT/STLExtras.h" @@ -164,7 +165,7 @@ bool ABIMacOSX_i386::GetArgumentValues(Thread &thread, // We currently only support extracting values with Clang QualTypes. Do we // care about others? CompilerType compiler_type(value->GetCompilerType()); - llvm::Optional<uint64_t> bit_size = compiler_type.GetBitSize(&thread); + std::optional<uint64_t> bit_size = compiler_type.GetBitSize(&thread); if (bit_size) { bool is_signed; if (compiler_type.IsIntegerOrEnumerationType(is_signed)) @@ -273,7 +274,7 @@ ABIMacOSX_i386::GetReturnValueObjectImpl(Thread &thread, bool is_signed; if (compiler_type.IsIntegerOrEnumerationType(is_signed)) { - llvm::Optional<uint64_t> bit_width = compiler_type.GetBitSize(&thread); + std::optional<uint64_t> bit_width = compiler_type.GetBitSize(&thread); if (!bit_width) return return_valobj_sp; unsigned eax_id = diff --git a/contrib/llvm-project/lldb/source/Plugins/ABI/X86/ABISysV_i386.cpp b/contrib/llvm-project/lldb/source/Plugins/ABI/X86/ABISysV_i386.cpp index 054e28f5c7a6..2bc6e3b891e6 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ABI/X86/ABISysV_i386.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ABI/X86/ABISysV_i386.cpp @@ -27,6 +27,7 @@ #include "lldb/Utility/Log.h" #include "lldb/Utility/RegisterValue.h" #include "lldb/Utility/Status.h" +#include <optional> using namespace lldb; using namespace lldb_private; @@ -181,7 +182,7 @@ bool ABISysV_i386::GetArgumentValues(Thread &thread, ValueList &values) const { // Currently: Support for extracting values with Clang QualTypes only. CompilerType compiler_type(value->GetCompilerType()); - llvm::Optional<uint64_t> bit_size = compiler_type.GetBitSize(&thread); + std::optional<uint64_t> bit_size = compiler_type.GetBitSize(&thread); if (bit_size) { bool is_signed; if (compiler_type.IsIntegerOrEnumerationType(is_signed)) { @@ -386,7 +387,7 @@ ValueObjectSP ABISysV_i386::GetReturnValueObjectSimple( (type_flags & eTypeIsEnumeration)) //'Integral' + 'Floating Point' { value.SetValueType(Value::ValueType::Scalar); - llvm::Optional<uint64_t> byte_size = + std::optional<uint64_t> byte_size = return_compiler_type.GetByteSize(&thread); if (!byte_size) return return_valobj_sp; @@ -511,7 +512,7 @@ ValueObjectSP ABISysV_i386::GetReturnValueObjectSimple( // ToDo: Yet to be implemented } else if (type_flags & eTypeIsVector) // 'Packed' { - llvm::Optional<uint64_t> byte_size = + std::optional<uint64_t> byte_size = return_compiler_type.GetByteSize(&thread); if (byte_size && *byte_size > 0) { const RegisterInfo *vec_reg = reg_ctx->GetRegisterInfoByName("xmm0", 0); @@ -528,7 +529,7 @@ ValueObjectSP ABISysV_i386::GetReturnValueObjectSimple( RegisterValue reg_value; if (reg_ctx->ReadRegister(vec_reg, reg_value)) { Status error; - if (reg_value.GetAsMemoryData(vec_reg, heap_data_up->GetBytes(), + if (reg_value.GetAsMemoryData(*vec_reg, heap_data_up->GetBytes(), heap_data_up->GetByteSize(), byte_order, error)) { DataExtractor data(DataBufferSP(heap_data_up.release()), @@ -556,11 +557,12 @@ ValueObjectSP ABISysV_i386::GetReturnValueObjectSimple( reg_ctx->ReadRegister(vec_reg2, reg_value2)) { Status error; - if (reg_value.GetAsMemoryData(vec_reg, heap_data_up->GetBytes(), - vec_reg->byte_size, byte_order, - error) && + if (reg_value.GetAsMemoryData( + *vec_reg, heap_data_up->GetBytes(), vec_reg->byte_size, + byte_order, error) && reg_value2.GetAsMemoryData( - vec_reg2, heap_data_up->GetBytes() + vec_reg->byte_size, + *vec_reg2, + heap_data_up->GetBytes() + vec_reg->byte_size, heap_data_up->GetByteSize() - vec_reg->byte_size, byte_order, error)) { DataExtractor data(DataBufferSP(heap_data_up.release()), diff --git a/contrib/llvm-project/lldb/source/Plugins/ABI/X86/ABISysV_x86_64.cpp b/contrib/llvm-project/lldb/source/Plugins/ABI/X86/ABISysV_x86_64.cpp index 031ccf5f54cc..9d5ed1fa2666 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ABI/X86/ABISysV_x86_64.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ABI/X86/ABISysV_x86_64.cpp @@ -31,6 +31,7 @@ #include "lldb/Utility/RegisterValue.h" #include "lldb/Utility/Status.h" +#include <optional> #include <vector> using namespace lldb; @@ -267,7 +268,7 @@ bool ABISysV_x86_64::GetArgumentValues(Thread &thread, // We currently only support extracting values with Clang QualTypes. Do we // care about others? CompilerType compiler_type = value->GetCompilerType(); - llvm::Optional<uint64_t> bit_size = compiler_type.GetBitSize(&thread); + std::optional<uint64_t> bit_size = compiler_type.GetBitSize(&thread); if (!bit_size) return false; bool is_signed; @@ -337,7 +338,7 @@ Status ABISysV_x86_64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, error.SetErrorString( "We don't support returning complex values at present"); else { - llvm::Optional<uint64_t> bit_width = + std::optional<uint64_t> bit_width = compiler_type.GetBitSize(frame_sp.get()); if (!bit_width) { error.SetErrorString("can't get type size"); @@ -406,7 +407,7 @@ ValueObjectSP ABISysV_x86_64::GetReturnValueObjectSimple( if (type_flags & eTypeIsInteger) { // Extract the register context so we can read arguments from registers - llvm::Optional<uint64_t> byte_size = + std::optional<uint64_t> byte_size = return_compiler_type.GetByteSize(&thread); if (!byte_size) return return_valobj_sp; @@ -453,7 +454,7 @@ ValueObjectSP ABISysV_x86_64::GetReturnValueObjectSimple( if (type_flags & eTypeIsComplex) { // Don't handle complex yet. } else { - llvm::Optional<uint64_t> byte_size = + std::optional<uint64_t> byte_size = return_compiler_type.GetByteSize(&thread); if (byte_size && *byte_size <= sizeof(long double)) { const RegisterInfo *xmm0_info = @@ -492,7 +493,7 @@ ValueObjectSP ABISysV_x86_64::GetReturnValueObjectSimple( return_valobj_sp = ValueObjectConstResult::Create( thread.GetStackFrameAtIndex(0).get(), value, ConstString("")); } else if (type_flags & eTypeIsVector) { - llvm::Optional<uint64_t> byte_size = + std::optional<uint64_t> byte_size = return_compiler_type.GetByteSize(&thread); if (byte_size && *byte_size > 0) { const RegisterInfo *altivec_reg = @@ -511,7 +512,7 @@ ValueObjectSP ABISysV_x86_64::GetReturnValueObjectSimple( if (reg_ctx->ReadRegister(altivec_reg, reg_value)) { Status error; if (reg_value.GetAsMemoryData( - altivec_reg, heap_data_up->GetBytes(), + *altivec_reg, heap_data_up->GetBytes(), heap_data_up->GetByteSize(), byte_order, error)) { DataExtractor data(DataBufferSP(heap_data_up.release()), byte_order, @@ -539,10 +540,10 @@ ValueObjectSP ABISysV_x86_64::GetReturnValueObjectSimple( Status error; if (reg_value.GetAsMemoryData( - altivec_reg, heap_data_up->GetBytes(), + *altivec_reg, heap_data_up->GetBytes(), altivec_reg->byte_size, byte_order, error) && reg_value2.GetAsMemoryData( - altivec_reg2, + *altivec_reg2, heap_data_up->GetBytes() + altivec_reg->byte_size, heap_data_up->GetByteSize() - altivec_reg->byte_size, byte_order, error)) { @@ -587,8 +588,8 @@ static bool FlattenAggregateType( uint64_t field_bit_offset = 0; CompilerType field_compiler_type = return_compiler_type.GetFieldAtIndex( idx, name, &field_bit_offset, nullptr, nullptr); - llvm::Optional<uint64_t> field_bit_width = - field_compiler_type.GetBitSize(&thread); + std::optional<uint64_t> field_bit_width = + field_compiler_type.GetBitSize(&thread); // if we don't know the size of the field (e.g. invalid type), exit if (!field_bit_width || *field_bit_width == 0) { @@ -630,7 +631,7 @@ ValueObjectSP ABISysV_x86_64::GetReturnValueObjectImpl( if (!reg_ctx_sp) return return_valobj_sp; - llvm::Optional<uint64_t> bit_width = return_compiler_type.GetBitSize(&thread); + std::optional<uint64_t> bit_width = return_compiler_type.GetBitSize(&thread); if (!bit_width) return return_valobj_sp; if (return_compiler_type.IsAggregateType()) { @@ -638,12 +639,12 @@ ValueObjectSP ABISysV_x86_64::GetReturnValueObjectImpl( bool is_memory = true; std::vector<uint32_t> aggregate_field_offsets; std::vector<CompilerType> aggregate_compiler_types; - if (return_compiler_type.GetTypeSystem()->CanPassInRegisters( - return_compiler_type) && - *bit_width <= 128 && - FlattenAggregateType(thread, exe_ctx, return_compiler_type, - 0, aggregate_field_offsets, - aggregate_compiler_types)) { + auto ts = return_compiler_type.GetTypeSystem(); + if (ts && ts->CanPassInRegisters(return_compiler_type) && + *bit_width <= 128 && + FlattenAggregateType(thread, exe_ctx, return_compiler_type, 0, + aggregate_field_offsets, + aggregate_compiler_types)) { ByteOrder byte_order = target->GetArchitecture().GetByteOrder(); WritableDataBufferSP data_sp(new DataBufferHeap(16, 0)); DataExtractor return_ext(data_sp, byte_order, diff --git a/contrib/llvm-project/lldb/source/Plugins/ABI/X86/ABIWindows_x86_64.cpp b/contrib/llvm-project/lldb/source/Plugins/ABI/X86/ABIWindows_x86_64.cpp index b91ba32a97cf..6d9b3ae3c636 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ABI/X86/ABIWindows_x86_64.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ABI/X86/ABIWindows_x86_64.cpp @@ -30,6 +30,7 @@ #include "lldb/Utility/Log.h" #include "lldb/Utility/RegisterValue.h" #include "lldb/Utility/Status.h" +#include <optional> using namespace lldb; using namespace lldb_private; @@ -274,7 +275,7 @@ bool ABIWindows_x86_64::GetArgumentValues(Thread &thread, return false; CompilerType compiler_type = value->GetCompilerType(); - llvm::Optional<uint64_t> bit_size = compiler_type.GetBitSize(&thread); + std::optional<uint64_t> bit_size = compiler_type.GetBitSize(&thread); if (!bit_size) return false; bool is_signed; @@ -344,7 +345,7 @@ Status ABIWindows_x86_64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, error.SetErrorString( "We don't support returning complex values at present"); else { - llvm::Optional<uint64_t> bit_width = + std::optional<uint64_t> bit_width = compiler_type.GetBitSize(frame_sp.get()); if (!bit_width) { error.SetErrorString("can't get type size"); @@ -414,7 +415,7 @@ ValueObjectSP ABIWindows_x86_64::GetReturnValueObjectSimple( bool success = false; if (type_flags & eTypeIsInteger) { // Extract the register context so we can read arguments from registers - llvm::Optional<uint64_t> byte_size = + std::optional<uint64_t> byte_size = return_compiler_type.GetByteSize(&thread); if (!byte_size) return return_valobj_sp; @@ -461,7 +462,7 @@ ValueObjectSP ABIWindows_x86_64::GetReturnValueObjectSimple( if (type_flags & eTypeIsComplex) { // Don't handle complex yet. } else { - llvm::Optional<uint64_t> byte_size = + std::optional<uint64_t> byte_size = return_compiler_type.GetByteSize(&thread); if (byte_size && *byte_size <= sizeof(long double)) { const RegisterInfo *xmm0_info = @@ -499,7 +500,7 @@ ValueObjectSP ABIWindows_x86_64::GetReturnValueObjectSimple( return_valobj_sp = ValueObjectConstResult::Create( thread.GetStackFrameAtIndex(0).get(), value, ConstString("")); } else if (type_flags & eTypeIsVector) { - llvm::Optional<uint64_t> byte_size = + std::optional<uint64_t> byte_size = return_compiler_type.GetByteSize(&thread); if (byte_size && *byte_size > 0) { const RegisterInfo *xmm_reg = @@ -517,9 +518,9 @@ ValueObjectSP ABIWindows_x86_64::GetReturnValueObjectSimple( RegisterValue reg_value; if (reg_ctx->ReadRegister(xmm_reg, reg_value)) { Status error; - if (reg_value.GetAsMemoryData( - xmm_reg, heap_data_up->GetBytes(), - heap_data_up->GetByteSize(), byte_order, error)) { + if (reg_value.GetAsMemoryData(*xmm_reg, heap_data_up->GetBytes(), + heap_data_up->GetByteSize(), + byte_order, error)) { DataExtractor data(DataBufferSP(heap_data_up.release()), byte_order, process_sp->GetTarget() @@ -560,8 +561,8 @@ static bool FlattenAggregateType( uint64_t field_bit_offset = 0; CompilerType field_compiler_type = return_compiler_type.GetFieldAtIndex( idx, name, &field_bit_offset, nullptr, nullptr); - llvm::Optional<uint64_t> field_bit_width = - field_compiler_type.GetBitSize(&thread); + std::optional<uint64_t> field_bit_width = + field_compiler_type.GetBitSize(&thread); // if we don't know the size of the field (e.g. invalid type), exit if (!field_bit_width || *field_bit_width == 0) { @@ -611,7 +612,7 @@ ValueObjectSP ABIWindows_x86_64::GetReturnValueObjectImpl( return return_valobj_sp; } - llvm::Optional<uint64_t> bit_width = return_compiler_type.GetBitSize(&thread); + std::optional<uint64_t> bit_width = return_compiler_type.GetBitSize(&thread); if (!bit_width) { return return_valobj_sp; } diff --git a/contrib/llvm-project/lldb/source/Plugins/ABI/X86/ABIX86.cpp b/contrib/llvm-project/lldb/source/Plugins/ABI/X86/ABIX86.cpp index 768e4047dba6..46b1743af2c4 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ABI/X86/ABIX86.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ABI/X86/ABIX86.cpp @@ -17,6 +17,7 @@ #include "ABIX86.h" #include "lldb/Core/PluginManager.h" #include "lldb/Target/Process.h" +#include <optional> using namespace lldb; using namespace lldb_private; @@ -62,7 +63,7 @@ enum RegKind { struct RegData { RegKind subreg_kind; llvm::StringRef subreg_name; - llvm::Optional<uint32_t> base_index; + std::optional<uint32_t> base_index; }; static void @@ -112,8 +113,8 @@ addCombinedRegisters(std::vector<DynamicRegisterInfo::Register> ®s, if (regdata1->subreg_name != regdata2->subreg_name) continue; - uint32_t base_index1 = regdata1->base_index.value(); - uint32_t base_index2 = regdata2->base_index.value(); + uint32_t base_index1 = *regdata1->base_index; + uint32_t base_index2 = *regdata2->base_index; if (regs[base_index1].byte_size != base_size || regs[base_index2].byte_size != base_size) continue; @@ -142,42 +143,44 @@ typedef llvm::SmallDenseMap<llvm::StringRef, llvm::SmallVector<RegData, 4>, 64> #define GPRh(l) \ { \ - is64bit \ - ? BaseRegToRegsMap::value_type("r" l "x", \ - {{GPR32, "e" l "x", llvm::None}, \ - {GPR16, l "x", llvm::None}, \ - {GPR8h, l "h", llvm::None}, \ - {GPR8, l "l", llvm::None}}) \ - : BaseRegToRegsMap::value_type("e" l "x", {{GPR16, l "x", llvm::None}, \ - {GPR8h, l "h", llvm::None}, \ - {GPR8, l "l", llvm::None}}) \ + is64bit ? BaseRegToRegsMap::value_type("r" l "x", \ + {{GPR32, "e" l "x", std::nullopt}, \ + {GPR16, l "x", std::nullopt}, \ + {GPR8h, l "h", std::nullopt}, \ + {GPR8, l "l", std::nullopt}}) \ + : BaseRegToRegsMap::value_type("e" l "x", \ + {{GPR16, l "x", std::nullopt}, \ + {GPR8h, l "h", std::nullopt}, \ + {GPR8, l "l", std::nullopt}}) \ } #define GPR(r16) \ { \ - is64bit \ - ? BaseRegToRegsMap::value_type("r" r16, {{GPR32, "e" r16, llvm::None}, \ - {GPR16, r16, llvm::None}, \ - {GPR8, r16 "l", llvm::None}}) \ - : BaseRegToRegsMap::value_type("e" r16, {{GPR16, r16, llvm::None}, \ - {GPR8, r16 "l", llvm::None}}) \ + is64bit ? BaseRegToRegsMap::value_type("r" r16, \ + {{GPR32, "e" r16, std::nullopt}, \ + {GPR16, r16, std::nullopt}, \ + {GPR8, r16 "l", std::nullopt}}) \ + : BaseRegToRegsMap::value_type( \ + "e" r16, \ + {{GPR16, r16, std::nullopt}, {GPR8, r16 "l", std::nullopt}}) \ } #define GPR64(n) \ { \ - BaseRegToRegsMap::value_type("r" #n, {{GPR32, "r" #n "d", llvm::None}, \ - {GPR16, "r" #n "w", llvm::None}, \ - {GPR8, "r" #n "l", llvm::None}}) \ + BaseRegToRegsMap::value_type("r" #n, {{GPR32, "r" #n "d", std::nullopt}, \ + {GPR16, "r" #n "w", std::nullopt}, \ + {GPR8, "r" #n "l", std::nullopt}}) \ } #define STMM(n) \ - { BaseRegToRegsMap::value_type("st" #n, {{MM, "mm" #n, llvm::None}}) } + { BaseRegToRegsMap::value_type("st" #n, {{MM, "mm" #n, std::nullopt}}) } #define YMM(n) \ {BaseRegToRegsMap::value_type("ymm" #n "h", \ - {{YMM_YMMh, "ymm" #n, llvm::None}})}, \ + {{YMM_YMMh, "ymm" #n, std::nullopt}})}, \ { \ - BaseRegToRegsMap::value_type("xmm" #n, {{YMM_XMM, "ymm" #n, llvm::None}}) \ + BaseRegToRegsMap::value_type("xmm" #n, \ + {{YMM_XMM, "ymm" #n, std::nullopt}}) \ } BaseRegToRegsMap makeBaseRegMap(bool is64bit) { diff --git a/contrib/llvm-project/lldb/source/Plugins/Disassembler/LLVMC/DisassemblerLLVMC.cpp b/contrib/llvm-project/lldb/source/Plugins/Disassembler/LLVMC/DisassemblerLLVMC.cpp index 973884283f46..ed3b3e6da02b 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Disassembler/LLVMC/DisassemblerLLVMC.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Disassembler/LLVMC/DisassemblerLLVMC.cpp @@ -42,6 +42,7 @@ #include "lldb/Utility/Log.h" #include "lldb/Utility/RegularExpression.h" #include "lldb/Utility/Stream.h" +#include <optional> using namespace lldb; using namespace lldb_private; @@ -252,8 +253,8 @@ MapOpcodeIntoControlFlowKind(InstructionOpcodeAndModrm opcode_and_modrm) { /// Returns decoded instruction as struct InstructionOpcodeAndModrm, holding /// primary_opcode, opcode_len and modrm byte. Refer to the struct definition /// for more details. -/// Otherwise if the given instruction is invalid, returns None. -llvm::Optional<InstructionOpcodeAndModrm> +/// Otherwise if the given instruction is invalid, returns std::nullopt. +std::optional<InstructionOpcodeAndModrm> InstructionLengthDecode(const uint8_t *inst_bytes, int bytes_len, bool is_exec_mode_64b) { int op_idx = 0; @@ -266,7 +267,7 @@ InstructionLengthDecode(const uint8_t *inst_bytes, int bytes_len, // in `src/pt_ild.c` while (!prefix_done) { if (op_idx >= bytes_len) - return llvm::None; + return std::nullopt; ret.primary_opcode = inst_bytes[op_idx]; switch (ret.primary_opcode) { @@ -384,7 +385,7 @@ InstructionLengthDecode(const uint8_t *inst_bytes, int bytes_len, lldb::InstructionControlFlowKind GetControlFlowKind(bool is_exec_mode_64b, Opcode m_opcode) { - llvm::Optional<InstructionOpcodeAndModrm> ret = llvm::None; + std::optional<InstructionOpcodeAndModrm> ret; if (m_opcode.GetOpcodeBytes() == nullptr || m_opcode.GetByteSize() <= 0) { // x86_64 and i386 instructions are categorized as Opcode::Type::eTypeBytes @@ -398,7 +399,7 @@ lldb::InstructionControlFlowKind GetControlFlowKind(bool is_exec_mode_64b, if (!ret) return lldb::eInstructionControlFlowKindUnknown; else - return MapOpcodeIntoControlFlowKind(ret.value()); + return MapOpcodeIntoControlFlowKind(*ret); } } // namespace x86 @@ -1383,7 +1384,7 @@ bool DisassemblerLLVMC::MCDisasmInstance::IsLoad(llvm::MCInst &mc_inst) const { bool DisassemblerLLVMC::MCDisasmInstance::IsAuthenticated( llvm::MCInst &mc_inst) const { - auto InstrDesc = m_instr_info_up->get(mc_inst.getOpcode()); + const auto &InstrDesc = m_instr_info_up->get(mc_inst.getOpcode()); // Treat software auth traps (brk 0xc470 + aut key, where 0x70 == 'p', 0xc4 // == 'a' + 'c') as authenticated instructions for reporting purposes, in @@ -1710,13 +1711,13 @@ const char *DisassemblerLLVMC::SymbolLookup(uint64_t value, uint64_t *type_ptr, // then this is a pc-relative address calculation. if (*type_ptr == LLVMDisassembler_ReferenceType_In_ARM64_ADDXri && m_adrp_insn && m_adrp_address == pc - 4 && - (m_adrp_insn.value() & 0x1f) == ((value >> 5) & 0x1f)) { + (*m_adrp_insn & 0x1f) == ((value >> 5) & 0x1f)) { uint32_t addxri_inst; uint64_t adrp_imm, addxri_imm; // Get immlo and immhi bits, OR them together to get the ADRP imm // value. - adrp_imm = ((m_adrp_insn.value() & 0x00ffffe0) >> 3) | - ((m_adrp_insn.value() >> 29) & 0x3); + adrp_imm = + ((*m_adrp_insn & 0x00ffffe0) >> 3) | ((*m_adrp_insn >> 29) & 0x3); // if high bit of immhi after right-shifting set, sign extend if (adrp_imm & (1ULL << 20)) adrp_imm |= ~((1ULL << 21) - 1); diff --git a/contrib/llvm-project/lldb/source/Plugins/Disassembler/LLVMC/DisassemblerLLVMC.h b/contrib/llvm-project/lldb/source/Plugins/Disassembler/LLVMC/DisassemblerLLVMC.h index 5d0204caaa9a..68ae3a32e18f 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Disassembler/LLVMC/DisassemblerLLVMC.h +++ b/contrib/llvm-project/lldb/source/Plugins/Disassembler/LLVMC/DisassemblerLLVMC.h @@ -11,12 +11,12 @@ #include <memory> #include <mutex> +#include <optional> #include <string> #include "lldb/Core/Address.h" #include "lldb/Core/Disassembler.h" #include "lldb/Core/PluginManager.h" -#include "llvm/ADT/Optional.h" class InstructionLLVMC; @@ -77,7 +77,7 @@ protected: // this is a pc-relative address calculation and we need both // parts to calculate the symbolication. lldb::addr_t m_adrp_address; - llvm::Optional<uint32_t> m_adrp_insn; + std::optional<uint32_t> m_adrp_insn; // Since we need to make two actual MC Disassemblers for ARM (ARM & THUMB), // and there's a bit of goo to set up and own in the MC disassembler world, diff --git a/contrib/llvm-project/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.cpp b/contrib/llvm-project/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.cpp index 5dbbd209bd9b..d2bf2586cd82 100644 --- a/contrib/llvm-project/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.cpp @@ -168,8 +168,7 @@ bool HexagonDYLDRendezvous::UpdateSOEntriesForAddition() { if (entry.path.empty() || ::strcmp(entry.path.c_str(), m_exe_path) == 0) continue; - pos = std::find(m_soentries.begin(), m_soentries.end(), entry); - if (pos == m_soentries.end()) { + if (!llvm::is_contained(m_soentries, entry)) { m_soentries.push_back(entry); m_added_soentries.push_back(entry); } @@ -188,8 +187,7 @@ bool HexagonDYLDRendezvous::UpdateSOEntriesForDeletion() { return false; for (iterator I = begin(); I != end(); ++I) { - pos = std::find(entry_list.begin(), entry_list.end(), *I); - if (pos == entry_list.end()) + if (!llvm::is_contained(entry_list, *I)) m_removed_soentries.push_back(*I); } diff --git a/contrib/llvm-project/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp b/contrib/llvm-project/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp index 4869cf0fd9c8..f20167b46d27 100644 --- a/contrib/llvm-project/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp @@ -119,7 +119,7 @@ void DYLDRendezvous::UpdateExecutablePath() { if (exe_mod) { m_exe_file_spec = exe_mod->GetPlatformFileSpec(); LLDB_LOGF(log, "DYLDRendezvous::%s exe module executable path set: '%s'", - __FUNCTION__, m_exe_file_spec.GetCString()); + __FUNCTION__, m_exe_file_spec.GetPath().c_str()); } else { LLDB_LOGF(log, "DYLDRendezvous::%s cannot cache exe module path: null " @@ -190,6 +190,14 @@ bool DYLDRendezvous::IsValid() { } DYLDRendezvous::RendezvousAction DYLDRendezvous::GetAction() const { + // If we have a core file, we will read the current rendezvous state + // from the core file's memory into m_current which can be in an inconsistent + // state, so we can't rely on its state to determine what we should do. We + // always need it to load all of the shared libraries one time when we attach + // to a core file. + if (IsCoreFile()) + return eTakeSnapshot; + switch (m_current.state) { case eConsistent: @@ -396,8 +404,7 @@ bool DYLDRendezvous::AddSOEntries() { UpdateFileSpecIfNecessary(entry); - pos = std::find(m_soentries.begin(), m_soentries.end(), entry); - if (pos == m_soentries.end()) { + if (!llvm::is_contained(m_soentries, entry)) { m_soentries.push_back(entry); m_added_soentries.push_back(entry); } @@ -416,8 +423,7 @@ bool DYLDRendezvous::RemoveSOEntries() { return false; for (iterator I = begin(); I != end(); ++I) { - pos = std::find(entry_list.begin(), entry_list.end(), *I); - if (pos == entry_list.end()) + if (!llvm::is_contained(entry_list, *I)) m_removed_soentries.push_back(*I); } @@ -658,7 +664,7 @@ void DYLDRendezvous::DumpToLog(Log *log) const { log->PutCString("DYLDRendezvous SOEntries:"); for (int i = 1; I != E; ++I, ++i) { - LLDB_LOGF(log, "\n SOEntry [%d] %s", i, I->file_spec.GetCString()); + LLDB_LOGF(log, "\n SOEntry [%d] %s", i, I->file_spec.GetPath().c_str()); LLDB_LOGF(log, " Base : %" PRIx64, I->base_addr); LLDB_LOGF(log, " Path : %" PRIx64, I->path_addr); LLDB_LOGF(log, " Dyn : %" PRIx64, I->dyn_addr); @@ -666,3 +672,7 @@ void DYLDRendezvous::DumpToLog(Log *log) const { LLDB_LOGF(log, " Prev : %" PRIx64, I->prev); } } + +bool DYLDRendezvous::IsCoreFile() const { + return !m_process->IsLiveDebugSession(); +} diff --git a/contrib/llvm-project/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h b/contrib/llvm-project/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h index 04d3e665f859..fc1dd6921455 100644 --- a/contrib/llvm-project/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h +++ b/contrib/llvm-project/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h @@ -267,6 +267,8 @@ protected: bool FindMetadata(const char *name, PThreadField field, uint32_t &value); + bool IsCoreFile() const; + enum RendezvousAction { eNoAction, eTakeSnapshot, diff --git a/contrib/llvm-project/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp b/contrib/llvm-project/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp index 8a708c1f9898..13a6ffa78a6e 100644 --- a/contrib/llvm-project/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp @@ -26,6 +26,7 @@ #include "lldb/Utility/ProcessInfo.h" #include <memory> +#include <optional> using namespace lldb; using namespace lldb_private; @@ -213,6 +214,10 @@ void DynamicLoaderPOSIXDYLD::UnloadSections(const ModuleSP module) { void DynamicLoaderPOSIXDYLD::ProbeEntry() { Log *log = GetLog(LLDBLog::DynamicLoader); + // If we have a core file, we don't need any breakpoints. + if (IsCoreFile()) + return; + const addr_t entry = GetEntryPoint(); if (entry == LLDB_INVALID_ADDRESS) { LLDB_LOGF( @@ -297,6 +302,11 @@ bool DynamicLoaderPOSIXDYLD::EntryBreakpointHit( bool DynamicLoaderPOSIXDYLD::SetRendezvousBreakpoint() { Log *log = GetLog(LLDBLog::DynamicLoader); + + // If we have a core file, we don't need any breakpoints. + if (IsCoreFile()) + return false; + if (m_dyld_bid != LLDB_INVALID_BREAK_ID) { LLDB_LOG(log, "Rendezvous breakpoint breakpoint id {0} for pid {1}" @@ -592,7 +602,7 @@ ModuleSP DynamicLoaderPOSIXDYLD::LoadModuleAtAddress(const FileSpec &file, // (e.g. com.example.myapplication) instead of the main process binary // (/system/bin/app_process(32)). The logic is not sound in general (it // assumes base_addr is the real address, even though it actually is a load - // bias), but it happens to work on adroid because app_process has a file + // bias), but it happens to work on android because app_process has a file // address of zero. // This should be removed after we drop support for android-23. if (m_process->GetTarget().GetArchitecture().GetTriple().isAndroid()) { @@ -650,7 +660,7 @@ void DynamicLoaderPOSIXDYLD::LoadAllCurrentModules() { LLDB_LOGF( log, "DynamicLoaderPOSIXDYLD::%s failed loading module %s at 0x%" PRIx64, - __FUNCTION__, I->file_spec.GetCString(), I->base_addr); + __FUNCTION__, I->file_spec.GetPath().c_str(), I->base_addr); } } @@ -685,11 +695,11 @@ addr_t DynamicLoaderPOSIXDYLD::ComputeLoadOffset() { } void DynamicLoaderPOSIXDYLD::EvalSpecialModulesStatus() { - if (llvm::Optional<uint64_t> vdso_base = + if (std::optional<uint64_t> vdso_base = m_auxv->GetAuxValue(AuxVector::AUXV_AT_SYSINFO_EHDR)) m_vdso_base = *vdso_base; - if (llvm::Optional<uint64_t> interpreter_base = + if (std::optional<uint64_t> interpreter_base = m_auxv->GetAuxValue(AuxVector::AUXV_AT_BASE)) m_interpreter_base = *interpreter_base; } @@ -701,7 +711,7 @@ addr_t DynamicLoaderPOSIXDYLD::GetEntryPoint() { if (m_auxv == nullptr) return LLDB_INVALID_ADDRESS; - llvm::Optional<uint64_t> entry_point = + std::optional<uint64_t> entry_point = m_auxv->GetAuxValue(AuxVector::AUXV_AT_ENTRY); if (!entry_point) return LLDB_INVALID_ADDRESS; @@ -829,3 +839,7 @@ bool DynamicLoaderPOSIXDYLD::AlwaysRelyOnEHUnwindInfo( return module_sp->GetFileSpec().GetPath() == "[vdso]"; } + +bool DynamicLoaderPOSIXDYLD::IsCoreFile() const { + return !m_process->IsLiveDebugSession(); +} diff --git a/contrib/llvm-project/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h b/contrib/llvm-project/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h index 8d3e4cde54c7..4c92335602cd 100644 --- a/contrib/llvm-project/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h +++ b/contrib/llvm-project/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h @@ -91,6 +91,9 @@ protected: std::map<lldb::ModuleWP, lldb::addr_t, std::owner_less<lldb::ModuleWP>> m_loaded_modules; + /// Returns true if the process is for a core file. + bool IsCoreFile() const; + /// If possible sets a breakpoint on a function called by the runtime /// linker each time a module is loaded or unloaded. bool SetRendezvousBreakpoint(); diff --git a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp index 799ae29e2841..07cb4c9f027c 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp @@ -470,7 +470,7 @@ void ASTResultSynthesizer::CommitPersistentDecls() { auto *persistent_vars = llvm::cast<ClangPersistentVariables>(state); - TypeSystemClang *scratch_ctx = ScratchTypeSystemClang::GetForTarget( + lldb::TypeSystemClangSP scratch_ts_sp = ScratchTypeSystemClang::GetForTarget( m_target, m_ast_context->getLangOpts()); for (clang::NamedDecl *decl : m_decls) { @@ -478,7 +478,7 @@ void ASTResultSynthesizer::CommitPersistentDecls() { ConstString name_cs(name.str().c_str()); Decl *D_scratch = persistent_vars->GetClangASTImporter()->DeportDecl( - &scratch_ctx->getASTContext(), decl); + &scratch_ts_sp->getASTContext(), decl); if (!D_scratch) { Log *log = GetLog(LLDBLog::Expressions); @@ -497,7 +497,7 @@ void ASTResultSynthesizer::CommitPersistentDecls() { if (NamedDecl *NamedDecl_scratch = dyn_cast<NamedDecl>(D_scratch)) persistent_vars->RegisterPersistentDecl(name_cs, NamedDecl_scratch, - scratch_ctx); + scratch_ts_sp); } } diff --git a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ASTUtils.h b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ASTUtils.h index b70ec223df4d..95e8a600f838 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ASTUtils.h +++ b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ASTUtils.h @@ -14,6 +14,7 @@ #include "clang/Sema/MultiplexExternalSemaSource.h" #include "clang/Sema/Sema.h" #include "clang/Sema/SemaConsumer.h" +#include <optional> namespace lldb_private { @@ -72,7 +73,7 @@ public: return m_Source->getModule(ID); } - llvm::Optional<clang::ASTSourceDescriptor> + std::optional<clang::ASTSourceDescriptor> getSourceDescriptor(unsigned ID) override { return m_Source->getSourceDescriptor(ID); } diff --git a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.cpp b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.cpp index 9ef3c3671abf..c084c3fbefc5 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.cpp @@ -25,6 +25,7 @@ #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" #include <memory> +#include <optional> using namespace lldb_private; using namespace clang; @@ -33,8 +34,7 @@ CompilerType ClangASTImporter::CopyType(TypeSystemClang &dst_ast, const CompilerType &src_type) { clang::ASTContext &dst_clang_ast = dst_ast.getASTContext(); - TypeSystemClang *src_ast = - llvm::dyn_cast_or_null<TypeSystemClang>(src_type.GetTypeSystem()); + auto src_ast = src_type.GetTypeSystem().dyn_cast_or_null<TypeSystemClang>(); if (!src_ast) return CompilerType(); @@ -59,7 +59,7 @@ CompilerType ClangASTImporter::CopyType(TypeSystemClang &dst_ast, lldb::opaque_compiler_type_t dst_clang_type = ret_or_error->getAsOpaquePtr(); if (dst_clang_type) - return CompilerType(&dst_ast, dst_clang_type); + return CompilerType(dst_ast.weak_from_this(), dst_clang_type); return CompilerType(); } @@ -305,8 +305,9 @@ CompilerType ClangASTImporter::DeportType(TypeSystemClang &dst, const CompilerType &src_type) { Log *log = GetLog(LLDBLog::Expressions); - TypeSystemClang *src_ctxt = - llvm::cast<TypeSystemClang>(src_type.GetTypeSystem()); + auto src_ctxt = src_type.GetTypeSystem().dyn_cast_or_null<TypeSystemClang>(); + if (!src_ctxt) + return {}; LLDB_LOG(log, " [ClangASTImporter] DeportType called on ({0}Type*){1} " @@ -811,7 +812,7 @@ ClangASTImporter::MapCompleter::~MapCompleter() = default; llvm::Expected<Decl *> ClangASTImporter::ASTImporterDelegate::ImportImpl(Decl *From) { if (m_std_handler) { - llvm::Optional<Decl *> D = m_std_handler->Import(From); + std::optional<Decl *> D = m_std_handler->Import(From); if (D) { // Make sure we don't use this decl later to map it back to it's original // decl. The decl the CxxModuleHandler created has nothing to do with diff --git a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp index 71242925862b..108566b066d7 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp @@ -78,14 +78,14 @@ ClangASTSource::~ClangASTSource() { // query the deleted ASTContext for additional type information. // We unregister from *all* scratch ASTContexts in case a type got exported // to a scratch AST that isn't the best fitting scratch ASTContext. - TypeSystemClang *scratch_ast = ScratchTypeSystemClang::GetForTarget( + lldb::TypeSystemClangSP scratch_ts_sp = ScratchTypeSystemClang::GetForTarget( *m_target, ScratchTypeSystemClang::DefaultAST, false); - if (!scratch_ast) + if (!scratch_ts_sp) return; ScratchTypeSystemClang *default_scratch_ast = - llvm::cast<ScratchTypeSystemClang>(scratch_ast); + llvm::cast<ScratchTypeSystemClang>(scratch_ts_sp.get()); // Unregister from the default scratch AST (and all sub-ASTs). default_scratch_ast->ForgetSource(m_ast_context, *m_ast_importer_sp); } @@ -405,7 +405,7 @@ void ClangASTSource::FindExternalLexicalDecls( if (const NamedDecl *context_named_decl = dyn_cast<NamedDecl>(context_decl)) LLDB_LOG(log, "FindExternalLexicalDecls on (ASTContext*){0} '{1}' in " - "'{2}' (%sDecl*){3}", + "'{2}' ({3}Decl*){4}", m_ast_context, m_clang_ast_context->getDisplayName(), context_named_decl->getNameAsString().c_str(), context_decl->getDeclKindName(), @@ -1733,10 +1733,10 @@ ClangASTImporter::DeclOrigin ClangASTSource::GetDeclOrigin(const clang::Decl *de } CompilerType ClangASTSource::GuardedCopyType(const CompilerType &src_type) { - TypeSystemClang *src_ast = - llvm::dyn_cast_or_null<TypeSystemClang>(src_type.GetTypeSystem()); - if (src_ast == nullptr) - return CompilerType(); + auto ts = src_type.GetTypeSystem(); + auto src_ast = ts.dyn_cast_or_null<TypeSystemClang>(); + if (!src_ast) + return {}; QualType copied_qual_type = ClangUtil::GetQualType( m_ast_importer_sp->CopyType(*m_clang_ast_context, src_type)); @@ -1745,7 +1745,7 @@ CompilerType ClangASTSource::GuardedCopyType(const CompilerType &src_type) { copied_qual_type->getCanonicalTypeInternal().isNull()) // this shouldn't happen, but we're hardening because the AST importer // seems to be generating bad types on occasion. - return CompilerType(); + return {}; return m_clang_ast_context->GetType(copied_qual_type); } diff --git a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp index 6ba03dad98d1..c573b8b8154a 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp @@ -205,8 +205,9 @@ ClangExpressionDeclMap::TargetInfo ClangExpressionDeclMap::GetTargetInfo() { TypeFromUser ClangExpressionDeclMap::DeportType(TypeSystemClang &target, TypeSystemClang &source, TypeFromParser parser_type) { - assert(&target == GetScratchContext(*m_target)); - assert((TypeSystem *)&source == parser_type.GetTypeSystem()); + assert(&target == GetScratchContext(*m_target).get()); + assert((TypeSystem *)&source == + parser_type.GetTypeSystem().GetSharedPointer().get()); assert(&source.getASTContext() == m_ast_context); return TypeFromUser(m_ast_importer_sp->DeportType(target, parser_type)); @@ -218,9 +219,7 @@ bool ClangExpressionDeclMap::AddPersistentVariable(const NamedDecl *decl, bool is_result, bool is_lvalue) { assert(m_parser_vars.get()); - - TypeSystemClang *ast = - llvm::dyn_cast_or_null<TypeSystemClang>(parser_type.GetTypeSystem()); + auto ast = parser_type.GetTypeSystem().dyn_cast_or_null<TypeSystemClang>(); if (ast == nullptr) return false; @@ -243,7 +242,7 @@ bool ClangExpressionDeclMap::AddPersistentVariable(const NamedDecl *decl, if (target == nullptr) return false; - auto *clang_ast_context = GetScratchContext(*target); + auto clang_ast_context = GetScratchContext(*target); if (!clang_ast_context) return false; @@ -281,7 +280,7 @@ bool ClangExpressionDeclMap::AddPersistentVariable(const NamedDecl *decl, if (target == nullptr) return false; - TypeSystemClang *context = GetScratchContext(*target); + auto context = GetScratchContext(*target); if (!context) return false; @@ -568,7 +567,7 @@ addr_t ClangExpressionDeclMap::GetSymbolAddress(Target &target, reexport_module_sp = target.GetImages().FindFirstModule(reexport_module_spec); if (!reexport_module_sp) { - reexport_module_spec.GetPlatformFileSpec().GetDirectory().Clear(); + reexport_module_spec.GetPlatformFileSpec().ClearDirectory(); reexport_module_sp = target.GetImages().FindFirstModule(reexport_module_spec); } @@ -847,8 +846,9 @@ void ClangExpressionDeclMap::LookUpLldbClass(NameSearchContext &context) { QualType class_qual_type(class_decl->getTypeForDecl(), 0); - TypeFromUser class_user_type(class_qual_type.getAsOpaquePtr(), - function_decl_ctx.GetTypeSystem()); + TypeFromUser class_user_type( + class_qual_type.getAsOpaquePtr(), + function_decl_ctx.GetTypeSystem()->weak_from_this()); LLDB_LOG(log, " CEDM::FEVD Adding type for $__lldb_class: {0}", class_qual_type.getAsString()); @@ -866,7 +866,7 @@ void ClangExpressionDeclMap::LookUpLldbClass(NameSearchContext &context) { // emit DW_AT_object_pointer // for C++ so it hasn't actually been tested. - VariableList *vars = frame->GetVariableList(false); + VariableList *vars = frame->GetVariableList(false, nullptr); lldb::VariableSP this_var = vars->FindVariable(ConstString("this")); @@ -936,8 +936,9 @@ void ClangExpressionDeclMap::LookUpLldbObjCClass(NameSearchContext &context) { return; // This is unlikely, but we have seen crashes where this // occurred - TypeFromUser class_user_type(QualType(interface_type, 0).getAsOpaquePtr(), - function_decl_ctx.GetTypeSystem()); + TypeFromUser class_user_type( + QualType(interface_type, 0).getAsOpaquePtr(), + function_decl_ctx.GetTypeSystem()->weak_from_this()); LLDB_LOG(log, " FEVD[{0}] Adding type for $__lldb_objc_class: {1}", ClangUtil::ToString(interface_type)); @@ -951,7 +952,7 @@ void ClangExpressionDeclMap::LookUpLldbObjCClass(NameSearchContext &context) { // In that case, just look up the "self" variable in the current scope // and use its type. - VariableList *vars = frame->GetVariableList(false); + VariableList *vars = frame->GetVariableList(false, nullptr); lldb::VariableSP self_var = vars->FindVariable(ConstString("self")); @@ -1501,8 +1502,8 @@ bool ClangExpressionDeclMap::GetVariableValue(VariableSP &var, return false; } - TypeSystemClang *clang_ast = llvm::dyn_cast_or_null<TypeSystemClang>( - var_type->GetForwardCompilerType().GetTypeSystem()); + auto ts = var_type->GetForwardCompilerType().GetTypeSystem(); + auto clang_ast = ts.dyn_cast_or_null<TypeSystemClang>(); if (!clang_ast) { LLDB_LOG(log, "Skipped a definition because it has no Clang AST"); @@ -1621,8 +1622,8 @@ void ClangExpressionDeclMap::AddOneVariable( TypeFromUser user_type = valobj->GetCompilerType(); - TypeSystemClang *clang_ast = - llvm::dyn_cast_or_null<TypeSystemClang>(user_type.GetTypeSystem()); + auto clang_ast = + user_type.GetTypeSystem().dyn_cast_or_null<TypeSystemClang>(); if (!clang_ast) { LLDB_LOG(log, "Skipped a definition because it has no Clang AST"); @@ -1727,7 +1728,7 @@ void ClangExpressionDeclMap::AddOneGenericVariable(NameSearchContext &context, if (target == nullptr) return; - TypeSystemClang *scratch_ast_context = GetScratchContext(*target); + auto scratch_ast_context = GetScratchContext(*target); if (!scratch_ast_context) return; @@ -1915,7 +1916,7 @@ void ClangExpressionDeclMap::AddOneFunction(NameSearchContext &context, // We failed to copy the type we found LLDB_LOG(log, " Failed to import the function type '{0}' ({1:x})" - " into the expression parser AST contenxt", + " into the expression parser AST context", function_type->GetName(), function_type->GetID()); return; diff --git a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h index bf7646ccaedf..9430ab5b0464 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h +++ b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h @@ -12,6 +12,7 @@ #include <csignal> #include <cstdint> +#include <memory> #include <vector> #include "ClangASTSource.h" @@ -377,7 +378,7 @@ private: /// Deallocate struct variables void DisableStructVars() { m_struct_vars.reset(); } - TypeSystemClang *GetScratchContext(Target &target) { + lldb::TypeSystemClangSP GetScratchContext(Target &target) { return ScratchTypeSystemClang::GetForTarget(target, m_ast_context->getLangOpts()); } diff --git a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp index ec3dc28a3a8c..58e81fb1cd74 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp @@ -86,7 +86,6 @@ #include "lldb/Utility/LLDBAssert.h" #include "lldb/Utility/LLDBLog.h" #include "lldb/Utility/Log.h" -#include "lldb/Utility/ReproducerProvider.h" #include "lldb/Utility/Stream.h" #include "lldb/Utility/StreamString.h" #include "lldb/Utility/StringList.h" @@ -96,6 +95,7 @@ #include <cctype> #include <memory> +#include <optional> using namespace clang; using namespace llvm; @@ -391,18 +391,6 @@ ClangExpressionParser::ClangExpressionParser( // 1. Create a new compiler instance. m_compiler = std::make_unique<CompilerInstance>(); - // When capturing a reproducer, hook up the file collector with clang to - // collector modules and headers. - if (repro::Generator *g = repro::Reproducer::Instance().GetGenerator()) { - repro::FileProvider &fp = g->GetOrCreate<repro::FileProvider>(); - m_compiler->setModuleDepCollector( - std::make_shared<ModuleDependencyCollectorAdaptor>( - fp.GetFileCollector())); - DependencyOutputOptions &opts = m_compiler->getDependencyOutputOpts(); - opts.IncludeSystemHeaders = true; - opts.IncludeModuleFiles = true; - } - // Make sure clang uses the same VFS as LLDB. m_compiler->createFileManager(FileSystem::Instance().GetVirtualFileSystem()); @@ -559,7 +547,7 @@ ClangExpressionParser::ClangExpressionParser( case lldb::eLanguageTypeC_plus_plus_14: lang_opts.CPlusPlus11 = true; m_compiler->getHeaderSearchOpts().UseLibcxx = true; - LLVM_FALLTHROUGH; + [[fallthrough]]; case lldb::eLanguageTypeC_plus_plus_03: lang_opts.CPlusPlus = true; if (process_sp) @@ -714,7 +702,7 @@ ClangExpressionParser::ClangExpressionParser( m_compiler->createASTContext(); clang::ASTContext &ast_context = m_compiler->getASTContext(); - m_ast_context = std::make_unique<TypeSystemClang>( + m_ast_context = std::make_shared<TypeSystemClang>( "Expression ASTContext for '" + m_filename + "'", ast_context); std::string module_name("$__lldb_module"); @@ -887,9 +875,9 @@ private: /// non-deterministic order, so this function should have no side effects. /// To make this easier to enforce, this function and all its parameters /// should always be const-qualified. - /// \return Returns llvm::None if no completion should be provided for the + /// \return Returns std::nullopt if no completion should be provided for the /// given CodeCompletionResult. - llvm::Optional<CompletionWithPriority> + std::optional<CompletionWithPriority> getCompletionForResult(const CodeCompletionResult &R) const { std::string ToInsert; std::string Description; @@ -934,9 +922,9 @@ private: // We also filter some internal lldb identifiers here. The user // shouldn't see these. if (llvm::StringRef(ToInsert).startswith("$__lldb_")) - return llvm::None; + return std::nullopt; if (ToInsert.empty()) - return llvm::None; + return std::nullopt; // Merge the suggested Token into the existing command line to comply // with the kind of result the lldb API expects. std::string CompletionSuggestion = @@ -978,7 +966,7 @@ public: continue; CodeCompletionResult &R = Results[I]; - llvm::Optional<CompletionWithPriority> CompletionAndPriority = + std::optional<CompletionWithPriority> CompletionAndPriority = getCompletionForResult(R); if (!CompletionAndPriority) continue; diff --git a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h index 6afee22da8d1..185a5a381f23 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h +++ b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h @@ -177,7 +177,7 @@ private: class LLDBPreprocessorCallbacks; LLDBPreprocessorCallbacks *m_pp_callbacks; ///< Called when the preprocessor ///encounters module imports - std::unique_ptr<TypeSystemClang> m_ast_context; + std::shared_ptr<TypeSystemClang> m_ast_context; std::vector<std::string> m_include_directories; /// File name used for the user expression. diff --git a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExternalASTSourceCallbacks.cpp b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExternalASTSourceCallbacks.cpp index 390afb458b5a..89d9ac042e57 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExternalASTSourceCallbacks.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExternalASTSourceCallbacks.cpp @@ -11,6 +11,7 @@ #include "clang/AST/Decl.h" #include "clang/AST/DeclObjC.h" +#include <optional> using namespace lldb_private; @@ -69,7 +70,7 @@ ClangExternalASTSourceCallbacks::RegisterModule(clang::Module *module) { return OptionalClangModuleID(id); } -llvm::Optional<clang::ASTSourceDescriptor> +std::optional<clang::ASTSourceDescriptor> ClangExternalASTSourceCallbacks::getSourceDescriptor(unsigned id) { if (clang::Module *module = getModule(id)) return {*module}; diff --git a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExternalASTSourceCallbacks.h b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExternalASTSourceCallbacks.h index 69088d9c82a5..219ed641615e 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExternalASTSourceCallbacks.h +++ b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExternalASTSourceCallbacks.h @@ -11,6 +11,7 @@ #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" #include "clang/Basic/Module.h" +#include <optional> namespace lldb_private { @@ -49,7 +50,7 @@ public: /// Module-related methods. /// \{ - llvm::Optional<clang::ASTSourceDescriptor> + std::optional<clang::ASTSourceDescriptor> getSourceDescriptor(unsigned ID) override; clang::Module *getModule(unsigned ID) override; OptionalClangModuleID RegisterModule(clang::Module *module); diff --git a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangHost.cpp b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangHost.cpp index 2099cfaaefec..ae4dcc05256e 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangHost.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangHost.cpp @@ -55,11 +55,11 @@ static bool DefaultComputeClangResourceDirectory(FileSpec &lldb_shlib_spec, static const llvm::StringRef kResourceDirSuffixes[] = { // LLVM.org's build of LLDB uses the clang resource directory placed // in $install_dir/lib{,64}/clang/$clang_version. - "lib" CLANG_LIBDIR_SUFFIX "/clang/" CLANG_VERSION_STRING, + CLANG_INSTALL_LIBDIR_BASENAME "/clang/" CLANG_VERSION_MAJOR_STRING, // swift-lldb uses the clang resource directory copied from swift, which // by default is placed in $install_dir/lib{,64}/lldb/clang. LLDB places - // it there, so we use LLDB_LIBDIR_SUFFIX. - "lib" LLDB_LIBDIR_SUFFIX "/lldb/clang", + // it there, so we use LLDB_INSTALL_LIBDIR_BASENAME. + LLDB_INSTALL_LIBDIR_BASENAME "/lldb/clang", }; for (const auto &Suffix : kResourceDirSuffixes) { @@ -72,7 +72,7 @@ static bool DefaultComputeClangResourceDirectory(FileSpec &lldb_shlib_spec, "DefaultComputeClangResourceDir: Setting ClangResourceDir " "to \"{0}\", verify = {1}", clang_dir.str(), verify ? "true" : "false"); - file_spec.GetDirectory().SetString(clang_dir); + file_spec.SetDirectory(clang_dir); FileSystem::Instance().Resolve(file_spec); return true; } @@ -119,7 +119,7 @@ bool lldb_private::ComputeClangResourceDirectory(FileSpec &lldb_shlib_spec, "Developer/Toolchains/XcodeDefault.xctoolchain", swift_clang_resource_dir); if (!verify || VerifyClangPath(clang_path)) { - file_spec.GetDirectory().SetString(clang_path.c_str()); + file_spec.SetDirectory(clang_path); FileSystem::Instance().Resolve(file_spec); return true; } @@ -134,7 +134,7 @@ bool lldb_private::ComputeClangResourceDirectory(FileSpec &lldb_shlib_spec, raw_path.resize(parent - r_end); llvm::sys::path::append(clang_path, raw_path, swift_clang_resource_dir); if (!verify || VerifyClangPath(clang_path)) { - file_spec.GetDirectory().SetString(clang_path.c_str()); + file_spec.SetDirectory(clang_path); FileSystem::Instance().Resolve(file_spec); return true; } @@ -145,7 +145,7 @@ bool lldb_private::ComputeClangResourceDirectory(FileSpec &lldb_shlib_spec, raw_path = lldb_shlib_spec.GetPath(); raw_path.resize(rev_it - r_end); raw_path.append("LLDB.framework/Resources/Clang"); - file_spec.GetDirectory().SetString(raw_path.c_str()); + file_spec.SetDirectory(raw_path); FileSystem::Instance().Resolve(file_spec); return true; #endif // __APPLE__ diff --git a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp index 38dd55bc76d3..2b98fc83097a 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp @@ -6,6 +6,9 @@ // //===----------------------------------------------------------------------===// +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/DiagnosticFrontend.h" +#include "clang/Basic/DiagnosticSerialization.h" #include "clang/Basic/TargetInfo.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendActions.h" @@ -15,7 +18,9 @@ #include "clang/Parse/Parser.h" #include "clang/Sema/Lookup.h" #include "clang/Serialization/ASTReader.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/FormatVariadic.h" #include "llvm/Support/Path.h" #include "llvm/Support/Threading.h" @@ -25,6 +30,7 @@ #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" #include "lldb/Core/ModuleList.h" +#include "lldb/Core/Progress.h" #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.h" #include "lldb/Symbol/CompileUnit.h" @@ -34,7 +40,6 @@ #include "lldb/Utility/LLDBAssert.h" #include "lldb/Utility/LLDBLog.h" #include "lldb/Utility/Log.h" -#include "lldb/Utility/ReproducerProvider.h" #include "lldb/Utility/StreamString.h" #include <memory> @@ -62,6 +67,9 @@ public: void EndSourceFile() override; private: + bool HandleModuleRemark(const clang::Diagnostic &info); + void SetCurrentModuleProgress(llvm::StringRef module_name); + typedef std::pair<clang::DiagnosticsEngine::Level, std::string> IDAndDiagnostic; std::vector<IDAndDiagnostic> m_diagnostics; @@ -73,6 +81,9 @@ private: /// Output string filled by m_os. Will be reused for different diagnostics. std::string m_output; Log *m_log; + /// A Progress with explicitly managed lifetime. + std::unique_ptr<Progress> m_current_progress_up; + std::vector<std::string> m_module_build_stack; }; /// The private implementation of our ClangModulesDeclVendor. Contains all the @@ -126,7 +137,7 @@ private: ImportedModuleSet m_user_imported_modules; // We assume that every ASTContext has an TypeSystemClang, so we also store // a custom TypeSystemClang for our internal ASTContext. - std::unique_ptr<TypeSystemClang> m_ast_context; + std::shared_ptr<TypeSystemClang> m_ast_context; }; } // anonymous namespace @@ -141,6 +152,9 @@ StoringDiagnosticConsumer::StoringDiagnosticConsumer() { void StoringDiagnosticConsumer::HandleDiagnostic( clang::DiagnosticsEngine::Level DiagLevel, const clang::Diagnostic &info) { + if (HandleModuleRemark(info)) + return; + // Print the diagnostic to m_output. m_output.clear(); m_diag_printer->HandleDiagnostic(DiagLevel, info); @@ -171,9 +185,54 @@ void StoringDiagnosticConsumer::BeginSourceFile( } void StoringDiagnosticConsumer::EndSourceFile() { + m_current_progress_up = nullptr; m_diag_printer->EndSourceFile(); } +bool StoringDiagnosticConsumer::HandleModuleRemark( + const clang::Diagnostic &info) { + Log *log = GetLog(LLDBLog::Expressions); + switch (info.getID()) { + case clang::diag::remark_module_build: { + const auto &module_name = info.getArgStdStr(0); + SetCurrentModuleProgress(module_name); + m_module_build_stack.push_back(module_name); + + const auto &module_path = info.getArgStdStr(1); + LLDB_LOG(log, "Building Clang module {0} as {1}", module_name, module_path); + return true; + } + case clang::diag::remark_module_build_done: { + // The current module is done. + m_module_build_stack.pop_back(); + if (m_module_build_stack.empty()) { + m_current_progress_up = nullptr; + } else { + // Update the progress to re-show the module that was currently being + // built from the time the now completed module was originally began. + const auto &resumed_module_name = m_module_build_stack.back(); + SetCurrentModuleProgress(resumed_module_name); + } + + const auto &module_name = info.getArgStdStr(0); + LLDB_LOG(log, "Finished building Clang module {0}", module_name); + return true; + } + default: + return false; + } +} + +void StoringDiagnosticConsumer::SetCurrentModuleProgress( + llvm::StringRef module_name) { + // Ensure the ordering of: + // 1. Completing the existing progress event. + // 2. Beginining a new progress event. + m_current_progress_up = nullptr; + m_current_progress_up = std::make_unique<Progress>( + llvm::formatv("Currently building module {0}", module_name)); +} + ClangModulesDeclVendor::ClangModulesDeclVendor() : ClangDeclVendor(eClangModuleDeclVendor) {} @@ -191,7 +250,7 @@ ClangModulesDeclVendorImpl::ClangModulesDeclVendorImpl( // Initialize our TypeSystemClang. m_ast_context = - std::make_unique<TypeSystemClang>("ClangModulesDeclVendor ASTContext", + std::make_shared<TypeSystemClang>("ClangModulesDeclVendor ASTContext", m_compiler_instance->getASTContext()); } @@ -610,7 +669,9 @@ ClangModulesDeclVendor::Create(Target &target) { "-target", arch.GetTriple().str(), "-fmodules-validate-system-headers", - "-Werror=non-modular-include-in-framework-module"}; + "-Werror=non-modular-include-in-framework-module", + "-Xclang=-fincremental-extensions", + "-Rmodule-build"}; target.GetPlatform()->AddClangModuleCompilationOptions( &target, compiler_invocation_arguments); @@ -648,16 +709,18 @@ ClangModulesDeclVendor::Create(Target &target) { } } - llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> diagnostics_engine = - clang::CompilerInstance::createDiagnostics(new clang::DiagnosticOptions, - new StoringDiagnosticConsumer); - std::vector<const char *> compiler_invocation_argument_cstrs; compiler_invocation_argument_cstrs.reserve( compiler_invocation_arguments.size()); for (const std::string &arg : compiler_invocation_arguments) compiler_invocation_argument_cstrs.push_back(arg.c_str()); + auto diag_options_up = + clang::CreateAndPopulateDiagOpts(compiler_invocation_argument_cstrs); + llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> diagnostics_engine = + clang::CompilerInstance::createDiagnostics(diag_options_up.release(), + new StoringDiagnosticConsumer); + Log *log = GetLog(LLDBLog::Expressions); LLDB_LOG(log, "ClangModulesDeclVendor's compiler flags {0:$[ ]}", llvm::make_range(compiler_invocation_arguments.begin(), @@ -683,18 +746,6 @@ ClangModulesDeclVendor::Create(Target &target) { std::unique_ptr<clang::CompilerInstance> instance( new clang::CompilerInstance); - // When capturing a reproducer, hook up the file collector with clang to - // collector modules and headers. - if (repro::Generator *g = repro::Reproducer::Instance().GetGenerator()) { - repro::FileProvider &fp = g->GetOrCreate<repro::FileProvider>(); - instance->setModuleDepCollector( - std::make_shared<ModuleDependencyCollectorAdaptor>( - fp.GetFileCollector())); - clang::DependencyOutputOptions &opts = instance->getDependencyOutputOpts(); - opts.IncludeSystemHeaders = true; - opts.IncludeModuleFiles = true; - } - // Make sure clang uses the same VFS as LLDB. instance->createFileManager(FileSystem::Instance().GetVirtualFileSystem()); instance->setDiagnostics(diagnostics_engine.get()); @@ -714,8 +765,6 @@ ClangModulesDeclVendor::Create(Target &target) { instance->getFrontendOpts().Inputs[0])) return nullptr; - instance->getPreprocessor().enableIncrementalProcessing(); - instance->createASTReader(); instance->createSema(action->getTranslationUnitKind(), nullptr); diff --git a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp index 13d6a37113b8..a7b20a5b6853 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp @@ -20,6 +20,8 @@ #include "clang/AST/Decl.h" #include "llvm/ADT/StringMap.h" +#include <optional> +#include <memory> using namespace lldb; using namespace lldb_private; @@ -68,25 +70,25 @@ void ClangPersistentVariables::RemovePersistentVariable( m_next_persistent_variable_id--; } -llvm::Optional<CompilerType> +std::optional<CompilerType> ClangPersistentVariables::GetCompilerTypeFromPersistentDecl( ConstString type_name) { PersistentDecl p = m_persistent_decls.lookup(type_name.GetCString()); if (p.m_decl == nullptr) - return llvm::None; + return std::nullopt; if (clang::TypeDecl *tdecl = llvm::dyn_cast<clang::TypeDecl>(p.m_decl)) { opaque_compiler_type_t t = static_cast<opaque_compiler_type_t>( const_cast<clang::Type *>(tdecl->getTypeForDecl())); return CompilerType(p.m_context, t); } - return llvm::None; + return std::nullopt; } -void ClangPersistentVariables::RegisterPersistentDecl(ConstString name, - clang::NamedDecl *decl, - TypeSystemClang *ctx) { +void ClangPersistentVariables::RegisterPersistentDecl( + ConstString name, clang::NamedDecl *decl, + std::shared_ptr<TypeSystemClang> ctx) { PersistentDecl p = {decl, ctx}; m_persistent_decls.insert(std::make_pair(name.GetCString(), p)); @@ -116,7 +118,7 @@ std::shared_ptr<ClangModulesDeclVendor> ClangPersistentVariables::GetClangModulesDeclVendor() { if (!m_modules_decl_vendor_sp) { m_modules_decl_vendor_sp.reset( - ClangModulesDeclVendor::Create(*m_target_sp.get())); + ClangModulesDeclVendor::Create(*m_target_sp)); } return m_modules_decl_vendor_sp; } diff --git a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h index b8a359d05f75..1ea4125077fa 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h +++ b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h @@ -15,6 +15,7 @@ #include "ClangModulesDeclVendor.h" #include "lldb/Expression/ExpressionVariable.h" +#include <optional> namespace lldb_private { @@ -65,11 +66,11 @@ public: return name; } - llvm::Optional<CompilerType> + std::optional<CompilerType> GetCompilerTypeFromPersistentDecl(ConstString type_name) override; void RegisterPersistentDecl(ConstString name, clang::NamedDecl *decl, - TypeSystemClang *ctx); + std::shared_ptr<TypeSystemClang> ctx); clang::NamedDecl *GetPersistentDecl(ConstString name); @@ -97,7 +98,7 @@ private: /// The persistent decl. clang::NamedDecl *m_decl = nullptr; /// The TypeSystemClang for the ASTContext of m_decl. - TypeSystemClang *m_context = nullptr; + lldb::TypeSystemWP m_context; }; typedef llvm::DenseMap<const char *, PersistentDecl> PersistentDeclMap; diff --git a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp index 7145e7804e68..3399f423f8fc 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp @@ -753,7 +753,7 @@ bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager, if (jit_module_sp) { ConstString const_func_name(FunctionName()); FileSpec jit_file; - jit_file.GetFilename() = const_func_name; + jit_file.SetFilename(const_func_name); jit_module_sp->SetFileSpecAndObjectName(jit_file, ConstString()); m_jit_module_wp = jit_module_sp; target->GetImages().Append(jit_module_sp); diff --git a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h index 4d5458f1807d..f05624c6119b 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h +++ b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h @@ -9,6 +9,7 @@ #ifndef LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_CLANGUSEREXPRESSION_H #define LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_CLANGUSEREXPRESSION_H +#include <optional> #include <vector> #include "ASTResultSynthesizer.h" @@ -232,7 +233,7 @@ private: /// The absolute character position in the transformed source code where the /// user code (as typed by the user) starts. If the variable is empty, then we /// were not able to calculate this position. - llvm::Optional<size_t> m_user_expression_start_pos; + std::optional<size_t> m_user_expression_start_pos; ResultDelegate m_result_delegate; ClangPersistentVariables *m_clang_state; std::unique_ptr<ClangExpressionSourceCode> m_source_code; diff --git a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangUtil.cpp b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangUtil.cpp index a7f5dce8558f..2e0bb318cb50 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangUtil.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangUtil.cpp @@ -19,7 +19,7 @@ bool ClangUtil::IsClangType(const CompilerType &ct) { if (!ct) return false; - if (llvm::dyn_cast_or_null<TypeSystemClang>(ct.GetTypeSystem()) == nullptr) + if (!ct.GetTypeSystem().dyn_cast_or_null<TypeSystemClang>()) return false; if (!ct.GetOpaqueQualType()) diff --git a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp index 3db3fcea0192..66493aa3e592 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp @@ -99,6 +99,12 @@ bool ClangUtilityFunction::Install(DiagnosticManager &diagnostic_manager, return false; } + // Since we might need to call allocate memory and maybe call code to make + // the caller, we need to be stopped. + if (process->GetState() != lldb::eStateStopped) { + diagnostic_manager.PutString(eDiagnosticSeverityError, "process running"); + return false; + } ////////////////////////// // Parse the expression // @@ -144,7 +150,7 @@ bool ClangUtilityFunction::Install(DiagnosticManager &diagnostic_manager, if (jit_module_sp) { ConstString const_func_name(FunctionName()); FileSpec jit_file; - jit_file.GetFilename() = const_func_name; + jit_file.SetFilename(const_func_name); jit_module_sp->SetFileSpecAndObjectName(jit_file, ConstString()); m_jit_module_wp = jit_module_sp; target->GetImages().Append(jit_module_sp); diff --git a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.cpp b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.cpp index befb1f125406..055ad0711f90 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.cpp @@ -11,6 +11,7 @@ #include "ClangHost.h" #include "lldb/Host/FileSystem.h" #include "llvm/ADT/Triple.h" +#include <optional> using namespace lldb_private; @@ -46,14 +47,14 @@ getTargetIncludePaths(const llvm::Triple &triple) { } /// Returns the include path matching the given pattern for the given file -/// path (or None if the path doesn't match the pattern). -static llvm::Optional<llvm::StringRef> +/// path (or std::nullopt if the path doesn't match the pattern). +static std::optional<llvm::StringRef> guessIncludePath(llvm::StringRef path_to_file, llvm::StringRef pattern) { if (pattern.empty()) - return llvm::NoneType(); + return std::nullopt; size_t pos = path_to_file.find(pattern); if (pos == llvm::StringRef::npos) - return llvm::NoneType(); + return std::nullopt; return path_to_file.substr(0, pos + pattern.size()); } @@ -83,7 +84,7 @@ bool CppModuleConfiguration::analyzeFile(const FileSpec &f, (posix_dir + triple.str() + "/c++/v1").str()); } - llvm::Optional<llvm::StringRef> inc_path; + std::optional<llvm::StringRef> inc_path; // Target specific paths contains /usr/include, so we check them first for (auto &path : getTargetIncludePaths(triple)) { if ((inc_path = guessIncludePath(posix_dir, path))) diff --git a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.h b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.h index 5db8abbdbdf3..3a87570bf804 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.h +++ b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.h @@ -30,7 +30,7 @@ class CppModuleConfiguration { public: /// Try setting the path. Returns true if the path was set and false if /// the path was already set. - LLVM_NODISCARD bool TrySet(llvm::StringRef path); + [[nodiscard]] bool TrySet(llvm::StringRef path); /// Return the path if there is one. llvm::StringRef Get() const { assert(m_valid && "Called Get() on an invalid SetOncePath?"); diff --git a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/CxxModuleHandler.cpp b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/CxxModuleHandler.cpp index 9453cdc3a451..3eda04dc022a 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/CxxModuleHandler.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/CxxModuleHandler.cpp @@ -13,6 +13,7 @@ #include "lldb/Utility/Log.h" #include "clang/Sema/Lookup.h" #include "llvm/Support/Error.h" +#include <optional> using namespace lldb_private; using namespace clang; @@ -180,27 +181,27 @@ T *createDecl(ASTImporter &importer, Decl *from_d, Args &&... args) { return to_d; } -llvm::Optional<Decl *> CxxModuleHandler::tryInstantiateStdTemplate(Decl *d) { +std::optional<Decl *> CxxModuleHandler::tryInstantiateStdTemplate(Decl *d) { Log *log = GetLog(LLDBLog::Expressions); // If we don't have a template to instiantiate, then there is nothing to do. auto td = dyn_cast<ClassTemplateSpecializationDecl>(d); if (!td) - return llvm::None; + return std::nullopt; // We only care about templates in the std namespace. if (!td->getDeclContext()->isStdNamespace()) - return llvm::None; + return std::nullopt; // We have a list of supported template names. if (!m_supported_templates.contains(td->getName())) - return llvm::None; + return std::nullopt; // Early check if we even support instantiating this template. We do this // before we import anything into the target AST. auto &foreign_args = td->getTemplateInstantiationArgs(); if (!templateArgsAreSupported(foreign_args.asArray())) - return llvm::None; + return std::nullopt; // Find the local DeclContext that corresponds to the DeclContext of our // decl we want to import. @@ -211,7 +212,7 @@ llvm::Optional<Decl *> CxxModuleHandler::tryInstantiateStdTemplate(Decl *d) { "Got error while searching equal local DeclContext for decl " "'{1}':\n{0}", td->getName()); - return llvm::None; + return std::nullopt; } // Look up the template in our local context. @@ -224,7 +225,7 @@ llvm::Optional<Decl *> CxxModuleHandler::tryInstantiateStdTemplate(Decl *d) { break; } if (!new_class_template) - return llvm::None; + return std::nullopt; // Import the foreign template arguments. llvm::SmallVector<TemplateArgument, 4> imported_args; @@ -236,7 +237,7 @@ llvm::Optional<Decl *> CxxModuleHandler::tryInstantiateStdTemplate(Decl *d) { llvm::Expected<QualType> type = m_importer->Import(arg.getAsType()); if (!type) { LLDB_LOG_ERROR(log, type.takeError(), "Couldn't import type: {0}"); - return llvm::None; + return std::nullopt; } imported_args.push_back(TemplateArgument(*type)); break; @@ -247,7 +248,7 @@ llvm::Optional<Decl *> CxxModuleHandler::tryInstantiateStdTemplate(Decl *d) { m_importer->Import(arg.getIntegralType()); if (!type) { LLDB_LOG_ERROR(log, type.takeError(), "Couldn't import type: {0}"); - return llvm::None; + return std::nullopt; } imported_args.push_back( TemplateArgument(d->getASTContext(), integral, *type)); @@ -287,7 +288,7 @@ llvm::Optional<Decl *> CxxModuleHandler::tryInstantiateStdTemplate(Decl *d) { return result; } -llvm::Optional<Decl *> CxxModuleHandler::Import(Decl *d) { +std::optional<Decl *> CxxModuleHandler::Import(Decl *d) { if (!isValid()) return {}; diff --git a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/CxxModuleHandler.h b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/CxxModuleHandler.h index 6490af7f8978..24289c83e88e 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/CxxModuleHandler.h +++ b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/CxxModuleHandler.h @@ -12,6 +12,7 @@ #include "clang/AST/ASTImporter.h" #include "clang/Sema/Sema.h" #include "llvm/ADT/StringSet.h" +#include <optional> namespace lldb_private { @@ -43,7 +44,7 @@ class CxxModuleHandler { /// Tries to manually instantiate the given foreign template in the target /// context (designated by m_sema). - llvm::Optional<clang::Decl *> tryInstantiateStdTemplate(clang::Decl *d); + std::optional<clang::Decl *> tryInstantiateStdTemplate(clang::Decl *d); public: CxxModuleHandler() = default; @@ -53,7 +54,7 @@ public: /// deserializing it from the 'std' module. This function returns a Decl if a /// Decl has been deserialized from the 'std' module. Otherwise this function /// returns nothing. - llvm::Optional<clang::Decl *> Import(clang::Decl *d); + std::optional<clang::Decl *> Import(clang::Decl *d); /// Returns true iff this instance is capable of importing any declarations /// in the target ASTContext. diff --git a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp index 047aa1e7c084..ec0243d92099 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp @@ -40,6 +40,7 @@ #include "lldb/Utility/StreamString.h" #include <map> +#include <optional> using namespace llvm; using lldb_private::LLDBLog; @@ -299,7 +300,7 @@ bool IRForTarget::CreateResultVariable(llvm::Function &llvm_function) { } lldb::TargetSP target_sp(m_execution_unit.GetTarget()); - llvm::Optional<uint64_t> bit_size = m_result_type.GetBitSize(target_sp.get()); + std::optional<uint64_t> bit_size = m_result_type.GetBitSize(target_sp.get()); if (!bit_size) { lldb_private::StreamString type_desc_stream; m_result_type.DumpTypeDescription(&type_desc_stream); @@ -1193,11 +1194,10 @@ bool IRForTarget::MaybeHandleVariable(Value *llvm_value_ptr) { } auto *target = m_execution_unit.GetTarget().get(); - llvm::Optional<uint64_t> value_size = compiler_type.GetByteSize(target); + std::optional<uint64_t> value_size = compiler_type.GetByteSize(target); if (!value_size) return false; - llvm::Optional<size_t> opt_alignment = - compiler_type.GetTypeBitAlign(target); + std::optional<size_t> opt_alignment = compiler_type.GetTypeBitAlign(target); if (!opt_alignment) return false; lldb::offset_t value_alignment = (*opt_alignment + 7ull) / 8ull; diff --git a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/NameSearchContext.cpp b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/NameSearchContext.cpp index a672045dfe31..a67cc8e10c17 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/NameSearchContext.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/NameSearchContext.cpp @@ -19,8 +19,7 @@ clang::NamedDecl *NameSearchContext::AddVarDecl(const CompilerType &type) { if (!type.IsValid()) return nullptr; - TypeSystemClang *lldb_ast = - llvm::dyn_cast<TypeSystemClang>(type.GetTypeSystem()); + auto lldb_ast = type.GetTypeSystem().dyn_cast_or_null<TypeSystemClang>(); if (!lldb_ast) return nullptr; @@ -46,8 +45,7 @@ clang::NamedDecl *NameSearchContext::AddFunDecl(const CompilerType &type, if (m_function_types.count(type)) return nullptr; - TypeSystemClang *lldb_ast = - llvm::dyn_cast<TypeSystemClang>(type.GetTypeSystem()); + auto lldb_ast = type.GetTypeSystem().dyn_cast_or_null<TypeSystemClang>(); if (!lldb_ast) return nullptr; diff --git a/contrib/llvm-project/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp b/contrib/llvm-project/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp index b00a17736679..5ab256a62e07 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include <cstdlib> +#include <optional> #include "EmulateInstructionARM.h" #include "EmulationStateARM.h" @@ -42,7 +43,8 @@ LLDB_PLUGIN_DEFINE_ADV(EmulateInstructionARM, InstructionARM) // ITSession implementation // -static bool GetARMDWARFRegisterInfo(unsigned reg_num, RegisterInfo ®_info) { +static std::optional<RegisterInfo> GetARMDWARFRegisterInfo(unsigned reg_num) { + RegisterInfo reg_info; ::memset(®_info, 0, sizeof(RegisterInfo)); ::memset(reg_info.kinds, LLDB_INVALID_REGNUM, sizeof(reg_info.kinds)); @@ -594,9 +596,9 @@ static bool GetARMDWARFRegisterInfo(unsigned reg_num, RegisterInfo ®_info) { break; default: - return false; + return {}; } - return true; + return reg_info; } // A8.6.50 @@ -782,9 +784,9 @@ bool EmulateInstructionARM::WriteBits32Unknown(int n) { return true; } -bool EmulateInstructionARM::GetRegisterInfo(lldb::RegisterKind reg_kind, - uint32_t reg_num, - RegisterInfo ®_info) { +std::optional<RegisterInfo> +EmulateInstructionARM::GetRegisterInfo(lldb::RegisterKind reg_kind, + uint32_t reg_num) { if (reg_kind == eRegisterKindGeneric) { switch (reg_num) { case LLDB_REGNUM_GENERIC_PC: @@ -808,13 +810,13 @@ bool EmulateInstructionARM::GetRegisterInfo(lldb::RegisterKind reg_kind, reg_num = dwarf_cpsr; break; default: - return false; + return {}; } } if (reg_kind == eRegisterKindDWARF) - return GetARMDWARFRegisterInfo(reg_num, reg_info); - return false; + return GetARMDWARFRegisterInfo(reg_num); + return {}; } uint32_t EmulateInstructionARM::GetFramePointerRegisterNumber() const { @@ -969,13 +971,13 @@ bool EmulateInstructionARM::EmulatePUSH(const uint32_t opcode, EmulateInstruction::Context context; context.type = EmulateInstruction::eContextPushRegisterOnStack; - RegisterInfo reg_info; - RegisterInfo sp_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg); + std::optional<RegisterInfo> sp_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_sp); for (i = 0; i < 15; ++i) { if (BitIsSet(registers, i)) { - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i, reg_info); - context.SetRegisterToRegisterPlusOffset(reg_info, sp_reg, addr - sp); + std::optional<RegisterInfo> reg_info = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i); + context.SetRegisterToRegisterPlusOffset(*reg_info, *sp_reg, addr - sp); uint32_t reg_value = ReadCoreReg(i, &success); if (!success) return false; @@ -986,8 +988,9 @@ bool EmulateInstructionARM::EmulatePUSH(const uint32_t opcode, } if (BitIsSet(registers, 15)) { - GetRegisterInfo(eRegisterKindDWARF, dwarf_pc, reg_info); - context.SetRegisterToRegisterPlusOffset(reg_info, sp_reg, addr - sp); + std::optional<RegisterInfo> reg_info = + GetRegisterInfo(eRegisterKindDWARF, dwarf_pc); + context.SetRegisterToRegisterPlusOffset(*reg_info, *sp_reg, addr - sp); const uint32_t pc = ReadCoreReg(PC_REG, &success); if (!success) return false; @@ -1097,8 +1100,8 @@ bool EmulateInstructionARM::EmulatePOP(const uint32_t opcode, EmulateInstruction::Context context; context.type = EmulateInstruction::eContextPopRegisterOffStack; - RegisterInfo sp_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg); + std::optional<RegisterInfo> sp_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_sp); for (i = 0; i < 15; ++i) { if (BitIsSet(registers, i)) { @@ -1114,7 +1117,7 @@ bool EmulateInstructionARM::EmulatePOP(const uint32_t opcode, } if (BitIsSet(registers, 15)) { - context.SetRegisterPlusOffset(sp_reg, addr - sp); + context.SetRegisterPlusOffset(*sp_reg, addr - sp); data = MemARead(context, addr, 4, 0, &success); if (!success) return false; @@ -1184,9 +1187,9 @@ bool EmulateInstructionARM::EmulateADDRdSPImm(const uint32_t opcode, context.type = eContextSetFramePointer; else context.type = EmulateInstruction::eContextRegisterPlusOffset; - RegisterInfo sp_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg); - context.SetRegisterPlusOffset(sp_reg, sp_offset); + std::optional<RegisterInfo> sp_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_sp); + context.SetRegisterPlusOffset(*sp_reg, sp_offset); if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + Rd, addr)) @@ -1240,9 +1243,9 @@ bool EmulateInstructionARM::EmulateMOVRdSP(const uint32_t opcode, context.type = EmulateInstruction::eContextSetFramePointer; else context.type = EmulateInstruction::eContextRegisterPlusOffset; - RegisterInfo sp_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg); - context.SetRegisterPlusOffset(sp_reg, 0); + std::optional<RegisterInfo> sp_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_sp); + context.SetRegisterPlusOffset(*sp_reg, 0); if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + Rd, sp)) return false; @@ -1337,9 +1340,9 @@ bool EmulateInstructionARM::EmulateMOVRdRm(const uint32_t opcode, context.type = EmulateInstruction::eContextSetFramePointer; else context.type = EmulateInstruction::eContextRegisterPlusOffset; - RegisterInfo dwarf_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg); - context.SetRegisterPlusOffset(dwarf_reg, 0); + std::optional<RegisterInfo> dwarf_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm); + context.SetRegisterPlusOffset(*dwarf_reg, 0); if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags)) return false; @@ -1556,14 +1559,14 @@ bool EmulateInstructionARM::EmulateMUL(const uint32_t opcode, uint64_t result = operand1 * operand2; // R[d] = result<31:0>; - RegisterInfo op1_reg; - RegisterInfo op2_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, op1_reg); - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, op2_reg); + std::optional<RegisterInfo> op1_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); + std::optional<RegisterInfo> op2_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m); EmulateInstruction::Context context; context.type = eContextArithmetic; - context.SetRegisterRegisterOperands(op1_reg, op2_reg); + context.SetRegisterRegisterOperands(*op1_reg, *op2_reg); if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d, (0x0000ffff & result))) @@ -1764,9 +1767,9 @@ bool EmulateInstructionARM::EmulateLDRRtPCRelative(const uint32_t opcode, // PC relative immediate load context EmulateInstruction::Context context; context.type = EmulateInstruction::eContextRegisterPlusOffset; - RegisterInfo pc_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_pc, pc_reg); - context.SetRegisterPlusOffset(pc_reg, 0); + std::optional<RegisterInfo> pc_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_pc); + context.SetRegisterPlusOffset(*pc_reg, 0); uint32_t Rt; // the destination register uint32_t imm32; // immediate offset from the PC @@ -1797,7 +1800,7 @@ bool EmulateInstructionARM::EmulateLDRRtPCRelative(const uint32_t opcode, else address = base - imm32; - context.SetRegisterPlusOffset(pc_reg, address - base); + context.SetRegisterPlusOffset(*pc_reg, address - base); data = MemURead(context, address, 4, 0, &success); if (!success) return false; @@ -1908,9 +1911,9 @@ bool EmulateInstructionARM::EmulateADDSPImm(const uint32_t opcode, else context.type = EmulateInstruction::eContextRegisterPlusOffset; - RegisterInfo sp_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg); - context.SetRegisterPlusOffset(sp_reg, res.result - sp); + std::optional<RegisterInfo> sp_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_sp); + context.SetRegisterPlusOffset(*sp_reg, res.result - sp); if (d == 15) { if (!ALUWritePC(context, res.result)) @@ -1975,12 +1978,11 @@ bool EmulateInstructionARM::EmulateADDSPRm(const uint32_t opcode, EmulateInstruction::Context context; context.type = eContextArithmetic; - RegisterInfo sp_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg); - - RegisterInfo other_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm, other_reg); - context.SetRegisterRegisterOperands(sp_reg, other_reg); + std::optional<RegisterInfo> sp_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_sp); + std::optional<RegisterInfo> other_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm); + context.SetRegisterRegisterOperands(*sp_reg, *other_reg); if (!WriteRegisterUnsigned(context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr)) @@ -2148,9 +2150,9 @@ bool EmulateInstructionARM::EmulateBLXRm(const uint32_t opcode, addr_t target = ReadCoreReg(Rm, &success); if (!success) return false; - RegisterInfo dwarf_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg); - context.SetRegister(dwarf_reg); + std::optional<RegisterInfo> dwarf_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm); + context.SetRegister(*dwarf_reg); if (!WriteRegisterUnsigned(context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr)) return false; @@ -2194,9 +2196,9 @@ bool EmulateInstructionARM::EmulateBXRm(const uint32_t opcode, if (!success) return false; - RegisterInfo dwarf_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg); - context.SetRegister(dwarf_reg); + std::optional<RegisterInfo> dwarf_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm); + context.SetRegister(*dwarf_reg); if (!BXWritePC(context, target)) return false; } @@ -2252,9 +2254,9 @@ bool EmulateInstructionARM::EmulateBXJRm(const uint32_t opcode, if (!success) return false; - RegisterInfo dwarf_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg); - context.SetRegister(dwarf_reg); + std::optional<RegisterInfo> dwarf_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm); + context.SetRegister(*dwarf_reg); if (!BXWritePC(context, target)) return false; } @@ -2301,9 +2303,9 @@ bool EmulateInstructionARM::EmulateSUBR7IPImm(const uint32_t opcode, EmulateInstruction::Context context; context.type = EmulateInstruction::eContextRegisterPlusOffset; - RegisterInfo dwarf_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r12, dwarf_reg); - context.SetRegisterPlusOffset(dwarf_reg, -ip_offset); + std::optional<RegisterInfo> dwarf_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r12); + context.SetRegisterPlusOffset(*dwarf_reg, -ip_offset); if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r7, addr)) return false; @@ -2351,9 +2353,9 @@ bool EmulateInstructionARM::EmulateSUBIPSPImm(const uint32_t opcode, EmulateInstruction::Context context; context.type = EmulateInstruction::eContextRegisterPlusOffset; - RegisterInfo dwarf_reg; - GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, dwarf_reg); - context.SetRegisterPlusOffset(dwarf_reg, -sp_offset); + std::optional<RegisterInfo> dwarf_reg = + GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP); + context.SetRegisterPlusOffset(*dwarf_reg, -sp_offset); if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r12, addr)) return false; @@ -2513,12 +2515,12 @@ bool EmulateInstructionARM::EmulateSTRRtSP(const uint32_t opcode, EmulateInstruction::Context context; context.type = EmulateInstruction::eContextPushRegisterOnStack; - RegisterInfo sp_reg; - RegisterInfo dwarf_reg; + std::optional<RegisterInfo> sp_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_sp); + std::optional<RegisterInfo> dwarf_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rt); - GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg); - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rt, dwarf_reg); - context.SetRegisterToRegisterPlusOffset(dwarf_reg, sp_reg, addr - sp); + context.SetRegisterToRegisterPlusOffset(*dwarf_reg, *sp_reg, addr - sp); if (Rt != 15) { uint32_t reg_value = ReadCoreReg(Rt, &success); if (!success) @@ -2612,14 +2614,14 @@ bool EmulateInstructionARM::EmulateVPUSH(const uint32_t opcode, EmulateInstruction::Context context; context.type = EmulateInstruction::eContextPushRegisterOnStack; - RegisterInfo dwarf_reg; - RegisterInfo sp_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg); + std::optional<RegisterInfo> sp_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_sp); for (i = 0; i < regs; ++i) { - GetRegisterInfo(eRegisterKindDWARF, start_reg + d + i, dwarf_reg); - context.SetRegisterToRegisterPlusOffset(dwarf_reg, sp_reg, addr - sp); + std::optional<RegisterInfo> dwarf_reg = + GetRegisterInfo(eRegisterKindDWARF, start_reg + d + i); + context.SetRegisterToRegisterPlusOffset(*dwarf_reg, *sp_reg, addr - sp); // uint64_t to accommodate 64-bit registers. - uint64_t reg_value = ReadRegisterUnsigned(&dwarf_reg, 0, &success); + uint64_t reg_value = ReadRegisterUnsigned(*dwarf_reg, 0, &success); if (!success) return false; if (!MemAWrite(context, addr, reg_value, reg_byte_size)) @@ -2705,16 +2707,14 @@ bool EmulateInstructionARM::EmulateVPOP(const uint32_t opcode, EmulateInstruction::Context context; context.type = EmulateInstruction::eContextPopRegisterOffStack; - RegisterInfo dwarf_reg; - RegisterInfo sp_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg); for (i = 0; i < regs; ++i) { - GetRegisterInfo(eRegisterKindDWARF, start_reg + d + i, dwarf_reg); + std::optional<RegisterInfo> dwarf_reg = + GetRegisterInfo(eRegisterKindDWARF, start_reg + d + i); context.SetAddress(addr); data = MemARead(context, addr, reg_byte_size, 0, &success); if (!success) return false; - if (!WriteRegisterUnsigned(context, &dwarf_reg, data)) + if (!WriteRegisterUnsigned(context, *dwarf_reg, data)) return false; addr += reg_byte_size; } @@ -3106,12 +3106,11 @@ bool EmulateInstructionARM::EmulateADDImmThumb(const uint32_t opcode, //(result, carry, overflow) = AddWithCarry(R[n], imm32, '0'); AddWithCarryResult res = AddWithCarry(Rn, imm32, 0); - RegisterInfo reg_n; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, reg_n); - + std::optional<RegisterInfo> reg_n = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); EmulateInstruction::Context context; context.type = eContextArithmetic; - context.SetRegisterPlusOffset(reg_n, imm32); + context.SetRegisterPlusOffset(*reg_n, imm32); // R[d] = result; // if setflags then @@ -3180,9 +3179,9 @@ bool EmulateInstructionARM::EmulateADDImmARM(const uint32_t opcode, else context.type = EmulateInstruction::eContextRegisterPlusOffset; - RegisterInfo dwarf_reg; - GetRegisterInfo(eRegisterKindDWARF, Rn, dwarf_reg); - context.SetRegisterPlusOffset(dwarf_reg, imm32); + std::optional<RegisterInfo> dwarf_reg = + GetRegisterInfo(eRegisterKindDWARF, Rn); + context.SetRegisterPlusOffset(*dwarf_reg, imm32); if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) @@ -3268,11 +3267,11 @@ bool EmulateInstructionARM::EmulateADDReg(const uint32_t opcode, EmulateInstruction::Context context; context.type = eContextArithmetic; - RegisterInfo op1_reg; - RegisterInfo op2_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rn, op1_reg); - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm, op2_reg); - context.SetRegisterRegisterOperands(op1_reg, op2_reg); + std::optional<RegisterInfo> op1_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rn); + std::optional<RegisterInfo> op2_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm); + context.SetRegisterRegisterOperands(*op1_reg, *op2_reg); if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) @@ -3769,10 +3768,6 @@ bool EmulateInstructionARM::EmulateShiftImm(const uint32_t opcode, switch (use_encoding) { case eEncodingT1: - // Due to the above special case handling! - if (shift_type == SRType_ROR) - return false; - Rd = Bits32(opcode, 2, 0); Rm = Bits32(opcode, 5, 3); setflags = !InITBlock(); @@ -3983,14 +3978,14 @@ bool EmulateInstructionARM::EmulateLDM(const uint32_t opcode, EmulateInstruction::Context context; context.type = EmulateInstruction::eContextRegisterPlusOffset; - RegisterInfo dwarf_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg); - context.SetRegisterPlusOffset(dwarf_reg, offset); + std::optional<RegisterInfo> dwarf_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); + context.SetRegisterPlusOffset(*dwarf_reg, offset); for (int i = 0; i < 14; ++i) { if (BitIsSet(registers, i)) { context.type = EmulateInstruction::eContextRegisterPlusOffset; - context.SetRegisterPlusOffset(dwarf_reg, offset); + context.SetRegisterPlusOffset(*dwarf_reg, offset); if (wback && (n == 13)) // Pop Instruction { context.type = EmulateInstruction::eContextPopRegisterOffStack; @@ -4014,7 +4009,7 @@ bool EmulateInstructionARM::EmulateLDM(const uint32_t opcode, if (BitIsSet(registers, 15)) { // LoadWritePC (MemA [address, 4]); context.type = EmulateInstruction::eContextRegisterPlusOffset; - context.SetRegisterPlusOffset(dwarf_reg, offset); + context.SetRegisterPlusOffset(*dwarf_reg, offset); uint32_t data = MemARead(context, base_address + offset, addr_byte_size, 0, &success); if (!success) @@ -4028,7 +4023,7 @@ bool EmulateInstructionARM::EmulateLDM(const uint32_t opcode, // R[n] = R[n] + 4 * BitCount (registers) int32_t offset = addr_byte_size * BitCount(registers); context.type = EmulateInstruction::eContextAdjustBaseRegister; - context.SetRegisterPlusOffset(dwarf_reg, offset); + context.SetRegisterPlusOffset(*dwarf_reg, offset); if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset)) @@ -4103,16 +4098,16 @@ bool EmulateInstructionARM::EmulateLDMDA(const uint32_t opcode, EmulateInstruction::Context context; context.type = EmulateInstruction::eContextRegisterPlusOffset; - RegisterInfo dwarf_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg); - context.SetRegisterPlusOffset(dwarf_reg, offset); + std::optional<RegisterInfo> dwarf_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); + context.SetRegisterPlusOffset(*dwarf_reg, offset); // for i = 0 to 14 for (int i = 0; i < 14; ++i) { // if registers<i> == '1' then if (BitIsSet(registers, i)) { // R[i] = MemA[address,4]; address = address + 4; - context.SetRegisterPlusOffset(dwarf_reg, Rn - (address + offset)); + context.SetRegisterPlusOffset(*dwarf_reg, Rn - (address + offset)); uint32_t data = MemARead(context, address + offset, addr_byte_size, 0, &success); if (!success) @@ -4127,7 +4122,7 @@ bool EmulateInstructionARM::EmulateLDMDA(const uint32_t opcode, // if registers<15> == '1' then // LoadWritePC(MemA[address,4]); if (BitIsSet(registers, 15)) { - context.SetRegisterPlusOffset(dwarf_reg, offset); + context.SetRegisterPlusOffset(*dwarf_reg, offset); uint32_t data = MemARead(context, address + offset, addr_byte_size, 0, &success); if (!success) @@ -4139,8 +4134,6 @@ bool EmulateInstructionARM::EmulateLDMDA(const uint32_t opcode, // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers); if (wback && BitIsClear(registers, n)) { - if (!success) - return false; offset = (addr_byte_size * BitCount(registers)) * -1; context.type = EmulateInstruction::eContextAdjustBaseRegister; @@ -4241,14 +4234,14 @@ bool EmulateInstructionARM::EmulateLDMDB(const uint32_t opcode, addr_t address = Rn - (addr_byte_size * BitCount(registers)); EmulateInstruction::Context context; context.type = EmulateInstruction::eContextRegisterPlusOffset; - RegisterInfo dwarf_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg); - context.SetRegisterPlusOffset(dwarf_reg, Rn - address); + std::optional<RegisterInfo> dwarf_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); + context.SetRegisterPlusOffset(*dwarf_reg, Rn - address); for (int i = 0; i < 14; ++i) { if (BitIsSet(registers, i)) { // R[i] = MemA[address,4]; address = address + 4; - context.SetRegisterPlusOffset(dwarf_reg, Rn - (address + offset)); + context.SetRegisterPlusOffset(*dwarf_reg, Rn - (address + offset)); uint32_t data = MemARead(context, address + offset, addr_byte_size, 0, &success); if (!success) @@ -4265,7 +4258,7 @@ bool EmulateInstructionARM::EmulateLDMDB(const uint32_t opcode, // if registers<15> == '1' then // LoadWritePC(MemA[address,4]); if (BitIsSet(registers, 15)) { - context.SetRegisterPlusOffset(dwarf_reg, offset); + context.SetRegisterPlusOffset(*dwarf_reg, offset); uint32_t data = MemARead(context, address + offset, addr_byte_size, 0, &success); if (!success) @@ -4277,8 +4270,6 @@ bool EmulateInstructionARM::EmulateLDMDB(const uint32_t opcode, // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers); if (wback && BitIsClear(registers, n)) { - if (!success) - return false; offset = (addr_byte_size * BitCount(registers)) * -1; context.type = EmulateInstruction::eContextAdjustBaseRegister; @@ -4354,15 +4345,15 @@ bool EmulateInstructionARM::EmulateLDMIB(const uint32_t opcode, EmulateInstruction::Context context; context.type = EmulateInstruction::eContextRegisterPlusOffset; - RegisterInfo dwarf_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg); - context.SetRegisterPlusOffset(dwarf_reg, offset); + std::optional<RegisterInfo> dwarf_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); + context.SetRegisterPlusOffset(*dwarf_reg, offset); for (int i = 0; i < 14; ++i) { if (BitIsSet(registers, i)) { // R[i] = MemA[address,4]; address = address + 4; - context.SetRegisterPlusOffset(dwarf_reg, offset + addr_byte_size); + context.SetRegisterPlusOffset(*dwarf_reg, offset + addr_byte_size); uint32_t data = MemARead(context, address + offset, addr_byte_size, 0, &success); if (!success) @@ -4379,7 +4370,7 @@ bool EmulateInstructionARM::EmulateLDMIB(const uint32_t opcode, // if registers<15> == '1' then // LoadWritePC(MemA[address,4]); if (BitIsSet(registers, 15)) { - context.SetRegisterPlusOffset(dwarf_reg, offset); + context.SetRegisterPlusOffset(*dwarf_reg, offset); uint32_t data = MemARead(context, address + offset, addr_byte_size, 0, &success); if (!success) @@ -4391,8 +4382,6 @@ bool EmulateInstructionARM::EmulateLDMIB(const uint32_t opcode, // if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers); if (wback && BitIsClear(registers, n)) { - if (!success) - return false; offset = addr_byte_size * BitCount(registers); context.type = EmulateInstruction::eContextAdjustBaseRegister; @@ -4526,8 +4515,8 @@ bool EmulateInstructionARM::EmulateLDRRtRnImm(const uint32_t opcode, address = (index ? offset_addr : base); - RegisterInfo base_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rn, base_reg); + std::optional<RegisterInfo> base_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rn); if (wback) { EmulateInstruction::Context ctx; if (Rn == 13) { @@ -4535,10 +4524,10 @@ bool EmulateInstructionARM::EmulateLDRRtRnImm(const uint32_t opcode, ctx.SetImmediateSigned((int32_t)(offset_addr - base)); } else if (Rn == GetFramePointerRegisterNumber()) { ctx.type = eContextSetFramePointer; - ctx.SetRegisterPlusOffset(base_reg, (int32_t)(offset_addr - base)); + ctx.SetRegisterPlusOffset(*base_reg, (int32_t)(offset_addr - base)); } else { ctx.type = EmulateInstruction::eContextAdjustBaseRegister; - ctx.SetRegisterPlusOffset(base_reg, (int32_t)(offset_addr - base)); + ctx.SetRegisterPlusOffset(*base_reg, (int32_t)(offset_addr - base)); } if (!WriteRegisterUnsigned(ctx, eRegisterKindDWARF, dwarf_r0 + Rn, @@ -4549,7 +4538,7 @@ bool EmulateInstructionARM::EmulateLDRRtRnImm(const uint32_t opcode, // Prepare to write to the Rt register. EmulateInstruction::Context context; context.type = EmulateInstruction::eContextRegisterLoad; - context.SetRegisterPlusOffset(base_reg, (int32_t)(offset_addr - base)); + context.SetRegisterPlusOffset(*base_reg, (int32_t)(offset_addr - base)); // Read memory from the address. data = MemURead(context, address, 4, 0, &success); @@ -4662,8 +4651,8 @@ bool EmulateInstructionARM::EmulateSTM(const uint32_t opcode, EmulateInstruction::Context context; context.type = EmulateInstruction::eContextRegisterStore; - RegisterInfo base_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); + std::optional<RegisterInfo> base_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); // for i = 0 to 14 uint32_t lowest_set_bit = 14; @@ -4684,9 +4673,9 @@ bool EmulateInstructionARM::EmulateSTM(const uint32_t opcode, if (!success) return false; - RegisterInfo data_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i, data_reg); - context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, offset); + std::optional<RegisterInfo> data_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i); + context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, offset); if (!MemAWrite(context, address + offset, data, addr_byte_size)) return false; } @@ -4699,9 +4688,9 @@ bool EmulateInstructionARM::EmulateSTM(const uint32_t opcode, // if registers<15> == '1' then // Only possible for encoding A1 // MemA[address,4] = PCStoreValue(); if (BitIsSet(registers, 15)) { - RegisterInfo pc_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_pc, pc_reg); - context.SetRegisterPlusOffset(pc_reg, 8); + std::optional<RegisterInfo> pc_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_pc); + context.SetRegisterPlusOffset(*pc_reg, 8); const uint32_t pc = ReadCoreReg(PC_REG, &success); if (!success) return false; @@ -4784,8 +4773,8 @@ bool EmulateInstructionARM::EmulateSTMDA(const uint32_t opcode, EmulateInstruction::Context context; context.type = EmulateInstruction::eContextRegisterStore; - RegisterInfo base_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); + std::optional<RegisterInfo> base_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); // for i = 0 to 14 uint32_t lowest_bit_set = 14; @@ -4805,9 +4794,9 @@ bool EmulateInstructionARM::EmulateSTMDA(const uint32_t opcode, if (!success) return false; - RegisterInfo data_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i, data_reg); - context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, + std::optional<RegisterInfo> data_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i); + context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, Rn - (address + offset)); if (!MemAWrite(context, address + offset, data, addr_byte_size)) return false; @@ -4821,9 +4810,9 @@ bool EmulateInstructionARM::EmulateSTMDA(const uint32_t opcode, // if registers<15> == '1' then // MemA[address,4] = PCStoreValue(); if (BitIsSet(registers, 15)) { - RegisterInfo pc_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_pc, pc_reg); - context.SetRegisterPlusOffset(pc_reg, 8); + std::optional<RegisterInfo> pc_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_pc); + context.SetRegisterPlusOffset(*pc_reg, 8); const uint32_t pc = ReadCoreReg(PC_REG, &success); if (!success) return false; @@ -4932,8 +4921,8 @@ bool EmulateInstructionARM::EmulateSTMDB(const uint32_t opcode, EmulateInstruction::Context context; context.type = EmulateInstruction::eContextRegisterStore; - RegisterInfo base_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); + std::optional<RegisterInfo> base_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); // for i = 0 to 14 uint32_t lowest_set_bit = 14; @@ -4954,9 +4943,9 @@ bool EmulateInstructionARM::EmulateSTMDB(const uint32_t opcode, if (!success) return false; - RegisterInfo data_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i, data_reg); - context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, + std::optional<RegisterInfo> data_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i); + context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, Rn - (address + offset)); if (!MemAWrite(context, address + offset, data, addr_byte_size)) return false; @@ -4970,9 +4959,9 @@ bool EmulateInstructionARM::EmulateSTMDB(const uint32_t opcode, // if registers<15> == '1' then // Only possible for encoding A1 // MemA[address,4] = PCStoreValue(); if (BitIsSet(registers, 15)) { - RegisterInfo pc_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_pc, pc_reg); - context.SetRegisterPlusOffset(pc_reg, 8); + std::optional<RegisterInfo> pc_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_pc); + context.SetRegisterPlusOffset(*pc_reg, 8); const uint32_t pc = ReadCoreReg(PC_REG, &success); if (!success) return false; @@ -5055,8 +5044,8 @@ bool EmulateInstructionARM::EmulateSTMIB(const uint32_t opcode, EmulateInstruction::Context context; context.type = EmulateInstruction::eContextRegisterStore; - RegisterInfo base_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); + std::optional<RegisterInfo> base_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); uint32_t lowest_set_bit = 14; // for i = 0 to 14 @@ -5077,9 +5066,9 @@ bool EmulateInstructionARM::EmulateSTMIB(const uint32_t opcode, if (!success) return false; - RegisterInfo data_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i, data_reg); - context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, + std::optional<RegisterInfo> data_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i); + context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, offset + addr_byte_size); if (!MemAWrite(context, address + offset, data, addr_byte_size)) return false; @@ -5093,9 +5082,9 @@ bool EmulateInstructionARM::EmulateSTMIB(const uint32_t opcode, // if registers<15> == '1' then // MemA[address,4] = PCStoreValue(); if (BitIsSet(registers, 15)) { - RegisterInfo pc_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_pc, pc_reg); - context.SetRegisterPlusOffset(pc_reg, 8); + std::optional<RegisterInfo> pc_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_pc); + context.SetRegisterPlusOffset(*pc_reg, 8); const uint32_t pc = ReadCoreReg(PC_REG, &success); if (!success) return false; @@ -5246,8 +5235,8 @@ bool EmulateInstructionARM::EmulateSTRThumb(const uint32_t opcode, else context.type = eContextRegisterStore; - RegisterInfo base_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); + std::optional<RegisterInfo> base_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); // if UnalignedSupport() || address<1:0> == '00' then if (UnalignedSupport() || @@ -5258,10 +5247,10 @@ bool EmulateInstructionARM::EmulateSTRThumb(const uint32_t opcode, if (!success) return false; - RegisterInfo data_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg); + std::optional<RegisterInfo> data_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t); int32_t offset = address - base_address; - context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, offset); + context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, offset); if (!MemUWrite(context, address, data, addr_byte_size)) return false; } else { @@ -5452,13 +5441,12 @@ bool EmulateInstructionARM::EmulateSTRRegister(const uint32_t opcode, CurrentInstrSet() == eModeARM) { // MemU[address,4] = data; - RegisterInfo base_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); - - RegisterInfo data_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg); + std::optional<RegisterInfo> base_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); + std::optional<RegisterInfo> data_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t); - context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, + context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, address - base_address); if (!MemUWrite(context, address, data, addr_byte_size)) return false; @@ -5578,15 +5566,14 @@ bool EmulateInstructionARM::EmulateSTRBThumb(const uint32_t opcode, address = base_address; // MemU[address,1] = R[t]<7:0> - RegisterInfo base_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); - - RegisterInfo data_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg); + std::optional<RegisterInfo> base_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); + std::optional<RegisterInfo> data_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t); EmulateInstruction::Context context; context.type = eContextRegisterStore; - context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, + context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, address - base_address); uint32_t data = @@ -5748,10 +5735,6 @@ bool EmulateInstructionARM::EmulateSTRHRegister(const uint32_t opcode, EmulateInstruction::Context context; context.type = eContextRegisterStore; - RegisterInfo base_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); - RegisterInfo offset_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, offset_reg); // if UnalignedSupport() || address<0> == '0' then if (UnalignedSupport() || BitIsClear(address, 0)) { @@ -5762,14 +5745,14 @@ bool EmulateInstructionARM::EmulateSTRHRegister(const uint32_t opcode, EmulateInstruction::Context context; context.type = eContextRegisterStore; - RegisterInfo base_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); - RegisterInfo offset_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, offset_reg); - RegisterInfo data_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg); - context.SetRegisterToRegisterPlusIndirectOffset(base_reg, offset_reg, - data_reg); + std::optional<RegisterInfo> base_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); + std::optional<RegisterInfo> offset_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m); + std::optional<RegisterInfo> data_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t); + context.SetRegisterToRegisterPlusIndirectOffset(*base_reg, *offset_reg, + *data_reg); if (!MemUWrite(context, address, Bits32(Rt, 15, 0), 2)) return false; @@ -6416,12 +6399,11 @@ bool EmulateInstructionARM::EmulateLDRImmediateARM(const uint32_t opcode, // data = MemU[address,4]; - RegisterInfo base_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); - + std::optional<RegisterInfo> base_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); EmulateInstruction::Context context; context.type = eContextRegisterLoad; - context.SetRegisterPlusOffset(base_reg, address - base_address); + context.SetRegisterPlusOffset(*base_reg, address - base_address); uint64_t data = MemURead(context, address, addr_byte_size, 0, &success); if (!success) @@ -6442,7 +6424,7 @@ bool EmulateInstructionARM::EmulateLDRImmediateARM(const uint32_t opcode, if (BitIsClear(address, 1) && BitIsClear(address, 0)) { // LoadWritePC (data); context.type = eContextRegisterLoad; - context.SetRegisterPlusOffset(base_reg, address - base_address); + context.SetRegisterPlusOffset(*base_reg, address - base_address); LoadWritePC(context, data); } else return false; @@ -6452,7 +6434,7 @@ bool EmulateInstructionARM::EmulateLDRImmediateARM(const uint32_t opcode, (BitIsClear(address, 1) && BitIsClear(address, 0))) { // R[t] = data; context.type = eContextRegisterLoad; - context.SetRegisterPlusOffset(base_reg, address - base_address); + context.SetRegisterPlusOffset(*base_reg, address - base_address); if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data)) return false; @@ -6622,12 +6604,11 @@ bool EmulateInstructionARM::EmulateLDRRegister(const uint32_t opcode, address = Rn; // data = MemU[address,4]; - RegisterInfo base_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); - + std::optional<RegisterInfo> base_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); EmulateInstruction::Context context; context.type = eContextRegisterLoad; - context.SetRegisterPlusOffset(base_reg, address - Rn); + context.SetRegisterPlusOffset(*base_reg, address - Rn); uint64_t data = MemURead(context, address, addr_byte_size, 0, &success); if (!success) @@ -6647,7 +6628,7 @@ bool EmulateInstructionARM::EmulateLDRRegister(const uint32_t opcode, // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE; if (BitIsClear(address, 1) && BitIsClear(address, 0)) { context.type = eContextRegisterLoad; - context.SetRegisterPlusOffset(base_reg, address - Rn); + context.SetRegisterPlusOffset(*base_reg, address - Rn); LoadWritePC(context, data); } else return false; @@ -6657,7 +6638,7 @@ bool EmulateInstructionARM::EmulateLDRRegister(const uint32_t opcode, (BitIsClear(address, 1) && BitIsClear(address, 0))) { // R[t] = data; context.type = eContextRegisterLoad; - context.SetRegisterPlusOffset(base_reg, address - Rn); + context.SetRegisterPlusOffset(*base_reg, address - Rn); if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data)) return false; @@ -6800,14 +6781,14 @@ bool EmulateInstructionARM::EmulateLDRBImmediate(const uint32_t opcode, address = Rn; // R[t] = ZeroExtend(MemU[address,1], 32); - RegisterInfo base_reg; - RegisterInfo data_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg); + std::optional<RegisterInfo> base_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); + std::optional<RegisterInfo> data_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t); EmulateInstruction::Context context; context.type = eContextRegisterLoad; - context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, address - Rn); + context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, address - Rn); uint64_t data = MemURead(context, address, 1, 0, &success); if (!success) @@ -7044,12 +7025,12 @@ bool EmulateInstructionARM::EmulateLDRBRegister(const uint32_t opcode, address = Rn; // R[t] = ZeroExtend(MemU[address,1],32); - RegisterInfo base_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); + std::optional<RegisterInfo> base_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); EmulateInstruction::Context context; context.type = eContextRegisterLoad; - context.SetRegisterPlusOffset(base_reg, address - Rn); + context.SetRegisterPlusOffset(*base_reg, address - Rn); uint64_t data = MemURead(context, address, 1, 0, &success); if (!success) @@ -7181,12 +7162,12 @@ bool EmulateInstructionARM::EmulateLDRHImmediate(const uint32_t opcode, address = Rn; // data = MemU[address,2]; - RegisterInfo base_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); + std::optional<RegisterInfo> base_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); EmulateInstruction::Context context; context.type = eContextRegisterLoad; - context.SetRegisterPlusOffset(base_reg, address - Rn); + context.SetRegisterPlusOffset(*base_reg, address - Rn); uint64_t data = MemURead(context, address, 2, 0, &success); if (!success) @@ -7205,7 +7186,7 @@ bool EmulateInstructionARM::EmulateLDRHImmediate(const uint32_t opcode, if (UnalignedSupport() || BitIsClear(address, 0)) { // R[t] = ZeroExtend(data, 32); context.type = eContextRegisterLoad; - context.SetRegisterPlusOffset(base_reg, address - Rn); + context.SetRegisterPlusOffset(*base_reg, address - Rn); if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data)) return false; @@ -7291,12 +7272,12 @@ bool EmulateInstructionARM::EmulateLDRHLiteral(const uint32_t opcode, address = base - imm32; // data = MemU[address,2]; - RegisterInfo base_reg; - GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, base_reg); + std::optional<RegisterInfo> base_reg = + GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); EmulateInstruction::Context context; context.type = eContextRegisterLoad; - context.SetRegisterPlusOffset(base_reg, address - base); + context.SetRegisterPlusOffset(*base_reg, address - base); uint64_t data = MemURead(context, address, 2, 0, &success); if (!success) @@ -7306,7 +7287,7 @@ bool EmulateInstructionARM::EmulateLDRHLiteral(const uint32_t opcode, if (UnalignedSupport() || BitIsClear(address, 0)) { // R[t] = ZeroExtend(data, 32); context.type = eContextRegisterLoad; - context.SetRegisterPlusOffset(base_reg, address - base); + context.SetRegisterPlusOffset(*base_reg, address - base); if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data)) return false; @@ -7459,14 +7440,14 @@ bool EmulateInstructionARM::EmulateLDRHRegister(const uint32_t opcode, address = Rn; // data = MemU[address,2]; - RegisterInfo base_reg; - RegisterInfo offset_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, offset_reg); + std::optional<RegisterInfo> base_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); + std::optional<RegisterInfo> offset_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m); EmulateInstruction::Context context; context.type = eContextRegisterLoad; - context.SetRegisterPlusIndirectOffset(base_reg, offset_reg); + context.SetRegisterPlusIndirectOffset(*base_reg, *offset_reg); uint64_t data = MemURead(context, address, 2, 0, &success); if (!success) return false; @@ -7484,7 +7465,7 @@ bool EmulateInstructionARM::EmulateLDRHRegister(const uint32_t opcode, if (UnalignedSupport() || BitIsClear(address, 0)) { // R[t] = ZeroExtend(data, 32); context.type = eContextRegisterLoad; - context.SetRegisterPlusIndirectOffset(base_reg, offset_reg); + context.SetRegisterPlusIndirectOffset(*base_reg, *offset_reg); if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data)) return false; @@ -7618,12 +7599,12 @@ bool EmulateInstructionARM::EmulateLDRSBImmediate(const uint32_t opcode, address = Rn; // R[t] = SignExtend(MemU[address,1], 32); - RegisterInfo base_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); + std::optional<RegisterInfo> base_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); EmulateInstruction::Context context; context.type = eContextRegisterLoad; - context.SetRegisterPlusOffset(base_reg, address - Rn); + context.SetRegisterPlusOffset(*base_reg, address - Rn); uint64_t unsigned_data = MemURead(context, address, 1, 0, &success); if (!success) @@ -7715,12 +7696,12 @@ bool EmulateInstructionARM::EmulateLDRSBLiteral(const uint32_t opcode, address = base - imm32; // R[t] = SignExtend(MemU[address,1], 32); - RegisterInfo base_reg; - GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, base_reg); + std::optional<RegisterInfo> base_reg = + GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); EmulateInstruction::Context context; context.type = eContextRegisterLoad; - context.SetRegisterPlusOffset(base_reg, address - base); + context.SetRegisterPlusOffset(*base_reg, address - base); uint64_t unsigned_data = MemURead(context, address, 1, 0, &success); if (!success) @@ -7864,14 +7845,14 @@ bool EmulateInstructionARM::EmulateLDRSBRegister(const uint32_t opcode, address = Rn; // R[t] = SignExtend(MemU[address,1], 32); - RegisterInfo base_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); - RegisterInfo offset_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, offset_reg); + std::optional<RegisterInfo> base_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); + std::optional<RegisterInfo> offset_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m); EmulateInstruction::Context context; context.type = eContextRegisterLoad; - context.SetRegisterPlusIndirectOffset(base_reg, offset_reg); + context.SetRegisterPlusIndirectOffset(*base_reg, *offset_reg); uint64_t unsigned_data = MemURead(context, address, 1, 0, &success); if (!success) @@ -8016,12 +7997,12 @@ bool EmulateInstructionARM::EmulateLDRSHImmediate(const uint32_t opcode, address = Rn; // data = MemU[address,2]; - RegisterInfo base_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); + std::optional<RegisterInfo> base_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); EmulateInstruction::Context context; context.type = eContextRegisterLoad; - context.SetRegisterPlusOffset(base_reg, address - Rn); + context.SetRegisterPlusOffset(*base_reg, address - Rn); uint64_t data = MemURead(context, address, 2, 0, &success); if (!success) @@ -8041,7 +8022,7 @@ bool EmulateInstructionARM::EmulateLDRSHImmediate(const uint32_t opcode, // R[t] = SignExtend(data, 32); int64_t signed_data = llvm::SignExtend64<16>(data); context.type = eContextRegisterLoad; - context.SetRegisterPlusOffset(base_reg, address - Rn); + context.SetRegisterPlusOffset(*base_reg, address - Rn); if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t)signed_data)) return false; @@ -8126,12 +8107,12 @@ bool EmulateInstructionARM::EmulateLDRSHLiteral(const uint32_t opcode, address = base - imm32; // data = MemU[address,2]; - RegisterInfo base_reg; - GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, base_reg); + std::optional<RegisterInfo> base_reg = + GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); EmulateInstruction::Context context; context.type = eContextRegisterLoad; - context.SetRegisterPlusOffset(base_reg, imm32); + context.SetRegisterPlusOffset(*base_reg, imm32); uint64_t data = MemURead(context, address, 2, 0, &success); if (!success) @@ -8292,15 +8273,14 @@ bool EmulateInstructionARM::EmulateLDRSHRegister(const uint32_t opcode, address = Rn; // data = MemU[address,2]; - RegisterInfo base_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); - - RegisterInfo offset_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, offset_reg); + std::optional<RegisterInfo> base_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); + std::optional<RegisterInfo> offset_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m); EmulateInstruction::Context context; context.type = eContextRegisterLoad; - context.SetRegisterPlusIndirectOffset(base_reg, offset_reg); + context.SetRegisterPlusIndirectOffset(*base_reg, *offset_reg); uint64_t data = MemURead(context, address, 2, 0, &success); if (!success) @@ -8319,7 +8299,7 @@ bool EmulateInstructionARM::EmulateLDRSHRegister(const uint32_t opcode, if (UnalignedSupport() || BitIsClear(address, 0)) { // R[t] = SignExtend(data, 32); context.type = eContextRegisterLoad; - context.SetRegisterPlusIndirectOffset(base_reg, offset_reg); + context.SetRegisterPlusIndirectOffset(*base_reg, *offset_reg); int64_t signed_data = llvm::SignExtend64<16>(data); if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, @@ -8405,12 +8385,12 @@ bool EmulateInstructionARM::EmulateSXTB(const uint32_t opcode, // R[d] = SignExtend(rotated<7:0>, 32); int64_t data = llvm::SignExtend64<8>(rotated); - RegisterInfo source_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, source_reg); + std::optional<RegisterInfo> source_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m); EmulateInstruction::Context context; context.type = eContextRegisterLoad; - context.SetRegister(source_reg); + context.SetRegister(*source_reg); if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t)data)) @@ -8488,12 +8468,12 @@ bool EmulateInstructionARM::EmulateSXTH(const uint32_t opcode, return false; // R[d] = SignExtend(rotated<15:0>, 32); - RegisterInfo source_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, source_reg); + std::optional<RegisterInfo> source_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m); EmulateInstruction::Context context; context.type = eContextRegisterLoad; - context.SetRegister(source_reg); + context.SetRegister(*source_reg); int64_t data = llvm::SignExtend64<16>(rotated); if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d, @@ -8573,12 +8553,12 @@ bool EmulateInstructionARM::EmulateUXTB(const uint32_t opcode, return false; // R[d] = ZeroExtend(rotated<7:0>, 32); - RegisterInfo source_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, source_reg); + std::optional<RegisterInfo> source_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m); EmulateInstruction::Context context; context.type = eContextRegisterLoad; - context.SetRegister(source_reg); + context.SetRegister(*source_reg); if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d, Bits32(rotated, 7, 0))) @@ -8655,12 +8635,12 @@ bool EmulateInstructionARM::EmulateUXTH(const uint32_t opcode, return false; // R[d] = ZeroExtend(rotated<15:0>, 32); - RegisterInfo source_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, source_reg); + std::optional<RegisterInfo> source_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m); EmulateInstruction::Context context; context.type = eContextRegisterLoad; - context.SetRegister(source_reg); + context.SetRegister(*source_reg); if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d, Bits32(rotated, 15, 0))) @@ -8774,12 +8754,12 @@ bool EmulateInstructionARM::EmulateRFE(const uint32_t opcode, address = address + 4; // CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE); - RegisterInfo base_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); + std::optional<RegisterInfo> base_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); EmulateInstruction::Context context; context.type = eContextReturnFromException; - context.SetRegisterPlusOffset(base_reg, address - Rn); + context.SetRegisterPlusOffset(*base_reg, address - Rn); uint64_t data = MemARead(context, address + 4, 4, 0, &success); if (!success) @@ -9736,10 +9716,10 @@ bool EmulateInstructionARM::EmulateSUBImmARM(const uint32_t opcode, else context.type = EmulateInstruction::eContextRegisterPlusOffset; - RegisterInfo dwarf_reg; - GetRegisterInfo(eRegisterKindDWARF, Rn, dwarf_reg); + std::optional<RegisterInfo> dwarf_reg = + GetRegisterInfo(eRegisterKindDWARF, Rn); int64_t imm32_signed = imm32; - context.SetRegisterPlusOffset(dwarf_reg, -imm32_signed); + context.SetRegisterPlusOffset(*dwarf_reg, -imm32_signed); if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) @@ -10089,11 +10069,11 @@ bool EmulateInstructionARM::EmulateSUBSPReg(const uint32_t opcode, EmulateInstruction::Context context; context.type = eContextArithmetic; - RegisterInfo sp_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg); - RegisterInfo dwarf_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, dwarf_reg); - context.SetRegisterRegisterOperands(sp_reg, dwarf_reg); + std::optional<RegisterInfo> sp_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_sp); + std::optional<RegisterInfo> dwarf_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m); + context.SetRegisterRegisterOperands(*sp_reg, *dwarf_reg); if (!WriteCoreRegOptionalFlags(context, res.result, dwarf_r0 + d, setflags, res.carry_out, res.overflow)) @@ -10176,12 +10156,12 @@ bool EmulateInstructionARM::EmulateADDRegShift(const uint32_t opcode, // R[d] = result; EmulateInstruction::Context context; context.type = eContextArithmetic; - RegisterInfo reg_n; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, reg_n); - RegisterInfo reg_m; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, reg_m); + std::optional<RegisterInfo> reg_n = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); + std::optional<RegisterInfo> reg_m = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m); - context.SetRegisterRegisterOperands(reg_n, reg_m); + context.SetRegisterRegisterOperands(*reg_n, *reg_m); if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d, res.result)) @@ -10316,11 +10296,11 @@ bool EmulateInstructionARM::EmulateSUBReg(const uint32_t opcode, EmulateInstruction::Context context; context.type = eContextArithmetic; - RegisterInfo reg_n; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, reg_n); - RegisterInfo reg_m; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, reg_m); - context.SetRegisterRegisterOperands(reg_n, reg_m); + std::optional<RegisterInfo> reg_n = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); + std::optional<RegisterInfo> reg_m = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m); + context.SetRegisterRegisterOperands(*reg_n, *reg_m); if (!WriteCoreRegOptionalFlags(context, res.result, dwarf_r0 + d, setflags, res.carry_out, res.overflow)) @@ -10404,13 +10384,13 @@ bool EmulateInstructionARM::EmulateSTREX(const uint32_t opcode, addr_t address = Rn + imm32; - RegisterInfo base_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); - RegisterInfo data_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg); + std::optional<RegisterInfo> base_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); + std::optional<RegisterInfo> data_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t); EmulateInstruction::Context context; context.type = eContextRegisterStore; - context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, imm32); + context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, imm32); // if ExclusiveMonitorsPass(address,4) then if (ExclusiveMonitorsPass // (address, addr_byte_size)) -- For now, for the sake of emulation, we @@ -10515,13 +10495,13 @@ bool EmulateInstructionARM::EmulateSTRBImmARM(const uint32_t opcode, if (!success) return false; - RegisterInfo base_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); - RegisterInfo data_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg); + std::optional<RegisterInfo> base_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); + std::optional<RegisterInfo> data_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t); EmulateInstruction::Context context; context.type = eContextRegisterStore; - context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, address - Rn); + context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, address - Rn); if (!MemUWrite(context, address, Bits32(Rt, 7, 0), 1)) return false; @@ -10603,13 +10583,13 @@ bool EmulateInstructionARM::EmulateSTRImmARM(const uint32_t opcode, else address = Rn; - RegisterInfo base_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); - RegisterInfo data_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg); + std::optional<RegisterInfo> base_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); + std::optional<RegisterInfo> data_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t); EmulateInstruction::Context context; context.type = eContextRegisterStore; - context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, address - Rn); + context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, address - Rn); // MemU[address,4] = if t == 15 then PCStoreValue() else R[t]; uint32_t Rt = ReadCoreReg(t, &success); @@ -10749,8 +10729,6 @@ bool EmulateInstructionARM::EmulateLDRDImmediate(const uint32_t opcode, address = Rn; // R[t] = MemA[address,4]; - RegisterInfo base_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); EmulateInstruction::Context context; if (n == 13) @@ -10857,14 +10835,10 @@ bool EmulateInstructionARM::EmulateLDRDRegister(const uint32_t opcode, uint32_t Rn = ReadCoreReg(n, &success); if (!success) return false; - RegisterInfo base_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); uint32_t Rm = ReadCoreReg(m, &success); if (!success) return false; - RegisterInfo offset_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, offset_reg); // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]); addr_t offset_addr; @@ -11006,8 +10980,8 @@ bool EmulateInstructionARM::EmulateSTRDImm(const uint32_t opcode, return false; } - RegisterInfo base_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); + std::optional<RegisterInfo> base_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); uint32_t Rn = ReadCoreReg(n, &success); if (!success) @@ -11028,8 +11002,8 @@ bool EmulateInstructionARM::EmulateSTRDImm(const uint32_t opcode, address = Rn; // MemA[address,4] = R[t]; - RegisterInfo data_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg); + std::optional<RegisterInfo> data_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t); uint32_t data = ReadCoreReg(t, &success); if (!success) @@ -11040,7 +11014,7 @@ bool EmulateInstructionARM::EmulateSTRDImm(const uint32_t opcode, context.type = eContextPushRegisterOnStack; else context.type = eContextRegisterStore; - context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, address - Rn); + context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, address - Rn); const uint32_t addr_byte_size = GetAddressByteSize(); @@ -11048,8 +11022,8 @@ bool EmulateInstructionARM::EmulateSTRDImm(const uint32_t opcode, return false; // MemA[address+4,4] = R[t2]; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t2, data_reg); - context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, + data_reg = GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t2); + context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, (address + 4) - Rn); data = ReadCoreReg(t2, &success); @@ -11138,12 +11112,6 @@ bool EmulateInstructionARM::EmulateSTRDReg(const uint32_t opcode, return false; } - RegisterInfo base_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); - RegisterInfo offset_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, offset_reg); - RegisterInfo data_reg; - uint32_t Rn = ReadCoreReg(n, &success); if (!success) return false; @@ -11176,9 +11144,14 @@ bool EmulateInstructionARM::EmulateSTRDReg(const uint32_t opcode, else context.type = eContextRegisterStore; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg); - context.SetRegisterToRegisterPlusIndirectOffset(base_reg, offset_reg, - data_reg); + std::optional<RegisterInfo> base_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); + std::optional<RegisterInfo> offset_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m); + std::optional<RegisterInfo> data_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t); + context.SetRegisterToRegisterPlusIndirectOffset(*base_reg, *offset_reg, + *data_reg); const uint32_t addr_byte_size = GetAddressByteSize(); @@ -11190,10 +11163,10 @@ bool EmulateInstructionARM::EmulateSTRDReg(const uint32_t opcode, if (!success) return false; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t2, data_reg); + data_reg = GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t2); - context.SetRegisterToRegisterPlusIndirectOffset(base_reg, offset_reg, - data_reg); + context.SetRegisterToRegisterPlusIndirectOffset(*base_reg, *offset_reg, + *data_reg); if (!MemAWrite(context, address + 4, Rt2, addr_byte_size)) return false; @@ -11315,9 +11288,6 @@ bool EmulateInstructionARM::EmulateVLDM(const uint32_t opcode, return false; } - RegisterInfo base_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); - uint32_t Rn = ReadCoreReg(n, &success); if (!success) return false; @@ -11351,11 +11321,14 @@ bool EmulateInstructionARM::EmulateVLDM(const uint32_t opcode, context.type = eContextRegisterLoad; + std::optional<RegisterInfo> base_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); + // for r = 0 to regs-1 for (uint32_t r = 0; r < regs; ++r) { if (single_regs) { // S[d+r] = MemA[address,4]; address = address+4; - context.SetRegisterPlusOffset(base_reg, address - Rn); + context.SetRegisterPlusOffset(*base_reg, address - Rn); uint32_t data = MemARead(context, address, addr_byte_size, 0, &success); if (!success) @@ -11369,13 +11342,13 @@ bool EmulateInstructionARM::EmulateVLDM(const uint32_t opcode, } else { // word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = // address+8; - context.SetRegisterPlusOffset(base_reg, address - Rn); + context.SetRegisterPlusOffset(*base_reg, address - Rn); uint32_t word1 = MemARead(context, address, addr_byte_size, 0, &success); if (!success) return false; - context.SetRegisterPlusOffset(base_reg, (address + 4) - Rn); + context.SetRegisterPlusOffset(*base_reg, (address + 4) - Rn); uint32_t word2 = MemARead(context, address + 4, addr_byte_size, 0, &success); if (!success) @@ -11510,8 +11483,8 @@ bool EmulateInstructionARM::EmulateVSTM(const uint32_t opcode, return false; } - RegisterInfo base_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); + std::optional<RegisterInfo> base_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); uint32_t Rn = ReadCoreReg(n, &success); if (!success) @@ -11534,7 +11507,7 @@ bool EmulateInstructionARM::EmulateVSTM(const uint32_t opcode, value = Rn - imm32; context.type = eContextAdjustBaseRegister; - context.SetRegisterPlusOffset(base_reg, value - Rn); + context.SetRegisterPlusOffset(*base_reg, value - Rn); if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, value)) @@ -11555,9 +11528,9 @@ bool EmulateInstructionARM::EmulateVSTM(const uint32_t opcode, if (!success) return false; - RegisterInfo data_reg; - GetRegisterInfo(eRegisterKindDWARF, start_reg + d + r, data_reg); - context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, + std::optional<RegisterInfo> data_reg = + GetRegisterInfo(eRegisterKindDWARF, start_reg + d + r); + context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, address - Rn); if (!MemAWrite(context, address, data, addr_byte_size)) return false; @@ -11574,28 +11547,28 @@ bool EmulateInstructionARM::EmulateVSTM(const uint32_t opcode, if (!success) return false; - RegisterInfo data_reg; - GetRegisterInfo(eRegisterKindDWARF, start_reg + d + r, data_reg); + std::optional<RegisterInfo> data_reg = + GetRegisterInfo(eRegisterKindDWARF, start_reg + d + r); if (GetByteOrder() == eByteOrderBig) { - context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, + context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, address - Rn); if (!MemAWrite(context, address, Bits64(data, 63, 32), addr_byte_size)) return false; - context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, + context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, (address + 4) - Rn); if (!MemAWrite(context, address + 4, Bits64(data, 31, 0), addr_byte_size)) return false; } else { - context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, + context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, address - Rn); if (!MemAWrite(context, address, Bits64(data, 31, 0), addr_byte_size)) return false; - context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, + context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, (address + 4) - Rn); if (!MemAWrite(context, address + 4, Bits64(data, 63, 32), addr_byte_size)) @@ -11668,8 +11641,8 @@ bool EmulateInstructionARM::EmulateVLDR(const uint32_t opcode, default: return false; } - RegisterInfo base_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); + std::optional<RegisterInfo> base_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); uint32_t Rn = ReadCoreReg(n, &success); if (!success) @@ -11694,7 +11667,7 @@ bool EmulateInstructionARM::EmulateVLDR(const uint32_t opcode, EmulateInstruction::Context context; context.type = eContextRegisterLoad; - context.SetRegisterPlusOffset(base_reg, address - base); + context.SetRegisterPlusOffset(*base_reg, address - base); if (single_reg) { // S[d] = MemA[address,4]; @@ -11711,7 +11684,7 @@ bool EmulateInstructionARM::EmulateVLDR(const uint32_t opcode, if (!success) return false; - context.SetRegisterPlusOffset(base_reg, (address + 4) - base); + context.SetRegisterPlusOffset(*base_reg, (address + 4) - base); uint32_t word2 = MemARead(context, address + 4, addr_byte_size, 0, &success); if (!success) @@ -11803,9 +11776,6 @@ bool EmulateInstructionARM::EmulateVSTR(const uint32_t opcode, return false; } - RegisterInfo base_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); - uint32_t Rn = ReadCoreReg(n, &success); if (!success) return false; @@ -11820,11 +11790,13 @@ bool EmulateInstructionARM::EmulateVSTR(const uint32_t opcode, const uint32_t addr_byte_size = GetAddressByteSize(); uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0; - RegisterInfo data_reg; - GetRegisterInfo(eRegisterKindDWARF, start_reg + d, data_reg); + std::optional<RegisterInfo> base_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); + std::optional<RegisterInfo> data_reg = + GetRegisterInfo(eRegisterKindDWARF, start_reg + d); EmulateInstruction::Context context; context.type = eContextRegisterStore; - context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, address - Rn); + context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, address - Rn); if (single_reg) { // MemA[address,4] = S[d]; @@ -11849,7 +11821,7 @@ bool EmulateInstructionARM::EmulateVSTR(const uint32_t opcode, if (!MemAWrite(context, address, Bits64(data, 63, 32), addr_byte_size)) return false; - context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, + context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, (address + 4) - Rn); if (!MemAWrite(context, address + 4, Bits64(data, 31, 0), addr_byte_size)) @@ -11858,7 +11830,7 @@ bool EmulateInstructionARM::EmulateVSTR(const uint32_t opcode, if (!MemAWrite(context, address, Bits64(data, 31, 0), addr_byte_size)) return false; - context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, + context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, (address + 4) - Rn); if (!MemAWrite(context, address + 4, Bits64(data, 63, 32), addr_byte_size)) @@ -11966,8 +11938,8 @@ bool EmulateInstructionARM::EmulateVLD1Multiple(const uint32_t opcode, return false; } - RegisterInfo base_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); + std::optional<RegisterInfo> base_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); uint32_t Rn = ReadCoreReg(n, &success); if (!success) @@ -11994,7 +11966,7 @@ bool EmulateInstructionARM::EmulateVLD1Multiple(const uint32_t opcode, uint32_t value = Rn + offset; context.type = eContextAdjustBaseRegister; - context.SetRegisterPlusOffset(base_reg, offset); + context.SetRegisterPlusOffset(*base_reg, offset); if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, value)) @@ -12008,7 +11980,7 @@ bool EmulateInstructionARM::EmulateVLD1Multiple(const uint32_t opcode, for (uint32_t e = 0; e < elements; ++e) { // Elem[D[d+r],e,esize] = MemU[address,ebytes]; context.type = eContextRegisterLoad; - context.SetRegisterPlusOffset(base_reg, address - Rn); + context.SetRegisterPlusOffset(*base_reg, address - Rn); uint64_t data = MemURead(context, address, ebytes, 0, &success); if (!success) return false; @@ -12133,9 +12105,6 @@ bool EmulateInstructionARM::EmulateVLD1Single(const uint32_t opcode, return false; } - RegisterInfo base_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); - uint32_t Rn = ReadCoreReg(n, &success); if (!success) return false; @@ -12162,7 +12131,9 @@ bool EmulateInstructionARM::EmulateVLD1Single(const uint32_t opcode, uint32_t value = Rn + offset; context.type = eContextAdjustBaseRegister; - context.SetRegisterPlusOffset(base_reg, offset); + std::optional<RegisterInfo> base_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); + context.SetRegisterPlusOffset(*base_reg, offset); if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, value)) @@ -12299,8 +12270,8 @@ bool EmulateInstructionARM::EmulateVST1Multiple(const uint32_t opcode, return false; } - RegisterInfo base_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); + std::optional<RegisterInfo> base_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); uint32_t Rn = ReadCoreReg(n, &success); if (!success) @@ -12326,18 +12297,18 @@ bool EmulateInstructionARM::EmulateVST1Multiple(const uint32_t opcode, offset = 8 * regs; context.type = eContextAdjustBaseRegister; - context.SetRegisterPlusOffset(base_reg, offset); + context.SetRegisterPlusOffset(*base_reg, offset); if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, Rn + offset)) return false; } - RegisterInfo data_reg; context.type = eContextRegisterStore; // for r = 0 to regs-1 for (uint32_t r = 0; r < regs; ++r) { - GetRegisterInfo(eRegisterKindDWARF, dwarf_d0 + d + r, data_reg); + std::optional<RegisterInfo> data_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_d0 + d + r); uint64_t register_data = ReadRegisterUnsigned( eRegisterKindDWARF, dwarf_d0 + d + r, 0, &success); if (!success) @@ -12348,7 +12319,7 @@ bool EmulateInstructionARM::EmulateVST1Multiple(const uint32_t opcode, // MemU[address,ebytes] = Elem[D[d+r],e,esize]; uint64_t word = Bits64(register_data, ((e + 1) * esize) - 1, e * esize); - context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, + context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, address - Rn); if (!MemUWrite(context, address, word, ebytes)) return false; @@ -12466,8 +12437,8 @@ bool EmulateInstructionARM::EmulateVST1Single(const uint32_t opcode, return false; } - RegisterInfo base_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); + std::optional<RegisterInfo> base_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); uint32_t Rn = ReadCoreReg(n, &success); if (!success) @@ -12493,7 +12464,7 @@ bool EmulateInstructionARM::EmulateVST1Single(const uint32_t opcode, offset = ebytes; context.type = eContextAdjustBaseRegister; - context.SetRegisterPlusOffset(base_reg, offset); + context.SetRegisterPlusOffset(*base_reg, offset); if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, Rn + offset)) @@ -12509,10 +12480,10 @@ bool EmulateInstructionARM::EmulateVST1Single(const uint32_t opcode, uint64_t word = Bits64(register_data, ((index + 1) * esize) - 1, index * esize); - RegisterInfo data_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_d0 + d, data_reg); + std::optional<RegisterInfo> data_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_d0 + d); context.type = eContextRegisterStore; - context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, address - Rn); + context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, address - Rn); if (!MemUWrite(context, address, word, ebytes)) return false; @@ -12591,9 +12562,6 @@ bool EmulateInstructionARM::EmulateVLD1SingleAll(const uint32_t opcode, return false; } - RegisterInfo base_reg; - GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); - uint32_t Rn = ReadCoreReg(n, &success); if (!success) return false; @@ -12618,7 +12586,9 @@ bool EmulateInstructionARM::EmulateVLD1SingleAll(const uint32_t opcode, offset = ebytes; context.type = eContextAdjustBaseRegister; - context.SetRegisterPlusOffset(base_reg, offset); + std::optional<RegisterInfo> base_reg = + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); + context.SetRegisterPlusOffset(*base_reg, offset); if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, Rn + offset)) @@ -13198,7 +13168,7 @@ EmulateInstructionARM::GetARMOpcodeForInstruction(const uint32_t opcode, &EmulateInstructionARM::EmulateRFE, "rfe{<amode>} <Rn>{!}"} }; - static const size_t k_num_arm_opcodes = llvm::array_lengthof(g_arm_opcodes); + static const size_t k_num_arm_opcodes = std::size(g_arm_opcodes); for (size_t i = 0; i < k_num_arm_opcodes; ++i) { if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value && @@ -13749,7 +13719,7 @@ EmulateInstructionARM::GetThumbOpcodeForInstruction(const uint32_t opcode, &EmulateInstructionARM::EmulateUXTH, "uxth<c>.w <Rd>,<Rm>{,<rotation>}"}, }; - const size_t k_num_thumb_opcodes = llvm::array_lengthof(g_thumb_opcodes); + const size_t k_num_thumb_opcodes = std::size(g_thumb_opcodes); for (size_t i = 0; i < k_num_thumb_opcodes; ++i) { if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value && (g_thumb_opcodes[i].variants & arm_isa) != 0) diff --git a/contrib/llvm-project/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.h b/contrib/llvm-project/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.h index c877724a9d30..7b8849ede9c7 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.h +++ b/contrib/llvm-project/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.h @@ -13,6 +13,7 @@ #include "lldb/Core/EmulateInstruction.h" #include "lldb/Utility/ConstString.h" #include "lldb/Utility/Status.h" +#include <optional> namespace lldb_private { @@ -135,8 +136,8 @@ public: bool TestEmulation(Stream *out_stream, ArchSpec &arch, OptionValueDictionary *test_data) override; - bool GetRegisterInfo(lldb::RegisterKind reg_kind, uint32_t reg_num, - RegisterInfo ®_info) override; + std::optional<RegisterInfo> GetRegisterInfo(lldb::RegisterKind reg_kind, + uint32_t reg_num) override; bool CreateFunctionEntryUnwind(UnwindPlan &unwind_plan) override; diff --git a/contrib/llvm-project/lldb/source/Plugins/Instruction/ARM/EmulationStateARM.cpp b/contrib/llvm-project/lldb/source/Plugins/Instruction/ARM/EmulationStateARM.cpp index da679a3e8547..1bb96fc8a2f7 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Instruction/ARM/EmulationStateARM.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Instruction/ARM/EmulationStateARM.cpp @@ -26,43 +26,6 @@ EmulationStateARM::EmulationStateARM() : m_vfp_regs(), m_memory() { EmulationStateARM::~EmulationStateARM() = default; -bool EmulationStateARM::LoadPseudoRegistersFromFrame(StackFrame &frame) { - RegisterContext *reg_ctx = frame.GetRegisterContext().get(); - bool success = true; - uint32_t reg_num; - - for (int i = dwarf_r0; i < dwarf_r0 + 17; ++i) { - reg_num = - reg_ctx->ConvertRegisterKindToRegisterNumber(eRegisterKindDWARF, i); - const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg_num); - RegisterValue reg_value; - if (reg_ctx->ReadRegister(reg_info, reg_value)) { - m_gpr[i - dwarf_r0] = reg_value.GetAsUInt32(); - } else - success = false; - } - - for (int i = dwarf_d0; i < dwarf_d0 + 32; ++i) { - reg_num = - reg_ctx->ConvertRegisterKindToRegisterNumber(eRegisterKindDWARF, i); - RegisterValue reg_value; - const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg_num); - - if (reg_ctx->ReadRegister(reg_info, reg_value)) { - uint64_t value = reg_value.GetAsUInt64(); - uint32_t idx = i - dwarf_d0; - if (i < 16) { - m_vfp_regs.s_regs[idx * 2] = (uint32_t)value; - m_vfp_regs.s_regs[idx * 2 + 1] = (uint32_t)(value >> 32); - } else - m_vfp_regs.d_regs[idx - 16] = value; - } else - success = false; - } - - return success; -} - bool EmulationStateARM::StorePseudoRegisterValue(uint32_t reg_num, uint64_t value) { if (reg_num <= dwarf_cpsr) @@ -92,7 +55,7 @@ uint64_t EmulationStateARM::ReadPseudoRegisterValue(uint32_t reg_num, value = m_gpr[reg_num - dwarf_r0]; else if ((dwarf_s0 <= reg_num) && (reg_num <= dwarf_s31)) { uint32_t idx = reg_num - dwarf_s0; - value = m_vfp_regs.d_regs[idx]; + value = m_vfp_regs.s_regs[idx]; } else if ((dwarf_d0 <= reg_num) && (reg_num <= dwarf_d31)) { uint32_t idx = reg_num - dwarf_d0; if (idx < 16) diff --git a/contrib/llvm-project/lldb/source/Plugins/Instruction/ARM/EmulationStateARM.h b/contrib/llvm-project/lldb/source/Plugins/Instruction/ARM/EmulationStateARM.h index bc885dab9ac7..bf322f5b1a91 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Instruction/ARM/EmulationStateARM.h +++ b/contrib/llvm-project/lldb/source/Plugins/Instruction/ARM/EmulationStateARM.h @@ -32,8 +32,6 @@ public: void ClearPseudoMemory(); - bool LoadPseudoRegistersFromFrame(lldb_private::StackFrame &frame); - bool LoadStateFromDictionary(lldb_private::OptionValueDictionary *test_data); bool CompareState(EmulationStateARM &other_state, diff --git a/contrib/llvm-project/lldb/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp b/contrib/llvm-project/lldb/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp index f86609f3c5c1..0861d24dcc79 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp @@ -23,6 +23,7 @@ #include "Plugins/Process/Utility/lldb-arm64-register-enums.h" #include <cstdlib> +#include <optional> #define GPR_OFFSET(idx) ((idx)*8) #define GPR_OFFSET_NAME(reg) 0 @@ -51,11 +52,10 @@ using namespace lldb_private; LLDB_PLUGIN_DEFINE_ADV(EmulateInstructionARM64, InstructionARM64) -static bool LLDBTableGetRegisterInfo(uint32_t reg_num, RegisterInfo ®_info) { - if (reg_num >= llvm::array_lengthof(g_register_infos_arm64_le)) - return false; - reg_info = g_register_infos_arm64_le[reg_num]; - return true; +static std::optional<RegisterInfo> LLDBTableGetRegisterInfo(uint32_t reg_num) { + if (reg_num >= std::size(g_register_infos_arm64_le)) + return {}; + return g_register_infos_arm64_le[reg_num]; } #define No_VFP 0 @@ -144,9 +144,9 @@ bool EmulateInstructionARM64::SetTargetTriple(const ArchSpec &arch) { return false; } -bool EmulateInstructionARM64::GetRegisterInfo(RegisterKind reg_kind, - uint32_t reg_num, - RegisterInfo ®_info) { +std::optional<RegisterInfo> +EmulateInstructionARM64::GetRegisterInfo(RegisterKind reg_kind, + uint32_t reg_num) { if (reg_kind == eRegisterKindGeneric) { switch (reg_num) { case LLDB_REGNUM_GENERIC_PC: @@ -171,13 +171,13 @@ bool EmulateInstructionARM64::GetRegisterInfo(RegisterKind reg_kind, break; default: - return false; + return {}; } } if (reg_kind == eRegisterKindLLDB) - return LLDBTableGetRegisterInfo(reg_num, reg_info); - return false; + return LLDBTableGetRegisterInfo(reg_num); + return {}; } EmulateInstructionARM64::Opcode * @@ -360,7 +360,7 @@ EmulateInstructionARM64::GetOpcodeForInstruction(const uint32_t opcode) { "TBNZ <R><t>, #<imm>, <label>"}, }; - static const size_t k_num_arm_opcodes = llvm::array_lengthof(g_opcodes); + static const size_t k_num_arm_opcodes = std::size(g_opcodes); for (size_t i = 0; i < k_num_arm_opcodes; ++i) { if ((g_opcodes[i].mask & opcode) == g_opcodes[i].value) @@ -561,7 +561,7 @@ uint64_t EmulateInstructionARM64:: AddWithCarry(uint32_t N, uint64_t x, uint64_t y, bit carry_in, EmulateInstructionARM64::ProcState &proc_state) { uint64_t unsigned_sum = UInt(x) + UInt(y) + UInt(carry_in); - llvm::Optional<int64_t> signed_sum = llvm::checkedAdd(SInt(x), SInt(y)); + std::optional<int64_t> signed_sum = llvm::checkedAdd(SInt(x), SInt(y)); bool overflow = !signed_sum; if (!overflow) overflow |= !llvm::checkedAdd(*signed_sum, SInt(carry_in)); @@ -633,7 +633,7 @@ bool EmulateInstructionARM64::EmulateADDSUBImm(const uint32_t opcode) { imm = imm12; break; case 1: - imm = imm12 << 12; + imm = static_cast<uint64_t>(imm12) << 12; break; default: return false; // UNDEFINED; @@ -664,9 +664,10 @@ bool EmulateInstructionARM64::EmulateADDSUBImm(const uint32_t opcode) { } Context context; - RegisterInfo reg_info_Rn; - if (GetRegisterInfo(eRegisterKindLLDB, n, reg_info_Rn)) - context.SetRegisterPlusOffset(reg_info_Rn, imm); + std::optional<RegisterInfo> reg_info_Rn = + GetRegisterInfo(eRegisterKindLLDB, n); + if (reg_info_Rn) + context.SetRegisterPlusOffset(*reg_info_Rn, imm); if (n == GetFramePointerRegisterNumber() && d == gpr_sp_arm64 && !setflags) { // 'mov sp, fp' - common epilogue instruction, CFA is now in terms of the @@ -768,26 +769,25 @@ bool EmulateInstructionARM64::EmulateLDPSTP(const uint32_t opcode) { uint64_t address; uint64_t wb_address; - RegisterValue data_Rt; - RegisterValue data_Rt2; - RegisterInfo reg_info_base; - RegisterInfo reg_info_Rt; - RegisterInfo reg_info_Rt2; - if (!GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + n, reg_info_base)) + std::optional<RegisterInfo> reg_info_base = + GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + n); + if (!reg_info_base) return false; + std::optional<RegisterInfo> reg_info_Rt; + std::optional<RegisterInfo> reg_info_Rt2; + if (vector) { - if (!GetRegisterInfo(eRegisterKindLLDB, fpu_d0_arm64 + t, reg_info_Rt)) - return false; - if (!GetRegisterInfo(eRegisterKindLLDB, fpu_d0_arm64 + t2, reg_info_Rt2)) - return false; + reg_info_Rt = GetRegisterInfo(eRegisterKindLLDB, fpu_d0_arm64 + t); + reg_info_Rt2 = GetRegisterInfo(eRegisterKindLLDB, fpu_d0_arm64 + t2); } else { - if (!GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + t, reg_info_Rt)) - return false; - if (!GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + t2, reg_info_Rt2)) - return false; + reg_info_Rt = GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + t); + reg_info_Rt2 = GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + t2); } + if (!reg_info_Rt || !reg_info_Rt2) + return false; + bool success = false; if (n == 31) { // CheckSPAlignment(); @@ -819,29 +819,32 @@ bool EmulateInstructionARM64::EmulateLDPSTP(const uint32_t opcode) { context_t.type = eContextRegisterStore; context_t2.type = eContextRegisterStore; } - context_t.SetRegisterToRegisterPlusOffset(reg_info_Rt, reg_info_base, 0); - context_t2.SetRegisterToRegisterPlusOffset(reg_info_Rt2, reg_info_base, + context_t.SetRegisterToRegisterPlusOffset(*reg_info_Rt, *reg_info_base, 0); + context_t2.SetRegisterToRegisterPlusOffset(*reg_info_Rt2, *reg_info_base, size); - if (!ReadRegister(®_info_Rt, data_Rt)) + std::optional<RegisterValue> data_Rt = ReadRegister(*reg_info_Rt); + if (!data_Rt) return false; - if (data_Rt.GetAsMemoryData(®_info_Rt, buffer, reg_info_Rt.byte_size, - eByteOrderLittle, error) == 0) + if (data_Rt->GetAsMemoryData(*reg_info_Rt, buffer, reg_info_Rt->byte_size, + eByteOrderLittle, error) == 0) return false; - if (!WriteMemory(context_t, address + 0, buffer, reg_info_Rt.byte_size)) + if (!WriteMemory(context_t, address + 0, buffer, reg_info_Rt->byte_size)) return false; - if (!ReadRegister(®_info_Rt2, data_Rt2)) + std::optional<RegisterValue> data_Rt2 = ReadRegister(*reg_info_Rt2); + if (!data_Rt2) return false; - if (data_Rt2.GetAsMemoryData(®_info_Rt2, buffer, reg_info_Rt2.byte_size, - eByteOrderLittle, error) == 0) + if (data_Rt2->GetAsMemoryData(*reg_info_Rt2, buffer, + reg_info_Rt2->byte_size, eByteOrderLittle, + error) == 0) return false; if (!WriteMemory(context_t2, address + size, buffer, - reg_info_Rt2.byte_size)) + reg_info_Rt2->byte_size)) return false; } break; @@ -860,37 +863,39 @@ bool EmulateInstructionARM64::EmulateLDPSTP(const uint32_t opcode) { context_t2.SetAddress(address + size); if (rt_unknown) - memset(buffer, 'U', reg_info_Rt.byte_size); + memset(buffer, 'U', reg_info_Rt->byte_size); else { - if (!ReadMemory(context_t, address, buffer, reg_info_Rt.byte_size)) + if (!ReadMemory(context_t, address, buffer, reg_info_Rt->byte_size)) return false; } - if (data_Rt.SetFromMemoryData(®_info_Rt, buffer, reg_info_Rt.byte_size, + RegisterValue data_Rt; + if (data_Rt.SetFromMemoryData(*reg_info_Rt, buffer, reg_info_Rt->byte_size, eByteOrderLittle, error) == 0) return false; if (!vector && is_signed && !data_Rt.SignExtend(datasize)) return false; - if (!WriteRegister(context_t, ®_info_Rt, data_Rt)) + if (!WriteRegister(context_t, *reg_info_Rt, data_Rt)) return false; if (!rt_unknown) { if (!ReadMemory(context_t2, address + size, buffer, - reg_info_Rt2.byte_size)) + reg_info_Rt2->byte_size)) return false; } - if (data_Rt2.SetFromMemoryData(®_info_Rt2, buffer, - reg_info_Rt2.byte_size, eByteOrderLittle, + RegisterValue data_Rt2; + if (data_Rt2.SetFromMemoryData(*reg_info_Rt2, buffer, + reg_info_Rt2->byte_size, eByteOrderLittle, error) == 0) return false; if (!vector && is_signed && !data_Rt2.SignExtend(datasize)) return false; - if (!WriteRegister(context_t2, ®_info_Rt2, data_Rt2)) + if (!WriteRegister(context_t2, *reg_info_Rt2, data_Rt2)) return false; } break; @@ -907,7 +912,7 @@ bool EmulateInstructionARM64::EmulateLDPSTP(const uint32_t opcode) { context.type = eContextAdjustStackPointer; else context.type = eContextAdjustBaseRegister; - WriteRegisterUnsigned(context, ®_info_base, wb_address); + WriteRegisterUnsigned(context, *reg_info_base, wb_address); } return true; } @@ -955,7 +960,6 @@ bool EmulateInstructionARM64::EmulateLDRSTRImm(const uint32_t opcode) { bool success = false; uint64_t address; uint8_t buffer[RegisterValue::kMaxRegisterByteSize]; - RegisterValue data_Rt; if (n == 31) address = @@ -970,38 +974,41 @@ bool EmulateInstructionARM64::EmulateLDRSTRImm(const uint32_t opcode) { if (!postindex) address += offset; - RegisterInfo reg_info_base; - if (!GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + n, reg_info_base)) + std::optional<RegisterInfo> reg_info_base = + GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + n); + if (!reg_info_base) return false; - RegisterInfo reg_info_Rt; - if (!GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + t, reg_info_Rt)) + std::optional<RegisterInfo> reg_info_Rt = + GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + t); + if (!reg_info_Rt) return false; Context context; switch (memop) { - case MemOp_STORE: + case MemOp_STORE: { if (n == 31 || n == GetFramePointerRegisterNumber()) // if this store is // based off of the sp // or fp register context.type = eContextPushRegisterOnStack; else context.type = eContextRegisterStore; - context.SetRegisterToRegisterPlusOffset(reg_info_Rt, reg_info_base, + context.SetRegisterToRegisterPlusOffset(*reg_info_Rt, *reg_info_base, postindex ? 0 : offset); - if (!ReadRegister(®_info_Rt, data_Rt)) + std::optional<RegisterValue> data_Rt = ReadRegister(*reg_info_Rt); + if (!data_Rt) return false; - if (data_Rt.GetAsMemoryData(®_info_Rt, buffer, reg_info_Rt.byte_size, - eByteOrderLittle, error) == 0) + if (data_Rt->GetAsMemoryData(*reg_info_Rt, buffer, reg_info_Rt->byte_size, + eByteOrderLittle, error) == 0) return false; - if (!WriteMemory(context, address, buffer, reg_info_Rt.byte_size)) + if (!WriteMemory(context, address, buffer, reg_info_Rt->byte_size)) return false; - break; + } break; - case MemOp_LOAD: + case MemOp_LOAD: { if (n == 31 || n == GetFramePointerRegisterNumber()) // if this store is // based off of the sp // or fp register @@ -1010,16 +1017,17 @@ bool EmulateInstructionARM64::EmulateLDRSTRImm(const uint32_t opcode) { context.type = eContextRegisterLoad; context.SetAddress(address); - if (!ReadMemory(context, address, buffer, reg_info_Rt.byte_size)) + if (!ReadMemory(context, address, buffer, reg_info_Rt->byte_size)) return false; - if (data_Rt.SetFromMemoryData(®_info_Rt, buffer, reg_info_Rt.byte_size, + RegisterValue data_Rt; + if (data_Rt.SetFromMemoryData(*reg_info_Rt, buffer, reg_info_Rt->byte_size, eByteOrderLittle, error) == 0) return false; - if (!WriteRegister(context, ®_info_Rt, data_Rt)) + if (!WriteRegister(context, *reg_info_Rt, data_Rt)) return false; - break; + } break; default: return false; } @@ -1034,7 +1042,7 @@ bool EmulateInstructionARM64::EmulateLDRSTRImm(const uint32_t opcode) { context.type = eContextAdjustBaseRegister; context.SetImmediateSigned(offset); - if (!WriteRegisterUnsigned(context, ®_info_base, address)) + if (!WriteRegisterUnsigned(context, *reg_info_base, address)) return false; } return true; diff --git a/contrib/llvm-project/lldb/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.h b/contrib/llvm-project/lldb/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.h index 4f11f7387a2e..b4b107fc267b 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.h +++ b/contrib/llvm-project/lldb/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.h @@ -13,6 +13,7 @@ #include "lldb/Core/EmulateInstruction.h" #include "lldb/Interpreter/OptionValue.h" #include "lldb/Utility/Status.h" +#include <optional> class EmulateInstructionARM64 : public lldb_private::EmulateInstruction { public: @@ -65,8 +66,8 @@ public: return false; } - bool GetRegisterInfo(lldb::RegisterKind reg_kind, uint32_t reg_num, - lldb_private::RegisterInfo ®_info) override; + std::optional<lldb_private::RegisterInfo> + GetRegisterInfo(lldb::RegisterKind reg_kind, uint32_t reg_num) override; bool CreateFunctionEntryUnwind(lldb_private::UnwindPlan &unwind_plan) override; diff --git a/contrib/llvm-project/lldb/source/Plugins/Instruction/LoongArch/EmulateInstructionLoongArch.cpp b/contrib/llvm-project/lldb/source/Plugins/Instruction/LoongArch/EmulateInstructionLoongArch.cpp new file mode 100644 index 000000000000..adfd57dff07c --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/Instruction/LoongArch/EmulateInstructionLoongArch.cpp @@ -0,0 +1,544 @@ +//===---EmulateInstructionLoongArch.cpp------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include <cstdlib> +#include <optional> + +#include "EmulateInstructionLoongArch.h" +#include "Plugins/Process/Utility/InstructionUtils.h" +#include "Plugins/Process/Utility/RegisterInfoPOSIX_loongarch64.h" +#include "Plugins/Process/Utility/lldb-loongarch-register-enums.h" +#include "lldb/Core/Address.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Interpreter/OptionValueArray.h" +#include "lldb/Interpreter/OptionValueDictionary.h" +#include "lldb/Symbol/UnwindPlan.h" +#include "lldb/Utility/ArchSpec.h" +#include "lldb/Utility/LLDBLog.h" +#include "lldb/Utility/RegisterValue.h" +#include "lldb/Utility/Stream.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/MathExtras.h" + +using namespace lldb; +using namespace lldb_private; + +LLDB_PLUGIN_DEFINE_ADV(EmulateInstructionLoongArch, InstructionLoongArch) + +namespace lldb_private { + +EmulateInstructionLoongArch::Opcode * +EmulateInstructionLoongArch::GetOpcodeForInstruction(uint32_t inst) { + // TODO: Add the mask for other instruction. + static EmulateInstructionLoongArch::Opcode g_opcodes[] = { + {0xfc000000, 0x40000000, &EmulateInstructionLoongArch::EmulateBEQZ, + "beqz rj, offs21"}, + {0xfc000000, 0x44000000, &EmulateInstructionLoongArch::EmulateBNEZ, + "bnez rj, offs21"}, + {0xfc000300, 0x48000000, &EmulateInstructionLoongArch::EmulateBCEQZ, + "bceqz cj, offs21"}, + {0xfc000300, 0x48000100, &EmulateInstructionLoongArch::EmulateBCNEZ, + "bcnez cj, offs21"}, + {0xfc000000, 0x4c000000, &EmulateInstructionLoongArch::EmulateJIRL, + "jirl rd, rj, offs16"}, + {0xfc000000, 0x50000000, &EmulateInstructionLoongArch::EmulateB, + " b offs26"}, + {0xfc000000, 0x54000000, &EmulateInstructionLoongArch::EmulateBL, + "bl offs26"}, + {0xfc000000, 0x58000000, &EmulateInstructionLoongArch::EmulateBEQ, + "beq rj, rd, offs16"}, + {0xfc000000, 0x5c000000, &EmulateInstructionLoongArch::EmulateBNE, + "bne rj, rd, offs16"}, + {0xfc000000, 0x60000000, &EmulateInstructionLoongArch::EmulateBLT, + "blt rj, rd, offs16"}, + {0xfc000000, 0x64000000, &EmulateInstructionLoongArch::EmulateBGE, + "bge rj, rd, offs16"}, + {0xfc000000, 0x68000000, &EmulateInstructionLoongArch::EmulateBLTU, + "bltu rj, rd, offs16"}, + {0xfc000000, 0x6c000000, &EmulateInstructionLoongArch::EmulateBGEU, + "bgeu rj, rd, offs16"}, + {0x00000000, 0x00000000, &EmulateInstructionLoongArch::EmulateNonJMP, + "NonJMP"}}; + static const size_t num_loongarch_opcodes = std::size(g_opcodes); + + for (size_t i = 0; i < num_loongarch_opcodes; ++i) + if ((g_opcodes[i].mask & inst) == g_opcodes[i].value) + return &g_opcodes[i]; + return nullptr; +} + +bool EmulateInstructionLoongArch::TestExecute(uint32_t inst) { + Opcode *opcode_data = GetOpcodeForInstruction(inst); + if (!opcode_data) + return false; + // Call the Emulate... function. + if (!(this->*opcode_data->callback)(inst)) + return false; + return true; +} + +bool EmulateInstructionLoongArch::EvaluateInstruction(uint32_t options) { + uint32_t inst_size = m_opcode.GetByteSize(); + uint32_t inst = m_opcode.GetOpcode32(); + bool increase_pc = options & eEmulateInstructionOptionAutoAdvancePC; + bool success = false; + + Opcode *opcode_data = GetOpcodeForInstruction(inst); + if (!opcode_data) + return false; + + lldb::addr_t old_pc = 0; + if (increase_pc) { + old_pc = ReadPC(&success); + if (!success) + return false; + } + + // Call the Emulate... function. + if (!(this->*opcode_data->callback)(inst)) + return false; + + if (increase_pc) { + lldb::addr_t new_pc = ReadPC(&success); + if (!success) + return false; + + if (new_pc == old_pc && !WritePC(old_pc + inst_size)) + return false; + } + return true; +} + +bool EmulateInstructionLoongArch::ReadInstruction() { + bool success = false; + m_addr = ReadPC(&success); + if (!success) { + m_addr = LLDB_INVALID_ADDRESS; + return false; + } + + Context ctx; + ctx.type = eContextReadOpcode; + ctx.SetNoArgs(); + uint32_t inst = (uint32_t)ReadMemoryUnsigned(ctx, m_addr, 4, 0, &success); + m_opcode.SetOpcode32(inst, GetByteOrder()); + + return true; +} + +lldb::addr_t EmulateInstructionLoongArch::ReadPC(bool *success) { + return ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, + LLDB_INVALID_ADDRESS, success); +} + +bool EmulateInstructionLoongArch::WritePC(lldb::addr_t pc) { + EmulateInstruction::Context ctx; + ctx.type = eContextAdvancePC; + ctx.SetNoArgs(); + return WriteRegisterUnsigned(ctx, eRegisterKindGeneric, + LLDB_REGNUM_GENERIC_PC, pc); +} + +std::optional<RegisterInfo> +EmulateInstructionLoongArch::GetRegisterInfo(lldb::RegisterKind reg_kind, + uint32_t reg_index) { + if (reg_kind == eRegisterKindGeneric) { + switch (reg_index) { + case LLDB_REGNUM_GENERIC_PC: + reg_kind = eRegisterKindLLDB; + reg_index = gpr_pc_loongarch; + break; + case LLDB_REGNUM_GENERIC_SP: + reg_kind = eRegisterKindLLDB; + reg_index = gpr_sp_loongarch; + break; + case LLDB_REGNUM_GENERIC_FP: + reg_kind = eRegisterKindLLDB; + reg_index = gpr_fp_loongarch; + break; + case LLDB_REGNUM_GENERIC_RA: + reg_kind = eRegisterKindLLDB; + reg_index = gpr_ra_loongarch; + break; + // We may handle LLDB_REGNUM_GENERIC_ARGx when more instructions are + // supported. + default: + llvm_unreachable("unsupported register"); + } + } + + const RegisterInfo *array = + RegisterInfoPOSIX_loongarch64::GetRegisterInfoPtr(m_arch); + const uint32_t length = + RegisterInfoPOSIX_loongarch64::GetRegisterInfoCount(m_arch); + + if (reg_index >= length || reg_kind != eRegisterKindLLDB) + return {}; + return array[reg_index]; +} + +bool EmulateInstructionLoongArch::SetTargetTriple(const ArchSpec &arch) { + return SupportsThisArch(arch); +} + +bool EmulateInstructionLoongArch::TestEmulation( + Stream *out_stream, ArchSpec &arch, OptionValueDictionary *test_data) { + return false; +} + +void EmulateInstructionLoongArch::Initialize() { + PluginManager::RegisterPlugin(GetPluginNameStatic(), + GetPluginDescriptionStatic(), CreateInstance); +} + +void EmulateInstructionLoongArch::Terminate() { + PluginManager::UnregisterPlugin(CreateInstance); +} + +lldb_private::EmulateInstruction * +EmulateInstructionLoongArch::CreateInstance(const ArchSpec &arch, + InstructionType inst_type) { + if (EmulateInstructionLoongArch::SupportsThisInstructionType(inst_type) && + SupportsThisArch(arch)) + return new EmulateInstructionLoongArch(arch); + return nullptr; +} + +bool EmulateInstructionLoongArch::SupportsThisArch(const ArchSpec &arch) { + return arch.GetTriple().isLoongArch(); +} + +bool EmulateInstructionLoongArch::EmulateBEQZ(uint32_t inst) { + return IsLoongArch64() ? EmulateBEQZ64(inst) : false; +} + +bool EmulateInstructionLoongArch::EmulateBNEZ(uint32_t inst) { + return IsLoongArch64() ? EmulateBNEZ64(inst) : false; +} + +bool EmulateInstructionLoongArch::EmulateBCEQZ(uint32_t inst) { + return IsLoongArch64() ? EmulateBCEQZ64(inst) : false; +} + +bool EmulateInstructionLoongArch::EmulateBCNEZ(uint32_t inst) { + return IsLoongArch64() ? EmulateBCNEZ64(inst) : false; +} + +bool EmulateInstructionLoongArch::EmulateJIRL(uint32_t inst) { + return IsLoongArch64() ? EmulateJIRL64(inst) : false; +} + +bool EmulateInstructionLoongArch::EmulateB(uint32_t inst) { + return IsLoongArch64() ? EmulateB64(inst) : false; +} + +bool EmulateInstructionLoongArch::EmulateBL(uint32_t inst) { + return IsLoongArch64() ? EmulateBL64(inst) : false; +} + +bool EmulateInstructionLoongArch::EmulateBEQ(uint32_t inst) { + return IsLoongArch64() ? EmulateBEQ64(inst) : false; +} + +bool EmulateInstructionLoongArch::EmulateBNE(uint32_t inst) { + return IsLoongArch64() ? EmulateBNE64(inst) : false; +} + +bool EmulateInstructionLoongArch::EmulateBLT(uint32_t inst) { + return IsLoongArch64() ? EmulateBLT64(inst) : false; +} + +bool EmulateInstructionLoongArch::EmulateBGE(uint32_t inst) { + return IsLoongArch64() ? EmulateBGE64(inst) : false; +} + +bool EmulateInstructionLoongArch::EmulateBLTU(uint32_t inst) { + return IsLoongArch64() ? EmulateBLTU64(inst) : false; +} + +bool EmulateInstructionLoongArch::EmulateBGEU(uint32_t inst) { + return IsLoongArch64() ? EmulateBGEU64(inst) : false; +} + +bool EmulateInstructionLoongArch::EmulateNonJMP(uint32_t inst) { return false; } + +// beqz rj, offs21 +// if GR[rj] == 0: +// PC = PC + SignExtend({offs21, 2'b0}, GRLEN) +bool EmulateInstructionLoongArch::EmulateBEQZ64(uint32_t inst) { + bool success = false; + uint32_t rj = Bits32(inst, 9, 5); + uint64_t pc = ReadPC(&success); + if (!success) + return false; + uint32_t offs21 = Bits32(inst, 25, 10) + (Bits32(inst, 4, 0) << 16); + uint64_t rj_val = ReadRegisterUnsigned(eRegisterKindLLDB, rj, 0, &success); + if (!success) + return false; + if (rj_val == 0) { + uint64_t next_pc = pc + llvm::SignExtend64<23>(offs21 << 2); + return WritePC(next_pc); + } else + return WritePC(pc + 4); +} + +// bnez rj, offs21 +// if GR[rj] != 0: +// PC = PC + SignExtend({offs21, 2'b0}, GRLEN) +bool EmulateInstructionLoongArch::EmulateBNEZ64(uint32_t inst) { + bool success = false; + uint32_t rj = Bits32(inst, 9, 5); + uint64_t pc = ReadPC(&success); + if (!success) + return false; + uint32_t offs21 = Bits32(inst, 25, 10) + (Bits32(inst, 4, 0) << 16); + uint64_t rj_val = ReadRegisterUnsigned(eRegisterKindLLDB, rj, 0, &success); + if (!success) + return false; + if (rj_val != 0) { + uint64_t next_pc = pc + llvm::SignExtend64<23>(offs21 << 2); + return WritePC(next_pc); + } else + return WritePC(pc + 4); +} + +// bceqz cj, offs21 +// if CFR[cj] == 0: +// PC = PC + SignExtend({offs21, 2'b0}, GRLEN) +bool EmulateInstructionLoongArch::EmulateBCEQZ64(uint32_t inst) { + bool success = false; + uint32_t cj = Bits32(inst, 7, 5) + fpr_fcc0_loongarch; + uint64_t pc = ReadPC(&success); + if (!success) + return false; + uint32_t offs21 = Bits32(inst, 25, 10) + (Bits32(inst, 4, 0) << 16); + uint8_t cj_val = + (uint8_t)ReadRegisterUnsigned(eRegisterKindLLDB, cj, 0, &success); + if (!success) + return false; + if (cj_val == 0) { + uint64_t next_pc = pc + llvm::SignExtend64<23>(offs21 << 2); + return WritePC(next_pc); + } else + return WritePC(pc + 4); + return false; +} + +// bcnez cj, offs21 +// if CFR[cj] != 0: +// PC = PC + SignExtend({offs21, 2'b0}, GRLEN) +bool EmulateInstructionLoongArch::EmulateBCNEZ64(uint32_t inst) { + bool success = false; + uint32_t cj = Bits32(inst, 7, 5) + fpr_fcc0_loongarch; + uint64_t pc = ReadPC(&success); + if (!success) + return false; + uint32_t offs21 = Bits32(inst, 25, 10) + (Bits32(inst, 4, 0) << 16); + uint8_t cj_val = + (uint8_t)ReadRegisterUnsigned(eRegisterKindLLDB, cj, 0, &success); + if (!success) + return false; + if (cj_val != 0) { + uint64_t next_pc = pc + llvm::SignExtend64<23>(offs21 << 2); + return WritePC(next_pc); + } else + return WritePC(pc + 4); + return false; +} + +// jirl rd, rj, offs16 +// GR[rd] = PC + 4 +// PC = GR[rj] + SignExtend({offs16, 2'b0}, GRLEN) +bool EmulateInstructionLoongArch::EmulateJIRL64(uint32_t inst) { + uint32_t rj = Bits32(inst, 9, 5); + uint32_t rd = Bits32(inst, 4, 0); + bool success = false; + uint64_t pc = ReadPC(&success); + if (!success) + return false; + EmulateInstruction::Context ctx; + if (!WriteRegisterUnsigned(ctx, eRegisterKindLLDB, rd, pc + 4)) + return false; + uint64_t rj_val = ReadRegisterUnsigned(eRegisterKindLLDB, rj, 0, &success); + if (!success) + return false; + uint64_t next_pc = rj_val + llvm::SignExtend64<18>(Bits32(inst, 25, 10) << 2); + return WritePC(next_pc); +} + +// b offs26 +// PC = PC + SignExtend({offs26, 2' b0}, GRLEN) +bool EmulateInstructionLoongArch::EmulateB64(uint32_t inst) { + bool success = false; + uint64_t pc = ReadPC(&success); + if (!success) + return false; + uint32_t offs26 = Bits32(inst, 25, 10) + (Bits32(inst, 9, 0) << 16); + uint64_t next_pc = pc + llvm::SignExtend64<28>(offs26 << 2); + return WritePC(next_pc); +} + +// bl offs26 +// GR[1] = PC + 4 +// PC = PC + SignExtend({offs26, 2'b0}, GRLEN) +bool EmulateInstructionLoongArch::EmulateBL64(uint32_t inst) { + bool success = false; + uint64_t pc = ReadPC(&success); + if (!success) + return false; + EmulateInstruction::Context ctx; + if (!WriteRegisterUnsigned(ctx, eRegisterKindLLDB, gpr_r1_loongarch, pc + 4)) + return false; + uint32_t offs26 = Bits32(inst, 25, 10) + (Bits32(inst, 9, 0) << 16); + uint64_t next_pc = pc + llvm::SignExtend64<28>(offs26 << 2); + return WritePC(next_pc); +} + +// beq rj, rd, offs16 +// if GR[rj] == GR[rd]: +// PC = PC + SignExtend({offs16, 2'b0}, GRLEN) +bool EmulateInstructionLoongArch::EmulateBEQ64(uint32_t inst) { + bool success = false; + uint32_t rj = Bits32(inst, 9, 5); + uint32_t rd = Bits32(inst, 4, 0); + uint64_t pc = ReadPC(&success); + if (!success) + return false; + uint64_t rj_val = ReadRegisterUnsigned(eRegisterKindLLDB, rj, 0, &success); + if (!success) + return false; + uint64_t rd_val = ReadRegisterUnsigned(eRegisterKindLLDB, rd, 0, &success); + if (!success) + return false; + if (rj_val == rd_val) { + uint64_t next_pc = pc + llvm::SignExtend64<18>(Bits32(inst, 25, 10) << 2); + return WritePC(next_pc); + } else + return WritePC(pc + 4); +} + +// bne rj, rd, offs16 +// if GR[rj] != GR[rd]: +// PC = PC + SignExtend({offs16, 2'b0}, GRLEN) +bool EmulateInstructionLoongArch::EmulateBNE64(uint32_t inst) { + bool success = false; + uint32_t rj = Bits32(inst, 9, 5); + uint32_t rd = Bits32(inst, 4, 0); + uint64_t pc = ReadPC(&success); + if (!success) + return false; + uint64_t rj_val = ReadRegisterUnsigned(eRegisterKindLLDB, rj, 0, &success); + if (!success) + return false; + uint64_t rd_val = ReadRegisterUnsigned(eRegisterKindLLDB, rd, 0, &success); + if (!success) + return false; + if (rj_val != rd_val) { + uint64_t next_pc = pc + llvm::SignExtend64<18>(Bits32(inst, 25, 10) << 2); + return WritePC(next_pc); + } else + return WritePC(pc + 4); +} + +// blt rj, rd, offs16 +// if signed(GR[rj]) < signed(GR[rd]): +// PC = PC + SignExtend({offs16, 2'b0}, GRLEN) +bool EmulateInstructionLoongArch::EmulateBLT64(uint32_t inst) { + bool success = false; + uint32_t rj = Bits32(inst, 9, 5); + uint32_t rd = Bits32(inst, 4, 0); + uint64_t pc = ReadPC(&success); + if (!success) + return false; + int64_t rj_val = + (int64_t)ReadRegisterUnsigned(eRegisterKindLLDB, rj, 0, &success); + if (!success) + return false; + int64_t rd_val = + (int64_t)ReadRegisterUnsigned(eRegisterKindLLDB, rd, 0, &success); + if (!success) + return false; + if (rj_val < rd_val) { + uint64_t next_pc = pc + llvm::SignExtend64<18>(Bits32(inst, 25, 10) << 2); + return WritePC(next_pc); + } else + return WritePC(pc + 4); +} + +// bge rj, rd, offs16 +// if signed(GR[rj]) >= signed(GR[rd]): +// PC = PC + SignExtend({offs16, 2'b0}, GRLEN) +bool EmulateInstructionLoongArch::EmulateBGE64(uint32_t inst) { + bool success = false; + uint32_t rj = Bits32(inst, 9, 5); + uint32_t rd = Bits32(inst, 4, 0); + uint64_t pc = ReadPC(&success); + if (!success) + return false; + int64_t rj_val = + (int64_t)ReadRegisterUnsigned(eRegisterKindLLDB, rj, 0, &success); + if (!success) + return false; + int64_t rd_val = + (int64_t)ReadRegisterUnsigned(eRegisterKindLLDB, rd, 0, &success); + if (!success) + return false; + if (rj_val >= rd_val) { + uint64_t next_pc = pc + llvm::SignExtend64<18>(Bits32(inst, 25, 10) << 2); + return WritePC(next_pc); + } else + return WritePC(pc + 4); +} + +// bltu rj, rd, offs16 +// if unsigned(GR[rj]) < unsigned(GR[rd]): +// PC = PC + SignExtend({offs16, 2'b0}, GRLEN) +bool EmulateInstructionLoongArch::EmulateBLTU64(uint32_t inst) { + bool success = false; + uint32_t rj = Bits32(inst, 9, 5); + uint32_t rd = Bits32(inst, 4, 0); + uint64_t pc = ReadPC(&success); + if (!success) + return false; + uint64_t rj_val = ReadRegisterUnsigned(eRegisterKindLLDB, rj, 0, &success); + if (!success) + return false; + uint64_t rd_val = ReadRegisterUnsigned(eRegisterKindLLDB, rd, 0, &success); + if (!success) + return false; + if (rj_val < rd_val) { + uint64_t next_pc = pc + llvm::SignExtend64<18>(Bits32(inst, 25, 10) << 2); + return WritePC(next_pc); + } else + return WritePC(pc + 4); +} + +// bgeu rj, rd, offs16 +// if unsigned(GR[rj]) >= unsigned(GR[rd]): +// PC = PC + SignExtend({offs16, 2'b0}, GRLEN) +bool EmulateInstructionLoongArch::EmulateBGEU64(uint32_t inst) { + bool success = false; + uint32_t rj = Bits32(inst, 9, 5); + uint32_t rd = Bits32(inst, 4, 0); + uint64_t pc = ReadPC(&success); + if (!success) + return false; + uint64_t rj_val = ReadRegisterUnsigned(eRegisterKindLLDB, rj, 0, &success); + if (!success) + return false; + uint64_t rd_val = ReadRegisterUnsigned(eRegisterKindLLDB, rd, 0, &success); + if (!success) + return false; + if (rj_val >= rd_val) { + uint64_t next_pc = pc + llvm::SignExtend64<18>(Bits32(inst, 25, 10) << 2); + return WritePC(next_pc); + } else + return WritePC(pc + 4); +} + +} // namespace lldb_private diff --git a/contrib/llvm-project/lldb/source/Plugins/Instruction/LoongArch/EmulateInstructionLoongArch.h b/contrib/llvm-project/lldb/source/Plugins/Instruction/LoongArch/EmulateInstructionLoongArch.h new file mode 100644 index 000000000000..e03356244b47 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/Instruction/LoongArch/EmulateInstructionLoongArch.h @@ -0,0 +1,108 @@ +//===---EmulateInstructionLoongArch.h--------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_SOURCE_PLUGINS_INSTRUCTION_LOONGARCH_EMULATEINSTRUCTIONLOONGARCH_H +#define LLDB_SOURCE_PLUGINS_INSTRUCTION_LOONGARCH_EMULATEINSTRUCTIONLOONGARCH_H + +#include "lldb/Core/EmulateInstruction.h" +#include "lldb/Interpreter/OptionValue.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/Status.h" +#include <optional> + +namespace lldb_private { + +class EmulateInstructionLoongArch : public EmulateInstruction { +public: + static llvm::StringRef GetPluginNameStatic() { return "LoongArch"; } + + static llvm::StringRef GetPluginDescriptionStatic() { + return "Emulate instructions for the LoongArch architecture."; + } + + static bool SupportsThisInstructionType(InstructionType inst_type) { + return inst_type == eInstructionTypePCModifying; + } + + static bool SupportsThisArch(const ArchSpec &arch); + + static lldb_private::EmulateInstruction * + CreateInstance(const lldb_private::ArchSpec &arch, InstructionType inst_type); + + static void Initialize(); + + static void Terminate(); + +public: + EmulateInstructionLoongArch(const ArchSpec &arch) : EmulateInstruction(arch) { + m_arch_subtype = arch.GetMachine(); + } + + llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); } + + bool SupportsEmulatingInstructionsOfType(InstructionType inst_type) override { + return SupportsThisInstructionType(inst_type); + } + + bool SetTargetTriple(const ArchSpec &arch) override; + bool ReadInstruction() override; + bool EvaluateInstruction(uint32_t options) override; + bool TestEmulation(Stream *out_stream, ArchSpec &arch, + OptionValueDictionary *test_data) override; + + std::optional<RegisterInfo> GetRegisterInfo(lldb::RegisterKind reg_kind, + uint32_t reg_num) override; + lldb::addr_t ReadPC(bool *success); + bool WritePC(lldb::addr_t pc); + bool IsLoongArch64() { return m_arch_subtype == llvm::Triple::loongarch64; } + bool TestExecute(uint32_t inst); + +private: + struct Opcode { + uint32_t mask; + uint32_t value; + bool (EmulateInstructionLoongArch::*callback)(uint32_t opcode); + const char *name; + }; + + llvm::Triple::ArchType m_arch_subtype; + Opcode *GetOpcodeForInstruction(uint32_t inst); + + bool EmulateBEQZ(uint32_t inst); + bool EmulateBNEZ(uint32_t inst); + bool EmulateBCEQZ(uint32_t inst); + bool EmulateBCNEZ(uint32_t inst); + bool EmulateJIRL(uint32_t inst); + bool EmulateB(uint32_t inst); + bool EmulateBL(uint32_t inst); + bool EmulateBEQ(uint32_t inst); + bool EmulateBNE(uint32_t inst); + bool EmulateBLT(uint32_t inst); + bool EmulateBGE(uint32_t inst); + bool EmulateBLTU(uint32_t inst); + bool EmulateBGEU(uint32_t inst); + bool EmulateNonJMP(uint32_t inst); + + bool EmulateBEQZ64(uint32_t inst); + bool EmulateBNEZ64(uint32_t inst); + bool EmulateBCEQZ64(uint32_t inst); + bool EmulateBCNEZ64(uint32_t inst); + bool EmulateJIRL64(uint32_t inst); + bool EmulateB64(uint32_t inst); + bool EmulateBL64(uint32_t inst); + bool EmulateBEQ64(uint32_t inst); + bool EmulateBNE64(uint32_t inst); + bool EmulateBLT64(uint32_t inst); + bool EmulateBGE64(uint32_t inst); + bool EmulateBLTU64(uint32_t inst); + bool EmulateBGEU64(uint32_t inst); +}; + +} // namespace lldb_private + +#endif // LLDB_SOURCE_PLUGINS_INSTRUCTION_LOONGARCH_EMULATEINSTRUCTIONLOONGARCH_H diff --git a/contrib/llvm-project/lldb/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp b/contrib/llvm-project/lldb/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp index 7aff11ede400..1be41e4a316b 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp @@ -9,6 +9,7 @@ #include "EmulateInstructionMIPS.h" #include <cstdlib> +#include <optional> #include "lldb/Core/Address.h" #include "lldb/Core/Opcode.h" @@ -585,9 +586,9 @@ const char *EmulateInstructionMIPS::GetRegisterName(unsigned reg_num, return nullptr; } -bool EmulateInstructionMIPS::GetRegisterInfo(RegisterKind reg_kind, - uint32_t reg_num, - RegisterInfo ®_info) { +std::optional<RegisterInfo> +EmulateInstructionMIPS::GetRegisterInfo(RegisterKind reg_kind, + uint32_t reg_num) { if (reg_kind == eRegisterKindGeneric) { switch (reg_num) { case LLDB_REGNUM_GENERIC_PC: @@ -611,11 +612,12 @@ bool EmulateInstructionMIPS::GetRegisterInfo(RegisterKind reg_kind, reg_num = dwarf_sr_mips; break; default: - return false; + return {}; } } if (reg_kind == eRegisterKindDWARF) { + RegisterInfo reg_info; ::memset(®_info, 0, sizeof(RegisterInfo)); ::memset(reg_info.kinds, LLDB_INVALID_REGNUM, sizeof(reg_info.kinds)); @@ -636,7 +638,7 @@ bool EmulateInstructionMIPS::GetRegisterInfo(RegisterKind reg_kind, reg_info.format = eFormatVectorOfUInt8; reg_info.encoding = eEncodingVector; } else { - return false; + return {}; } reg_info.name = GetRegisterName(reg_num, false); @@ -662,9 +664,9 @@ bool EmulateInstructionMIPS::GetRegisterInfo(RegisterKind reg_kind, default: break; } - return true; + return reg_info; } - return false; + return {}; } EmulateInstructionMIPS::MipsOpcode * @@ -1196,10 +1198,10 @@ bool EmulateInstructionMIPS::Emulate_ADDiu(llvm::MCInst &insn) { /* Check if this is daddiu sp, sp, imm16 */ if (dst == dwarf_sp_mips) { uint64_t result = src_opd_val + imm; - RegisterInfo reg_info_sp; - - if (GetRegisterInfo(eRegisterKindDWARF, dwarf_sp_mips, reg_info_sp)) - context.SetRegisterPlusOffset(reg_info_sp, imm); + std::optional<RegisterInfo> reg_info_sp = + GetRegisterInfo(eRegisterKindDWARF, dwarf_sp_mips); + if (reg_info_sp) + context.SetRegisterPlusOffset(*reg_info_sp, imm); /* We are allocating bytes on stack */ context.type = eContextAdjustStackPointer; @@ -1228,13 +1230,12 @@ bool EmulateInstructionMIPS::Emulate_SW(llvm::MCInst &insn) { int32_t address; Context bad_vaddr_context; - RegisterInfo reg_info_base; - src = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); base = m_reg_info->getEncodingValue(insn.getOperand(1).getReg()); - if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base, - reg_info_base)) + std::optional<RegisterInfo> reg_info_base = + GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base); + if (!reg_info_base) return false; /* read base register */ @@ -1253,29 +1254,28 @@ bool EmulateInstructionMIPS::Emulate_SW(llvm::MCInst &insn) { /* We look for sp based non-volatile register stores */ if (nonvolatile_reg_p(src)) { - - RegisterInfo reg_info_src; - - if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + src, - reg_info_src)) + std::optional<RegisterInfo> reg_info_src = + GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + src); + if (!reg_info_src) return false; Context context; - RegisterValue data_src; context.type = eContextPushRegisterOnStack; - context.SetRegisterToRegisterPlusOffset(reg_info_src, reg_info_base, 0); + context.SetRegisterToRegisterPlusOffset(*reg_info_src, *reg_info_base, 0); uint8_t buffer[RegisterValue::kMaxRegisterByteSize]; Status error; - if (!ReadRegister(®_info_base, data_src)) + std::optional<RegisterValue> data_src = ReadRegister(*reg_info_base); + if (!data_src) return false; - if (data_src.GetAsMemoryData(®_info_src, buffer, reg_info_src.byte_size, - eByteOrderLittle, error) == 0) + if (data_src->GetAsMemoryData(*reg_info_src, buffer, + reg_info_src->byte_size, eByteOrderLittle, + error) == 0) return false; - if (!WriteMemory(context, address, buffer, reg_info_src.byte_size)) + if (!WriteMemory(context, address, buffer, reg_info_src->byte_size)) return false; return true; @@ -1294,9 +1294,7 @@ bool EmulateInstructionMIPS::Emulate_LW(llvm::MCInst &insn) { base = m_reg_info->getEncodingValue(insn.getOperand(1).getReg()); imm = insn.getOperand(2).getImm(); - RegisterInfo reg_info_base; - if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base, - reg_info_base)) + if (GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base)) return false; /* read base register */ @@ -1315,17 +1313,16 @@ bool EmulateInstructionMIPS::Emulate_LW(llvm::MCInst &insn) { if (nonvolatile_reg_p(src)) { RegisterValue data_src; - RegisterInfo reg_info_src; - - if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + src, - reg_info_src)) + std::optional<RegisterInfo> reg_info_src = + GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + src); + if (!reg_info_src) return false; Context context; context.type = eContextPopRegisterOffStack; context.SetAddress(address); - return WriteRegister(context, ®_info_src, data_src); + return WriteRegister(context, *reg_info_src, data_src); } return false; @@ -1366,9 +1363,10 @@ bool EmulateInstructionMIPS::Emulate_SUBU_ADDU(llvm::MCInst &insn) { result = src_opd_val + rt_opd_val; Context context; - RegisterInfo reg_info_sp; - if (GetRegisterInfo(eRegisterKindDWARF, dwarf_sp_mips, reg_info_sp)) - context.SetRegisterPlusOffset(reg_info_sp, rt_opd_val); + std::optional<RegisterInfo> reg_info_sp = + GetRegisterInfo(eRegisterKindDWARF, dwarf_sp_mips); + if (reg_info_sp) + context.SetRegisterPlusOffset(*reg_info_sp, rt_opd_val); /* We are allocating bytes on stack */ context.type = eContextAdjustStackPointer; @@ -1441,9 +1439,10 @@ bool EmulateInstructionMIPS::Emulate_ADDIUSP(llvm::MCInst &insn) { result = src_opd_val + imm9; Context context; - RegisterInfo reg_info_sp; - if (GetRegisterInfo(eRegisterKindDWARF, dwarf_sp_mips, reg_info_sp)) - context.SetRegisterPlusOffset(reg_info_sp, imm9); + std::optional<RegisterInfo> reg_info_sp = + GetRegisterInfo(eRegisterKindDWARF, dwarf_sp_mips); + if (reg_info_sp) + context.SetRegisterPlusOffset(*reg_info_sp, imm9); // We are adjusting the stack. context.type = eContextAdjustStackPointer; @@ -1472,9 +1471,10 @@ bool EmulateInstructionMIPS::Emulate_ADDIUS5(llvm::MCInst &insn) { result = src_opd_val + imm4; Context context; - RegisterInfo reg_info_sp; - if (GetRegisterInfo(eRegisterKindDWARF, dwarf_sp_mips, reg_info_sp)) - context.SetRegisterPlusOffset(reg_info_sp, imm4); + std::optional<RegisterInfo> reg_info_sp = + GetRegisterInfo(eRegisterKindDWARF, dwarf_sp_mips); + if (reg_info_sp) + context.SetRegisterPlusOffset(*reg_info_sp, imm4); // We are adjusting the stack. context.type = eContextAdjustStackPointer; @@ -1495,10 +1495,9 @@ bool EmulateInstructionMIPS::Emulate_SWSP(llvm::MCInst &insn) { src = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); base = m_reg_info->getEncodingValue(insn.getOperand(1).getReg()); - RegisterInfo reg_info_base; - - if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base, - reg_info_base)) + std::optional<RegisterInfo> reg_info_base = + GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base); + if (!reg_info_base) return false; // read base register @@ -1521,18 +1520,18 @@ bool EmulateInstructionMIPS::Emulate_SWSP(llvm::MCInst &insn) { if (base == dwarf_sp_mips && nonvolatile_reg_p(src)) { RegisterInfo reg_info_src = {}; Context context; - RegisterValue data_src; context.type = eContextPushRegisterOnStack; - context.SetRegisterToRegisterPlusOffset(reg_info_src, reg_info_base, 0); + context.SetRegisterToRegisterPlusOffset(reg_info_src, *reg_info_base, 0); uint8_t buffer[RegisterValue::kMaxRegisterByteSize]; Status error; - if (!ReadRegister(®_info_base, data_src)) + std::optional<RegisterValue> data_src = ReadRegister(*reg_info_base); + if (!data_src) return false; - if (data_src.GetAsMemoryData(®_info_src, buffer, reg_info_src.byte_size, - eByteOrderLittle, error) == 0) + if (data_src->GetAsMemoryData(reg_info_src, buffer, reg_info_src.byte_size, + eByteOrderLittle, error) == 0) return false; if (!WriteMemory(context, address, buffer, reg_info_src.byte_size)) @@ -1568,11 +1567,9 @@ bool EmulateInstructionMIPS::Emulate_SWM16_32(llvm::MCInst &insn) { // offset is always the last operand. uint32_t offset = insn.getOperand(num_operands - 1).getImm(); - RegisterInfo reg_info_base; - RegisterInfo reg_info_src; - - if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base, - reg_info_base)) + std::optional<RegisterInfo> reg_info_base = + GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base); + if (!reg_info_base) return false; // read SP @@ -1599,30 +1596,32 @@ bool EmulateInstructionMIPS::Emulate_SWM16_32(llvm::MCInst &insn) { if (!nonvolatile_reg_p(src)) return false; - if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + src, - reg_info_src)) + std::optional<RegisterInfo> reg_info_src = + GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + src); + if (!reg_info_src) return false; Context context; - RegisterValue data_src; context.type = eContextPushRegisterOnStack; - context.SetRegisterToRegisterPlusOffset(reg_info_src, reg_info_base, 0); + context.SetRegisterToRegisterPlusOffset(*reg_info_src, *reg_info_base, 0); uint8_t buffer[RegisterValue::kMaxRegisterByteSize]; Status error; - if (!ReadRegister(®_info_base, data_src)) + std::optional<RegisterValue> data_src = ReadRegister(*reg_info_base); + if (!data_src) return false; - if (data_src.GetAsMemoryData(®_info_src, buffer, reg_info_src.byte_size, - eByteOrderLittle, error) == 0) + if (data_src->GetAsMemoryData(*reg_info_src, buffer, + reg_info_src->byte_size, eByteOrderLittle, + error) == 0) return false; - if (!WriteMemory(context, base_address, buffer, reg_info_src.byte_size)) + if (!WriteMemory(context, base_address, buffer, reg_info_src->byte_size)) return false; // Stack address for next register - base_address = base_address + reg_info_src.byte_size; + base_address = base_address + reg_info_src->byte_size; } return true; } @@ -1634,9 +1633,7 @@ bool EmulateInstructionMIPS::Emulate_LWSP(llvm::MCInst &insn) { uint32_t imm5 = insn.getOperand(2).getImm(); Context bad_vaddr_context; - RegisterInfo reg_info_base; - if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base, - reg_info_base)) + if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base)) return false; // read base register @@ -1656,17 +1653,16 @@ bool EmulateInstructionMIPS::Emulate_LWSP(llvm::MCInst &insn) { if (base == dwarf_sp_mips && nonvolatile_reg_p(src)) { RegisterValue data_src; - RegisterInfo reg_info_src; - - if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + src, - reg_info_src)) + std::optional<RegisterInfo> reg_info_src = + GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + src); + if (!reg_info_src) return false; Context context; context.type = eContextPopRegisterOffStack; context.SetAddress(base_address); - return WriteRegister(context, ®_info_src, data_src); + return WriteRegister(context, *reg_info_src, data_src); } return false; @@ -1703,7 +1699,6 @@ bool EmulateInstructionMIPS::Emulate_LWM16_32(llvm::MCInst &insn) { base_address = base_address + imm; RegisterValue data_dst; - RegisterInfo reg_info_dst; // Total no of registers to be re-stored are num_operands-2. for (uint32_t i = 0; i < num_operands - 2; i++) { @@ -1720,15 +1715,16 @@ bool EmulateInstructionMIPS::Emulate_LWM16_32(llvm::MCInst &insn) { if (!nonvolatile_reg_p(dst)) return false; - if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + dst, - reg_info_dst)) + std::optional<RegisterInfo> reg_info_dst = + GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + dst); + if (!reg_info_dst) return false; Context context; context.type = eContextPopRegisterOffStack; context.SetAddress(base_address + (i * 4)); - if (!WriteRegister(context, ®_info_dst, data_dst)) + if (!WriteRegister(context, *reg_info_dst, data_dst)) return false; } @@ -1765,9 +1761,10 @@ bool EmulateInstructionMIPS::Emulate_JRADDIUSP(llvm::MCInst &insn) { ra_val)) return false; - RegisterInfo reg_info_sp; - if (GetRegisterInfo(eRegisterKindDWARF, dwarf_sp_mips, reg_info_sp)) - context.SetRegisterPlusOffset(reg_info_sp, imm5); + std::optional<RegisterInfo> reg_info_sp = + GetRegisterInfo(eRegisterKindDWARF, dwarf_sp_mips); + if (reg_info_sp) + context.SetRegisterPlusOffset(*reg_info_sp, imm5); // We are adjusting stack context.type = eContextAdjustStackPointer; @@ -2983,9 +2980,7 @@ bool EmulateInstructionMIPS::Emulate_LDST_Imm(llvm::MCInst &insn) { m_reg_info->getEncodingValue(insn.getOperand(num_operands - 2).getReg()); imm = insn.getOperand(num_operands - 1).getImm(); - RegisterInfo reg_info_base; - if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base, - reg_info_base)) + if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base)) return false; /* read base register */ @@ -3017,13 +3012,10 @@ bool EmulateInstructionMIPS::Emulate_LDST_Reg(llvm::MCInst &insn) { index = m_reg_info->getEncodingValue(insn.getOperand(num_operands - 1).getReg()); - RegisterInfo reg_info_base, reg_info_index; - if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base, - reg_info_base)) + if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base)) return false; - if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + index, - reg_info_index)) + if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + index)) return false; /* read base register */ diff --git a/contrib/llvm-project/lldb/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.h b/contrib/llvm-project/lldb/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.h index 4862f6c7e0dc..ab30be6a8f0d 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.h +++ b/contrib/llvm-project/lldb/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.h @@ -26,6 +26,7 @@ namespace lldb_private { #include "lldb/Core/EmulateInstruction.h" #include "lldb/Utility/Status.h" +#include <optional> class EmulateInstructionMIPS : public lldb_private::EmulateInstruction { public: @@ -80,8 +81,8 @@ public: return false; } - bool GetRegisterInfo(lldb::RegisterKind reg_kind, uint32_t reg_num, - lldb_private::RegisterInfo ®_info) override; + std::optional<lldb_private::RegisterInfo> + GetRegisterInfo(lldb::RegisterKind reg_kind, uint32_t reg_num) override; bool CreateFunctionEntryUnwind(lldb_private::UnwindPlan &unwind_plan) override; diff --git a/contrib/llvm-project/lldb/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp b/contrib/llvm-project/lldb/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp index b4a860af54bd..c472f90ea3ba 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp @@ -9,6 +9,7 @@ #include "EmulateInstructionMIPS64.h" #include <cstdlib> +#include <optional> #include "lldb/Core/Address.h" #include "lldb/Core/Opcode.h" @@ -572,9 +573,9 @@ const char *EmulateInstructionMIPS64::GetRegisterName(unsigned reg_num, return nullptr; } -bool EmulateInstructionMIPS64::GetRegisterInfo(RegisterKind reg_kind, - uint32_t reg_num, - RegisterInfo ®_info) { +std::optional<RegisterInfo> +EmulateInstructionMIPS64::GetRegisterInfo(RegisterKind reg_kind, + uint32_t reg_num) { if (reg_kind == eRegisterKindGeneric) { switch (reg_num) { case LLDB_REGNUM_GENERIC_PC: @@ -598,11 +599,12 @@ bool EmulateInstructionMIPS64::GetRegisterInfo(RegisterKind reg_kind, reg_num = dwarf_sr_mips64; break; default: - return false; + return {}; } } if (reg_kind == eRegisterKindDWARF) { + RegisterInfo reg_info; ::memset(®_info, 0, sizeof(RegisterInfo)); ::memset(reg_info.kinds, LLDB_INVALID_REGNUM, sizeof(reg_info.kinds)); @@ -623,7 +625,7 @@ bool EmulateInstructionMIPS64::GetRegisterInfo(RegisterKind reg_kind, reg_info.format = eFormatVectorOfUInt8; reg_info.encoding = eEncodingVector; } else { - return false; + return {}; } reg_info.name = GetRegisterName(reg_num, false); @@ -649,9 +651,9 @@ bool EmulateInstructionMIPS64::GetRegisterInfo(RegisterKind reg_kind, default: break; } - return true; + return reg_info; } - return false; + return {}; } EmulateInstructionMIPS64::MipsOpcode * @@ -1097,10 +1099,10 @@ bool EmulateInstructionMIPS64::Emulate_DADDiu(llvm::MCInst &insn) { * Assume 2's complement and rely on unsigned overflow here. */ uint64_t result = src_opd_val + imm; - RegisterInfo reg_info_sp; - - if (GetRegisterInfo(eRegisterKindDWARF, dwarf_sp_mips64, reg_info_sp)) - context.SetRegisterPlusOffset(reg_info_sp, imm); + std::optional<RegisterInfo> reg_info_sp = + GetRegisterInfo(eRegisterKindDWARF, dwarf_sp_mips64); + if (reg_info_sp) + context.SetRegisterPlusOffset(*reg_info_sp, imm); /* We are allocating bytes on stack */ context.type = eContextAdjustStackPointer; @@ -1124,8 +1126,6 @@ bool EmulateInstructionMIPS64::Emulate_DADDiu(llvm::MCInst &insn) { bool EmulateInstructionMIPS64::Emulate_SD(llvm::MCInst &insn) { uint64_t address; - RegisterInfo reg_info_base; - RegisterInfo reg_info_src; bool success = false; uint32_t imm16 = insn.getOperand(2).getImm(); uint64_t imm = SignedBits(imm16, 15, 0); @@ -1135,10 +1135,11 @@ bool EmulateInstructionMIPS64::Emulate_SD(llvm::MCInst &insn) { src = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); base = m_reg_info->getEncodingValue(insn.getOperand(1).getReg()); - if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips64 + base, - reg_info_base) || - !GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips64 + src, - reg_info_src)) + std::optional<RegisterInfo> reg_info_base = + GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips64 + base); + std::optional<RegisterInfo> reg_info_src = + GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips64 + src); + if (!reg_info_base || !reg_info_src) return false; /* read SP */ @@ -1153,21 +1154,22 @@ bool EmulateInstructionMIPS64::Emulate_SD(llvm::MCInst &insn) { /* We look for sp based non-volatile register stores */ if (nonvolatile_reg_p(src)) { Context context; - RegisterValue data_src; context.type = eContextPushRegisterOnStack; - context.SetRegisterToRegisterPlusOffset(reg_info_src, reg_info_base, 0); + context.SetRegisterToRegisterPlusOffset(*reg_info_src, *reg_info_base, 0); uint8_t buffer[RegisterValue::kMaxRegisterByteSize]; Status error; - if (!ReadRegister(®_info_base, data_src)) + std::optional<RegisterValue> data_src = ReadRegister(*reg_info_base); + if (!data_src) return false; - if (data_src.GetAsMemoryData(®_info_src, buffer, reg_info_src.byte_size, - eByteOrderLittle, error) == 0) + if (data_src->GetAsMemoryData(*reg_info_src, buffer, + reg_info_src->byte_size, eByteOrderLittle, + error) == 0) return false; - if (!WriteMemory(context, address, buffer, reg_info_src.byte_size)) + if (!WriteMemory(context, address, buffer, reg_info_src->byte_size)) return false; } @@ -1189,9 +1191,7 @@ bool EmulateInstructionMIPS64::Emulate_LD(llvm::MCInst &insn) { base = m_reg_info->getEncodingValue(insn.getOperand(1).getReg()); imm = insn.getOperand(2).getImm(); - RegisterInfo reg_info_base; - if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips64 + base, - reg_info_base)) + if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips64 + base)) return false; /* read base register */ @@ -1210,16 +1210,15 @@ bool EmulateInstructionMIPS64::Emulate_LD(llvm::MCInst &insn) { if (nonvolatile_reg_p(src)) { RegisterValue data_src; - RegisterInfo reg_info_src; - - if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips64 + src, - reg_info_src)) + std::optional<RegisterInfo> reg_info_src = + GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips64 + src); + if (!reg_info_src) return false; Context context; context.type = eContextRegisterLoad; - return WriteRegister(context, ®_info_src, data_src); + return WriteRegister(context, *reg_info_src, data_src); } return false; @@ -1278,9 +1277,10 @@ bool EmulateInstructionMIPS64::Emulate_DSUBU_DADDU(llvm::MCInst &insn) { result = src_opd_val + rt_opd_val; Context context; - RegisterInfo reg_info_sp; - if (GetRegisterInfo(eRegisterKindDWARF, dwarf_sp_mips64, reg_info_sp)) - context.SetRegisterPlusOffset(reg_info_sp, rt_opd_val); + std::optional<RegisterInfo> reg_info_sp = + GetRegisterInfo(eRegisterKindDWARF, dwarf_sp_mips64); + if (reg_info_sp) + context.SetRegisterPlusOffset(*reg_info_sp, rt_opd_val); /* We are allocating bytes on stack */ context.type = eContextAdjustStackPointer; @@ -2306,9 +2306,7 @@ bool EmulateInstructionMIPS64::Emulate_LDST_Imm(llvm::MCInst &insn) { m_reg_info->getEncodingValue(insn.getOperand(num_operands - 2).getReg()); imm = insn.getOperand(num_operands - 1).getImm(); - RegisterInfo reg_info_base; - if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base, - reg_info_base)) + if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base)) return false; /* read base register */ @@ -2340,13 +2338,10 @@ bool EmulateInstructionMIPS64::Emulate_LDST_Reg(llvm::MCInst &insn) { index = m_reg_info->getEncodingValue(insn.getOperand(num_operands - 1).getReg()); - RegisterInfo reg_info_base, reg_info_index; - if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base, - reg_info_base)) + if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base)) return false; - if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + index, - reg_info_index)) + if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + index)) return false; /* read base register */ diff --git a/contrib/llvm-project/lldb/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.h b/contrib/llvm-project/lldb/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.h index 3f56bc658c16..e94269e52f83 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.h +++ b/contrib/llvm-project/lldb/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.h @@ -12,6 +12,7 @@ #include "lldb/Core/EmulateInstruction.h" #include "lldb/Interpreter/OptionValue.h" #include "lldb/Utility/Status.h" +#include <optional> namespace llvm { class MCDisassembler; @@ -72,8 +73,8 @@ public: return false; } - bool GetRegisterInfo(lldb::RegisterKind reg_kind, uint32_t reg_num, - lldb_private::RegisterInfo ®_info) override; + std::optional<lldb_private::RegisterInfo> + GetRegisterInfo(lldb::RegisterKind reg_kind, uint32_t reg_num) override; bool CreateFunctionEntryUnwind(lldb_private::UnwindPlan &unwind_plan) override; diff --git a/contrib/llvm-project/lldb/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.cpp b/contrib/llvm-project/lldb/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.cpp index 13cd4db22714..3035c5134177 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.cpp @@ -9,6 +9,7 @@ #include "EmulateInstructionPPC64.h" #include <cstdlib> +#include <optional> #include "Plugins/Process/Utility/lldb-ppc64le-register-enums.h" #include "lldb/Core/PluginManager.h" @@ -58,16 +59,15 @@ bool EmulateInstructionPPC64::SetTargetTriple(const ArchSpec &arch) { return arch.GetTriple().isPPC64(); } -static bool LLDBTableGetRegisterInfo(uint32_t reg_num, RegisterInfo ®_info) { - if (reg_num >= llvm::array_lengthof(g_register_infos_ppc64le)) - return false; - reg_info = g_register_infos_ppc64le[reg_num]; - return true; +static std::optional<RegisterInfo> LLDBTableGetRegisterInfo(uint32_t reg_num) { + if (reg_num >= std::size(g_register_infos_ppc64le)) + return {}; + return g_register_infos_ppc64le[reg_num]; } -bool EmulateInstructionPPC64::GetRegisterInfo(RegisterKind reg_kind, - uint32_t reg_num, - RegisterInfo ®_info) { +std::optional<RegisterInfo> +EmulateInstructionPPC64::GetRegisterInfo(RegisterKind reg_kind, + uint32_t reg_num) { if (reg_kind == eRegisterKindGeneric) { switch (reg_num) { case LLDB_REGNUM_GENERIC_PC: @@ -88,13 +88,13 @@ bool EmulateInstructionPPC64::GetRegisterInfo(RegisterKind reg_kind, break; default: - return false; + return {}; } } if (reg_kind == eRegisterKindLLDB) - return LLDBTableGetRegisterInfo(reg_num, reg_info); - return false; + return LLDBTableGetRegisterInfo(reg_num); + return {}; } bool EmulateInstructionPPC64::ReadInstruction() { @@ -147,7 +147,7 @@ EmulateInstructionPPC64::GetOpcodeForInstruction(uint32_t opcode) { "addi RT, RA, SI"}, {0xfc000003, 0xe8000000, &EmulateInstructionPPC64::EmulateLD, "ld RT, DS(RA)"}}; - static const size_t k_num_ppc_opcodes = llvm::array_lengthof(g_opcodes); + static const size_t k_num_ppc_opcodes = std::size(g_opcodes); for (size_t i = 0; i < k_num_ppc_opcodes; ++i) { if ((g_opcodes[i].mask & opcode) == g_opcodes[i].value) @@ -240,14 +240,15 @@ bool EmulateInstructionPPC64::EmulateLD(uint32_t opcode) { Log *log = GetLog(LLDBLog::Unwind); LLDB_LOG(log, "EmulateLD: {0:X+8}: ld r{1}, {2}(r{3})", m_addr, rt, ids, ra); - RegisterInfo r1_info; - if (!GetRegisterInfo(eRegisterKindLLDB, gpr_r1_ppc64le, r1_info)) + std::optional<RegisterInfo> r1_info = + GetRegisterInfo(eRegisterKindLLDB, gpr_r1_ppc64le); + if (!r1_info) return false; // restore SP Context ctx; ctx.type = eContextRestoreStackPointer; - ctx.SetRegisterToRegisterPlusOffset(r1_info, r1_info, 0); + ctx.SetRegisterToRegisterPlusOffset(*r1_info, *r1_info, 0); WriteRegisterUnsigned(ctx, eRegisterKindLLDB, gpr_r1_ppc64le, 0); LLDB_LOG(log, "EmulateLD: success!"); @@ -290,16 +291,17 @@ bool EmulateInstructionPPC64::EmulateSTD(uint32_t opcode) { } // set context - RegisterInfo rs_info; - if (!GetRegisterInfo(eRegisterKindLLDB, rs_num, rs_info)) + std::optional<RegisterInfo> rs_info = + GetRegisterInfo(eRegisterKindLLDB, rs_num); + if (!rs_info) return false; - RegisterInfo ra_info; - if (!GetRegisterInfo(eRegisterKindLLDB, ra, ra_info)) + std::optional<RegisterInfo> ra_info = GetRegisterInfo(eRegisterKindLLDB, ra); + if (!ra_info) return false; Context ctx; ctx.type = eContextPushRegisterOnStack; - ctx.SetRegisterToRegisterPlusOffset(rs_info, ra_info, ids); + ctx.SetRegisterToRegisterPlusOffset(*rs_info, *ra_info, ids); // store uint64_t ra_val = ReadRegisterUnsigned(eRegisterKindLLDB, ra, 0, &success); @@ -335,13 +337,13 @@ bool EmulateInstructionPPC64::EmulateOR(uint32_t opcode) { LLDB_LOG(log, "EmulateOR: {0:X+8}: mr r{1}, r{2}", m_addr, ra, rb); // set context - RegisterInfo ra_info; - if (!GetRegisterInfo(eRegisterKindLLDB, ra, ra_info)) + std::optional<RegisterInfo> ra_info = GetRegisterInfo(eRegisterKindLLDB, ra); + if (!ra_info) return false; Context ctx; ctx.type = eContextSetFramePointer; - ctx.SetRegister(ra_info); + ctx.SetRegister(*ra_info); // move bool success; @@ -370,13 +372,14 @@ bool EmulateInstructionPPC64::EmulateADDI(uint32_t opcode) { LLDB_LOG(log, "EmulateADDI: {0:X+8}: addi r1, r1, {1}", m_addr, si_val); // set context - RegisterInfo r1_info; - if (!GetRegisterInfo(eRegisterKindLLDB, gpr_r1_ppc64le, r1_info)) + std::optional<RegisterInfo> r1_info = + GetRegisterInfo(eRegisterKindLLDB, gpr_r1_ppc64le); + if (!r1_info) return false; Context ctx; ctx.type = eContextRestoreStackPointer; - ctx.SetRegisterToRegisterPlusOffset(r1_info, r1_info, 0); + ctx.SetRegisterToRegisterPlusOffset(*r1_info, *r1_info, 0); // adjust SP bool success; diff --git a/contrib/llvm-project/lldb/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.h b/contrib/llvm-project/lldb/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.h index 117ff8965eb5..7b63819e5131 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.h +++ b/contrib/llvm-project/lldb/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.h @@ -12,6 +12,7 @@ #include "lldb/Core/EmulateInstruction.h" #include "lldb/Interpreter/OptionValue.h" #include "lldb/Utility/Log.h" +#include <optional> namespace lldb_private { @@ -61,8 +62,8 @@ public: return false; } - bool GetRegisterInfo(lldb::RegisterKind reg_kind, uint32_t reg_num, - RegisterInfo ®_info) override; + std::optional<RegisterInfo> GetRegisterInfo(lldb::RegisterKind reg_kind, + uint32_t reg_num) override; bool CreateFunctionEntryUnwind(UnwindPlan &unwind_plan) override; diff --git a/contrib/llvm-project/lldb/source/Plugins/Instruction/RISCV/EmulateInstructionRISCV.cpp b/contrib/llvm-project/lldb/source/Plugins/Instruction/RISCV/EmulateInstructionRISCV.cpp new file mode 100644 index 000000000000..06772aaa6e17 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/Instruction/RISCV/EmulateInstructionRISCV.cpp @@ -0,0 +1,1780 @@ +//===-- EmulateInstructionRISCV.cpp ---------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "EmulateInstructionRISCV.h" +#include "Plugins/Process/Utility/RegisterInfoPOSIX_riscv64.h" +#include "Plugins/Process/Utility/lldb-riscv-register-enums.h" +#include "RISCVCInstructions.h" +#include "RISCVInstructions.h" + +#include "lldb/Core/Address.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Interpreter/OptionValueArray.h" +#include "lldb/Interpreter/OptionValueDictionary.h" +#include "lldb/Symbol/UnwindPlan.h" +#include "lldb/Utility/ArchSpec.h" +#include "lldb/Utility/LLDBLog.h" +#include "lldb/Utility/Stream.h" + +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/MathExtras.h" +#include <optional> + +using namespace llvm; +using namespace lldb; +using namespace lldb_private; + +LLDB_PLUGIN_DEFINE_ADV(EmulateInstructionRISCV, InstructionRISCV) + +namespace lldb_private { + +/// Returns all values wrapped in Optional, or std::nullopt if any of the values +/// is std::nullopt. +template <typename... Ts> +static std::optional<std::tuple<Ts...>> zipOpt(std::optional<Ts> &&...ts) { + if ((ts.has_value() && ...)) + return std::optional<std::tuple<Ts...>>(std::make_tuple(std::move(*ts)...)); + else + return std::nullopt; +} + +// The funct3 is the type of compare in B<CMP> instructions. +// funct3 means "3-bits function selector", which RISC-V ISA uses as minor +// opcode. It reuses the major opcode encoding space. +constexpr uint32_t BEQ = 0b000; +constexpr uint32_t BNE = 0b001; +constexpr uint32_t BLT = 0b100; +constexpr uint32_t BGE = 0b101; +constexpr uint32_t BLTU = 0b110; +constexpr uint32_t BGEU = 0b111; + +// used in decoder +constexpr int32_t SignExt(uint32_t imm) { return int32_t(imm); } + +// used in executor +template <typename T> +constexpr std::enable_if_t<sizeof(T) <= 4, uint64_t> SextW(T value) { + return uint64_t(int64_t(int32_t(value))); +} + +// used in executor +template <typename T> constexpr uint64_t ZextD(T value) { + return uint64_t(value); +} + +constexpr uint32_t DecodeJImm(uint32_t inst) { + return (uint64_t(int64_t(int32_t(inst & 0x80000000)) >> 11)) // imm[20] + | (inst & 0xff000) // imm[19:12] + | ((inst >> 9) & 0x800) // imm[11] + | ((inst >> 20) & 0x7fe); // imm[10:1] +} + +constexpr uint32_t DecodeIImm(uint32_t inst) { + return int64_t(int32_t(inst)) >> 20; // imm[11:0] +} + +constexpr uint32_t DecodeBImm(uint32_t inst) { + return (uint64_t(int64_t(int32_t(inst & 0x80000000)) >> 19)) // imm[12] + | ((inst & 0x80) << 4) // imm[11] + | ((inst >> 20) & 0x7e0) // imm[10:5] + | ((inst >> 7) & 0x1e); // imm[4:1] +} + +constexpr uint32_t DecodeSImm(uint32_t inst) { + return (uint64_t(int64_t(int32_t(inst & 0xFE000000)) >> 20)) // imm[11:5] + | ((inst & 0xF80) >> 7); // imm[4:0] +} + +constexpr uint32_t DecodeUImm(uint32_t inst) { + return SextW(inst & 0xFFFFF000); // imm[31:12] +} + +static uint32_t GPREncodingToLLDB(uint32_t reg_encode) { + if (reg_encode == 0) + return gpr_x0_riscv; + if (reg_encode >= 1 && reg_encode <= 31) + return gpr_x1_riscv + reg_encode - 1; + return LLDB_INVALID_REGNUM; +} + +static uint32_t FPREncodingToLLDB(uint32_t reg_encode) { + if (reg_encode <= 31) + return fpr_f0_riscv + reg_encode; + return LLDB_INVALID_REGNUM; +} + +bool Rd::Write(EmulateInstructionRISCV &emulator, uint64_t value) { + uint32_t lldb_reg = GPREncodingToLLDB(rd); + EmulateInstruction::Context ctx; + ctx.type = EmulateInstruction::eContextRegisterStore; + ctx.SetNoArgs(); + RegisterValue registerValue; + registerValue.SetUInt64(value); + return emulator.WriteRegister(ctx, eRegisterKindLLDB, lldb_reg, + registerValue); +} + +bool Rd::WriteAPFloat(EmulateInstructionRISCV &emulator, APFloat value) { + uint32_t lldb_reg = FPREncodingToLLDB(rd); + EmulateInstruction::Context ctx; + ctx.type = EmulateInstruction::eContextRegisterStore; + ctx.SetNoArgs(); + RegisterValue registerValue; + registerValue.SetUInt64(value.bitcastToAPInt().getZExtValue()); + return emulator.WriteRegister(ctx, eRegisterKindLLDB, lldb_reg, + registerValue); +} + +std::optional<uint64_t> Rs::Read(EmulateInstructionRISCV &emulator) { + uint32_t lldbReg = GPREncodingToLLDB(rs); + RegisterValue value; + return emulator.ReadRegister(eRegisterKindLLDB, lldbReg, value) + ? std::optional<uint64_t>(value.GetAsUInt64()) + : std::nullopt; +} + +std::optional<int32_t> Rs::ReadI32(EmulateInstructionRISCV &emulator) { + return transformOptional( + Read(emulator), [](uint64_t value) { return int32_t(uint32_t(value)); }); +} + +std::optional<int64_t> Rs::ReadI64(EmulateInstructionRISCV &emulator) { + return transformOptional(Read(emulator), + [](uint64_t value) { return int64_t(value); }); +} + +std::optional<uint32_t> Rs::ReadU32(EmulateInstructionRISCV &emulator) { + return transformOptional(Read(emulator), + [](uint64_t value) { return uint32_t(value); }); +} + +std::optional<APFloat> Rs::ReadAPFloat(EmulateInstructionRISCV &emulator, + bool isDouble) { + uint32_t lldbReg = FPREncodingToLLDB(rs); + RegisterValue value; + if (!emulator.ReadRegister(eRegisterKindLLDB, lldbReg, value)) + return std::nullopt; + uint64_t bits = value.GetAsUInt64(); + APInt api(64, bits, false); + return APFloat(isDouble ? APFloat(api.bitsToDouble()) + : APFloat(api.bitsToFloat())); +} + +static bool CompareB(uint64_t rs1, uint64_t rs2, uint32_t funct3) { + switch (funct3) { + case BEQ: + return rs1 == rs2; + case BNE: + return rs1 != rs2; + case BLT: + return int64_t(rs1) < int64_t(rs2); + case BGE: + return int64_t(rs1) >= int64_t(rs2); + case BLTU: + return rs1 < rs2; + case BGEU: + return rs1 >= rs2; + default: + llvm_unreachable("unexpected funct3"); + } +} + +template <typename T> +constexpr bool is_load = + std::is_same_v<T, LB> || std::is_same_v<T, LH> || std::is_same_v<T, LW> || + std::is_same_v<T, LD> || std::is_same_v<T, LBU> || std::is_same_v<T, LHU> || + std::is_same_v<T, LWU>; + +template <typename T> +constexpr bool is_store = std::is_same_v<T, SB> || std::is_same_v<T, SH> || + std::is_same_v<T, SW> || std::is_same_v<T, SD>; + +template <typename T> +constexpr bool is_amo_add = + std::is_same_v<T, AMOADD_W> || std::is_same_v<T, AMOADD_D>; + +template <typename T> +constexpr bool is_amo_bit_op = + std::is_same_v<T, AMOXOR_W> || std::is_same_v<T, AMOXOR_D> || + std::is_same_v<T, AMOAND_W> || std::is_same_v<T, AMOAND_D> || + std::is_same_v<T, AMOOR_W> || std::is_same_v<T, AMOOR_D>; + +template <typename T> +constexpr bool is_amo_swap = + std::is_same_v<T, AMOSWAP_W> || std::is_same_v<T, AMOSWAP_D>; + +template <typename T> +constexpr bool is_amo_cmp = + std::is_same_v<T, AMOMIN_W> || std::is_same_v<T, AMOMIN_D> || + std::is_same_v<T, AMOMAX_W> || std::is_same_v<T, AMOMAX_D> || + std::is_same_v<T, AMOMINU_W> || std::is_same_v<T, AMOMINU_D> || + std::is_same_v<T, AMOMAXU_W> || std::is_same_v<T, AMOMAXU_D>; + +template <typename I> +static std::enable_if_t<is_load<I> || is_store<I>, std::optional<uint64_t>> +LoadStoreAddr(EmulateInstructionRISCV &emulator, I inst) { + return transformOptional(inst.rs1.Read(emulator), [&](uint64_t rs1) { + return rs1 + uint64_t(SignExt(inst.imm)); + }); +} + +// Read T from memory, then load its sign-extended value m_emu to register. +template <typename I, typename T, typename E> +static std::enable_if_t<is_load<I>, bool> +Load(EmulateInstructionRISCV &emulator, I inst, uint64_t (*extend)(E)) { + auto addr = LoadStoreAddr(emulator, inst); + if (!addr) + return false; + return transformOptional( + emulator.ReadMem<T>(*addr), + [&](T t) { return inst.rd.Write(emulator, extend(E(t))); }) + .value_or(false); +} + +template <typename I, typename T> +static std::enable_if_t<is_store<I>, bool> +Store(EmulateInstructionRISCV &emulator, I inst) { + auto addr = LoadStoreAddr(emulator, inst); + if (!addr) + return false; + return transformOptional( + inst.rs2.Read(emulator), + [&](uint64_t rs2) { return emulator.WriteMem<T>(*addr, rs2); }) + .value_or(false); +} + +template <typename I> +static std::enable_if_t<is_amo_add<I> || is_amo_bit_op<I> || is_amo_swap<I> || + is_amo_cmp<I>, + std::optional<uint64_t>> +AtomicAddr(EmulateInstructionRISCV &emulator, I inst, unsigned int align) { + return transformOptional(inst.rs1.Read(emulator), + [&](uint64_t rs1) { + return rs1 % align == 0 + ? std::optional<uint64_t>(rs1) + : std::nullopt; + }) + .value_or(std::nullopt); +} + +template <typename I, typename T> +static std::enable_if_t<is_amo_swap<I>, bool> +AtomicSwap(EmulateInstructionRISCV &emulator, I inst, int align, + uint64_t (*extend)(T)) { + auto addr = AtomicAddr(emulator, inst, align); + if (!addr) + return false; + return transformOptional( + zipOpt(emulator.ReadMem<T>(*addr), inst.rs2.Read(emulator)), + [&](auto &&tup) { + auto [tmp, rs2] = tup; + return emulator.WriteMem<T>(*addr, T(rs2)) && + inst.rd.Write(emulator, extend(tmp)); + }) + .value_or(false); +} + +template <typename I, typename T> +static std::enable_if_t<is_amo_add<I>, bool> +AtomicADD(EmulateInstructionRISCV &emulator, I inst, int align, + uint64_t (*extend)(T)) { + auto addr = AtomicAddr(emulator, inst, align); + if (!addr) + return false; + return transformOptional( + zipOpt(emulator.ReadMem<T>(*addr), inst.rs2.Read(emulator)), + [&](auto &&tup) { + auto [tmp, rs2] = tup; + return emulator.WriteMem<T>(*addr, T(tmp + rs2)) && + inst.rd.Write(emulator, extend(tmp)); + }) + .value_or(false); +} + +template <typename I, typename T> +static std::enable_if_t<is_amo_bit_op<I>, bool> +AtomicBitOperate(EmulateInstructionRISCV &emulator, I inst, int align, + uint64_t (*extend)(T), T (*operate)(T, T)) { + auto addr = AtomicAddr(emulator, inst, align); + if (!addr) + return false; + return transformOptional( + zipOpt(emulator.ReadMem<T>(*addr), inst.rs2.Read(emulator)), + [&](auto &&tup) { + auto [value, rs2] = tup; + return emulator.WriteMem<T>(*addr, operate(value, T(rs2))) && + inst.rd.Write(emulator, extend(value)); + }) + .value_or(false); +} + +template <typename I, typename T> +static std::enable_if_t<is_amo_cmp<I>, bool> +AtomicCmp(EmulateInstructionRISCV &emulator, I inst, int align, + uint64_t (*extend)(T), T (*cmp)(T, T)) { + auto addr = AtomicAddr(emulator, inst, align); + if (!addr) + return false; + return transformOptional( + zipOpt(emulator.ReadMem<T>(*addr), inst.rs2.Read(emulator)), + [&](auto &&tup) { + auto [value, rs2] = tup; + return emulator.WriteMem<T>(*addr, cmp(value, T(rs2))) && + inst.rd.Write(emulator, extend(value)); + }) + .value_or(false); +} + +bool AtomicSequence(EmulateInstructionRISCV &emulator) { + // The atomic sequence is always 4 instructions long: + // example: + // 110cc: 100427af lr.w a5,(s0) + // 110d0: 00079663 bnez a5,110dc + // 110d4: 1ce426af sc.w.aq a3,a4,(s0) + // 110d8: fe069ae3 bnez a3,110cc + // 110dc: ........ <next instruction> + const auto pc = emulator.ReadPC(); + if (!pc) + return false; + auto current_pc = *pc; + const auto entry_pc = current_pc; + + // The first instruction should be LR.W or LR.D + auto inst = emulator.ReadInstructionAt(current_pc); + if (!inst || (!std::holds_alternative<LR_W>(inst->decoded) && + !std::holds_alternative<LR_D>(inst->decoded))) + return false; + + // The second instruction should be BNE to exit address + inst = emulator.ReadInstructionAt(current_pc += 4); + if (!inst || !std::holds_alternative<B>(inst->decoded)) + return false; + auto bne_exit = std::get<B>(inst->decoded); + if (bne_exit.funct3 != BNE) + return false; + // save the exit address to check later + const auto exit_pc = current_pc + SextW(bne_exit.imm); + + // The third instruction should be SC.W or SC.D + inst = emulator.ReadInstructionAt(current_pc += 4); + if (!inst || (!std::holds_alternative<SC_W>(inst->decoded) && + !std::holds_alternative<SC_D>(inst->decoded))) + return false; + + // The fourth instruction should be BNE to entry address + inst = emulator.ReadInstructionAt(current_pc += 4); + if (!inst || !std::holds_alternative<B>(inst->decoded)) + return false; + auto bne_start = std::get<B>(inst->decoded); + if (bne_start.funct3 != BNE) + return false; + if (entry_pc != current_pc + SextW(bne_start.imm)) + return false; + + current_pc += 4; + // check the exit address and jump to it + return exit_pc == current_pc && emulator.WritePC(current_pc); +} + +template <typename T> static RISCVInst DecodeUType(uint32_t inst) { + return T{Rd{DecodeRD(inst)}, DecodeUImm(inst)}; +} + +template <typename T> static RISCVInst DecodeJType(uint32_t inst) { + return T{Rd{DecodeRD(inst)}, DecodeJImm(inst)}; +} + +template <typename T> static RISCVInst DecodeIType(uint32_t inst) { + return T{Rd{DecodeRD(inst)}, Rs{DecodeRS1(inst)}, DecodeIImm(inst)}; +} + +template <typename T> static RISCVInst DecodeBType(uint32_t inst) { + return T{Rs{DecodeRS1(inst)}, Rs{DecodeRS2(inst)}, DecodeBImm(inst), + DecodeFunct3(inst)}; +} + +template <typename T> static RISCVInst DecodeSType(uint32_t inst) { + return T{Rs{DecodeRS1(inst)}, Rs{DecodeRS2(inst)}, DecodeSImm(inst)}; +} + +template <typename T> static RISCVInst DecodeRType(uint32_t inst) { + return T{Rd{DecodeRD(inst)}, Rs{DecodeRS1(inst)}, Rs{DecodeRS2(inst)}}; +} + +template <typename T> static RISCVInst DecodeRShamtType(uint32_t inst) { + return T{Rd{DecodeRD(inst)}, Rs{DecodeRS1(inst)}, DecodeRS2(inst)}; +} + +template <typename T> static RISCVInst DecodeRRS1Type(uint32_t inst) { + return T{Rd{DecodeRD(inst)}, Rs{DecodeRS1(inst)}}; +} + +template <typename T> static RISCVInst DecodeR4Type(uint32_t inst) { + return T{Rd{DecodeRD(inst)}, Rs{DecodeRS1(inst)}, Rs{DecodeRS2(inst)}, + Rs{DecodeRS3(inst)}, DecodeRM(inst)}; +} + +static const InstrPattern PATTERNS[] = { + // RV32I & RV64I (The base integer ISA) // + {"LUI", 0x7F, 0x37, DecodeUType<LUI>}, + {"AUIPC", 0x7F, 0x17, DecodeUType<AUIPC>}, + {"JAL", 0x7F, 0x6F, DecodeJType<JAL>}, + {"JALR", 0x707F, 0x67, DecodeIType<JALR>}, + {"B", 0x7F, 0x63, DecodeBType<B>}, + {"LB", 0x707F, 0x3, DecodeIType<LB>}, + {"LH", 0x707F, 0x1003, DecodeIType<LH>}, + {"LW", 0x707F, 0x2003, DecodeIType<LW>}, + {"LBU", 0x707F, 0x4003, DecodeIType<LBU>}, + {"LHU", 0x707F, 0x5003, DecodeIType<LHU>}, + {"SB", 0x707F, 0x23, DecodeSType<SB>}, + {"SH", 0x707F, 0x1023, DecodeSType<SH>}, + {"SW", 0x707F, 0x2023, DecodeSType<SW>}, + {"ADDI", 0x707F, 0x13, DecodeIType<ADDI>}, + {"SLTI", 0x707F, 0x2013, DecodeIType<SLTI>}, + {"SLTIU", 0x707F, 0x3013, DecodeIType<SLTIU>}, + {"XORI", 0x707F, 0x4013, DecodeIType<XORI>}, + {"ORI", 0x707F, 0x6013, DecodeIType<ORI>}, + {"ANDI", 0x707F, 0x7013, DecodeIType<ANDI>}, + {"SLLI", 0xF800707F, 0x1013, DecodeRShamtType<SLLI>}, + {"SRLI", 0xF800707F, 0x5013, DecodeRShamtType<SRLI>}, + {"SRAI", 0xF800707F, 0x40005013, DecodeRShamtType<SRAI>}, + {"ADD", 0xFE00707F, 0x33, DecodeRType<ADD>}, + {"SUB", 0xFE00707F, 0x40000033, DecodeRType<SUB>}, + {"SLL", 0xFE00707F, 0x1033, DecodeRType<SLL>}, + {"SLT", 0xFE00707F, 0x2033, DecodeRType<SLT>}, + {"SLTU", 0xFE00707F, 0x3033, DecodeRType<SLTU>}, + {"XOR", 0xFE00707F, 0x4033, DecodeRType<XOR>}, + {"SRL", 0xFE00707F, 0x5033, DecodeRType<SRL>}, + {"SRA", 0xFE00707F, 0x40005033, DecodeRType<SRA>}, + {"OR", 0xFE00707F, 0x6033, DecodeRType<OR>}, + {"AND", 0xFE00707F, 0x7033, DecodeRType<AND>}, + {"LWU", 0x707F, 0x6003, DecodeIType<LWU>}, + {"LD", 0x707F, 0x3003, DecodeIType<LD>}, + {"SD", 0x707F, 0x3023, DecodeSType<SD>}, + {"ADDIW", 0x707F, 0x1B, DecodeIType<ADDIW>}, + {"SLLIW", 0xFE00707F, 0x101B, DecodeRShamtType<SLLIW>}, + {"SRLIW", 0xFE00707F, 0x501B, DecodeRShamtType<SRLIW>}, + {"SRAIW", 0xFE00707F, 0x4000501B, DecodeRShamtType<SRAIW>}, + {"ADDW", 0xFE00707F, 0x3B, DecodeRType<ADDW>}, + {"SUBW", 0xFE00707F, 0x4000003B, DecodeRType<SUBW>}, + {"SLLW", 0xFE00707F, 0x103B, DecodeRType<SLLW>}, + {"SRLW", 0xFE00707F, 0x503B, DecodeRType<SRLW>}, + {"SRAW", 0xFE00707F, 0x4000503B, DecodeRType<SRAW>}, + + // RV32M & RV64M (The integer multiplication and division extension) // + {"MUL", 0xFE00707F, 0x2000033, DecodeRType<MUL>}, + {"MULH", 0xFE00707F, 0x2001033, DecodeRType<MULH>}, + {"MULHSU", 0xFE00707F, 0x2002033, DecodeRType<MULHSU>}, + {"MULHU", 0xFE00707F, 0x2003033, DecodeRType<MULHU>}, + {"DIV", 0xFE00707F, 0x2004033, DecodeRType<DIV>}, + {"DIVU", 0xFE00707F, 0x2005033, DecodeRType<DIVU>}, + {"REM", 0xFE00707F, 0x2006033, DecodeRType<REM>}, + {"REMU", 0xFE00707F, 0x2007033, DecodeRType<REMU>}, + {"MULW", 0xFE00707F, 0x200003B, DecodeRType<MULW>}, + {"DIVW", 0xFE00707F, 0x200403B, DecodeRType<DIVW>}, + {"DIVUW", 0xFE00707F, 0x200503B, DecodeRType<DIVUW>}, + {"REMW", 0xFE00707F, 0x200603B, DecodeRType<REMW>}, + {"REMUW", 0xFE00707F, 0x200703B, DecodeRType<REMUW>}, + + // RV32A & RV64A (The standard atomic instruction extension) // + {"LR_W", 0xF9F0707F, 0x1000202F, DecodeRRS1Type<LR_W>}, + {"LR_D", 0xF9F0707F, 0x1000302F, DecodeRRS1Type<LR_D>}, + {"SC_W", 0xF800707F, 0x1800202F, DecodeRType<SC_W>}, + {"SC_D", 0xF800707F, 0x1800302F, DecodeRType<SC_D>}, + {"AMOSWAP_W", 0xF800707F, 0x800202F, DecodeRType<AMOSWAP_W>}, + {"AMOADD_W", 0xF800707F, 0x202F, DecodeRType<AMOADD_W>}, + {"AMOXOR_W", 0xF800707F, 0x2000202F, DecodeRType<AMOXOR_W>}, + {"AMOAND_W", 0xF800707F, 0x6000202F, DecodeRType<AMOAND_W>}, + {"AMOOR_W", 0xF800707F, 0x4000202F, DecodeRType<AMOOR_W>}, + {"AMOMIN_W", 0xF800707F, 0x8000202F, DecodeRType<AMOMIN_W>}, + {"AMOMAX_W", 0xF800707F, 0xA000202F, DecodeRType<AMOMAX_W>}, + {"AMOMINU_W", 0xF800707F, 0xC000202F, DecodeRType<AMOMINU_W>}, + {"AMOMAXU_W", 0xF800707F, 0xE000202F, DecodeRType<AMOMAXU_W>}, + {"AMOSWAP_D", 0xF800707F, 0x800302F, DecodeRType<AMOSWAP_D>}, + {"AMOADD_D", 0xF800707F, 0x302F, DecodeRType<AMOADD_D>}, + {"AMOXOR_D", 0xF800707F, 0x2000302F, DecodeRType<AMOXOR_D>}, + {"AMOAND_D", 0xF800707F, 0x6000302F, DecodeRType<AMOAND_D>}, + {"AMOOR_D", 0xF800707F, 0x4000302F, DecodeRType<AMOOR_D>}, + {"AMOMIN_D", 0xF800707F, 0x8000302F, DecodeRType<AMOMIN_D>}, + {"AMOMAX_D", 0xF800707F, 0xA000302F, DecodeRType<AMOMAX_D>}, + {"AMOMINU_D", 0xF800707F, 0xC000302F, DecodeRType<AMOMINU_D>}, + {"AMOMAXU_D", 0xF800707F, 0xE000302F, DecodeRType<AMOMAXU_D>}, + + // RVC (Compressed Instructions) // + {"C_LWSP", 0xE003, 0x4002, DecodeC_LWSP}, + {"C_LDSP", 0xE003, 0x6002, DecodeC_LDSP, RV64 | RV128}, + {"C_SWSP", 0xE003, 0xC002, DecodeC_SWSP}, + {"C_SDSP", 0xE003, 0xE002, DecodeC_SDSP, RV64 | RV128}, + {"C_LW", 0xE003, 0x4000, DecodeC_LW}, + {"C_LD", 0xE003, 0x6000, DecodeC_LD, RV64 | RV128}, + {"C_SW", 0xE003, 0xC000, DecodeC_SW}, + {"C_SD", 0xE003, 0xE000, DecodeC_SD, RV64 | RV128}, + {"C_J", 0xE003, 0xA001, DecodeC_J}, + {"C_JR", 0xF07F, 0x8002, DecodeC_JR}, + {"C_JALR", 0xF07F, 0x9002, DecodeC_JALR}, + {"C_BNEZ", 0xE003, 0xE001, DecodeC_BNEZ}, + {"C_BEQZ", 0xE003, 0xC001, DecodeC_BEQZ}, + {"C_LI", 0xE003, 0x4001, DecodeC_LI}, + {"C_LUI_ADDI16SP", 0xE003, 0x6001, DecodeC_LUI_ADDI16SP}, + {"C_ADDI", 0xE003, 0x1, DecodeC_ADDI}, + {"C_ADDIW", 0xE003, 0x2001, DecodeC_ADDIW, RV64 | RV128}, + {"C_ADDI4SPN", 0xE003, 0x0, DecodeC_ADDI4SPN}, + {"C_SLLI", 0xE003, 0x2, DecodeC_SLLI, RV64 | RV128}, + {"C_SRLI", 0xEC03, 0x8001, DecodeC_SRLI, RV64 | RV128}, + {"C_SRAI", 0xEC03, 0x8401, DecodeC_SRAI, RV64 | RV128}, + {"C_ANDI", 0xEC03, 0x8801, DecodeC_ANDI}, + {"C_MV", 0xF003, 0x8002, DecodeC_MV}, + {"C_ADD", 0xF003, 0x9002, DecodeC_ADD}, + {"C_AND", 0xFC63, 0x8C61, DecodeC_AND}, + {"C_OR", 0xFC63, 0x8C41, DecodeC_OR}, + {"C_XOR", 0xFC63, 0x8C21, DecodeC_XOR}, + {"C_SUB", 0xFC63, 0x8C01, DecodeC_SUB}, + {"C_SUBW", 0xFC63, 0x9C01, DecodeC_SUBW, RV64 | RV128}, + {"C_ADDW", 0xFC63, 0x9C21, DecodeC_ADDW, RV64 | RV128}, + // RV32FC // + {"FLW", 0xE003, 0x6000, DecodeC_FLW, RV32}, + {"FSW", 0xE003, 0xE000, DecodeC_FSW, RV32}, + {"FLWSP", 0xE003, 0x6002, DecodeC_FLWSP, RV32}, + {"FSWSP", 0xE003, 0xE002, DecodeC_FSWSP, RV32}, + // RVDC // + {"FLDSP", 0xE003, 0x2002, DecodeC_FLDSP, RV32 | RV64}, + {"FSDSP", 0xE003, 0xA002, DecodeC_FSDSP, RV32 | RV64}, + {"FLD", 0xE003, 0x2000, DecodeC_FLD, RV32 | RV64}, + {"FSD", 0xE003, 0xA000, DecodeC_FSD, RV32 | RV64}, + + // RV32F (Extension for Single-Precision Floating-Point) // + {"FLW", 0x707F, 0x2007, DecodeIType<FLW>}, + {"FSW", 0x707F, 0x2027, DecodeSType<FSW>}, + {"FMADD_S", 0x600007F, 0x43, DecodeR4Type<FMADD_S>}, + {"FMSUB_S", 0x600007F, 0x47, DecodeR4Type<FMSUB_S>}, + {"FNMSUB_S", 0x600007F, 0x4B, DecodeR4Type<FNMSUB_S>}, + {"FNMADD_S", 0x600007F, 0x4F, DecodeR4Type<FNMADD_S>}, + {"FADD_S", 0xFE00007F, 0x53, DecodeRType<FADD_S>}, + {"FSUB_S", 0xFE00007F, 0x8000053, DecodeRType<FSUB_S>}, + {"FMUL_S", 0xFE00007F, 0x10000053, DecodeRType<FMUL_S>}, + {"FDIV_S", 0xFE00007F, 0x18000053, DecodeRType<FDIV_S>}, + {"FSQRT_S", 0xFFF0007F, 0x58000053, DecodeIType<FSQRT_S>}, + {"FSGNJ_S", 0xFE00707F, 0x20000053, DecodeRType<FSGNJ_S>}, + {"FSGNJN_S", 0xFE00707F, 0x20001053, DecodeRType<FSGNJN_S>}, + {"FSGNJX_S", 0xFE00707F, 0x20002053, DecodeRType<FSGNJX_S>}, + {"FMIN_S", 0xFE00707F, 0x28000053, DecodeRType<FMIN_S>}, + {"FMAX_S", 0xFE00707F, 0x28001053, DecodeRType<FMAX_S>}, + {"FCVT_W_S", 0xFFF0007F, 0xC0000053, DecodeIType<FCVT_W_S>}, + {"FCVT_WU_S", 0xFFF0007F, 0xC0100053, DecodeIType<FCVT_WU_S>}, + {"FMV_X_W", 0xFFF0707F, 0xE0000053, DecodeIType<FMV_X_W>}, + {"FEQ_S", 0xFE00707F, 0xA0002053, DecodeRType<FEQ_S>}, + {"FLT_S", 0xFE00707F, 0xA0001053, DecodeRType<FLT_S>}, + {"FLE_S", 0xFE00707F, 0xA0000053, DecodeRType<FLE_S>}, + {"FCLASS_S", 0xFFF0707F, 0xE0001053, DecodeIType<FCLASS_S>}, + {"FCVT_S_W", 0xFFF0007F, 0xD0000053, DecodeIType<FCVT_S_W>}, + {"FCVT_S_WU", 0xFFF0007F, 0xD0100053, DecodeIType<FCVT_S_WU>}, + {"FMV_W_X", 0xFFF0707F, 0xF0000053, DecodeIType<FMV_W_X>}, + + // RV64F (Extension for Single-Precision Floating-Point) // + {"FCVT_L_S", 0xFFF0007F, 0xC0200053, DecodeIType<FCVT_L_S>}, + {"FCVT_LU_S", 0xFFF0007F, 0xC0300053, DecodeIType<FCVT_LU_S>}, + {"FCVT_S_L", 0xFFF0007F, 0xD0200053, DecodeIType<FCVT_S_L>}, + {"FCVT_S_LU", 0xFFF0007F, 0xD0300053, DecodeIType<FCVT_S_LU>}, + + // RV32D (Extension for Double-Precision Floating-Point) // + {"FLD", 0x707F, 0x3007, DecodeIType<FLD>}, + {"FSD", 0x707F, 0x3027, DecodeSType<FSD>}, + {"FMADD_D", 0x600007F, 0x2000043, DecodeR4Type<FMADD_D>}, + {"FMSUB_D", 0x600007F, 0x2000047, DecodeR4Type<FMSUB_D>}, + {"FNMSUB_D", 0x600007F, 0x200004B, DecodeR4Type<FNMSUB_D>}, + {"FNMADD_D", 0x600007F, 0x200004F, DecodeR4Type<FNMADD_D>}, + {"FADD_D", 0xFE00007F, 0x2000053, DecodeRType<FADD_D>}, + {"FSUB_D", 0xFE00007F, 0xA000053, DecodeRType<FSUB_D>}, + {"FMUL_D", 0xFE00007F, 0x12000053, DecodeRType<FMUL_D>}, + {"FDIV_D", 0xFE00007F, 0x1A000053, DecodeRType<FDIV_D>}, + {"FSQRT_D", 0xFFF0007F, 0x5A000053, DecodeIType<FSQRT_D>}, + {"FSGNJ_D", 0xFE00707F, 0x22000053, DecodeRType<FSGNJ_D>}, + {"FSGNJN_D", 0xFE00707F, 0x22001053, DecodeRType<FSGNJN_D>}, + {"FSGNJX_D", 0xFE00707F, 0x22002053, DecodeRType<FSGNJX_D>}, + {"FMIN_D", 0xFE00707F, 0x2A000053, DecodeRType<FMIN_D>}, + {"FMAX_D", 0xFE00707F, 0x2A001053, DecodeRType<FMAX_D>}, + {"FCVT_S_D", 0xFFF0007F, 0x40100053, DecodeIType<FCVT_S_D>}, + {"FCVT_D_S", 0xFFF0007F, 0x42000053, DecodeIType<FCVT_D_S>}, + {"FEQ_D", 0xFE00707F, 0xA2002053, DecodeRType<FEQ_D>}, + {"FLT_D", 0xFE00707F, 0xA2001053, DecodeRType<FLT_D>}, + {"FLE_D", 0xFE00707F, 0xA2000053, DecodeRType<FLE_D>}, + {"FCLASS_D", 0xFFF0707F, 0xE2001053, DecodeIType<FCLASS_D>}, + {"FCVT_W_D", 0xFFF0007F, 0xC2000053, DecodeIType<FCVT_W_D>}, + {"FCVT_WU_D", 0xFFF0007F, 0xC2100053, DecodeIType<FCVT_WU_D>}, + {"FCVT_D_W", 0xFFF0007F, 0xD2000053, DecodeIType<FCVT_D_W>}, + {"FCVT_D_WU", 0xFFF0007F, 0xD2100053, DecodeIType<FCVT_D_WU>}, + + // RV64D (Extension for Double-Precision Floating-Point) // + {"FCVT_L_D", 0xFFF0007F, 0xC2200053, DecodeIType<FCVT_L_D>}, + {"FCVT_LU_D", 0xFFF0007F, 0xC2300053, DecodeIType<FCVT_LU_D>}, + {"FMV_X_D", 0xFFF0707F, 0xE2000053, DecodeIType<FMV_X_D>}, + {"FCVT_D_L", 0xFFF0007F, 0xD2200053, DecodeIType<FCVT_D_L>}, + {"FCVT_D_LU", 0xFFF0007F, 0xD2300053, DecodeIType<FCVT_D_LU>}, + {"FMV_D_X", 0xFFF0707F, 0xF2000053, DecodeIType<FMV_D_X>}, +}; + +std::optional<DecodeResult> EmulateInstructionRISCV::Decode(uint32_t inst) { + Log *log = GetLog(LLDBLog::Unwind); + + uint16_t try_rvc = uint16_t(inst & 0x0000ffff); + // check whether the compressed encode could be valid + uint16_t mask = try_rvc & 0b11; + bool is_rvc = try_rvc != 0 && mask != 3; + uint8_t inst_type = RV64; + + // if we have ArchSpec::eCore_riscv128 in the future, + // we also need to check it here + if (m_arch.GetCore() == ArchSpec::eCore_riscv32) + inst_type = RV32; + + for (const InstrPattern &pat : PATTERNS) { + if ((inst & pat.type_mask) == pat.eigen && + (inst_type & pat.inst_type) != 0) { + LLDB_LOGF( + log, "EmulateInstructionRISCV::%s: inst(%x at %lx) was decoded to %s", + __FUNCTION__, inst, m_addr, pat.name); + auto decoded = is_rvc ? pat.decode(try_rvc) : pat.decode(inst); + return DecodeResult{decoded, inst, is_rvc, pat}; + } + } + LLDB_LOGF(log, "EmulateInstructionRISCV::%s: inst(0x%x) was unsupported", + __FUNCTION__, inst); + return std::nullopt; +} + +class Executor { + EmulateInstructionRISCV &m_emu; + bool m_ignore_cond; + bool m_is_rvc; + +public: + // also used in EvaluateInstruction() + static uint64_t size(bool is_rvc) { return is_rvc ? 2 : 4; } + +private: + uint64_t delta() { return size(m_is_rvc); } + +public: + Executor(EmulateInstructionRISCV &emulator, bool ignoreCond, bool is_rvc) + : m_emu(emulator), m_ignore_cond(ignoreCond), m_is_rvc(is_rvc) {} + + bool operator()(LUI inst) { return inst.rd.Write(m_emu, SignExt(inst.imm)); } + bool operator()(AUIPC inst) { + return transformOptional(m_emu.ReadPC(), + [&](uint64_t pc) { + return inst.rd.Write(m_emu, + SignExt(inst.imm) + pc); + }) + .value_or(false); + } + bool operator()(JAL inst) { + return transformOptional(m_emu.ReadPC(), + [&](uint64_t pc) { + return inst.rd.Write(m_emu, pc + delta()) && + m_emu.WritePC(SignExt(inst.imm) + pc); + }) + .value_or(false); + } + bool operator()(JALR inst) { + return transformOptional(zipOpt(m_emu.ReadPC(), inst.rs1.Read(m_emu)), + [&](auto &&tup) { + auto [pc, rs1] = tup; + return inst.rd.Write(m_emu, pc + delta()) && + m_emu.WritePC((SignExt(inst.imm) + rs1) & + ~1); + }) + .value_or(false); + } + bool operator()(B inst) { + return transformOptional(zipOpt(m_emu.ReadPC(), inst.rs1.Read(m_emu), + inst.rs2.Read(m_emu)), + [&](auto &&tup) { + auto [pc, rs1, rs2] = tup; + if (m_ignore_cond || + CompareB(rs1, rs2, inst.funct3)) + return m_emu.WritePC(SignExt(inst.imm) + pc); + return true; + }) + .value_or(false); + } + bool operator()(LB inst) { + return Load<LB, uint8_t, int8_t>(m_emu, inst, SextW); + } + bool operator()(LH inst) { + return Load<LH, uint16_t, int16_t>(m_emu, inst, SextW); + } + bool operator()(LW inst) { + return Load<LW, uint32_t, int32_t>(m_emu, inst, SextW); + } + bool operator()(LBU inst) { + return Load<LBU, uint8_t, uint8_t>(m_emu, inst, ZextD); + } + bool operator()(LHU inst) { + return Load<LHU, uint16_t, uint16_t>(m_emu, inst, ZextD); + } + bool operator()(SB inst) { return Store<SB, uint8_t>(m_emu, inst); } + bool operator()(SH inst) { return Store<SH, uint16_t>(m_emu, inst); } + bool operator()(SW inst) { return Store<SW, uint32_t>(m_emu, inst); } + bool operator()(ADDI inst) { + return transformOptional(inst.rs1.ReadI64(m_emu), + [&](int64_t rs1) { + return inst.rd.Write( + m_emu, rs1 + int64_t(SignExt(inst.imm))); + }) + .value_or(false); + } + bool operator()(SLTI inst) { + return transformOptional(inst.rs1.ReadI64(m_emu), + [&](int64_t rs1) { + return inst.rd.Write( + m_emu, rs1 < int64_t(SignExt(inst.imm))); + }) + .value_or(false); + } + bool operator()(SLTIU inst) { + return transformOptional(inst.rs1.Read(m_emu), + [&](uint64_t rs1) { + return inst.rd.Write( + m_emu, rs1 < uint64_t(SignExt(inst.imm))); + }) + .value_or(false); + } + bool operator()(XORI inst) { + return transformOptional(inst.rs1.Read(m_emu), + [&](uint64_t rs1) { + return inst.rd.Write( + m_emu, rs1 ^ uint64_t(SignExt(inst.imm))); + }) + .value_or(false); + } + bool operator()(ORI inst) { + return transformOptional(inst.rs1.Read(m_emu), + [&](uint64_t rs1) { + return inst.rd.Write( + m_emu, rs1 | uint64_t(SignExt(inst.imm))); + }) + .value_or(false); + } + bool operator()(ANDI inst) { + return transformOptional(inst.rs1.Read(m_emu), + [&](uint64_t rs1) { + return inst.rd.Write( + m_emu, rs1 & uint64_t(SignExt(inst.imm))); + }) + .value_or(false); + } + bool operator()(ADD inst) { + return transformOptional(zipOpt(inst.rs1.Read(m_emu), inst.rs2.Read(m_emu)), + [&](auto &&tup) { + auto [rs1, rs2] = tup; + return inst.rd.Write(m_emu, rs1 + rs2); + }) + .value_or(false); + } + bool operator()(SUB inst) { + return transformOptional(zipOpt(inst.rs1.Read(m_emu), inst.rs2.Read(m_emu)), + [&](auto &&tup) { + auto [rs1, rs2] = tup; + return inst.rd.Write(m_emu, rs1 - rs2); + }) + .value_or(false); + } + bool operator()(SLL inst) { + return transformOptional(zipOpt(inst.rs1.Read(m_emu), inst.rs2.Read(m_emu)), + [&](auto &&tup) { + auto [rs1, rs2] = tup; + return inst.rd.Write(m_emu, + rs1 << (rs2 & 0b111111)); + }) + .value_or(false); + } + bool operator()(SLT inst) { + return transformOptional( + zipOpt(inst.rs1.ReadI64(m_emu), inst.rs2.ReadI64(m_emu)), + [&](auto &&tup) { + auto [rs1, rs2] = tup; + return inst.rd.Write(m_emu, rs1 < rs2); + }) + .value_or(false); + } + bool operator()(SLTU inst) { + return transformOptional(zipOpt(inst.rs1.Read(m_emu), inst.rs2.Read(m_emu)), + [&](auto &&tup) { + auto [rs1, rs2] = tup; + return inst.rd.Write(m_emu, rs1 < rs2); + }) + .value_or(false); + } + bool operator()(XOR inst) { + return transformOptional(zipOpt(inst.rs1.Read(m_emu), inst.rs2.Read(m_emu)), + [&](auto &&tup) { + auto [rs1, rs2] = tup; + return inst.rd.Write(m_emu, rs1 ^ rs2); + }) + .value_or(false); + } + bool operator()(SRL inst) { + return transformOptional(zipOpt(inst.rs1.Read(m_emu), inst.rs2.Read(m_emu)), + [&](auto &&tup) { + auto [rs1, rs2] = tup; + return inst.rd.Write(m_emu, + rs1 >> (rs2 & 0b111111)); + }) + .value_or(false); + } + bool operator()(SRA inst) { + return transformOptional( + zipOpt(inst.rs1.ReadI64(m_emu), inst.rs2.Read(m_emu)), + [&](auto &&tup) { + auto [rs1, rs2] = tup; + return inst.rd.Write(m_emu, rs1 >> (rs2 & 0b111111)); + }) + .value_or(false); + } + bool operator()(OR inst) { + return transformOptional(zipOpt(inst.rs1.Read(m_emu), inst.rs2.Read(m_emu)), + [&](auto &&tup) { + auto [rs1, rs2] = tup; + return inst.rd.Write(m_emu, rs1 | rs2); + }) + .value_or(false); + } + bool operator()(AND inst) { + return transformOptional(zipOpt(inst.rs1.Read(m_emu), inst.rs2.Read(m_emu)), + [&](auto &&tup) { + auto [rs1, rs2] = tup; + return inst.rd.Write(m_emu, rs1 & rs2); + }) + .value_or(false); + } + bool operator()(LWU inst) { + return Load<LWU, uint32_t, uint32_t>(m_emu, inst, ZextD); + } + bool operator()(LD inst) { + return Load<LD, uint64_t, uint64_t>(m_emu, inst, ZextD); + } + bool operator()(SD inst) { return Store<SD, uint64_t>(m_emu, inst); } + bool operator()(SLLI inst) { + return transformOptional(inst.rs1.Read(m_emu), + [&](uint64_t rs1) { + return inst.rd.Write(m_emu, rs1 << inst.shamt); + }) + .value_or(false); + } + bool operator()(SRLI inst) { + return transformOptional(inst.rs1.Read(m_emu), + [&](uint64_t rs1) { + return inst.rd.Write(m_emu, rs1 >> inst.shamt); + }) + .value_or(false); + } + bool operator()(SRAI inst) { + return transformOptional(inst.rs1.ReadI64(m_emu), + [&](int64_t rs1) { + return inst.rd.Write(m_emu, rs1 >> inst.shamt); + }) + .value_or(false); + } + bool operator()(ADDIW inst) { + return transformOptional(inst.rs1.ReadI32(m_emu), + [&](int32_t rs1) { + return inst.rd.Write( + m_emu, SextW(rs1 + SignExt(inst.imm))); + }) + .value_or(false); + } + bool operator()(SLLIW inst) { + return transformOptional(inst.rs1.ReadU32(m_emu), + [&](uint32_t rs1) { + return inst.rd.Write(m_emu, + SextW(rs1 << inst.shamt)); + }) + .value_or(false); + } + bool operator()(SRLIW inst) { + return transformOptional(inst.rs1.ReadU32(m_emu), + [&](uint32_t rs1) { + return inst.rd.Write(m_emu, + SextW(rs1 >> inst.shamt)); + }) + .value_or(false); + } + bool operator()(SRAIW inst) { + return transformOptional(inst.rs1.ReadI32(m_emu), + [&](int32_t rs1) { + return inst.rd.Write(m_emu, + SextW(rs1 >> inst.shamt)); + }) + .value_or(false); + } + bool operator()(ADDW inst) { + return transformOptional(zipOpt(inst.rs1.Read(m_emu), inst.rs2.Read(m_emu)), + [&](auto &&tup) { + auto [rs1, rs2] = tup; + return inst.rd.Write(m_emu, + SextW(uint32_t(rs1 + rs2))); + }) + .value_or(false); + } + bool operator()(SUBW inst) { + return transformOptional(zipOpt(inst.rs1.Read(m_emu), inst.rs2.Read(m_emu)), + [&](auto &&tup) { + auto [rs1, rs2] = tup; + return inst.rd.Write(m_emu, + SextW(uint32_t(rs1 - rs2))); + }) + .value_or(false); + } + bool operator()(SLLW inst) { + return transformOptional( + zipOpt(inst.rs1.ReadU32(m_emu), inst.rs2.ReadU32(m_emu)), + [&](auto &&tup) { + auto [rs1, rs2] = tup; + return inst.rd.Write(m_emu, SextW(rs1 << (rs2 & 0b11111))); + }) + .value_or(false); + } + bool operator()(SRLW inst) { + return transformOptional( + zipOpt(inst.rs1.ReadU32(m_emu), inst.rs2.ReadU32(m_emu)), + [&](auto &&tup) { + auto [rs1, rs2] = tup; + return inst.rd.Write(m_emu, SextW(rs1 >> (rs2 & 0b11111))); + }) + .value_or(false); + } + bool operator()(SRAW inst) { + return transformOptional( + zipOpt(inst.rs1.ReadI32(m_emu), inst.rs2.Read(m_emu)), + [&](auto &&tup) { + auto [rs1, rs2] = tup; + return inst.rd.Write(m_emu, SextW(rs1 >> (rs2 & 0b11111))); + }) + .value_or(false); + } + // RV32M & RV64M (Integer Multiplication and Division Extension) // + bool operator()(MUL inst) { + return transformOptional(zipOpt(inst.rs1.Read(m_emu), inst.rs2.Read(m_emu)), + [&](auto &&tup) { + auto [rs1, rs2] = tup; + return inst.rd.Write(m_emu, rs1 * rs2); + }) + .value_or(false); + } + bool operator()(MULH inst) { + return transformOptional( + zipOpt(inst.rs1.Read(m_emu), inst.rs2.Read(m_emu)), + [&](auto &&tup) { + auto [rs1, rs2] = tup; + // signed * signed + auto mul = APInt(128, rs1, true) * APInt(128, rs2, true); + return inst.rd.Write(m_emu, + mul.ashr(64).trunc(64).getZExtValue()); + }) + .value_or(false); + } + bool operator()(MULHSU inst) { + return transformOptional( + zipOpt(inst.rs1.Read(m_emu), inst.rs2.Read(m_emu)), + [&](auto &&tup) { + auto [rs1, rs2] = tup; + // signed * unsigned + auto mul = + APInt(128, rs1, true).zext(128) * APInt(128, rs2, false); + return inst.rd.Write(m_emu, + mul.lshr(64).trunc(64).getZExtValue()); + }) + .value_or(false); + } + bool operator()(MULHU inst) { + return transformOptional( + zipOpt(inst.rs1.Read(m_emu), inst.rs2.Read(m_emu)), + [&](auto &&tup) { + auto [rs1, rs2] = tup; + // unsigned * unsigned + auto mul = APInt(128, rs1, false) * APInt(128, rs2, false); + return inst.rd.Write(m_emu, + mul.lshr(64).trunc(64).getZExtValue()); + }) + .value_or(false); + } + bool operator()(DIV inst) { + return transformOptional( + zipOpt(inst.rs1.ReadI64(m_emu), inst.rs2.ReadI64(m_emu)), + [&](auto &&tup) { + auto [dividend, divisor] = tup; + + if (divisor == 0) + return inst.rd.Write(m_emu, UINT64_MAX); + + if (dividend == INT64_MIN && divisor == -1) + return inst.rd.Write(m_emu, dividend); + + return inst.rd.Write(m_emu, dividend / divisor); + }) + .value_or(false); + } + bool operator()(DIVU inst) { + return transformOptional(zipOpt(inst.rs1.Read(m_emu), inst.rs2.Read(m_emu)), + [&](auto &&tup) { + auto [dividend, divisor] = tup; + + if (divisor == 0) + return inst.rd.Write(m_emu, UINT64_MAX); + + return inst.rd.Write(m_emu, dividend / divisor); + }) + .value_or(false); + } + bool operator()(REM inst) { + return transformOptional( + zipOpt(inst.rs1.ReadI64(m_emu), inst.rs2.ReadI64(m_emu)), + [&](auto &&tup) { + auto [dividend, divisor] = tup; + + if (divisor == 0) + return inst.rd.Write(m_emu, dividend); + + if (dividend == INT64_MIN && divisor == -1) + return inst.rd.Write(m_emu, 0); + + return inst.rd.Write(m_emu, dividend % divisor); + }) + .value_or(false); + } + bool operator()(REMU inst) { + return transformOptional(zipOpt(inst.rs1.Read(m_emu), inst.rs2.Read(m_emu)), + [&](auto &&tup) { + auto [dividend, divisor] = tup; + + if (divisor == 0) + return inst.rd.Write(m_emu, dividend); + + return inst.rd.Write(m_emu, dividend % divisor); + }) + .value_or(false); + } + bool operator()(MULW inst) { + return transformOptional( + zipOpt(inst.rs1.ReadI32(m_emu), inst.rs2.ReadI32(m_emu)), + [&](auto &&tup) { + auto [rs1, rs2] = tup; + return inst.rd.Write(m_emu, SextW(rs1 * rs2)); + }) + .value_or(false); + } + bool operator()(DIVW inst) { + return transformOptional( + zipOpt(inst.rs1.ReadI32(m_emu), inst.rs2.ReadI32(m_emu)), + [&](auto &&tup) { + auto [dividend, divisor] = tup; + + if (divisor == 0) + return inst.rd.Write(m_emu, UINT64_MAX); + + if (dividend == INT32_MIN && divisor == -1) + return inst.rd.Write(m_emu, SextW(dividend)); + + return inst.rd.Write(m_emu, SextW(dividend / divisor)); + }) + .value_or(false); + } + bool operator()(DIVUW inst) { + return transformOptional( + zipOpt(inst.rs1.ReadU32(m_emu), inst.rs2.ReadU32(m_emu)), + [&](auto &&tup) { + auto [dividend, divisor] = tup; + + if (divisor == 0) + return inst.rd.Write(m_emu, UINT64_MAX); + + return inst.rd.Write(m_emu, SextW(dividend / divisor)); + }) + .value_or(false); + } + bool operator()(REMW inst) { + return transformOptional( + zipOpt(inst.rs1.ReadI32(m_emu), inst.rs2.ReadI32(m_emu)), + [&](auto &&tup) { + auto [dividend, divisor] = tup; + + if (divisor == 0) + return inst.rd.Write(m_emu, SextW(dividend)); + + if (dividend == INT32_MIN && divisor == -1) + return inst.rd.Write(m_emu, 0); + + return inst.rd.Write(m_emu, SextW(dividend % divisor)); + }) + .value_or(false); + } + bool operator()(REMUW inst) { + return transformOptional( + zipOpt(inst.rs1.ReadU32(m_emu), inst.rs2.ReadU32(m_emu)), + [&](auto &&tup) { + auto [dividend, divisor] = tup; + + if (divisor == 0) + return inst.rd.Write(m_emu, SextW(dividend)); + + return inst.rd.Write(m_emu, SextW(dividend % divisor)); + }) + .value_or(false); + } + // RV32A & RV64A (The standard atomic instruction extension) // + bool operator()(LR_W) { return AtomicSequence(m_emu); } + bool operator()(LR_D) { return AtomicSequence(m_emu); } + bool operator()(SC_W) { + llvm_unreachable("should be handled in AtomicSequence"); + } + bool operator()(SC_D) { + llvm_unreachable("should be handled in AtomicSequence"); + } + bool operator()(AMOSWAP_W inst) { + return AtomicSwap<AMOSWAP_W, uint32_t>(m_emu, inst, 4, SextW); + } + bool operator()(AMOADD_W inst) { + return AtomicADD<AMOADD_W, uint32_t>(m_emu, inst, 4, SextW); + } + bool operator()(AMOXOR_W inst) { + return AtomicBitOperate<AMOXOR_W, uint32_t>( + m_emu, inst, 4, SextW, [](uint32_t a, uint32_t b) { return a ^ b; }); + } + bool operator()(AMOAND_W inst) { + return AtomicBitOperate<AMOAND_W, uint32_t>( + m_emu, inst, 4, SextW, [](uint32_t a, uint32_t b) { return a & b; }); + } + bool operator()(AMOOR_W inst) { + return AtomicBitOperate<AMOOR_W, uint32_t>( + m_emu, inst, 4, SextW, [](uint32_t a, uint32_t b) { return a | b; }); + } + bool operator()(AMOMIN_W inst) { + return AtomicCmp<AMOMIN_W, uint32_t>( + m_emu, inst, 4, SextW, [](uint32_t a, uint32_t b) { + return uint32_t(std::min(int32_t(a), int32_t(b))); + }); + } + bool operator()(AMOMAX_W inst) { + return AtomicCmp<AMOMAX_W, uint32_t>( + m_emu, inst, 4, SextW, [](uint32_t a, uint32_t b) { + return uint32_t(std::max(int32_t(a), int32_t(b))); + }); + } + bool operator()(AMOMINU_W inst) { + return AtomicCmp<AMOMINU_W, uint32_t>( + m_emu, inst, 4, SextW, + [](uint32_t a, uint32_t b) { return std::min(a, b); }); + } + bool operator()(AMOMAXU_W inst) { + return AtomicCmp<AMOMAXU_W, uint32_t>( + m_emu, inst, 4, SextW, + [](uint32_t a, uint32_t b) { return std::max(a, b); }); + } + bool operator()(AMOSWAP_D inst) { + return AtomicSwap<AMOSWAP_D, uint64_t>(m_emu, inst, 8, ZextD); + } + bool operator()(AMOADD_D inst) { + return AtomicADD<AMOADD_D, uint64_t>(m_emu, inst, 8, ZextD); + } + bool operator()(AMOXOR_D inst) { + return AtomicBitOperate<AMOXOR_D, uint64_t>( + m_emu, inst, 8, ZextD, [](uint64_t a, uint64_t b) { return a ^ b; }); + } + bool operator()(AMOAND_D inst) { + return AtomicBitOperate<AMOAND_D, uint64_t>( + m_emu, inst, 8, ZextD, [](uint64_t a, uint64_t b) { return a & b; }); + } + bool operator()(AMOOR_D inst) { + return AtomicBitOperate<AMOOR_D, uint64_t>( + m_emu, inst, 8, ZextD, [](uint64_t a, uint64_t b) { return a | b; }); + } + bool operator()(AMOMIN_D inst) { + return AtomicCmp<AMOMIN_D, uint64_t>( + m_emu, inst, 8, ZextD, [](uint64_t a, uint64_t b) { + return uint64_t(std::min(int64_t(a), int64_t(b))); + }); + } + bool operator()(AMOMAX_D inst) { + return AtomicCmp<AMOMAX_D, uint64_t>( + m_emu, inst, 8, ZextD, [](uint64_t a, uint64_t b) { + return uint64_t(std::max(int64_t(a), int64_t(b))); + }); + } + bool operator()(AMOMINU_D inst) { + return AtomicCmp<AMOMINU_D, uint64_t>( + m_emu, inst, 8, ZextD, + [](uint64_t a, uint64_t b) { return std::min(a, b); }); + } + bool operator()(AMOMAXU_D inst) { + return AtomicCmp<AMOMAXU_D, uint64_t>( + m_emu, inst, 8, ZextD, + [](uint64_t a, uint64_t b) { return std::max(a, b); }); + } + template <typename T> + bool F_Load(T inst, const fltSemantics &(*semantics)(), + unsigned int numBits) { + return transformOptional(inst.rs1.Read(m_emu), + [&](auto &&rs1) { + uint64_t addr = rs1 + uint64_t(inst.imm); + uint64_t bits = *m_emu.ReadMem<uint64_t>(addr); + APFloat f(semantics(), APInt(numBits, bits)); + return inst.rd.WriteAPFloat(m_emu, f); + }) + .value_or(false); + } + bool operator()(FLW inst) { return F_Load(inst, &APFloat::IEEEsingle, 32); } + template <typename T> bool F_Store(T inst, bool isDouble) { + return transformOptional(zipOpt(inst.rs1.Read(m_emu), + inst.rs2.ReadAPFloat(m_emu, isDouble)), + [&](auto &&tup) { + auto [rs1, rs2] = tup; + uint64_t addr = rs1 + uint64_t(inst.imm); + uint64_t bits = + rs2.bitcastToAPInt().getZExtValue(); + return m_emu.WriteMem<uint64_t>(addr, bits); + }) + .value_or(false); + } + bool operator()(FSW inst) { return F_Store(inst, false); } + std::tuple<bool, APFloat> FusedMultiplyAdd(APFloat rs1, APFloat rs2, + APFloat rs3) { + auto opStatus = rs1.fusedMultiplyAdd(rs2, rs3, m_emu.GetRoundingMode()); + auto res = m_emu.SetAccruedExceptions(opStatus); + return {res, rs1}; + } + template <typename T> + bool FMA(T inst, bool isDouble, float rs2_sign, float rs3_sign) { + return transformOptional(zipOpt(inst.rs1.ReadAPFloat(m_emu, isDouble), + inst.rs2.ReadAPFloat(m_emu, isDouble), + inst.rs3.ReadAPFloat(m_emu, isDouble)), + [&](auto &&tup) { + auto [rs1, rs2, rs3] = tup; + rs2.copySign(APFloat(rs2_sign)); + rs3.copySign(APFloat(rs3_sign)); + auto [res, f] = FusedMultiplyAdd(rs1, rs2, rs3); + return res && inst.rd.WriteAPFloat(m_emu, f); + }) + .value_or(false); + } + bool operator()(FMADD_S inst) { return FMA(inst, false, 1.0f, 1.0f); } + bool operator()(FMSUB_S inst) { return FMA(inst, false, 1.0f, -1.0f); } + bool operator()(FNMSUB_S inst) { return FMA(inst, false, -1.0f, 1.0f); } + bool operator()(FNMADD_S inst) { return FMA(inst, false, -1.0f, -1.0f); } + template <typename T> + bool F_Op(T inst, bool isDouble, + APFloat::opStatus (APFloat::*f)(const APFloat &RHS, + APFloat::roundingMode RM)) { + return transformOptional(zipOpt(inst.rs1.ReadAPFloat(m_emu, isDouble), + inst.rs2.ReadAPFloat(m_emu, isDouble)), + [&](auto &&tup) { + auto [rs1, rs2] = tup; + auto res = + ((&rs1)->*f)(rs2, m_emu.GetRoundingMode()); + inst.rd.WriteAPFloat(m_emu, rs1); + return m_emu.SetAccruedExceptions(res); + }) + .value_or(false); + } + bool operator()(FADD_S inst) { return F_Op(inst, false, &APFloat::add); } + bool operator()(FSUB_S inst) { return F_Op(inst, false, &APFloat::subtract); } + bool operator()(FMUL_S inst) { return F_Op(inst, false, &APFloat::multiply); } + bool operator()(FDIV_S inst) { return F_Op(inst, false, &APFloat::divide); } + bool operator()(FSQRT_S inst) { + // TODO: APFloat doesn't have a sqrt function. + return false; + } + template <typename T> bool F_SignInj(T inst, bool isDouble, bool isNegate) { + return transformOptional(zipOpt(inst.rs1.ReadAPFloat(m_emu, isDouble), + inst.rs2.ReadAPFloat(m_emu, isDouble)), + [&](auto &&tup) { + auto [rs1, rs2] = tup; + if (isNegate) + rs2.changeSign(); + rs1.copySign(rs2); + return inst.rd.WriteAPFloat(m_emu, rs1); + }) + .value_or(false); + } + bool operator()(FSGNJ_S inst) { return F_SignInj(inst, false, false); } + bool operator()(FSGNJN_S inst) { return F_SignInj(inst, false, true); } + template <typename T> bool F_SignInjXor(T inst, bool isDouble) { + return transformOptional(zipOpt(inst.rs1.ReadAPFloat(m_emu, isDouble), + inst.rs2.ReadAPFloat(m_emu, isDouble)), + [&](auto &&tup) { + auto [rs1, rs2] = tup; + // spec: the sign bit is the XOR of the sign bits + // of rs1 and rs2. if rs1 and rs2 have the same + // signs set rs1 to positive else set rs1 to + // negative + if (rs1.isNegative() == rs2.isNegative()) { + rs1.clearSign(); + } else { + rs1.clearSign(); + rs1.changeSign(); + } + return inst.rd.WriteAPFloat(m_emu, rs1); + }) + .value_or(false); + } + bool operator()(FSGNJX_S inst) { return F_SignInjXor(inst, false); } + template <typename T> + bool F_MAX_MIN(T inst, bool isDouble, + APFloat (*f)(const APFloat &A, const APFloat &B)) { + return transformOptional( + zipOpt(inst.rs1.ReadAPFloat(m_emu, isDouble), + inst.rs2.ReadAPFloat(m_emu, isDouble)), + [&](auto &&tup) { + auto [rs1, rs2] = tup; + // If both inputs are NaNs, the result is the canonical NaN. + // If only one operand is a NaN, the result is the non-NaN + // operand. Signaling NaN inputs set the invalid operation + // exception flag, even when the result is not NaN. + if (rs1.isNaN() || rs2.isNaN()) + m_emu.SetAccruedExceptions(APFloat::opInvalidOp); + if (rs1.isNaN() && rs2.isNaN()) { + auto canonicalNaN = APFloat::getQNaN(rs1.getSemantics()); + return inst.rd.WriteAPFloat(m_emu, canonicalNaN); + } + return inst.rd.WriteAPFloat(m_emu, f(rs1, rs2)); + }) + .value_or(false); + } + bool operator()(FMIN_S inst) { return F_MAX_MIN(inst, false, minnum); } + bool operator()(FMAX_S inst) { return F_MAX_MIN(inst, false, maxnum); } + bool operator()(FCVT_W_S inst) { + return FCVT_i2f<FCVT_W_S, int32_t, float>(inst, false, + &APFloat::convertToFloat); + } + bool operator()(FCVT_WU_S inst) { + return FCVT_i2f<FCVT_WU_S, uint32_t, float>(inst, false, + &APFloat::convertToFloat); + } + template <typename T> bool FMV_f2i(T inst, bool isDouble) { + return transformOptional( + inst.rs1.ReadAPFloat(m_emu, isDouble), + [&](auto &&rs1) { + if (rs1.isNaN()) { + if (isDouble) + return inst.rd.Write(m_emu, 0x7ff8'0000'0000'0000); + else + return inst.rd.Write(m_emu, 0x7fc0'0000); + } + auto bits = rs1.bitcastToAPInt().getZExtValue(); + if (isDouble) + return inst.rd.Write(m_emu, bits); + else + return inst.rd.Write(m_emu, uint64_t(bits & 0xffff'ffff)); + }) + .value_or(false); + } + bool operator()(FMV_X_W inst) { return FMV_f2i(inst, false); } + enum F_CMP { + FEQ, + FLT, + FLE, + }; + template <typename T> bool F_Compare(T inst, bool isDouble, F_CMP cmp) { + return transformOptional( + zipOpt(inst.rs1.ReadAPFloat(m_emu, isDouble), + inst.rs2.ReadAPFloat(m_emu, isDouble)), + [&](auto &&tup) { + auto [rs1, rs2] = tup; + if (rs1.isNaN() || rs2.isNaN()) { + if (cmp == FEQ) { + if (rs1.isSignaling() || rs2.isSignaling()) { + auto res = + m_emu.SetAccruedExceptions(APFloat::opInvalidOp); + return res && inst.rd.Write(m_emu, 0); + } + } + auto res = m_emu.SetAccruedExceptions(APFloat::opInvalidOp); + return res && inst.rd.Write(m_emu, 0); + } + switch (cmp) { + case FEQ: + return inst.rd.Write(m_emu, + rs1.compare(rs2) == APFloat::cmpEqual); + case FLT: + return inst.rd.Write(m_emu, rs1.compare(rs2) == + APFloat::cmpLessThan); + case FLE: + return inst.rd.Write(m_emu, rs1.compare(rs2) != + APFloat::cmpGreaterThan); + } + llvm_unreachable("unsupported F_CMP"); + }) + .value_or(false); + } + + bool operator()(FEQ_S inst) { return F_Compare(inst, false, FEQ); } + bool operator()(FLT_S inst) { return F_Compare(inst, false, FLT); } + bool operator()(FLE_S inst) { return F_Compare(inst, false, FLE); } + template <typename T> bool FCLASS(T inst, bool isDouble) { + return transformOptional(inst.rs1.ReadAPFloat(m_emu, isDouble), + [&](auto &&rs1) { + uint64_t result = 0; + if (rs1.isInfinity() && rs1.isNegative()) + result |= 1 << 0; + // neg normal + if (rs1.isNormal() && rs1.isNegative()) + result |= 1 << 1; + // neg subnormal + if (rs1.isDenormal() && rs1.isNegative()) + result |= 1 << 2; + if (rs1.isNegZero()) + result |= 1 << 3; + if (rs1.isPosZero()) + result |= 1 << 4; + // pos normal + if (rs1.isNormal() && !rs1.isNegative()) + result |= 1 << 5; + // pos subnormal + if (rs1.isDenormal() && !rs1.isNegative()) + result |= 1 << 6; + if (rs1.isInfinity() && !rs1.isNegative()) + result |= 1 << 7; + if (rs1.isNaN()) { + if (rs1.isSignaling()) + result |= 1 << 8; + else + result |= 1 << 9; + } + return inst.rd.Write(m_emu, result); + }) + .value_or(false); + } + bool operator()(FCLASS_S inst) { return FCLASS(inst, false); } + template <typename T, typename E> + bool FCVT_f2i(T inst, std::optional<E> (Rs::*f)(EmulateInstructionRISCV &emu), + const fltSemantics &semantics) { + return transformOptional(((&inst.rs1)->*f)(m_emu), + [&](auto &&rs1) { + APFloat apf(semantics, rs1); + return inst.rd.WriteAPFloat(m_emu, apf); + }) + .value_or(false); + } + bool operator()(FCVT_S_W inst) { + return FCVT_f2i(inst, &Rs::ReadI32, APFloat::IEEEsingle()); + } + bool operator()(FCVT_S_WU inst) { + return FCVT_f2i(inst, &Rs::ReadU32, APFloat::IEEEsingle()); + } + template <typename T, typename E> + bool FMV_i2f(T inst, unsigned int numBits, E (APInt::*f)() const) { + return transformOptional(inst.rs1.Read(m_emu), + [&](auto &&rs1) { + APInt apInt(numBits, rs1); + if (numBits == 32) // a.k.a. float + apInt = APInt(numBits, NanUnBoxing(rs1)); + APFloat apf((&apInt->*f)()); + return inst.rd.WriteAPFloat(m_emu, apf); + }) + .value_or(false); + } + bool operator()(FMV_W_X inst) { + return FMV_i2f(inst, 32, &APInt::bitsToFloat); + } + template <typename I, typename E, typename T> + bool FCVT_i2f(I inst, bool isDouble, T (APFloat::*f)() const) { + return transformOptional(inst.rs1.ReadAPFloat(m_emu, isDouble), + [&](auto &&rs1) { + E res = E((&rs1->*f)()); + return inst.rd.Write(m_emu, uint64_t(res)); + }) + .value_or(false); + } + bool operator()(FCVT_L_S inst) { + return FCVT_i2f<FCVT_L_S, int64_t, float>(inst, false, + &APFloat::convertToFloat); + } + bool operator()(FCVT_LU_S inst) { + return FCVT_i2f<FCVT_LU_S, uint64_t, float>(inst, false, + &APFloat::convertToFloat); + } + bool operator()(FCVT_S_L inst) { + return FCVT_f2i(inst, &Rs::ReadI64, APFloat::IEEEsingle()); + } + bool operator()(FCVT_S_LU inst) { + return FCVT_f2i(inst, &Rs::Read, APFloat::IEEEsingle()); + } + bool operator()(FLD inst) { return F_Load(inst, &APFloat::IEEEdouble, 64); } + bool operator()(FSD inst) { return F_Store(inst, true); } + bool operator()(FMADD_D inst) { return FMA(inst, true, 1.0f, 1.0f); } + bool operator()(FMSUB_D inst) { return FMA(inst, true, 1.0f, -1.0f); } + bool operator()(FNMSUB_D inst) { return FMA(inst, true, -1.0f, 1.0f); } + bool operator()(FNMADD_D inst) { return FMA(inst, true, -1.0f, -1.0f); } + bool operator()(FADD_D inst) { return F_Op(inst, true, &APFloat::add); } + bool operator()(FSUB_D inst) { return F_Op(inst, true, &APFloat::subtract); } + bool operator()(FMUL_D inst) { return F_Op(inst, true, &APFloat::multiply); } + bool operator()(FDIV_D inst) { return F_Op(inst, true, &APFloat::divide); } + bool operator()(FSQRT_D inst) { + // TODO: APFloat doesn't have a sqrt function. + return false; + } + bool operator()(FSGNJ_D inst) { return F_SignInj(inst, true, false); } + bool operator()(FSGNJN_D inst) { return F_SignInj(inst, true, true); } + bool operator()(FSGNJX_D inst) { return F_SignInjXor(inst, true); } + bool operator()(FMIN_D inst) { return F_MAX_MIN(inst, true, minnum); } + bool operator()(FMAX_D inst) { return F_MAX_MIN(inst, true, maxnum); } + bool operator()(FCVT_S_D inst) { + return transformOptional(inst.rs1.ReadAPFloat(m_emu, true), + [&](auto &&rs1) { + double d = rs1.convertToDouble(); + APFloat apf((float(d))); + return inst.rd.WriteAPFloat(m_emu, apf); + }) + .value_or(false); + } + bool operator()(FCVT_D_S inst) { + return transformOptional(inst.rs1.ReadAPFloat(m_emu, false), + [&](auto &&rs1) { + float f = rs1.convertToFloat(); + APFloat apf((double(f))); + return inst.rd.WriteAPFloat(m_emu, apf); + }) + .value_or(false); + } + bool operator()(FEQ_D inst) { return F_Compare(inst, true, FEQ); } + bool operator()(FLT_D inst) { return F_Compare(inst, true, FLT); } + bool operator()(FLE_D inst) { return F_Compare(inst, true, FLE); } + bool operator()(FCLASS_D inst) { return FCLASS(inst, true); } + bool operator()(FCVT_W_D inst) { + return FCVT_i2f<FCVT_W_D, int32_t, double>(inst, true, + &APFloat::convertToDouble); + } + bool operator()(FCVT_WU_D inst) { + return FCVT_i2f<FCVT_WU_D, uint32_t, double>(inst, true, + &APFloat::convertToDouble); + } + bool operator()(FCVT_D_W inst) { + return FCVT_f2i(inst, &Rs::ReadI32, APFloat::IEEEdouble()); + } + bool operator()(FCVT_D_WU inst) { + return FCVT_f2i(inst, &Rs::ReadU32, APFloat::IEEEdouble()); + } + bool operator()(FCVT_L_D inst) { + return FCVT_i2f<FCVT_L_D, int64_t, double>(inst, true, + &APFloat::convertToDouble); + } + bool operator()(FCVT_LU_D inst) { + return FCVT_i2f<FCVT_LU_D, uint64_t, double>(inst, true, + &APFloat::convertToDouble); + } + bool operator()(FMV_X_D inst) { return FMV_f2i(inst, true); } + bool operator()(FCVT_D_L inst) { + return FCVT_f2i(inst, &Rs::ReadI64, APFloat::IEEEdouble()); + } + bool operator()(FCVT_D_LU inst) { + return FCVT_f2i(inst, &Rs::Read, APFloat::IEEEdouble()); + } + bool operator()(FMV_D_X inst) { + return FMV_i2f(inst, 64, &APInt::bitsToDouble); + } + bool operator()(INVALID inst) { return false; } + bool operator()(RESERVED inst) { return false; } + bool operator()(EBREAK inst) { return false; } + bool operator()(HINT inst) { return true; } + bool operator()(NOP inst) { return true; } +}; + +bool EmulateInstructionRISCV::Execute(DecodeResult inst, bool ignore_cond) { + return std::visit(Executor(*this, ignore_cond, inst.is_rvc), inst.decoded); +} + +bool EmulateInstructionRISCV::EvaluateInstruction(uint32_t options) { + bool increase_pc = options & eEmulateInstructionOptionAutoAdvancePC; + bool ignore_cond = options & eEmulateInstructionOptionIgnoreConditions; + + if (!increase_pc) + return Execute(m_decoded, ignore_cond); + + auto old_pc = ReadPC(); + if (!old_pc) + return false; + + bool success = Execute(m_decoded, ignore_cond); + if (!success) + return false; + + auto new_pc = ReadPC(); + if (!new_pc) + return false; + + // If the pc is not updated during execution, we do it here. + return new_pc != old_pc || + WritePC(*old_pc + Executor::size(m_decoded.is_rvc)); +} + +std::optional<DecodeResult> +EmulateInstructionRISCV::ReadInstructionAt(addr_t addr) { + return transformOptional(ReadMem<uint32_t>(addr), + [&](uint32_t inst) { return Decode(inst); }) + .value_or(std::nullopt); +} + +bool EmulateInstructionRISCV::ReadInstruction() { + auto addr = ReadPC(); + m_addr = addr.value_or(LLDB_INVALID_ADDRESS); + if (!addr) + return false; + auto inst = ReadInstructionAt(*addr); + if (!inst) + return false; + m_decoded = *inst; + if (inst->is_rvc) + m_opcode.SetOpcode16(inst->inst, GetByteOrder()); + else + m_opcode.SetOpcode32(inst->inst, GetByteOrder()); + return true; +} + +std::optional<addr_t> EmulateInstructionRISCV::ReadPC() { + bool success = false; + auto addr = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, + LLDB_INVALID_ADDRESS, &success); + return success ? std::optional<addr_t>(addr) : std::nullopt; +} + +bool EmulateInstructionRISCV::WritePC(addr_t pc) { + EmulateInstruction::Context ctx; + ctx.type = eContextAdvancePC; + ctx.SetNoArgs(); + return WriteRegisterUnsigned(ctx, eRegisterKindGeneric, + LLDB_REGNUM_GENERIC_PC, pc); +} + +RoundingMode EmulateInstructionRISCV::GetRoundingMode() { + bool success = false; + auto fcsr = ReadRegisterUnsigned(eRegisterKindLLDB, fpr_fcsr_riscv, + LLDB_INVALID_ADDRESS, &success); + if (!success) + return RoundingMode::Invalid; + auto frm = (fcsr >> 5) & 0x7; + switch (frm) { + case 0b000: + return RoundingMode::NearestTiesToEven; + case 0b001: + return RoundingMode::TowardZero; + case 0b010: + return RoundingMode::TowardNegative; + case 0b011: + return RoundingMode::TowardPositive; + case 0b111: + return RoundingMode::Dynamic; + default: + // Reserved for future use. + return RoundingMode::Invalid; + } +} + +bool EmulateInstructionRISCV::SetAccruedExceptions( + APFloatBase::opStatus opStatus) { + bool success = false; + auto fcsr = ReadRegisterUnsigned(eRegisterKindLLDB, fpr_fcsr_riscv, + LLDB_INVALID_ADDRESS, &success); + if (!success) + return false; + switch (opStatus) { + case APFloatBase::opInvalidOp: + fcsr |= 1 << 4; + break; + case APFloatBase::opDivByZero: + fcsr |= 1 << 3; + break; + case APFloatBase::opOverflow: + fcsr |= 1 << 2; + break; + case APFloatBase::opUnderflow: + fcsr |= 1 << 1; + break; + case APFloatBase::opInexact: + fcsr |= 1 << 0; + break; + case APFloatBase::opOK: + break; + } + EmulateInstruction::Context ctx; + ctx.type = eContextRegisterStore; + ctx.SetNoArgs(); + return WriteRegisterUnsigned(ctx, eRegisterKindLLDB, fpr_fcsr_riscv, fcsr); +} + +std::optional<RegisterInfo> +EmulateInstructionRISCV::GetRegisterInfo(RegisterKind reg_kind, + uint32_t reg_index) { + if (reg_kind == eRegisterKindGeneric) { + switch (reg_index) { + case LLDB_REGNUM_GENERIC_PC: + reg_kind = eRegisterKindLLDB; + reg_index = gpr_pc_riscv; + break; + case LLDB_REGNUM_GENERIC_SP: + reg_kind = eRegisterKindLLDB; + reg_index = gpr_sp_riscv; + break; + case LLDB_REGNUM_GENERIC_FP: + reg_kind = eRegisterKindLLDB; + reg_index = gpr_fp_riscv; + break; + case LLDB_REGNUM_GENERIC_RA: + reg_kind = eRegisterKindLLDB; + reg_index = gpr_ra_riscv; + break; + // We may handle LLDB_REGNUM_GENERIC_ARGx when more instructions are + // supported. + default: + llvm_unreachable("unsupported register"); + } + } + + const RegisterInfo *array = + RegisterInfoPOSIX_riscv64::GetRegisterInfoPtr(m_arch); + const uint32_t length = + RegisterInfoPOSIX_riscv64::GetRegisterInfoCount(m_arch); + + if (reg_index >= length || reg_kind != eRegisterKindLLDB) + return {}; + + return array[reg_index]; +} + +bool EmulateInstructionRISCV::SetTargetTriple(const ArchSpec &arch) { + return SupportsThisArch(arch); +} + +bool EmulateInstructionRISCV::TestEmulation(Stream *out_stream, ArchSpec &arch, + OptionValueDictionary *test_data) { + return false; +} + +void EmulateInstructionRISCV::Initialize() { + PluginManager::RegisterPlugin(GetPluginNameStatic(), + GetPluginDescriptionStatic(), CreateInstance); +} + +void EmulateInstructionRISCV::Terminate() { + PluginManager::UnregisterPlugin(CreateInstance); +} + +lldb_private::EmulateInstruction * +EmulateInstructionRISCV::CreateInstance(const ArchSpec &arch, + InstructionType inst_type) { + if (EmulateInstructionRISCV::SupportsThisInstructionType(inst_type) && + SupportsThisArch(arch)) { + return new EmulateInstructionRISCV(arch); + } + + return nullptr; +} + +bool EmulateInstructionRISCV::SupportsThisArch(const ArchSpec &arch) { + return arch.GetTriple().isRISCV(); +} + +} // namespace lldb_private diff --git a/contrib/llvm-project/lldb/source/Plugins/Instruction/RISCV/EmulateInstructionRISCV.h b/contrib/llvm-project/lldb/source/Plugins/Instruction/RISCV/EmulateInstructionRISCV.h new file mode 100644 index 000000000000..c3997b89466b --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/Instruction/RISCV/EmulateInstructionRISCV.h @@ -0,0 +1,106 @@ +//===-- EmulateInstructionRISCV.h -----------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_SOURCE_PLUGINS_INSTRUCTION_RISCV_EMULATEINSTRUCTIONRISCV_H +#define LLDB_SOURCE_PLUGINS_INSTRUCTION_RISCV_EMULATEINSTRUCTIONRISCV_H + +#include "RISCVInstructions.h" + +#include "lldb/Core/EmulateInstruction.h" +#include "lldb/Interpreter/OptionValue.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/RegisterValue.h" +#include "lldb/Utility/Status.h" +#include <optional> + +namespace lldb_private { + +class EmulateInstructionRISCV : public EmulateInstruction { +public: + static llvm::StringRef GetPluginNameStatic() { return "riscv"; } + + static llvm::StringRef GetPluginDescriptionStatic() { + return "Emulate instructions for the RISC-V architecture."; + } + + static bool SupportsThisInstructionType(InstructionType inst_type) { + switch (inst_type) { + case eInstructionTypeAny: + case eInstructionTypePCModifying: + return true; + case eInstructionTypePrologueEpilogue: + case eInstructionTypeAll: + return false; + } + llvm_unreachable("Fully covered switch above!"); + } + + static bool SupportsThisArch(const ArchSpec &arch); + + static lldb_private::EmulateInstruction * + CreateInstance(const lldb_private::ArchSpec &arch, InstructionType inst_type); + + static void Initialize(); + + static void Terminate(); + +public: + EmulateInstructionRISCV(const ArchSpec &arch) : EmulateInstruction(arch) {} + + llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); } + + bool SupportsEmulatingInstructionsOfType(InstructionType inst_type) override { + return SupportsThisInstructionType(inst_type); + } + + bool SetTargetTriple(const ArchSpec &arch) override; + bool ReadInstruction() override; + bool EvaluateInstruction(uint32_t options) override; + bool TestEmulation(Stream *out_stream, ArchSpec &arch, + OptionValueDictionary *test_data) override; + std::optional<RegisterInfo> GetRegisterInfo(lldb::RegisterKind reg_kind, + uint32_t reg_num) override; + + std::optional<lldb::addr_t> ReadPC(); + bool WritePC(lldb::addr_t pc); + + std::optional<DecodeResult> ReadInstructionAt(lldb::addr_t addr); + std::optional<DecodeResult> Decode(uint32_t inst); + bool Execute(DecodeResult inst, bool ignore_cond); + + template <typename T> + std::enable_if_t<std::is_integral_v<T>, std::optional<T>> + ReadMem(uint64_t addr) { + EmulateInstructionRISCV::Context ctx; + ctx.type = EmulateInstruction::eContextRegisterLoad; + ctx.SetNoArgs(); + bool success = false; + T result = ReadMemoryUnsigned(ctx, addr, sizeof(T), T(), &success); + if (!success) + return {}; // aka return false + return result; + } + + template <typename T> bool WriteMem(uint64_t addr, uint64_t value) { + EmulateInstructionRISCV::Context ctx; + ctx.type = EmulateInstruction::eContextRegisterStore; + ctx.SetNoArgs(); + return WriteMemoryUnsigned(ctx, addr, value, sizeof(T)); + } + + llvm::RoundingMode GetRoundingMode(); + bool SetAccruedExceptions(llvm::APFloatBase::opStatus); + +private: + /// Last decoded instruction from m_opcode + DecodeResult m_decoded; +}; + +} // namespace lldb_private + +#endif // LLDB_SOURCE_PLUGINS_INSTRUCTION_RISCV_EMULATEINSTRUCTIONRISCV_H diff --git a/contrib/llvm-project/lldb/source/Plugins/Instruction/RISCV/RISCVCInstructions.h b/contrib/llvm-project/lldb/source/Plugins/Instruction/RISCV/RISCVCInstructions.h new file mode 100644 index 000000000000..867f067f24b3 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/Instruction/RISCV/RISCVCInstructions.h @@ -0,0 +1,357 @@ +//===-- RISCVCInstructions.h ----------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_SOURCE_PLUGINS_INSTRUCTION_RISCV_RISCVCINSTRUCTION_H +#define LLDB_SOURCE_PLUGINS_INSTRUCTION_RISCV_RISCVCINSTRUCTION_H + +#include <cstdint> +#include <variant> + +#include "Plugins/Process/Utility/lldb-riscv-register-enums.h" +#include "RISCVInstructions.h" + +namespace lldb_private { + +/// Unified RISC-V C register encoding. +struct RxC { + uint32_t rd; + bool shift = true; + operator int() { return rd; } + operator Rd() { return Rd{rd + (shift ? 8 : 0)}; } + operator Rs() { return Rs{rd + (shift ? 8 : 0)}; } +}; + +// decode register for RVC +constexpr RxC DecodeCR_RD(uint32_t inst) { return RxC{DecodeRD(inst), false}; } +constexpr RxC DecodeCI_RD(uint32_t inst) { return RxC{DecodeRD(inst), false}; } +constexpr RxC DecodeCR_RS1(uint32_t inst) { return RxC{DecodeRD(inst), false}; } +constexpr RxC DecodeCI_RS1(uint32_t inst) { return RxC{DecodeRD(inst), false}; } +constexpr RxC DecodeCR_RS2(uint32_t inst) { + return RxC{(inst & 0x7C) >> 2, false}; +} + +constexpr RxC DecodeCIW_RD(uint32_t inst) { return RxC{(inst & 0x1C) >> 2}; } +constexpr RxC DecodeCL_RD(uint32_t inst) { return RxC{DecodeCIW_RD(inst)}; } +constexpr RxC DecodeCA_RD(uint32_t inst) { return RxC{(inst & 0x380) >> 7}; } +constexpr RxC DecodeCB_RD(uint32_t inst) { return RxC{DecodeCA_RD(inst)}; } + +constexpr RxC DecodeCL_RS1(uint32_t inst) { return RxC{DecodeCA_RD(inst)}; } +constexpr RxC DecodeCS_RS1(uint32_t inst) { return RxC{DecodeCA_RD(inst)}; } +constexpr RxC DecodeCA_RS1(uint32_t inst) { return RxC{DecodeCA_RD(inst)}; } +constexpr RxC DecodeCB_RS1(uint32_t inst) { return RxC{DecodeCA_RD(inst)}; } + +constexpr RxC DecodeCSS_RS2(uint32_t inst) { return DecodeCR_RS2(inst); } +constexpr RxC DecodeCS_RS2(uint32_t inst) { return RxC{DecodeCIW_RD(inst)}; } +constexpr RxC DecodeCA_RS2(uint32_t inst) { return RxC{DecodeCIW_RD(inst)}; } + +RISCVInst DecodeC_LWSP(uint32_t inst) { + auto rd = DecodeCI_RD(inst); + uint16_t offset = ((inst << 4) & 0xc0) // offset[7:6] + | ((inst >> 7) & 0x20) // offset[5] + | ((inst >> 2) & 0x1c); // offset[4:2] + if (rd == 0) + return RESERVED{inst}; + return LW{rd, Rs{gpr_sp_riscv}, uint32_t(offset)}; +} + +RISCVInst DecodeC_LDSP(uint32_t inst) { + auto rd = DecodeCI_RD(inst); + uint16_t offset = ((inst << 4) & 0x1c0) // offset[8:6] + | ((inst >> 7) & 0x20) // offset[5] + | ((inst >> 2) & 0x18); // offset[4:3] + if (rd == 0) + return RESERVED{inst}; + return LD{rd, Rs{gpr_sp_riscv}, uint32_t(offset)}; +} + +RISCVInst DecodeC_SWSP(uint32_t inst) { + uint16_t offset = ((inst >> 1) & 0xc0) // offset[7:6] + | ((inst >> 7) & 0x3c); // offset[5:2] + return SW{Rs{gpr_sp_riscv}, DecodeCSS_RS2(inst), uint32_t(offset)}; +} + +RISCVInst DecodeC_SDSP(uint32_t inst) { + uint16_t offset = ((inst >> 1) & 0x1c0) // offset[8:6] + | ((inst >> 7) & 0x38); // offset[5:3] + return SD{Rs{gpr_sp_riscv}, DecodeCSS_RS2(inst), uint32_t(offset)}; +} + +RISCVInst DecodeC_LW(uint32_t inst) { + uint16_t offset = ((inst << 1) & 0x40) // imm[6] + | ((inst >> 7) & 0x38) // imm[5:3] + | ((inst >> 4) & 0x4); // imm[2] + return LW{DecodeCL_RD(inst), DecodeCL_RS1(inst), uint32_t(offset)}; +} + +RISCVInst DecodeC_LD(uint32_t inst) { + uint16_t offset = ((inst << 1) & 0xc0) // imm[7:6] + | ((inst >> 7) & 0x38); // imm[5:3] + return LD{DecodeCL_RD(inst), DecodeCL_RS1(inst), uint32_t(offset)}; +} + +RISCVInst DecodeC_SW(uint32_t inst) { + uint16_t offset = ((inst << 1) & 0x40) // imm[6] + | ((inst >> 7) & 0x38) // imm[5:3] + | ((inst >> 4) & 0x4); // imm[2] + return SW{DecodeCS_RS1(inst), DecodeCS_RS2(inst), uint32_t(offset)}; +} + +RISCVInst DecodeC_SD(uint32_t inst) { + uint16_t offset = ((inst << 1) & 0xc0) // imm[7:6] + | ((inst >> 7) & 0x38); // imm[5:3] + return SD{DecodeCS_RS1(inst), DecodeCS_RS2(inst), uint32_t(offset)}; +} + +RISCVInst DecodeC_J(uint32_t inst) { + uint16_t offset = ((inst >> 1) & 0x800) // offset[11] + | ((inst << 2) & 0x400) // offset[10] + | ((inst >> 1) & 0x300) // offset[9:8] + | ((inst << 1) & 0x80) // offset[7] + | ((inst >> 1) & 0x40) // offset[6] + | ((inst << 3) & 0x20) // offset[5] + | ((inst >> 7) & 0x10) // offset[4] + | ((inst >> 2) & 0xe); // offset[3:1] + if ((offset & 0x800) == 0) + return JAL{Rd{0}, uint32_t(offset)}; + return JAL{Rd{0}, uint32_t(int32_t(int16_t(offset | 0xf000)))}; +} + +RISCVInst DecodeC_JR(uint32_t inst) { + auto rs1 = DecodeCR_RS1(inst); + if (rs1 == 0) + return RESERVED{inst}; + return JALR{Rd{0}, rs1, 0}; +} + +RISCVInst DecodeC_JALR(uint32_t inst) { + auto rs1 = DecodeCR_RS1(inst); + if (rs1 == 0) + return EBREAK{inst}; + return JALR{Rd{1}, rs1, 0}; +} + +constexpr uint16_t BOffset(uint32_t inst) { + return ((inst >> 4) & 0x100) // offset[8] + | ((inst << 1) & 0xc0) // offset[7:6] + | ((inst << 3) & 0x20) // offset[5] + | ((inst >> 7) & 0x18) // offset[4:3] + | ((inst >> 2) & 0x6); // offset[2:1] +} + +RISCVInst DecodeC_BNEZ(uint32_t inst) { + auto rs1 = DecodeCB_RS1(inst); + uint16_t offset = BOffset(inst); + if ((offset & 0x100) == 0) + return B{rs1, Rs{0}, uint32_t(offset), 0b001}; + return B{rs1, Rs{0}, uint32_t(int32_t(int16_t(offset | 0xfe00))), 0b001}; +} + +RISCVInst DecodeC_BEQZ(uint32_t inst) { + auto rs1 = DecodeCB_RS1(inst); + uint16_t offset = BOffset(inst); + if ((offset & 0x100) == 0) + return B{rs1, Rs{0}, uint32_t(offset), 0b000}; + return B{rs1, Rs{0}, uint32_t(int32_t(int16_t(offset | 0xfe00))), 0b000}; +} + +RISCVInst DecodeC_LI(uint32_t inst) { + auto rd = DecodeCI_RD(inst); + uint16_t imm = ((inst >> 7) & 0x20) | ((inst >> 2) & 0x1f); + if ((imm & 0x20) == 0) + return ADDI{rd, Rs{0}, uint32_t(imm)}; + return ADDI{rd, Rs{0}, uint32_t(int32_t(int8_t(imm | 0xc0)))}; +} + +RISCVInst DecodeC_LUI_ADDI16SP(uint32_t inst) { + auto rd = DecodeCI_RD(inst); + if (rd == 0) + return HINT{inst}; + if (rd == 2) { + uint16_t nzimm = ((inst >> 3) & 0x200) // nzimm[9] + | ((inst >> 2) & 0x10) // nzimm[4] + | ((inst << 1) & 0x40) // nzimm[6] + | ((inst << 4) & 0x180) // nzimm[8:7] + | ((inst << 3) & 0x20); // nzimm[5] + if (nzimm == 0) + return RESERVED{inst}; + if ((nzimm & 0x200) == 0) + return ADDI{Rd{gpr_sp_riscv}, Rs{gpr_sp_riscv}, uint32_t(nzimm)}; + return ADDI{Rd{gpr_sp_riscv}, Rs{gpr_sp_riscv}, + uint32_t(int32_t(int16_t(nzimm | 0xfc00)))}; + } + uint32_t imm = + ((uint32_t(inst) << 5) & 0x20000) | ((uint32_t(inst) << 10) & 0x1f000); + if ((imm & 0x20000) == 0) + return LUI{rd, imm}; + return LUI{rd, uint32_t(int32_t(imm | 0xfffc0000))}; +} + +RISCVInst DecodeC_ADDI(uint32_t inst) { + auto rd = DecodeCI_RD(inst); + if (rd == 0) + return NOP{inst}; + uint16_t imm = ((inst >> 7) & 0x20) | ((inst >> 2) & 0x1f); + if ((imm & 0x20) == 0) + return ADDI{rd, rd, uint32_t(imm)}; + return ADDI{rd, rd, uint32_t(int32_t(int8_t(imm | 0xc0)))}; +} + +RISCVInst DecodeC_ADDIW(uint32_t inst) { + auto rd = DecodeCI_RD(inst); + if (rd == 0) + return RESERVED{inst}; + uint16_t imm = ((inst >> 7) & 0x20) | ((inst >> 2) & 0x1f); + if ((imm & 0x20) == 0) + return ADDIW{rd, rd, uint32_t(imm)}; + return ADDIW{rd, rd, uint32_t(int32_t(int8_t(imm | 0xc0)))}; +} + +RISCVInst DecodeC_ADDI4SPN(uint32_t inst) { + auto rd = DecodeCIW_RD(inst); + uint16_t nzuimm = ((inst >> 1) & 0x3c0) // nzuimm[9:6] + | ((inst >> 7) & 0x30) // nzuimm[5:4] + | ((inst >> 2) & 0x8) // nzuimm[3] + | ((inst >> 4) & 0x4); // nzuimm[2] + + if (rd == 0 && nzuimm == 0) + return INVALID{inst}; + if (nzuimm == 0) + return RESERVED{inst}; + return ADDI{rd, Rs{gpr_sp_riscv}, uint32_t(nzuimm)}; +} + +RISCVInst DecodeC_SLLI(uint32_t inst) { + auto rd = DecodeCI_RD(inst); + uint16_t shamt = ((inst >> 7) & 0x20) | ((inst >> 2) & 0x1f); + if (rd == 0 || shamt == 0) + return HINT{inst}; + return SLLI{rd, rd, uint8_t(shamt)}; +} + +RISCVInst DecodeC_SRLI(uint32_t inst) { + auto rd = DecodeCB_RD(inst); + uint16_t shamt = ((inst >> 7) & 0x20) | ((inst >> 2) & 0x1f); + if (shamt == 0) + return HINT{inst}; + return SRLI{rd, rd, uint8_t(shamt)}; +} + +RISCVInst DecodeC_SRAI(uint32_t inst) { + auto rd = DecodeCB_RD(inst); + uint16_t shamt = ((inst >> 7) & 0x20) | ((inst >> 2) & 0x1f); + if (shamt == 0) + return HINT{inst}; + return SRAI{rd, rd, uint8_t(shamt)}; +} + +RISCVInst DecodeC_ANDI(uint32_t inst) { + auto rd = DecodeCB_RD(inst); + uint16_t imm = ((inst >> 7) & 0x20) | ((inst >> 2) & 0x1f); + if ((imm & 0x20) == 0) + return ANDI{rd, rd, uint32_t(imm)}; + return ANDI{rd, rd, uint32_t(int32_t(int8_t(imm | 0xc0)))}; +} + +RISCVInst DecodeC_MV(uint32_t inst) { + auto rd = DecodeCR_RD(inst); + auto rs2 = DecodeCR_RS2(inst); + if (rd == 0) + return HINT{inst}; + return ADD{rd, Rs{0}, rs2}; +} + +RISCVInst DecodeC_ADD(uint32_t inst) { + auto rd = DecodeCR_RD(inst); + return ADD{rd, rd, DecodeCR_RS2(inst)}; +} + +RISCVInst DecodeC_AND(uint32_t inst) { + auto rd = DecodeCA_RD(inst); + return AND{rd, rd, DecodeCA_RS2(inst)}; +} + +RISCVInst DecodeC_OR(uint32_t inst) { + auto rd = DecodeCA_RD(inst); + return OR{rd, rd, DecodeCA_RS2(inst)}; +} + +RISCVInst DecodeC_XOR(uint32_t inst) { + auto rd = DecodeCA_RD(inst); + return XOR{rd, rd, DecodeCA_RS2(inst)}; +} + +RISCVInst DecodeC_SUB(uint32_t inst) { + auto rd = DecodeCA_RD(inst); + return SUB{rd, rd, DecodeCA_RS2(inst)}; +} + +RISCVInst DecodeC_SUBW(uint32_t inst) { + auto rd = DecodeCA_RD(inst); + return SUBW{rd, rd, DecodeCA_RS2(inst)}; +} + +RISCVInst DecodeC_ADDW(uint32_t inst) { + auto rd = DecodeCA_RD(inst); + return ADDW{rd, rd, DecodeCA_RS2(inst)}; +} +RISCVInst DecodeC_FLW(uint32_t inst) { + uint16_t offset = ((inst << 1) & 0x40) // imm[6] + | ((inst >> 7) & 0x38) // imm[5:3] + | ((inst >> 4) & 0x4); // imm[2] + return FLW{DecodeCL_RD(inst), DecodeCL_RS1(inst), uint32_t(offset)}; +} + +RISCVInst DecodeC_FSW(uint32_t inst) { + uint16_t offset = ((inst << 1) & 0x40) // imm[6] + | ((inst >> 7) & 0x38) // imm[5:3] + | ((inst >> 4) & 0x4); // imm[2] + return FSW{DecodeCS_RS1(inst), DecodeCS_RS2(inst), uint32_t(offset)}; +} + +RISCVInst DecodeC_FLWSP(uint32_t inst) { + auto rd = DecodeCI_RD(inst); + uint16_t offset = ((inst << 4) & 0xc0) // offset[7:6] + | ((inst >> 7) & 0x20) // offset[5] + | ((inst >> 2) & 0x1c); // offset[4:2] + return FLW{rd, Rs{gpr_sp_riscv}, uint32_t(offset)}; +} + +RISCVInst DecodeC_FSWSP(uint32_t inst) { + uint16_t offset = ((inst >> 1) & 0xc0) // offset[7:6] + | ((inst >> 7) & 0x3c); // offset[5:2] + return FSW{Rs{gpr_sp_riscv}, DecodeCSS_RS2(inst), uint32_t(offset)}; +} + +RISCVInst DecodeC_FLDSP(uint32_t inst) { + auto rd = DecodeCI_RD(inst); + uint16_t offset = ((inst << 4) & 0x1c0) // offset[8:6] + | ((inst >> 7) & 0x20) // offset[5] + | ((inst >> 2) & 0x18); // offset[4:3] + return FLD{rd, Rs{gpr_sp_riscv}, uint32_t(offset)}; +} + +RISCVInst DecodeC_FSDSP(uint32_t inst) { + uint16_t offset = ((inst >> 1) & 0x1c0) // offset[8:6] + | ((inst >> 7) & 0x38); // offset[5:3] + return FSD{Rs{gpr_sp_riscv}, DecodeCSS_RS2(inst), uint32_t(offset)}; +} + +RISCVInst DecodeC_FLD(uint32_t inst) { + uint16_t offset = ((inst << 1) & 0xc0) // imm[7:6] + | ((inst >> 7) & 0x38); // imm[5:3] + return FLD{DecodeCL_RD(inst), DecodeCL_RS1(inst), uint32_t(offset)}; +} + +RISCVInst DecodeC_FSD(uint32_t inst) { + uint16_t offset = ((inst << 1) & 0xc0) // imm[7:6] + | ((inst >> 7) & 0x38); // imm[5:3] + return FSD{DecodeCS_RS1(inst), DecodeCS_RS2(inst), uint32_t(offset)}; +} + +} // namespace lldb_private +#endif // LLDB_SOURCE_PLUGINS_INSTRUCTION_RISCV_RISCVCINSTRUCTION_H diff --git a/contrib/llvm-project/lldb/source/Plugins/Instruction/RISCV/RISCVInstructions.h b/contrib/llvm-project/lldb/source/Plugins/Instruction/RISCV/RISCVInstructions.h new file mode 100644 index 000000000000..252cef805408 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/Instruction/RISCV/RISCVInstructions.h @@ -0,0 +1,352 @@ +//===-- RISCVInstructions.h -----------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_SOURCE_PLUGINS_INSTRUCTION_RISCV_RISCVINSTRUCTION_H +#define LLDB_SOURCE_PLUGINS_INSTRUCTION_RISCV_RISCVINSTRUCTION_H + +#include <cstdint> +#include <optional> +#include <variant> + +#include "llvm/ADT/APFloat.h" + +namespace lldb_private { + +class EmulateInstructionRISCV; + +struct Rd { + uint32_t rd; + bool Write(EmulateInstructionRISCV &emulator, uint64_t value); + bool WriteAPFloat(EmulateInstructionRISCV &emulator, llvm::APFloat value); +}; + +struct Rs { + uint32_t rs; + std::optional<uint64_t> Read(EmulateInstructionRISCV &emulator); + std::optional<int32_t> ReadI32(EmulateInstructionRISCV &emulator); + std::optional<int64_t> ReadI64(EmulateInstructionRISCV &emulator); + std::optional<uint32_t> ReadU32(EmulateInstructionRISCV &emulator); + std::optional<llvm::APFloat> ReadAPFloat(EmulateInstructionRISCV &emulator, + bool isDouble); +}; + +#define DERIVE_EQ(NAME) \ + bool operator==(const NAME &r) const { \ + return std::memcmp(this, &r, sizeof(NAME)) == 0; \ + } + +#define I_TYPE_INST(NAME) \ + struct NAME { \ + Rd rd; \ + Rs rs1; \ + uint32_t imm; \ + DERIVE_EQ(NAME); \ + } +#define S_TYPE_INST(NAME) \ + struct NAME { \ + Rs rs1; \ + Rs rs2; \ + uint32_t imm; \ + DERIVE_EQ(NAME); \ + } +#define U_TYPE_INST(NAME) \ + struct NAME { \ + Rd rd; \ + uint32_t imm; \ + DERIVE_EQ(NAME); \ + } +/// The memory layout are the same in our code. +#define J_TYPE_INST(NAME) U_TYPE_INST(NAME) +#define R_TYPE_INST(NAME) \ + struct NAME { \ + Rd rd; \ + Rs rs1; \ + Rs rs2; \ + DERIVE_EQ(NAME); \ + } +#define R_SHAMT_TYPE_INST(NAME) \ + struct NAME { \ + Rd rd; \ + Rs rs1; \ + uint32_t shamt; \ + DERIVE_EQ(NAME); \ + } +#define R_RS1_TYPE_INST(NAME) \ + struct NAME { \ + Rd rd; \ + Rs rs1; \ + DERIVE_EQ(NAME); \ + } +#define R4_TYPE_INST(NAME) \ + struct NAME { \ + Rd rd; \ + Rs rs1; \ + Rs rs2; \ + Rs rs3; \ + int32_t rm; \ + DERIVE_EQ(NAME); \ + } +/// The `inst` fields are used for debugging. +#define INVALID_INST(NAME) \ + struct NAME { \ + uint32_t inst; \ + DERIVE_EQ(NAME); \ + } + +// RV32I instructions (The base integer ISA) +struct B { + Rs rs1; + Rs rs2; + uint32_t imm; + uint32_t funct3; + DERIVE_EQ(B); +}; +U_TYPE_INST(LUI); +U_TYPE_INST(AUIPC); +J_TYPE_INST(JAL); +I_TYPE_INST(JALR); +I_TYPE_INST(LB); +I_TYPE_INST(LH); +I_TYPE_INST(LW); +I_TYPE_INST(LBU); +I_TYPE_INST(LHU); +S_TYPE_INST(SB); +S_TYPE_INST(SH); +S_TYPE_INST(SW); +I_TYPE_INST(ADDI); +I_TYPE_INST(SLTI); +I_TYPE_INST(SLTIU); +I_TYPE_INST(XORI); +I_TYPE_INST(ORI); +I_TYPE_INST(ANDI); +R_TYPE_INST(ADD); +R_TYPE_INST(SUB); +R_TYPE_INST(SLL); +R_TYPE_INST(SLT); +R_TYPE_INST(SLTU); +R_TYPE_INST(XOR); +R_TYPE_INST(SRL); +R_TYPE_INST(SRA); +R_TYPE_INST(OR); +R_TYPE_INST(AND); + +// RV64I inst (The base integer ISA) +I_TYPE_INST(LWU); +I_TYPE_INST(LD); +S_TYPE_INST(SD); +R_SHAMT_TYPE_INST(SLLI); +R_SHAMT_TYPE_INST(SRLI); +R_SHAMT_TYPE_INST(SRAI); +I_TYPE_INST(ADDIW); +R_SHAMT_TYPE_INST(SLLIW); +R_SHAMT_TYPE_INST(SRLIW); +R_SHAMT_TYPE_INST(SRAIW); +R_TYPE_INST(ADDW); +R_TYPE_INST(SUBW); +R_TYPE_INST(SLLW); +R_TYPE_INST(SRLW); +R_TYPE_INST(SRAW); + +// RV32M inst (The standard integer multiplication and division extension) +R_TYPE_INST(MUL); +R_TYPE_INST(MULH); +R_TYPE_INST(MULHSU); +R_TYPE_INST(MULHU); +R_TYPE_INST(DIV); +R_TYPE_INST(DIVU); +R_TYPE_INST(REM); +R_TYPE_INST(REMU); + +// RV64M inst (The standard integer multiplication and division extension) +R_TYPE_INST(MULW); +R_TYPE_INST(DIVW); +R_TYPE_INST(DIVUW); +R_TYPE_INST(REMW); +R_TYPE_INST(REMUW); + +// RV32A inst (The standard atomic instruction extension) +R_RS1_TYPE_INST(LR_W); +R_TYPE_INST(SC_W); +R_TYPE_INST(AMOSWAP_W); +R_TYPE_INST(AMOADD_W); +R_TYPE_INST(AMOXOR_W); +R_TYPE_INST(AMOAND_W); +R_TYPE_INST(AMOOR_W); +R_TYPE_INST(AMOMIN_W); +R_TYPE_INST(AMOMAX_W); +R_TYPE_INST(AMOMINU_W); +R_TYPE_INST(AMOMAXU_W); + +// RV64A inst (The standard atomic instruction extension) +R_RS1_TYPE_INST(LR_D); +R_TYPE_INST(SC_D); +R_TYPE_INST(AMOSWAP_D); +R_TYPE_INST(AMOADD_D); +R_TYPE_INST(AMOXOR_D); +R_TYPE_INST(AMOAND_D); +R_TYPE_INST(AMOOR_D); +R_TYPE_INST(AMOMIN_D); +R_TYPE_INST(AMOMAX_D); +R_TYPE_INST(AMOMINU_D); +R_TYPE_INST(AMOMAXU_D); + +// RV32F inst (The standard single-precision floating-point extension) +I_TYPE_INST(FLW); +S_TYPE_INST(FSW); +R4_TYPE_INST(FMADD_S); +R4_TYPE_INST(FMSUB_S); +R4_TYPE_INST(FNMADD_S); +R4_TYPE_INST(FNMSUB_S); +R_TYPE_INST(FADD_S); +R_TYPE_INST(FSUB_S); +R_TYPE_INST(FMUL_S); +R_TYPE_INST(FDIV_S); +I_TYPE_INST(FSQRT_S); +R_TYPE_INST(FSGNJ_S); +R_TYPE_INST(FSGNJN_S); +R_TYPE_INST(FSGNJX_S); +R_TYPE_INST(FMIN_S); +R_TYPE_INST(FMAX_S); +I_TYPE_INST(FCVT_W_S); +I_TYPE_INST(FCVT_WU_S); +I_TYPE_INST(FMV_X_W); +R_TYPE_INST(FEQ_S); +R_TYPE_INST(FLT_S); +R_TYPE_INST(FLE_S); +I_TYPE_INST(FCLASS_S); +I_TYPE_INST(FCVT_S_W); +I_TYPE_INST(FCVT_S_WU); +I_TYPE_INST(FMV_W_X); + +// RV64F inst (The standard single-precision floating-point extension) +I_TYPE_INST(FCVT_L_S); +I_TYPE_INST(FCVT_LU_S); +I_TYPE_INST(FCVT_S_L); +I_TYPE_INST(FCVT_S_LU); + +// RV32D inst (Extension for Double-Precision Floating-Point) +I_TYPE_INST(FLD); +S_TYPE_INST(FSD); +R4_TYPE_INST(FMADD_D); +R4_TYPE_INST(FMSUB_D); +R4_TYPE_INST(FNMSUB_D); +R4_TYPE_INST(FNMADD_D); +R_TYPE_INST(FADD_D); +R_TYPE_INST(FSUB_D); +R_TYPE_INST(FMUL_D); +R_TYPE_INST(FDIV_D); +I_TYPE_INST(FSQRT_D); +R_TYPE_INST(FSGNJ_D); +R_TYPE_INST(FSGNJN_D); +R_TYPE_INST(FSGNJX_D); +R_TYPE_INST(FMIN_D); +R_TYPE_INST(FMAX_D); +I_TYPE_INST(FCVT_S_D); +I_TYPE_INST(FCVT_D_S); +R_TYPE_INST(FEQ_D); +R_TYPE_INST(FLT_D); +R_TYPE_INST(FLE_D); +I_TYPE_INST(FCLASS_D); +I_TYPE_INST(FCVT_W_D); +I_TYPE_INST(FCVT_WU_D); +I_TYPE_INST(FCVT_D_W); +I_TYPE_INST(FCVT_D_WU); + +// RV64D inst (Extension for Double-Precision Floating-Point) +I_TYPE_INST(FCVT_L_D); +I_TYPE_INST(FCVT_LU_D); +I_TYPE_INST(FMV_X_D); +I_TYPE_INST(FCVT_D_L); +I_TYPE_INST(FCVT_D_LU); +I_TYPE_INST(FMV_D_X); + +/// Invalid and reserved instructions, the `inst` fields are used for debugging. +INVALID_INST(INVALID); +INVALID_INST(RESERVED); +INVALID_INST(EBREAK); +INVALID_INST(HINT); +INVALID_INST(NOP); + +using RISCVInst = std::variant< + LUI, AUIPC, JAL, JALR, B, LB, LH, LW, LBU, LHU, SB, SH, SW, ADDI, SLTI, + SLTIU, XORI, ORI, ANDI, ADD, SUB, SLL, SLT, SLTU, XOR, SRL, SRA, OR, AND, + LWU, LD, SD, SLLI, SRLI, SRAI, ADDIW, SLLIW, SRLIW, SRAIW, ADDW, SUBW, SLLW, + SRLW, SRAW, MUL, MULH, MULHSU, MULHU, DIV, DIVU, REM, REMU, MULW, DIVW, + DIVUW, REMW, REMUW, LR_W, SC_W, AMOSWAP_W, AMOADD_W, AMOXOR_W, AMOAND_W, + AMOOR_W, AMOMIN_W, AMOMAX_W, AMOMINU_W, AMOMAXU_W, LR_D, SC_D, AMOSWAP_D, + AMOADD_D, AMOXOR_D, AMOAND_D, AMOOR_D, AMOMIN_D, AMOMAX_D, AMOMINU_D, + AMOMAXU_D, FLW, FSW, FMADD_S, FMSUB_S, FNMADD_S, FNMSUB_S, FADD_S, FSUB_S, + FMUL_S, FDIV_S, FSQRT_S, FSGNJ_S, FSGNJN_S, FSGNJX_S, FMIN_S, FMAX_S, + FCVT_W_S, FCVT_WU_S, FMV_X_W, FEQ_S, FLT_S, FLE_S, FCLASS_S, FCVT_S_W, + FCVT_S_WU, FMV_W_X, FCVT_L_S, FCVT_LU_S, FCVT_S_L, FCVT_S_LU, FLD, FSD, + FMADD_D, FMSUB_D, FNMSUB_D, FNMADD_D, FADD_D, FSUB_D, FMUL_D, FDIV_D, + FSQRT_D, FSGNJ_D, FSGNJN_D, FSGNJX_D, FMIN_D, FMAX_D, FCVT_S_D, FCVT_D_S, + FEQ_D, FLT_D, FLE_D, FCLASS_D, FCVT_W_D, FCVT_WU_D, FCVT_D_W, FCVT_D_WU, + FCVT_L_D, FCVT_LU_D, FMV_X_D, FCVT_D_L, FCVT_D_LU, FMV_D_X, INVALID, EBREAK, + RESERVED, HINT, NOP>; + +constexpr uint8_t RV32 = 1; +constexpr uint8_t RV64 = 2; +constexpr uint8_t RV128 = 4; + +struct InstrPattern { + const char *name; + /// Bit mask to check the type of a instruction (B-Type, I-Type, J-Type, etc.) + uint32_t type_mask; + /// Characteristic value after bitwise-and with type_mask. + uint32_t eigen; + RISCVInst (*decode)(uint32_t inst); + /// If not specified, the inst will be supported by all RV versions. + uint8_t inst_type = RV32 | RV64 | RV128; +}; + +struct DecodeResult { + RISCVInst decoded; + uint32_t inst; + bool is_rvc; + InstrPattern pattern; +}; + +constexpr uint32_t DecodeRD(uint32_t inst) { return (inst & 0xF80) >> 7; } +constexpr uint32_t DecodeRS1(uint32_t inst) { return (inst & 0xF8000) >> 15; } +constexpr uint32_t DecodeRS2(uint32_t inst) { return (inst & 0x1F00000) >> 20; } +constexpr uint32_t DecodeRS3(uint32_t inst) { + return (inst & 0xF0000000) >> 27; +} +constexpr uint32_t DecodeFunct3(uint32_t inst) { return (inst & 0x7000) >> 12; } +constexpr uint32_t DecodeFunct2(uint32_t inst) { + return (inst & 0xE000000) >> 25; +} +constexpr uint32_t DecodeFunct7(uint32_t inst) { + return (inst & 0xFE000000) >> 25; +} + +constexpr int32_t DecodeRM(uint32_t inst) { return DecodeFunct3(inst); } + +/// RISC-V spec: The upper bits of a valid NaN-boxed value must be all 1s. +constexpr uint64_t NanBoxing(uint64_t val) { + return val | 0xFFFF'FFFF'0000'0000; +} +constexpr uint32_t NanUnBoxing(uint64_t val) { + return val & (~0xFFFF'FFFF'0000'0000); +} + +#undef R_TYPE_INST +#undef R_SHAMT_TYPE_INST +#undef R_RS1_TYPE_INST +#undef R4_TYPE_INST +#undef I_TYPE_INST +#undef S_TYPE_INST +#undef B_TYPE_INST +#undef U_TYPE_INST +#undef J_TYPE_INST +#undef INVALID_INST +#undef DERIVE_EQ + +} // namespace lldb_private +#endif // LLDB_SOURCE_PLUGINS_INSTRUCTION_RISCV_RISCVINSTRUCTION_H diff --git a/contrib/llvm-project/lldb/source/Plugins/InstrumentationRuntime/ASan/InstrumentationRuntimeASan.cpp b/contrib/llvm-project/lldb/source/Plugins/InstrumentationRuntime/ASan/InstrumentationRuntimeASan.cpp index 474611287311..72dfbd586622 100644 --- a/contrib/llvm-project/lldb/source/Plugins/InstrumentationRuntime/ASan/InstrumentationRuntimeASan.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/InstrumentationRuntime/ASan/InstrumentationRuntimeASan.cpp @@ -299,14 +299,15 @@ void InstrumentationRuntimeASan::Activate() { if (symbol_address == LLDB_INVALID_ADDRESS) return; - bool internal = true; - bool hardware = false; + const bool internal = true; + const bool hardware = false; + const bool sync = false; Breakpoint *breakpoint = process_sp->GetTarget() .CreateBreakpoint(symbol_address, internal, hardware) .get(); breakpoint->SetCallback(InstrumentationRuntimeASan::NotifyBreakpointHit, this, - true); + sync); breakpoint->SetBreakpointKind("address-sanitizer-report"); SetBreakpointID(breakpoint->GetID()); diff --git a/contrib/llvm-project/lldb/source/Plugins/InstrumentationRuntime/MainThreadChecker/InstrumentationRuntimeMainThreadChecker.cpp b/contrib/llvm-project/lldb/source/Plugins/InstrumentationRuntime/MainThreadChecker/InstrumentationRuntimeMainThreadChecker.cpp index a5c23615309d..e22cc86116ce 100644 --- a/contrib/llvm-project/lldb/source/Plugins/InstrumentationRuntime/MainThreadChecker/InstrumentationRuntimeMainThreadChecker.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/InstrumentationRuntime/MainThreadChecker/InstrumentationRuntimeMainThreadChecker.cpp @@ -214,8 +214,9 @@ void InstrumentationRuntimeMainThreadChecker::Activate() { .CreateBreakpoint(symbol_address, /*internal=*/true, /*hardware=*/false) .get(); + const bool sync = false; breakpoint->SetCallback( - InstrumentationRuntimeMainThreadChecker::NotifyBreakpointHit, this, true); + InstrumentationRuntimeMainThreadChecker::NotifyBreakpointHit, this, sync); breakpoint->SetBreakpointKind("main-thread-checker-report"); SetBreakpointID(breakpoint->GetID()); diff --git a/contrib/llvm-project/lldb/source/Plugins/InstrumentationRuntime/TSan/InstrumentationRuntimeTSan.cpp b/contrib/llvm-project/lldb/source/Plugins/InstrumentationRuntime/TSan/InstrumentationRuntimeTSan.cpp index 55ef3d245411..425b0baa453f 100644 --- a/contrib/llvm-project/lldb/source/Plugins/InstrumentationRuntime/TSan/InstrumentationRuntimeTSan.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/InstrumentationRuntime/TSan/InstrumentationRuntimeTSan.cpp @@ -206,10 +206,10 @@ for (int i = 0; i < t.unique_tid_count; i++) { t; )"; -static StructuredData::Array * +static StructuredData::ArraySP CreateStackTrace(ValueObjectSP o, const std::string &trace_item_name = ".trace") { - StructuredData::Array *trace = new StructuredData::Array(); + auto trace_sp = std::make_shared<StructuredData::Array>(); ValueObjectSP trace_value_object = o->GetValueForExpressionPath(trace_item_name.c_str()); size_t count = trace_value_object->GetNumChildren(); @@ -218,18 +218,18 @@ CreateStackTrace(ValueObjectSP o, trace_value_object->GetChildAtIndex(j, true)->GetValueAsUnsigned(0); if (trace_addr == 0) break; - trace->AddItem( - StructuredData::ObjectSP(new StructuredData::Integer(trace_addr))); + trace_sp->AddItem(std::make_shared<StructuredData::Integer>(trace_addr)); } - return trace; + return trace_sp; } -static StructuredData::Array *ConvertToStructuredArray( +static StructuredData::ArraySP ConvertToStructuredArray( ValueObjectSP return_value_sp, const std::string &items_name, const std::string &count_name, - std::function<void(ValueObjectSP o, StructuredData::Dictionary *dict)> const + std::function<void(const ValueObjectSP &o, + const StructuredData::DictionarySP &dict)> const &callback) { - StructuredData::Array *array = new StructuredData::Array(); + auto array_sp = std::make_shared<StructuredData::Array>(); unsigned int count = return_value_sp->GetValueForExpressionPath(count_name.c_str()) ->GetValueAsUnsigned(0); @@ -237,13 +237,13 @@ static StructuredData::Array *ConvertToStructuredArray( return_value_sp->GetValueForExpressionPath(items_name.c_str()); for (unsigned int i = 0; i < count; i++) { ValueObjectSP o = objects->GetChildAtIndex(i, true); - StructuredData::Dictionary *dict = new StructuredData::Dictionary(); + auto dict_sp = std::make_shared<StructuredData::Dictionary>(); - callback(o, dict); + callback(o, dict_sp); - array->AddItem(StructuredData::ObjectSP(dict)); + array_sp->AddItem(dict_sp); } - return array; + return array_sp; } static std::string RetrieveString(ValueObjectSP return_value_sp, @@ -263,8 +263,8 @@ GetRenumberedThreadIds(ProcessSP process_sp, ValueObjectSP data, std::map<uint64_t, user_id_t> &thread_id_map) { ConvertToStructuredArray( data, ".threads", ".thread_count", - [process_sp, &thread_id_map](ValueObjectSP o, - StructuredData::Dictionary *dict) { + [process_sp, &thread_id_map](const ValueObjectSP &o, + const StructuredData::DictionarySP &dict) { uint64_t thread_id = o->GetValueForExpressionPath(".tid")->GetValueAsUnsigned(0); uint64_t thread_os_id = @@ -338,31 +338,33 @@ StructuredData::ObjectSP InstrumentationRuntimeTSan::RetrieveReportData( std::map<uint64_t, user_id_t> thread_id_map; GetRenumberedThreadIds(process_sp, main_value, thread_id_map); - StructuredData::Dictionary *dict = new StructuredData::Dictionary(); + auto dict = std::make_shared<StructuredData::Dictionary>(); dict->AddStringItem("instrumentation_class", "ThreadSanitizer"); dict->AddStringItem("issue_type", RetrieveString(main_value, process_sp, ".description")); dict->AddIntegerItem("report_count", main_value->GetValueForExpressionPath(".report_count") ->GetValueAsUnsigned(0)); - dict->AddItem("sleep_trace", StructuredData::ObjectSP(CreateStackTrace( - main_value, ".sleep_trace"))); + dict->AddItem("sleep_trace", CreateStackTrace( + main_value, ".sleep_trace")); - StructuredData::Array *stacks = ConvertToStructuredArray( + StructuredData::ArraySP stacks = ConvertToStructuredArray( main_value, ".stacks", ".stack_count", - [thread_sp](ValueObjectSP o, StructuredData::Dictionary *dict) { + [thread_sp](const ValueObjectSP &o, + const StructuredData::DictionarySP &dict) { dict->AddIntegerItem( "index", o->GetValueForExpressionPath(".idx")->GetValueAsUnsigned(0)); - dict->AddItem("trace", StructuredData::ObjectSP(CreateStackTrace(o))); + dict->AddItem("trace", CreateStackTrace(o)); // "stacks" happen on the current thread dict->AddIntegerItem("thread_id", thread_sp->GetIndexID()); }); - dict->AddItem("stacks", StructuredData::ObjectSP(stacks)); + dict->AddItem("stacks", stacks); - StructuredData::Array *mops = ConvertToStructuredArray( + StructuredData::ArraySP mops = ConvertToStructuredArray( main_value, ".mops", ".mop_count", - [&thread_id_map](ValueObjectSP o, StructuredData::Dictionary *dict) { + [&thread_id_map](const ValueObjectSP &o, + const StructuredData::DictionarySP &dict) { dict->AddIntegerItem( "index", o->GetValueForExpressionPath(".idx")->GetValueAsUnsigned(0)); @@ -383,14 +385,14 @@ StructuredData::ObjectSP InstrumentationRuntimeTSan::RetrieveReportData( dict->AddIntegerItem( "address", o->GetValueForExpressionPath(".addr")->GetValueAsUnsigned(0)); - dict->AddItem("trace", StructuredData::ObjectSP(CreateStackTrace(o))); + dict->AddItem("trace", CreateStackTrace(o)); }); - dict->AddItem("mops", StructuredData::ObjectSP(mops)); + dict->AddItem("mops", mops); - StructuredData::Array *locs = ConvertToStructuredArray( + StructuredData::ArraySP locs = ConvertToStructuredArray( main_value, ".locs", ".loc_count", - [process_sp, &thread_id_map](ValueObjectSP o, - StructuredData::Dictionary *dict) { + [process_sp, &thread_id_map](const ValueObjectSP &o, + const StructuredData::DictionarySP &dict) { dict->AddIntegerItem( "index", o->GetValueForExpressionPath(".idx")->GetValueAsUnsigned(0)); @@ -415,15 +417,15 @@ StructuredData::ObjectSP InstrumentationRuntimeTSan::RetrieveReportData( dict->AddIntegerItem("suppressable", o->GetValueForExpressionPath(".suppressable") ->GetValueAsUnsigned(0)); - dict->AddItem("trace", StructuredData::ObjectSP(CreateStackTrace(o))); + dict->AddItem("trace", CreateStackTrace(o)); dict->AddStringItem("object_type", RetrieveString(o, process_sp, ".object_type")); }); - dict->AddItem("locs", StructuredData::ObjectSP(locs)); + dict->AddItem("locs", locs); - StructuredData::Array *mutexes = ConvertToStructuredArray( + StructuredData::ArraySP mutexes = ConvertToStructuredArray( main_value, ".mutexes", ".mutex_count", - [](ValueObjectSP o, StructuredData::Dictionary *dict) { + [](const ValueObjectSP &o, const StructuredData::DictionarySP &dict) { dict->AddIntegerItem( "index", o->GetValueForExpressionPath(".idx")->GetValueAsUnsigned(0)); @@ -436,14 +438,14 @@ StructuredData::ObjectSP InstrumentationRuntimeTSan::RetrieveReportData( dict->AddIntegerItem( "destroyed", o->GetValueForExpressionPath(".destroyed")->GetValueAsUnsigned(0)); - dict->AddItem("trace", StructuredData::ObjectSP(CreateStackTrace(o))); + dict->AddItem("trace", CreateStackTrace(o)); }); - dict->AddItem("mutexes", StructuredData::ObjectSP(mutexes)); + dict->AddItem("mutexes", mutexes); - StructuredData::Array *threads = ConvertToStructuredArray( + StructuredData::ArraySP threads = ConvertToStructuredArray( main_value, ".threads", ".thread_count", - [process_sp, &thread_id_map](ValueObjectSP o, - StructuredData::Dictionary *dict) { + [process_sp, &thread_id_map](const ValueObjectSP &o, + const StructuredData::DictionarySP &dict) { dict->AddIntegerItem( "index", o->GetValueForExpressionPath(".idx")->GetValueAsUnsigned(0)); @@ -464,13 +466,14 @@ StructuredData::ObjectSP InstrumentationRuntimeTSan::RetrieveReportData( Renumber(o->GetValueForExpressionPath(".parent_tid") ->GetValueAsUnsigned(0), thread_id_map)); - dict->AddItem("trace", StructuredData::ObjectSP(CreateStackTrace(o))); + dict->AddItem("trace", CreateStackTrace(o)); }); - dict->AddItem("threads", StructuredData::ObjectSP(threads)); + dict->AddItem("threads", threads); - StructuredData::Array *unique_tids = ConvertToStructuredArray( + StructuredData::ArraySP unique_tids = ConvertToStructuredArray( main_value, ".unique_tids", ".unique_tid_count", - [&thread_id_map](ValueObjectSP o, StructuredData::Dictionary *dict) { + [&thread_id_map](const ValueObjectSP &o, + const StructuredData::DictionarySP &dict) { dict->AddIntegerItem( "index", o->GetValueForExpressionPath(".idx")->GetValueAsUnsigned(0)); @@ -480,9 +483,9 @@ StructuredData::ObjectSP InstrumentationRuntimeTSan::RetrieveReportData( o->GetValueForExpressionPath(".tid")->GetValueAsUnsigned(0), thread_id_map)); }); - dict->AddItem("unique_tids", StructuredData::ObjectSP(unique_tids)); + dict->AddItem("unique_tids", unique_tids); - return StructuredData::ObjectSP(dict); + return dict; } std::string @@ -912,14 +915,15 @@ void InstrumentationRuntimeTSan::Activate() { if (symbol_address == LLDB_INVALID_ADDRESS) return; - bool internal = true; - bool hardware = false; + const bool internal = true; + const bool hardware = false; + const bool sync = false; Breakpoint *breakpoint = process_sp->GetTarget() .CreateBreakpoint(symbol_address, internal, hardware) .get(); breakpoint->SetCallback(InstrumentationRuntimeTSan::NotifyBreakpointHit, this, - true); + sync); breakpoint->SetBreakpointKind("thread-sanitizer-report"); SetBreakpointID(breakpoint->GetID()); @@ -1030,9 +1034,8 @@ static void AddThreadsForPath(const std::string &path, o->GetObjectForDotSeparatedPath("thread_os_id"); tid_t tid = thread_id_obj ? thread_id_obj->GetIntegerValue() : 0; - HistoryThread *history_thread = - new HistoryThread(*process_sp, tid, pcs); - ThreadSP new_thread_sp(history_thread); + ThreadSP new_thread_sp = + std::make_shared<HistoryThread>(*process_sp, tid, pcs); new_thread_sp->SetName(GenerateThreadName(path, o, info).c_str()); // Save this in the Process' ExtendedThreadList so a strong pointer @@ -1047,8 +1050,8 @@ static void AddThreadsForPath(const std::string &path, lldb::ThreadCollectionSP InstrumentationRuntimeTSan::GetBacktracesFromExtendedStopInfo( StructuredData::ObjectSP info) { - ThreadCollectionSP threads; - threads = std::make_shared<ThreadCollection>(); + + ThreadCollectionSP threads = std::make_shared<ThreadCollection>(); if (info->GetObjectForDotSeparatedPath("instrumentation_class") ->GetStringValue() != "ThreadSanitizer") diff --git a/contrib/llvm-project/lldb/source/Plugins/InstrumentationRuntime/UBSan/InstrumentationRuntimeUBSan.cpp b/contrib/llvm-project/lldb/source/Plugins/InstrumentationRuntime/UBSan/InstrumentationRuntimeUBSan.cpp index 5544c5f08f3b..7ea8b4697d20 100644 --- a/contrib/llvm-project/lldb/source/Plugins/InstrumentationRuntime/UBSan/InstrumentationRuntimeUBSan.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/InstrumentationRuntime/UBSan/InstrumentationRuntimeUBSan.cpp @@ -275,8 +275,9 @@ void InstrumentationRuntimeUBSan::Activate() { .CreateBreakpoint(symbol_address, /*internal=*/true, /*hardware=*/false) .get(); + const bool sync = false; breakpoint->SetCallback(InstrumentationRuntimeUBSan::NotifyBreakpointHit, - this, true); + this, sync); breakpoint->SetBreakpointKind("undefined-behavior-sanitizer-report"); SetBreakpointID(breakpoint->GetID()); diff --git a/contrib/llvm-project/lldb/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp b/contrib/llvm-project/lldb/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp index 13633e8261e4..c78804f98b09 100644 --- a/contrib/llvm-project/lldb/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp @@ -55,7 +55,6 @@ template <typename ptr_t> struct jit_descriptor { }; namespace { - enum EnableJITLoaderGDB { eEnableJITLoaderGDBDefault, eEnableJITLoaderGDBOn, @@ -107,6 +106,7 @@ public: g_jitloadergdb_properties[ePropertyEnable].default_uint_value); } }; +} // namespace static PluginProperties &GetGlobalPluginProperties() { static PluginProperties g_settings; @@ -114,8 +114,8 @@ static PluginProperties &GetGlobalPluginProperties() { } template <typename ptr_t> -bool ReadJITEntry(const addr_t from_addr, Process *process, - jit_code_entry<ptr_t> *entry) { +static bool ReadJITEntry(const addr_t from_addr, Process *process, + jit_code_entry<ptr_t> *entry) { lldbassert(from_addr % sizeof(ptr_t) == 0); ArchSpec::Core core = process->GetTarget().GetArchitecture().GetCore(); @@ -144,8 +144,6 @@ bool ReadJITEntry(const addr_t from_addr, Process *process, return true; } -} // anonymous namespace end - JITLoaderGDB::JITLoaderGDB(lldb_private::Process *process) : JITLoader(process), m_jit_objects(), m_jit_break_id(LLDB_INVALID_BREAK_ID), @@ -194,7 +192,7 @@ void JITLoaderGDB::SetJITBreakpoint(lldb_private::ModuleList &module_list) { __FUNCTION__); addr_t jit_addr = GetSymbolAddress( - module_list, ConstString("__jit_debug_register_code"), eSymbolTypeAny); + module_list, ConstString("__jit_debug_register_code"), eSymbolTypeCode); if (jit_addr == LLDB_INVALID_ADDRESS) return; diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/BlockPointer.cpp b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/BlockPointer.cpp index 1b3cf1ec0987..40ffe9673792 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/BlockPointer.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/BlockPointer.cpp @@ -49,8 +49,10 @@ public: return; } - TypeSystemClang *clang_ast_context = - llvm::cast<TypeSystemClang>(block_pointer_type.GetTypeSystem()); + auto ts = block_pointer_type.GetTypeSystem(); + auto clang_ast_context = ts.dyn_cast_or_null<TypeSystemClang>(); + if (!clang_ast_context) + return; std::shared_ptr<ClangASTImporter> clang_ast_importer; auto *state = target_sp->GetPersistentExpressionStateForLanguage( diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp index 23ce1654fb83..1b152c16eac2 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp @@ -23,11 +23,13 @@ #include "lldb/Core/Module.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/UniqueCStringMap.h" +#include "lldb/Core/ValueObjectVariable.h" #include "lldb/DataFormatters/CXXFunctionPointer.h" #include "lldb/DataFormatters/DataVisualization.h" #include "lldb/DataFormatters/FormattersHelpers.h" #include "lldb/DataFormatters/VectorType.h" #include "lldb/Symbol/SymbolFile.h" +#include "lldb/Symbol/VariableList.h" #include "lldb/Utility/ConstString.h" #include "lldb/Utility/LLDBLog.h" #include "lldb/Utility/Log.h" @@ -35,6 +37,7 @@ #include "BlockPointer.h" #include "CPlusPlusNameParser.h" +#include "Coroutines.h" #include "CxxStringTypes.h" #include "Generic.h" #include "LibCxx.h" @@ -108,6 +111,7 @@ void CPlusPlusLanguage::MethodName::Clear() { m_context = llvm::StringRef(); m_arguments = llvm::StringRef(); m_qualifiers = llvm::StringRef(); + m_return_type = llvm::StringRef(); m_parsed = false; m_parse_error = false; } @@ -169,6 +173,40 @@ static bool IsTrivialBasename(const llvm::StringRef &basename) { return idx == basename.size(); } +/// Writes out the function name in 'full_name' to 'out_stream' +/// but replaces each argument type with the variable name +/// and the corresponding pretty-printed value +static bool PrettyPrintFunctionNameWithArgs(Stream &out_stream, + char const *full_name, + ExecutionContextScope *exe_scope, + VariableList const &args) { + CPlusPlusLanguage::MethodName cpp_method{ConstString(full_name)}; + + if (!cpp_method.IsValid()) + return false; + + llvm::StringRef return_type = cpp_method.GetReturnType(); + if (!return_type.empty()) { + out_stream.PutCString(return_type); + out_stream.PutChar(' '); + } + + out_stream.PutCString(cpp_method.GetScopeQualifiedName()); + out_stream.PutChar('('); + + FormatEntity::PrettyPrintFunctionArguments(out_stream, args, exe_scope); + + out_stream.PutChar(')'); + + llvm::StringRef qualifiers = cpp_method.GetQualifiers(); + if (!qualifiers.empty()) { + out_stream.PutChar(' '); + out_stream.PutCString(qualifiers); + } + + return true; +} + bool CPlusPlusLanguage::MethodName::TrySimplifiedParse() { // This method tries to parse simple method definitions which are presumably // most comman in user programs. Definitions that can be parsed by this @@ -205,6 +243,7 @@ bool CPlusPlusLanguage::MethodName::TrySimplifiedParse() { m_basename = llvm::StringRef(); m_arguments = llvm::StringRef(); m_qualifiers = llvm::StringRef(); + m_return_type = llvm::StringRef(); return false; } } @@ -218,10 +257,11 @@ void CPlusPlusLanguage::MethodName::Parse() { } else { CPlusPlusNameParser parser(m_full.GetStringRef()); if (auto function = parser.ParseAsFunctionDefinition()) { - m_basename = function.value().name.basename; - m_context = function.value().name.context; - m_arguments = function.value().arguments; - m_qualifiers = function.value().qualifiers; + m_basename = function->name.basename; + m_context = function->name.context; + m_arguments = function->arguments; + m_qualifiers = function->qualifiers; + m_return_type = function->return_type; m_parse_error = false; } else { m_parse_error = true; @@ -255,6 +295,12 @@ llvm::StringRef CPlusPlusLanguage::MethodName::GetQualifiers() { return m_qualifiers; } +llvm::StringRef CPlusPlusLanguage::MethodName::GetReturnType() { + if (!m_parsed) + Parse(); + return m_return_type; +} + std::string CPlusPlusLanguage::MethodName::GetScopeQualifiedName() { if (!m_parsed) Parse(); @@ -268,9 +314,21 @@ std::string CPlusPlusLanguage::MethodName::GetScopeQualifiedName() { return res; } +llvm::StringRef +CPlusPlusLanguage::MethodName::GetBasenameNoTemplateParameters() { + llvm::StringRef basename = GetBasename(); + size_t arg_start, arg_end; + llvm::StringRef parens("<>", 2); + if (ReverseFindMatchingChars(basename, parens, arg_start, arg_end)) + return basename.substr(0, arg_start); + + return basename; +} + bool CPlusPlusLanguage::MethodName::ContainsPath(llvm::StringRef path) { if (!m_parsed) Parse(); + // If we can't parse the incoming name, then just check that it contains path. if (m_parse_error) return m_full.GetStringRef().contains(path); @@ -285,8 +343,23 @@ bool CPlusPlusLanguage::MethodName::ContainsPath(llvm::StringRef path) { if (!success) return m_full.GetStringRef().contains(path); - if (identifier != GetBasename()) + // Basename may include template arguments. + // E.g., + // GetBaseName(): func<int> + // identifier : func + // + // ...but we still want to account for identifiers with template parameter + // lists, e.g., when users set breakpoints on template specializations. + // + // E.g., + // GetBaseName(): func<uint32_t> + // identifier : func<int32_t*> + // + // Try to match the basename with or without template parameters. + if (GetBasename() != identifier && + GetBasenameNoTemplateParameters() != identifier) return false; + // Incoming path only had an identifier, so we match. if (context.empty()) return true; @@ -329,8 +402,8 @@ bool CPlusPlusLanguage::ExtractContextAndIdentifier( CPlusPlusNameParser parser(name); if (auto full_name = parser.ParseAsFullName()) { - identifier = full_name.value().basename; - context = full_name.value().context; + identifier = full_name->basename; + context = full_name->context; return true; } return false; @@ -762,9 +835,15 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { "libc++ std::span synthetic children", ConstString("^std::__[[:alnum:]]+::span<.+>(( )?&)?$"), stl_deref_flags, true); + AddCXXSynthetic( + cpp_category_sp, + lldb_private::formatters::LibcxxStdRangesRefViewSyntheticFrontEndCreator, + "libc++ std::ranges::ref_view synthetic children", + ConstString("^std::__[[:alnum:]]+::ranges::ref_view<.+>(( )?&)?$"), + stl_deref_flags, true); - cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add( - RegularExpression("^(std::__[[:alnum:]]+::)deque<.+>(( )?&)?$"), + cpp_category_sp->AddTypeSynthetic( + "^(std::__[[:alnum:]]+::)deque<.+>(( )?&)?$", eFormatterMatchRegex, SyntheticChildrenSP(new ScriptedSyntheticChildren( stl_synth_flags, "lldb.formatters.cpp.libcxx.stddeque_SynthProvider"))); @@ -796,6 +875,14 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { ConstString("^std::__[[:alnum:]]+::function<.+>$"), stl_summary_flags, true); + ConstString libcxx_std_coroutine_handle_regex( + "^std::__[[:alnum:]]+::coroutine_handle<.+>(( )?&)?$"); + AddCXXSynthetic( + cpp_category_sp, + lldb_private::formatters::StdlibCoroutineHandleSyntheticFrontEndCreator, + "coroutine_handle synthetic children", libcxx_std_coroutine_handle_regex, + stl_deref_flags, true); + stl_summary_flags.SetDontShowChildren(false); stl_summary_flags.SetSkipPointers(false); AddCXXSummary(cpp_category_sp, @@ -898,6 +985,11 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { "libc++ std::unique_ptr summary provider", libcxx_std_unique_ptr_regex, stl_summary_flags, true); + AddCXXSummary(cpp_category_sp, + lldb_private::formatters::StdlibCoroutineHandleSummaryProvider, + "libc++ std::coroutine_handle summary provider", + libcxx_std_coroutine_handle_regex, stl_summary_flags, true); + AddCXXSynthetic( cpp_category_sp, lldb_private::formatters::LibCxxVectorIteratorSyntheticFrontEndCreator, @@ -944,55 +1036,52 @@ static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { stl_summary_flags, LibStdcppWStringSummaryProvider, "libstdc++ c++11 std::wstring summary provider")); - cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::string"), - std_string_summary_sp); - cpp_category_sp->GetTypeSummariesContainer()->Add( - ConstString("std::basic_string<char>"), std_string_summary_sp); - cpp_category_sp->GetTypeSummariesContainer()->Add( - ConstString("std::basic_string<char,std::char_traits<char>,std::" - "allocator<char> >"), - std_string_summary_sp); - cpp_category_sp->GetTypeSummariesContainer()->Add( - ConstString("std::basic_string<char, std::char_traits<char>, " - "std::allocator<char> >"), - std_string_summary_sp); - - cpp_category_sp->GetTypeSummariesContainer()->Add( - ConstString("std::__cxx11::string"), cxx11_string_summary_sp); - cpp_category_sp->GetTypeSummariesContainer()->Add( - ConstString("std::__cxx11::basic_string<char, std::char_traits<char>, " - "std::allocator<char> >"), - cxx11_string_summary_sp); - cpp_category_sp->GetTypeSummariesContainer()->Add( - ConstString("std::__cxx11::basic_string<unsigned char, " - "std::char_traits<unsigned char>, " - "std::allocator<unsigned char> >"), - cxx11_string_summary_sp); + cpp_category_sp->AddTypeSummary("std::string", eFormatterMatchExact, + std_string_summary_sp); + cpp_category_sp->AddTypeSummary("std::basic_string<char>", + eFormatterMatchRegex, std_string_summary_sp); + cpp_category_sp->AddTypeSummary( + "std::basic_string<char,std::char_traits<char>,std::allocator<char> >", + eFormatterMatchExact, std_string_summary_sp); + cpp_category_sp->AddTypeSummary( + "std::basic_string<char, std::char_traits<char>, std::allocator<char> >", + eFormatterMatchExact, std_string_summary_sp); + + cpp_category_sp->AddTypeSummary("std::__cxx11::string", eFormatterMatchExact, + cxx11_string_summary_sp); + cpp_category_sp->AddTypeSummary( + "std::__cxx11::basic_string<char, std::char_traits<char>, " + "std::allocator<char> >", + eFormatterMatchExact, cxx11_string_summary_sp); + cpp_category_sp->AddTypeSummary("std::__cxx11::basic_string<unsigned char, " + "std::char_traits<unsigned char>, " + "std::allocator<unsigned char> >", + eFormatterMatchExact, + cxx11_string_summary_sp); // making sure we force-pick the summary for printing wstring (_M_p is a // wchar_t*) lldb::TypeSummaryImplSP std_wstring_summary_sp( new StringSummaryFormat(stl_summary_flags, "${var._M_dataplus._M_p%S}")); - cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::wstring"), - std_wstring_summary_sp); - cpp_category_sp->GetTypeSummariesContainer()->Add( - ConstString("std::basic_string<wchar_t>"), std_wstring_summary_sp); - cpp_category_sp->GetTypeSummariesContainer()->Add( - ConstString("std::basic_string<wchar_t,std::char_traits<wchar_t>,std::" - "allocator<wchar_t> >"), - std_wstring_summary_sp); - cpp_category_sp->GetTypeSummariesContainer()->Add( - ConstString("std::basic_string<wchar_t, std::char_traits<wchar_t>, " - "std::allocator<wchar_t> >"), - std_wstring_summary_sp); - - cpp_category_sp->GetTypeSummariesContainer()->Add( - ConstString("std::__cxx11::wstring"), cxx11_wstring_summary_sp); - cpp_category_sp->GetTypeSummariesContainer()->Add( - ConstString("std::__cxx11::basic_string<wchar_t, " - "std::char_traits<wchar_t>, std::allocator<wchar_t> >"), - cxx11_wstring_summary_sp); + cpp_category_sp->AddTypeSummary("std::wstring", eFormatterMatchExact, + std_wstring_summary_sp); + cpp_category_sp->AddTypeSummary("std::basic_string<wchar_t>", + eFormatterMatchExact, std_wstring_summary_sp); + cpp_category_sp->AddTypeSummary("std::basic_string<wchar_t,std::char_traits<" + "wchar_t>,std::allocator<wchar_t> >", + eFormatterMatchExact, std_wstring_summary_sp); + cpp_category_sp->AddTypeSummary( + "std::basic_string<wchar_t, std::char_traits<wchar_t>, " + "std::allocator<wchar_t> >", + eFormatterMatchExact, std_wstring_summary_sp); + + cpp_category_sp->AddTypeSummary("std::__cxx11::wstring", eFormatterMatchExact, + cxx11_wstring_summary_sp); + cpp_category_sp->AddTypeSummary( + "std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, " + "std::allocator<wchar_t> >", + eFormatterMatchExact, cxx11_wstring_summary_sp); SyntheticChildren::Flags stl_synth_flags; stl_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences( @@ -1000,94 +1089,95 @@ static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { SyntheticChildren::Flags stl_deref_flags = stl_synth_flags; stl_deref_flags.SetFrontEndWantsDereference(); - cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add( - RegularExpression("^std::vector<.+>(( )?&)?$"), + cpp_category_sp->AddTypeSynthetic( + "^std::vector<.+>(( )?&)?$", eFormatterMatchRegex, SyntheticChildrenSP(new ScriptedSyntheticChildren( stl_synth_flags, "lldb.formatters.cpp.gnu_libstdcpp.StdVectorSynthProvider"))); - cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add( - RegularExpression("^std::map<.+> >(( )?&)?$"), + cpp_category_sp->AddTypeSynthetic( + "^std::map<.+> >(( )?&)?$", eFormatterMatchRegex, SyntheticChildrenSP(new ScriptedSyntheticChildren( stl_synth_flags, "lldb.formatters.cpp.gnu_libstdcpp.StdMapLikeSynthProvider"))); - cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add( - RegularExpression("^std::deque<.+>(( )?&)?$"), + cpp_category_sp->AddTypeSynthetic( + "^std::deque<.+>(( )?&)?$", eFormatterMatchRegex, SyntheticChildrenSP(new ScriptedSyntheticChildren( stl_deref_flags, "lldb.formatters.cpp.gnu_libstdcpp.StdDequeSynthProvider"))); - cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add( - RegularExpression("^std::set<.+> >(( )?&)?$"), + cpp_category_sp->AddTypeSynthetic( + "^std::set<.+> >(( )?&)?$", eFormatterMatchRegex, SyntheticChildrenSP(new ScriptedSyntheticChildren( stl_deref_flags, "lldb.formatters.cpp.gnu_libstdcpp.StdMapLikeSynthProvider"))); - cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add( - RegularExpression("^std::multimap<.+> >(( )?&)?$"), + cpp_category_sp->AddTypeSynthetic( + "^std::multimap<.+> >(( )?&)?$", eFormatterMatchRegex, SyntheticChildrenSP(new ScriptedSyntheticChildren( stl_deref_flags, "lldb.formatters.cpp.gnu_libstdcpp.StdMapLikeSynthProvider"))); - cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add( - RegularExpression("^std::multiset<.+> >(( )?&)?$"), + cpp_category_sp->AddTypeSynthetic( + "^std::multiset<.+> >(( )?&)?$", eFormatterMatchRegex, SyntheticChildrenSP(new ScriptedSyntheticChildren( stl_deref_flags, "lldb.formatters.cpp.gnu_libstdcpp.StdMapLikeSynthProvider"))); - cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add( - RegularExpression("^std::unordered_(multi)?(map|set)<.+> >$"), + cpp_category_sp->AddTypeSynthetic( + "^std::unordered_(multi)?(map|set)<.+> >$", eFormatterMatchRegex, SyntheticChildrenSP(new ScriptedSyntheticChildren( stl_deref_flags, "lldb.formatters.cpp.gnu_libstdcpp.StdUnorderedMapSynthProvider"))); - cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add( - RegularExpression("^std::(__cxx11::)?list<.+>(( )?&)?$"), + cpp_category_sp->AddTypeSynthetic( + "^std::(__cxx11::)?list<.+>(( )?&)?$", eFormatterMatchRegex, SyntheticChildrenSP(new ScriptedSyntheticChildren( stl_deref_flags, "lldb.formatters.cpp.gnu_libstdcpp.StdListSynthProvider"))); - cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add( - RegularExpression("^std::(__cxx11::)?forward_list<.+>(( )?&)?$"), + cpp_category_sp->AddTypeSynthetic( + "^std::(__cxx11::)?forward_list<.+>(( )?&)?$", eFormatterMatchRegex, SyntheticChildrenSP(new ScriptedSyntheticChildren( stl_synth_flags, "lldb.formatters.cpp.gnu_libstdcpp.StdForwardListSynthProvider"))); stl_summary_flags.SetDontShowChildren(false); stl_summary_flags.SetSkipPointers(false); - cpp_category_sp->GetRegexTypeSummariesContainer()->Add( - RegularExpression("^std::bitset<.+>(( )?&)?$"), - TypeSummaryImplSP( - new StringSummaryFormat(stl_summary_flags, "size=${svar%#}"))); - cpp_category_sp->GetRegexTypeSummariesContainer()->Add( - RegularExpression("^std::vector<.+>(( )?&)?$"), - TypeSummaryImplSP( - new StringSummaryFormat(stl_summary_flags, "size=${svar%#}"))); - cpp_category_sp->GetRegexTypeSummariesContainer()->Add( - RegularExpression("^std::map<.+> >(( )?&)?$"), - TypeSummaryImplSP( - new StringSummaryFormat(stl_summary_flags, "size=${svar%#}"))); - cpp_category_sp->GetRegexTypeSummariesContainer()->Add( - RegularExpression("^std::set<.+> >(( )?&)?$"), - TypeSummaryImplSP( - new StringSummaryFormat(stl_summary_flags, "size=${svar%#}"))); - cpp_category_sp->GetRegexTypeSummariesContainer()->Add( - RegularExpression("^std::deque<.+>(( )?&)?$"), - TypeSummaryImplSP( - new StringSummaryFormat(stl_summary_flags, "size=${svar%#}"))); - cpp_category_sp->GetRegexTypeSummariesContainer()->Add( - RegularExpression("^std::multimap<.+> >(( )?&)?$"), - TypeSummaryImplSP( - new StringSummaryFormat(stl_summary_flags, "size=${svar%#}"))); - cpp_category_sp->GetRegexTypeSummariesContainer()->Add( - RegularExpression("^std::multiset<.+> >(( )?&)?$"), - TypeSummaryImplSP( - new StringSummaryFormat(stl_summary_flags, "size=${svar%#}"))); - cpp_category_sp->GetRegexTypeSummariesContainer()->Add( - RegularExpression("^std::unordered_(multi)?(map|set)<.+> >$"), - TypeSummaryImplSP( - new StringSummaryFormat(stl_summary_flags, "size=${svar%#}"))); - cpp_category_sp->GetRegexTypeSummariesContainer()->Add( - RegularExpression("^std::(__cxx11::)?list<.+>(( )?&)?$"), - TypeSummaryImplSP( - new StringSummaryFormat(stl_summary_flags, "size=${svar%#}"))); - cpp_category_sp->GetRegexTypeSummariesContainer()->Add( - RegularExpression("^std::(__cxx11::)?forward_list<.+>(( )?&)?$"), - TypeSummaryImplSP( - new ScriptSummaryFormat(stl_summary_flags, "lldb.formatters.cpp.gnu_libstdcpp.ForwardListSummaryProvider"))); + cpp_category_sp->AddTypeSummary("^std::bitset<.+>(( )?&)?$", + eFormatterMatchRegex, + TypeSummaryImplSP(new StringSummaryFormat( + stl_summary_flags, "size=${svar%#}"))); + cpp_category_sp->AddTypeSummary("^std::vector<.+>(( )?&)?$", + eFormatterMatchRegex, + TypeSummaryImplSP(new StringSummaryFormat( + stl_summary_flags, "size=${svar%#}"))); + cpp_category_sp->AddTypeSummary("^std::map<.+> >(( )?&)?$", + eFormatterMatchRegex, + TypeSummaryImplSP(new StringSummaryFormat( + stl_summary_flags, "size=${svar%#}"))); + cpp_category_sp->AddTypeSummary("^std::set<.+> >(( )?&)?$", + eFormatterMatchRegex, + TypeSummaryImplSP(new StringSummaryFormat( + stl_summary_flags, "size=${svar%#}"))); + cpp_category_sp->AddTypeSummary("^std::deque<.+>(( )?&)?$", + eFormatterMatchRegex, + TypeSummaryImplSP(new StringSummaryFormat( + stl_summary_flags, "size=${svar%#}"))); + cpp_category_sp->AddTypeSummary("^std::multimap<.+> >(( )?&)?$", + eFormatterMatchRegex, + TypeSummaryImplSP(new StringSummaryFormat( + stl_summary_flags, "size=${svar%#}"))); + cpp_category_sp->AddTypeSummary("^std::multiset<.+> >(( )?&)?$", + eFormatterMatchRegex, + TypeSummaryImplSP(new StringSummaryFormat( + stl_summary_flags, "size=${svar%#}"))); + cpp_category_sp->AddTypeSummary("^std::unordered_(multi)?(map|set)<.+> >$", + eFormatterMatchRegex, + TypeSummaryImplSP(new StringSummaryFormat( + stl_summary_flags, "size=${svar%#}"))); + cpp_category_sp->AddTypeSummary("^std::(__cxx11::)?list<.+>(( )?&)?$", + eFormatterMatchRegex, + TypeSummaryImplSP(new StringSummaryFormat( + stl_summary_flags, "size=${svar%#}"))); + cpp_category_sp->AddTypeSummary( + "^std::(__cxx11::)?forward_list<.+>(( )?&)?$", eFormatterMatchRegex, + TypeSummaryImplSP(new ScriptSummaryFormat( + stl_summary_flags, + "lldb.formatters.cpp.gnu_libstdcpp.ForwardListSummaryProvider"))); AddCXXSynthetic( cpp_category_sp, @@ -1122,6 +1212,14 @@ static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { "std::tuple synthetic children", ConstString("^std::tuple<.+>(( )?&)?$"), stl_synth_flags, true); + ConstString libstdcpp_std_coroutine_handle_regex( + "^std::coroutine_handle<.+>(( )?&)?$"); + AddCXXSynthetic( + cpp_category_sp, + lldb_private::formatters::StdlibCoroutineHandleSyntheticFrontEndCreator, + "std::coroutine_handle synthetic children", + libstdcpp_std_coroutine_handle_regex, stl_deref_flags, true); + AddCXXSynthetic( cpp_category_sp, lldb_private::formatters::LibStdcppBitsetSyntheticFrontEndCreator, @@ -1149,6 +1247,10 @@ static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { "libstdc++ std::weak_ptr summary provider", ConstString("^std::weak_ptr<.+>(( )?&)?$"), stl_summary_flags, true); + AddCXXSummary(cpp_category_sp, + lldb_private::formatters::StdlibCoroutineHandleSummaryProvider, + "libstdc++ std::coroutine_handle summary provider", + libstdcpp_std_coroutine_handle_regex, stl_summary_flags, true); AddCXXSummary( cpp_category_sp, lldb_private::formatters::GenericOptionalSummaryProvider, "libstd++ std::optional summary provider", @@ -1405,3 +1507,66 @@ bool CPlusPlusLanguage::IsSourceFile(llvm::StringRef file_path) const { // that we could check for. return file_path.contains("/usr/include/c++/"); } + +bool CPlusPlusLanguage::GetFunctionDisplayName( + const SymbolContext *sc, const ExecutionContext *exe_ctx, + FunctionNameRepresentation representation, Stream &s) { + switch (representation) { + case FunctionNameRepresentation::eNameWithArgs: { + // Print the function name with arguments in it + if (sc->function) { + ExecutionContextScope *exe_scope = + exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr; + const char *cstr = sc->function->GetName().AsCString(nullptr); + if (cstr) { + const InlineFunctionInfo *inline_info = nullptr; + VariableListSP variable_list_sp; + bool get_function_vars = true; + if (sc->block) { + Block *inline_block = sc->block->GetContainingInlinedBlock(); + + if (inline_block) { + get_function_vars = false; + inline_info = sc->block->GetInlinedFunctionInfo(); + if (inline_info) + variable_list_sp = inline_block->GetBlockVariableList(true); + } + } + + if (get_function_vars) { + variable_list_sp = + sc->function->GetBlock(true).GetBlockVariableList(true); + } + + if (inline_info) { + s.PutCString(cstr); + s.PutCString(" [inlined] "); + cstr = inline_info->GetName().GetCString(); + } + + VariableList args; + if (variable_list_sp) + variable_list_sp->AppendVariablesWithScope(eValueTypeVariableArgument, + args); + if (args.GetSize() > 0) { + if (!PrettyPrintFunctionNameWithArgs(s, cstr, exe_scope, args)) + return false; + } else { + s.PutCString(cstr); + } + return true; + } + } else if (sc->symbol) { + const char *cstr = sc->symbol->GetName().AsCString(nullptr); + if (cstr) { + s.PutCString(cstr); + return true; + } + } + } break; + default: + return false; + } + + return false; +} diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h index 53a01cfc4799..809996497c11 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h +++ b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h @@ -55,20 +55,42 @@ public: llvm::StringRef GetArguments(); llvm::StringRef GetQualifiers(); - + + /// Returns the methods return-type. + /// + /// Currently returns an empty llvm::StringRef + /// if the return-type is a function pointer. + llvm::StringRef GetReturnType(); + bool ContainsPath(llvm::StringRef path); + private: + /// Returns the Basename of this method without a template parameter + /// list, if any. + /// + // Examples: + // + // +--------------------------------+---------+ + // | MethodName | Returns | + // +--------------------------------+---------+ + // | void func() | func | + // | void func<int>() | func | + // | void func<std::vector<int>>() | func | + // +--------------------------------+---------+ + llvm::StringRef GetBasenameNoTemplateParameters(); + protected: void Parse(); bool TrySimplifiedParse(); ConstString m_full; // Full name: - // "lldb::SBTarget::GetBreakpointAtIndex(unsigned int) - // const" - llvm::StringRef m_basename; // Basename: "GetBreakpointAtIndex" - llvm::StringRef m_context; // Decl context: "lldb::SBTarget" - llvm::StringRef m_arguments; // Arguments: "(unsigned int)" - llvm::StringRef m_qualifiers; // Qualifiers: "const" + // "size_t lldb::SBTarget::GetBreakpointAtIndex(unsigned + // int) const" + llvm::StringRef m_basename; // Basename: "GetBreakpointAtIndex" + llvm::StringRef m_context; // Decl context: "lldb::SBTarget" + llvm::StringRef m_arguments; // Arguments: "(unsigned int)" + llvm::StringRef m_qualifiers; // Qualifiers: "const" + llvm::StringRef m_return_type; // Return type: "size_t" bool m_parsed = false; bool m_parse_error = false; }; @@ -114,6 +136,11 @@ public: ConstString GetDemangledFunctionNameWithoutArguments(Mangled mangled) const override; + bool GetFunctionDisplayName(const SymbolContext *sc, + const ExecutionContext *exe_ctx, + FunctionNameRepresentation representation, + Stream &s) override; + static bool IsCPPMangledName(llvm::StringRef name); // Extract C++ context and identifier from a string using heuristic matching diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.cpp b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.cpp index a9a4e98775d9..617181a35d1d 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.cpp @@ -9,20 +9,20 @@ #include "CPlusPlusNameParser.h" #include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/TokenKinds.h" #include "llvm/ADT/StringMap.h" #include "llvm/Support/Threading.h" +#include <optional> using namespace lldb; using namespace lldb_private; -using llvm::Optional; -using llvm::None; using ParsedFunction = lldb_private::CPlusPlusNameParser::ParsedFunction; using ParsedName = lldb_private::CPlusPlusNameParser::ParsedName; namespace tok = clang::tok; -Optional<ParsedFunction> CPlusPlusNameParser::ParseAsFunctionDefinition() { +std::optional<ParsedFunction> CPlusPlusNameParser::ParseAsFunctionDefinition() { m_next_token_index = 0; - Optional<ParsedFunction> result(None); + std::optional<ParsedFunction> result(std::nullopt); // Try to parse the name as function without a return type specified e.g. // main(int, char*[]) @@ -43,20 +43,20 @@ Optional<ParsedFunction> CPlusPlusNameParser::ParseAsFunctionDefinition() { // e.g. int main(int, char*[]) result = ParseFunctionImpl(true); if (HasMoreTokens()) - return None; + return std::nullopt; return result; } -Optional<ParsedName> CPlusPlusNameParser::ParseAsFullName() { +std::optional<ParsedName> CPlusPlusNameParser::ParseAsFullName() { m_next_token_index = 0; - Optional<ParsedNameRanges> name_ranges = ParseFullNameImpl(); + std::optional<ParsedNameRanges> name_ranges = ParseFullNameImpl(); if (!name_ranges) - return None; + return std::nullopt; if (HasMoreTokens()) - return None; + return std::nullopt; ParsedName result; - result.basename = GetTextForRange(name_ranges.value().basename_range); - result.context = GetTextForRange(name_ranges.value().context_range); + result.basename = GetTextForRange(name_ranges->basename_range); + result.context = GetTextForRange(name_ranges->context_range); return result; } @@ -101,52 +101,78 @@ clang::Token &CPlusPlusNameParser::Peek() { return m_tokens[m_next_token_index]; } -Optional<ParsedFunction> +std::optional<ParsedFunction> CPlusPlusNameParser::ParseFunctionImpl(bool expect_return_type) { Bookmark start_position = SetBookmark(); + + ParsedFunction result; if (expect_return_type) { + size_t return_start = GetCurrentPosition(); // Consume return type if it's expected. - if (!ConsumeTypename()) - return None; + if (!ConsumeToken(tok::kw_auto) && !ConsumeTypename()) + return std::nullopt; + + size_t return_end = GetCurrentPosition(); + result.return_type = GetTextForRange(Range(return_start, return_end)); } auto maybe_name = ParseFullNameImpl(); if (!maybe_name) { - return None; + return std::nullopt; } size_t argument_start = GetCurrentPosition(); if (!ConsumeArguments()) { - return None; + return std::nullopt; } size_t qualifiers_start = GetCurrentPosition(); SkipFunctionQualifiers(); size_t end_position = GetCurrentPosition(); - ParsedFunction result; - result.name.basename = GetTextForRange(maybe_name.value().basename_range); - result.name.context = GetTextForRange(maybe_name.value().context_range); + result.name.basename = GetTextForRange(maybe_name->basename_range); + result.name.context = GetTextForRange(maybe_name->context_range); result.arguments = GetTextForRange(Range(argument_start, qualifiers_start)); result.qualifiers = GetTextForRange(Range(qualifiers_start, end_position)); start_position.Remove(); return result; } -Optional<ParsedFunction> +std::optional<ParsedFunction> CPlusPlusNameParser::ParseFuncPtr(bool expect_return_type) { + // This function parses a function definition + // that returns a pointer type. + // E.g., double (*(*func(long))(int))(float) + + // Step 1: + // Remove the return type of the innermost + // function pointer type. + // + // Leaves us with: + // (*(*func(long))(int))(float) Bookmark start_position = SetBookmark(); if (expect_return_type) { // Consume return type. if (!ConsumeTypename()) - return None; + return std::nullopt; } + // Step 2: + // + // Skip a pointer and parenthesis pair. + // + // Leaves us with: + // (*func(long))(int))(float) if (!ConsumeToken(tok::l_paren)) - return None; + return std::nullopt; if (!ConsumePtrsAndRefs()) - return None; + return std::nullopt; + // Step 3: + // + // Consume inner function name. This will fail unless + // we stripped all the pointers on the left hand side + // of the funciton name. { Bookmark before_inner_function_pos = SetBookmark(); auto maybe_inner_function_name = ParseFunctionImpl(false); @@ -160,6 +186,24 @@ CPlusPlusNameParser::ParseFuncPtr(bool expect_return_type) { } } + // Step 4: + // + // Parse the remaining string as a function pointer again. + // This time don't consume the inner-most typename since + // we're left with pointers only. This will strip another + // layer of pointers until we're left with the innermost + // function name/argument. I.e., func(long))(int))(float) + // + // Once we successfully stripped all pointers and gotten + // the innermost function name from ParseFunctionImpl above, + // we consume a single ')' and the arguments '(...)' that follows. + // + // Leaves us with: + // )(float) + // + // This is the remnant of the outer function pointers' arguments. + // Unwinding the recursive calls will remove the remaining + // arguments. auto maybe_inner_function_ptr_name = ParseFuncPtr(false); if (maybe_inner_function_ptr_name) if (ConsumeToken(tok::r_paren)) @@ -168,7 +212,8 @@ CPlusPlusNameParser::ParseFuncPtr(bool expect_return_type) { start_position.Remove(); return maybe_inner_function_ptr_name; } - return None; + + return std::nullopt; } bool CPlusPlusNameParser::ConsumeArguments() { @@ -225,9 +270,15 @@ bool CPlusPlusNameParser::ConsumeTemplateArgs() { Advance(); break; case tok::l_square: - if (!ConsumeBrackets(tok::l_square, tok::r_square)) + // Handle templates tagged with an ABI tag. + // An example demangled/prettified version is: + // func[abi:tag1][abi:tag2]<type[abi:tag3]>(int) + if (ConsumeAbiTag()) + can_open_template = true; + else if (ConsumeBrackets(tok::l_square, tok::r_square)) + can_open_template = false; + else return false; - can_open_template = false; break; case tok::l_paren: if (!ConsumeArguments()) @@ -248,6 +299,32 @@ bool CPlusPlusNameParser::ConsumeTemplateArgs() { return true; } +bool CPlusPlusNameParser::ConsumeAbiTag() { + Bookmark start_position = SetBookmark(); + if (!ConsumeToken(tok::l_square)) + return false; + + if (HasMoreTokens() && Peek().is(tok::raw_identifier) && + Peek().getRawIdentifier() == "abi") + Advance(); + else + return false; + + if (!ConsumeToken(tok::colon)) + return false; + + // Consume the actual tag string (and allow some special characters) + while (ConsumeToken(tok::raw_identifier, tok::comma, tok::period, + tok::numeric_constant)) + ; + + if (!ConsumeToken(tok::r_square)) + return false; + + start_position.Remove(); + return true; +} + bool CPlusPlusNameParser::ConsumeAnonymousNamespace() { Bookmark start_position = SetBookmark(); if (!ConsumeToken(tok::l_paren)) { @@ -491,7 +568,7 @@ bool CPlusPlusNameParser::ConsumeTypename() { return true; } -Optional<CPlusPlusNameParser::ParsedNameRanges> +std::optional<CPlusPlusNameParser::ParsedNameRanges> CPlusPlusNameParser::ParseFullNameImpl() { // Name parsing state machine. enum class State { @@ -505,7 +582,7 @@ CPlusPlusNameParser::ParseFullNameImpl() { Bookmark start_position = SetBookmark(); State state = State::Beginning; bool continue_parsing = true; - Optional<size_t> last_coloncolon_position = None; + std::optional<size_t> last_coloncolon_position; while (continue_parsing && HasMoreTokens()) { const auto &token = Peek(); @@ -518,6 +595,22 @@ CPlusPlusNameParser::ParseFullNameImpl() { Advance(); state = State::AfterIdentifier; break; + case tok::l_square: { + // Handles types or functions that were tagged + // with, e.g., + // [[gnu::abi_tag("tag1","tag2")]] func() + // and demangled/prettified into: + // func[abi:tag1][abi:tag2]() + + // ABI tags only appear after a method or type name + const bool valid_state = + state == State::AfterIdentifier || state == State::AfterOperator; + if (!valid_state || !ConsumeAbiTag()) { + continue_parsing = false; + } + + break; + } case tok::l_paren: { if (state == State::Beginning || state == State::AfterTwoColons) { // (anonymous namespace) @@ -616,10 +709,10 @@ CPlusPlusNameParser::ParseFullNameImpl() { state == State::AfterTemplate) { ParsedNameRanges result; if (last_coloncolon_position) { - result.context_range = Range(start_position.GetSavedPosition(), - last_coloncolon_position.value()); + result.context_range = + Range(start_position.GetSavedPosition(), *last_coloncolon_position); result.basename_range = - Range(last_coloncolon_position.value() + 1, GetCurrentPosition()); + Range(*last_coloncolon_position + 1, GetCurrentPosition()); } else { result.basename_range = Range(start_position.GetSavedPosition(), GetCurrentPosition()); @@ -627,7 +720,7 @@ CPlusPlusNameParser::ParseFullNameImpl() { start_position.Remove(); return result; } else { - return None; + return std::nullopt; } } diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.h b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.h index 426434c48608..326efb7a8be0 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.h +++ b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.h @@ -10,12 +10,12 @@ #define LLDB_SOURCE_PLUGINS_LANGUAGE_CPLUSPLUS_CPLUSPLUSNAMEPARSER_H #include "clang/Lex/Lexer.h" -#include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "lldb/Utility/ConstString.h" #include "lldb/lldb-private.h" +#include <optional> namespace lldb_private { @@ -33,6 +33,7 @@ public: ParsedName name; llvm::StringRef arguments; llvm::StringRef qualifiers; + llvm::StringRef return_type; }; // Treats given text as a function definition and parses it. @@ -44,7 +45,7 @@ public: // std::vector<int>::push_back(int) // int& map<int, pair<short, int>>::operator[](short) const // int (*get_function(const chat *))() - llvm::Optional<ParsedFunction> ParseAsFunctionDefinition(); + std::optional<ParsedFunction> ParseAsFunctionDefinition(); // Treats given text as a potentially nested name of C++ entity (function, // class, field) and parses it. @@ -54,7 +55,7 @@ public: // std::vector<int>::push_back // map<int, pair<short, int>>::operator[] // func<C>(int, C&)::nested_class::method - llvm::Optional<ParsedName> ParseAsFullName(); + std::optional<ParsedName> ParseAsFullName(); private: // A C++ definition to parse. @@ -117,16 +118,17 @@ private: void Advance(); void TakeBack(); bool ConsumeToken(clang::tok::TokenKind kind); + template <typename... Ts> bool ConsumeToken(Ts... kinds); Bookmark SetBookmark(); size_t GetCurrentPosition(); clang::Token &Peek(); bool ConsumeBrackets(clang::tok::TokenKind left, clang::tok::TokenKind right); - llvm::Optional<ParsedFunction> ParseFunctionImpl(bool expect_return_type); + std::optional<ParsedFunction> ParseFunctionImpl(bool expect_return_type); // Parses functions returning function pointers 'string (*f(int x))(float y)' - llvm::Optional<ParsedFunction> ParseFuncPtr(bool expect_return_type); + std::optional<ParsedFunction> ParseFuncPtr(bool expect_return_type); // Consumes function arguments enclosed within '(' ... ')' bool ConsumeArguments(); @@ -164,7 +166,17 @@ private: // Consumes full type name like 'Namespace::Class<int>::Method()::InnerClass' bool ConsumeTypename(); - llvm::Optional<ParsedNameRanges> ParseFullNameImpl(); + /// Consumes ABI tags enclosed within '[abi:' ... ']' + /// + /// Since there is no restriction on what the ABI tag + /// string may contain, this API supports parsing a small + /// set of special characters. + /// + /// The following regex describes the set of supported characters: + /// [A-Za-z,.\s\d]+ + bool ConsumeAbiTag(); + + std::optional<ParsedNameRanges> ParseFullNameImpl(); llvm::StringRef GetTextForRange(const Range &range); // Populate m_tokens by calling clang lexer on m_text. diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/Coroutines.cpp b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/Coroutines.cpp new file mode 100644 index 000000000000..bd9ff99db67b --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/Coroutines.cpp @@ -0,0 +1,207 @@ +//===-- Coroutines.cpp ----------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "Coroutines.h" + +#include "Plugins/ExpressionParser/Clang/ClangASTImporter.h" +#include "Plugins/TypeSystem/Clang/TypeSystemClang.h" +#include "lldb/Symbol/Function.h" +#include "lldb/Symbol/VariableList.h" + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::formatters; + +static ValueObjectSP GetCoroFramePtrFromHandle(ValueObject &valobj) { + ValueObjectSP valobj_sp(valobj.GetNonSyntheticValue()); + if (!valobj_sp) + return nullptr; + + // We expect a single pointer in the `coroutine_handle` class. + // We don't care about its name. + if (valobj_sp->GetNumChildren() != 1) + return nullptr; + ValueObjectSP ptr_sp(valobj_sp->GetChildAtIndex(0, true)); + if (!ptr_sp) + return nullptr; + if (!ptr_sp->GetCompilerType().IsPointerType()) + return nullptr; + + return ptr_sp; +} + +static Function *ExtractDestroyFunction(ValueObjectSP &frame_ptr_sp) { + lldb::TargetSP target_sp = frame_ptr_sp->GetTargetSP(); + lldb::ProcessSP process_sp = frame_ptr_sp->GetProcessSP(); + auto ptr_size = process_sp->GetAddressByteSize(); + + AddressType addr_type; + lldb::addr_t frame_ptr_addr = frame_ptr_sp->GetPointerValue(&addr_type); + if (!frame_ptr_addr || frame_ptr_addr == LLDB_INVALID_ADDRESS) + return nullptr; + lldbassert(addr_type == AddressType::eAddressTypeLoad); + + Status error; + // The destroy pointer is the 2nd pointer inside the compiler-generated + // `pair<resumePtr,destroyPtr>`. + auto destroy_func_ptr_addr = frame_ptr_addr + ptr_size; + lldb::addr_t destroy_func_addr = + process_sp->ReadPointerFromMemory(destroy_func_ptr_addr, error); + if (error.Fail()) + return nullptr; + + Address destroy_func_address; + if (!target_sp->ResolveLoadAddress(destroy_func_addr, destroy_func_address)) + return nullptr; + + Function *destroy_func = + destroy_func_address.CalculateSymbolContextFunction(); + if (!destroy_func) + return nullptr; + + return destroy_func; +} + +static CompilerType InferPromiseType(Function &destroy_func) { + Block &block = destroy_func.GetBlock(true); + auto variable_list = block.GetBlockVariableList(true); + + // clang generates an artificial `__promise` variable inside the + // `destroy` function. Look for it. + auto promise_var = variable_list->FindVariable(ConstString("__promise")); + if (!promise_var) + return {}; + if (!promise_var->IsArtificial()) + return {}; + + Type *promise_type = promise_var->GetType(); + if (!promise_type) + return {}; + return promise_type->GetForwardCompilerType(); +} + +static CompilerType GetCoroutineFrameType(TypeSystemClang &ast_ctx, + CompilerType promise_type) { + CompilerType void_type = ast_ctx.GetBasicType(lldb::eBasicTypeVoid); + CompilerType coro_func_type = ast_ctx.CreateFunctionType( + /*result_type=*/void_type, /*args=*/&void_type, /*num_args=*/1, + /*is_variadic=*/false, /*qualifiers=*/0); + CompilerType coro_abi_type; + if (promise_type.IsVoidType()) { + coro_abi_type = ast_ctx.CreateStructForIdentifier( + ConstString(), {{"resume", coro_func_type.GetPointerType()}, + {"destroy", coro_func_type.GetPointerType()}}); + } else { + coro_abi_type = ast_ctx.CreateStructForIdentifier( + ConstString(), {{"resume", coro_func_type.GetPointerType()}, + {"destroy", coro_func_type.GetPointerType()}, + {"promise", promise_type}}); + } + return coro_abi_type; +} + +bool lldb_private::formatters::StdlibCoroutineHandleSummaryProvider( + ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) { + ValueObjectSP ptr_sp(GetCoroFramePtrFromHandle(valobj)); + if (!ptr_sp) + return false; + + if (!ptr_sp->GetValueAsUnsigned(0)) { + stream << "nullptr"; + } else { + stream.Printf("coro frame = 0x%" PRIx64, ptr_sp->GetValueAsUnsigned(0)); + } + return true; +} + +lldb_private::formatters::StdlibCoroutineHandleSyntheticFrontEnd:: + StdlibCoroutineHandleSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp) + : SyntheticChildrenFrontEnd(*valobj_sp), + m_ast_importer(std::make_unique<ClangASTImporter>()) { + if (valobj_sp) + Update(); +} + +lldb_private::formatters::StdlibCoroutineHandleSyntheticFrontEnd:: + ~StdlibCoroutineHandleSyntheticFrontEnd() = default; + +size_t lldb_private::formatters::StdlibCoroutineHandleSyntheticFrontEnd:: + CalculateNumChildren() { + if (!m_frame_ptr_sp) + return 0; + + return m_frame_ptr_sp->GetNumChildren(); +} + +lldb::ValueObjectSP lldb_private::formatters:: + StdlibCoroutineHandleSyntheticFrontEnd::GetChildAtIndex(size_t idx) { + if (!m_frame_ptr_sp) + return lldb::ValueObjectSP(); + + return m_frame_ptr_sp->GetChildAtIndex(idx, true); +} + +bool lldb_private::formatters::StdlibCoroutineHandleSyntheticFrontEnd:: + Update() { + m_frame_ptr_sp.reset(); + + ValueObjectSP valobj_sp = m_backend.GetSP(); + if (!valobj_sp) + return false; + + ValueObjectSP ptr_sp(GetCoroFramePtrFromHandle(m_backend)); + if (!ptr_sp) + return false; + + // Get the `promise_type` from the template argument + CompilerType promise_type( + valobj_sp->GetCompilerType().GetTypeTemplateArgument(0)); + if (!promise_type) + return false; + + // Try to infer the promise_type if it was type-erased + auto ts = valobj_sp->GetCompilerType().GetTypeSystem(); + auto ast_ctx = ts.dyn_cast_or_null<TypeSystemClang>(); + if (!ast_ctx) + return false; + if (promise_type.IsVoidType()) { + if (Function *destroy_func = ExtractDestroyFunction(ptr_sp)) { + if (CompilerType inferred_type = InferPromiseType(*destroy_func)) { + // Copy the type over to the correct `TypeSystemClang` instance + promise_type = m_ast_importer->CopyType(*ast_ctx, inferred_type); + } + } + } + + // Build the coroutine frame type + CompilerType coro_frame_type = GetCoroutineFrameType(*ast_ctx, promise_type); + + m_frame_ptr_sp = ptr_sp->Cast(coro_frame_type.GetPointerType()); + + return false; +} + +bool lldb_private::formatters::StdlibCoroutineHandleSyntheticFrontEnd:: + MightHaveChildren() { + return true; +} + +size_t StdlibCoroutineHandleSyntheticFrontEnd::GetIndexOfChildWithName( + ConstString name) { + if (!m_frame_ptr_sp) + return UINT32_MAX; + + return m_frame_ptr_sp->GetIndexOfChildWithName(name); +} + +SyntheticChildrenFrontEnd * +lldb_private::formatters::StdlibCoroutineHandleSyntheticFrontEndCreator( + CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) { + return (valobj_sp ? new StdlibCoroutineHandleSyntheticFrontEnd(valobj_sp) + : nullptr); +} diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/Coroutines.h b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/Coroutines.h new file mode 100644 index 000000000000..c052bd23f4ca --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/Coroutines.h @@ -0,0 +1,61 @@ +//===-- Coroutines.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_SOURCE_PLUGINS_LANGUAGE_CPLUSPLUS_COROUTINES_H +#define LLDB_SOURCE_PLUGINS_LANGUAGE_CPLUSPLUS_COROUTINES_H + +#include "lldb/Core/ValueObject.h" +#include "lldb/DataFormatters/TypeSummary.h" +#include "lldb/DataFormatters/TypeSynthetic.h" +#include "lldb/Utility/Stream.h" + +namespace lldb_private { + +class ClangASTImporter; + +namespace formatters { + +/// Summary provider for `std::coroutine_handle<T>` from libc++, libstdc++ and +/// MSVC STL. +bool StdlibCoroutineHandleSummaryProvider(ValueObject &valobj, Stream &stream, + const TypeSummaryOptions &options); + +/// Synthetic children frontend for `std::coroutine_handle<promise_type>` from +/// libc++, libstdc++ and MSVC STL. Shows the compiler-generated `resume` and +/// `destroy` function pointers as well as the `promise`, if the promise type +/// is `promise_type != void`. +class StdlibCoroutineHandleSyntheticFrontEnd + : public SyntheticChildrenFrontEnd { +public: + StdlibCoroutineHandleSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); + + ~StdlibCoroutineHandleSyntheticFrontEnd() override; + + size_t CalculateNumChildren() override; + + lldb::ValueObjectSP GetChildAtIndex(size_t idx) override; + + bool Update() override; + + bool MightHaveChildren() override; + + size_t GetIndexOfChildWithName(ConstString name) override; + +private: + lldb::ValueObjectSP m_frame_ptr_sp; + std::unique_ptr<lldb_private::ClangASTImporter> m_ast_importer; +}; + +SyntheticChildrenFrontEnd * +StdlibCoroutineHandleSyntheticFrontEndCreator(CXXSyntheticChildren *, + lldb::ValueObjectSP); + +} // namespace formatters +} // namespace lldb_private + +#endif // LLDB_SOURCE_PLUGINS_LANGUAGE_CPLUSPLUS_COROUTINES_H diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/CxxStringTypes.cpp b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/CxxStringTypes.cpp index 535a9f6015d8..bbd1e52ebaaf 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/CxxStringTypes.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/CxxStringTypes.cpp @@ -27,6 +27,7 @@ #include "lldb/Utility/Stream.h" #include <algorithm> +#include <optional> using namespace lldb; using namespace lldb_private; @@ -123,7 +124,7 @@ bool lldb_private::formatters::WCharStringSummaryProvider( return false; // Safe to pass nullptr for exe_scope here. - llvm::Optional<uint64_t> size = wchar_compiler_type.GetBitSize(nullptr); + std::optional<uint64_t> size = wchar_compiler_type.GetBitSize(nullptr); if (!size) return false; const uint32_t wchar_size = *size; @@ -183,7 +184,7 @@ bool lldb_private::formatters::WCharSummaryProvider( return false; // Safe to pass nullptr for exe_scope here. - llvm::Optional<uint64_t> size = wchar_compiler_type.GetBitSize(nullptr); + std::optional<uint64_t> size = wchar_compiler_type.GetBitSize(nullptr); if (!size) return false; const uint32_t wchar_size = *size; diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/GenericBitset.cpp b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/GenericBitset.cpp index d1d844bb4ca4..bc65570fe339 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/GenericBitset.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/GenericBitset.cpp @@ -11,6 +11,7 @@ #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" #include "lldb/DataFormatters/FormattersHelpers.h" #include "lldb/Target/Target.h" +#include <optional> using namespace lldb; using namespace lldb_private; @@ -106,7 +107,7 @@ ValueObjectSP GenericBitsetFrontEnd::GetChildAtIndex(size_t idx) { ValueObjectSP chunk; // For small bitsets __first_ is not an array, but a plain size_t. if (m_first->GetCompilerType().IsArrayType(&type)) { - llvm::Optional<uint64_t> bit_size = + std::optional<uint64_t> bit_size = type.GetBitSize(ctx.GetBestExecutionContextScope()); if (!bit_size || *bit_size == 0) return {}; @@ -118,7 +119,7 @@ ValueObjectSP GenericBitsetFrontEnd::GetChildAtIndex(size_t idx) { if (!type || !chunk) return {}; - llvm::Optional<uint64_t> bit_size = + std::optional<uint64_t> bit_size = type.GetBitSize(ctx.GetBestExecutionContextScope()); if (!bit_size || *bit_size == 0) return {}; diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp index 3b04b3a1b2ac..faa33ecefc2d 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp @@ -28,12 +28,24 @@ #include "Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h" #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" #include "lldb/lldb-enumerations.h" +#include <optional> #include <tuple> using namespace lldb; using namespace lldb_private; using namespace lldb_private::formatters; +lldb::ValueObjectSP lldb_private::formatters::GetChildMemberWithName( + ValueObject &obj, llvm::ArrayRef<ConstString> alternative_names) { + for (ConstString name : alternative_names) { + lldb::ValueObjectSP child_sp = obj.GetChildMemberWithName(name, true); + + if (child_sp) + return child_sp; + } + return {}; +} + bool lldb_private::formatters::LibcxxOptionalSummaryProvider( ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) { ValueObjectSP valobj_sp(valobj.GetNonSyntheticValue()); @@ -280,8 +292,8 @@ bool lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::Update() { auto addr(m_pair_ptr->GetValueAsUnsigned(LLDB_INVALID_ADDRESS)); m_pair_ptr = nullptr; if (addr && addr != LLDB_INVALID_ADDRESS) { - TypeSystemClang *ast_ctx = - llvm::dyn_cast_or_null<TypeSystemClang>(pair_type.GetTypeSystem()); + auto ts = pair_type.GetTypeSystem(); + auto ast_ctx = ts.dyn_cast_or_null<TypeSystemClang>(); if (!ast_ctx) return false; @@ -310,7 +322,7 @@ bool lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::Update() { ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType()}, {"cw", ast_ctx->GetBasicType(lldb::eBasicTypeBool)}, {"payload", pair_type}}); - llvm::Optional<uint64_t> size = tree_node_type.GetByteSize(nullptr); + std::optional<uint64_t> size = tree_node_type.GetByteSize(nullptr); if (!size) return false; WritableDataBufferSP buffer_sp(new DataBufferHeap(*size, 0)); @@ -449,8 +461,8 @@ bool lldb_private::formatters::LibCxxUnorderedMapIteratorSyntheticFrontEnd:: if (addr == 0 || addr == LLDB_INVALID_ADDRESS) return false; - TypeSystemClang *ast_ctx = - llvm::dyn_cast_or_null<TypeSystemClang>(pair_type.GetTypeSystem()); + auto ts = pair_type.GetTypeSystem(); + auto ast_ctx = ts.dyn_cast_or_null<TypeSystemClang>(); if (!ast_ctx) return false; @@ -472,7 +484,7 @@ bool lldb_private::formatters::LibCxxUnorderedMapIteratorSyntheticFrontEnd:: ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType()}, {"__hash_", ast_ctx->GetBasicType(lldb::eBasicTypeUnsignedLongLong)}, {"__value_", pair_type}}); - llvm::Optional<uint64_t> size = tree_node_type.GetByteSize(nullptr); + std::optional<uint64_t> size = tree_node_type.GetByteSize(nullptr); if (!size) return false; WritableDataBufferSP buffer_sp(new DataBufferHeap(*size, 0)); @@ -538,12 +550,9 @@ lldb_private::formatters::LibCxxUnorderedMapIteratorSyntheticFrontEndCreator( SyntheticChildrenFrontEnd * lldb_private::formatters::LibCxxVectorIteratorSyntheticFrontEndCreator( CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) { - static ConstString g_item_name; - if (!g_item_name) - g_item_name.SetCString("__i"); - return (valobj_sp - ? new VectorIteratorSyntheticFrontEnd(valobj_sp, g_item_name) - : nullptr); + return (valobj_sp ? new VectorIteratorSyntheticFrontEnd( + valobj_sp, {ConstString("__i_"), ConstString("__i")}) + : nullptr); } lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd:: @@ -721,7 +730,7 @@ enum class StringLayout { CSD, DSC }; /// Determine the size in bytes of \p valobj (a libc++ std::string object) and /// extract its data payload. Return the size + payload pair. // TODO: Support big-endian architectures. -static llvm::Optional<std::pair<uint64_t, ValueObjectSP>> +static std::optional<std::pair<uint64_t, ValueObjectSP>> ExtractLibcxxStringInfo(ValueObject &valobj) { ValueObjectSP valobj_r_sp = valobj.GetChildMemberWithName(ConstString("__r_"), /*can_create=*/true); @@ -790,7 +799,7 @@ ExtractLibcxxStringInfo(ValueObject &valobj) { // inline string buffer (23 bytes on x86_64/Darwin). If it doesn't, it's // likely that the string isn't initialized and we're reading garbage. ExecutionContext exe_ctx(location_sp->GetExecutionContextRef()); - const llvm::Optional<uint64_t> max_bytes = + const std::optional<uint64_t> max_bytes = location_sp->GetCompilerType().GetByteSize( exe_ctx.GetBestExecutionContextScope()); if (!max_bytes || size > *max_bytes || !location_sp) @@ -844,13 +853,13 @@ LibcxxWStringSummaryProvider(ValueObject &valobj, Stream &stream, return false; // std::wstring::size() is measured in 'characters', not bytes - TypeSystemClang *ast_context = + TypeSystemClangSP scratch_ts_sp = ScratchTypeSystemClang::GetForTarget(*valobj.GetTargetSP()); - if (!ast_context) + if (!scratch_ts_sp) return false; auto wchar_t_size = - ast_context->GetBasicType(lldb::eBasicTypeWChar).GetByteSize(nullptr); + scratch_ts_sp->GetBasicType(lldb::eBasicTypeWChar).GetByteSize(nullptr); if (!wchar_t_size) return false; @@ -992,11 +1001,10 @@ bool lldb_private::formatters::LibcxxStringSummaryProviderUTF32( static std::tuple<bool, ValueObjectSP, size_t> LibcxxExtractStringViewData(ValueObject& valobj) { - ConstString g_data_name("__data"); - ConstString g_size_name("__size"); - auto dataobj = valobj.GetChildMemberWithName(g_data_name, true); - auto sizeobj = valobj.GetChildMemberWithName(g_size_name, true); - + auto dataobj = GetChildMemberWithName( + valobj, {ConstString("__data_"), ConstString("__data")}); + auto sizeobj = GetChildMemberWithName( + valobj, {ConstString("__size_"), ConstString("__size")}); if (!dataobj || !sizeobj) return std::make_tuple<bool,ValueObjectSP,size_t>(false, {}, {}); diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h index b5ade4af8574..9ab22153a92a 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h +++ b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h @@ -18,6 +18,11 @@ namespace lldb_private { namespace formatters { +/// Find a child member of \c obj_sp, trying all alternative names in order. +lldb::ValueObjectSP +GetChildMemberWithName(ValueObject &obj, + llvm::ArrayRef<ConstString> alternative_names); + bool LibcxxStringSummaryProviderASCII( ValueObject &valobj, Stream &stream, const TypeSummaryOptions &summary_options); // libc++ std::string @@ -251,6 +256,10 @@ SyntheticChildrenFrontEnd * LibcxxStdSpanSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP); +SyntheticChildrenFrontEnd * +LibcxxStdRangesRefViewSyntheticFrontEndCreator(CXXSyntheticChildren *, + lldb::ValueObjectSP); + } // namespace formatters } // namespace lldb_private diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxInitializerList.cpp b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxInitializerList.cpp index d3be56e3f3c8..fbea4ec01717 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxInitializerList.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxInitializerList.cpp @@ -11,6 +11,7 @@ #include "lldb/Core/ValueObject.h" #include "lldb/DataFormatters/FormattersHelpers.h" #include "lldb/Utility/ConstString.h" +#include <optional> using namespace lldb; using namespace lldb_private; @@ -92,7 +93,7 @@ bool lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd:: if (!m_element_type.IsValid()) return false; - if (llvm::Optional<uint64_t> size = m_element_type.GetByteSize(nullptr)) { + if (std::optional<uint64_t> size = m_element_type.GetByteSize(nullptr)) { m_element_size = *size; // Store raw pointers or end up with a circular dependency. m_start = m_backend.GetChildMemberWithName(g_begin_, true).get(); diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp index ca6f92d003ad..bf6c65c8d9c2 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp @@ -249,7 +249,7 @@ bool lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetDataType() { static ConstString g_tree_("__tree_"); static ConstString g_pair3("__pair3_"); - if (m_element_type.GetOpaqueQualType() && m_element_type.GetTypeSystem()) + if (m_element_type.IsValid()) return true; m_element_type.Clear(); ValueObjectSP deref; @@ -295,8 +295,7 @@ void lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetValueOffset( UINT32_MAX) { m_skip_size = bit_offset / 8u; } else { - TypeSystemClang *ast_ctx = - llvm::dyn_cast_or_null<TypeSystemClang>(node_type.GetTypeSystem()); + auto ast_ctx = node_type.GetTypeSystem().dyn_cast_or_null<TypeSystemClang>(); if (!ast_ctx) return; CompilerType tree_node_type = ast_ctx->CreateStructForIdentifier( @@ -328,7 +327,7 @@ void lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetValueOffset( lldb::ValueObjectSP lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetChildAtIndex( size_t idx) { - static ConstString g_cc("__cc"); + static ConstString g_cc_("__cc_"), g_cc("__cc"); static ConstString g_nc("__nc"); static ConstString g_value_("__value_"); @@ -414,15 +413,17 @@ lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetChildAtIndex( switch (potential_child_sp->GetNumChildren()) { case 1: { auto child0_sp = potential_child_sp->GetChildAtIndex(0, true); - if (child0_sp && child0_sp->GetName() == g_cc) + if (child0_sp && + (child0_sp->GetName() == g_cc_ || child0_sp->GetName() == g_cc)) potential_child_sp = child0_sp->Clone(ConstString(name.GetString())); break; } case 2: { auto child0_sp = potential_child_sp->GetChildAtIndex(0, true); auto child1_sp = potential_child_sp->GetChildAtIndex(1, true); - if (child0_sp && child0_sp->GetName() == g_cc && child1_sp && - child1_sp->GetName() == g_nc) + if (child0_sp && + (child0_sp->GetName() == g_cc_ || child0_sp->GetName() == g_cc) && + child1_sp && child1_sp->GetName() == g_nc) potential_child_sp = child0_sp->Clone(ConstString(name.GetString())); break; } diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxRangesRefView.cpp b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxRangesRefView.cpp new file mode 100644 index 000000000000..6aeb557a95ff --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxRangesRefView.cpp @@ -0,0 +1,87 @@ +//===-- LibCxxRangesRefView.cpp -------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "LibCxx.h" + +#include "lldb/Core/ValueObject.h" +#include "lldb/DataFormatters/FormattersHelpers.h" +#include "lldb/Utility/ConstString.h" +#include "llvm/ADT/APSInt.h" + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::formatters; + +namespace lldb_private { +namespace formatters { + +class LibcxxStdRangesRefViewSyntheticFrontEnd + : public SyntheticChildrenFrontEnd { +public: + LibcxxStdRangesRefViewSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); + + ~LibcxxStdRangesRefViewSyntheticFrontEnd() override = default; + + size_t CalculateNumChildren() override { + // __range_ will be the sole child of this type + return 1; + } + + lldb::ValueObjectSP GetChildAtIndex(size_t idx) override { + // Since we only have a single child, return it + assert(idx == 0); + return m_range_sp; + } + + bool Update() override; + + bool MightHaveChildren() override { return true; } + + size_t GetIndexOfChildWithName(ConstString name) override { + // We only have a single child + return 0; + } + +private: + /// Pointer to the dereferenced __range_ member + lldb::ValueObjectSP m_range_sp = nullptr; +}; + +lldb_private::formatters::LibcxxStdRangesRefViewSyntheticFrontEnd:: + LibcxxStdRangesRefViewSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp) + : SyntheticChildrenFrontEnd(*valobj_sp) { + if (valobj_sp) + Update(); +} + +bool lldb_private::formatters::LibcxxStdRangesRefViewSyntheticFrontEnd:: + Update() { + ValueObjectSP range_ptr = + GetChildMemberWithName(m_backend, {ConstString("__range_")}); + if (!range_ptr) + return false; + + lldb_private::Status error; + m_range_sp = range_ptr->Dereference(error); + + return error.Success(); +} + +lldb_private::SyntheticChildrenFrontEnd * +LibcxxStdRangesRefViewSyntheticFrontEndCreator(CXXSyntheticChildren *, + lldb::ValueObjectSP valobj_sp) { + if (!valobj_sp) + return nullptr; + CompilerType type = valobj_sp->GetCompilerType(); + if (!type.IsValid()) + return nullptr; + return new LibcxxStdRangesRefViewSyntheticFrontEnd(valobj_sp); +} + +} // namespace formatters +} // namespace lldb_private diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxSpan.cpp b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxSpan.cpp index 0379ba2d85ad..ec062ed21ee4 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxSpan.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxSpan.cpp @@ -12,6 +12,7 @@ #include "lldb/DataFormatters/FormattersHelpers.h" #include "lldb/Utility/ConstString.h" #include "llvm/ADT/APSInt.h" +#include <optional> using namespace lldb; using namespace lldb_private; @@ -94,15 +95,15 @@ lldb_private::formatters::LibcxxStdSpanSyntheticFrontEnd::GetChildAtIndex( bool lldb_private::formatters::LibcxxStdSpanSyntheticFrontEnd::Update() { // Get element type. - ValueObjectSP data_type_finder_sp( - m_backend.GetChildMemberWithName(ConstString("__data"), true)); + ValueObjectSP data_type_finder_sp = GetChildMemberWithName( + m_backend, {ConstString("__data_"), ConstString("__data")}); if (!data_type_finder_sp) return false; m_element_type = data_type_finder_sp->GetCompilerType().GetPointeeType(); // Get element size. - if (llvm::Optional<uint64_t> size = m_element_type.GetByteSize(nullptr)) { + if (std::optional<uint64_t> size = m_element_type.GetByteSize(nullptr)) { m_element_size = *size; // Get data. @@ -111,8 +112,8 @@ bool lldb_private::formatters::LibcxxStdSpanSyntheticFrontEnd::Update() { } // Get number of elements. - if (auto size_sp = - m_backend.GetChildMemberWithName(ConstString("__size"), true)) { + if (auto size_sp = GetChildMemberWithName( + m_backend, {ConstString("__size_"), ConstString("__size")})) { m_num_elements = size_sp->GetValueAsUnsigned(0); } else if (auto arg = m_backend.GetCompilerType().GetIntegralTemplateArgument(1)) { diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp index 85c04ea728f5..cba1078d05d7 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp @@ -13,10 +13,12 @@ #include "lldb/Core/ValueObjectConstResult.h" #include "lldb/DataFormatters/FormattersHelpers.h" #include "lldb/Target/Target.h" +#include "lldb/Utility/ConstString.h" #include "lldb/Utility/DataBufferHeap.h" #include "lldb/Utility/Endian.h" #include "lldb/Utility/Status.h" #include "lldb/Utility/Stream.h" +#include "llvm/ADT/StringRef.h" using namespace lldb; using namespace lldb_private; @@ -65,6 +67,31 @@ size_t lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd:: return m_num_elements; } +static void consumeInlineNamespace(llvm::StringRef &name) { + // Delete past an inline namespace, if any: __[a-zA-Z0-9_]+:: + auto scratch = name; + if (scratch.consume_front("__") && std::isalnum(scratch[0])) { + scratch = scratch.drop_while([](char c) { return std::isalnum(c); }); + if (scratch.consume_front("::")) { + // Successfully consumed a namespace. + name = scratch; + } + } +} + +static bool isStdTemplate(ConstString type_name, llvm::StringRef type) { + llvm::StringRef name = type_name.GetStringRef(); + // The type name may be prefixed with `std::__<inline-namespace>::`. + if (name.consume_front("std::")) + consumeInlineNamespace(name); + return name.consume_front(type) && name.startswith("<"); +} + +static bool isUnorderedMap(ConstString type_name) { + return isStdTemplate(type_name, "unordered_map") || + isStdTemplate(type_name, "unordered_multimap"); +} + lldb::ValueObjectSP lldb_private::formatters:: LibcxxStdUnorderedMapSyntheticFrontEnd::GetChildAtIndex(size_t idx) { if (idx >= CalculateNumChildren()) @@ -118,10 +145,20 @@ lldb::ValueObjectSP lldb_private::formatters:: m_element_type = m_element_type.GetPointeeType(); m_node_type = m_element_type; m_element_type = m_element_type.GetTypeTemplateArgument(0); - std::string name; - m_element_type = - m_element_type.GetFieldAtIndex(0, name, nullptr, nullptr, nullptr); - m_element_type = m_element_type.GetTypedefedType(); + // This synthetic provider is used for both unordered_(multi)map and + // unordered_(multi)set. For unordered_map, the element type has an + // additional type layer, an internal struct (`__hash_value_type`) + // that wraps a std::pair. Peel away the internal wrapper type - whose + // structure is of no value to users, to expose the std::pair. This + // matches the structure returned by the std::map synthetic provider. + if (isUnorderedMap(m_backend.GetTypeName())) { + std::string name; + CompilerType field_type = m_element_type.GetFieldAtIndex( + 0, name, nullptr, nullptr, nullptr); + CompilerType actual_type = field_type.GetTypedefedType(); + if (isStdTemplate(actual_type.GetTypeName(), "pair")) + m_element_type = actual_type; + } } if (!m_node_type) return nullptr; @@ -153,7 +190,7 @@ lldb::ValueObjectSP lldb_private::formatters:: ExecutionContext exe_ctx = val_hash.first->GetExecutionContextRef().Lock( thread_and_frame_only_if_stopped); return CreateValueObjectFromData(stream.GetString(), data, exe_ctx, - val_hash.first->GetCompilerType()); + m_element_type); } bool lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd:: diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxVariant.cpp b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxVariant.cpp index 951bf2896fb0..4e54e7b5b7fa 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxVariant.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxVariant.cpp @@ -7,10 +7,13 @@ //===----------------------------------------------------------------------===// #include "LibCxxVariant.h" +#include "LibCxx.h" #include "lldb/DataFormatters/FormattersHelpers.h" +#include "lldb/Symbol/CompilerType.h" +#include "lldb/Utility/LLDBAssert.h" -#include "llvm/ADT/Optional.h" #include "llvm/ADT/ScopeExit.h" +#include <optional> using namespace lldb; using namespace lldb_private; @@ -65,6 +68,19 @@ namespace { // 3) NPos, its value is variant_npos which means the variant has no value enum class LibcxxVariantIndexValidity { Valid, Invalid, NPos }; +uint64_t VariantNposValue(uint64_t index_byte_size) { + switch (index_byte_size) { + case 1: + return static_cast<uint8_t>(-1); + case 2: + return static_cast<uint16_t>(-1); + case 4: + return static_cast<uint32_t>(-1); + } + lldbassert(false && "Unknown index type size"); + return static_cast<uint32_t>(-1); // Fallback to stable ABI type. +} + LibcxxVariantIndexValidity LibcxxVariantGetIndexValidity(ValueObjectSP &impl_sp) { ValueObjectSP index_sp( @@ -73,15 +89,29 @@ LibcxxVariantGetIndexValidity(ValueObjectSP &impl_sp) { if (!index_sp) return LibcxxVariantIndexValidity::Invalid; - int64_t index_value = index_sp->GetValueAsSigned(0); + // In the stable ABI, the type of __index is just int. + // In the unstable ABI, where _LIBCPP_ABI_VARIANT_INDEX_TYPE_OPTIMIZATION is + // enabled, the type can either be unsigned char/short/int depending on + // how many variant types there are. + // We only need to do this here when comparing against npos, because npos is + // just `-1`, but that translates to different unsigned values depending on + // the byte size. + CompilerType index_type = index_sp->GetCompilerType(); + + std::optional<uint64_t> index_type_bytes = index_type.GetByteSize(nullptr); + if (!index_type_bytes) + return LibcxxVariantIndexValidity::Invalid; - if (index_value == -1) + uint64_t npos_value = VariantNposValue(*index_type_bytes); + uint64_t index_value = index_sp->GetValueAsUnsigned(0); + + if (index_value == npos_value) return LibcxxVariantIndexValidity::NPos; return LibcxxVariantIndexValidity::Valid; } -llvm::Optional<uint64_t> LibcxxVariantIndexValue(ValueObjectSP &impl_sp) { +std::optional<uint64_t> LibcxxVariantIndexValue(ValueObjectSP &impl_sp) { ValueObjectSP index_sp( impl_sp->GetChildMemberWithName(ConstString("__index"), true)); @@ -121,8 +151,8 @@ bool LibcxxVariantSummaryProvider(ValueObject &valobj, Stream &stream, if (!valobj_sp) return false; - ValueObjectSP impl_sp( - valobj_sp->GetChildMemberWithName(ConstString("__impl"), true)); + ValueObjectSP impl_sp = GetChildMemberWithName( + *valobj_sp, {ConstString("__impl_"), ConstString("__impl")}); if (!impl_sp) return false; @@ -189,8 +219,8 @@ private: bool VariantFrontEnd::Update() { m_size = 0; - ValueObjectSP impl_sp( - m_backend.GetChildMemberWithName(ConstString("__impl"), true)); + ValueObjectSP impl_sp = formatters::GetChildMemberWithName( + m_backend, {ConstString("__impl_"), ConstString("__impl")}); if (!impl_sp) return false; @@ -209,38 +239,40 @@ bool VariantFrontEnd::Update() { ValueObjectSP VariantFrontEnd::GetChildAtIndex(size_t idx) { if (idx >= m_size) - return ValueObjectSP(); + return {}; - ValueObjectSP impl_sp( - m_backend.GetChildMemberWithName(ConstString("__impl"), true)); + ValueObjectSP impl_sp = formatters::GetChildMemberWithName( + m_backend, {ConstString("__impl_"), ConstString("__impl")}); + if (!impl_sp) + return {}; auto optional_index_value = LibcxxVariantIndexValue(impl_sp); if (!optional_index_value) - return ValueObjectSP(); + return {}; uint64_t index_value = *optional_index_value; ValueObjectSP nth_head = LibcxxVariantGetNthHead(impl_sp, index_value); if (!nth_head) - return ValueObjectSP(); + return {}; CompilerType head_type = nth_head->GetCompilerType(); if (!head_type) - return ValueObjectSP(); + return {}; CompilerType template_type = head_type.GetTypeTemplateArgument(1); if (!template_type) - return ValueObjectSP(); + return {}; ValueObjectSP head_value( nth_head->GetChildMemberWithName(ConstString("__value"), true)); if (!head_value) - return ValueObjectSP(); + return {}; return head_value->Clone(ConstString("Value")); } diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxVariant.h b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxVariant.h index b4c27ccb9d77..9488d94efda7 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxVariant.h +++ b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxVariant.h @@ -1,5 +1,4 @@ -//===-- LibCxxVariant.h -------------------------------------------*- C++ -//-*-===// +//===-- LibCxxVariant.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. diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp index 3e3727ac55a1..218ff9cd4741 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp @@ -11,6 +11,7 @@ #include "lldb/Core/ValueObject.h" #include "lldb/DataFormatters/FormattersHelpers.h" #include "lldb/Utility/ConstString.h" +#include <optional> using namespace lldb; using namespace lldb_private; @@ -143,7 +144,7 @@ bool lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::Update() { if (!data_type_finder_sp) return false; m_element_type = data_type_finder_sp->GetCompilerType().GetPointeeType(); - if (llvm::Optional<uint64_t> size = m_element_type.GetByteSize(nullptr)) { + if (std::optional<uint64_t> size = m_element_type.GetByteSize(nullptr)) { m_element_size = *size; if (m_element_size > 0) { @@ -211,7 +212,7 @@ lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::GetChildAtIndex( return {}; mask = 1 << bit_index; bool bit_set = ((byte & mask) != 0); - llvm::Optional<uint64_t> size = m_bool_type.GetByteSize(nullptr); + std::optional<uint64_t> size = m_bool_type.GetByteSize(nullptr); if (!size) return {}; WritableDataBufferSP buffer_sp(new DataBufferHeap(*size, 0)); diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp index d8623641b03f..90976fa053b8 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "LibStdcpp.h" +#include "LibCxx.h" #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" #include "lldb/Core/ValueObject.h" @@ -18,6 +19,7 @@ #include "lldb/Utility/Endian.h" #include "lldb/Utility/Status.h" #include "lldb/Utility/Stream.h" +#include <optional> using namespace lldb; using namespace lldb_private; @@ -169,19 +171,16 @@ lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEndCreator( SyntheticChildrenFrontEnd * lldb_private::formatters::LibStdcppVectorIteratorSyntheticFrontEndCreator( CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) { - static ConstString g_item_name; - if (!g_item_name) - g_item_name.SetCString("_M_current"); - return (valobj_sp - ? new VectorIteratorSyntheticFrontEnd(valobj_sp, g_item_name) - : nullptr); + return (valobj_sp ? new VectorIteratorSyntheticFrontEnd( + valobj_sp, {ConstString("_M_current")}) + : nullptr); } lldb_private::formatters::VectorIteratorSyntheticFrontEnd:: VectorIteratorSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp, - ConstString item_name) + llvm::ArrayRef<ConstString> item_names) : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), - m_item_name(item_name), m_item_sp() { + m_item_names(item_names), m_item_sp() { if (valobj_sp) Update(); } @@ -196,7 +195,8 @@ bool VectorIteratorSyntheticFrontEnd::Update() { if (!valobj_sp) return false; - ValueObjectSP item_ptr(valobj_sp->GetChildMemberWithName(m_item_name, true)); + ValueObjectSP item_ptr = + formatters::GetChildMemberWithName(*valobj_sp, m_item_names); if (!item_ptr) return false; if (item_ptr->GetValueAsUnsigned(0) == 0) @@ -298,7 +298,7 @@ bool lldb_private::formatters::LibStdcppWStringSummaryProvider( return false; // Safe to pass nullptr for exe_scope here. - llvm::Optional<uint64_t> size = wchar_compiler_type.GetBitSize(nullptr); + std::optional<uint64_t> size = wchar_compiler_type.GetBitSize(nullptr); if (!size) return false; const uint32_t wchar_size = *size; diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.cpp b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.cpp index 8ecf6712eace..72afc6fe75ac 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.cpp @@ -11,6 +11,13 @@ #include <stack> MSVCUndecoratedNameParser::MSVCUndecoratedNameParser(llvm::StringRef name) { + // Global ctor and dtor are global functions. + if (name.contains("dynamic initializer for") || + name.contains("dynamic atexit destructor for")) { + m_specifiers.emplace_back(name, name); + return; + } + std::size_t last_base_start = 0; std::stack<std::size_t> stack; diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/ClangCommon/ClangHighlighter.cpp b/contrib/llvm-project/lldb/source/Plugins/Language/ClangCommon/ClangHighlighter.cpp index fe6eeea54e4d..6b78ce5de697 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Language/ClangCommon/ClangHighlighter.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Language/ClangCommon/ClangHighlighter.cpp @@ -18,6 +18,7 @@ #include "clang/Lex/Lexer.h" #include "llvm/ADT/StringSet.h" #include "llvm/Support/MemoryBuffer.h" +#include <optional> using namespace lldb_private; @@ -131,7 +132,7 @@ determineClangStyle(const ClangHighlighter &highlighter, void ClangHighlighter::Highlight(const HighlightStyle &options, llvm::StringRef line, - llvm::Optional<size_t> cursor_pos, + std::optional<size_t> cursor_pos, llvm::StringRef previous_lines, Stream &result) const { using namespace clang; diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/ClangCommon/ClangHighlighter.h b/contrib/llvm-project/lldb/source/Plugins/Language/ClangCommon/ClangHighlighter.h index 5257c728ca5c..20bb09502d42 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Language/ClangCommon/ClangHighlighter.h +++ b/contrib/llvm-project/lldb/source/Plugins/Language/ClangCommon/ClangHighlighter.h @@ -13,6 +13,7 @@ #include "llvm/ADT/StringSet.h" #include "lldb/Core/Highlighter.h" +#include <optional> namespace lldb_private { @@ -24,7 +25,7 @@ public: llvm::StringRef GetName() const override { return "clang"; } void Highlight(const HighlightStyle &options, llvm::StringRef line, - llvm::Optional<size_t> cursor_pos, + std::optional<size_t> cursor_pos, llvm::StringRef previous_lines, Stream &s) const override; /// Returns true if the given string represents a keywords in any Clang diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/Cocoa.cpp b/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/Cocoa.cpp index 14cd64fe4b5e..46f82daaff8d 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/Cocoa.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/Cocoa.cpp @@ -616,7 +616,7 @@ bool lldb_private::formatters::NSNumberSummaryProvider( break; case 17: data_location += 8; - LLVM_FALLTHROUGH; + [[fallthrough]]; case 4: type_code = TypeCodes::sint64; break; diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/CoreMedia.cpp b/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/CoreMedia.cpp index a862da551813..1f4991bbfda2 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/CoreMedia.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/CoreMedia.cpp @@ -25,7 +25,9 @@ bool lldb_private::formatters::CMTimeSummaryProvider( if (!type.IsValid()) return false; - TypeSystem *type_system = type.GetTypeSystem(); + auto type_system = type.GetTypeSystem(); + if (!type_system) + return false; // fetch children by offset to compensate for potential lack of debug info auto int64_ty = type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingSint, 64); @@ -65,9 +67,6 @@ bool lldb_private::formatters::CMTimeSummaryProvider( return true; } - if (timescale == 0) - return false; - switch (timescale) { case 0: return false; diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/NSArray.cpp b/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/NSArray.cpp index adda04e18629..18bb2b8c4fdc 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/NSArray.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/NSArray.cpp @@ -463,12 +463,12 @@ lldb_private::formatters::NSArrayMSyntheticFrontEndBase:: NSArrayMSyntheticFrontEndBase(lldb::ValueObjectSP valobj_sp) : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), m_id_type() { if (valobj_sp) { - auto *clang_ast_context = ScratchTypeSystemClang::GetForTarget( + TypeSystemClangSP scratch_ts_sp = ScratchTypeSystemClang::GetForTarget( *valobj_sp->GetExecutionContextRef().GetTargetSP()); - if (clang_ast_context) + if (scratch_ts_sp) m_id_type = CompilerType( - clang_ast_context, - clang_ast_context->getASTContext().ObjCBuiltinIdTy.getAsOpaquePtr()); + scratch_ts_sp->weak_from_this(), + scratch_ts_sp->getASTContext().ObjCBuiltinIdTy.getAsOpaquePtr()); if (valobj_sp->GetProcessSP()) m_ptr_size = valobj_sp->GetProcessSP()->GetAddressByteSize(); } @@ -532,9 +532,8 @@ lldb_private::formatters:: process_sp->ReadMemory(data_location, m_data_64, sizeof(D64), error); } - if (error.Fail()) - return false; - return false; + + return error.Success(); } bool @@ -610,11 +609,11 @@ lldb_private::formatters::GenericNSArrayISyntheticFrontEnd<D32, D64, Inline>:: if (valobj_sp) { CompilerType type = valobj_sp->GetCompilerType(); if (type) { - auto *clang_ast_context = ScratchTypeSystemClang::GetForTarget( + TypeSystemClangSP scratch_ts_sp = ScratchTypeSystemClang::GetForTarget( *valobj_sp->GetExecutionContextRef().GetTargetSP()); - if (clang_ast_context) - m_id_type = clang_ast_context->GetType( - clang_ast_context->getASTContext().ObjCBuiltinIdTy); + if (scratch_ts_sp) + m_id_type = scratch_ts_sp->GetType( + scratch_ts_sp->getASTContext().ObjCBuiltinIdTy); } } } @@ -675,9 +674,8 @@ lldb_private::formatters::GenericNSArrayISyntheticFrontEnd<D32, D64, Inline>:: process_sp->ReadMemory(data_location, m_data_64, sizeof(D64), error); } - if (error.Fail()) - return false; - return false; + + return error.Success(); } template <typename D32, typename D64, bool Inline> @@ -778,11 +776,10 @@ lldb_private::formatters::NSArray1SyntheticFrontEnd::GetChildAtIndex( static const ConstString g_zero("[0]"); if (idx == 0) { - auto *clang_ast_context = + TypeSystemClangSP scratch_ts_sp = ScratchTypeSystemClang::GetForTarget(*m_backend.GetTargetSP()); - if (clang_ast_context) { - CompilerType id_type( - clang_ast_context->GetBasicType(lldb::eBasicTypeObjCID)); + if (scratch_ts_sp) { + CompilerType id_type(scratch_ts_sp->GetBasicType(lldb::eBasicTypeObjCID)); return m_backend.GetSyntheticChildAtOffset( m_backend.GetProcessSP()->GetAddressByteSize(), id_type, true, g_zero); diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp b/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp index e5e62b534560..4bab8924f3a5 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp @@ -66,18 +66,17 @@ NSDictionary_Additionals::GetAdditionalSynthetics() { static CompilerType GetLLDBNSPairType(TargetSP target_sp) { CompilerType compiler_type; - TypeSystemClang *target_ast_context = + TypeSystemClangSP scratch_ts_sp = ScratchTypeSystemClang::GetForTarget(*target_sp); - if (target_ast_context) { + if (scratch_ts_sp) { ConstString g_lldb_autogen_nspair("__lldb_autogen_nspair"); - compiler_type = - target_ast_context->GetTypeForIdentifier<clang::CXXRecordDecl>( - g_lldb_autogen_nspair); + compiler_type = scratch_ts_sp->GetTypeForIdentifier<clang::CXXRecordDecl>( + g_lldb_autogen_nspair); if (!compiler_type) { - compiler_type = target_ast_context->CreateRecordType( + compiler_type = scratch_ts_sp->CreateRecordType( nullptr, OptionalClangModuleID(), lldb::eAccessPublic, g_lldb_autogen_nspair.GetCString(), clang::TTK_Struct, lldb::eLanguageTypeC); @@ -85,7 +84,7 @@ static CompilerType GetLLDBNSPairType(TargetSP target_sp) { if (compiler_type) { TypeSystemClang::StartTagDeclarationDefinition(compiler_type); CompilerType id_compiler_type = - target_ast_context->GetBasicType(eBasicTypeObjCID); + scratch_ts_sp->GetBasicType(eBasicTypeObjCID); TypeSystemClang::AddFieldToRecordType( compiler_type, "key", id_compiler_type, lldb::eAccessPublic, 0); TypeSystemClang::AddFieldToRecordType( @@ -1121,9 +1120,8 @@ lldb_private::formatters::GenericNSDictionaryMSyntheticFrontEnd<D32,D64>:: process_sp->ReadMemory(data_location, m_data_64, sizeof(D64), error); } - if (error.Fail()) - return false; - return true; + + return error.Success(); } template <typename D32, typename D64> @@ -1284,9 +1282,8 @@ lldb_private::formatters::Foundation1100:: process_sp->ReadMemory(data_location, m_data_64, sizeof(DataDescriptor_64), error); } - if (error.Fail()) - return false; - return false; + + return error.Success(); } bool diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/NSError.cpp b/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/NSError.cpp index 4f237824c4b0..c267089f763d 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/NSError.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/NSError.cpp @@ -83,13 +83,15 @@ bool lldb_private::formatters::NSError_SummaryProvider( } InferiorSizedWord isw(domain_str_value, *process_sp); + TypeSystemClangSP scratch_ts_sp = + ScratchTypeSystemClang::GetForTarget(process_sp->GetTarget()); + if (!scratch_ts_sp) + return false; ValueObjectSP domain_str_sp = ValueObject::CreateValueObjectFromData( "domain_str", isw.GetAsData(process_sp->GetByteOrder()), valobj.GetExecutionContextRef(), - ScratchTypeSystemClang::GetForTarget(process_sp->GetTarget()) - ->GetBasicType(lldb::eBasicTypeVoid) - .GetPointerType()); + scratch_ts_sp->GetBasicType(lldb::eBasicTypeVoid).GetPointerType()); if (!domain_str_sp) return false; @@ -153,11 +155,14 @@ public: if (userinfo == LLDB_INVALID_ADDRESS || error.Fail()) return false; InferiorSizedWord isw(userinfo, *process_sp); + TypeSystemClangSP scratch_ts_sp = + ScratchTypeSystemClang::GetForTarget(process_sp->GetTarget()); + if (!scratch_ts_sp) + return false; m_child_sp = CreateValueObjectFromData( "_userInfo", isw.GetAsData(process_sp->GetByteOrder()), m_backend.GetExecutionContextRef(), - ScratchTypeSystemClang::GetForTarget(process_sp->GetTarget()) - ->GetBasicType(lldb::eBasicTypeObjCID)); + scratch_ts_sp->GetBasicType(lldb::eBasicTypeObjCID)); return false; } diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/NSException.cpp b/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/NSException.cpp index cb6b712a908b..875a30c11877 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/NSException.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/NSException.cpp @@ -69,13 +69,13 @@ static bool ExtractFields(ValueObject &valobj, ValueObjectSP *name_sp, InferiorSizedWord userinfo_isw(userinfo, *process_sp); InferiorSizedWord reserved_isw(reserved, *process_sp); - auto *clang_ast_context = + TypeSystemClangSP scratch_ts_sp = ScratchTypeSystemClang::GetForTarget(process_sp->GetTarget()); - if (!clang_ast_context) + if (!scratch_ts_sp) return false; CompilerType voidstar = - clang_ast_context->GetBasicType(lldb::eBasicTypeVoid).GetPointerType(); + scratch_ts_sp->GetBasicType(lldb::eBasicTypeVoid).GetPointerType(); if (name_sp) *name_sp = ValueObject::CreateValueObjectFromData( diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/NSIndexPath.cpp b/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/NSIndexPath.cpp index 429633e5e6b8..2a4ce80224e9 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/NSIndexPath.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/NSIndexPath.cpp @@ -49,11 +49,11 @@ public: bool Update() override { m_impl.Clear(); - TypeSystem *type_system = m_backend.GetCompilerType().GetTypeSystem(); + auto type_system = m_backend.GetCompilerType().GetTypeSystem(); if (!type_system) return false; - TypeSystemClang *ast = ScratchTypeSystemClang::GetForTarget( + auto ast = ScratchTypeSystemClang::GetForTarget( *m_backend.GetExecutionContextRef().GetTargetSP()); if (!ast) return false; diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/NSSet.cpp b/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/NSSet.cpp index b5c8e849abcc..fac8594d0c7d 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/NSSet.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/NSSet.cpp @@ -461,7 +461,7 @@ bool lldb_private::formatters::NSSetISyntheticFrontEnd::Update() { if (error.Fail()) return false; m_data_ptr = data_location + m_ptr_size; - return false; + return true; } bool lldb_private::formatters::NSSetISyntheticFrontEnd::MightHaveChildren() { @@ -735,9 +735,7 @@ lldb_private::formatters:: process_sp->ReadMemory(data_location, m_data_64, sizeof(D64), error); } - if (error.Fail()) - return false; - return false; + return error.Success(); } template <typename D32, typename D64> diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp b/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp index 99ce389bb53e..9cbb40419167 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp @@ -12,6 +12,7 @@ #include "Plugins/ExpressionParser/Clang/ClangUtil.h" #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" +#include "lldb/Core/Debugger.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/ValueObject.h" #include "lldb/DataFormatters/DataVisualization.h" @@ -284,12 +285,12 @@ static void LoadObjCFormatters(TypeCategoryImplSP objc_category_sp) { lldb::TypeSummaryImplSP ObjC_BOOL_summary(new CXXFunctionSummaryFormat( objc_flags, lldb_private::formatters::ObjCBOOLSummaryProvider, "")); - objc_category_sp->GetTypeSummariesContainer()->Add(ConstString("BOOL"), - ObjC_BOOL_summary); - objc_category_sp->GetTypeSummariesContainer()->Add(ConstString("BOOL &"), - ObjC_BOOL_summary); - objc_category_sp->GetTypeSummariesContainer()->Add(ConstString("BOOL *"), - ObjC_BOOL_summary); + objc_category_sp->AddTypeSummary("BOOL", eFormatterMatchExact, + ObjC_BOOL_summary); + objc_category_sp->AddTypeSummary("BOOL &", eFormatterMatchExact, + ObjC_BOOL_summary); + objc_category_sp->AddTypeSummary("BOOL *", eFormatterMatchExact, + ObjC_BOOL_summary); // we need to skip pointers here since we are special casing a SEL* when // retrieving its value @@ -931,10 +932,10 @@ lldb::TypeCategoryImplSP ObjCLanguage::GetFormatters() { return g_category; } -std::vector<ConstString> +std::vector<FormattersMatchCandidate> ObjCLanguage::GetPossibleFormattersMatches(ValueObject &valobj, lldb::DynamicValueType use_dynamic) { - std::vector<ConstString> result; + std::vector<FormattersMatchCandidate> result; if (use_dynamic == lldb::eNoDynamicValues) return result; @@ -959,7 +960,10 @@ ObjCLanguage::GetPossibleFormattersMatches(ValueObject &valobj, if (!objc_class_sp) break; if (ConstString name = objc_class_sp->GetClassName()) - result.push_back(name); + result.push_back( + {name, valobj.GetTargetSP()->GetDebugger().GetScriptInterpreter(), + TypeImpl(objc_class_sp->GetType()), + FormattersMatchCandidate::Flags{}}); } while (false); } diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/ObjCLanguage.h b/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/ObjCLanguage.h index 914452086db7..b61348a3280e 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/ObjCLanguage.h +++ b/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/ObjCLanguage.h @@ -108,7 +108,7 @@ public: lldb::TypeCategoryImplSP GetFormatters() override; - std::vector<ConstString> + std::vector<FormattersMatchCandidate> GetPossibleFormattersMatches(ValueObject &valobj, lldb::DynamicValueType use_dynamic) override; diff --git a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp index 1595335cfe33..f05997fa03af 100644 --- a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp @@ -453,6 +453,8 @@ lldb::SearchFilterSP ItaniumABILanguageRuntime::CreateExceptionSearchFilter() { // Apple binaries. filter_modules.EmplaceBack("libc++abi.dylib"); filter_modules.EmplaceBack("libSystem.B.dylib"); + filter_modules.EmplaceBack("libc++abi.1.0.dylib"); + filter_modules.EmplaceBack("libc++abi.1.dylib"); } return target.GetSearchFilterForModuleList(&filter_modules); } @@ -523,13 +525,13 @@ ValueObjectSP ItaniumABILanguageRuntime::GetExceptionObjectForThread( if (!thread_sp->SafeToCallFunctions()) return {}; - TypeSystemClang *clang_ast_context = + TypeSystemClangSP scratch_ts_sp = ScratchTypeSystemClang::GetForTarget(m_process->GetTarget()); - if (!clang_ast_context) + if (!scratch_ts_sp) return {}; CompilerType voidstar = - clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); + scratch_ts_sp->GetBasicType(eBasicTypeVoid).GetPointerType(); DiagnosticManager diagnostics; ExecutionContext exe_ctx; diff --git a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp index 5f3ae3b12975..4d6c86f7d28c 100644 --- a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp @@ -120,7 +120,7 @@ public: void StartTranslationUnit(clang::ASTConsumer *Consumer) override { clang::TranslationUnitDecl *translation_unit_decl = - m_decl_vendor.m_ast_ctx.getASTContext().getTranslationUnitDecl(); + m_decl_vendor.m_ast_ctx->getASTContext().getTranslationUnitDecl(); translation_unit_decl->setHasExternalVisibleStorage(); translation_unit_decl->setHasExternalLexicalStorage(); } @@ -131,14 +131,14 @@ private: AppleObjCDeclVendor::AppleObjCDeclVendor(ObjCLanguageRuntime &runtime) : ClangDeclVendor(eAppleObjCDeclVendor), m_runtime(runtime), - m_ast_ctx( - "AppleObjCDeclVendor AST", - runtime.GetProcess()->GetTarget().GetArchitecture().GetTriple()), m_type_realizer_sp(m_runtime.GetEncodingToType()) { + m_ast_ctx = std::make_shared<TypeSystemClang>( + "AppleObjCDeclVendor AST", + runtime.GetProcess()->GetTarget().GetArchitecture().GetTriple()); m_external_source = new AppleObjCExternalASTSource(*this); llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> external_source_owning_ptr( m_external_source); - m_ast_ctx.getASTContext().setExternalSource(external_source_owning_ptr); + m_ast_ctx->getASTContext().setExternalSource(external_source_owning_ptr); } clang::ObjCInterfaceDecl * @@ -148,7 +148,7 @@ AppleObjCDeclVendor::GetDeclForISA(ObjCLanguageRuntime::ObjCISA isa) { if (iter != m_isa_to_interface.end()) return iter->second; - clang::ASTContext &ast_ctx = m_ast_ctx.getASTContext(); + clang::ASTContext &ast_ctx = m_ast_ctx->getASTContext(); ObjCLanguageRuntime::ClassDescriptorSP descriptor = m_runtime.GetClassDescriptorFromISA(isa); @@ -167,7 +167,7 @@ AppleObjCDeclVendor::GetDeclForISA(ObjCLanguageRuntime::ObjCISA isa) { ClangASTMetadata meta_data; meta_data.SetISAPtr(isa); - m_ast_ctx.SetMetadata(new_iface_decl, meta_data); + m_ast_ctx->SetMetadata(new_iface_decl, meta_data); new_iface_decl->setHasExternalVisibleStorage(); new_iface_decl->setHasExternalLexicalStorage(); @@ -398,7 +398,7 @@ bool AppleObjCDeclVendor::FinishDecl(clang::ObjCInterfaceDecl *interface_decl) { Log *log( GetLog(LLDBLog::Expressions)); // FIXME - a more appropriate log channel? - ClangASTMetadata *metadata = m_ast_ctx.GetMetadata(interface_decl); + ClangASTMetadata *metadata = m_ast_ctx->GetMetadata(interface_decl); ObjCLanguageRuntime::ObjCISA objc_isa = 0; if (metadata) objc_isa = metadata->GetISAPtr(); @@ -428,7 +428,7 @@ bool AppleObjCDeclVendor::FinishDecl(clang::ObjCInterfaceDecl *interface_decl) { return; FinishDecl(superclass_decl); - clang::ASTContext &context = m_ast_ctx.getASTContext(); + clang::ASTContext &context = m_ast_ctx->getASTContext(); interface_decl->setSuperClass(context.getTrivialTypeSourceInfo( context.getObjCInterfaceType(superclass_decl))); }; @@ -441,7 +441,7 @@ bool AppleObjCDeclVendor::FinishDecl(clang::ObjCInterfaceDecl *interface_decl) { ObjCRuntimeMethodType method_type(types); clang::ObjCMethodDecl *method_decl = method_type.BuildMethod( - m_ast_ctx, interface_decl, name, true, m_type_realizer_sp); + *m_ast_ctx, interface_decl, name, true, m_type_realizer_sp); LLDB_LOGF(log, "[ AOTV::FD] Instance method [%s] [%s]", name, types); @@ -459,7 +459,7 @@ bool AppleObjCDeclVendor::FinishDecl(clang::ObjCInterfaceDecl *interface_decl) { ObjCRuntimeMethodType method_type(types); clang::ObjCMethodDecl *method_decl = method_type.BuildMethod( - m_ast_ctx, interface_decl, name, false, m_type_realizer_sp); + *m_ast_ctx, interface_decl, name, false, m_type_realizer_sp); LLDB_LOGF(log, "[ AOTV::FD] Class method [%s] [%s]", name, types); @@ -482,14 +482,14 @@ bool AppleObjCDeclVendor::FinishDecl(clang::ObjCInterfaceDecl *interface_decl) { name, type, offset_ptr); CompilerType ivar_type = m_runtime.GetEncodingToType()->RealizeType( - m_ast_ctx, type, for_expression); + *m_ast_ctx, type, for_expression); if (ivar_type.IsValid()) { clang::TypeSourceInfo *const type_source_info = nullptr; const bool is_synthesized = false; clang::ObjCIvarDecl *ivar_decl = clang::ObjCIvarDecl::Create( - m_ast_ctx.getASTContext(), interface_decl, clang::SourceLocation(), - clang::SourceLocation(), &m_ast_ctx.getASTContext().Idents.get(name), + m_ast_ctx->getASTContext(), interface_decl, clang::SourceLocation(), + clang::SourceLocation(), &m_ast_ctx->getASTContext().Idents.get(name), ClangUtil::GetQualType(ivar_type), type_source_info, // TypeSourceInfo * clang::ObjCIvarDecl::Public, nullptr, is_synthesized); @@ -541,7 +541,7 @@ uint32_t AppleObjCDeclVendor::FindDecls(ConstString name, bool append, do { // See if the type is already in our ASTContext. - clang::ASTContext &ast_ctx = m_ast_ctx.getASTContext(); + clang::ASTContext &ast_ctx = m_ast_ctx->getASTContext(); clang::IdentifierInfo &identifier_info = ast_ctx.Idents.get(name.GetStringRef()); @@ -559,7 +559,7 @@ uint32_t AppleObjCDeclVendor::FindDecls(ConstString name, bool append, ast_ctx.getObjCInterfaceType(result_iface_decl); uint64_t isa_value = LLDB_INVALID_ADDRESS; - ClangASTMetadata *metadata = m_ast_ctx.GetMetadata(result_iface_decl); + ClangASTMetadata *metadata = m_ast_ctx->GetMetadata(result_iface_decl); if (metadata) isa_value = metadata->GetISAPtr(); @@ -568,7 +568,7 @@ uint32_t AppleObjCDeclVendor::FindDecls(ConstString name, bool append, result_iface_type.getAsString(), isa_value); } - decls.push_back(m_ast_ctx.GetCompilerDecl(result_iface_decl)); + decls.push_back(m_ast_ctx->GetCompilerDecl(result_iface_decl)); ret++; break; } else { @@ -609,7 +609,7 @@ uint32_t AppleObjCDeclVendor::FindDecls(ConstString name, bool append, new_iface_type.getAsString(), (uint64_t)isa); } - decls.push_back(m_ast_ctx.GetCompilerDecl(iface_decl)); + decls.push_back(m_ast_ctx->GetCompilerDecl(iface_decl)); ret++; break; } while (false); diff --git a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.h b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.h index c1201b985814..3bb0f77f6bde 100644 --- a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.h +++ b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.h @@ -37,7 +37,7 @@ private: bool FinishDecl(clang::ObjCInterfaceDecl *decl); ObjCLanguageRuntime &m_runtime; - TypeSystemClang m_ast_ctx; + std::shared_ptr<TypeSystemClang> m_ast_ctx; ObjCLanguageRuntime::EncodingToTypeSP m_type_realizer_sp; AppleObjCExternalASTSource *m_external_source; diff --git a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp index dfa2d4c05126..a413c846b0c0 100644 --- a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp @@ -123,14 +123,14 @@ bool AppleObjCRuntime::GetObjectDescription(Stream &strm, Value &value, } } else { // If it is not a pointer, see if we can make it into a pointer. - TypeSystemClang *ast_context = + TypeSystemClangSP scratch_ts_sp = ScratchTypeSystemClang::GetForTarget(*target); - if (!ast_context) + if (!scratch_ts_sp) return false; - CompilerType opaque_type = ast_context->GetBasicType(eBasicTypeObjCID); + CompilerType opaque_type = scratch_ts_sp->GetBasicType(eBasicTypeObjCID); if (!opaque_type) - opaque_type = ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); + opaque_type = scratch_ts_sp->GetBasicType(eBasicTypeVoid).GetPointerType(); // value.SetContext(Value::eContextTypeClangType, opaque_type_ptr); value.SetCompilerType(opaque_type); } @@ -139,11 +139,12 @@ bool AppleObjCRuntime::GetObjectDescription(Stream &strm, Value &value, arg_value_list.PushValue(value); // This is the return value: - TypeSystemClang *ast_context = ScratchTypeSystemClang::GetForTarget(*target); - if (!ast_context) + TypeSystemClangSP scratch_ts_sp = + ScratchTypeSystemClang::GetForTarget(*target); + if (!scratch_ts_sp) return false; - CompilerType return_compiler_type = ast_context->GetCStringType(true); + CompilerType return_compiler_type = scratch_ts_sp->GetCStringType(true); Value ret; // ret.SetContext(Value::eContextTypeClangType, return_compiler_type); ret.SetCompilerType(return_compiler_type); @@ -503,7 +504,7 @@ ValueObjectSP AppleObjCRuntime::GetExceptionObjectForThread( /// \param msg The message to add to the log. /// \return An invalid ThreadSP to be returned from /// GetBacktraceThreadFromException. -LLVM_NODISCARD +[[nodiscard]] static ThreadSP FailExceptionParsing(llvm::StringRef msg) { Log *log = GetLog(LLDBLog::Language); LLDB_LOG(log, "Failed getting backtrace from exception: {0}", msg); @@ -521,12 +522,11 @@ ThreadSP AppleObjCRuntime::GetBacktraceThreadFromException( if (!reserved_dict) return FailExceptionParsing("Failed to get synthetic value."); - TypeSystemClang *clang_ast_context = + TypeSystemClangSP scratch_ts_sp = ScratchTypeSystemClang::GetForTarget(*exception_sp->GetTargetSP()); - if (!clang_ast_context) + if (!scratch_ts_sp) return FailExceptionParsing("Failed to get scratch AST."); - CompilerType objc_id = - clang_ast_context->GetBasicType(lldb::eBasicTypeObjCID); + CompilerType objc_id = scratch_ts_sp->GetBasicType(lldb::eBasicTypeObjCID); ValueObjectSP return_addresses; auto objc_object_from_address = [&exception_sp, &objc_id](uint64_t addr, diff --git a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h index e9790871e8c4..cfeec3d679be 100644 --- a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h +++ b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h @@ -9,7 +9,6 @@ #ifndef LLDB_SOURCE_PLUGINS_LANGUAGERUNTIME_OBJC_APPLEOBJCRUNTIME_APPLEOBJCRUNTIME_H #define LLDB_SOURCE_PLUGINS_LANGUAGERUNTIME_OBJC_APPLEOBJCRUNTIME_APPLEOBJCRUNTIME_H -#include "llvm/ADT/Optional.h" #include "AppleObjCTrampolineHandler.h" #include "AppleThreadPlanStepThroughObjCTrampoline.h" @@ -17,6 +16,7 @@ #include "lldb/lldb-private.h" #include "Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h" +#include <optional> namespace lldb_private { @@ -127,7 +127,7 @@ protected: lldb::ModuleWP m_objc_module_wp; std::unique_ptr<FunctionCaller> m_print_object_caller_up; - llvm::Optional<uint32_t> m_Foundation_major; + std::optional<uint32_t> m_Foundation_major; }; } // namespace lldb_private diff --git a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp index 1c2447b2bec5..7d376f2b9ac1 100644 --- a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp @@ -868,7 +868,7 @@ public: } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_objc_classtable_dump_options); + return llvm::ArrayRef(g_objc_classtable_dump_options); } OptionValueBoolean m_verbose; @@ -1627,9 +1627,9 @@ AppleObjCRuntimeV2::DynamicClassInfoExtractor::GetClassInfoUtilityFunctionImpl( LLDB_LOG(log, "Creating utility function {0}", name); - TypeSystemClang *ast = + TypeSystemClangSP scratch_ts_sp = ScratchTypeSystemClang::GetForTarget(exe_ctx.GetTargetRef()); - if (!ast) + if (!scratch_ts_sp) return {}; auto utility_fn_or_error = exe_ctx.GetTargetRef().CreateUtilityFunction( @@ -1643,9 +1643,9 @@ AppleObjCRuntimeV2::DynamicClassInfoExtractor::GetClassInfoUtilityFunctionImpl( // Make some types for our arguments. CompilerType clang_uint32_t_type = - ast->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32); + scratch_ts_sp->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32); CompilerType clang_void_pointer_type = - ast->GetBasicType(eBasicTypeVoid).GetPointerType(); + scratch_ts_sp->GetBasicType(eBasicTypeVoid).GetPointerType(); // Make the runner function for our implementation utility function. ValueList arguments; @@ -1768,9 +1768,9 @@ AppleObjCRuntimeV2::SharedCacheClassInfoExtractor:: LLDB_LOG(log, "Creating utility function {0}", g_get_shared_cache_class_info_name); - TypeSystemClang *ast = + TypeSystemClangSP scratch_ts_sp = ScratchTypeSystemClang::GetForTarget(exe_ctx.GetTargetRef()); - if (!ast) + if (!scratch_ts_sp) return {}; // If the inferior objc.dylib has the class_getNameRaw function, use that in @@ -1808,11 +1808,11 @@ AppleObjCRuntimeV2::SharedCacheClassInfoExtractor:: // Make some types for our arguments. CompilerType clang_uint32_t_type = - ast->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32); + scratch_ts_sp->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32); CompilerType clang_void_pointer_type = - ast->GetBasicType(eBasicTypeVoid).GetPointerType(); + scratch_ts_sp->GetBasicType(eBasicTypeVoid).GetPointerType(); CompilerType clang_uint64_t_pointer_type = - ast->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 64) + scratch_ts_sp->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 64) .GetPointerType(); // Next make the function caller for our implementation utility function. @@ -1875,11 +1875,14 @@ AppleObjCRuntimeV2::DynamicClassInfoExtractor::UpdateISAToDescriptorMap( if (!thread_sp) return DescriptorMapUpdateResult::Fail(); + if (!thread_sp->SafeToCallFunctions()) + return DescriptorMapUpdateResult::Retry(); + thread_sp->CalculateExecutionContext(exe_ctx); - TypeSystemClang *ast = + TypeSystemClangSP scratch_ts_sp = ScratchTypeSystemClang::GetForTarget(process->GetTarget()); - if (!ast) + if (!scratch_ts_sp) return DescriptorMapUpdateResult::Fail(); Address function_address; @@ -1999,7 +2002,7 @@ AppleObjCRuntimeV2::DynamicClassInfoExtractor::UpdateISAToDescriptorMap( options.SetIsForUtilityExpr(true); CompilerType clang_uint32_t_type = - ast->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32); + scratch_ts_sp->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32); Value return_value; return_value.SetValueType(Value::ValueType::Scalar); @@ -2042,7 +2045,7 @@ AppleObjCRuntimeV2::DynamicClassInfoExtractor::UpdateISAToDescriptorMap( } } - return DescriptorMapUpdateResult(success, num_class_infos); + return DescriptorMapUpdateResult(success, false, num_class_infos); } uint32_t AppleObjCRuntimeV2::ParseClassInfoArray(const DataExtractor &data, @@ -2137,11 +2140,14 @@ AppleObjCRuntimeV2::SharedCacheClassInfoExtractor::UpdateISAToDescriptorMap() { if (!thread_sp) return DescriptorMapUpdateResult::Fail(); + if (!thread_sp->SafeToCallFunctions()) + return DescriptorMapUpdateResult::Retry(); + thread_sp->CalculateExecutionContext(exe_ctx); - TypeSystemClang *ast = + TypeSystemClangSP scratch_ts_sp = ScratchTypeSystemClang::GetForTarget(process->GetTarget()); - if (!ast) + if (!scratch_ts_sp) return DescriptorMapUpdateResult::Fail(); Address function_address; @@ -2231,7 +2237,7 @@ AppleObjCRuntimeV2::SharedCacheClassInfoExtractor::UpdateISAToDescriptorMap() { options.SetIsForUtilityExpr(true); CompilerType clang_uint32_t_type = - ast->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32); + scratch_ts_sp->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32); Value return_value; return_value.SetValueType(Value::ValueType::Scalar); @@ -2314,7 +2320,7 @@ AppleObjCRuntimeV2::SharedCacheClassInfoExtractor::UpdateISAToDescriptorMap() { // Deallocate the memory we allocated for the ClassInfo array process->DeallocateMemory(class_infos_addr); - return DescriptorMapUpdateResult(success, num_class_infos); + return DescriptorMapUpdateResult(success, false, num_class_infos); } lldb::addr_t AppleObjCRuntimeV2::GetSharedCacheReadOnlyAddress() { @@ -2414,18 +2420,23 @@ void AppleObjCRuntimeV2::UpdateISAToDescriptorMapIfNeeded() { LLDB_LOGF(log, "attempted to read objc class data - results: " - "[dynamic_update]: ran: %s, count: %" PRIu32 - " [shared_cache_update]: ran: %s, count: %" PRIu32, + "[dynamic_update]: ran: %s, retry: %s, count: %" PRIu32 + " [shared_cache_update]: ran: %s, retry: %s, count: %" PRIu32, dynamic_update_result.m_update_ran ? "yes" : "no", + dynamic_update_result.m_retry_update ? "yes" : "no", dynamic_update_result.m_num_found, shared_cache_update_result.m_update_ran ? "yes" : "no", + shared_cache_update_result.m_retry_update ? "yes" : "no", shared_cache_update_result.m_num_found); // warn if: // - we could not run either expression // - we found fewer than num_classes_to_warn_at classes total - if ((!shared_cache_update_result.m_update_ran) || - (!dynamic_update_result.m_update_ran)) + if (dynamic_update_result.m_retry_update || + shared_cache_update_result.m_retry_update) + WarnIfNoClassesCached(SharedCacheWarningReason::eExpressionUnableToRun); + else if ((!shared_cache_update_result.m_update_ran) || + (!dynamic_update_result.m_update_ran)) WarnIfNoClassesCached( SharedCacheWarningReason::eExpressionExecutionFailure); else if (dynamic_update_result.m_num_found + @@ -2504,6 +2515,12 @@ void AppleObjCRuntimeV2::WarnIfNoClassesCached( "reduce the quality of type information available.\n", debugger.GetID(), &m_no_classes_cached_warning); break; + case SharedCacheWarningReason::eExpressionUnableToRun: + Debugger::ReportWarning( + "could not execute support code to read Objective-C class data because " + "it's not yet safe to do so, and will be retried later.\n", + debugger.GetID(), nullptr); + break; } } @@ -3234,12 +3251,12 @@ public: if (!abi) return; - TypeSystemClang *clang_ast_context = + TypeSystemClangSP scratch_ts_sp = ScratchTypeSystemClang::GetForTarget(process_sp->GetTarget()); - if (!clang_ast_context) + if (!scratch_ts_sp) return; CompilerType voidstar = - clang_ast_context->GetBasicType(lldb::eBasicTypeVoid).GetPointerType(); + scratch_ts_sp->GetBasicType(lldb::eBasicTypeVoid).GetPointerType(); ValueList args; Value input_value; diff --git a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h index 1a8e9d4aa339..bc8738094316 100644 --- a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h +++ b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h @@ -12,6 +12,7 @@ #include <map> #include <memory> #include <mutex> +#include <optional> #include "AppleObjCRuntime.h" #include "lldb/lldb-private.h" @@ -286,18 +287,24 @@ private: struct DescriptorMapUpdateResult { bool m_update_ran; + bool m_retry_update; uint32_t m_num_found; - DescriptorMapUpdateResult(bool ran, uint32_t found) { + DescriptorMapUpdateResult(bool ran, bool retry, uint32_t found) { m_update_ran = ran; + + m_retry_update = retry; + m_num_found = found; } - static DescriptorMapUpdateResult Fail() { return {false, 0}; } + static DescriptorMapUpdateResult Fail() { return {false, false, 0}; } static DescriptorMapUpdateResult Success(uint32_t found) { - return {true, found}; + return {true, false, found}; } + + static DescriptorMapUpdateResult Retry() { return {false, true, 0}; } }; /// Abstraction to read the Objective-C class info. @@ -395,6 +402,7 @@ private: uint32_t num_class_infos); enum class SharedCacheWarningReason { + eExpressionUnableToRun, eExpressionExecutionFailure, eNotEnoughClassesRead }; @@ -437,7 +445,7 @@ private: EncodingToTypeSP m_encoding_to_type_sp; std::once_flag m_no_classes_cached_warning; std::once_flag m_no_expanded_cache_warning; - llvm::Optional<std::pair<lldb::addr_t, lldb::addr_t>> m_CFBoolean_values; + std::optional<std::pair<lldb::addr_t, lldb::addr_t>> m_CFBoolean_values; uint64_t m_realized_class_generation_count; }; diff --git a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp index 18e1d12ef980..940e66afa0c0 100644 --- a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp @@ -416,15 +416,15 @@ bool AppleObjCTrampolineHandler::AppleObjCVTables::RefreshTrampolines( Process *process = exe_ctx.GetProcessPtr(); const ABI *abi = process->GetABI().get(); - TypeSystemClang *clang_ast_context = + TypeSystemClangSP scratch_ts_sp = ScratchTypeSystemClang::GetForTarget(process->GetTarget()); - if (!clang_ast_context) + if (!scratch_ts_sp) return false; ValueList argument_values; Value input_value; CompilerType clang_void_ptr_type = - clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); + scratch_ts_sp->GetBasicType(eBasicTypeVoid).GetPointerType(); input_value.SetValueType(Value::ValueType::Scalar); // input_value.SetContext (Value::eContextTypeClangType, @@ -656,7 +656,7 @@ AppleObjCTrampolineHandler::AppleObjCTrampolineHandler( // array into a template table, and populate the DispatchFunction // map from there. - for (size_t i = 0; i != llvm::array_lengthof(g_dispatch_functions); i++) { + for (size_t i = 0; i != std::size(g_dispatch_functions); i++) { ConstString name_const_str(g_dispatch_functions[i].name); const Symbol *msgSend_symbol = m_objc_module_sp->FindFirstSymbolWithNameAndType(name_const_str, @@ -674,9 +674,9 @@ AppleObjCTrampolineHandler::AppleObjCTrampolineHandler( m_msgSend_map.insert(std::pair<lldb::addr_t, int>(sym_addr, i)); } } - + // Similarly, cache the addresses of the "optimized dispatch" function. - for (size_t i = 0; i != llvm::array_lengthof(g_opt_dispatch_names); i++) { + for (size_t i = 0; i != std::size(g_opt_dispatch_names); i++) { ConstString name_const_str(g_opt_dispatch_names[i]); const Symbol *msgSend_symbol = m_objc_module_sp->FindFirstSymbolWithNameAndType(name_const_str, @@ -730,13 +730,13 @@ AppleObjCTrampolineHandler::SetupDispatchFunction(Thread &thread, } // Next make the runner function for our implementation utility function. - TypeSystemClang *clang_ast_context = ScratchTypeSystemClang::GetForTarget( + TypeSystemClangSP scratch_ts_sp = ScratchTypeSystemClang::GetForTarget( thread.GetProcess()->GetTarget()); - if (!clang_ast_context) + if (!scratch_ts_sp) return LLDB_INVALID_ADDRESS; CompilerType clang_void_ptr_type = - clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); + scratch_ts_sp->GetBasicType(eBasicTypeVoid).GetPointerType(); Status error; impl_function_caller = m_impl_code->MakeFunctionCaller( @@ -866,15 +866,15 @@ AppleObjCTrampolineHandler::GetStepThroughDispatchPlan(Thread &thread, TargetSP target_sp(thread.CalculateTarget()); - TypeSystemClang *clang_ast_context = + TypeSystemClangSP scratch_ts_sp = ScratchTypeSystemClang::GetForTarget(*target_sp); - if (!clang_ast_context) + if (!scratch_ts_sp) return ret_plan_sp; ValueList argument_values; Value void_ptr_value; CompilerType clang_void_ptr_type = - clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); + scratch_ts_sp->GetBasicType(eBasicTypeVoid).GetPointerType(); void_ptr_value.SetValueType(Value::ValueType::Scalar); // void_ptr_value.SetContext (Value::eContextTypeClangType, // clang_void_ptr_type); @@ -1089,7 +1089,7 @@ AppleObjCTrampolineHandler::GetStepThroughDispatchPlan(Thread &thread, Value flag_value; CompilerType clang_int_type = - clang_ast_context->GetBuiltinTypeForEncodingAndBitSize( + scratch_ts_sp->GetBuiltinTypeForEncodingAndBitSize( lldb::eEncodingSint, 32); flag_value.SetValueType(Value::ValueType::Scalar); // flag_value.SetContext (Value::eContextTypeClangType, clang_int_type); diff --git a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp index 40a0ea3e97a4..987726379623 100644 --- a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp @@ -24,10 +24,12 @@ using namespace lldb_private; AppleObjCTypeEncodingParser::AppleObjCTypeEncodingParser( ObjCLanguageRuntime &runtime) : ObjCLanguageRuntime::EncodingToType(), m_runtime(runtime) { - if (!m_scratch_ast_ctx_up) - m_scratch_ast_ctx_up = std::make_unique<TypeSystemClang>( - "AppleObjCTypeEncodingParser ASTContext", - runtime.GetProcess()->GetTarget().GetArchitecture().GetTriple()); + if (m_scratch_ast_ctx_sp) + return; + + m_scratch_ast_ctx_sp = std::make_shared<TypeSystemClang>( + "AppleObjCTypeEncodingParser ASTContext", + runtime.GetProcess()->GetTarget().GetArchitecture().GetTriple()); } std::string AppleObjCTypeEncodingParser::ReadStructName(StringLexer &type) { @@ -155,7 +157,8 @@ clang::QualType AppleObjCTypeEncodingParser::BuildArray( if (!type.NextIf(_C_ARY_E)) return clang::QualType(); CompilerType array_type(ast_ctx.CreateArrayType( - CompilerType(&ast_ctx, element_type.getAsOpaquePtr()), size, false)); + CompilerType(ast_ctx.weak_from_this(), element_type.getAsOpaquePtr()), + size, false)); return ClangUtil::GetQualType(array_type); } diff --git a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.cpp b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.cpp index b387de38d3bf..e28f224101bb 100644 --- a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.cpp @@ -27,6 +27,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Support/DJB.h" +#include <optional> using namespace lldb; using namespace lldb_private; @@ -330,8 +331,8 @@ ObjCLanguageRuntime::GetNonKVOClassDescriptor(ObjCISA isa) { CompilerType ObjCLanguageRuntime::EncodingToType::RealizeType(const char *name, bool for_expression) { - if (m_scratch_ast_ctx_up) - return RealizeType(*m_scratch_ast_ctx_up, name, for_expression); + if (m_scratch_ast_ctx_sp) + return RealizeType(*m_scratch_ast_ctx_sp, name, for_expression); return CompilerType(); } @@ -413,7 +414,7 @@ Status ObjCLanguageRuntime::ObjCExceptionPrecondition::ConfigurePrecondition( return error; } -llvm::Optional<CompilerType> +std::optional<CompilerType> ObjCLanguageRuntime::GetRuntimeType(CompilerType base_type) { CompilerType class_type; bool is_pointer_type = false; @@ -423,18 +424,18 @@ ObjCLanguageRuntime::GetRuntimeType(CompilerType base_type) { else if (TypeSystemClang::IsObjCObjectOrInterfaceType(base_type)) class_type = base_type; else - return llvm::None; + return std::nullopt; if (!class_type) - return llvm::None; + return std::nullopt; ConstString class_name(class_type.GetTypeName()); if (!class_name) - return llvm::None; + return std::nullopt; TypeSP complete_objc_class_type_sp = LookupInCompleteClassCache(class_name); if (!complete_objc_class_type_sp) - return llvm::None; + return std::nullopt; CompilerType complete_class( complete_objc_class_type_sp->GetFullCompilerType()); @@ -445,5 +446,5 @@ ObjCLanguageRuntime::GetRuntimeType(CompilerType base_type) { return complete_class; } - return llvm::None; + return std::nullopt; } diff --git a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h index 9431b4250240..f968a090c0f7 100644 --- a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h +++ b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h @@ -12,6 +12,7 @@ #include <functional> #include <map> #include <memory> +#include <optional> #include <unordered_set> #include "llvm/Support/Casting.h" @@ -158,7 +159,7 @@ public: virtual CompilerType RealizeType(const char *name, bool for_expression); protected: - std::unique_ptr<TypeSystemClang> m_scratch_ast_ctx_up; + std::shared_ptr<TypeSystemClang> m_scratch_ast_ctx_sp; }; class ObjCExceptionPrecondition : public BreakpointPrecondition { @@ -266,7 +267,7 @@ public: lldb::TypeSP LookupInCompleteClassCache(ConstString &name); - llvm::Optional<CompilerType> GetRuntimeType(CompilerType base_type) override; + std::optional<CompilerType> GetRuntimeType(CompilerType base_type) override; virtual llvm::Expected<std::unique_ptr<UtilityFunction>> CreateObjectChecker(std::string name, ExecutionContext &exe_ctx) = 0; diff --git a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.cpp b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.cpp index 7078c059adc7..2430ec3ff5d4 100644 --- a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.cpp @@ -8,7 +8,6 @@ #include <string> -#include "llvm/ADT/None.h" #include "llvm/ADT/StringRef.h" #include "llvm/IR/Instruction.h" #include "llvm/IR/Instructions.h" @@ -49,7 +48,7 @@ static bool registerRSDefaultTargetOpts(clang::TargetOptions &proto, proto.CPU = "atom"; proto.Features.push_back("+long64"); // Fallthrough for common x86 family features - LLVM_FALLTHROUGH; + [[fallthrough]]; case llvm::Triple::ArchType::x86_64: proto.Features.push_back("+mmx"); proto.Features.push_back("+sse"); @@ -92,7 +91,7 @@ bool RenderScriptRuntimeModulePass::runOnModule(llvm::Module &module) { return false; } - llvm::Optional<llvm::Reloc::Model> reloc_model = llvm::None; + std::optional<llvm::Reloc::Model> reloc_model; assert(m_process_ptr && "no available lldb process"); switch (m_process_ptr->GetTarget().GetArchitecture().GetMachine()) { case llvm::Triple::ArchType::x86: @@ -175,7 +174,6 @@ bool RenderScriptRuntime::GetIRPasses(LLVMUserExpression::IRPasses &passes) { namespace lldb_renderscript { RSIRPasses::RSIRPasses(Process *process) { - IRPasses(); assert(process); EarlyPasses = std::make_shared<llvm::legacy::PassManager>(); diff --git a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp index 0c032f8a7c88..e168241fb2c9 100644 --- a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp @@ -577,7 +577,7 @@ struct RenderScriptRuntime::Element { array_size; // Number of items in array, only needed for structs ConstString type_name; // Name of type, only needed for structs - static ConstString + static ConstString GetFallbackStructName(); // Print this as the type name of a struct Element // If we can't resolve the actual struct name @@ -879,7 +879,7 @@ RSReduceBreakpointResolver::SearchCallback(lldb_private::SearchFilter &filter, LLDB_LOGF(log, "%s: %s reduction breakpoint on %s in %s", __FUNCTION__, new_bp ? "new" : "existing", kernel_name.GetCString(), - address.GetModule()->GetFileSpec().GetCString()); + address.GetModule()->GetFileSpec().GetPath().c_str()); } } } @@ -2984,7 +2984,8 @@ bool RSModuleDescriptor::ParseRSInfo() { const llvm::StringRef raw_rs_info((const char *)buffer->GetBytes()); raw_rs_info.split(info_lines, '\n'); LLDB_LOGF(log, "'.rs.info symbol for '%s':\n%s", - m_module->GetFileSpec().GetCString(), raw_rs_info.str().c_str()); + m_module->GetFileSpec().GetPath().c_str(), + raw_rs_info.str().c_str()); } enum { @@ -4112,7 +4113,7 @@ public: } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_renderscript_reduction_bp_set_options); + return llvm::ArrayRef(g_renderscript_reduction_bp_set_options); } bool ParseReductionTypes(llvm::StringRef option_val, @@ -4264,7 +4265,7 @@ public: } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_renderscript_kernel_bp_set_options); + return llvm::ArrayRef(g_renderscript_kernel_bp_set_options); } RSCoordinate m_coord; @@ -4544,7 +4545,7 @@ public: } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_renderscript_runtime_alloc_dump_options); + return llvm::ArrayRef(g_renderscript_runtime_alloc_dump_options); } FileSpec m_outfile; @@ -4662,7 +4663,7 @@ public: void OptionParsingStarting(ExecutionContext *exe_ctx) override { m_id = 0; } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_renderscript_runtime_alloc_list_options); + return llvm::ArrayRef(g_renderscript_runtime_alloc_list_options); } uint32_t m_id = 0; diff --git a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.cpp b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.cpp index ec8f8d83c4b3..917242e9b287 100644 --- a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.cpp @@ -122,7 +122,7 @@ findRSCallSites(llvm::Module &module, std::set<llvm::CallInst *> &rs_callsites, bool found = false; for (auto &func : module.getFunctionList()) - for (auto &block : func.getBasicBlockList()) + for (auto &block : func) for (auto &inst : block) { llvm::CallInst *call_inst = llvm::dyn_cast_or_null<llvm::CallInst>(&inst); diff --git a/contrib/llvm-project/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp b/contrib/llvm-project/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp index 9fe222eceedc..957ecc223405 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp @@ -511,30 +511,6 @@ bool ObjectContainerBSDArchive::ParseHeader() { return m_archive_sp.get() != nullptr; } -void ObjectContainerBSDArchive::Dump(Stream *s) const { - s->Printf("%p: ", static_cast<const void *>(this)); - s->Indent(); - const size_t num_archs = GetNumArchitectures(); - const size_t num_objects = GetNumObjects(); - s->Printf("ObjectContainerBSDArchive, num_archs = %" PRIu64 - ", num_objects = %" PRIu64 "", - (uint64_t)num_archs, (uint64_t)num_objects); - uint32_t i; - ArchSpec arch; - s->IndentMore(); - for (i = 0; i < num_archs; i++) { - s->Indent(); - GetArchitectureAtIndex(i, arch); - s->Printf("arch[%u] = %s\n", i, arch.GetArchitectureName()); - } - for (i = 0; i < num_objects; i++) { - s->Indent(); - s->Printf("object[%u] = %s\n", i, GetObjectNameAtIndex(i)); - } - s->IndentLess(); - s->EOL(); -} - FileSpec GetChildFileSpecificationsFromThin(llvm::StringRef childPath, const FileSpec &parentFileSpec) { llvm::SmallString<128> FullPath; diff --git a/contrib/llvm-project/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h b/contrib/llvm-project/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h index ace072cbe149..1e2ffce3e5e2 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h +++ b/contrib/llvm-project/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h @@ -70,8 +70,6 @@ public: return 0; } - void Dump(lldb_private::Stream *s) const override; - lldb::ObjectFileSP GetObjectFile(const lldb_private::FileSpec *file) override; // PluginInterface protocol diff --git a/contrib/llvm-project/lldb/source/Plugins/ObjectContainer/Mach-O-Fileset/ObjectContainerMachOFileset.cpp b/contrib/llvm-project/lldb/source/Plugins/ObjectContainer/Mach-O-Fileset/ObjectContainerMachOFileset.cpp new file mode 100644 index 000000000000..4f9661eb0cdf --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/ObjectContainer/Mach-O-Fileset/ObjectContainerMachOFileset.cpp @@ -0,0 +1,299 @@ +//===-- ObjectContainerMachOFileset.cpp -----------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "ObjectContainerMachOFileset.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/ModuleSpec.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Symbol/ObjectFile.h" +#include "lldb/Target/Target.h" +#include "lldb/Utility/ArchSpec.h" +#include "lldb/Utility/DataBuffer.h" +#include "lldb/Utility/Stream.h" +#include <optional> + +using namespace lldb; +using namespace lldb_private; +using namespace llvm::MachO; + +LLDB_PLUGIN_DEFINE(ObjectContainerMachOFileset) + +void ObjectContainerMachOFileset::Initialize() { + PluginManager::RegisterPlugin(GetPluginNameStatic(), + GetPluginDescriptionStatic(), CreateInstance, + GetModuleSpecifications, CreateMemoryInstance); +} + +void ObjectContainerMachOFileset::Terminate() { + PluginManager::UnregisterPlugin(CreateInstance); +} + +ObjectContainerMachOFileset::ObjectContainerMachOFileset( + const lldb::ModuleSP &module_sp, lldb::DataBufferSP &data_sp, + lldb::offset_t data_offset, const lldb_private::FileSpec *file, + lldb::offset_t offset, lldb::offset_t length) + : ObjectContainer(module_sp, file, offset, length, data_sp, data_offset), + m_memory_addr(LLDB_INVALID_ADDRESS) {} + +ObjectContainerMachOFileset::ObjectContainerMachOFileset( + const lldb::ModuleSP &module_sp, lldb::WritableDataBufferSP data_sp, + const lldb::ProcessSP &process_sp, lldb::addr_t header_addr) + : ObjectContainer(module_sp, nullptr, 0, data_sp->GetByteSize(), data_sp, + 0), + m_process_wp(process_sp), m_memory_addr(header_addr) {} + +ObjectContainer *ObjectContainerMachOFileset::CreateInstance( + const lldb::ModuleSP &module_sp, DataBufferSP &data_sp, + lldb::offset_t data_offset, const FileSpec *file, + lldb::offset_t file_offset, lldb::offset_t length) { + if (!data_sp) + return {}; + + DataExtractor data; + data.SetData(data_sp, data_offset, length); + if (!MagicBytesMatch(data)) + return {}; + + auto container_up = std::make_unique<ObjectContainerMachOFileset>( + module_sp, data_sp, data_offset, file, file_offset, length); + if (!container_up->ParseHeader()) + return {}; + + return container_up.release(); +} + +ObjectContainer *ObjectContainerMachOFileset::CreateMemoryInstance( + const lldb::ModuleSP &module_sp, lldb::WritableDataBufferSP data_sp, + const lldb::ProcessSP &process_sp, lldb::addr_t header_addr) { + if (!MagicBytesMatch(data_sp, 0, data_sp->GetByteSize())) + return {}; + + auto container_up = std::make_unique<ObjectContainerMachOFileset>( + module_sp, data_sp, process_sp, header_addr); + if (!container_up->ParseHeader()) + return {}; + + return container_up.release(); +} + +ObjectContainerMachOFileset::~ObjectContainerMachOFileset() = default; + +static uint32_t MachHeaderSizeFromMagic(uint32_t magic) { + switch (magic) { + case MH_MAGIC: + case MH_CIGAM: + return sizeof(struct mach_header); + case MH_MAGIC_64: + case MH_CIGAM_64: + return sizeof(struct mach_header_64); + default: + return 0; + } +} + +static std::optional<mach_header> ParseMachOHeader(DataExtractor &data) { + lldb::offset_t offset = 0; + mach_header header; + header.magic = data.GetU32(&offset); + switch (header.magic) { + case MH_MAGIC: + data.SetByteOrder(endian::InlHostByteOrder()); + data.SetAddressByteSize(4); + break; + case MH_MAGIC_64: + data.SetByteOrder(endian::InlHostByteOrder()); + data.SetAddressByteSize(8); + break; + case MH_CIGAM: + data.SetByteOrder(endian::InlHostByteOrder() == eByteOrderBig + ? eByteOrderLittle + : eByteOrderBig); + data.SetAddressByteSize(4); + break; + case MH_CIGAM_64: + data.SetByteOrder(endian::InlHostByteOrder() == eByteOrderBig + ? eByteOrderLittle + : eByteOrderBig); + data.SetAddressByteSize(8); + break; + default: + return {}; + } + + header.cputype = data.GetU32(&offset); + header.cpusubtype = data.GetU32(&offset); + header.filetype = data.GetU32(&offset); + header.ncmds = data.GetU32(&offset); + header.sizeofcmds = data.GetU32(&offset); + return header; +} + +static bool +ParseFileset(DataExtractor &data, mach_header header, + std::vector<ObjectContainerMachOFileset::Entry> &entries, + std::optional<lldb::addr_t> load_addr = std::nullopt) { + lldb::offset_t offset = MachHeaderSizeFromMagic(header.magic); + lldb::offset_t slide = 0; + for (uint32_t i = 0; i < header.ncmds; ++i) { + const lldb::offset_t load_cmd_offset = offset; + load_command lc = {}; + if (data.GetU32(&offset, &lc.cmd, 2) == nullptr) + break; + + // If we know the load address we can compute the slide. + if (load_addr) { + if (lc.cmd == llvm::MachO::LC_SEGMENT_64) { + segment_command_64 segment; + data.CopyData(load_cmd_offset, sizeof(segment_command_64), &segment); + if (llvm::StringRef(segment.segname) == "__TEXT") + slide = *load_addr - segment.vmaddr; + } + } + + if (lc.cmd == LC_FILESET_ENTRY) { + fileset_entry_command entry; + data.CopyData(load_cmd_offset, sizeof(fileset_entry_command), &entry); + lldb::offset_t entry_id_offset = load_cmd_offset + entry.entry_id; + const char *id = data.GetCStr(&entry_id_offset); + entries.emplace_back(entry.vmaddr + slide, entry.fileoff, + std::string(id)); + } + + offset = load_cmd_offset + lc.cmdsize; + } + + return true; +} + +bool ObjectContainerMachOFileset::ParseHeader( + DataExtractor &data, const lldb_private::FileSpec &file, + lldb::offset_t file_offset, std::vector<Entry> &entries) { + std::optional<mach_header> header = ParseMachOHeader(data); + + if (!header) + return false; + + const size_t header_size = MachHeaderSizeFromMagic(header->magic); + const size_t header_and_lc_size = header_size + header->sizeofcmds; + + if (data.GetByteSize() < header_and_lc_size) { + DataBufferSP data_sp = + ObjectFile::MapFileData(file, header_and_lc_size, file_offset); + data.SetData(data_sp); + } + + return ParseFileset(data, *header, entries); +} + +bool ObjectContainerMachOFileset::ParseHeader() { + ModuleSP module_sp(GetModule()); + if (!module_sp) + return false; + + std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); + + std::optional<mach_header> header = ParseMachOHeader(m_data); + if (!header) + return false; + + const size_t header_size = MachHeaderSizeFromMagic(header->magic); + const size_t header_and_lc_size = header_size + header->sizeofcmds; + + if (m_data.GetByteSize() < header_and_lc_size) { + ProcessSP process_sp(m_process_wp.lock()); + DataBufferSP data_sp = + process_sp + ? ObjectFile::ReadMemory(process_sp, m_memory_addr, + header_and_lc_size) + : ObjectFile::MapFileData(m_file, header_and_lc_size, m_offset); + m_data.SetData(data_sp); + } + + return ParseFileset(m_data, *header, m_entries, m_memory_addr); +} + +size_t ObjectContainerMachOFileset::GetModuleSpecifications( + const lldb_private::FileSpec &file, lldb::DataBufferSP &data_sp, + lldb::offset_t data_offset, lldb::offset_t file_offset, + lldb::offset_t file_size, lldb_private::ModuleSpecList &specs) { + const size_t initial_count = specs.GetSize(); + + DataExtractor data; + data.SetData(data_sp, data_offset, data_sp->GetByteSize()); + + if (MagicBytesMatch(data)) { + std::vector<Entry> entries; + if (ParseHeader(data, file, file_offset, entries)) { + for (const Entry &entry : entries) { + const lldb::offset_t entry_offset = entry.fileoff + file_offset; + if (ObjectFile::GetModuleSpecifications( + file, entry_offset, file_size - entry_offset, specs)) { + ModuleSpec &spec = specs.GetModuleSpecRefAtIndex(specs.GetSize() - 1); + spec.GetObjectName() = ConstString(entry.id); + } + } + } + } + return specs.GetSize() - initial_count; +} + +bool ObjectContainerMachOFileset::MagicBytesMatch(DataBufferSP data_sp, + lldb::addr_t data_offset, + lldb::addr_t data_length) { + DataExtractor data; + data.SetData(data_sp, data_offset, data_length); + return MagicBytesMatch(data); +} + +bool ObjectContainerMachOFileset::MagicBytesMatch(const DataExtractor &data) { + lldb::offset_t offset = 0; + uint32_t magic = data.GetU32(&offset); + switch (magic) { + case MH_MAGIC: + case MH_CIGAM: + case MH_MAGIC_64: + case MH_CIGAM_64: + break; + default: + return false; + } + offset += 4; // cputype + offset += 4; // cpusubtype + uint32_t filetype = data.GetU32(&offset); + return filetype == MH_FILESET; +} + +ObjectFileSP +ObjectContainerMachOFileset::GetObjectFile(const lldb_private::FileSpec *file) { + ModuleSP module_sp(GetModule()); + if (!module_sp) + return {}; + + ConstString object_name = module_sp->GetObjectName(); + if (!object_name) + return {}; + + Entry *entry = FindEntry(object_name.GetCString()); + if (!entry) + return {}; + + DataBufferSP data_sp; + lldb::offset_t data_offset = 0; + return ObjectFile::FindPlugin(module_sp, file, m_offset + entry->fileoff, + m_data.GetByteSize() - entry->fileoff, data_sp, + data_offset); +} + +ObjectContainerMachOFileset::Entry * +ObjectContainerMachOFileset::FindEntry(llvm::StringRef id) { + for (Entry &entry : m_entries) { + if (entry.id == id) + return &entry; + } + return nullptr; +} diff --git a/contrib/llvm-project/lldb/source/Plugins/ObjectContainer/Mach-O-Fileset/ObjectContainerMachOFileset.h b/contrib/llvm-project/lldb/source/Plugins/ObjectContainer/Mach-O-Fileset/ObjectContainerMachOFileset.h new file mode 100644 index 000000000000..134c503aac91 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/ObjectContainer/Mach-O-Fileset/ObjectContainerMachOFileset.h @@ -0,0 +1,94 @@ +//===-- ObjectContainerMachOFileset.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_SOURCE_PLUGINS_OBJECTCONTAINER_MACH_O_FILESET_OBJECTCONTAINERMADCHOFILESET_H +#define LLDB_SOURCE_PLUGINS_OBJECTCONTAINER_MACH_O_FILESET_OBJECTCONTAINERMADCHOFILESET_H + +#include "lldb/Host/SafeMachO.h" +#include "lldb/Symbol/ObjectContainer.h" +#include "lldb/Utility/FileSpec.h" + +namespace lldb_private { + +class ObjectContainerMachOFileset : public lldb_private::ObjectContainer { +public: + ObjectContainerMachOFileset(const lldb::ModuleSP &module_sp, + lldb::DataBufferSP &data_sp, + lldb::offset_t data_offset, + const lldb_private::FileSpec *file, + lldb::offset_t offset, lldb::offset_t length); + + ObjectContainerMachOFileset(const lldb::ModuleSP &module_sp, + lldb::WritableDataBufferSP data_sp, + const lldb::ProcessSP &process_sp, + lldb::addr_t header_addr); + + ~ObjectContainerMachOFileset() override; + + static void Initialize(); + static void Terminate(); + + static llvm::StringRef GetPluginNameStatic() { return "mach-o-fileset"; } + + static llvm::StringRef GetPluginDescriptionStatic() { + return "Mach-O Fileset container reader."; + } + + static lldb_private::ObjectContainer * + CreateInstance(const lldb::ModuleSP &module_sp, lldb::DataBufferSP &data_sp, + lldb::offset_t data_offset, const lldb_private::FileSpec *file, + lldb::offset_t offset, lldb::offset_t length); + + static lldb_private::ObjectContainer *CreateMemoryInstance( + const lldb::ModuleSP &module_sp, lldb::WritableDataBufferSP data_sp, + const lldb::ProcessSP &process_sp, lldb::addr_t header_addr); + + static size_t GetModuleSpecifications(const lldb_private::FileSpec &file, + lldb::DataBufferSP &data_sp, + lldb::offset_t data_offset, + lldb::offset_t file_offset, + lldb::offset_t length, + lldb_private::ModuleSpecList &specs); + + static bool MagicBytesMatch(const lldb_private::DataExtractor &data); + static bool MagicBytesMatch(lldb::DataBufferSP data_sp, + lldb::addr_t data_offset, + lldb::addr_t data_length); + + bool ParseHeader() override; + + size_t GetNumObjects() const override { return m_entries.size(); } + + lldb::ObjectFileSP GetObjectFile(const lldb_private::FileSpec *file) override; + + llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); } + + struct Entry { + Entry(uint64_t vmaddr, uint64_t fileoff, std::string id) + : vmaddr(vmaddr), fileoff(fileoff), id(id) {} + uint64_t vmaddr; + uint64_t fileoff; + std::string id; + }; + + Entry *FindEntry(llvm::StringRef id); + +private: + static bool ParseHeader(lldb_private::DataExtractor &data, + const lldb_private::FileSpec &file, + lldb::offset_t file_offset, + std::vector<Entry> &entries); + + std::vector<Entry> m_entries; + lldb::ProcessWP m_process_wp; + const lldb::addr_t m_memory_addr; +}; + +} // namespace lldb_private + +#endif // LLDB_SOURCE_PLUGINS_OBJECTCONTAINER_MACH_O_FILESET_OBJECTCONTAINERMADCHOFILESET_H diff --git a/contrib/llvm-project/lldb/source/Plugins/ObjectFile/Breakpad/BreakpadRecords.cpp b/contrib/llvm-project/lldb/source/Plugins/ObjectFile/Breakpad/BreakpadRecords.cpp index 24941be515de..f26d6df1e910 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ObjectFile/Breakpad/BreakpadRecords.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ObjectFile/Breakpad/BreakpadRecords.cpp @@ -11,6 +11,7 @@ #include "llvm/ADT/StringSwitch.h" #include "llvm/Support/Endian.h" #include "llvm/Support/FormatVariadic.h" +#include <optional> using namespace lldb_private; using namespace lldb_private::breakpad; @@ -99,7 +100,7 @@ static UUID parseModuleId(llvm::Triple::OSType os, llvm::StringRef str) { uuid_t uuid; llvm::support::ubig32_t age; } data; - static_assert(sizeof(data) == 20, ""); + static_assert(sizeof(data) == 20); // The textual module id encoding should be between 33 and 40 bytes long, // depending on the size of the age field, which is of variable length. // The first three chunks of the id are encoded in big endian, so we need to @@ -122,11 +123,11 @@ static UUID parseModuleId(llvm::Triple::OSType os, llvm::StringRef str) { // On non-windows, the age field should always be zero, so we don't include to // match the native uuid format of these platforms. - return UUID::fromData(&data, os == llvm::Triple::Win32 ? sizeof(data) - : sizeof(data.uuid)); + return UUID(&data, os == llvm::Triple::Win32 ? sizeof(data) + : sizeof(data.uuid)); } -llvm::Optional<Record::Kind> Record::classify(llvm::StringRef Line) { +std::optional<Record::Kind> Record::classify(llvm::StringRef Line) { Token Tok = consume<Token>(Line); switch (Tok) { case Token::Module: @@ -147,7 +148,7 @@ llvm::Optional<Record::Kind> Record::classify(llvm::StringRef Line) { case Token::Win: return Record::StackWin; default: - return llvm::None; + return std::nullopt; } case Token::Inline: return Record::Inline; @@ -164,29 +165,29 @@ llvm::Optional<Record::Kind> Record::classify(llvm::StringRef Line) { case Token::Init: case Token::Win: // These should never appear at the start of a valid record. - return llvm::None; + return std::nullopt; } llvm_unreachable("Fully covered switch above!"); } -llvm::Optional<ModuleRecord> ModuleRecord::parse(llvm::StringRef Line) { +std::optional<ModuleRecord> ModuleRecord::parse(llvm::StringRef Line) { // MODULE Linux x86_64 E5894855C35DCCCCCCCCCCCCCCCCCCCC0 a.out if (consume<Token>(Line) != Token::Module) - return llvm::None; + return std::nullopt; llvm::Triple::OSType OS = consume<llvm::Triple::OSType>(Line); if (OS == llvm::Triple::UnknownOS) - return llvm::None; + return std::nullopt; llvm::Triple::ArchType Arch = consume<llvm::Triple::ArchType>(Line); if (Arch == llvm::Triple::UnknownArch) - return llvm::None; + return std::nullopt; llvm::StringRef Str; std::tie(Str, Line) = getToken(Line); UUID ID = parseModuleId(OS, Str); if (!ID) - return llvm::None; + return std::nullopt; return ModuleRecord(OS, Arch, std::move(ID)); } @@ -198,13 +199,13 @@ llvm::raw_ostream &breakpad::operator<<(llvm::raw_ostream &OS, << R.ID.GetAsString(); } -llvm::Optional<InfoRecord> InfoRecord::parse(llvm::StringRef Line) { +std::optional<InfoRecord> InfoRecord::parse(llvm::StringRef Line) { // INFO CODE_ID 554889E55DC3CCCCCCCCCCCCCCCCCCCC [a.exe] if (consume<Token>(Line) != Token::Info) - return llvm::None; + return std::nullopt; if (consume<Token>(Line) != Token::CodeID) - return llvm::None; + return std::nullopt; llvm::StringRef Str; std::tie(Str, Line) = getToken(Line); @@ -213,7 +214,7 @@ llvm::Optional<InfoRecord> InfoRecord::parse(llvm::StringRef Line) { UUID ID; if (Line.trim().empty()) { if (Str.empty() || !ID.SetFromStringRef(Str)) - return llvm::None; + return std::nullopt; } return InfoRecord(std::move(ID)); } @@ -224,26 +225,25 @@ llvm::raw_ostream &breakpad::operator<<(llvm::raw_ostream &OS, } template <typename T> -static llvm::Optional<T> parseNumberName(llvm::StringRef Line, - Token TokenType) { +static std::optional<T> parseNumberName(llvm::StringRef Line, Token TokenType) { // TOKEN number name if (consume<Token>(Line) != TokenType) - return llvm::None; + return std::nullopt; llvm::StringRef Str; size_t Number; std::tie(Str, Line) = getToken(Line); if (!to_integer(Str, Number)) - return llvm::None; + return std::nullopt; llvm::StringRef Name = Line.trim(); if (Name.empty()) - return llvm::None; + return std::nullopt; return T(Number, Name); } -llvm::Optional<FileRecord> FileRecord::parse(llvm::StringRef Line) { +std::optional<FileRecord> FileRecord::parse(llvm::StringRef Line) { // FILE number name return parseNumberName<FileRecord>(Line, Token::File); } @@ -253,7 +253,7 @@ llvm::raw_ostream &breakpad::operator<<(llvm::raw_ostream &OS, return OS << "FILE " << R.Number << " " << R.Name; } -llvm::Optional<InlineOriginRecord> +std::optional<InlineOriginRecord> InlineOriginRecord::parse(llvm::StringRef Line) { // INLINE_ORIGIN number name return parseNumberName<InlineOriginRecord>(Line, Token::InlineOrigin); @@ -302,7 +302,7 @@ static bool parsePublicOrFunc(llvm::StringRef Line, bool &Multiple, return true; } -llvm::Optional<FuncRecord> FuncRecord::parse(llvm::StringRef Line) { +std::optional<FuncRecord> FuncRecord::parse(llvm::StringRef Line) { bool Multiple; lldb::addr_t Address, Size, ParamSize; llvm::StringRef Name; @@ -310,7 +310,7 @@ llvm::Optional<FuncRecord> FuncRecord::parse(llvm::StringRef Line) { if (parsePublicOrFunc(Line, Multiple, Address, &Size, ParamSize, Name)) return FuncRecord(Multiple, Address, Size, ParamSize, Name); - return llvm::None; + return std::nullopt; } bool breakpad::operator==(const FuncRecord &L, const FuncRecord &R) { @@ -324,16 +324,16 @@ llvm::raw_ostream &breakpad::operator<<(llvm::raw_ostream &OS, R.ParamSize, R.Name); } -llvm::Optional<InlineRecord> InlineRecord::parse(llvm::StringRef Line) { +std::optional<InlineRecord> InlineRecord::parse(llvm::StringRef Line) { // INLINE inline_nest_level call_site_line call_site_file_num origin_num // [address size]+ if (consume<Token>(Line) != Token::Inline) - return llvm::None; + return std::nullopt; llvm::SmallVector<llvm::StringRef> Tokens; SplitString(Line, Tokens, " "); if (Tokens.size() < 6 || Tokens.size() % 2 == 1) - return llvm::None; + return std::nullopt; size_t InlineNestLevel; uint32_t CallSiteLineNum; @@ -343,17 +343,17 @@ llvm::Optional<InlineRecord> InlineRecord::parse(llvm::StringRef Line) { to_integer(Tokens[1], CallSiteLineNum) && to_integer(Tokens[2], CallSiteFileNum) && to_integer(Tokens[3], OriginNum))) - return llvm::None; + return std::nullopt; InlineRecord Record = InlineRecord(InlineNestLevel, CallSiteLineNum, CallSiteFileNum, OriginNum); for (size_t i = 4; i < Tokens.size(); i += 2) { lldb::addr_t Address; if (!to_integer(Tokens[i], Address, 16)) - return llvm::None; + return std::nullopt; lldb::addr_t Size; if (!to_integer(Tokens[i + 1].trim(), Size, 16)) - return llvm::None; + return std::nullopt; Record.Ranges.emplace_back(Address, Size); } return Record; @@ -376,27 +376,27 @@ llvm::raw_ostream &breakpad::operator<<(llvm::raw_ostream &OS, return OS; } -llvm::Optional<LineRecord> LineRecord::parse(llvm::StringRef Line) { +std::optional<LineRecord> LineRecord::parse(llvm::StringRef Line) { lldb::addr_t Address; llvm::StringRef Str; std::tie(Str, Line) = getToken(Line); if (!to_integer(Str, Address, 16)) - return llvm::None; + return std::nullopt; lldb::addr_t Size; std::tie(Str, Line) = getToken(Line); if (!to_integer(Str, Size, 16)) - return llvm::None; + return std::nullopt; uint32_t LineNum; std::tie(Str, Line) = getToken(Line); if (!to_integer(Str, LineNum)) - return llvm::None; + return std::nullopt; size_t FileNum; std::tie(Str, Line) = getToken(Line); if (!to_integer(Str, FileNum)) - return llvm::None; + return std::nullopt; return LineRecord(Address, Size, LineNum, FileNum); } @@ -411,7 +411,7 @@ llvm::raw_ostream &breakpad::operator<<(llvm::raw_ostream &OS, R.LineNum, R.FileNum); } -llvm::Optional<PublicRecord> PublicRecord::parse(llvm::StringRef Line) { +std::optional<PublicRecord> PublicRecord::parse(llvm::StringRef Line) { bool Multiple; lldb::addr_t Address, ParamSize; llvm::StringRef Name; @@ -419,7 +419,7 @@ llvm::Optional<PublicRecord> PublicRecord::parse(llvm::StringRef Line) { if (parsePublicOrFunc(Line, Multiple, Address, nullptr, ParamSize, Name)) return PublicRecord(Multiple, Address, ParamSize, Name); - return llvm::None; + return std::nullopt; } bool breakpad::operator==(const PublicRecord &L, const PublicRecord &R) { @@ -433,16 +433,16 @@ llvm::raw_ostream &breakpad::operator<<(llvm::raw_ostream &OS, R.Name); } -llvm::Optional<StackCFIRecord> StackCFIRecord::parse(llvm::StringRef Line) { +std::optional<StackCFIRecord> StackCFIRecord::parse(llvm::StringRef Line) { // STACK CFI INIT address size reg1: expr1 reg2: expr2 ... // or // STACK CFI address reg1: expr1 reg2: expr2 ... // No token in exprN ends with a colon. if (consume<Token>(Line) != Token::Stack) - return llvm::None; + return std::nullopt; if (consume<Token>(Line) != Token::CFI) - return llvm::None; + return std::nullopt; llvm::StringRef Str; std::tie(Str, Line) = getToken(Line); @@ -453,14 +453,14 @@ llvm::Optional<StackCFIRecord> StackCFIRecord::parse(llvm::StringRef Line) { lldb::addr_t Address; if (!to_integer(Str, Address, 16)) - return llvm::None; + return std::nullopt; - llvm::Optional<lldb::addr_t> Size; + std::optional<lldb::addr_t> Size; if (IsInitRecord) { Size.emplace(); std::tie(Str, Line) = getToken(Line); if (!to_integer(Str, *Size, 16)) - return llvm::None; + return std::nullopt; } return StackCFIRecord(Address, Size, Line.trim()); @@ -482,32 +482,32 @@ llvm::raw_ostream &breakpad::operator<<(llvm::raw_ostream &OS, return OS << " " << R.UnwindRules; } -llvm::Optional<StackWinRecord> StackWinRecord::parse(llvm::StringRef Line) { +std::optional<StackWinRecord> StackWinRecord::parse(llvm::StringRef Line) { // STACK WIN type rva code_size prologue_size epilogue_size parameter_size // saved_register_size local_size max_stack_size has_program_string // program_string_OR_allocates_base_pointer if (consume<Token>(Line) != Token::Stack) - return llvm::None; + return std::nullopt; if (consume<Token>(Line) != Token::Win) - return llvm::None; + return std::nullopt; llvm::StringRef Str; uint8_t Type; std::tie(Str, Line) = getToken(Line); // Right now we only support the "FrameData" frame type. if (!to_integer(Str, Type) || FrameType(Type) != FrameType::FrameData) - return llvm::None; + return std::nullopt; lldb::addr_t RVA; std::tie(Str, Line) = getToken(Line); if (!to_integer(Str, RVA, 16)) - return llvm::None; + return std::nullopt; lldb::addr_t CodeSize; std::tie(Str, Line) = getToken(Line); if (!to_integer(Str, CodeSize, 16)) - return llvm::None; + return std::nullopt; // Skip fields which we aren't using right now. std::tie(Str, Line) = getToken(Line); // prologue_size @@ -516,27 +516,27 @@ llvm::Optional<StackWinRecord> StackWinRecord::parse(llvm::StringRef Line) { lldb::addr_t ParameterSize; std::tie(Str, Line) = getToken(Line); if (!to_integer(Str, ParameterSize, 16)) - return llvm::None; + return std::nullopt; lldb::addr_t SavedRegisterSize; std::tie(Str, Line) = getToken(Line); if (!to_integer(Str, SavedRegisterSize, 16)) - return llvm::None; + return std::nullopt; lldb::addr_t LocalSize; std::tie(Str, Line) = getToken(Line); if (!to_integer(Str, LocalSize, 16)) - return llvm::None; + return std::nullopt; std::tie(Str, Line) = getToken(Line); // max_stack_size uint8_t HasProgramString; std::tie(Str, Line) = getToken(Line); if (!to_integer(Str, HasProgramString)) - return llvm::None; + return std::nullopt; // FrameData records should always have a program string. if (!HasProgramString) - return llvm::None; + return std::nullopt; return StackWinRecord(RVA, CodeSize, ParameterSize, SavedRegisterSize, LocalSize, Line.trim()); diff --git a/contrib/llvm-project/lldb/source/Plugins/ObjectFile/Breakpad/BreakpadRecords.h b/contrib/llvm-project/lldb/source/Plugins/ObjectFile/Breakpad/BreakpadRecords.h index 8a11323d521c..416f84fe2430 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ObjectFile/Breakpad/BreakpadRecords.h +++ b/contrib/llvm-project/lldb/source/Plugins/ObjectFile/Breakpad/BreakpadRecords.h @@ -14,6 +14,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Triple.h" #include "llvm/Support/FormatProviders.h" +#include <optional> namespace lldb_private { namespace breakpad { @@ -36,7 +37,7 @@ public: /// Attempt to guess the kind of the record present in the argument without /// doing a full parse. The returned kind will always be correct for valid /// records, but the full parse can still fail in case of corrupted input. - static llvm::Optional<Kind> classify(llvm::StringRef Line); + static std::optional<Kind> classify(llvm::StringRef Line); protected: Record(Kind K) : TheKind(K) {} @@ -58,7 +59,7 @@ inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, Record::Kind K) { class ModuleRecord : public Record { public: - static llvm::Optional<ModuleRecord> parse(llvm::StringRef Line); + static std::optional<ModuleRecord> parse(llvm::StringRef Line); ModuleRecord(llvm::Triple::OSType OS, llvm::Triple::ArchType Arch, UUID ID) : Record(Module), OS(OS), Arch(Arch), ID(std::move(ID)) {} @@ -74,7 +75,7 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const ModuleRecord &R); class InfoRecord : public Record { public: - static llvm::Optional<InfoRecord> parse(llvm::StringRef Line); + static std::optional<InfoRecord> parse(llvm::StringRef Line); InfoRecord(UUID ID) : Record(Info), ID(std::move(ID)) {} UUID ID; @@ -87,7 +88,7 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const InfoRecord &R); class FileRecord : public Record { public: - static llvm::Optional<FileRecord> parse(llvm::StringRef Line); + static std::optional<FileRecord> parse(llvm::StringRef Line); FileRecord(size_t Number, llvm::StringRef Name) : Record(File), Number(Number), Name(Name) {} @@ -102,7 +103,7 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const FileRecord &R); class InlineOriginRecord : public Record { public: - static llvm::Optional<InlineOriginRecord> parse(llvm::StringRef Line); + static std::optional<InlineOriginRecord> parse(llvm::StringRef Line); InlineOriginRecord(size_t Number, llvm::StringRef Name) : Record(InlineOrigin), Number(Number), Name(Name) {} @@ -119,7 +120,7 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, class FuncRecord : public Record { public: - static llvm::Optional<FuncRecord> parse(llvm::StringRef Line); + static std::optional<FuncRecord> parse(llvm::StringRef Line); FuncRecord(bool Multiple, lldb::addr_t Address, lldb::addr_t Size, lldb::addr_t ParamSize, llvm::StringRef Name) : Record(Module), Multiple(Multiple), Address(Address), Size(Size), @@ -137,7 +138,7 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const FuncRecord &R); class InlineRecord : public Record { public: - static llvm::Optional<InlineRecord> parse(llvm::StringRef Line); + static std::optional<InlineRecord> parse(llvm::StringRef Line); InlineRecord(size_t InlineNestLevel, uint32_t CallSiteLineNum, size_t CallSiteFileNum, size_t OriginNum) : Record(Inline), InlineNestLevel(InlineNestLevel), @@ -157,7 +158,7 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const InlineRecord &R); class LineRecord : public Record { public: - static llvm::Optional<LineRecord> parse(llvm::StringRef Line); + static std::optional<LineRecord> parse(llvm::StringRef Line); LineRecord(lldb::addr_t Address, lldb::addr_t Size, uint32_t LineNum, size_t FileNum) : Record(Line), Address(Address), Size(Size), LineNum(LineNum), @@ -174,7 +175,7 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const LineRecord &R); class PublicRecord : public Record { public: - static llvm::Optional<PublicRecord> parse(llvm::StringRef Line); + static std::optional<PublicRecord> parse(llvm::StringRef Line); PublicRecord(bool Multiple, lldb::addr_t Address, lldb::addr_t ParamSize, llvm::StringRef Name) : Record(Module), Multiple(Multiple), Address(Address), @@ -191,14 +192,14 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const PublicRecord &R); class StackCFIRecord : public Record { public: - static llvm::Optional<StackCFIRecord> parse(llvm::StringRef Line); - StackCFIRecord(lldb::addr_t Address, llvm::Optional<lldb::addr_t> Size, + static std::optional<StackCFIRecord> parse(llvm::StringRef Line); + StackCFIRecord(lldb::addr_t Address, std::optional<lldb::addr_t> Size, llvm::StringRef UnwindRules) : Record(StackCFI), Address(Address), Size(Size), UnwindRules(UnwindRules) {} lldb::addr_t Address; - llvm::Optional<lldb::addr_t> Size; + std::optional<lldb::addr_t> Size; llvm::StringRef UnwindRules; }; @@ -207,7 +208,7 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const StackCFIRecord &R); class StackWinRecord : public Record { public: - static llvm::Optional<StackWinRecord> parse(llvm::StringRef Line); + static std::optional<StackWinRecord> parse(llvm::StringRef Line); StackWinRecord(lldb::addr_t RVA, lldb::addr_t CodeSize, lldb::addr_t ParameterSize, lldb::addr_t SavedRegisterSize, diff --git a/contrib/llvm-project/lldb/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.cpp b/contrib/llvm-project/lldb/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.cpp index c591a4a7534c..33673f139b49 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.cpp @@ -11,6 +11,7 @@ #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/Section.h" +#include <optional> using namespace lldb; using namespace lldb_private; @@ -22,16 +23,16 @@ namespace { struct Header { ArchSpec arch; UUID uuid; - static llvm::Optional<Header> parse(llvm::StringRef text); + static std::optional<Header> parse(llvm::StringRef text); }; } // namespace -llvm::Optional<Header> Header::parse(llvm::StringRef text) { +std::optional<Header> Header::parse(llvm::StringRef text) { llvm::StringRef line; std::tie(line, text) = text.split('\n'); auto Module = ModuleRecord::parse(line); if (!Module) - return llvm::None; + return std::nullopt; llvm::Triple triple; triple.setArch(Module->Arch); @@ -66,7 +67,7 @@ ObjectFile *ObjectFileBreakpad::CreateInstance( data_offset = 0; } auto text = toStringRef(data_sp->GetData()); - llvm::Optional<Header> header = Header::parse(text); + std::optional<Header> header = Header::parse(text); if (!header) return nullptr; @@ -93,7 +94,7 @@ size_t ObjectFileBreakpad::GetModuleSpecifications( const FileSpec &file, DataBufferSP &data_sp, offset_t data_offset, offset_t file_offset, offset_t length, ModuleSpecList &specs) { auto text = toStringRef(data_sp->GetData()); - llvm::Optional<Header> header = Header::parse(text); + std::optional<Header> header = Header::parse(text); if (!header) return 0; ModuleSpec spec(file, std::move(header->arch)); @@ -127,7 +128,7 @@ void ObjectFileBreakpad::CreateSections(SectionList &unified_section_list) { return; m_sections_up = std::make_unique<SectionList>(); - llvm::Optional<Record::Kind> current_section; + std::optional<Record::Kind> current_section; offset_t section_start; llvm::StringRef text = toStringRef(m_data.GetData()); uint32_t next_section_id = 1; @@ -148,7 +149,7 @@ void ObjectFileBreakpad::CreateSections(SectionList &unified_section_list) { llvm::StringRef line; std::tie(line, text) = text.split('\n'); - llvm::Optional<Record::Kind> next_section = Record::classify(line); + std::optional<Record::Kind> next_section = Record::classify(line); if (next_section == Record::Line || next_section == Record::Inline) { // Line/Inline records logically belong to the preceding Func record, so // we put them in the same section. diff --git a/contrib/llvm-project/lldb/source/Plugins/ObjectFile/ELF/ELFHeader.cpp b/contrib/llvm-project/lldb/source/Plugins/ObjectFile/ELF/ELFHeader.cpp index abda0cd0e9a3..a6e385f70709 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ObjectFile/ELF/ELFHeader.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ObjectFile/ELF/ELFHeader.cpp @@ -211,6 +211,9 @@ unsigned ELFHeader::GetRelocationJumpSlotType() const { case EM_RISCV: slot = R_RISCV_JUMP_SLOT; break; + case EM_LOONGARCH: + slot = R_LARCH_JUMP_SLOT; + break; } return slot; diff --git a/contrib/llvm-project/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/contrib/llvm-project/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp index 122298d87bf8..9131367bf223 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp @@ -10,6 +10,7 @@ #include <algorithm> #include <cassert> +#include <optional> #include <unordered_map> #include "lldb/Core/FileSpecList.h" @@ -121,6 +122,8 @@ public: static unsigned RelocAddend64(const ELFRelocation &rel); + bool IsRela() { return (reloc.is<ELFRela *>()); } + private: typedef llvm::PointerUnion<ELFRel *, ELFRela *> RelocUnion; @@ -318,6 +321,18 @@ static uint32_t ppc64VariantFromElfFlags(const elf::ELFHeader &header) { return ArchSpec::eCore_ppc64_generic; } +static uint32_t loongarchVariantFromElfFlags(const elf::ELFHeader &header) { + uint32_t fileclass = header.e_ident[EI_CLASS]; + switch (fileclass) { + case llvm::ELF::ELFCLASS32: + return ArchSpec::eLoongArchSubType_loongarch32; + case llvm::ELF::ELFCLASS64: + return ArchSpec::eLoongArchSubType_loongarch64; + default: + return ArchSpec::eLoongArchSubType_unknown; + } +} + static uint32_t subTypeFromElfHeader(const elf::ELFHeader &header) { if (header.e_machine == llvm::ELF::EM_MIPS) return mipsVariantFromElfFlags(header); @@ -325,6 +340,8 @@ static uint32_t subTypeFromElfHeader(const elf::ELFHeader &header) { return ppc64VariantFromElfFlags(header); else if (header.e_machine == llvm::ELF::EM_RISCV) return riscvVariantFromElfFlags(header); + else if (header.e_machine == llvm::ELF::EM_LOONGARCH) + return loongarchVariantFromElfFlags(header); return LLDB_INVALID_CPUTYPE; } @@ -430,8 +447,8 @@ bool ObjectFileELF::MagicBytesMatch(DataBufferSP &data_sp, } static uint32_t calc_crc32(uint32_t init, const DataExtractor &data) { - return llvm::crc32( - init, llvm::makeArrayRef(data.GetDataStart(), data.GetByteSize())); + return llvm::crc32(init, + llvm::ArrayRef(data.GetDataStart(), data.GetByteSize())); } uint32_t ObjectFileELF::CalculateELFNotesSegmentsCRC32( @@ -627,13 +644,13 @@ size_t ObjectFileELF::GetModuleSpecifications( if (gnu_debuglink_crc) { // Use 4 bytes of crc from the .gnu_debuglink section. u32le data(gnu_debuglink_crc); - uuid = UUID::fromData(&data, sizeof(data)); + uuid = UUID(&data, sizeof(data)); } else if (core_notes_crc) { // Use 8 bytes - first 4 bytes for *magic* prefix, mainly to make // it look different form .gnu_debuglink crc followed by 4 bytes // of note segments crc. u32le data[] = {u32le(g_core_uuid_magic), u32le(core_notes_crc)}; - uuid = UUID::fromData(data, sizeof(data)); + uuid = UUID(data, sizeof(data)); } } @@ -788,7 +805,7 @@ UUID ObjectFileELF::GetUUID() { // look different form .gnu_debuglink crc - followed by 4 bytes of note // segments crc. u32le data[] = {u32le(g_core_uuid_magic), u32le(core_notes_crc)}; - m_uuid = UUID::fromData(data, sizeof(data)); + m_uuid = UUID(data, sizeof(data)); } } else { if (!m_gnu_debuglink_crc) @@ -796,7 +813,7 @@ UUID ObjectFileELF::GetUUID() { if (m_gnu_debuglink_crc) { // Use 4 bytes of crc from the .gnu_debuglink section. u32le data(m_gnu_debuglink_crc); - m_uuid = UUID::fromData(&data, sizeof(data)); + m_uuid = UUID(&data, sizeof(data)); } } } @@ -804,9 +821,9 @@ UUID ObjectFileELF::GetUUID() { return m_uuid; } -llvm::Optional<FileSpec> ObjectFileELF::GetDebugLink() { +std::optional<FileSpec> ObjectFileELF::GetDebugLink() { if (m_gnu_debuglink_file.empty()) - return llvm::None; + return std::nullopt; return FileSpec(m_gnu_debuglink_file); } @@ -1134,7 +1151,7 @@ ObjectFileELF::RefineModuleDetailsFromNote(lldb_private::DataExtractor &data, if (note.n_descsz >= 4) { if (const uint8_t *buf = data.PeekData(offset, note.n_descsz)) { // Save the build id as the UUID for the module. - uuid = UUID::fromData(buf, note.n_descsz); + uuid = UUID(buf, note.n_descsz); } else { error.SetErrorString("failed to read GNU_BUILD_ID note payload"); return error; @@ -1750,22 +1767,22 @@ public: return llvm::formatv("{0}[{1}]", SegmentName, SegmentCount).str(); } - llvm::Optional<VMRange> GetAddressInfo(const ELFProgramHeader &H) { + std::optional<VMRange> GetAddressInfo(const ELFProgramHeader &H) { if (H.p_memsz == 0) { LLDB_LOG(Log, "Ignoring zero-sized {0} segment. Corrupt object file?", SegmentName); - return llvm::None; + return std::nullopt; } if (Segments.overlaps(H.p_vaddr, H.p_vaddr + H.p_memsz)) { LLDB_LOG(Log, "Ignoring overlapping {0} segment. Corrupt object file?", SegmentName); - return llvm::None; + return std::nullopt; } return VMRange(H.p_vaddr, H.p_memsz); } - llvm::Optional<SectionAddressInfo> GetAddressInfo(const ELFSectionHeader &H) { + std::optional<SectionAddressInfo> GetAddressInfo(const ELFSectionHeader &H) { VMRange Range = GetVMRange(H); SectionSP Segment; auto It = Segments.find(Range.GetRangeBase()); @@ -1785,7 +1802,7 @@ public: if (Range.GetByteSize() > 0 && Sections.overlaps(Range.GetRangeBase(), Range.GetRangeEnd())) { LLDB_LOG(Log, "Ignoring overlapping section. Corrupt object file?"); - return llvm::None; + return std::nullopt; } if (Segment) Range.Slide(-Segment->GetFileAddress()); @@ -1935,7 +1952,7 @@ std::shared_ptr<ObjectFileELF> ObjectFileELF::GetGnuDebugDataObjectFile() { auto err = lldb_private::lzma::uncompress(data.GetData(), uncompressedData); if (err) { GetModule()->ReportWarning( - "An error occurred while decompression the section %s: %s", + "An error occurred while decompression the section {0}: {1}", section->GetName().AsCString(), llvm::toString(std::move(err)).c_str()); return nullptr; } @@ -2223,23 +2240,6 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id, // symbols. See above for more details. uint64_t symbol_value = symbol.st_value + symbol_value_offset; - if (symbol_section_sp == nullptr && shndx == SHN_ABS && - symbol.st_size != 0) { - // We don't have a section for a symbol with non-zero size. Create a new - // section for it so the address range covered by the symbol is also - // covered by the module (represented through the section list). It is - // needed so module lookup for the addresses covered by this symbol will - // be successfull. This case happens for absolute symbols. - ConstString fake_section_name(std::string(".absolute.") + symbol_name); - symbol_section_sp = - std::make_shared<Section>(module_sp, this, SHN_ABS, fake_section_name, - eSectionTypeAbsoluteAddress, symbol_value, - symbol.st_size, 0, 0, 0, SHF_ALLOC); - - module_section_list->AddSection(symbol_section_sp); - section_list->AddSection(symbol_section_sp); - } - if (symbol_section_sp && CalculateType() != ObjectFile::Type::eTypeObjectFile) symbol_value -= symbol_section_sp->GetFileAddress(); @@ -2614,25 +2614,46 @@ unsigned ObjectFileELF::ApplyRelocations( } for (unsigned i = 0; i < num_relocations; ++i) { - if (!rel.Parse(rel_data, &offset)) + if (!rel.Parse(rel_data, &offset)) { + GetModule()->ReportError(".rel{0}[{1:d}] failed to parse relocation", + rel_section->GetName().AsCString(), i); break; - + } Symbol *symbol = nullptr; if (hdr->Is32Bit()) { switch (reloc_type(rel)) { case R_386_32: + symbol = symtab->FindSymbolByID(reloc_symbol(rel)); + if (symbol) { + addr_t f_offset = + rel_section->GetFileOffset() + ELFRelocation::RelocOffset32(rel); + DataBufferSP &data_buffer_sp = debug_data.GetSharedDataBuffer(); + // ObjectFileELF creates a WritableDataBuffer in CreateInstance. + WritableDataBuffer *data_buffer = + llvm::cast<WritableDataBuffer>(data_buffer_sp.get()); + uint32_t *dst = reinterpret_cast<uint32_t *>( + data_buffer->GetBytes() + f_offset); + + addr_t value = symbol->GetAddressRef().GetFileAddress(); + if (rel.IsRela()) { + value += ELFRelocation::RelocAddend32(rel); + } else { + value += *dst; + } + *dst = value; + } else { + GetModule()->ReportError(".rel{0}[{1}] unknown symbol id: {2:d}", + rel_section->GetName().AsCString(), i, + reloc_symbol(rel)); + } + break; case R_386_PC32: default: - // FIXME: This asserts with this input: - // - // foo.cpp - // int main(int argc, char **argv) { return 0; } - // - // clang++.exe --target=i686-unknown-linux-gnu -g -c foo.cpp -o foo.o - // - // and running this on the foo.o module. - assert(false && "unexpected relocation type"); + GetModule()->ReportError("unsupported 32-bit relocation:" + " .rel{0}[{1}], type {2}", + rel_section->GetName().AsCString(), i, + reloc_type(rel)); } } else { switch (reloc_type(rel)) { @@ -3375,7 +3396,7 @@ size_t ObjectFileELF::ReadSectionData(Section *section, GetByteOrder() == eByteOrderLittle, GetAddressByteSize() == 8); if (!Decompressor) { GetModule()->ReportWarning( - "Unable to initialize decompressor for section '%s': %s", + "Unable to initialize decompressor for section '{0}': {1}", section->GetName().GetCString(), llvm::toString(Decompressor.takeError()).c_str()); section_data.Clear(); @@ -3386,10 +3407,9 @@ size_t ObjectFileELF::ReadSectionData(Section *section, std::make_shared<DataBufferHeap>(Decompressor->getDecompressedSize(), 0); if (auto error = Decompressor->decompress( {buffer_sp->GetBytes(), size_t(buffer_sp->GetByteSize())})) { - GetModule()->ReportWarning( - "Decompression of section '%s' failed: %s", - section->GetName().GetCString(), - llvm::toString(std::move(error)).c_str()); + GetModule()->ReportWarning("Decompression of section '{0}' failed: {1}", + section->GetName().GetCString(), + llvm::toString(std::move(error)).c_str()); section_data.Clear(); return 0; } diff --git a/contrib/llvm-project/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h b/contrib/llvm-project/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h index 5deb2c7d163c..bc8e34981a9d 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h +++ b/contrib/llvm-project/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h @@ -11,6 +11,7 @@ #include <cstdint> +#include <optional> #include <vector> #include "lldb/Symbol/ObjectFile.h" @@ -124,7 +125,7 @@ public: /// Return the contents of the .gnu_debuglink section, if the object file /// contains it. - llvm::Optional<lldb_private::FileSpec> GetDebugLink(); + std::optional<lldb_private::FileSpec> GetDebugLink(); uint32_t GetDependentModules(lldb_private::FileSpecList &files) override; diff --git a/contrib/llvm-project/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.cpp b/contrib/llvm-project/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.cpp index 44c708676e52..c62a67fa29f9 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.cpp @@ -31,7 +31,7 @@ static UUID GetPDBUUID(InfoStream &IS) { UUID::CvRecordPdb70 debug_info; memcpy(&debug_info.Uuid, IS.getGuid().Guid, sizeof(debug_info.Uuid)); debug_info.Age = IS.getAge(); - return UUID::fromCvRecord(debug_info); + return UUID(debug_info); } char ObjectFilePDB::ID; diff --git a/contrib/llvm-project/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp b/contrib/llvm-project/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp index 905e9637493b..06eb6ff9cafb 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp @@ -24,6 +24,7 @@ #include "llvm/BinaryFormat/Wasm.h" #include "llvm/Support/Endian.h" #include "llvm/Support/Format.h" +#include <optional> using namespace lldb; using namespace lldb_private; @@ -49,7 +50,7 @@ static bool ValidateModuleHeader(const DataBufferSP &data_sp) { return version == llvm::wasm::WasmVersion; } -static llvm::Optional<ConstString> +static std::optional<ConstString> GetWasmString(llvm::DataExtractor &data, llvm::DataExtractor::Cursor &c) { // A Wasm string is encoded as a vector of UTF-8 codes. // Vectors are encoded with their u32 length followed by the element @@ -57,21 +58,21 @@ GetWasmString(llvm::DataExtractor &data, llvm::DataExtractor::Cursor &c) { uint64_t len = data.getULEB128(c); if (!c) { consumeError(c.takeError()); - return llvm::None; + return std::nullopt; } if (len >= (uint64_t(1) << 32)) { - return llvm::None; + return std::nullopt; } llvm::SmallVector<uint8_t, 32> str_storage; data.getU8(c, str_storage, len); if (!c) { consumeError(c.takeError()); - return llvm::None; + return std::nullopt; } - llvm::StringRef str = toStringRef(makeArrayRef(str_storage)); + llvm::StringRef str = toStringRef(llvm::ArrayRef(str_storage)); return ConstString(str); } @@ -181,7 +182,7 @@ bool ObjectFileWasm::DecodeNextSection(lldb::offset_t *offset_ptr) { // identifying the custom section, followed by an uninterpreted sequence // of bytes. lldb::offset_t prev_offset = c.tell(); - llvm::Optional<ConstString> sect_name = GetWasmString(data, c); + std::optional<ConstString> sect_name = GetWasmString(data, c); if (!sect_name) return false; @@ -412,7 +413,7 @@ DataExtractor ObjectFileWasm::ReadImageData(offset_t offset, uint32_t size) { return data; } -llvm::Optional<FileSpec> ObjectFileWasm::GetExternalDebugInfoFileSpec() { +std::optional<FileSpec> ObjectFileWasm::GetExternalDebugInfoFileSpec() { static ConstString g_sect_name_external_debug_info("external_debug_info"); for (const section_info §_info : m_sect_infos) { @@ -422,12 +423,12 @@ llvm::Optional<FileSpec> ObjectFileWasm::GetExternalDebugInfoFileSpec() { ReadImageData(sect_info.offset, kBufferSize); llvm::DataExtractor data = section_header_data.GetAsLLVM(); llvm::DataExtractor::Cursor c(0); - llvm::Optional<ConstString> symbols_url = GetWasmString(data, c); + std::optional<ConstString> symbols_url = GetWasmString(data, c); if (symbols_url) return FileSpec(symbols_url->GetStringRef()); } } - return llvm::None; + return std::nullopt; } void ObjectFileWasm::Dump(Stream *s) { diff --git a/contrib/llvm-project/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.h b/contrib/llvm-project/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.h index 5676030f955e..531b5f0437a4 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.h +++ b/contrib/llvm-project/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.h @@ -11,6 +11,7 @@ #include "lldb/Symbol/ObjectFile.h" #include "lldb/Utility/ArchSpec.h" +#include <optional> namespace lldb_private { namespace wasm { @@ -108,7 +109,7 @@ public: /// custom section named "external_debug_info", whose payload is an UTF-8 /// encoded string that points to a Wasm module that contains the debug /// information for this module. - llvm::Optional<FileSpec> GetExternalDebugInfoFileSpec(); + std::optional<FileSpec> GetExternalDebugInfoFileSpec(); private: ObjectFileWasm(const lldb::ModuleSP &module_sp, lldb::DataBufferSP data_sp, diff --git a/contrib/llvm-project/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp b/contrib/llvm-project/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp index 17c86a435aa8..0c6831b77d87 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp @@ -187,9 +187,12 @@ MmapArgList PlatformFreeBSD::GetMmapArgumentList(const ArchSpec &arch, } CompilerType PlatformFreeBSD::GetSiginfoType(const llvm::Triple &triple) { - if (!m_type_system_up) - m_type_system_up.reset(new TypeSystemClang("siginfo", triple)); - TypeSystemClang *ast = m_type_system_up.get(); + { + std::lock_guard<std::mutex> guard(m_mutex); + if (!m_type_system) + m_type_system = std::make_shared<TypeSystemClang>("siginfo", triple); + } + TypeSystemClang *ast = m_type_system.get(); // generic types CompilerType int_type = ast->GetBasicType(eBasicTypeInt); diff --git a/contrib/llvm-project/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h b/contrib/llvm-project/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h index 4aeedb62931d..1e92bb4a1e14 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h +++ b/contrib/llvm-project/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h @@ -60,7 +60,8 @@ public: std::vector<ArchSpec> m_supported_architectures; private: - std::unique_ptr<TypeSystemClang> m_type_system_up; + std::mutex m_mutex; + std::shared_ptr<TypeSystemClang> m_type_system; }; } // namespace platform_freebsd diff --git a/contrib/llvm-project/lldb/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp b/contrib/llvm-project/lldb/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp index d79fe664cb1c..59bbc3f638af 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp @@ -206,9 +206,12 @@ MmapArgList PlatformNetBSD::GetMmapArgumentList(const ArchSpec &arch, } CompilerType PlatformNetBSD::GetSiginfoType(const llvm::Triple &triple) { - if (!m_type_system_up) - m_type_system_up.reset(new TypeSystemClang("siginfo", triple)); - TypeSystemClang *ast = m_type_system_up.get(); + { + std::lock_guard<std::mutex> guard(m_mutex); + if (!m_type_system) + m_type_system = std::make_shared<TypeSystemClang>("siginfo", triple); + } + TypeSystemClang *ast = m_type_system.get(); // generic types CompilerType int_type = ast->GetBasicType(eBasicTypeInt); diff --git a/contrib/llvm-project/lldb/source/Plugins/Platform/NetBSD/PlatformNetBSD.h b/contrib/llvm-project/lldb/source/Plugins/Platform/NetBSD/PlatformNetBSD.h index 2613311790a3..3437d7e5eb51 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Platform/NetBSD/PlatformNetBSD.h +++ b/contrib/llvm-project/lldb/source/Plugins/Platform/NetBSD/PlatformNetBSD.h @@ -62,7 +62,8 @@ public: std::vector<ArchSpec> m_supported_architectures; private: - std::unique_ptr<TypeSystemClang> m_type_system_up; + std::mutex m_mutex; + std::shared_ptr<TypeSystemClang> m_type_system; }; } // namespace platform_netbsd diff --git a/contrib/llvm-project/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp b/contrib/llvm-project/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp index fb0d39ea6f86..222dbfa71964 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp @@ -33,6 +33,7 @@ #include "lldb/Utility/Log.h" #include "lldb/Utility/StreamString.h" #include "llvm/ADT/ScopeExit.h" +#include <optional> using namespace lldb; using namespace lldb_private; @@ -626,15 +627,15 @@ PlatformPOSIX::MakeLoadImageUtilityFunction(ExecutionContext &exe_ctx, FunctionCaller *do_dlopen_function = nullptr; // Fetch the clang types we will need: - TypeSystemClang *ast = + TypeSystemClangSP scratch_ts_sp = ScratchTypeSystemClang::GetForTarget(process->GetTarget()); - if (!ast) + if (!scratch_ts_sp) return nullptr; - CompilerType clang_void_pointer_type - = ast->GetBasicType(eBasicTypeVoid).GetPointerType(); - CompilerType clang_char_pointer_type - = ast->GetBasicType(eBasicTypeChar).GetPointerType(); + CompilerType clang_void_pointer_type = + scratch_ts_sp->GetBasicType(eBasicTypeVoid).GetPointerType(); + CompilerType clang_char_pointer_type = + scratch_ts_sp->GetBasicType(eBasicTypeChar).GetPointerType(); // We are passing four arguments, the basename, the list of places to look, // a buffer big enough for all the path + name combos, and @@ -760,15 +761,14 @@ uint32_t PlatformPOSIX::DoLoadImage(lldb_private::Process *process, // This will be the address of the storage for paths, if we are using them, // or nullptr to signal we aren't. lldb::addr_t path_array_addr = 0x0; - llvm::Optional<llvm::detail::scope_exit<std::function<void()>>> + std::optional<llvm::detail::scope_exit<std::function<void()>>> path_array_cleanup; // This is the address to a buffer large enough to hold the largest path // conjoined with the library name we're passing in. This is a convenience // to avoid having to call malloc in the dlopen function. lldb::addr_t buffer_addr = 0x0; - llvm::Optional<llvm::detail::scope_exit<std::function<void()>>> - buffer_cleanup; + std::optional<llvm::detail::scope_exit<std::function<void()>>> buffer_cleanup; // Set the values into our args and write them to the target: if (paths != nullptr) { @@ -876,15 +876,15 @@ uint32_t PlatformPOSIX::DoLoadImage(lldb_private::Process *process, Value return_value; // Fetch the clang types we will need: - TypeSystemClang *ast = + TypeSystemClangSP scratch_ts_sp = ScratchTypeSystemClang::GetForTarget(process->GetTarget()); - if (!ast) { + if (!scratch_ts_sp) { error.SetErrorString("dlopen error: Unable to get TypeSystemClang"); return LLDB_INVALID_IMAGE_TOKEN; } - CompilerType clang_void_pointer_type - = ast->GetBasicType(eBasicTypeVoid).GetPointerType(); + CompilerType clang_void_pointer_type = + scratch_ts_sp->GetBasicType(eBasicTypeVoid).GetPointerType(); return_value.SetCompilerType(clang_void_pointer_type); diff --git a/contrib/llvm-project/lldb/source/Plugins/Platform/QemuUser/PlatformQemuUser.cpp b/contrib/llvm-project/lldb/source/Plugins/Platform/QemuUser/PlatformQemuUser.cpp index 7ee92ef76c9c..4ba20117cdb5 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Platform/QemuUser/PlatformQemuUser.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Platform/QemuUser/PlatformQemuUser.cpp @@ -23,6 +23,7 @@ using namespace lldb_private; LLDB_PLUGIN_DEFINE(PlatformQemuUser) +namespace { #define LLDB_PROPERTIES_platformqemuuser #include "PlatformQemuUserProperties.inc" @@ -71,6 +72,8 @@ public: } }; +} // namespace + static PluginProperties &GetGlobalProperties() { static PluginProperties g_settings; return g_settings; diff --git a/contrib/llvm-project/lldb/source/Plugins/Platform/QemuUser/PlatformQemuUser.h b/contrib/llvm-project/lldb/source/Plugins/Platform/QemuUser/PlatformQemuUser.h index 0dd0e2f6f2b9..596cf75b591f 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Platform/QemuUser/PlatformQemuUser.h +++ b/contrib/llvm-project/lldb/source/Plugins/Platform/QemuUser/PlatformQemuUser.h @@ -6,6 +6,9 @@ // //===----------------------------------------------------------------------===// +#ifndef LLDB_SOURCE_PLUGINS_PLATFORM_QEMUUSER_PLATFORMQEMUUSER_H +#define LLDB_SOURCE_PLUGINS_PLATFORM_QEMUUSER_PLATFORMQEMUUSER_H + #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.h" #include "lldb/Target/Platform.h" @@ -42,6 +45,16 @@ public: return nullptr; } + uint32_t FindProcesses(const ProcessInstanceInfoMatch &match_info, + ProcessInstanceInfoList &proc_infos) override { + return 0; + } + + bool GetProcessInfo(lldb::pid_t pid, + ProcessInstanceInfo &proc_info) override { + return false; + } + bool IsConnected() const override { return true; } void CalculateTrapHandlerSymbolNames() override {} @@ -64,3 +77,5 @@ private: }; } // namespace lldb_private + +#endif // LLDB_SOURCE_PLUGINS_PLATFORM_QEMUUSER_PLATFORMQEMUUSER_H diff --git a/contrib/llvm-project/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp b/contrib/llvm-project/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp index 243866188629..0858a2a8d3c8 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp @@ -29,9 +29,11 @@ #include "lldb/Utility/Status.h" #include "lldb/Utility/StreamString.h" #include "lldb/Utility/UriParser.h" +#include "llvm/Support/FormatAdapters.h" #include "Plugins/Process/Utility/GDBRemoteSignals.h" #include "Plugins/Process/gdb-remote/ProcessGDBRemote.h" +#include <optional> using namespace lldb; using namespace lldb_private; @@ -150,16 +152,16 @@ bool PlatformRemoteGDBServer::GetRemoteOSVersion() { return !m_os_version.empty(); } -llvm::Optional<std::string> PlatformRemoteGDBServer::GetRemoteOSBuildString() { +std::optional<std::string> PlatformRemoteGDBServer::GetRemoteOSBuildString() { if (!m_gdb_client_up) - return llvm::None; + return std::nullopt; return m_gdb_client_up->GetOSBuildString(); } -llvm::Optional<std::string> +std::optional<std::string> PlatformRemoteGDBServer::GetRemoteOSKernelDescription() { if (!m_gdb_client_up) - return llvm::None; + return std::nullopt; return m_gdb_client_up->GetOSKernelDescription(); } @@ -177,7 +179,7 @@ FileSpec PlatformRemoteGDBServer::GetRemoteWorkingDirectory() { if (m_gdb_client_up->GetWorkingDir(working_dir) && log) LLDB_LOGF(log, "PlatformRemoteGDBServer::GetRemoteWorkingDirectory() -> '%s'", - working_dir.GetCString()); + working_dir.GetPath().c_str()); return working_dir; } else { return Platform::GetRemoteWorkingDirectory(); @@ -191,7 +193,7 @@ bool PlatformRemoteGDBServer::SetRemoteWorkingDirectory( // will for use to re-read it Log *log = GetLog(LLDBLog::Platform); LLDB_LOGF(log, "PlatformRemoteGDBServer::SetRemoteWorkingDirectory('%s')", - working_dir.GetCString()); + working_dir.GetPath().c_str()); return m_gdb_client_up->SetWorkingDir(working_dir) == 0; } else return Platform::SetRemoteWorkingDirectory(working_dir); @@ -225,7 +227,7 @@ Status PlatformRemoteGDBServer::ConnectRemote(Args &args) { if (!url) return Status("URL is null."); - llvm::Optional<URI> parsed_url = URI::Parse(url); + std::optional<URI> parsed_url = URI::Parse(url); if (!parsed_url) return Status("Invalid URL: %s", url); @@ -238,11 +240,6 @@ Status PlatformRemoteGDBServer::ConnectRemote(Args &args) { client_up->SetPacketTimeout( process_gdb_remote::ProcessGDBRemote::GetPacketTimeout()); client_up->SetConnection(std::make_unique<ConnectionFileDescriptor>()); - if (repro::Generator *g = repro::Reproducer::Instance().GetGenerator()) { - repro::GDBRemoteProvider &provider = - g->GetOrCreate<repro::GDBRemoteProvider>(); - client_up->SetPacketRecorder(provider.GetNewPacketRecorder()); - } client_up->Connect(url, &error); if (error.Fail()) @@ -287,20 +284,20 @@ const char *PlatformRemoteGDBServer::GetHostname() { return m_hostname.c_str(); } -llvm::Optional<std::string> +std::optional<std::string> PlatformRemoteGDBServer::DoGetUserName(UserIDResolver::id_t uid) { std::string name; if (m_gdb_client_up && m_gdb_client_up->GetUserName(uid, name)) return std::move(name); - return llvm::None; + return std::nullopt; } -llvm::Optional<std::string> +std::optional<std::string> PlatformRemoteGDBServer::DoGetGroupName(UserIDResolver::id_t gid) { std::string name; if (m_gdb_client_up && m_gdb_client_up->GetGroupName(gid, name)) return std::move(name); - return llvm::None; + return std::nullopt; } uint32_t PlatformRemoteGDBServer::FindProcesses( @@ -366,39 +363,36 @@ Status PlatformRemoteGDBServer::LaunchProcess(ProcessLaunchInfo &launch_info) { "PlatformRemoteGDBServer::%s() set launch architecture triple to '%s'", __FUNCTION__, arch_triple ? arch_triple : "<NULL>"); - int arg_packet_err; { // Scope for the scoped timeout object process_gdb_remote::GDBRemoteCommunication::ScopedTimeout timeout( *m_gdb_client_up, std::chrono::seconds(5)); - arg_packet_err = m_gdb_client_up->SendArgumentsPacket(launch_info); + // Since we can't send argv0 separate from the executable path, we need to + // make sure to use the actual executable path found in the launch_info... + Args args = launch_info.GetArguments(); + if (FileSpec exe_file = launch_info.GetExecutableFile()) + args.ReplaceArgumentAtIndex(0, exe_file.GetPath(false)); + if (llvm::Error err = m_gdb_client_up->LaunchProcess(args)) { + error.SetErrorStringWithFormatv("Cannot launch '{0}': {1}", + args.GetArgumentAtIndex(0), + llvm::fmt_consume(std::move(err))); + return error; + } } - if (arg_packet_err == 0) { - std::string error_str; - if (m_gdb_client_up->GetLaunchSuccess(error_str)) { - const auto pid = m_gdb_client_up->GetCurrentProcessID(false); - if (pid != LLDB_INVALID_PROCESS_ID) { - launch_info.SetProcessID(pid); - LLDB_LOGF(log, - "PlatformRemoteGDBServer::%s() pid %" PRIu64 - " launched successfully", - __FUNCTION__, pid); - } else { - LLDB_LOGF(log, - "PlatformRemoteGDBServer::%s() launch succeeded but we " - "didn't get a valid process id back!", - __FUNCTION__); - error.SetErrorString("failed to get PID"); - } - } else { - error.SetErrorString(error_str.c_str()); - LLDB_LOGF(log, "PlatformRemoteGDBServer::%s() launch failed: %s", - __FUNCTION__, error.AsCString()); - } + const auto pid = m_gdb_client_up->GetCurrentProcessID(false); + if (pid != LLDB_INVALID_PROCESS_ID) { + launch_info.SetProcessID(pid); + LLDB_LOGF(log, + "PlatformRemoteGDBServer::%s() pid %" PRIu64 + " launched successfully", + __FUNCTION__, pid); } else { - error.SetErrorStringWithFormat("'A' packet returned an error: %i", - arg_packet_err); + LLDB_LOGF(log, + "PlatformRemoteGDBServer::%s() launch succeeded but we " + "didn't get a valid process id back!", + __FUNCTION__); + error.SetErrorString("failed to get PID"); } return error; } @@ -546,7 +540,8 @@ Status PlatformRemoteGDBServer::MakeDirectory(const FileSpec &file_spec, LLDB_LOGF(log, "PlatformRemoteGDBServer::MakeDirectory(path='%s', mode=%o) " "error = %u (%s)", - file_spec.GetCString(), mode, error.GetError(), error.AsCString()); + file_spec.GetPath().c_str(), mode, error.GetError(), + error.AsCString()); return error; } @@ -560,7 +555,7 @@ Status PlatformRemoteGDBServer::GetFilePermissions(const FileSpec &file_spec, LLDB_LOGF(log, "PlatformRemoteGDBServer::GetFilePermissions(path='%s', " "file_permissions=%o) error = %u (%s)", - file_spec.GetCString(), file_permissions, error.GetError(), + file_spec.GetPath().c_str(), file_permissions, error.GetError(), error.AsCString()); return error; } @@ -575,7 +570,7 @@ Status PlatformRemoteGDBServer::SetFilePermissions(const FileSpec &file_spec, LLDB_LOGF(log, "PlatformRemoteGDBServer::SetFilePermissions(path='%s', " "file_permissions=%o) error = %u (%s)", - file_spec.GetCString(), file_permissions, error.GetError(), + file_spec.GetPath().c_str(), file_permissions, error.GetError(), error.AsCString()); return error; } @@ -644,7 +639,7 @@ Status PlatformRemoteGDBServer::CreateSymlink( LLDB_LOGF(log, "PlatformRemoteGDBServer::CreateSymlink(src='%s', dst='%s') " "error = %u (%s)", - src.GetCString(), dst.GetCString(), error.GetError(), + src.GetPath().c_str(), dst.GetPath().c_str(), error.GetError(), error.AsCString()); return error; } @@ -655,7 +650,7 @@ Status PlatformRemoteGDBServer::Unlink(const FileSpec &file_spec) { Status error = m_gdb_client_up->Unlink(file_spec); Log *log = GetLog(LLDBLog::Platform); LLDB_LOGF(log, "PlatformRemoteGDBServer::Unlink(path='%s') error = %u (%s)", - file_spec.GetCString(), error.GetError(), error.AsCString()); + file_spec.GetPath().c_str(), error.GetError(), error.AsCString()); return error; } @@ -802,7 +797,7 @@ size_t PlatformRemoteGDBServer::ConnectToWaitingProcesses(Debugger &debugger, for (size_t i = 0; i < connection_urls.size(); ++i) { ConnectProcess(connection_urls[i].c_str(), "gdb-remote", debugger, nullptr, error); if (error.Fail()) - return i; // We already connected to i process succsessfully + return i; // We already connected to i process successfully } return connection_urls.size(); } diff --git a/contrib/llvm-project/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h b/contrib/llvm-project/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h index 3caf531edaa8..638f7db5ef80 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h +++ b/contrib/llvm-project/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h @@ -10,6 +10,7 @@ #ifndef LLDB_SOURCE_PLUGINS_PLATFORM_GDB_SERVER_PLATFORMREMOTEGDBSERVER_H #define LLDB_SOURCE_PLUGINS_PLATFORM_GDB_SERVER_PLATFORMREMOTEGDBSERVER_H +#include <optional> #include <string> #include "Plugins/Process/Utility/GDBRemoteSignals.h" @@ -75,9 +76,9 @@ public: bool GetRemoteOSVersion() override; - llvm::Optional<std::string> GetRemoteOSBuildString() override; + std::optional<std::string> GetRemoteOSBuildString() override; - llvm::Optional<std::string> GetRemoteOSKernelDescription() override; + std::optional<std::string> GetRemoteOSKernelDescription() override; // Remote Platform subclasses need to override this function ArchSpec GetRemoteSystemArchitecture() override; @@ -181,8 +182,8 @@ private: const std::string &platform_hostname, uint16_t port, const char *socket_name); - llvm::Optional<std::string> DoGetUserName(UserIDResolver::id_t uid) override; - llvm::Optional<std::string> DoGetGroupName(UserIDResolver::id_t uid) override; + std::optional<std::string> DoGetUserName(UserIDResolver::id_t uid) override; + std::optional<std::string> DoGetGroupName(UserIDResolver::id_t uid) override; std::vector<ArchSpec> m_supported_architectures; diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeProcessFreeBSD.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeProcessFreeBSD.cpp index 5d73ec3457e3..dbaa83fd15d7 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeProcessFreeBSD.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeProcessFreeBSD.cpp @@ -417,9 +417,9 @@ NativeProcessFreeBSD::GetSoftwareBreakpointTrapOpcode(size_t size_hint) { case llvm::Triple::arm: switch (size_hint) { case 2: - return llvm::makeArrayRef(g_thumb_opcode); + return llvm::ArrayRef(g_thumb_opcode); case 4: - return llvm::makeArrayRef(g_arm_opcode); + return llvm::ArrayRef(g_arm_opcode); default: return llvm::createStringError(llvm::inconvertibleErrorCode(), "Unrecognised trap opcode size hint!"); diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_mips64.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_mips64.cpp index 83664b586960..b8db7f2f3788 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_mips64.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_mips64.cpp @@ -22,6 +22,7 @@ #include <sys/ptrace.h> #include <sys/types.h> // clang-format on +#include <optional> using namespace lldb; using namespace lldb_private; @@ -60,7 +61,7 @@ uint32_t NativeRegisterContextFreeBSD_mips64::GetUserRegisterCount() const { return count; } -llvm::Optional<NativeRegisterContextFreeBSD_mips64::RegSetKind> +std::optional<NativeRegisterContextFreeBSD_mips64::RegSetKind> NativeRegisterContextFreeBSD_mips64::GetSetForNativeRegNum( uint32_t reg_num) const { switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) { @@ -120,7 +121,7 @@ NativeRegisterContextFreeBSD_mips64::ReadRegister(const RegisterInfo *reg_info, ? reg_info->name : "<unknown register>"); - llvm::Optional<RegSetKind> opt_set = GetSetForNativeRegNum(reg); + std::optional<RegSetKind> opt_set = GetSetForNativeRegNum(reg); if (!opt_set) { // This is likely an internal register for lldb use only and should not be // directly queried. @@ -154,7 +155,7 @@ Status NativeRegisterContextFreeBSD_mips64::WriteRegister( ? reg_info->name : "<unknown register>"); - llvm::Optional<RegSetKind> opt_set = GetSetForNativeRegNum(reg); + std::optional<RegSetKind> opt_set = GetSetForNativeRegNum(reg); if (!opt_set) { // This is likely an internal register for lldb use only and should not be // directly queried. diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_mips64.h b/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_mips64.h index 7a2c0b34eeee..0b4a508a7d5d 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_mips64.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_mips64.h @@ -20,6 +20,7 @@ #include "Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h" #include <array> +#include <optional> namespace lldb_private { namespace process_freebsd { @@ -58,7 +59,7 @@ private: }; std::array<uint8_t, sizeof(reg) + sizeof(fpreg)> m_reg_data; - llvm::Optional<RegSetKind> GetSetForNativeRegNum(uint32_t reg_num) const; + std::optional<RegSetKind> GetSetForNativeRegNum(uint32_t reg_num) const; Status ReadRegisterSet(RegSetKind set); Status WriteRegisterSet(RegSetKind set); diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_powerpc.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_powerpc.cpp index ee125e5e6881..7ad9e3c209df 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_powerpc.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_powerpc.cpp @@ -24,6 +24,7 @@ #include <sys/ptrace.h> #include <sys/types.h> // clang-format on +#include <optional> using namespace lldb; using namespace lldb_private; @@ -106,7 +107,7 @@ NativeRegisterContextFreeBSD_powerpc::GetRegisterSet(uint32_t set_index) const { } } -llvm::Optional<NativeRegisterContextFreeBSD_powerpc::RegSetKind> +std::optional<NativeRegisterContextFreeBSD_powerpc::RegSetKind> NativeRegisterContextFreeBSD_powerpc::GetSetForNativeRegNum( uint32_t reg_num) const { switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) { @@ -171,7 +172,7 @@ NativeRegisterContextFreeBSD_powerpc::ReadRegister(const RegisterInfo *reg_info, ? reg_info->name : "<unknown register>"); - llvm::Optional<RegSetKind> opt_set = GetSetForNativeRegNum(reg); + std::optional<RegSetKind> opt_set = GetSetForNativeRegNum(reg); if (!opt_set) { // This is likely an internal register for lldb use only and should not be // directly queried. @@ -205,7 +206,7 @@ Status NativeRegisterContextFreeBSD_powerpc::WriteRegister( ? reg_info->name : "<unknown register>"); - llvm::Optional<RegSetKind> opt_set = GetSetForNativeRegNum(reg); + std::optional<RegSetKind> opt_set = GetSetForNativeRegNum(reg); if (!opt_set) { // This is likely an internal register for lldb use only and should not be // directly queried. diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_powerpc.h b/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_powerpc.h index c77394366517..3df371036f91 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_powerpc.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_powerpc.h @@ -20,6 +20,7 @@ #include "Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h" #include <array> +#include <optional> namespace lldb_private { namespace process_freebsd { @@ -58,7 +59,7 @@ private: }; std::array<uint8_t, sizeof(reg) + sizeof(fpreg)> m_reg_data; - llvm::Optional<RegSetKind> GetSetForNativeRegNum(uint32_t reg_num) const; + std::optional<RegSetKind> GetSetForNativeRegNum(uint32_t reg_num) const; Status ReadRegisterSet(RegSetKind set); Status WriteRegisterSet(RegSetKind set); diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_x86_64.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_x86_64.cpp index b69cfa7d5d83..f4171a134aeb 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_x86_64.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_x86_64.cpp @@ -25,6 +25,7 @@ #include "NativeProcessFreeBSD.h" #include "Plugins/Process/Utility/RegisterContextFreeBSD_i386.h" #include "Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h" +#include <optional> using namespace lldb_private; using namespace lldb_private::process_freebsd; @@ -299,7 +300,7 @@ NativeRegisterContextFreeBSD_x86_64::GetRegisterSet(uint32_t set_index) const { } } -llvm::Optional<NativeRegisterContextFreeBSD_x86_64::RegSetKind> +std::optional<NativeRegisterContextFreeBSD_x86_64::RegSetKind> NativeRegisterContextFreeBSD_x86_64::GetSetForNativeRegNum( uint32_t reg_num) const { switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) { @@ -311,9 +312,9 @@ NativeRegisterContextFreeBSD_x86_64::GetSetForNativeRegNum( if (reg_num >= k_first_avx_i386 && reg_num <= k_last_avx_i386) return YMMRegSet; if (reg_num >= k_first_mpxr_i386 && reg_num <= k_last_mpxr_i386) - return llvm::None; // MPXR + return std::nullopt; // MPXR if (reg_num >= k_first_mpxc_i386 && reg_num <= k_last_mpxc_i386) - return llvm::None; // MPXC + return std::nullopt; // MPXC if (reg_num >= k_first_dbr_i386 && reg_num <= k_last_dbr_i386) return DBRegSet; // DBR break; @@ -325,9 +326,9 @@ NativeRegisterContextFreeBSD_x86_64::GetSetForNativeRegNum( if (reg_num >= k_first_avx_x86_64 && reg_num <= k_last_avx_x86_64) return YMMRegSet; if (reg_num >= k_first_mpxr_x86_64 && reg_num <= k_last_mpxr_x86_64) - return llvm::None; // MPXR + return std::nullopt; // MPXR if (reg_num >= k_first_mpxc_x86_64 && reg_num <= k_last_mpxc_x86_64) - return llvm::None; // MPXC + return std::nullopt; // MPXC if (reg_num >= k_first_dbr_x86_64 && reg_num <= k_last_dbr_x86_64) return DBRegSet; // DBR break; @@ -425,7 +426,7 @@ NativeRegisterContextFreeBSD_x86_64::ReadRegister(const RegisterInfo *reg_info, return error; } - llvm::Optional<RegSetKind> opt_set = GetSetForNativeRegNum(reg); + std::optional<RegSetKind> opt_set = GetSetForNativeRegNum(reg); if (!opt_set) { // This is likely an internal register for lldb use only and should not be // directly queried. @@ -434,7 +435,7 @@ NativeRegisterContextFreeBSD_x86_64::ReadRegister(const RegisterInfo *reg_info, return error; } - RegSetKind set = opt_set.getValue(); + RegSetKind set = opt_set.value(); error = ReadRegisterSet(set); if (error.Fail()) return error; @@ -453,7 +454,7 @@ NativeRegisterContextFreeBSD_x86_64::ReadRegister(const RegisterInfo *reg_info, break; } case YMMRegSet: { - llvm::Optional<YMMSplitPtr> ymm_reg = GetYMMSplitReg(reg); + std::optional<YMMSplitPtr> ymm_reg = GetYMMSplitReg(reg); if (!ymm_reg) { error.SetErrorStringWithFormat( "register \"%s\" not supported by CPU/kernel", reg_info->name); @@ -491,7 +492,7 @@ Status NativeRegisterContextFreeBSD_x86_64::WriteRegister( return error; } - llvm::Optional<RegSetKind> opt_set = GetSetForNativeRegNum(reg); + std::optional<RegSetKind> opt_set = GetSetForNativeRegNum(reg); if (!opt_set) { // This is likely an internal register for lldb use only and should not be // directly queried. @@ -500,7 +501,7 @@ Status NativeRegisterContextFreeBSD_x86_64::WriteRegister( return error; } - RegSetKind set = opt_set.getValue(); + RegSetKind set = opt_set.value(); error = ReadRegisterSet(set); if (error.Fail()) return error; @@ -518,7 +519,7 @@ Status NativeRegisterContextFreeBSD_x86_64::WriteRegister( break; } case YMMRegSet: { - llvm::Optional<YMMSplitPtr> ymm_reg = GetYMMSplitReg(reg); + std::optional<YMMSplitPtr> ymm_reg = GetYMMSplitReg(reg); if (!ymm_reg) { error.SetErrorStringWithFormat( "register \"%s\" not supported by CPU/kernel", reg_info->name); @@ -629,11 +630,11 @@ NativeRegisterContextFreeBSD_x86_64::GetOffsetRegSetData(RegSetKind set, return base + (reg_offset - m_regset_offsets[set]); } -llvm::Optional<NativeRegisterContextFreeBSD_x86_64::YMMSplitPtr> +std::optional<NativeRegisterContextFreeBSD_x86_64::YMMSplitPtr> NativeRegisterContextFreeBSD_x86_64::GetYMMSplitReg(uint32_t reg) { uint32_t offset = m_xsave_offsets[YMMRegSet]; if (offset == LLDB_INVALID_XSAVE_OFFSET) - return llvm::None; + return std::nullopt; uint32_t reg_index; switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) { diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_x86_64.h b/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_x86_64.h index 366a89b6eec8..54ec9fc154ca 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_x86_64.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_x86_64.h @@ -19,6 +19,7 @@ // clang-format on #include <array> +#include <optional> #include "Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD.h" #include "Plugins/Process/Utility/RegisterContext_x86.h" @@ -74,7 +75,7 @@ private: std::array<uint32_t, MaxRegSet + 1> m_xsave_offsets; std::array<size_t, MaxRegSet + 1> m_regset_offsets; - llvm::Optional<RegSetKind> GetSetForNativeRegNum(uint32_t reg_num) const; + std::optional<RegSetKind> GetSetForNativeRegNum(uint32_t reg_num) const; Status ReadRegisterSet(RegSetKind set); Status WriteRegisterSet(RegSetKind set); @@ -85,7 +86,7 @@ private: void *xmm; void *ymm_hi; }; - llvm::Optional<YMMSplitPtr> GetYMMSplitReg(uint32_t reg); + std::optional<YMMSplitPtr> GetYMMSplitReg(uint32_t reg); }; } // namespace process_freebsd diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp index 5a910b5a6ec9..b8de5f084883 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp @@ -31,6 +31,7 @@ #include <err.h> #include <cstdint> #include <cstdlib> +#include <optional> // clang-format on using namespace lldb_private; @@ -306,7 +307,7 @@ NativeRegisterContextNetBSD_x86_64::GetRegisterSet(uint32_t set_index) const { } } -llvm::Optional<NativeRegisterContextNetBSD_x86_64::RegSetKind> +std::optional<NativeRegisterContextNetBSD_x86_64::RegSetKind> NativeRegisterContextNetBSD_x86_64::GetSetForNativeRegNum( uint32_t reg_num) const { switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) { @@ -318,9 +319,9 @@ NativeRegisterContextNetBSD_x86_64::GetSetForNativeRegNum( if (reg_num >= k_first_avx_i386 && reg_num <= k_last_avx_i386) return YMMRegSet; if (reg_num >= k_first_mpxr_i386 && reg_num <= k_last_mpxr_i386) - return llvm::None; // MPXR + return std::nullopt; // MPXR if (reg_num >= k_first_mpxc_i386 && reg_num <= k_last_mpxc_i386) - return llvm::None; // MPXC + return std::nullopt; // MPXC if (reg_num >= k_first_dbr_i386 && reg_num <= k_last_dbr_i386) return DBRegSet; // DBR break; @@ -332,9 +333,9 @@ NativeRegisterContextNetBSD_x86_64::GetSetForNativeRegNum( if (reg_num >= k_first_avx_x86_64 && reg_num <= k_last_avx_x86_64) return YMMRegSet; if (reg_num >= k_first_mpxr_x86_64 && reg_num <= k_last_mpxr_x86_64) - return llvm::None; // MPXR + return std::nullopt; // MPXR if (reg_num >= k_first_mpxc_x86_64 && reg_num <= k_last_mpxc_x86_64) - return llvm::None; // MPXC + return std::nullopt; // MPXC if (reg_num >= k_first_dbr_x86_64 && reg_num <= k_last_dbr_x86_64) return DBRegSet; // DBR break; @@ -399,7 +400,7 @@ NativeRegisterContextNetBSD_x86_64::ReadRegister(const RegisterInfo *reg_info, return error; } - llvm::Optional<RegSetKind> opt_set = GetSetForNativeRegNum(reg); + std::optional<RegSetKind> opt_set = GetSetForNativeRegNum(reg); if (!opt_set) { // This is likely an internal register for lldb use only and should not be // directly queried. @@ -428,7 +429,7 @@ NativeRegisterContextNetBSD_x86_64::ReadRegister(const RegisterInfo *reg_info, break; } case YMMRegSet: { - llvm::Optional<YMMSplitPtr> ymm_reg = GetYMMSplitReg(reg); + std::optional<YMMSplitPtr> ymm_reg = GetYMMSplitReg(reg); if (!ymm_reg) { error.SetErrorStringWithFormat( "register \"%s\" not supported by CPU/kernel", reg_info->name); @@ -466,7 +467,7 @@ Status NativeRegisterContextNetBSD_x86_64::WriteRegister( return error; } - llvm::Optional<RegSetKind> opt_set = GetSetForNativeRegNum(reg); + std::optional<RegSetKind> opt_set = GetSetForNativeRegNum(reg); if (!opt_set) { // This is likely an internal register for lldb use only and should not be // directly queried. @@ -505,7 +506,7 @@ Status NativeRegisterContextNetBSD_x86_64::WriteRegister( break; } case YMMRegSet: { - llvm::Optional<YMMSplitPtr> ymm_reg = GetYMMSplitReg(reg); + std::optional<YMMSplitPtr> ymm_reg = GetYMMSplitReg(reg); if (!ymm_reg) { error.SetErrorStringWithFormat( "register \"%s\" not supported by CPU/kernel", reg_info->name); @@ -619,11 +620,11 @@ NativeRegisterContextNetBSD_x86_64::GetOffsetRegSetData(RegSetKind set, return base + (reg_offset - m_regset_offsets[set]); } -llvm::Optional<NativeRegisterContextNetBSD_x86_64::YMMSplitPtr> +std::optional<NativeRegisterContextNetBSD_x86_64::YMMSplitPtr> NativeRegisterContextNetBSD_x86_64::GetYMMSplitReg(uint32_t reg) { auto xst = reinterpret_cast<xstate *>(m_xstate.data()); if (!(xst->xs_rfbm & XCR0_SSE) || !(xst->xs_rfbm & XCR0_YMM_Hi128)) - return llvm::None; + return std::nullopt; uint32_t reg_index; switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) { diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h b/contrib/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h index 795cbeefd467..e4597b2f69c6 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h @@ -19,6 +19,7 @@ // clang-format on #include <array> +#include <optional> #include "Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h" #include "Plugins/Process/Utility/RegisterContext_x86.h" @@ -71,7 +72,7 @@ private: std::array<uint8_t, sizeof(struct dbreg)> m_dbr; std::array<size_t, MaxRegularRegSet + 1> m_regset_offsets; - llvm::Optional<RegSetKind> GetSetForNativeRegNum(uint32_t reg_num) const; + std::optional<RegSetKind> GetSetForNativeRegNum(uint32_t reg_num) const; Status ReadRegisterSet(RegSetKind set); Status WriteRegisterSet(RegSetKind set); @@ -82,7 +83,7 @@ private: void *xmm; void *ymm_hi; }; - llvm::Optional<YMMSplitPtr> GetYMMSplitReg(uint32_t reg); + std::optional<YMMSplitPtr> GetYMMSplitReg(uint32_t reg); }; } // namespace process_netbsd diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/POSIX/NativeProcessELF.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/POSIX/NativeProcessELF.cpp index cbaa1fc7a2b1..23e94a5f55e2 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/POSIX/NativeProcessELF.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/POSIX/NativeProcessELF.cpp @@ -9,15 +9,16 @@ #include "NativeProcessELF.h" #include "lldb/Utility/DataExtractor.h" +#include <optional> namespace lldb_private { -llvm::Optional<uint64_t> +std::optional<uint64_t> NativeProcessELF::GetAuxValue(enum AuxVector::EntryType type) { if (m_aux_vector == nullptr) { auto buffer_or_error = GetAuxvData(); if (!buffer_or_error) - return llvm::None; + return std::nullopt; DataExtractor auxv_data(buffer_or_error.get()->getBufferStart(), buffer_or_error.get()->getBufferSize(), GetByteOrder(), GetAddressByteSize()); @@ -44,11 +45,11 @@ lldb::addr_t NativeProcessELF::GetSharedLibraryInfoAddress() { template <typename ELF_EHDR, typename ELF_PHDR, typename ELF_DYN> lldb::addr_t NativeProcessELF::GetELFImageInfoAddress() { - llvm::Optional<uint64_t> maybe_phdr_addr = + std::optional<uint64_t> maybe_phdr_addr = GetAuxValue(AuxVector::AUXV_AT_PHDR); - llvm::Optional<uint64_t> maybe_phdr_entry_size = + std::optional<uint64_t> maybe_phdr_entry_size = GetAuxValue(AuxVector::AUXV_AT_PHENT); - llvm::Optional<uint64_t> maybe_phdr_num_entries = + std::optional<uint64_t> maybe_phdr_num_entries = GetAuxValue(AuxVector::AUXV_AT_PHNUM); if (!maybe_phdr_addr || !maybe_phdr_entry_size || !maybe_phdr_num_entries) return LLDB_INVALID_ADDRESS; @@ -161,7 +162,7 @@ NativeProcessELF::GetLoadedSVR4Libraries() { GetAddressByteSize(), bytes_read); if (!status.Success()) return status.ToError(); - if (address == 0) + if (link_map == 0) return llvm::createStringError(llvm::inconvertibleErrorCode(), "Invalid link_map address"); diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/POSIX/NativeProcessELF.h b/contrib/llvm-project/lldb/source/Plugins/Process/POSIX/NativeProcessELF.h index 8e92899defec..937def94436b 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/POSIX/NativeProcessELF.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/POSIX/NativeProcessELF.h @@ -12,6 +12,7 @@ #include "Plugins/Process/Utility/AuxVector.h" #include "lldb/Host/common/NativeProcessProtocol.h" #include "llvm/BinaryFormat/ELF.h" +#include <optional> namespace lldb_private { @@ -22,7 +23,7 @@ class NativeProcessELF : public NativeProcessProtocol { using NativeProcessProtocol::NativeProcessProtocol; public: - llvm::Optional<uint64_t> GetAuxValue(enum AuxVector::EntryType type); + std::optional<uint64_t> GetAuxValue(enum AuxVector::EntryType type); protected: template <typename T> struct ELFLinkMap { @@ -48,7 +49,7 @@ protected: void NotifyDidExec() override; std::unique_ptr<AuxVector> m_aux_vector; - llvm::Optional<lldb::addr_t> m_shared_library_info_addr; + std::optional<lldb::addr_t> m_shared_library_info_addr; }; // Explicitly declare the two 32/64 bit templates that NativeProcessELF.cpp will diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/ARMUtils.h b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/ARMUtils.h index bbe4c9a35fa6..a7aaa5ac7a1f 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/ARMUtils.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/ARMUtils.h @@ -25,7 +25,8 @@ static inline uint32_t DecodeImmShift(const uint32_t type, const uint32_t imm5, ARM_ShifterType &shift_t) { switch (type) { default: - // assert(0 && "Invalid shift type"); + assert(0 && "Invalid shift type"); + break; case 0: shift_t = SRType_LSL; return imm5; @@ -302,7 +303,7 @@ static inline uint32_t ARMExpandImm(uint32_t opcode) { // (imm32, carry_out) = ThumbExpandImm_C(imm12, carry_in) static inline uint32_t ThumbExpandImm_C(uint32_t opcode, uint32_t carry_in, uint32_t &carry_out) { - uint32_t imm32; // the expanded result + uint32_t imm32 = 0; // the expanded result const uint32_t i = bit(opcode, 26); const uint32_t imm3 = bits(opcode, 14, 12); const uint32_t abcdefgh = bits(opcode, 7, 0); @@ -311,6 +312,8 @@ static inline uint32_t ThumbExpandImm_C(uint32_t opcode, uint32_t carry_in, if (bits(imm12, 11, 10) == 0) { switch (bits(imm12, 9, 8)) { default: // Keep static analyzer happy with a default case + break; + case 0: imm32 = abcdefgh; break; diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/AuxVector.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/AuxVector.cpp index c4f45f759a33..f495ffb1924e 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/AuxVector.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/AuxVector.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "AuxVector.h" +#include <optional> AuxVector::AuxVector(const lldb_private::DataExtractor &data) { ParseAuxv(data); @@ -29,12 +30,12 @@ void AuxVector::ParseAuxv(const lldb_private::DataExtractor &data) { } } -llvm::Optional<uint64_t> +std::optional<uint64_t> AuxVector::GetAuxValue(enum EntryType entry_type) const { auto it = m_auxv_entries.find(static_cast<uint64_t>(entry_type)); if (it != m_auxv_entries.end()) return it->second; - return llvm::None; + return std::nullopt; } void AuxVector::DumpToLog(lldb_private::Log *log) const { diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/AuxVector.h b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/AuxVector.h index 07a0010e198f..3b0f55d35e5d 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/AuxVector.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/AuxVector.h @@ -11,6 +11,7 @@ #include "lldb/Utility/DataExtractor.h" #include "lldb/Utility/Log.h" +#include <optional> #include <unordered_map> class AuxVector { @@ -61,7 +62,7 @@ public: AUXV_AT_L3_CACHESHAPE = 37, }; - llvm::Optional<uint64_t> GetAuxValue(enum EntryType entry_type) const; + std::optional<uint64_t> GetAuxValue(enum EntryType entry_type) const; void DumpToLog(lldb_private::Log *log) const; const char *GetEntryName(EntryType type) const; diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp index 5091f68a9acf..0a1f34ec6b4e 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp @@ -88,9 +88,11 @@ bool lldb_private::InferiorCallMmap(Process *process, addr_t &allocated_addr, llvm::consumeError(type_system_or_err.takeError()); return false; } + auto ts = *type_system_or_err; + if (!ts) + return false; CompilerType void_ptr_type = - type_system_or_err->GetBasicTypeFromAST(eBasicTypeVoid) - .GetPointerType(); + ts->GetBasicTypeFromAST(eBasicTypeVoid).GetPointerType(); const ArchSpec arch = process->GetTarget().GetArchitecture(); MmapArgList args = process->GetTarget().GetPlatform()->GetMmapArgumentList( diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/LinuxProcMaps.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/LinuxProcMaps.cpp index 2a15f9813749..fd803c8cabaf 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/LinuxProcMaps.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/LinuxProcMaps.cpp @@ -11,6 +11,7 @@ #include "lldb/Utility/Status.h" #include "lldb/Utility/StringExtractor.h" #include "llvm/ADT/StringRef.h" +#include <optional> using namespace lldb_private; @@ -146,7 +147,7 @@ void lldb_private::ParseLinuxSMapRegions(llvm::StringRef linux_smap, llvm::StringRef lines(linux_smap); llvm::StringRef line; - llvm::Optional<MemoryRegionInfo> region; + std::optional<MemoryRegionInfo> region; while (lines.size()) { std::tie(line, lines) = lines.split('\n'); diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/NativeProcessSoftwareSingleStep.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/NativeProcessSoftwareSingleStep.cpp index ee5295bf6565..6bf8a0dc28b2 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/NativeProcessSoftwareSingleStep.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/NativeProcessSoftwareSingleStep.cpp @@ -128,8 +128,10 @@ Status NativeProcessSoftwareSingleStep::SetupSoftwareSingleStepping( auto pc_it = baton.m_register_values.find(reg_info_pc->kinds[eRegisterKindDWARF]); - auto flags_it = - baton.m_register_values.find(reg_info_flags->kinds[eRegisterKindDWARF]); + auto flags_it = reg_info_flags == nullptr + ? baton.m_register_values.end() + : baton.m_register_values.find( + reg_info_flags->kinds[eRegisterKindDWARF]); lldb::addr_t next_pc; lldb::addr_t next_flags; @@ -165,7 +167,8 @@ Status NativeProcessSoftwareSingleStep::SetupSoftwareSingleStepping( // Arm mode size_hint = 4; } - } else if (arch.IsMIPS() || arch.GetTriple().isPPC64()) + } else if (arch.IsMIPS() || arch.GetTriple().isPPC64() || + arch.GetTriple().isRISCV() || arch.GetTriple().isLoongArch()) size_hint = 4; error = process.SetBreakpoint(next_pc, size_hint, /*hardware=*/false); diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_x86.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_x86.cpp index 222e4a2690e4..f5525e3e3cb3 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_x86.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_x86.cpp @@ -18,7 +18,7 @@ using namespace lldb_private; static inline uint64_t GetStatusBit(uint32_t wp_index) { // DR6: ...BBBB // 3210 <- status bits for bp./wp. i; 1 if hit - return 1 << wp_index; + return 1ULL << wp_index; } // Returns mask/value for global enable bit of wp_index in DR7 @@ -27,14 +27,14 @@ static inline uint64_t GetEnableBit(uint32_t wp_index) { // 33221100 <- global/local enable for bp./wp.; 1 if enabled // we use global bits because NetBSD kernel does not preserve local // bits reliably; Linux seems fine with either - return 1 << (2 * wp_index + 1); + return 1ULL << (2 * wp_index + 1); } // Returns mask for both enable bits of wp_index in DR7 static inline uint64_t GetBothEnableBitMask(uint32_t wp_index) { // DR7: ...GLGLGLGL // 33221100 <- global/local enable for bp./wp.; 1 if enabled - return 3 << (2 * wp_index + 1); + return 3ULL << (2 * wp_index + 1); } // Returns value for type bits of wp_index in DR7 @@ -47,7 +47,7 @@ static inline uint64_t GetWatchTypeBits(uint32_t watch_flags, // wp.: 3333222211110000... // // where T - type is 01 for write, 11 for r/w - return watch_flags << (16 + 4 * wp_index); + return static_cast<uint64_t>(watch_flags) << (16 + 4 * wp_index); } // Returns value for size bits of wp_index in DR7 @@ -63,7 +63,8 @@ static inline uint64_t GetWatchSizeBits(uint32_t size, uint32_t wp_index) { // 01 for 2 bytes // 10 for 8 bytes // 11 for 4 bytes - return (size == 8 ? 0x2 : size - 1) << (18 + 4 * wp_index); + return static_cast<uint64_t>(size == 8 ? 0x2 : size - 1) + << (18 + 4 * wp_index); } // Returns bitmask for all bits controlling wp_index in DR7 diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp index 33bab249d960..b29d44176c94 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp @@ -856,7 +856,7 @@ static uint32_t g_exc_regnums[] = { exc_exception, exc_fsr, exc_far, }; -static size_t k_num_register_infos = llvm::array_lengthof(g_register_infos); +static size_t k_num_register_infos = std::size(g_register_infos); RegisterContextDarwin_arm::RegisterContextDarwin_arm( Thread &thread, uint32_t concrete_frame_idx) @@ -897,9 +897,9 @@ const RegisterInfo *RegisterContextDarwin_arm::GetRegisterInfos() { } // Number of registers in each register set -const size_t k_num_gpr_registers = llvm::array_lengthof(g_gpr_regnums); -const size_t k_num_fpu_registers = llvm::array_lengthof(g_fpu_regnums); -const size_t k_num_exc_registers = llvm::array_lengthof(g_exc_regnums); +const size_t k_num_gpr_registers = std::size(g_gpr_regnums); +const size_t k_num_fpu_registers = std::size(g_fpu_regnums); +const size_t k_num_exc_registers = std::size(g_exc_regnums); // Register set definitions. The first definitions at register set index of // zero is for all registers, followed by other registers sets. The register @@ -911,7 +911,7 @@ static const RegisterSet g_reg_sets[] = { {"Floating Point Registers", "fpu", k_num_fpu_registers, g_fpu_regnums}, {"Exception State Registers", "exc", k_num_exc_registers, g_exc_regnums}}; -const size_t k_num_regsets = llvm::array_lengthof(g_reg_sets); +const size_t k_num_regsets = std::size(g_reg_sets); size_t RegisterContextDarwin_arm::GetRegisterSetCount() { return k_num_regsets; @@ -1491,7 +1491,7 @@ uint32_t RegisterContextDarwin_arm::SetHardwareBreakpoint(lldb::addr_t addr, // We have a thumb breakpoint // We have an ARM breakpoint - dbg.bcr[i] = BCR_M_IMVA_MATCH | // Stop on address mismatch + dbg.bcr[i] = BCR_M_IMVA_MATCH | // Stop on address match byte_addr_select | // Set the correct byte address select // so we only trigger on the correct // opcode @@ -1510,7 +1510,7 @@ uint32_t RegisterContextDarwin_arm::SetHardwareBreakpoint(lldb::addr_t addr, } else if (size == 4) { // We have an ARM breakpoint dbg.bcr[i] = - BCR_M_IMVA_MATCH | // Stop on address mismatch + BCR_M_IMVA_MATCH | // Stop on address match BAS_IMVA_ALL | // Stop on any of the four bytes following the IMVA S_USER | // Which modes should this breakpoint stop in? BCR_ENABLE; // Enable this hardware breakpoint diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp index 691e7db3fc79..8cf90e1e2501 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp @@ -90,8 +90,7 @@ static uint32_t g_fpu_regnums[] = { static uint32_t g_exc_regnums[] = {exc_far, exc_esr, exc_exception}; -static size_t k_num_register_infos = - llvm::array_lengthof(g_register_infos_arm64_le); +static size_t k_num_register_infos = std::size(g_register_infos_arm64_le); RegisterContextDarwin_arm64::RegisterContextDarwin_arm64( Thread &thread, uint32_t concrete_frame_idx) @@ -132,9 +131,9 @@ const RegisterInfo *RegisterContextDarwin_arm64::GetRegisterInfos() { } // Number of registers in each register set -const size_t k_num_gpr_registers = llvm::array_lengthof(g_gpr_regnums); -const size_t k_num_fpu_registers = llvm::array_lengthof(g_fpu_regnums); -const size_t k_num_exc_registers = llvm::array_lengthof(g_exc_regnums); +const size_t k_num_gpr_registers = std::size(g_gpr_regnums); +const size_t k_num_fpu_registers = std::size(g_fpu_regnums); +const size_t k_num_exc_registers = std::size(g_exc_regnums); // Register set definitions. The first definitions at register set index of // zero is for all registers, followed by other registers sets. The register @@ -146,7 +145,7 @@ static const RegisterSet g_reg_sets[] = { {"Floating Point Registers", "fpu", k_num_fpu_registers, g_fpu_regnums}, {"Exception State Registers", "exc", k_num_exc_registers, g_exc_regnums}}; -const size_t k_num_regsets = llvm::array_lengthof(g_reg_sets); +const size_t k_num_regsets = std::size(g_reg_sets); size_t RegisterContextDarwin_arm64::GetRegisterSetCount() { return k_num_regsets; diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp index 9158f8acc2e7..32a976086f29 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp @@ -363,7 +363,7 @@ static RegisterInfo g_register_infos[] = { nullptr, }}; -static size_t k_num_register_infos = llvm::array_lengthof(g_register_infos); +static size_t k_num_register_infos = std::size(g_register_infos); RegisterContextDarwin_i386::RegisterContextDarwin_i386( Thread &thread, uint32_t concrete_frame_idx) @@ -421,9 +421,9 @@ static uint32_t g_fpu_regnums[] = { static uint32_t g_exc_regnums[] = {exc_trapno, exc_err, exc_faultvaddr}; // Number of registers in each register set -const size_t k_num_gpr_registers = llvm::array_lengthof(g_gpr_regnums); -const size_t k_num_fpu_registers = llvm::array_lengthof(g_fpu_regnums); -const size_t k_num_exc_registers = llvm::array_lengthof(g_exc_regnums); +const size_t k_num_gpr_registers = std::size(g_gpr_regnums); +const size_t k_num_fpu_registers = std::size(g_fpu_regnums); +const size_t k_num_exc_registers = std::size(g_exc_regnums); // Register set definitions. The first definitions at register set index of // zero is for all registers, followed by other registers sets. The register @@ -435,7 +435,7 @@ static const RegisterSet g_reg_sets[] = { {"Floating Point Registers", "fpu", k_num_fpu_registers, g_fpu_regnums}, {"Exception State Registers", "exc", k_num_exc_registers, g_exc_regnums}}; -const size_t k_num_regsets = llvm::array_lengthof(g_reg_sets); +const size_t k_num_regsets = std::size(g_reg_sets); size_t RegisterContextDarwin_i386::GetRegisterSetCount() { return k_num_regsets; diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp index ad25ebbbb804..dcd86a1ff92b 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp @@ -420,7 +420,7 @@ static RegisterInfo g_register_infos[] = { nullptr, }}; -static size_t k_num_register_infos = llvm::array_lengthof(g_register_infos); +static size_t k_num_register_infos = std::size(g_register_infos); RegisterContextDarwin_x86_64::RegisterContextDarwin_x86_64( Thread &thread, uint32_t concrete_frame_idx) @@ -477,9 +477,9 @@ static uint32_t g_fpu_regnums[] = { static uint32_t g_exc_regnums[] = {exc_trapno, exc_err, exc_faultvaddr}; // Number of registers in each register set -const size_t k_num_gpr_registers = llvm::array_lengthof(g_gpr_regnums); -const size_t k_num_fpu_registers = llvm::array_lengthof(g_fpu_regnums); -const size_t k_num_exc_registers = llvm::array_lengthof(g_exc_regnums); +const size_t k_num_gpr_registers = std::size(g_gpr_regnums); +const size_t k_num_fpu_registers = std::size(g_fpu_regnums); +const size_t k_num_exc_registers = std::size(g_exc_regnums); // Register set definitions. The first definitions at register set index of // zero is for all registers, followed by other registers sets. The register @@ -491,7 +491,7 @@ static const RegisterSet g_reg_sets[] = { {"Floating Point Registers", "fpu", k_num_fpu_registers, g_fpu_regnums}, {"Exception State Registers", "exc", k_num_exc_registers, g_exc_regnums}}; -const size_t k_num_regsets = llvm::array_lengthof(g_reg_sets); +const size_t k_num_regsets = std::size(g_reg_sets); size_t RegisterContextDarwin_x86_64::GetRegisterSetCount() { return k_num_regsets; diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_i386.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_i386.cpp index acebe9d53568..df6a82c11255 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_i386.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_i386.cpp @@ -68,7 +68,7 @@ RegisterContextFreeBSD_i386::RegisterContextFreeBSD_i386( size_t RegisterContextFreeBSD_i386::GetGPRSize() const { return sizeof(GPR); } const RegisterInfo *RegisterContextFreeBSD_i386::GetRegisterInfo() const { - switch (m_target_arch.GetMachine()) { + switch (GetTargetArchitecture().GetMachine()) { case llvm::Triple::x86: return g_register_infos_i386; default: diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_mips64.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_mips64.cpp index 7b4c7be21f74..1f52c09df12e 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_mips64.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_mips64.cpp @@ -169,7 +169,7 @@ size_t RegisterContextFreeBSD_mips64::GetRegisterSetCount() const { } const RegisterInfo *RegisterContextFreeBSD_mips64::GetRegisterInfo() const { - assert(m_target_arch.GetCore() == ArchSpec::eCore_mips64); + assert(GetTargetArchitecture().GetCore() == ArchSpec::eCore_mips64); return g_register_infos_mips64; } diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.cpp index 2991bd3c5f2c..d8dfa434335b 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.cpp @@ -186,7 +186,6 @@ size_t RegisterContextFreeBSD_powerpc::GetGPRSize() const { } const RegisterInfo *RegisterContextFreeBSD_powerpc::GetRegisterInfo() const { - // assert (m_target_arch.GetCore() == ArchSpec::eCore_powerpc); llvm_unreachable("Abstract class!"); return nullptr; } @@ -204,7 +203,6 @@ size_t RegisterContextFreeBSD_powerpc32::GetGPRSize() const { } const RegisterInfo *RegisterContextFreeBSD_powerpc32::GetRegisterInfo() const { - // assert (m_target_arch.GetCore() == ArchSpec::eCore_powerpc); return g_register_infos_powerpc32; } @@ -224,8 +222,7 @@ size_t RegisterContextFreeBSD_powerpc64::GetGPRSize() const { } const RegisterInfo *RegisterContextFreeBSD_powerpc64::GetRegisterInfo() const { - // assert (m_target_arch.GetCore() == ArchSpec::eCore_powerpc); - if (m_target_arch.GetMachine() == llvm::Triple::ppc) + if (GetTargetArchitecture().GetMachine() == llvm::Triple::ppc) return g_register_infos_powerpc64_32; return g_register_infos_powerpc64; } diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextLinux_i386.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextLinux_i386.cpp index 39bec20649a4..0b3953e1ec2c 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextLinux_i386.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextLinux_i386.cpp @@ -104,10 +104,10 @@ RegisterContextLinux_i386::RegisterContextLinux_i386( d_register_infos.push_back(orig_ax); } -size_t RegisterContextLinux_i386::GetGPRSize() const { return sizeof(GPR); } +size_t RegisterContextLinux_i386::GetGPRSizeStatic() { return sizeof(GPR); } const RegisterInfo *RegisterContextLinux_i386::GetRegisterInfo() const { - switch (m_target_arch.GetMachine()) { + switch (GetTargetArchitecture().GetMachine()) { case llvm::Triple::x86: case llvm::Triple::x86_64: return g_register_infos_i386; diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextLinux_i386.h b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextLinux_i386.h index ef731a5a7994..e0f8114fa58f 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextLinux_i386.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextLinux_i386.h @@ -15,7 +15,8 @@ class RegisterContextLinux_i386 : public lldb_private::RegisterInfoInterface { public: RegisterContextLinux_i386(const lldb_private::ArchSpec &target_arch); - size_t GetGPRSize() const override; + static size_t GetGPRSizeStatic(); + size_t GetGPRSize() const override { return GetGPRSizeStatic(); } const lldb_private::RegisterInfo *GetRegisterInfo() const override; diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.cpp index 20b8d74f8c0d..85c57ca698d4 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.cpp @@ -171,7 +171,7 @@ RegisterContextLinux_x86_64::RegisterContextLinux_x86_64( d_register_infos.push_back(orig_ax); } -size_t RegisterContextLinux_x86_64::GetGPRSize() const { return sizeof(GPR); } +size_t RegisterContextLinux_x86_64::GetGPRSizeStatic() { return sizeof(GPR); } const std::vector<lldb_private::RegisterInfo> * RegisterContextLinux_x86_64::GetDynamicRegisterInfoP() const { diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.h b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.h index ea21b913d5c5..a09deebed23a 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.h @@ -15,7 +15,8 @@ class RegisterContextLinux_x86_64 : public lldb_private::RegisterInfoInterface { public: RegisterContextLinux_x86_64(const lldb_private::ArchSpec &target_arch); - size_t GetGPRSize() const override; + static size_t GetGPRSizeStatic(); + size_t GetGPRSize() const override { return GetGPRSizeStatic(); } const lldb_private::RegisterInfo *GetRegisterInfo() const override; diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextMemory.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextMemory.cpp index ead8c4b4a80d..84a19d5b1303 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextMemory.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextMemory.cpp @@ -81,7 +81,7 @@ bool RegisterContextMemory::ReadRegister(const RegisterInfo *reg_info, } const bool partial_data_ok = false; return reg_value - .SetValueFromData(reg_info, m_reg_data, reg_info->byte_offset, + .SetValueFromData(*reg_info, m_reg_data, reg_info->byte_offset, partial_data_ok) .Success(); } diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextNetBSD_i386.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextNetBSD_i386.cpp index bd7830e42b42..ba089190bd22 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextNetBSD_i386.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextNetBSD_i386.cpp @@ -80,7 +80,7 @@ RegisterContextNetBSD_i386::RegisterContextNetBSD_i386( size_t RegisterContextNetBSD_i386::GetGPRSize() const { return sizeof(GPR); } const RegisterInfo *RegisterContextNetBSD_i386::GetRegisterInfo() const { - switch (m_target_arch.GetMachine()) { + switch (GetTargetArchitecture().GetMachine()) { case llvm::Triple::x86: case llvm::Triple::x86_64: return g_register_infos_i386; diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextOpenBSD_i386.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextOpenBSD_i386.cpp index 7183ffcfd0f6..ddf6cc5c3c65 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextOpenBSD_i386.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextOpenBSD_i386.cpp @@ -62,7 +62,7 @@ RegisterContextOpenBSD_i386::RegisterContextOpenBSD_i386( size_t RegisterContextOpenBSD_i386::GetGPRSize() const { return sizeof(GPR); } const RegisterInfo *RegisterContextOpenBSD_i386::GetRegisterInfo() const { - switch (m_target_arch.GetMachine()) { + switch (GetTargetArchitecture().GetMachine()) { case llvm::Triple::x86: return g_register_infos_i386; default: diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_loongarch64.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_loongarch64.cpp new file mode 100644 index 000000000000..a48a58f28f7a --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_loongarch64.cpp @@ -0,0 +1,82 @@ +//===-- RegisterContextPOSIX_loongarch64.cpp --------------------*- 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 +// +//===----------------------------------------------------------------------===// + +#include "lldb/Target/Process.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/Thread.h" +#include "lldb/Utility/DataBufferHeap.h" +#include "lldb/Utility/DataExtractor.h" +#include "lldb/Utility/Endian.h" +#include "lldb/Utility/RegisterValue.h" +#include "lldb/Utility/Scalar.h" +#include "llvm/Support/Compiler.h" + +#include "RegisterContextPOSIX_loongarch64.h" + +using namespace lldb; +using namespace lldb_private; + +RegisterContextPOSIX_loongarch64::RegisterContextPOSIX_loongarch64( + lldb_private::Thread &thread, + std::unique_ptr<RegisterInfoPOSIX_loongarch64> register_info) + : lldb_private::RegisterContext(thread, 0), + m_register_info_up(std::move(register_info)) {} + +RegisterContextPOSIX_loongarch64::~RegisterContextPOSIX_loongarch64() = default; + +void RegisterContextPOSIX_loongarch64::invalidate() {} + +void RegisterContextPOSIX_loongarch64::InvalidateAllRegisters() {} + +size_t RegisterContextPOSIX_loongarch64::GetRegisterCount() { + return m_register_info_up->GetRegisterCount(); +} + +size_t RegisterContextPOSIX_loongarch64::GetGPRSize() { + return m_register_info_up->GetGPRSize(); +} + +unsigned RegisterContextPOSIX_loongarch64::GetRegisterSize(unsigned int reg) { + return m_register_info_up->GetRegisterInfo()[reg].byte_size; +} + +unsigned RegisterContextPOSIX_loongarch64::GetRegisterOffset(unsigned int reg) { + return m_register_info_up->GetRegisterInfo()[reg].byte_offset; +} + +const lldb_private::RegisterInfo * +RegisterContextPOSIX_loongarch64::GetRegisterInfoAtIndex(size_t reg) { + if (reg < GetRegisterCount()) + return &GetRegisterInfo()[reg]; + + return nullptr; +} + +size_t RegisterContextPOSIX_loongarch64::GetRegisterSetCount() { + return m_register_info_up->GetRegisterCount(); +} + +const lldb_private::RegisterSet * +RegisterContextPOSIX_loongarch64::GetRegisterSet(size_t set) { + return m_register_info_up->GetRegisterSet(set); +} + +const lldb_private::RegisterInfo * +RegisterContextPOSIX_loongarch64::GetRegisterInfo() { + return m_register_info_up->GetRegisterInfo(); +} + +bool RegisterContextPOSIX_loongarch64::IsGPR(unsigned int reg) { + return m_register_info_up->GetRegisterSetFromRegisterIndex(reg) == + RegisterInfoPOSIX_loongarch64::GPRegSet; +} + +bool RegisterContextPOSIX_loongarch64::IsFPR(unsigned int reg) { + return m_register_info_up->GetRegisterSetFromRegisterIndex(reg) == + RegisterInfoPOSIX_loongarch64::FPRegSet; +} diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_loongarch64.h b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_loongarch64.h new file mode 100644 index 000000000000..95f93bb41f01 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_loongarch64.h @@ -0,0 +1,63 @@ +//===-- RegisterContextPOSIX_loongarch64.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_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTPOSIX_LOONGARCH64_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTPOSIX_LOONGARCH64_H + +#include "RegisterInfoInterface.h" +#include "RegisterInfoPOSIX_loongarch64.h" +#include "lldb-loongarch-register-enums.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/Utility/Log.h" + +class RegisterContextPOSIX_loongarch64 : public lldb_private::RegisterContext { +public: + RegisterContextPOSIX_loongarch64( + lldb_private::Thread &thread, + std::unique_ptr<RegisterInfoPOSIX_loongarch64> register_info); + + ~RegisterContextPOSIX_loongarch64() override; + + void invalidate(); + + void InvalidateAllRegisters() override; + + size_t GetRegisterCount() override; + + virtual size_t GetGPRSize(); + + virtual unsigned GetRegisterSize(unsigned reg); + + virtual unsigned GetRegisterOffset(unsigned reg); + + const lldb_private::RegisterInfo *GetRegisterInfoAtIndex(size_t reg) override; + + size_t GetRegisterSetCount() override; + + const lldb_private::RegisterSet *GetRegisterSet(size_t set) override; + +protected: + std::unique_ptr<RegisterInfoPOSIX_loongarch64> m_register_info_up; + + virtual const lldb_private::RegisterInfo *GetRegisterInfo(); + + bool IsGPR(unsigned reg); + + bool IsFPR(unsigned reg); + + size_t GetFPRSize() { return sizeof(RegisterInfoPOSIX_loongarch64::FPR); } + + uint32_t GetRegNumFCSR() const { return fpr_fcsr_loongarch; } + + virtual bool ReadGPR() = 0; + virtual bool ReadFPR() = 0; + virtual bool WriteGPR() = 0; + virtual bool WriteFPR() = 0; +}; + +#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTPOSIX_LOONGARCH64_H diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_riscv64.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_riscv64.cpp new file mode 100644 index 000000000000..1834a94dc026 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_riscv64.cpp @@ -0,0 +1,82 @@ +//===-- RegisterContextPOSIX_riscv64.cpp ------------------------*- 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 +// +//===----------------------------------------------------------------------===// + +#include "lldb/Target/Process.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/Thread.h" +#include "lldb/Utility/DataBufferHeap.h" +#include "lldb/Utility/DataExtractor.h" +#include "lldb/Utility/Endian.h" +#include "lldb/Utility/RegisterValue.h" +#include "lldb/Utility/Scalar.h" +#include "llvm/Support/Compiler.h" + +#include "RegisterContextPOSIX_riscv64.h" + +using namespace lldb; +using namespace lldb_private; + +RegisterContextPOSIX_riscv64::RegisterContextPOSIX_riscv64( + lldb_private::Thread &thread, + std::unique_ptr<RegisterInfoPOSIX_riscv64> register_info) + : lldb_private::RegisterContext(thread, 0), + m_register_info_up(std::move(register_info)) {} + +RegisterContextPOSIX_riscv64::~RegisterContextPOSIX_riscv64() = default; + +void RegisterContextPOSIX_riscv64::invalidate() {} + +void RegisterContextPOSIX_riscv64::InvalidateAllRegisters() {} + +size_t RegisterContextPOSIX_riscv64::GetRegisterCount() { + return m_register_info_up->GetRegisterCount(); +} + +size_t RegisterContextPOSIX_riscv64::GetGPRSize() { + return m_register_info_up->GetGPRSize(); +} + +unsigned RegisterContextPOSIX_riscv64::GetRegisterSize(unsigned int reg) { + return m_register_info_up->GetRegisterInfo()[reg].byte_size; +} + +unsigned RegisterContextPOSIX_riscv64::GetRegisterOffset(unsigned int reg) { + return m_register_info_up->GetRegisterInfo()[reg].byte_offset; +} + +const lldb_private::RegisterInfo * +RegisterContextPOSIX_riscv64::GetRegisterInfoAtIndex(size_t reg) { + if (reg < GetRegisterCount()) + return &GetRegisterInfo()[reg]; + + return nullptr; +} + +size_t RegisterContextPOSIX_riscv64::GetRegisterSetCount() { + return m_register_info_up->GetRegisterCount(); +} + +const lldb_private::RegisterSet * +RegisterContextPOSIX_riscv64::GetRegisterSet(size_t set) { + return m_register_info_up->GetRegisterSet(set); +} + +const lldb_private::RegisterInfo * +RegisterContextPOSIX_riscv64::GetRegisterInfo() { + return m_register_info_up->GetRegisterInfo(); +} + +bool RegisterContextPOSIX_riscv64::IsGPR(unsigned int reg) { + return m_register_info_up->GetRegisterSetFromRegisterIndex(reg) == + RegisterInfoPOSIX_riscv64::GPRegSet; +} + +bool RegisterContextPOSIX_riscv64::IsFPR(unsigned int reg) { + return m_register_info_up->GetRegisterSetFromRegisterIndex(reg) == + RegisterInfoPOSIX_riscv64::FPRegSet; +} diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_riscv64.h b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_riscv64.h new file mode 100644 index 000000000000..2431ed6ab8c6 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_riscv64.h @@ -0,0 +1,63 @@ +//===-- RegisterContextPOSIX_riscv64.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_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTPOSIX_RISCV64_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTPOSIX_RISCV64_H + +#include "RegisterInfoInterface.h" +#include "RegisterInfoPOSIX_riscv64.h" +#include "lldb-riscv-register-enums.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/Utility/Log.h" + +class RegisterContextPOSIX_riscv64 : public lldb_private::RegisterContext { +public: + RegisterContextPOSIX_riscv64( + lldb_private::Thread &thread, + std::unique_ptr<RegisterInfoPOSIX_riscv64> register_info); + + ~RegisterContextPOSIX_riscv64() override; + + void invalidate(); + + void InvalidateAllRegisters() override; + + size_t GetRegisterCount() override; + + virtual size_t GetGPRSize(); + + virtual unsigned GetRegisterSize(unsigned reg); + + virtual unsigned GetRegisterOffset(unsigned reg); + + const lldb_private::RegisterInfo *GetRegisterInfoAtIndex(size_t reg) override; + + size_t GetRegisterSetCount() override; + + const lldb_private::RegisterSet *GetRegisterSet(size_t set) override; + +protected: + std::unique_ptr<RegisterInfoPOSIX_riscv64> m_register_info_up; + + virtual const lldb_private::RegisterInfo *GetRegisterInfo(); + + bool IsGPR(unsigned reg); + + bool IsFPR(unsigned reg); + + size_t GetFPRSize() { return sizeof(RegisterInfoPOSIX_riscv64::FPR); } + + uint32_t GetRegNumFCSR() const { return fpr_fcsr_riscv; } + + virtual bool ReadGPR() = 0; + virtual bool ReadFPR() = 0; + virtual bool WriteGPR() = 0; + virtual bool WriteFPR() = 0; +}; + +#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTPOSIX_RISCV64_H diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.cpp index 21c8160e5b41..b85da39b4c45 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.cpp @@ -83,7 +83,7 @@ RegisterContextPOSIX_s390x::RegisterContextPOSIX_s390x( : RegisterContext(thread, concrete_frame_idx) { m_register_info_up.reset(register_info); - switch (register_info->m_target_arch.GetMachine()) { + switch (register_info->GetTargetArchitecture().GetMachine()) { case llvm::Triple::systemz: m_reg_info.num_registers = k_num_registers_s390x; m_reg_info.num_gpr_registers = k_num_gpr_registers_s390x; @@ -151,7 +151,7 @@ size_t RegisterContextPOSIX_s390x::GetRegisterSetCount() { const RegisterSet *RegisterContextPOSIX_s390x::GetRegisterSet(size_t set) { if (IsRegisterSetAvailable(set)) { - switch (m_register_info_up->m_target_arch.GetMachine()) { + switch (m_register_info_up->GetTargetArchitecture().GetMachine()) { case llvm::Triple::systemz: return &g_reg_sets_s390x[set]; default: diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp index 40f70e8a0a75..0e0db843c8b4 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp @@ -399,7 +399,7 @@ RegisterContextPOSIX_x86::RegisterContextPOSIX_x86( : RegisterContext(thread, concrete_frame_idx) { m_register_info_up.reset(register_info); - switch (register_info->m_target_arch.GetMachine()) { + switch (register_info->GetTargetArchitecture().GetMachine()) { case llvm::Triple::x86: m_reg_info.num_registers = k_num_registers_i386; m_reg_info.num_gpr_registers = k_num_gpr_registers_i386; @@ -518,7 +518,7 @@ size_t RegisterContextPOSIX_x86::GetRegisterSetCount() { const RegisterSet *RegisterContextPOSIX_x86::GetRegisterSet(size_t set) { if (IsRegisterSetAvailable(set)) { - switch (m_register_info_up->m_target_arch.GetMachine()) { + switch (m_register_info_up->GetTargetArchitecture().GetMachine()) { case llvm::Triple::x86: return &g_reg_sets_i386[set]; case llvm::Triple::x86_64: diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextWindows_i386.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextWindows_i386.cpp index 066d50d9c149..323f7e911866 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextWindows_i386.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextWindows_i386.cpp @@ -78,11 +78,11 @@ const RegisterInfo *RegisterContextWindows_i386::GetRegisterInfo() const { } uint32_t RegisterContextWindows_i386::GetRegisterCount() const { - return llvm::array_lengthof(g_register_infos_i386); + return std::size(g_register_infos_i386); } uint32_t RegisterContextWindows_i386::GetUserRegisterCount() const { - return llvm::array_lengthof(g_register_infos_i386); + return std::size(g_register_infos_i386); } size_t RegisterContextWindows_i386::GetGPRSize() const { return sizeof(GPR); } diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextWindows_x86_64.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextWindows_x86_64.cpp index a35ccace5d5b..aaebeaa686e3 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextWindows_x86_64.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextWindows_x86_64.cpp @@ -141,11 +141,11 @@ const RegisterInfo *RegisterContextWindows_x86_64::GetRegisterInfo() const { } uint32_t RegisterContextWindows_x86_64::GetRegisterCount() const { - return llvm::array_lengthof(g_register_infos_x86_64); + return std::size(g_register_infos_x86_64); } uint32_t RegisterContextWindows_x86_64::GetUserRegisterCount() const { - return llvm::array_lengthof(g_register_infos_x86_64); + return std::size(g_register_infos_x86_64); } size_t RegisterContextWindows_x86_64::GetGPRSize() const { return sizeof(GPR); } diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoInterface.h b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoInterface.h index c05438338c88..d8414c594d24 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoInterface.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoInterface.h @@ -61,9 +61,9 @@ public: return nullptr; } - // FIXME make private. +private: lldb_private::ArchSpec m_target_arch; }; -} +} // namespace lldb_private #endif diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp index 4db7abe603d4..1c46df79c7d0 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp @@ -217,9 +217,9 @@ RegisterInfoPOSIX_arm64::RegisterInfoPOSIX_arm64( if (m_opt_regsets.AnySet(eRegsetMaskDynamic)) { llvm::ArrayRef<lldb_private::RegisterInfo> reg_infos_ref = - llvm::makeArrayRef(m_register_info_p, m_register_info_count); + llvm::ArrayRef(m_register_info_p, m_register_info_count); llvm::ArrayRef<lldb_private::RegisterSet> reg_sets_ref = - llvm::makeArrayRef(m_register_set_p, m_register_set_count); + llvm::ArrayRef(m_register_set_p, m_register_set_count); llvm::copy(reg_infos_ref, std::back_inserter(m_dynamic_reg_infos)); llvm::copy(reg_sets_ref, std::back_inserter(m_dynamic_reg_sets)); @@ -245,7 +245,7 @@ uint32_t RegisterInfoPOSIX_arm64::GetRegisterCount() const { return m_register_info_count; } -size_t RegisterInfoPOSIX_arm64::GetGPRSize() const { +size_t RegisterInfoPOSIX_arm64::GetGPRSizeStatic() { return sizeof(struct RegisterInfoPOSIX_arm64::GPR); } @@ -333,7 +333,7 @@ uint32_t RegisterInfoPOSIX_arm64::ConfigureVectorLength(uint32_t sve_vq) { m_per_vq_reg_infos[sve_vq]; if (reg_info_ref.empty()) { - reg_info_ref = llvm::makeArrayRef(m_register_info_p, m_register_info_count); + reg_info_ref = llvm::ArrayRef(m_register_info_p, m_register_info_count); uint32_t offset = SVE_REGS_DEFAULT_OFFSET_LINUX; reg_info_ref[fpu_fpsr].byte_offset = offset; diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h index 96cab49d5ac8..4c52de99fde6 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h @@ -47,6 +47,7 @@ public: uint64_t sp; // x31 uint64_t pc; // pc uint32_t cpsr; // cpsr + uint32_t pad; }; LLVM_PACKED_END @@ -81,7 +82,8 @@ public: RegisterInfoPOSIX_arm64(const lldb_private::ArchSpec &target_arch, lldb_private::Flags opt_regsets); - size_t GetGPRSize() const override; + static size_t GetGPRSizeStatic(); + size_t GetGPRSize() const override { return GetGPRSizeStatic(); } size_t GetFPRSize() const override; @@ -103,6 +105,7 @@ public: uint32_t ConfigureVectorLength(uint32_t sve_vq); bool VectorSizeIsValid(uint32_t vq) { + // coverity[unsigned_compare] if (vq >= eVectorQuadwordAArch64 && vq <= eVectorQuadwordAArch64SVEMax) return true; return false; diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_loongarch64.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_loongarch64.cpp new file mode 100644 index 000000000000..6c723afe4b69 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_loongarch64.cpp @@ -0,0 +1,158 @@ +//===-- RegisterInfoPOSIX_loongarch64.cpp --------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===---------------------------------------------------------------------===// + +#include <cassert> +#include <lldb/Utility/Flags.h> +#include <stddef.h> + +#include "lldb/lldb-defines.h" +#include "llvm/Support/Compiler.h" + +#include "RegisterInfoPOSIX_loongarch64.h" + +#define GPR_OFFSET(idx) ((idx)*8 + 0) +#define FPR_OFFSET(idx) ((idx)*8 + sizeof(RegisterInfoPOSIX_loongarch64::GPR)) +#define FCC_OFFSET(idx) ((idx)*1 + 32 * 8 + sizeof(RegisterInfoPOSIX_loongarch64::GPR)) +#define FCSR_OFFSET (8 * 1 + 32 * 8 + sizeof(RegisterInfoPOSIX_loongarch64::GPR)) + +#define REG_CONTEXT_SIZE \ + (sizeof(RegisterInfoPOSIX_loongarch64::GPR) + \ + sizeof(RegisterInfoPOSIX_loongarch64::FPR)) + +#define DECLARE_REGISTER_INFOS_LOONGARCH64_STRUCT +#include "RegisterInfos_loongarch64.h" +#undef DECLARE_REGISTER_INFOS_LOONGARCH64_STRUCT + +const lldb_private::RegisterInfo * +RegisterInfoPOSIX_loongarch64::GetRegisterInfoPtr( + const lldb_private::ArchSpec &target_arch) { + switch (target_arch.GetMachine()) { + case llvm::Triple::loongarch64: + return g_register_infos_loongarch64; + default: + assert(false && "Unhandled target architecture."); + return nullptr; + } +} + +uint32_t RegisterInfoPOSIX_loongarch64::GetRegisterInfoCount( + const lldb_private::ArchSpec &target_arch) { + switch (target_arch.GetMachine()) { + case llvm::Triple::loongarch64: + return static_cast<uint32_t>(sizeof(g_register_infos_loongarch64) / + sizeof(g_register_infos_loongarch64[0])); + default: + assert(false && "Unhandled target architecture."); + return 0; + } +} + +// Number of register sets provided by this context. +enum { + k_num_gpr_registers = gpr_last_loongarch - gpr_first_loongarch + 1, + k_num_fpr_registers = fpr_last_loongarch - fpr_first_loongarch + 1, + k_num_register_sets = 2 +}; + +// LoongArch64 general purpose registers. +static const uint32_t g_gpr_regnums_loongarch64[] = { + gpr_r0_loongarch, gpr_r1_loongarch, gpr_r2_loongarch, + gpr_r3_loongarch, gpr_r4_loongarch, gpr_r5_loongarch, + gpr_r6_loongarch, gpr_r7_loongarch, gpr_r8_loongarch, + gpr_r9_loongarch, gpr_r10_loongarch, gpr_r11_loongarch, + gpr_r12_loongarch, gpr_r13_loongarch, gpr_r14_loongarch, + gpr_r15_loongarch, gpr_r16_loongarch, gpr_r17_loongarch, + gpr_r18_loongarch, gpr_r19_loongarch, gpr_r20_loongarch, + gpr_r21_loongarch, gpr_r22_loongarch, gpr_r23_loongarch, + gpr_r24_loongarch, gpr_r25_loongarch, gpr_r26_loongarch, + gpr_r27_loongarch, gpr_r28_loongarch, gpr_r29_loongarch, + gpr_r30_loongarch, gpr_r31_loongarch, gpr_orig_a0_loongarch, + gpr_pc_loongarch, gpr_badv_loongarch, gpr_reserved0_loongarch, + gpr_reserved1_loongarch, gpr_reserved2_loongarch, gpr_reserved3_loongarch, + gpr_reserved4_loongarch, gpr_reserved5_loongarch, gpr_reserved6_loongarch, + gpr_reserved7_loongarch, gpr_reserved8_loongarch, gpr_reserved9_loongarch, + LLDB_INVALID_REGNUM}; + +static_assert(((sizeof g_gpr_regnums_loongarch64 / + sizeof g_gpr_regnums_loongarch64[0]) - + 1) == k_num_gpr_registers, + "g_gpr_regnums_loongarch64 has wrong number of register infos"); + +// LoongArch64 floating point registers. +static const uint32_t g_fpr_regnums_loongarch64[] = { + fpr_f0_loongarch, fpr_f1_loongarch, fpr_f2_loongarch, + fpr_f3_loongarch, fpr_f4_loongarch, fpr_f5_loongarch, + fpr_f6_loongarch, fpr_f7_loongarch, fpr_f8_loongarch, + fpr_f9_loongarch, fpr_f10_loongarch, fpr_f11_loongarch, + fpr_f12_loongarch, fpr_f13_loongarch, fpr_f14_loongarch, + fpr_f15_loongarch, fpr_f16_loongarch, fpr_f17_loongarch, + fpr_f18_loongarch, fpr_f19_loongarch, fpr_f20_loongarch, + fpr_f21_loongarch, fpr_f22_loongarch, fpr_f23_loongarch, + fpr_f24_loongarch, fpr_f25_loongarch, fpr_f26_loongarch, + fpr_f27_loongarch, fpr_f28_loongarch, fpr_f29_loongarch, + fpr_f30_loongarch, fpr_f31_loongarch, fpr_fcc0_loongarch, + fpr_fcc1_loongarch, fpr_fcc2_loongarch, fpr_fcc3_loongarch, + fpr_fcc4_loongarch, fpr_fcc5_loongarch, fpr_fcc6_loongarch, + fpr_fcc7_loongarch, fpr_fcsr_loongarch, LLDB_INVALID_REGNUM}; + +static_assert(((sizeof g_fpr_regnums_loongarch64 / + sizeof g_fpr_regnums_loongarch64[0]) - + 1) == k_num_fpr_registers, + "g_fpr_regnums_loongarch64 has wrong number of register infos"); + +// Register sets for LoongArch64. +static const lldb_private::RegisterSet + g_reg_sets_loongarch64[k_num_register_sets] = { + {"General Purpose Registers", "gpr", k_num_gpr_registers, + g_gpr_regnums_loongarch64}, + {"Floating Point Registers", "fpr", k_num_fpr_registers, + g_fpr_regnums_loongarch64}}; + +RegisterInfoPOSIX_loongarch64::RegisterInfoPOSIX_loongarch64( + const lldb_private::ArchSpec &target_arch, lldb_private::Flags flags) + : lldb_private::RegisterInfoAndSetInterface(target_arch), + m_register_info_p(GetRegisterInfoPtr(target_arch)), + m_register_info_count(GetRegisterInfoCount(target_arch)) {} + +uint32_t RegisterInfoPOSIX_loongarch64::GetRegisterCount() const { + return m_register_info_count; +} + +size_t RegisterInfoPOSIX_loongarch64::GetGPRSize() const { + return sizeof(struct RegisterInfoPOSIX_loongarch64::GPR); +} + +size_t RegisterInfoPOSIX_loongarch64::GetFPRSize() const { + return sizeof(struct RegisterInfoPOSIX_loongarch64::FPR); +} + +const lldb_private::RegisterInfo * +RegisterInfoPOSIX_loongarch64::GetRegisterInfo() const { + return m_register_info_p; +} + +size_t RegisterInfoPOSIX_loongarch64::GetRegisterSetCount() const { + return k_num_register_sets; +} + +size_t RegisterInfoPOSIX_loongarch64::GetRegisterSetFromRegisterIndex( + uint32_t reg_index) const { + // coverity[unsigned_compare] + if (reg_index >= gpr_first_loongarch && reg_index <= gpr_last_loongarch) + return GPRegSet; + if (reg_index >= fpr_first_loongarch && reg_index <= fpr_last_loongarch) + return FPRegSet; + return LLDB_INVALID_REGNUM; +} + +const lldb_private::RegisterSet * +RegisterInfoPOSIX_loongarch64::GetRegisterSet(size_t set_index) const { + if (set_index < GetRegisterSetCount()) + return &g_reg_sets_loongarch64[set_index]; + return nullptr; +} diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_loongarch64.h b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_loongarch64.h new file mode 100644 index 000000000000..a3338acbbc97 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_loongarch64.h @@ -0,0 +1,69 @@ +//===-- RegisterInfoPOSIX_loongarch64.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_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERINFOPOSIX_LOONGARCH64_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERINFOPOSIX_LOONGARCH64_H + +#include "RegisterInfoAndSetInterface.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/lldb-private.h" +#include <map> + +class RegisterInfoPOSIX_loongarch64 + : public lldb_private::RegisterInfoAndSetInterface { +public: + static const lldb_private::RegisterInfo * + GetRegisterInfoPtr(const lldb_private::ArchSpec &target_arch); + static uint32_t + GetRegisterInfoCount(const lldb_private::ArchSpec &target_arch); + +public: + enum RegSetKind { + GPRegSet, + FPRegSet, + }; + + struct GPR { + uint64_t gpr[32]; + + uint64_t orig_a0; + uint64_t csr_era; + uint64_t csr_badv; + uint64_t reserved[10]; + }; + + struct FPR { + uint64_t fpr[32]; + uint64_t fcc; + uint32_t fcsr; + }; + + RegisterInfoPOSIX_loongarch64(const lldb_private::ArchSpec &target_arch, + lldb_private::Flags flags); + + size_t GetGPRSize() const override; + + size_t GetFPRSize() const override; + + const lldb_private::RegisterInfo *GetRegisterInfo() const override; + + uint32_t GetRegisterCount() const override; + + const lldb_private::RegisterSet * + GetRegisterSet(size_t reg_set) const override; + + size_t GetRegisterSetCount() const override; + + size_t GetRegisterSetFromRegisterIndex(uint32_t reg_index) const override; + +private: + const lldb_private::RegisterInfo *m_register_info_p; + uint32_t m_register_info_count; +}; + +#endif diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_riscv64.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_riscv64.cpp new file mode 100644 index 000000000000..3819401c543b --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_riscv64.cpp @@ -0,0 +1,142 @@ +//===-- RegisterInfoPOSIX_riscv64.cpp -------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===---------------------------------------------------------------------===// + +#include <cassert> +#include <lldb/Utility/Flags.h> +#include <stddef.h> + +#include "lldb/lldb-defines.h" +#include "llvm/Support/Compiler.h" + +#include "RegisterInfoPOSIX_riscv64.h" + +#define GPR_OFFSET(idx) ((idx)*8 + 0) +#define FPR_OFFSET(idx) ((idx)*8 + sizeof(RegisterInfoPOSIX_riscv64::GPR)) + +#define REG_CONTEXT_SIZE \ + (sizeof(RegisterInfoPOSIX_riscv64::GPR) + \ + sizeof(RegisterInfoPOSIX_riscv64::FPR)) + +#define DECLARE_REGISTER_INFOS_RISCV64_STRUCT +#include "RegisterInfos_riscv64.h" +#undef DECLARE_REGISTER_INFOS_RISCV64_STRUCT + +const lldb_private::RegisterInfo *RegisterInfoPOSIX_riscv64::GetRegisterInfoPtr( + const lldb_private::ArchSpec &target_arch) { + switch (target_arch.GetMachine()) { + case llvm::Triple::riscv64: + return g_register_infos_riscv64_le; + default: + assert(false && "Unhandled target architecture."); + return nullptr; + } +} + +uint32_t RegisterInfoPOSIX_riscv64::GetRegisterInfoCount( + const lldb_private::ArchSpec &target_arch) { + switch (target_arch.GetMachine()) { + case llvm::Triple::riscv64: + return static_cast<uint32_t>(sizeof(g_register_infos_riscv64_le) / + sizeof(g_register_infos_riscv64_le[0])); + default: + assert(false && "Unhandled target architecture."); + return 0; + } +} + +// Number of register sets provided by this context. +enum { + k_num_gpr_registers = gpr_last_riscv - gpr_first_riscv + 1, + k_num_fpr_registers = fpr_last_riscv - fpr_first_riscv + 1, + k_num_register_sets = 2 +}; + +// RISC-V64 general purpose registers. +static const uint32_t g_gpr_regnums_riscv64[] = { + gpr_pc_riscv, gpr_ra_riscv, gpr_sp_riscv, gpr_x3_riscv, + gpr_x4_riscv, gpr_x5_riscv, gpr_x6_riscv, gpr_x7_riscv, + gpr_fp_riscv, gpr_x9_riscv, gpr_x10_riscv, gpr_x11_riscv, + gpr_x12_riscv, gpr_x13_riscv, gpr_x14_riscv, gpr_x15_riscv, + gpr_x16_riscv, gpr_x17_riscv, gpr_x18_riscv, gpr_x19_riscv, + gpr_x20_riscv, gpr_x21_riscv, gpr_x22_riscv, gpr_x23_riscv, + gpr_x24_riscv, gpr_x25_riscv, gpr_x26_riscv, gpr_x27_riscv, + gpr_x28_riscv, gpr_x29_riscv, gpr_x30_riscv, gpr_x31_riscv, + gpr_x0_riscv, LLDB_INVALID_REGNUM}; + +static_assert(((sizeof g_gpr_regnums_riscv64 / + sizeof g_gpr_regnums_riscv64[0]) - + 1) == k_num_gpr_registers, + "g_gpr_regnums_riscv64 has wrong number of register infos"); + +// RISC-V64 floating point registers. +static const uint32_t g_fpr_regnums_riscv64[] = { + fpr_f0_riscv, fpr_f1_riscv, fpr_f2_riscv, fpr_f3_riscv, + fpr_f4_riscv, fpr_f5_riscv, fpr_f6_riscv, fpr_f7_riscv, + fpr_f8_riscv, fpr_f9_riscv, fpr_f10_riscv, fpr_f11_riscv, + fpr_f12_riscv, fpr_f13_riscv, fpr_f14_riscv, fpr_f15_riscv, + fpr_f16_riscv, fpr_f17_riscv, fpr_f18_riscv, fpr_f19_riscv, + fpr_f20_riscv, fpr_f21_riscv, fpr_f22_riscv, fpr_f23_riscv, + fpr_f24_riscv, fpr_f25_riscv, fpr_f26_riscv, fpr_f27_riscv, + fpr_f28_riscv, fpr_f29_riscv, fpr_f30_riscv, fpr_f31_riscv, + fpr_fcsr_riscv, LLDB_INVALID_REGNUM}; + +static_assert(((sizeof g_fpr_regnums_riscv64 / + sizeof g_fpr_regnums_riscv64[0]) - + 1) == k_num_fpr_registers, + "g_fpr_regnums_riscv64 has wrong number of register infos"); + +// Register sets for RISC-V64. +static const lldb_private::RegisterSet g_reg_sets_riscv64[k_num_register_sets] = + {{"General Purpose Registers", "gpr", k_num_gpr_registers, + g_gpr_regnums_riscv64}, + {"Floating Point Registers", "fpr", k_num_fpr_registers, + g_fpr_regnums_riscv64}}; + +RegisterInfoPOSIX_riscv64::RegisterInfoPOSIX_riscv64( + const lldb_private::ArchSpec &target_arch, lldb_private::Flags flags) + : lldb_private::RegisterInfoAndSetInterface(target_arch), + m_register_info_p(GetRegisterInfoPtr(target_arch)), + m_register_info_count(GetRegisterInfoCount(target_arch)) {} + +uint32_t RegisterInfoPOSIX_riscv64::GetRegisterCount() const { + return m_register_info_count; +} + +size_t RegisterInfoPOSIX_riscv64::GetGPRSize() const { + return sizeof(struct RegisterInfoPOSIX_riscv64::GPR); +} + +size_t RegisterInfoPOSIX_riscv64::GetFPRSize() const { + return sizeof(struct RegisterInfoPOSIX_riscv64::FPR); +} + +const lldb_private::RegisterInfo * +RegisterInfoPOSIX_riscv64::GetRegisterInfo() const { + return m_register_info_p; +} + +size_t RegisterInfoPOSIX_riscv64::GetRegisterSetCount() const { + return k_num_register_sets; +} + +size_t RegisterInfoPOSIX_riscv64::GetRegisterSetFromRegisterIndex( + uint32_t reg_index) const { + // coverity[unsigned_compare] + if (reg_index >= gpr_first_riscv && reg_index <= gpr_last_riscv) + return GPRegSet; + if (reg_index >= fpr_first_riscv && reg_index <= fpr_last_riscv) + return FPRegSet; + return LLDB_INVALID_REGNUM; +} + +const lldb_private::RegisterSet * +RegisterInfoPOSIX_riscv64::GetRegisterSet(size_t set_index) const { + if (set_index < GetRegisterSetCount()) + return &g_reg_sets_riscv64[set_index]; + return nullptr; +} diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_riscv64.h b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_riscv64.h new file mode 100644 index 000000000000..c5b955f93af6 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_riscv64.h @@ -0,0 +1,61 @@ +//===-- RegisterInfoPOSIX_riscv64.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_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERINFOPOSIX_RISCV64_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERINFOPOSIX_RISCV64_H + +#include "RegisterInfoAndSetInterface.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/lldb-private.h" +#include <map> + +class RegisterInfoPOSIX_riscv64 + : public lldb_private::RegisterInfoAndSetInterface { +public: + static const lldb_private::RegisterInfo * + GetRegisterInfoPtr(const lldb_private::ArchSpec &target_arch); + static uint32_t + GetRegisterInfoCount(const lldb_private::ArchSpec &target_arch); + +public: + enum { GPRegSet = 0, FPRegSet }; + + struct GPR { + // note: gpr[0] is pc, not x0 + uint64_t gpr[32]; + }; + + struct FPR { + uint64_t fpr[32]; + uint32_t fcsr; + }; + + RegisterInfoPOSIX_riscv64(const lldb_private::ArchSpec &target_arch, + lldb_private::Flags flags); + + size_t GetGPRSize() const override; + + size_t GetFPRSize() const override; + + const lldb_private::RegisterInfo *GetRegisterInfo() const override; + + uint32_t GetRegisterCount() const override; + + const lldb_private::RegisterSet * + GetRegisterSet(size_t reg_set) const override; + + size_t GetRegisterSetCount() const override; + + size_t GetRegisterSetFromRegisterIndex(uint32_t reg_index) const override; + +private: + const lldb_private::RegisterInfo *m_register_info_p; + uint32_t m_register_info_count; +}; + +#endif diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_arm64.h b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_arm64.h index d647fcaa600a..513ca5a8f10c 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_arm64.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_arm64.h @@ -484,6 +484,8 @@ static uint32_t g_d31_invalidates[] = {fpu_v31, fpu_s31, LLDB_INVALID_REGNUM}; #define MISC_FPU_KIND(lldb_kind) LLDB_KIND(lldb_kind) #define MISC_EXC_KIND(lldb_kind) LLDB_KIND(lldb_kind) +// clang-format off + // Defines a 64-bit general purpose register #define DEFINE_GPR64(reg, generic_kind) \ { \ diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_arm64_sve.h b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_arm64_sve.h index b2837b8f1e98..f61e3738b8fc 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_arm64_sve.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_arm64_sve.h @@ -304,6 +304,8 @@ static uint32_t g_contained_z31[] = {sve_z31, LLDB_INVALID_REGNUM}; // Default offset SVE Z registers and all corresponding pseudo registers // ( S, D and V registers) is zero and will be configured during execution. +// clang-format off + // Defines sve pseudo vector (V) register with 16-byte size #define DEFINE_VREG_SVE(vreg, zreg) \ { \ @@ -333,7 +335,6 @@ static uint32_t g_contained_z31[] = {sve_z31, LLDB_INVALID_REGNUM}; } static lldb_private::RegisterInfo g_register_infos_arm64_sve_le[] = { - // clang-format off // DEFINE_GPR64(name, GENERIC KIND) DEFINE_GPR64(x0, LLDB_REGNUM_GENERIC_ARG1), DEFINE_GPR64(x1, LLDB_REGNUM_GENERIC_ARG2), diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_loongarch64.h b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_loongarch64.h new file mode 100644 index 000000000000..27f2bac22dd5 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_loongarch64.h @@ -0,0 +1,171 @@ +//===-- RegisterInfos_loongarch64.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 +// +//===----------------------------------------------------------------------===// + +#ifdef DECLARE_REGISTER_INFOS_LOONGARCH64_STRUCT + +#include <stddef.h> + +#include "lldb/lldb-defines.h" +#include "lldb/lldb-enumerations.h" +#include "lldb/lldb-private.h" + +#include "Utility/LoongArch_DWARF_Registers.h" +#include "lldb-loongarch-register-enums.h" + +#ifndef GPR_OFFSET +#error GPR_OFFSET must be defined before including this header file +#endif + +#ifndef FPR_OFFSET +#error FPR_OFFSET must be defined before including this header file +#endif + +using namespace loongarch_dwarf; + +// clang-format off + +// I suppose EHFrame and DWARF are the same. +#define KIND_HELPER(reg, generic_kind) \ + { \ + loongarch_dwarf::dwarf_##reg, loongarch_dwarf::dwarf_##reg, generic_kind, \ + LLDB_INVALID_REGNUM, reg##_loongarch \ + } + +// Generates register kinds array for generic purpose registers +#define GPR64_KIND(reg, generic_kind) KIND_HELPER(reg, generic_kind) + +// Generates register kinds array for floating point registers +#define FPR64_KIND(reg, generic_kind) KIND_HELPER(reg, generic_kind) + +// Defines a 64-bit general purpose register +#define DEFINE_GPR64(reg, generic_kind) DEFINE_GPR64_ALT(reg, reg, generic_kind) +#define DEFINE_GPR64_ALT(reg, alt, generic_kind) \ + { \ + #reg, #alt, 8, GPR_OFFSET(gpr_##reg##_loongarch - gpr_first_loongarch), \ + lldb::eEncodingUint, lldb::eFormatHex, \ + GPR64_KIND(gpr_##reg, generic_kind), nullptr, nullptr \ + } + +// Defines a 64-bit floating point register +#define DEFINE_FPR64(reg, generic_kind) DEFINE_FPR64_ALT(reg, reg, generic_kind) +#define DEFINE_FPR64_ALT(reg, alt, generic_kind) \ + { \ + #reg, #alt, 8, FPR_OFFSET(fpr_##reg##_loongarch - fpr_first_loongarch), \ + lldb::eEncodingUint, lldb::eFormatHex, \ + FPR64_KIND(fpr_##reg, generic_kind), nullptr, nullptr \ + } + +#define DEFINE_FCC(reg, generic_kind) \ + { \ + #reg, nullptr, 1, FCC_OFFSET(fpr_##reg##_loongarch - fpr_fcc0_loongarch), \ + lldb::eEncodingUint, lldb::eFormatHex, \ + FPR64_KIND(fpr_##reg, generic_kind), nullptr, nullptr \ + } + +#define DEFINE_FCSR(reg, generic_kind) \ + { \ + #reg, nullptr, 4, FCSR_OFFSET, \ + lldb::eEncodingUint, lldb::eFormatHex, \ + FPR64_KIND(fpr_##reg, generic_kind), nullptr, nullptr \ + } + +// clang-format on + +static lldb_private::RegisterInfo g_register_infos_loongarch64[] = { + DEFINE_GPR64_ALT(r0, zero, LLDB_INVALID_REGNUM), + DEFINE_GPR64_ALT(r1, ra, LLDB_REGNUM_GENERIC_RA), + DEFINE_GPR64_ALT(r2, tp, LLDB_INVALID_REGNUM), + DEFINE_GPR64_ALT(r3, sp, LLDB_REGNUM_GENERIC_SP), + DEFINE_GPR64_ALT(r4, a0, LLDB_REGNUM_GENERIC_ARG1), + DEFINE_GPR64_ALT(r5, a1, LLDB_REGNUM_GENERIC_ARG2), + DEFINE_GPR64_ALT(r6, a2, LLDB_REGNUM_GENERIC_ARG3), + DEFINE_GPR64_ALT(r7, a3, LLDB_REGNUM_GENERIC_ARG4), + DEFINE_GPR64_ALT(r8, a4, LLDB_REGNUM_GENERIC_ARG5), + DEFINE_GPR64_ALT(r9, a5, LLDB_REGNUM_GENERIC_ARG6), + DEFINE_GPR64_ALT(r10, a6, LLDB_REGNUM_GENERIC_ARG7), + DEFINE_GPR64_ALT(r11, a7, LLDB_REGNUM_GENERIC_ARG8), + DEFINE_GPR64_ALT(r12, t0, LLDB_INVALID_REGNUM), + DEFINE_GPR64_ALT(r13, t1, LLDB_INVALID_REGNUM), + DEFINE_GPR64_ALT(r14, t2, LLDB_INVALID_REGNUM), + DEFINE_GPR64_ALT(r15, t3, LLDB_INVALID_REGNUM), + DEFINE_GPR64_ALT(r16, t4, LLDB_INVALID_REGNUM), + DEFINE_GPR64_ALT(r17, t5, LLDB_INVALID_REGNUM), + DEFINE_GPR64_ALT(r18, t6, LLDB_INVALID_REGNUM), + DEFINE_GPR64_ALT(r19, t7, LLDB_INVALID_REGNUM), + DEFINE_GPR64_ALT(r20, t8, LLDB_INVALID_REGNUM), + DEFINE_GPR64(r21, LLDB_INVALID_REGNUM), + DEFINE_GPR64_ALT(r22, fp, LLDB_REGNUM_GENERIC_FP), + DEFINE_GPR64_ALT(r23, s0, LLDB_INVALID_REGNUM), + DEFINE_GPR64_ALT(r24, s1, LLDB_INVALID_REGNUM), + DEFINE_GPR64_ALT(r25, s2, LLDB_INVALID_REGNUM), + DEFINE_GPR64_ALT(r26, s3, LLDB_INVALID_REGNUM), + DEFINE_GPR64_ALT(r27, s4, LLDB_INVALID_REGNUM), + DEFINE_GPR64_ALT(r28, s5, LLDB_INVALID_REGNUM), + DEFINE_GPR64_ALT(r29, s6, LLDB_INVALID_REGNUM), + DEFINE_GPR64_ALT(r30, s7, LLDB_INVALID_REGNUM), + DEFINE_GPR64_ALT(r31, s8, LLDB_INVALID_REGNUM), + + DEFINE_GPR64(orig_a0, LLDB_INVALID_REGNUM), + DEFINE_GPR64(pc, LLDB_REGNUM_GENERIC_PC), + DEFINE_GPR64(badv, LLDB_INVALID_REGNUM), + DEFINE_GPR64(reserved0, LLDB_INVALID_REGNUM), + DEFINE_GPR64(reserved1, LLDB_INVALID_REGNUM), + DEFINE_GPR64(reserved2, LLDB_INVALID_REGNUM), + DEFINE_GPR64(reserved3, LLDB_INVALID_REGNUM), + DEFINE_GPR64(reserved4, LLDB_INVALID_REGNUM), + DEFINE_GPR64(reserved5, LLDB_INVALID_REGNUM), + DEFINE_GPR64(reserved6, LLDB_INVALID_REGNUM), + DEFINE_GPR64(reserved7, LLDB_INVALID_REGNUM), + DEFINE_GPR64(reserved8, LLDB_INVALID_REGNUM), + DEFINE_GPR64(reserved9, LLDB_INVALID_REGNUM), + + DEFINE_FPR64_ALT(f0, fa0, LLDB_INVALID_REGNUM), + DEFINE_FPR64_ALT(f1, fa1, LLDB_INVALID_REGNUM), + DEFINE_FPR64_ALT(f2, fa2, LLDB_INVALID_REGNUM), + DEFINE_FPR64_ALT(f3, fa3, LLDB_INVALID_REGNUM), + DEFINE_FPR64_ALT(f4, fa4, LLDB_INVALID_REGNUM), + DEFINE_FPR64_ALT(f5, fa5, LLDB_INVALID_REGNUM), + DEFINE_FPR64_ALT(f6, fa6, LLDB_INVALID_REGNUM), + DEFINE_FPR64_ALT(f7, fa7, LLDB_INVALID_REGNUM), + DEFINE_FPR64_ALT(f8, ft0, LLDB_INVALID_REGNUM), + DEFINE_FPR64_ALT(f9, ft1, LLDB_INVALID_REGNUM), + DEFINE_FPR64_ALT(f10, ft2, LLDB_INVALID_REGNUM), + DEFINE_FPR64_ALT(f11, ft3, LLDB_INVALID_REGNUM), + DEFINE_FPR64_ALT(f12, ft4, LLDB_INVALID_REGNUM), + DEFINE_FPR64_ALT(f13, ft5, LLDB_INVALID_REGNUM), + DEFINE_FPR64_ALT(f14, ft6, LLDB_INVALID_REGNUM), + DEFINE_FPR64_ALT(f15, ft7, LLDB_INVALID_REGNUM), + DEFINE_FPR64_ALT(f16, ft8, LLDB_INVALID_REGNUM), + DEFINE_FPR64_ALT(f17, ft9, LLDB_INVALID_REGNUM), + DEFINE_FPR64_ALT(f18, ft10, LLDB_INVALID_REGNUM), + DEFINE_FPR64_ALT(f19, ft11, LLDB_INVALID_REGNUM), + DEFINE_FPR64_ALT(f20, ft12, LLDB_INVALID_REGNUM), + DEFINE_FPR64_ALT(f21, ft13, LLDB_INVALID_REGNUM), + DEFINE_FPR64_ALT(f22, ft14, LLDB_INVALID_REGNUM), + DEFINE_FPR64_ALT(f23, ft15, LLDB_INVALID_REGNUM), + DEFINE_FPR64_ALT(f24, fs0, LLDB_INVALID_REGNUM), + DEFINE_FPR64_ALT(f25, fs1, LLDB_INVALID_REGNUM), + DEFINE_FPR64_ALT(f26, fs2, LLDB_INVALID_REGNUM), + DEFINE_FPR64_ALT(f27, fs3, LLDB_INVALID_REGNUM), + DEFINE_FPR64_ALT(f28, fs4, LLDB_INVALID_REGNUM), + DEFINE_FPR64_ALT(f29, fs5, LLDB_INVALID_REGNUM), + DEFINE_FPR64_ALT(f30, fs6, LLDB_INVALID_REGNUM), + DEFINE_FPR64_ALT(f31, fs7, LLDB_INVALID_REGNUM), + + DEFINE_FCC(fcc0, LLDB_INVALID_REGNUM), + DEFINE_FCC(fcc1, LLDB_INVALID_REGNUM), + DEFINE_FCC(fcc2, LLDB_INVALID_REGNUM), + DEFINE_FCC(fcc3, LLDB_INVALID_REGNUM), + DEFINE_FCC(fcc4, LLDB_INVALID_REGNUM), + DEFINE_FCC(fcc5, LLDB_INVALID_REGNUM), + DEFINE_FCC(fcc6, LLDB_INVALID_REGNUM), + DEFINE_FCC(fcc7, LLDB_INVALID_REGNUM), + DEFINE_FCSR(fcsr, LLDB_INVALID_REGNUM), +}; + +#endif // DECLARE_REGISTER_INFOS_LOONGARCH64_STRUCT diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_riscv64.h b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_riscv64.h new file mode 100644 index 000000000000..331155eab32f --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_riscv64.h @@ -0,0 +1,140 @@ +//===-- RegisterInfos_riscv64.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 +// +//===----------------------------------------------------------------------===// + +#ifdef DECLARE_REGISTER_INFOS_RISCV64_STRUCT + +#include <stddef.h> + +#include "lldb/lldb-defines.h" +#include "lldb/lldb-enumerations.h" +#include "lldb/lldb-private.h" + +#include "Utility/RISCV_DWARF_Registers.h" +#include "lldb-riscv-register-enums.h" + +#ifndef GPR_OFFSET +#error GPR_OFFSET must be defined before including this header file +#endif + +#ifndef FPR_OFFSET +#error FPR_OFFSET must be defined before including this header file +#endif + +using namespace riscv_dwarf; + +// clang-format off + +// I suppose EHFrame and DWARF are the same. +#define KIND_HELPER(reg, generic_kind) \ + { \ + riscv_dwarf::dwarf_##reg, riscv_dwarf::dwarf_##reg, generic_kind, \ + LLDB_INVALID_REGNUM, reg##_riscv \ + } + +// Generates register kinds array for vector registers +#define GPR64_KIND(reg, generic_kind) KIND_HELPER(reg, generic_kind) + +// FPR register kinds array for vector registers +#define FPR64_KIND(reg, generic_kind) KIND_HELPER(reg, generic_kind) + +// Defines a 64-bit general purpose register +#define DEFINE_GPR64(reg, generic_kind) DEFINE_GPR64_ALT(reg, reg, generic_kind) + +// Defines a 64-bit general purpose register +#define DEFINE_GPR64_ALT(reg, alt, generic_kind) \ + { \ + #reg, #alt, 8, GPR_OFFSET(gpr_##reg##_riscv - gpr_first_riscv), \ + lldb::eEncodingUint, lldb::eFormatHex, \ + GPR64_KIND(gpr_##reg, generic_kind), nullptr, nullptr \ + } + +#define DEFINE_FPR64(reg, generic_kind) DEFINE_FPR64_ALT(reg, reg, generic_kind) + +#define DEFINE_FPR64_ALT(reg, alt, generic_kind) DEFINE_FPR_ALT(reg, alt, 8, generic_kind) + +#define DEFINE_FPR_ALT(reg, alt, size, generic_kind) \ + { \ + #reg, #alt, size, FPR_OFFSET(fpr_##reg##_riscv - fpr_first_riscv), \ + lldb::eEncodingUint, lldb::eFormatHex, \ + FPR64_KIND(fpr_##reg, generic_kind), nullptr, nullptr \ + } + +// clang-format on + +static lldb_private::RegisterInfo g_register_infos_riscv64_le[] = { + // DEFINE_GPR64(name, GENERIC KIND) + DEFINE_GPR64(pc, LLDB_REGNUM_GENERIC_PC), + DEFINE_GPR64_ALT(ra, x1, LLDB_REGNUM_GENERIC_RA), + DEFINE_GPR64_ALT(sp, x2, LLDB_REGNUM_GENERIC_SP), + DEFINE_GPR64_ALT(gp, x3, LLDB_INVALID_REGNUM), + DEFINE_GPR64_ALT(tp, x4, LLDB_INVALID_REGNUM), + DEFINE_GPR64_ALT(t0, x5, LLDB_INVALID_REGNUM), + DEFINE_GPR64_ALT(t1, x6, LLDB_INVALID_REGNUM), + DEFINE_GPR64_ALT(t2, x7, LLDB_INVALID_REGNUM), + DEFINE_GPR64_ALT(fp, x8, LLDB_REGNUM_GENERIC_FP), + DEFINE_GPR64_ALT(s1, x9, LLDB_INVALID_REGNUM), + DEFINE_GPR64_ALT(a0, x10, LLDB_REGNUM_GENERIC_ARG1), + DEFINE_GPR64_ALT(a1, x11, LLDB_REGNUM_GENERIC_ARG2), + DEFINE_GPR64_ALT(a2, x12, LLDB_REGNUM_GENERIC_ARG3), + DEFINE_GPR64_ALT(a3, x13, LLDB_REGNUM_GENERIC_ARG4), + DEFINE_GPR64_ALT(a4, x14, LLDB_REGNUM_GENERIC_ARG5), + DEFINE_GPR64_ALT(a5, x15, LLDB_REGNUM_GENERIC_ARG6), + DEFINE_GPR64_ALT(a6, x16, LLDB_REGNUM_GENERIC_ARG7), + DEFINE_GPR64_ALT(a7, x17, LLDB_REGNUM_GENERIC_ARG8), + DEFINE_GPR64_ALT(s2, x18, LLDB_INVALID_REGNUM), + DEFINE_GPR64_ALT(s3, x19, LLDB_INVALID_REGNUM), + DEFINE_GPR64_ALT(s4, x20, LLDB_INVALID_REGNUM), + DEFINE_GPR64_ALT(s5, x21, LLDB_INVALID_REGNUM), + DEFINE_GPR64_ALT(s6, x22, LLDB_INVALID_REGNUM), + DEFINE_GPR64_ALT(s7, x23, LLDB_INVALID_REGNUM), + DEFINE_GPR64_ALT(s8, x24, LLDB_INVALID_REGNUM), + DEFINE_GPR64_ALT(s9, x25, LLDB_INVALID_REGNUM), + DEFINE_GPR64_ALT(s10, x26, LLDB_INVALID_REGNUM), + DEFINE_GPR64_ALT(s11, x27, LLDB_INVALID_REGNUM), + DEFINE_GPR64_ALT(t3, x28, LLDB_INVALID_REGNUM), + DEFINE_GPR64_ALT(t4, x29, LLDB_INVALID_REGNUM), + DEFINE_GPR64_ALT(t5, x30, LLDB_INVALID_REGNUM), + DEFINE_GPR64_ALT(t6, x31, LLDB_INVALID_REGNUM), + DEFINE_GPR64_ALT(zero, x0, LLDB_INVALID_REGNUM), + + DEFINE_FPR64_ALT(ft0, f0, LLDB_INVALID_REGNUM), + DEFINE_FPR64_ALT(ft1, f1, LLDB_INVALID_REGNUM), + DEFINE_FPR64_ALT(ft2, f2, LLDB_INVALID_REGNUM), + DEFINE_FPR64_ALT(ft3, f3, LLDB_INVALID_REGNUM), + DEFINE_FPR64_ALT(ft4, f4, LLDB_INVALID_REGNUM), + DEFINE_FPR64_ALT(ft5, f5, LLDB_INVALID_REGNUM), + DEFINE_FPR64_ALT(ft6, f6, LLDB_INVALID_REGNUM), + DEFINE_FPR64_ALT(ft7, f7, LLDB_INVALID_REGNUM), + DEFINE_FPR64_ALT(fs0, f8, LLDB_INVALID_REGNUM), + DEFINE_FPR64_ALT(fs1, f9, LLDB_INVALID_REGNUM), + DEFINE_FPR64_ALT(fa0, f10, LLDB_INVALID_REGNUM), + DEFINE_FPR64_ALT(fa1, f11, LLDB_INVALID_REGNUM), + DEFINE_FPR64_ALT(fa2, f12, LLDB_INVALID_REGNUM), + DEFINE_FPR64_ALT(fa3, f13, LLDB_INVALID_REGNUM), + DEFINE_FPR64_ALT(fa4, f14, LLDB_INVALID_REGNUM), + DEFINE_FPR64_ALT(fa5, f15, LLDB_INVALID_REGNUM), + DEFINE_FPR64_ALT(fa6, f16, LLDB_INVALID_REGNUM), + DEFINE_FPR64_ALT(fa7, f17, LLDB_INVALID_REGNUM), + DEFINE_FPR64_ALT(fs2, f18, LLDB_INVALID_REGNUM), + DEFINE_FPR64_ALT(fs3, f19, LLDB_INVALID_REGNUM), + DEFINE_FPR64_ALT(fs4, f20, LLDB_INVALID_REGNUM), + DEFINE_FPR64_ALT(fs5, f21, LLDB_INVALID_REGNUM), + DEFINE_FPR64_ALT(fs6, f22, LLDB_INVALID_REGNUM), + DEFINE_FPR64_ALT(fs7, f23, LLDB_INVALID_REGNUM), + DEFINE_FPR64_ALT(fs8, f24, LLDB_INVALID_REGNUM), + DEFINE_FPR64_ALT(fs9, f25, LLDB_INVALID_REGNUM), + DEFINE_FPR64_ALT(fs10, f26, LLDB_INVALID_REGNUM), + DEFINE_FPR64_ALT(fs11, f27, LLDB_INVALID_REGNUM), + DEFINE_FPR64_ALT(ft8, f28, LLDB_INVALID_REGNUM), + DEFINE_FPR64_ALT(ft9, f29, LLDB_INVALID_REGNUM), + DEFINE_FPR64_ALT(ft10, f30, LLDB_INVALID_REGNUM), + DEFINE_FPR64_ALT(ft11, f31, LLDB_INVALID_REGNUM), + DEFINE_FPR_ALT(fcsr, nullptr, 4, LLDB_INVALID_REGNUM), +}; + +#endif // DECLARE_REGISTER_INFOS_RISCV64_STRUCT diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp index 4df210032153..aae15b2ef462 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp @@ -27,6 +27,7 @@ #include "lldb/Target/ThreadPlan.h" #include "lldb/Target/UnixSignals.h" #include "lldb/Utility/StreamString.h" +#include <optional> using namespace lldb; using namespace lldb_private; @@ -40,7 +41,7 @@ struct PtrauthInstructionInfo { /// Get any pointer-authentication related information about the instruction /// at address \p at_addr. -static llvm::Optional<PtrauthInstructionInfo> +static std::optional<PtrauthInstructionInfo> GetPtrauthInstructionInfo(Target &target, const ArchSpec &arch, const Address &at_addr) { const char *plugin_name = nullptr; @@ -50,12 +51,12 @@ GetPtrauthInstructionInfo(Target &target, const ArchSpec &arch, DisassemblerSP disassembler_sp = Disassembler::DisassembleRange( arch, plugin_name, flavor, target, range_bounds, prefer_file_cache); if (!disassembler_sp) - return llvm::None; + return std::nullopt; InstructionList &insn_list = disassembler_sp->GetInstructionList(); InstructionSP insn = insn_list.GetInstructionAtIndex(0); if (!insn) - return llvm::None; + return std::nullopt; return PtrauthInstructionInfo{insn->IsAuthenticated(), insn->IsLoad(), insn->DoesBranch()}; @@ -410,7 +411,8 @@ const char *StopInfoMachException::GetDescription() { switch (resource_type) { case RESOURCE_TYPE_CPU: - exc_desc = "EXC_RESOURCE RESOURCE_TYPE_CPU"; + exc_desc = + "EXC_RESOURCE (RESOURCE_TYPE_CPU: CPU usage monitor tripped)"; snprintf(code_desc_buf, sizeof(code_desc_buf), "%d%%", (int)EXC_RESOURCE_CPUMONITOR_DECODE_PERCENTAGE(m_exc_code)); snprintf(subcode_desc_buf, sizeof(subcode_desc_buf), "%d%%", @@ -418,7 +420,8 @@ const char *StopInfoMachException::GetDescription() { m_exc_subcode)); break; case RESOURCE_TYPE_WAKEUPS: - exc_desc = "EXC_RESOURCE RESOURCE_TYPE_WAKEUPS"; + exc_desc = "EXC_RESOURCE (RESOURCE_TYPE_WAKEUPS: idle wakeups monitor " + "tripped)"; snprintf( code_desc_buf, sizeof(code_desc_buf), "%d w/s", (int)EXC_RESOURCE_CPUMONITOR_DECODE_WAKEUPS_PERMITTED(m_exc_code)); @@ -427,11 +430,12 @@ const char *StopInfoMachException::GetDescription() { m_exc_subcode)); break; case RESOURCE_TYPE_MEMORY: - exc_desc = "EXC_RESOURCE RESOURCE_TYPE_MEMORY"; + exc_desc = "EXC_RESOURCE (RESOURCE_TYPE_MEMORY: high watermark memory " + "limit exceeded)"; snprintf(code_desc_buf, sizeof(code_desc_buf), "%d MB", (int)EXC_RESOURCE_HWM_DECODE_LIMIT(m_exc_code)); subcode_desc = nullptr; - subcode_label = "unused"; + subcode_label = nullptr; break; #if defined(RESOURCE_TYPE_IO) // RESOURCE_TYPE_IO is introduced in macOS SDK 10.12. @@ -468,9 +472,9 @@ const char *StopInfoMachException::GetDescription() { } if (m_exc_data_count >= 2) { - if (subcode_desc) + if (subcode_label && subcode_desc) strm.Printf(", %s=%s", subcode_label, subcode_desc); - else + else if (subcode_label) strm.Printf(", %s=0x%" PRIx64, subcode_label, m_exc_subcode); } @@ -519,6 +523,78 @@ static StopInfoSP GetStopInfoForHardwareBP(Thread &thread, Target *target, return nullptr; } +#if defined(__APPLE__) +const char * +StopInfoMachException::MachException::Name(exception_type_t exc_type) { + switch (exc_type) { + case EXC_BAD_ACCESS: + return "EXC_BAD_ACCESS"; + case EXC_BAD_INSTRUCTION: + return "EXC_BAD_INSTRUCTION"; + case EXC_ARITHMETIC: + return "EXC_ARITHMETIC"; + case EXC_EMULATION: + return "EXC_EMULATION"; + case EXC_SOFTWARE: + return "EXC_SOFTWARE"; + case EXC_BREAKPOINT: + return "EXC_BREAKPOINT"; + case EXC_SYSCALL: + return "EXC_SYSCALL"; + case EXC_MACH_SYSCALL: + return "EXC_MACH_SYSCALL"; + case EXC_RPC_ALERT: + return "EXC_RPC_ALERT"; +#ifdef EXC_CRASH + case EXC_CRASH: + return "EXC_CRASH"; +#endif + case EXC_RESOURCE: + return "EXC_RESOURCE"; +#ifdef EXC_GUARD + case EXC_GUARD: + return "EXC_GUARD"; +#endif +#ifdef EXC_CORPSE_NOTIFY + case EXC_CORPSE_NOTIFY: + return "EXC_CORPSE_NOTIFY"; +#endif +#ifdef EXC_CORPSE_VARIANT_BIT + case EXC_CORPSE_VARIANT_BIT: + return "EXC_CORPSE_VARIANT_BIT"; +#endif + default: + break; + } + return NULL; +} + +std::optional<exception_type_t> +StopInfoMachException::MachException::ExceptionCode(const char *name) { + return llvm::StringSwitch<std::optional<exception_type_t>>(name) + .Case("EXC_BAD_ACCESS", EXC_BAD_ACCESS) + .Case("EXC_BAD_INSTRUCTION", EXC_BAD_INSTRUCTION) + .Case("EXC_ARITHMETIC", EXC_ARITHMETIC) + .Case("EXC_EMULATION", EXC_EMULATION) + .Case("EXC_SOFTWARE", EXC_SOFTWARE) + .Case("EXC_BREAKPOINT", EXC_BREAKPOINT) + .Case("EXC_SYSCALL", EXC_SYSCALL) + .Case("EXC_MACH_SYSCALL", EXC_MACH_SYSCALL) + .Case("EXC_RPC_ALERT", EXC_RPC_ALERT) +#ifdef EXC_CRASH + .Case("EXC_CRASH", EXC_CRASH) +#endif + .Case("EXC_RESOURCE", EXC_RESOURCE) +#ifdef EXC_GUARD + .Case("EXC_GUARD", EXC_GUARD) +#endif +#ifdef EXC_CORPSE_NOTIFY + .Case("EXC_CORPSE_NOTIFY", EXC_CORPSE_NOTIFY) +#endif + .Default(std::nullopt); +} +#endif + StopInfoSP StopInfoMachException::CreateStopReasonWithMachException( Thread &thread, uint32_t exc_type, uint32_t exc_data_count, uint64_t exc_code, uint64_t exc_sub_code, uint64_t exc_sub_sub_code, diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/StopInfoMachException.h b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/StopInfoMachException.h index 6467745a7bf2..541ef5e69565 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/StopInfoMachException.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/StopInfoMachException.h @@ -9,10 +9,16 @@ #ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_STOPINFOMACHEXCEPTION_H #define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_STOPINFOMACHEXCEPTION_H +#include <optional> #include <string> #include "lldb/Target/StopInfo.h" +#if defined(__APPLE__) +// Needed for the EXC_* defines +#include <mach/exception.h> +#endif + namespace lldb_private { class StopInfoMachException : public StopInfo { @@ -37,6 +43,13 @@ public: const char *GetDescription() override; +#if defined(__APPLE__) + struct MachException { + static const char *Name(exception_type_t exc_type); + static std::optional<exception_type_t> ExceptionCode(const char *name); + }; +#endif + // Since some mach exceptions will be reported as breakpoints, signals, // or trace, we use this static accessor which will translate the mach // exception into the correct StopInfo. diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/lldb-loongarch-register-enums.h b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/lldb-loongarch-register-enums.h new file mode 100644 index 000000000000..f55c807f86c0 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/lldb-loongarch-register-enums.h @@ -0,0 +1,178 @@ +//===-- lldb-loongarch-register-enums.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_SOURCE_PLUGINS_PROCESS_UTILITY_LLDB_LOONGARCH_REGISTER_ENUMS_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_LLDB_LOONGARCH_REGISTER_ENUMS_H + +// LLDB register codes (e.g. RegisterKind == eRegisterKindLLDB) + +// Internal codes for all loongarch registers. +enum { + // The same order as user_regs_struct in <asm/ptrace.h> + // note: these enum values are used as byte_offset + gpr_first_loongarch = 0, + gpr_r0_loongarch = gpr_first_loongarch, + gpr_r1_loongarch, + gpr_r2_loongarch, + gpr_r3_loongarch, + gpr_r4_loongarch, + gpr_r5_loongarch, + gpr_r6_loongarch, + gpr_r7_loongarch, + gpr_r8_loongarch, + gpr_r9_loongarch, + gpr_r10_loongarch, + gpr_r11_loongarch, + gpr_r12_loongarch, + gpr_r13_loongarch, + gpr_r14_loongarch, + gpr_r15_loongarch, + gpr_r16_loongarch, + gpr_r17_loongarch, + gpr_r18_loongarch, + gpr_r19_loongarch, + gpr_r20_loongarch, + gpr_r21_loongarch, + gpr_r22_loongarch, + gpr_r23_loongarch, + gpr_r24_loongarch, + gpr_r25_loongarch, + gpr_r26_loongarch, + gpr_r27_loongarch, + gpr_r28_loongarch, + gpr_r29_loongarch, + gpr_r30_loongarch, + gpr_r31_loongarch, + gpr_orig_a0_loongarch, + gpr_pc_loongarch, + gpr_badv_loongarch, + gpr_reserved0_loongarch, + gpr_reserved1_loongarch, + gpr_reserved2_loongarch, + gpr_reserved3_loongarch, + gpr_reserved4_loongarch, + gpr_reserved5_loongarch, + gpr_reserved6_loongarch, + gpr_reserved7_loongarch, + gpr_reserved8_loongarch, + gpr_reserved9_loongarch, + gpr_last_loongarch = 44, + + gpr_zero_loongarch = gpr_r0_loongarch, + gpr_ra_loongarch = gpr_r1_loongarch, + gpr_tp_loongarch = gpr_r2_loongarch, + gpr_sp_loongarch = gpr_r3_loongarch, + gpr_a0_loongarch = gpr_r4_loongarch, + gpr_a1_loongarch = gpr_r5_loongarch, + gpr_a2_loongarch = gpr_r6_loongarch, + gpr_a3_loongarch = gpr_r7_loongarch, + gpr_a4_loongarch = gpr_r8_loongarch, + gpr_a5_loongarch = gpr_r9_loongarch, + gpr_a6_loongarch = gpr_r10_loongarch, + gpr_a7_loongarch = gpr_r11_loongarch, + gpr_t0_loongarch = gpr_r12_loongarch, + gpr_t1_loongarch = gpr_r13_loongarch, + gpr_t2_loongarch = gpr_r14_loongarch, + gpr_t3_loongarch = gpr_r15_loongarch, + gpr_t4_loongarch = gpr_r16_loongarch, + gpr_t5_loongarch = gpr_r17_loongarch, + gpr_t6_loongarch = gpr_r18_loongarch, + gpr_t7_loongarch = gpr_r19_loongarch, + gpr_t8_loongarch = gpr_r20_loongarch, + gpr_fp_loongarch = gpr_r22_loongarch, + gpr_s0_loongarch = gpr_r23_loongarch, + gpr_s1_loongarch = gpr_r24_loongarch, + gpr_s2_loongarch = gpr_r25_loongarch, + gpr_s3_loongarch = gpr_r26_loongarch, + gpr_s4_loongarch = gpr_r27_loongarch, + gpr_s5_loongarch = gpr_r28_loongarch, + gpr_s6_loongarch = gpr_r29_loongarch, + gpr_s7_loongarch = gpr_r30_loongarch, + gpr_s8_loongarch = gpr_r31_loongarch, + + fpr_first_loongarch = 45, + fpr_f0_loongarch = fpr_first_loongarch, + fpr_f1_loongarch, + fpr_f2_loongarch, + fpr_f3_loongarch, + fpr_f4_loongarch, + fpr_f5_loongarch, + fpr_f6_loongarch, + fpr_f7_loongarch, + fpr_f8_loongarch, + fpr_f9_loongarch, + fpr_f10_loongarch, + fpr_f11_loongarch, + fpr_f12_loongarch, + fpr_f13_loongarch, + fpr_f14_loongarch, + fpr_f15_loongarch, + fpr_f16_loongarch, + fpr_f17_loongarch, + fpr_f18_loongarch, + fpr_f19_loongarch, + fpr_f20_loongarch, + fpr_f21_loongarch, + fpr_f22_loongarch, + fpr_f23_loongarch, + fpr_f24_loongarch, + fpr_f25_loongarch, + fpr_f26_loongarch, + fpr_f27_loongarch, + fpr_f28_loongarch, + fpr_f29_loongarch, + fpr_f30_loongarch, + fpr_f31_loongarch, + fpr_fcc0_loongarch, + fpr_fcc1_loongarch, + fpr_fcc2_loongarch, + fpr_fcc3_loongarch, + fpr_fcc4_loongarch, + fpr_fcc5_loongarch, + fpr_fcc6_loongarch, + fpr_fcc7_loongarch, + fpr_fcsr_loongarch, + fpr_last_loongarch = fpr_fcsr_loongarch, + + fpr_fa0_loongarch = fpr_f0_loongarch, + fpr_fa1_loongarch = fpr_f1_loongarch, + fpr_fa2_loongarch = fpr_f2_loongarch, + fpr_fa3_loongarch = fpr_f3_loongarch, + fpr_fa4_loongarch = fpr_f4_loongarch, + fpr_fa5_loongarch = fpr_f5_loongarch, + fpr_fa6_loongarch = fpr_f6_loongarch, + fpr_fa7_loongarch = fpr_f7_loongarch, + fpr_ft0_loongarch = fpr_f8_loongarch, + fpr_ft1_loongarch = fpr_f9_loongarch, + fpr_ft2_loongarch = fpr_f10_loongarch, + fpr_ft3_loongarch = fpr_f11_loongarch, + fpr_ft4_loongarch = fpr_f12_loongarch, + fpr_ft5_loongarch = fpr_f13_loongarch, + fpr_ft6_loongarch = fpr_f14_loongarch, + fpr_ft7_loongarch = fpr_f15_loongarch, + fpr_ft8_loongarch = fpr_f16_loongarch, + fpr_ft9_loongarch = fpr_f17_loongarch, + fpr_ft10_loongarch = fpr_f18_loongarch, + fpr_ft11_loongarch = fpr_f19_loongarch, + fpr_ft12_loongarch = fpr_f20_loongarch, + fpr_ft13_loongarch = fpr_f21_loongarch, + fpr_ft14_loongarch = fpr_f22_loongarch, + fpr_ft15_loongarch = fpr_f23_loongarch, + fpr_fs0_loongarch = fpr_f24_loongarch, + fpr_fs1_loongarch = fpr_f25_loongarch, + fpr_fs2_loongarch = fpr_f26_loongarch, + fpr_fs3_loongarch = fpr_f27_loongarch, + fpr_fs4_loongarch = fpr_f28_loongarch, + fpr_fs5_loongarch = fpr_f29_loongarch, + fpr_fs6_loongarch = fpr_f30_loongarch, + fpr_fs7_loongarch = fpr_f31_loongarch, + + k_num_registers_loongarch +}; + +#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_LLDB_LOONGARCH_REGISTER_ENUMS_H diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/lldb-riscv-register-enums.h b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/lldb-riscv-register-enums.h new file mode 100644 index 000000000000..8c335b8c1094 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/lldb-riscv-register-enums.h @@ -0,0 +1,158 @@ +//===-- lldb-riscv-register-enums.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_SOURCE_PLUGINS_PROCESS_UTILITY_LLDB_RISCV_REGISTER_ENUMS_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_LLDB_RISCV_REGISTER_ENUMS_H + +// LLDB register codes (e.g. RegisterKind == eRegisterKindLLDB) + +// Internal codes for all riscv registers. +enum { + // The same order as user_regs_struct in <asm/ptrace.h> + // note: these enum values are used as byte_offset + gpr_first_riscv = 0, + gpr_pc_riscv = gpr_first_riscv, + gpr_x1_riscv, + gpr_x2_riscv, + gpr_x3_riscv, + gpr_x4_riscv, + gpr_x5_riscv, + gpr_x6_riscv, + gpr_x7_riscv, + gpr_x8_riscv, + gpr_x9_riscv, + gpr_x10_riscv, + gpr_x11_riscv, + gpr_x12_riscv, + gpr_x13_riscv, + gpr_x14_riscv, + gpr_x15_riscv, + gpr_x16_riscv, + gpr_x17_riscv, + gpr_x18_riscv, + gpr_x19_riscv, + gpr_x20_riscv, + gpr_x21_riscv, + gpr_x22_riscv, + gpr_x23_riscv, + gpr_x24_riscv, + gpr_x25_riscv, + gpr_x26_riscv, + gpr_x27_riscv, + gpr_x28_riscv, + gpr_x29_riscv, + gpr_x30_riscv, + gpr_x31_riscv, + gpr_x0_riscv, + gpr_zero_riscv = gpr_x0_riscv, + gpr_ra_riscv = gpr_x1_riscv, + gpr_sp_riscv = gpr_x2_riscv, + gpr_gp_riscv = gpr_x3_riscv, + gpr_tp_riscv = gpr_x4_riscv, + gpr_t0_riscv = gpr_x5_riscv, + gpr_t1_riscv = gpr_x6_riscv, + gpr_t2_riscv = gpr_x7_riscv, + gpr_fp_riscv = gpr_x8_riscv, + gpr_s1_riscv = gpr_x9_riscv, + gpr_a0_riscv = gpr_x10_riscv, + gpr_a1_riscv = gpr_x11_riscv, + gpr_a2_riscv = gpr_x12_riscv, + gpr_a3_riscv = gpr_x13_riscv, + gpr_a4_riscv = gpr_x14_riscv, + gpr_a5_riscv = gpr_x15_riscv, + gpr_a6_riscv = gpr_x16_riscv, + gpr_a7_riscv = gpr_x17_riscv, + gpr_s2_riscv = gpr_x18_riscv, + gpr_s3_riscv = gpr_x19_riscv, + gpr_s4_riscv = gpr_x20_riscv, + gpr_s5_riscv = gpr_x21_riscv, + gpr_s6_riscv = gpr_x22_riscv, + gpr_s7_riscv = gpr_x23_riscv, + gpr_s8_riscv = gpr_x24_riscv, + gpr_s9_riscv = gpr_x25_riscv, + gpr_s10_riscv = gpr_x26_riscv, + gpr_s11_riscv = gpr_x27_riscv, + gpr_t3_riscv = gpr_x28_riscv, + gpr_t4_riscv = gpr_x29_riscv, + gpr_t5_riscv = gpr_x30_riscv, + gpr_t6_riscv = gpr_x31_riscv, + gpr_last_riscv = gpr_x0_riscv, + + fpr_first_riscv = 33, + fpr_f0_riscv = fpr_first_riscv, + fpr_f1_riscv, + fpr_f2_riscv, + fpr_f3_riscv, + fpr_f4_riscv, + fpr_f5_riscv, + fpr_f6_riscv, + fpr_f7_riscv, + fpr_f8_riscv, + fpr_f9_riscv, + fpr_f10_riscv, + fpr_f11_riscv, + fpr_f12_riscv, + fpr_f13_riscv, + fpr_f14_riscv, + fpr_f15_riscv, + fpr_f16_riscv, + fpr_f17_riscv, + fpr_f18_riscv, + fpr_f19_riscv, + fpr_f20_riscv, + fpr_f21_riscv, + fpr_f22_riscv, + fpr_f23_riscv, + fpr_f24_riscv, + fpr_f25_riscv, + fpr_f26_riscv, + fpr_f27_riscv, + fpr_f28_riscv, + fpr_f29_riscv, + fpr_f30_riscv, + fpr_f31_riscv, + + fpr_fcsr_riscv, + fpr_ft0_riscv = fpr_f0_riscv, + fpr_ft1_riscv = fpr_f1_riscv, + fpr_ft2_riscv = fpr_f2_riscv, + fpr_ft3_riscv = fpr_f3_riscv, + fpr_ft4_riscv = fpr_f4_riscv, + fpr_ft5_riscv = fpr_f5_riscv, + fpr_ft6_riscv = fpr_f6_riscv, + fpr_ft7_riscv = fpr_f7_riscv, + fpr_fs0_riscv = fpr_f8_riscv, + fpr_fs1_riscv = fpr_f9_riscv, + fpr_fa0_riscv = fpr_f10_riscv, + fpr_fa1_riscv = fpr_f11_riscv, + fpr_fa2_riscv = fpr_f12_riscv, + fpr_fa3_riscv = fpr_f13_riscv, + fpr_fa4_riscv = fpr_f14_riscv, + fpr_fa5_riscv = fpr_f15_riscv, + fpr_fa6_riscv = fpr_f16_riscv, + fpr_fa7_riscv = fpr_f17_riscv, + fpr_fs2_riscv = fpr_f18_riscv, + fpr_fs3_riscv = fpr_f19_riscv, + fpr_fs4_riscv = fpr_f20_riscv, + fpr_fs5_riscv = fpr_f21_riscv, + fpr_fs6_riscv = fpr_f22_riscv, + fpr_fs7_riscv = fpr_f23_riscv, + fpr_fs8_riscv = fpr_f24_riscv, + fpr_fs9_riscv = fpr_f25_riscv, + fpr_fs10_riscv = fpr_f26_riscv, + fpr_fs11_riscv = fpr_f27_riscv, + fpr_ft8_riscv = fpr_f28_riscv, + fpr_ft9_riscv = fpr_f29_riscv, + fpr_ft10_riscv = fpr_f30_riscv, + fpr_ft11_riscv = fpr_f31_riscv, + fpr_last_riscv = fpr_fcsr_riscv, + + k_num_registers_riscv +}; + +#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_LLDB_RISCV_REGISTER_ENUMS_H diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp index bb88ce9e9e50..22a9996b1a6e 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp @@ -147,7 +147,7 @@ bool RegisterContextCorePOSIX_arm64::ReadRegister(const RegisterInfo *reg_info, // SVE is disabled take legacy route for FPU register access offset -= GetGPRSize(); if (offset < m_fpr_data.GetByteSize()) { - value.SetFromMemoryData(reg_info, m_fpr_data.GetDataStart() + offset, + value.SetFromMemoryData(*reg_info, m_fpr_data.GetDataStart() + offset, reg_info->byte_size, lldb::eByteOrderLittle, error); return error.Success(); @@ -180,7 +180,7 @@ bool RegisterContextCorePOSIX_arm64::ReadRegister(const RegisterInfo *reg_info, assert(sve_reg_num != LLDB_INVALID_REGNUM); assert(offset < m_sve_data.GetByteSize()); - value.SetFromMemoryData(reg_info, GetSVEBuffer(offset), + value.SetFromMemoryData(*reg_info, GetSVEBuffer(offset), reg_info->byte_size, lldb::eByteOrderLittle, error); } @@ -204,13 +204,13 @@ bool RegisterContextCorePOSIX_arm64::ReadRegister(const RegisterInfo *reg_info, assert(offset < m_sve_data.GetByteSize()); src = GetSVEBuffer(offset); } - value.SetFromMemoryData(reg_info, src, byte_size, lldb::eByteOrderLittle, + value.SetFromMemoryData(*reg_info, src, byte_size, lldb::eByteOrderLittle, error); } break; case SVEState::Full: offset = CalculateSVEOffset(reg_info); assert(offset < m_sve_data.GetByteSize()); - value.SetFromMemoryData(reg_info, GetSVEBuffer(offset), + value.SetFromMemoryData(*reg_info, GetSVEBuffer(offset), reg_info->byte_size, lldb::eByteOrderLittle, error); break; @@ -221,7 +221,7 @@ bool RegisterContextCorePOSIX_arm64::ReadRegister(const RegisterInfo *reg_info, } else if (IsPAuth(reg)) { offset = reg_info->byte_offset - m_register_info_up->GetPAuthOffset(); assert(offset < m_pac_data.GetByteSize()); - value.SetFromMemoryData(reg_info, m_pac_data.GetDataStart() + offset, + value.SetFromMemoryData(*reg_info, m_pac_data.GetDataStart() + offset, reg_info->byte_size, lldb::eByteOrderLittle, error); } else return false; diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp index 6bc8edb9226f..845312f4c1ed 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp @@ -73,7 +73,7 @@ bool RegisterContextCorePOSIX_x86_64::ReadRegister(const RegisterInfo *reg_info, } Status error; - value.SetFromMemoryData(reg_info, src + offset, reg_info->byte_size, + value.SetFromMemoryData(*reg_info, src + offset, reg_info->byte_size, lldb::eByteOrderLittle, error); return error.Success(); diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterUtilities.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterUtilities.cpp index 6f3bf02cd303..7455d78774ee 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterUtilities.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterUtilities.cpp @@ -8,10 +8,11 @@ #include "Plugins/Process/elf-core/RegisterUtilities.h" #include "llvm/ADT/STLExtras.h" +#include <optional> using namespace lldb_private; -static llvm::Optional<uint32_t> +static std::optional<uint32_t> getNoteType(const llvm::Triple &Triple, llvm::ArrayRef<RegsetDesc> RegsetDescs) { for (const auto &Entry : RegsetDescs) { @@ -22,7 +23,7 @@ getNoteType(const llvm::Triple &Triple, continue; return Entry.Note; } - return llvm::None; + return std::nullopt; } DataExtractor lldb_private::getRegset(llvm::ArrayRef<CoreNote> Notes, diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp index e3a3cfc4f23e..394b62559da7 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp @@ -31,10 +31,9 @@ static const seconds kWakeupInterval(5); GDBRemoteClientBase::ContinueDelegate::~ContinueDelegate() = default; -GDBRemoteClientBase::GDBRemoteClientBase(const char *comm_name, - const char *listener_name) - : GDBRemoteCommunication(comm_name, listener_name), m_async_count(0), - m_is_running(false), m_should_stop(false) {} +GDBRemoteClientBase::GDBRemoteClientBase(const char *comm_name) + : GDBRemoteCommunication(), Broadcaster(nullptr, comm_name), + m_async_count(0), m_is_running(false), m_should_stop(false) {} StateType GDBRemoteClientBase::SendContinuePacketAndWaitForResponse( ContinueDelegate &delegate, const UnixSignals &signals, @@ -196,6 +195,23 @@ GDBRemoteClientBase::SendPacketAndWaitForResponse( } GDBRemoteCommunication::PacketResult +GDBRemoteClientBase::ReadPacketWithOutputSupport( + StringExtractorGDBRemote &response, Timeout<std::micro> timeout, + bool sync_on_timeout, + llvm::function_ref<void(llvm::StringRef)> output_callback) { + auto result = ReadPacket(response, timeout, sync_on_timeout); + while (result == PacketResult::Success && response.IsNormalResponse() && + response.PeekChar() == 'O') { + response.GetChar(); + std::string output; + if (response.GetHexByteString(output)) + output_callback(output); + result = ReadPacket(response, timeout, sync_on_timeout); + } + return result; +} + +GDBRemoteCommunication::PacketResult GDBRemoteClientBase::SendPacketAndReceiveResponseWithOutputSupport( llvm::StringRef payload, StringExtractorGDBRemote &response, std::chrono::seconds interrupt_timeout, diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h index 43a5313eae6a..b47fee76a2ab 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h @@ -16,8 +16,12 @@ namespace lldb_private { namespace process_gdb_remote { -class GDBRemoteClientBase : public GDBRemoteCommunication { +class GDBRemoteClientBase : public GDBRemoteCommunication, public Broadcaster { public: + enum { + eBroadcastBitRunPacketSent = (1u << 0), + }; + struct ContinueDelegate { virtual ~ContinueDelegate(); virtual void HandleAsyncStdout(llvm::StringRef out) = 0; @@ -31,7 +35,7 @@ public: virtual void HandleAsyncStructuredDataPacket(llvm::StringRef data) = 0; }; - GDBRemoteClientBase(const char *comm_name, const char *listener_name); + GDBRemoteClientBase(const char *comm_name); bool SendAsyncSignal(int signo, std::chrono::seconds interrupt_timeout); @@ -54,6 +58,11 @@ public: llvm::StringRef payload, StringExtractorGDBRemote &response, std::chrono::seconds interrupt_timeout = std::chrono::seconds(0)); + PacketResult ReadPacketWithOutputSupport( + StringExtractorGDBRemote &response, Timeout<std::micro> timeout, + bool sync_on_timeout, + llvm::function_ref<void(llvm::StringRef)> output_callback); + PacketResult SendPacketAndReceiveResponseWithOutputSupport( llvm::StringRef payload, StringExtractorGDBRemote &response, std::chrono::seconds interrupt_timeout, diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp index 755b8220c49e..7daf003fec7b 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp @@ -30,7 +30,6 @@ #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/RegularExpression.h" -#include "lldb/Utility/Reproducer.h" #include "lldb/Utility/StreamString.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/ScopedPrinter.h" @@ -58,9 +57,8 @@ using namespace lldb_private; using namespace lldb_private::process_gdb_remote; // GDBRemoteCommunication constructor -GDBRemoteCommunication::GDBRemoteCommunication(const char *comm_name, - const char *listener_name) - : Communication(comm_name), +GDBRemoteCommunication::GDBRemoteCommunication() + : Communication(), #ifdef LLDB_CONFIGURATION_DEBUG m_packet_timeout(1000), #else @@ -223,23 +221,6 @@ GDBRemoteCommunication::PacketResult GDBRemoteCommunication::GetAck() { } GDBRemoteCommunication::PacketResult -GDBRemoteCommunication::ReadPacketWithOutputSupport( - StringExtractorGDBRemote &response, Timeout<std::micro> timeout, - bool sync_on_timeout, - llvm::function_ref<void(llvm::StringRef)> output_callback) { - auto result = ReadPacket(response, timeout, sync_on_timeout); - while (result == PacketResult::Success && response.IsNormalResponse() && - response.PeekChar() == 'O') { - response.GetChar(); - std::string output; - if (response.GetHexByteString(output)) - output_callback(output); - result = ReadPacket(response, timeout, sync_on_timeout); - } - return result; -} - -GDBRemoteCommunication::PacketResult GDBRemoteCommunication::ReadPacket(StringExtractorGDBRemote &response, Timeout<std::micro> timeout, bool sync_on_timeout) { @@ -679,7 +660,7 @@ GDBRemoteCommunication::CheckForPacket(const uint8_t *src, size_t src_len, case '%': // Async notify packet isNotifyPacket = true; - LLVM_FALLTHROUGH; + [[fallthrough]]; case '$': // Look for a standard gdb packet? @@ -1225,11 +1206,6 @@ Status GDBRemoteCommunication::StartDebugserverProcess( void GDBRemoteCommunication::DumpHistory(Stream &strm) { m_history.Dump(strm); } -void GDBRemoteCommunication::SetPacketRecorder( - repro::PacketRecorder *recorder) { - m_history.SetRecorder(recorder); -} - llvm::Error GDBRemoteCommunication::ConnectLocally(GDBRemoteCommunication &client, GDBRemoteCommunication &server) { @@ -1240,7 +1216,7 @@ GDBRemoteCommunication::ConnectLocally(GDBRemoteCommunication &client, listen_socket.Listen("localhost:0", backlog).ToError()) return error; - Socket *accept_socket; + Socket *accept_socket = nullptr; std::future<Status> accept_status = std::async( std::launch::async, [&] { return listen_socket.Accept(accept_socket); }); diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h index 35e86c202b5b..4e59bd5ec8be 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h @@ -82,10 +82,6 @@ class ProcessGDBRemote; class GDBRemoteCommunication : public Communication { public: - enum { - eBroadcastBitRunPacketSent = kLoUserBroadcastBit, - }; - enum class PacketType { Invalid = 0, Standard, Notify }; enum class PacketResult { @@ -120,7 +116,7 @@ public: bool m_timeout_modified; }; - GDBRemoteCommunication(const char *comm_name, const char *listener_name); + GDBRemoteCommunication(); ~GDBRemoteCommunication() override; @@ -180,6 +176,8 @@ protected: // false if this class represents a debug session for // a single process + std::string m_bytes; + std::recursive_mutex m_bytes_mutex; CompressionType m_compression_type; PacketResult SendPacketNoLock(llvm::StringRef payload); @@ -192,11 +190,6 @@ protected: PacketResult ReadPacket(StringExtractorGDBRemote &response, Timeout<std::micro> timeout, bool sync_on_timeout); - PacketResult ReadPacketWithOutputSupport( - StringExtractorGDBRemote &response, Timeout<std::micro> timeout, - bool sync_on_timeout, - llvm::function_ref<void(llvm::StringRef)> output_callback); - PacketResult WaitForPacketNoLock(StringExtractorGDBRemote &response, Timeout<std::micro> timeout, bool sync_on_timeout); diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp index 580cdde57d80..6e47e5b3e3d1 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -12,6 +12,7 @@ #include <sys/stat.h> #include <numeric> +#include <optional> #include <sstream> #include "lldb/Core/ModuleSpec.h" @@ -55,7 +56,7 @@ llvm::raw_ostream &process_gdb_remote::operator<<(llvm::raw_ostream &os, // GDBRemoteCommunicationClient constructor GDBRemoteCommunicationClient::GDBRemoteCommunicationClient() - : GDBRemoteClientBase("gdb-remote.client", "gdb-remote.client.rx_packet"), + : GDBRemoteClientBase("gdb-remote.client"), m_supports_qProcessInfoPID(true), m_supports_qfProcessInfo(true), m_supports_qUserName(true), m_supports_qGroupName(true), @@ -181,6 +182,12 @@ bool GDBRemoteCommunicationClient::GetQXferSigInfoReadSupported() { return m_supports_qXfer_siginfo_read == eLazyBoolYes; } +bool GDBRemoteCommunicationClient::GetMultiprocessSupported() { + if (m_supports_memory_tagging == eLazyBoolCalculate) + GetRemoteQSupported(); + return m_supports_multiprocess == eLazyBoolYes; +} + uint64_t GDBRemoteCommunicationClient::GetRemoteMaxPacketSize() { if (m_max_packet_size == 0) { GetRemoteQSupported(); @@ -607,6 +614,19 @@ bool GDBRemoteCommunicationClient::GetSharedCacheInfoSupported() { return m_supports_jGetSharedCacheInfo; } +bool GDBRemoteCommunicationClient::GetDynamicLoaderProcessStateSupported() { + if (m_supports_jGetDyldProcessState == eLazyBoolCalculate) { + StringExtractorGDBRemote response; + m_supports_jGetDyldProcessState = eLazyBoolNo; + if (SendPacketAndWaitForResponse("jGetDyldProcessState", response) == + PacketResult::Success) { + if (!response.IsUnsupportedResponse()) + m_supports_jGetDyldProcessState = eLazyBoolYes; + } + } + return m_supports_jGetDyldProcessState; +} + bool GDBRemoteCommunicationClient::GetMemoryTaggingSupported() { if (m_supports_memory_tagging == eLazyBoolCalculate) { GetRemoteQSupported(); @@ -740,108 +760,69 @@ lldb::pid_t GDBRemoteCommunicationClient::GetCurrentProcessID(bool allow_lazy) { return LLDB_INVALID_PROCESS_ID; } -bool GDBRemoteCommunicationClient::GetLaunchSuccess(std::string &error_str) { - error_str.clear(); - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse("qLaunchSuccess", response) == - PacketResult::Success) { - if (response.IsOKResponse()) - return true; - // GDB does not implement qLaunchSuccess -- but if we used vRun, - // then we already received a successful launch indication via stop - // reason. - if (response.IsUnsupportedResponse() && m_supports_vRun) - return true; - if (response.GetChar() == 'E') { - // A string the describes what failed when launching... - error_str = std::string(response.GetStringRef().substr(1)); - } else { - error_str.assign("unknown error occurred launching process"); +llvm::Error GDBRemoteCommunicationClient::LaunchProcess(const Args &args) { + if (!args.GetArgumentAtIndex(0)) + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "Nothing to launch"); + // try vRun first + if (m_supports_vRun) { + StreamString packet; + packet.PutCString("vRun"); + for (const Args::ArgEntry &arg : args) { + packet.PutChar(';'); + packet.PutStringAsRawHex8(arg.ref()); } - } else { - error_str.assign("timed out waiting for app to launch"); - } - return false; -} -int GDBRemoteCommunicationClient::SendArgumentsPacket( - const ProcessLaunchInfo &launch_info) { - // Since we don't get the send argv0 separate from the executable path, we - // need to make sure to use the actual executable path found in the - // launch_info... - std::vector<const char *> argv; - FileSpec exe_file = launch_info.GetExecutableFile(); - std::string exe_path; - const char *arg = nullptr; - const Args &launch_args = launch_info.GetArguments(); - if (exe_file) - exe_path = exe_file.GetPath(false); - else { - arg = launch_args.GetArgumentAtIndex(0); - if (arg) - exe_path = arg; - } - if (!exe_path.empty()) { - argv.push_back(exe_path.c_str()); - for (uint32_t i = 1; (arg = launch_args.GetArgumentAtIndex(i)) != nullptr; - ++i) { - if (arg) - argv.push_back(arg); - } - } - if (!argv.empty()) { - // try vRun first - if (m_supports_vRun) { - StreamString packet; - packet.PutCString("vRun"); - for (const char *arg : argv) { - packet.PutChar(';'); - packet.PutBytesAsRawHex8(arg, strlen(arg)); - } + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse(packet.GetString(), response) != + PacketResult::Success) + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "Sending vRun packet failed"); - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(packet.GetString(), response) != - PacketResult::Success) - return -1; + if (response.IsErrorResponse()) + return response.GetStatus().ToError(); - if (response.IsErrorResponse()) { - uint8_t error = response.GetError(); - if (error) - return error; - return -1; - } - // vRun replies with a stop reason packet - // FIXME: right now we just discard the packet and LLDB queries - // for stop reason again - if (!response.IsUnsupportedResponse()) - return 0; + // vRun replies with a stop reason packet + // FIXME: right now we just discard the packet and LLDB queries + // for stop reason again + if (!response.IsUnsupportedResponse()) + return llvm::Error::success(); - m_supports_vRun = false; - } + m_supports_vRun = false; + } - // fallback to A - StreamString packet; - packet.PutChar('A'); - for (size_t i = 0, n = argv.size(); i < n; ++i) { - arg = argv[i]; - const int arg_len = strlen(arg); - if (i > 0) - packet.PutChar(','); - packet.Printf("%i,%i,", arg_len * 2, (int)i); - packet.PutBytesAsRawHex8(arg, arg_len); - } + // fallback to A + StreamString packet; + packet.PutChar('A'); + llvm::ListSeparator LS(","); + for (const auto &arg : llvm::enumerate(args)) { + packet << LS; + packet.Format("{0},{1},", arg.value().ref().size() * 2, arg.index()); + packet.PutStringAsRawHex8(arg.value().ref()); + } - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(packet.GetString(), response) == - PacketResult::Success) { - if (response.IsOKResponse()) - return 0; - uint8_t error = response.GetError(); - if (error) - return error; - } + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse(packet.GetString(), response) != + PacketResult::Success) { + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "Sending A packet failed"); } - return -1; + if (!response.IsOKResponse()) + return response.GetStatus().ToError(); + + if (SendPacketAndWaitForResponse("qLaunchSuccess", response) != + PacketResult::Success) { + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "Sending qLaunchSuccess packet failed"); + } + if (response.IsOKResponse()) + return llvm::Error::success(); + if (response.GetChar() == 'E') { + return llvm::createStringError(llvm::inconvertibleErrorCode(), + response.GetStringRef().substr(1)); + } + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "unknown error occurred launching process"); } int GDBRemoteCommunicationClient::SendEnvironment(const Environment &env) { @@ -975,21 +956,21 @@ llvm::VersionTuple GDBRemoteCommunicationClient::GetMacCatalystVersion() { return m_maccatalyst_version; } -llvm::Optional<std::string> GDBRemoteCommunicationClient::GetOSBuildString() { +std::optional<std::string> GDBRemoteCommunicationClient::GetOSBuildString() { if (GetHostInfo()) { if (!m_os_build.empty()) return m_os_build; } - return llvm::None; + return std::nullopt; } -llvm::Optional<std::string> +std::optional<std::string> GDBRemoteCommunicationClient::GetOSKernelDescription() { if (GetHostInfo()) { if (!m_os_kernel.empty()) return m_os_kernel; } - return llvm::None; + return std::nullopt; } bool GDBRemoteCommunicationClient::GetHostname(std::string &s) { @@ -1033,6 +1014,13 @@ bool GDBRemoteCommunicationClient::GetProcessStandaloneBinary( return true; } +std::vector<addr_t> +GDBRemoteCommunicationClient::GetProcessStandaloneBinaries() { + if (m_qProcessInfo_is_valid == eLazyBoolCalculate) + GetCurrentProcessInfo(); + return m_binary_addresses; +} + bool GDBRemoteCommunicationClient::GetGDBServerVersion() { if (m_qGDBServerVersion_is_valid == eLazyBoolCalculate) { m_gdb_server_name.clear(); @@ -1507,7 +1495,7 @@ Status GDBRemoteCommunicationClient::Detach(bool keep_stopped, } } - if (m_supports_multiprocess) { + if (GetMultiprocessSupported()) { // Some servers (e.g. qemu) require specifying the PID even if only a single // process is running. if (pid == LLDB_INVALID_PROCESS_ID) @@ -1553,8 +1541,14 @@ Status GDBRemoteCommunicationClient::GetMemoryRegionInfo( if (!value.getAsInteger(16, addr_value)) region_info.GetRange().SetRangeBase(addr_value); } else if (name.equals("size")) { - if (!value.getAsInteger(16, addr_value)) + if (!value.getAsInteger(16, addr_value)) { region_info.GetRange().SetByteSize(addr_value); + if (region_info.GetRange().GetRangeEnd() < + region_info.GetRange().GetRangeBase()) { + // Range size overflowed, truncate it. + region_info.GetRange().SetRangeEnd(LLDB_INVALID_ADDRESS); + } + } } else if (name.equals("permissions") && region_info.GetRange().IsValid()) { saw_permissions = true; @@ -2192,6 +2186,15 @@ bool GDBRemoteCommunicationClient::GetCurrentProcessInfo(bool allow_lazy) { m_process_standalone_value_is_offset = false; ++num_keys_decoded; } + } else if (name.equals("binary-addresses")) { + m_binary_addresses.clear(); + ++num_keys_decoded; + for (llvm::StringRef x : llvm::split(value, ',')) { + addr_t vmaddr; + x.consume_front("0x"); + if (llvm::to_integer(x, vmaddr, 16)) + m_binary_addresses.push_back(vmaddr); + } } } if (num_keys_decoded > 0) @@ -2426,6 +2429,8 @@ static void MakeSpeedTestPacket(StreamString &packet, uint32_t send_size, duration<float> calculate_standard_deviation(const std::vector<duration<float>> &v) { + if (v.size() == 0) + return duration<float>::zero(); using Dur = duration<float>; Dur sum = std::accumulate(std::begin(v), std::end(v), Dur()); Dur mean = sum / v.size(); @@ -2443,7 +2448,7 @@ void GDBRemoteCommunicationClient::TestPacketSpeed(const uint32_t num_packets, uint32_t max_recv, uint64_t recv_amount, bool json, Stream &strm) { - uint32_t i; + if (SendSpeedTestPacket(0, 0)) { StreamString packet; if (json) @@ -2468,7 +2473,7 @@ void GDBRemoteCommunicationClient::TestPacketSpeed(const uint32_t num_packets, packet_times.clear(); // Test how long it takes to send 'num_packets' packets const auto start_time = steady_clock::now(); - for (i = 0; i < num_packets; ++i) { + for (uint32_t i = 0; i < num_packets; ++i) { const auto packet_start_time = steady_clock::now(); StringExtractorGDBRemote response; SendPacketAndWaitForResponse(packet.GetString(), response); @@ -2480,7 +2485,8 @@ void GDBRemoteCommunicationClient::TestPacketSpeed(const uint32_t num_packets, float packets_per_second = ((float)num_packets) / duration<float>(total_time).count(); - auto average_per_packet = total_time / num_packets; + auto average_per_packet = num_packets > 0 ? total_time / num_packets + : duration<float>::zero(); const duration<float> standard_deviation = calculate_standard_deviation(packet_times); if (json) { @@ -2536,7 +2542,9 @@ void GDBRemoteCommunicationClient::TestPacketSpeed(const uint32_t num_packets, (1024.0 * 1024.0); float packets_per_second = ((float)packet_count) / duration<float>(total_time).count(); - const auto average_per_packet = total_time / packet_count; + const auto average_per_packet = packet_count > 0 + ? total_time / packet_count + : duration<float>::zero(); if (json) { strm.Format("{0}\n {{\"send_size\" : {1,6}, \"recv_size\" : " @@ -2680,10 +2688,8 @@ bool GDBRemoteCommunicationClient::KillSpawnedProcess(lldb::pid_t pid) { return false; } -llvm::Optional<PidTid> -GDBRemoteCommunicationClient::SendSetCurrentThreadPacket(uint64_t tid, - uint64_t pid, - char op) { +std::optional<PidTid> GDBRemoteCommunicationClient::SendSetCurrentThreadPacket( + uint64_t tid, uint64_t pid, char op) { lldb_private::StreamString packet; packet.PutChar('H'); packet.PutChar(op); @@ -2712,7 +2718,7 @@ GDBRemoteCommunicationClient::SendSetCurrentThreadPacket(uint64_t tid, if (response.IsUnsupportedResponse() && IsConnected()) return {{1, 1}}; } - return llvm::None; + return std::nullopt; } bool GDBRemoteCommunicationClient::SetCurrentThread(uint64_t tid, @@ -2721,7 +2727,7 @@ bool GDBRemoteCommunicationClient::SetCurrentThread(uint64_t tid, (m_curr_pid == pid || LLDB_INVALID_PROCESS_ID == pid)) return true; - llvm::Optional<PidTid> ret = SendSetCurrentThreadPacket(tid, pid, 'g'); + std::optional<PidTid> ret = SendSetCurrentThreadPacket(tid, pid, 'g'); if (ret) { if (ret->pid != LLDB_INVALID_PROCESS_ID) m_curr_pid = ret->pid; @@ -2736,7 +2742,7 @@ bool GDBRemoteCommunicationClient::SetCurrentThreadForRun(uint64_t tid, (m_curr_pid_run == pid || LLDB_INVALID_PROCESS_ID == pid)) return true; - llvm::Optional<PidTid> ret = SendSetCurrentThreadPacket(tid, pid, 'c'); + std::optional<PidTid> ret = SendSetCurrentThreadPacket(tid, pid, 'c'); if (ret) { if (ret->pid != LLDB_INVALID_PROCESS_ID) m_curr_pid_run = ret->pid; @@ -3080,7 +3086,7 @@ bool GDBRemoteCommunicationClient::CloseFile(lldb::user_id_t fd, return false; } -llvm::Optional<GDBRemoteFStatData> +std::optional<GDBRemoteFStatData> GDBRemoteCommunicationClient::FStat(lldb::user_id_t fd) { lldb_private::StreamString stream; stream.Printf("vFile:fstat:%" PRIx64, fd); @@ -3088,29 +3094,29 @@ GDBRemoteCommunicationClient::FStat(lldb::user_id_t fd) { if (SendPacketAndWaitForResponse(stream.GetString(), response) == PacketResult::Success) { if (response.GetChar() != 'F') - return llvm::None; + return std::nullopt; int64_t size = response.GetS64(-1, 16); if (size > 0 && response.GetChar() == ';') { std::string buffer; if (response.GetEscapedBinaryData(buffer)) { GDBRemoteFStatData out; if (buffer.size() != sizeof(out)) - return llvm::None; + return std::nullopt; memcpy(&out, buffer.data(), sizeof(out)); return out; } } } - return llvm::None; + return std::nullopt; } -llvm::Optional<GDBRemoteFStatData> +std::optional<GDBRemoteFStatData> GDBRemoteCommunicationClient::Stat(const lldb_private::FileSpec &file_spec) { Status error; lldb::user_id_t fd = OpenFile(file_spec, File::eOpenOptionReadOnly, 0, error); if (fd == UINT64_MAX) - return llvm::None; - llvm::Optional<GDBRemoteFStatData> st = FStat(fd); + return std::nullopt; + std::optional<GDBRemoteFStatData> st = FStat(fd); CloseFile(fd, error); return st; } @@ -3138,7 +3144,7 @@ lldb::user_id_t GDBRemoteCommunicationClient::GetFileSize( } // Fallback to fstat. - llvm::Optional<GDBRemoteFStatData> st = Stat(file_spec); + std::optional<GDBRemoteFStatData> st = Stat(file_spec); return st ? st->gdb_st_size : UINT64_MAX; } @@ -3209,7 +3215,7 @@ GDBRemoteCommunicationClient::GetFilePermissions(const FileSpec &file_spec, } // Fallback to fstat. - if (llvm::Optional<GDBRemoteFStatData> st = Stat(file_spec)) { + if (std::optional<GDBRemoteFStatData> st = Stat(file_spec)) { file_permissions = st->gdb_st_mode & (S_IRWXU | S_IRWXG | S_IRWXO); return Status(); } @@ -3712,13 +3718,13 @@ GDBRemoteCommunicationClient::SendTraceGetBinaryData( escaped_packet.GetData()); } -llvm::Optional<QOffsets> GDBRemoteCommunicationClient::GetQOffsets() { +std::optional<QOffsets> GDBRemoteCommunicationClient::GetQOffsets() { StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse("qOffsets", response) != PacketResult::Success) - return llvm::None; + return std::nullopt; if (!response.IsNormalResponse()) - return llvm::None; + return std::nullopt; QOffsets result; llvm::StringRef ref = response.GetStringRef(); @@ -3733,9 +3739,9 @@ llvm::Optional<QOffsets> GDBRemoteCommunicationClient::GetQOffsets() { if (ref.consume_front("Text=")) { result.segments = false; if (!GetOffset()) - return llvm::None; + return std::nullopt; if (!ref.consume_front(";Data=") || !GetOffset()) - return llvm::None; + return std::nullopt; if (ref.empty()) return result; if (ref.consume_front(";Bss=") && GetOffset() && ref.empty()) @@ -3743,13 +3749,13 @@ llvm::Optional<QOffsets> GDBRemoteCommunicationClient::GetQOffsets() { } else if (ref.consume_front("TextSeg=")) { result.segments = true; if (!GetOffset()) - return llvm::None; + return std::nullopt; if (ref.empty()) return result; if (ref.consume_front(";DataSeg=") && GetOffset() && ref.empty()) return result; } - return llvm::None; + return std::nullopt; } bool GDBRemoteCommunicationClient::GetModuleInfo( @@ -3818,46 +3824,46 @@ bool GDBRemoteCommunicationClient::GetModuleInfo( return true; } -static llvm::Optional<ModuleSpec> +static std::optional<ModuleSpec> ParseModuleSpec(StructuredData::Dictionary *dict) { ModuleSpec result; if (!dict) - return llvm::None; + return std::nullopt; llvm::StringRef string; uint64_t integer; if (!dict->GetValueForKeyAsString("uuid", string)) - return llvm::None; + return std::nullopt; if (!result.GetUUID().SetFromStringRef(string)) - return llvm::None; + return std::nullopt; if (!dict->GetValueForKeyAsInteger("file_offset", integer)) - return llvm::None; + return std::nullopt; result.SetObjectOffset(integer); if (!dict->GetValueForKeyAsInteger("file_size", integer)) - return llvm::None; + return std::nullopt; result.SetObjectSize(integer); if (!dict->GetValueForKeyAsString("triple", string)) - return llvm::None; + return std::nullopt; result.GetArchitecture().SetTriple(string); if (!dict->GetValueForKeyAsString("file_path", string)) - return llvm::None; + return std::nullopt; result.GetFileSpec() = FileSpec(string, result.GetArchitecture().GetTriple()); return result; } -llvm::Optional<std::vector<ModuleSpec>> +std::optional<std::vector<ModuleSpec>> GDBRemoteCommunicationClient::GetModulesInfo( llvm::ArrayRef<FileSpec> module_file_specs, const llvm::Triple &triple) { namespace json = llvm::json; if (!m_supports_jModulesInfo) - return llvm::None; + return std::nullopt; json::Array module_array; for (const FileSpec &module_file_spec : module_file_specs) { @@ -3880,25 +3886,25 @@ GDBRemoteCommunicationClient::GetModulesInfo( if (SendPacketAndWaitForResponse(payload.GetString(), response) != PacketResult::Success || response.IsErrorResponse()) - return llvm::None; + return std::nullopt; if (response.IsUnsupportedResponse()) { m_supports_jModulesInfo = false; - return llvm::None; + return std::nullopt; } StructuredData::ObjectSP response_object_sp = StructuredData::ParseJSON(std::string(response.GetStringRef())); if (!response_object_sp) - return llvm::None; + return std::nullopt; StructuredData::Array *response_array = response_object_sp->GetAsArray(); if (!response_array) - return llvm::None; + return std::nullopt; std::vector<ModuleSpec> result; for (size_t i = 0; i < response_array->GetSize(); ++i) { - if (llvm::Optional<ModuleSpec> module_spec = ParseModuleSpec( + if (std::optional<ModuleSpec> module_spec = ParseModuleSpec( response_array->GetItemAtIndex(i)->GetAsDictionary())) result.push_back(*module_spec); } @@ -3948,7 +3954,7 @@ GDBRemoteCommunicationClient::ReadExtFeature(llvm::StringRef object, // last chunk case ('l'): active = false; - LLVM_FALLTHROUGH; + [[fallthrough]]; // more chunks case ('m'): diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h index 3d838d6d8074..45ea2f2589c1 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h @@ -14,6 +14,7 @@ #include <chrono> #include <map> #include <mutex> +#include <optional> #include <string> #include <vector> @@ -23,11 +24,11 @@ #include "lldb/Utility/ProcessInfo.h" #include "lldb/Utility/StructuredData.h" #include "lldb/Utility/TraceGDBRemotePackets.h" +#include "lldb/Utility/UUID.h" #if defined(_WIN32) #include "lldb/Host/windows/PosixApi.h" #endif -#include "llvm/ADT/Optional.h" #include "llvm/Support/VersionTuple.h" namespace lldb_private { @@ -79,8 +80,6 @@ public: lldb::pid_t GetCurrentProcessID(bool allow_lazy = true); - bool GetLaunchSuccess(std::string &error_str); - bool LaunchGDBServer(const char *remote_accept_hostname, lldb::pid_t &pid, uint16_t &port, std::string &socket_name); @@ -89,19 +88,11 @@ public: bool KillSpawnedProcess(lldb::pid_t pid); - /// Sends a GDB remote protocol 'A' packet that delivers program - /// arguments to the remote server. - /// - /// \param[in] launch_info - /// A NULL terminated array of const C strings to use as the - /// arguments. + /// Launch the process using the provided arguments. /// - /// \return - /// Zero if the response was "OK", a positive value if the - /// the response was "Exx" where xx are two hex digits, or - /// -1 if the call is unsupported or any other unexpected - /// response was received. - int SendArgumentsPacket(const ProcessLaunchInfo &launch_info); + /// \param[in] args + /// A list of program arguments. The first entry is the program being run. + llvm::Error LaunchProcess(const Args &args); /// Sends a "QEnvironment:NAME=VALUE" packet that will build up the /// environment that will get used when launching an application @@ -220,6 +211,8 @@ public: bool GetProcessStandaloneBinary(UUID &uuid, lldb::addr_t &value, bool &value_is_offset); + std::vector<lldb::addr_t> GetProcessStandaloneBinaries(); + void GetRemoteQSupported(); bool GetVContSupported(char flavor); @@ -242,9 +235,9 @@ public: llvm::VersionTuple GetMacCatalystVersion(); - llvm::Optional<std::string> GetOSBuildString(); + std::optional<std::string> GetOSBuildString(); - llvm::Optional<std::string> GetOSKernelDescription(); + std::optional<std::string> GetOSKernelDescription(); ArchSpec GetSystemArchitecture(); @@ -306,8 +299,8 @@ public: // and response times. bool SendSpeedTestPacket(uint32_t send_size, uint32_t recv_size); - llvm::Optional<PidTid> - SendSetCurrentThreadPacket(uint64_t tid, uint64_t pid, char op); + std::optional<PidTid> SendSetCurrentThreadPacket(uint64_t tid, uint64_t pid, + char op); bool SetCurrentThread(uint64_t tid, lldb::pid_t pid = LLDB_INVALID_PROCESS_ID); @@ -337,6 +330,8 @@ public: bool GetQXferSigInfoReadSupported(); + bool GetMultiprocessSupported(); + LazyBool SupportsAllocDeallocMemory() // const { // Uncomment this to have lldb pretend the debug server doesn't respond to @@ -356,11 +351,11 @@ public: bool CloseFile(lldb::user_id_t fd, Status &error); - llvm::Optional<GDBRemoteFStatData> FStat(lldb::user_id_t fd); + std::optional<GDBRemoteFStatData> FStat(lldb::user_id_t fd); // NB: this is just a convenience wrapper over open() + fstat(). It does not // work if the file cannot be opened. - llvm::Optional<GDBRemoteFStatData> Stat(const FileSpec &file_spec); + std::optional<GDBRemoteFStatData> Stat(const FileSpec &file_spec); lldb::user_id_t GetFileSize(const FileSpec &file_spec); @@ -434,6 +429,8 @@ public: bool GetSharedCacheInfoSupported(); + bool GetDynamicLoaderProcessStateSupported(); + bool GetMemoryTaggingSupported(); bool UsesNativeSignals(); @@ -447,12 +444,12 @@ public: /// Use qOffsets to query the offset used when relocating the target /// executable. If successful, the returned structure will contain at least /// one value in the offsets field. - llvm::Optional<QOffsets> GetQOffsets(); + std::optional<QOffsets> GetQOffsets(); bool GetModuleInfo(const FileSpec &module_file_spec, const ArchSpec &arch_spec, ModuleSpec &module_spec); - llvm::Optional<std::vector<ModuleSpec>> + std::optional<std::vector<ModuleSpec>> GetModulesInfo(llvm::ArrayRef<FileSpec> module_file_specs, const llvm::Triple &triple); @@ -558,6 +555,7 @@ protected: LazyBool m_supports_jThreadExtendedInfo = eLazyBoolCalculate; LazyBool m_supports_jLoadedDynamicLibrariesInfos = eLazyBoolCalculate; LazyBool m_supports_jGetSharedCacheInfo = eLazyBoolCalculate; + LazyBool m_supports_jGetDyldProcessState = eLazyBoolCalculate; LazyBool m_supports_QPassSignals = eLazyBoolCalculate; LazyBool m_supports_error_string_reply = eLazyBoolCalculate; LazyBool m_supports_multiprocess = eLazyBoolCalculate; @@ -593,6 +591,7 @@ protected: UUID m_process_standalone_uuid; lldb::addr_t m_process_standalone_value = LLDB_INVALID_ADDRESS; bool m_process_standalone_value_is_offset = false; + std::vector<lldb::addr_t> m_binary_addresses; llvm::VersionTuple m_os_version; llvm::VersionTuple m_maccatalyst_version; std::string m_os_build; diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp index d92c97e81659..a3477caea7d8 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp @@ -39,8 +39,6 @@ void GDBRemoteCommunicationHistory::AddPacket(char packet_char, m_packets[idx].bytes_transmitted = bytes_transmitted; m_packets[idx].packet_idx = m_total_packet_count; m_packets[idx].tid = llvm::get_threadid(); - if (m_recorder) - m_recorder->Record(m_packets[idx]); } void GDBRemoteCommunicationHistory::AddPacket(const std::string &src, @@ -57,8 +55,6 @@ void GDBRemoteCommunicationHistory::AddPacket(const std::string &src, m_packets[idx].bytes_transmitted = bytes_transmitted; m_packets[idx].packet_idx = m_total_packet_count; m_packets[idx].tid = llvm::get_threadid(); - if (m_recorder) - m_recorder->Record(m_packets[idx]); } void GDBRemoteCommunicationHistory::Dump(Stream &strm) const { diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.h b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.h index eda464a758e4..2fbc621a90e7 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.h @@ -13,23 +13,16 @@ #include <vector> #include "lldb/Utility/GDBRemote.h" -#include "lldb/Utility/Reproducer.h" #include "lldb/lldb-public.h" -#include "llvm/Support/YAMLTraits.h" #include "llvm/Support/raw_ostream.h" namespace lldb_private { -namespace repro { -class PacketRecorder; -} namespace process_gdb_remote { /// The history keeps a circular buffer of GDB remote packets. The history is /// used for logging and replaying GDB remote packets. class GDBRemoteCommunicationHistory { public: - friend llvm::yaml::MappingTraits<GDBRemoteCommunicationHistory>; - GDBRemoteCommunicationHistory(uint32_t size = 0); ~GDBRemoteCommunicationHistory(); @@ -45,8 +38,6 @@ public: void Dump(Log *log) const; bool DidDumpToLog() const { return m_dumped_to_log; } - void SetRecorder(repro::PacketRecorder *recorder) { m_recorder = recorder; } - private: uint32_t GetFirstSavedPacketIndex() const { if (m_total_packet_count < m_packets.size()) @@ -77,7 +68,6 @@ private: uint32_t m_curr_idx = 0; uint32_t m_total_packet_count = 0; mutable bool m_dumped_to_log = false; - repro::PacketRecorder *m_recorder = nullptr; }; } // namespace process_gdb_remote diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp index 7d21b0ff01da..e7a292f858a8 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp @@ -24,9 +24,8 @@ using namespace lldb_private; using namespace lldb_private::process_gdb_remote; using namespace llvm; -GDBRemoteCommunicationServer::GDBRemoteCommunicationServer( - const char *comm_name, const char *listener_name) - : GDBRemoteCommunication(comm_name, listener_name), m_exit_now(false) { +GDBRemoteCommunicationServer::GDBRemoteCommunicationServer() + : GDBRemoteCommunication(), m_exit_now(false) { RegisterPacketHandler( StringExtractorGDBRemote::eServerPacketType_QEnableErrorStrings, [this](StringExtractorGDBRemote packet, Status &error, bool &interrupt, diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h index 5de344061ec9..ccbcd0ac5bf5 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h @@ -31,8 +31,7 @@ public: std::function<PacketResult(StringExtractorGDBRemote &packet, Status &error, bool &interrupt, bool &quit)>; - GDBRemoteCommunicationServer(const char *comm_name, - const char *listener_name); + GDBRemoteCommunicationServer(); ~GDBRemoteCommunicationServer() override; diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp index 2a58f2028386..f71240672bcc 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp @@ -16,6 +16,7 @@ #include <chrono> #include <cstring> +#include <optional> #include "lldb/Core/ModuleSpec.h" #include "lldb/Host/Config.h" @@ -57,11 +58,9 @@ const static uint32_t g_default_packet_timeout_sec = 0; // not specified #endif // GDBRemoteCommunicationServerCommon constructor -GDBRemoteCommunicationServerCommon::GDBRemoteCommunicationServerCommon( - const char *comm_name, const char *listener_name) - : GDBRemoteCommunicationServer(comm_name, listener_name), - m_process_launch_info(), m_process_launch_error(), m_proc_infos(), - m_proc_infos_index(0) { +GDBRemoteCommunicationServerCommon::GDBRemoteCommunicationServerCommon() + : GDBRemoteCommunicationServer(), m_process_launch_info(), + m_process_launch_error(), m_proc_infos(), m_proc_infos_index(0) { RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_A, &GDBRemoteCommunicationServerCommon::Handle_A); RegisterMemberFunctionHandler( @@ -268,12 +267,12 @@ GDBRemoteCommunicationServerCommon::Handle_qHostInfo( } #endif - if (llvm::Optional<std::string> s = HostInfo::GetOSBuildString()) { + if (std::optional<std::string> s = HostInfo::GetOSBuildString()) { response.PutCString("os_build:"); response.PutStringAsRawHex8(*s); response.PutChar(';'); } - if (llvm::Optional<std::string> s = HostInfo::GetOSKernelDescription()) { + if (std::optional<std::string> s = HostInfo::GetOSKernelDescription()) { response.PutCString("os_kernel:"); response.PutStringAsRawHex8(*s); response.PutChar(';'); @@ -304,7 +303,7 @@ GDBRemoteCommunicationServerCommon::Handle_qHostInfo( response.PutChar(';'); } #endif // #if defined(__APPLE__) - + // coverity[unsigned_compare] if (g_default_packet_timeout_sec > 0) response.Printf("default_packet_timeout:%u;", g_default_packet_timeout_sec); @@ -434,7 +433,7 @@ GDBRemoteCommunicationServerCommon::Handle_qUserName( packet.SetFilePos(::strlen("qUserName:")); uint32_t uid = packet.GetU32(UINT32_MAX); if (uid != UINT32_MAX) { - if (llvm::Optional<llvm::StringRef> name = + if (std::optional<llvm::StringRef> name = HostInfo::GetUserIDResolver().GetUserName(uid)) { StreamString response; response.PutStringAsRawHex8(*name); @@ -454,7 +453,7 @@ GDBRemoteCommunicationServerCommon::Handle_qGroupName( packet.SetFilePos(::strlen("qGroupName:")); uint32_t gid = packet.GetU32(UINT32_MAX); if (gid != UINT32_MAX) { - if (llvm::Optional<llvm::StringRef> name = + if (std::optional<llvm::StringRef> name = HostInfo::GetUserIDResolver().GetGroupName(gid)) { StreamString response; response.PutStringAsRawHex8(*name); @@ -774,7 +773,7 @@ template <typename T, typename U> static void fill_clamp(T &dest, U src, typename T::value_type fallback) { static_assert(std::is_unsigned<typename T::value_type>::value, "Destination type must be unsigned."); - using UU = typename std::make_unsigned<U>::type; + using UU = std::make_unsigned_t<U>; constexpr auto T_max = std::numeric_limits<typename T::value_type>::max(); dest = src >= 0 && static_cast<UU>(src) <= T_max ? src : fallback; } @@ -1138,7 +1137,8 @@ GDBRemoteCommunicationServerCommon::Handle_qModuleInfo( response.PutChar(';'); response.PutCString("file_path:"); - response.PutStringAsRawHex8(matched_module_spec.GetFileSpec().GetCString()); + response.PutStringAsRawHex8( + matched_module_spec.GetFileSpec().GetPath().c_str()); response.PutChar(';'); response.PutCString("file_offset:"); response.PutHex64(file_offset); @@ -1213,7 +1213,7 @@ void GDBRemoteCommunicationServerCommon::CreateProcessInfoResponse( proc_info.GetUserID(), proc_info.GetGroupID(), proc_info.GetEffectiveUserID(), proc_info.GetEffectiveGroupID()); response.PutCString("name:"); - response.PutStringAsRawHex8(proc_info.GetExecutableFile().GetCString()); + response.PutStringAsRawHex8(proc_info.GetExecutableFile().GetPath().c_str()); response.PutChar(';'); response.PutCString("args:"); diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h index f696cb5c61c6..b4f1eb3e61c4 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h @@ -25,8 +25,7 @@ class ProcessGDBRemote; class GDBRemoteCommunicationServerCommon : public GDBRemoteCommunicationServer { public: - GDBRemoteCommunicationServerCommon(const char *comm_name, - const char *listener_name); + GDBRemoteCommunicationServerCommon(); ~GDBRemoteCommunicationServerCommon() override; diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp index 5804c13fe7b6..921c149b9762 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp @@ -10,10 +10,10 @@ #include "lldb/Host/Config.h" - #include <chrono> #include <cstring> #include <limits> +#include <optional> #include <thread> #include "GDBRemoteCommunicationServerLLGS.h" @@ -70,11 +70,9 @@ enum GDBRemoteServerError { // GDBRemoteCommunicationServerLLGS constructor GDBRemoteCommunicationServerLLGS::GDBRemoteCommunicationServerLLGS( MainLoop &mainloop, const NativeProcessProtocol::Factory &process_factory) - : GDBRemoteCommunicationServerCommon("gdb-remote.server", - "gdb-remote.server.rx_packet"), - m_mainloop(mainloop), m_process_factory(process_factory), - m_current_process(nullptr), m_continue_process(nullptr), - m_stdio_communication("process.stdio") { + : GDBRemoteCommunicationServerCommon(), m_mainloop(mainloop), + m_process_factory(process_factory), m_current_process(nullptr), + m_continue_process(nullptr), m_stdio_communication() { RegisterPacketHandlers(); } @@ -641,7 +639,7 @@ static void WriteRegisterValueInHexFixedWidth( } } -static llvm::Optional<json::Object> +static std::optional<json::Object> GetRegistersAsJSON(NativeThreadProtocol &thread) { Log *log = GetLog(LLDBLog::Thread); @@ -657,7 +655,7 @@ GetRegistersAsJSON(NativeThreadProtocol &thread) { reg_ctx.GetExpeditedRegisters(ExpeditedRegs::Minimal); #endif if (expedited_regs.empty()) - return llvm::None; + return std::nullopt; for (auto ®_num : expedited_regs) { const RegisterInfo *const reg_info_p = @@ -755,7 +753,7 @@ GetJSONThreadsInfo(NativeProcessProtocol &process, bool abridged) { json::Object thread_obj; if (!abridged) { - if (llvm::Optional<json::Object> registers = GetRegistersAsJSON(thread)) + if (std::optional<json::Object> registers = GetRegistersAsJSON(thread)) thread_obj.try_emplace("registers", std::move(*registers)); } @@ -1503,7 +1501,7 @@ GDBRemoteCommunicationServerLLGS::Handle_qGetWorkingDir( FileSpec working_dir{m_process_launch_info.GetWorkingDirectory()}; if (working_dir) { StreamString response; - response.PutStringAsRawHex8(working_dir.GetCString()); + response.PutStringAsRawHex8(working_dir.GetPath().c_str()); return SendPacketNoLock(response.GetString()); } @@ -1733,7 +1731,7 @@ GDBRemoteCommunicationServerLLGS::Handle_vCont( if (thread_action.signal == 0) return SendIllFormedResponse( packet, "Could not parse signal in vCont packet C action"); - LLVM_FALLTHROUGH; + [[fallthrough]]; case 'c': // Continue @@ -1745,7 +1743,7 @@ GDBRemoteCommunicationServerLLGS::Handle_vCont( if (thread_action.signal == 0) return SendIllFormedResponse( packet, "Could not parse signal in vCont packet S action"); - LLVM_FALLTHROUGH; + [[fallthrough]]; case 's': // Step @@ -1762,6 +1760,7 @@ GDBRemoteCommunicationServerLLGS::Handle_vCont( break; } + // If there's no thread-id (e.g. "vCont;c"), it's "p-1.-1". lldb::pid_t pid = StringExtractorGDBRemote::AllProcesses; lldb::tid_t tid = StringExtractorGDBRemote::AllThreads; @@ -1770,7 +1769,7 @@ GDBRemoteCommunicationServerLLGS::Handle_vCont( // Consume the separator. packet.GetChar(); - auto pid_tid = packet.GetPidTid(StringExtractorGDBRemote::AllProcesses); + auto pid_tid = packet.GetPidTid(LLDB_INVALID_PROCESS_ID); if (!pid_tid) return SendIllFormedResponse(packet, "Malformed thread-id"); @@ -1784,29 +1783,35 @@ GDBRemoteCommunicationServerLLGS::Handle_vCont( packet, "'t' action not supported for individual threads"); } - if (pid == StringExtractorGDBRemote::AllProcesses) { - if (m_debugged_processes.size() > 1) - return SendIllFormedResponse( - packet, "Resuming multiple processes not supported yet"); + // If we get TID without PID, it's the current process. + if (pid == LLDB_INVALID_PROCESS_ID) { if (!m_continue_process) { - LLDB_LOG(log, "no debugged process"); + LLDB_LOG(log, "no process selected via Hc"); return SendErrorResponse(0x36); } pid = m_continue_process->GetID(); } + assert(pid != LLDB_INVALID_PROCESS_ID); if (tid == StringExtractorGDBRemote::AllThreads) tid = LLDB_INVALID_THREAD_ID; - thread_action.tid = tid; - thread_actions[pid].Append(thread_action); + if (pid == StringExtractorGDBRemote::AllProcesses) { + if (tid != LLDB_INVALID_THREAD_ID) + return SendIllFormedResponse( + packet, "vCont: p-1 is not valid with a specific tid"); + for (auto &process_it : m_debugged_processes) + thread_actions[process_it.first].Append(thread_action); + } else + thread_actions[pid].Append(thread_action); } assert(thread_actions.size() >= 1); - if (thread_actions.size() > 1) + if (thread_actions.size() > 1 && !m_non_stop) return SendIllFormedResponse( - packet, "Resuming multiple processes not supported yet"); + packet, + "Resuming multiple processes is supported in non-stop mode only"); for (std::pair<lldb::pid_t, ResumeActionList> x : thread_actions) { auto process_it = m_debugged_processes.find(x.first); @@ -2302,7 +2307,7 @@ GDBRemoteCommunicationServerLLGS::Handle_P(StringExtractorGDBRemote &packet) { // Build the reginfos response. StreamGDBRemote response; - RegisterValue reg_value(makeArrayRef(reg_bytes, reg_size), + RegisterValue reg_value(ArrayRef(reg_bytes, reg_size), m_current_process->GetArchitecture().GetByteOrder()); Status error = reg_context.WriteRegister(reg_info, reg_value); if (error.Fail()) { @@ -2434,7 +2439,7 @@ GDBRemoteCommunicationServerLLGS::Handle_I(StringExtractorGDBRemote &packet) { // remote host ConnectionStatus status; Status error; - m_stdio_communication.Write(tmp, read, status, &error); + m_stdio_communication.WriteAll(tmp, read, status, &error); if (error.Fail()) { return SendErrorResponse(0x15); } @@ -3061,19 +3066,24 @@ GDBRemoteCommunicationServerLLGS::BuildTargetXml() { StreamString response; - response.Printf("<?xml version=\"1.0\"?>"); - response.Printf("<target version=\"1.0\">"); + response.Printf("<?xml version=\"1.0\"?>\n"); + response.Printf("<target version=\"1.0\">\n"); + response.IndentMore(); - response.Printf("<architecture>%s</architecture>", + response.Indent(); + response.Printf("<architecture>%s</architecture>\n", m_current_process->GetArchitecture() .GetTriple() .getArchName() .str() .c_str()); - response.Printf("<feature>"); + response.Indent("<feature>\n"); const int registers_count = reg_context.GetUserRegisterCount(); + if (registers_count) + response.IndentMore(); + for (int reg_index = 0; reg_index < registers_count; reg_index++) { const RegisterInfo *reg_info = reg_context.GetRegisterInfoAtIndex(reg_index); @@ -3085,7 +3095,9 @@ GDBRemoteCommunicationServerLLGS::BuildTargetXml() { continue; } - response.Printf("<reg name=\"%s\" bitsize=\"%" PRIu32 "\" regnum=\"%d\" ", + response.Indent(); + response.Printf("<reg name=\"%s\" bitsize=\"%" PRIu32 + "\" regnum=\"%d\" ", reg_info->name, reg_info->byte_size * 8, reg_index); if (!reg_context.RegisterOffsetIsDynamic()) @@ -3134,11 +3146,15 @@ GDBRemoteCommunicationServerLLGS::BuildTargetXml() { response.Printf("\" "); } - response.Printf("/>"); + response.Printf("/>\n"); } - response.Printf("</feature>"); - response.Printf("</target>"); + if (registers_count) + response.IndentLess(); + + response.Indent("</feature>\n"); + response.IndentLess(); + response.Indent("</target>\n"); return MemoryBuffer::getMemBufferCopy(response.GetString(), "target.xml"); } @@ -3510,19 +3526,17 @@ GDBRemoteCommunicationServerLLGS::Handle_vRun( arg.c_str()); } - if (!argv.empty()) { - m_process_launch_info.GetExecutableFile().SetFile( - m_process_launch_info.GetArguments()[0].ref(), FileSpec::Style::native); - m_process_launch_error = LaunchProcess(); - if (m_process_launch_error.Success()) { - assert(m_current_process); - return SendStopReasonForState(*m_current_process, - m_current_process->GetState(), - /*force_synchronous=*/true); - } - LLDB_LOG(log, "failed to launch exe: {0}", m_process_launch_error); - } - return SendErrorResponse(8); + if (argv.empty()) + return SendErrorResponse(Status("No arguments")); + m_process_launch_info.GetExecutableFile().SetFile( + m_process_launch_info.GetArguments()[0].ref(), FileSpec::Style::native); + m_process_launch_error = LaunchProcess(); + if (m_process_launch_error.Fail()) + return SendErrorResponse(m_process_launch_error); + assert(m_current_process); + return SendStopReasonForState(*m_current_process, + m_current_process->GetState(), + /*force_synchronous=*/true); } GDBRemoteCommunication::PacketResult @@ -3644,7 +3658,7 @@ GDBRemoteCommunicationServerLLGS::Handle_qWatchpointSupportInfo( auto hw_debug_cap = m_current_process->GetHardwareDebugSupportInfo(); StreamGDBRemote response; - if (hw_debug_cap == llvm::None) + if (hw_debug_cap == std::nullopt) response.Printf("num:0;"); else response.Printf("num:%d;", hw_debug_cap->second); @@ -4265,7 +4279,7 @@ std::string lldb_private::process_gdb_remote::LLGSArgToURL(llvm::StringRef url_arg, bool reverse_connect) { // Try parsing the argument as URL. - if (llvm::Optional<URI> url = URI::Parse(url_arg)) { + if (std::optional<URI> url = URI::Parse(url_arg)) { if (reverse_connect) return url_arg.str(); diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp index 6f137d09fee4..bdb6480ff4d9 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp @@ -14,6 +14,7 @@ #include <csignal> #include <cstring> #include <mutex> +#include <optional> #include <sstream> #include <thread> @@ -109,8 +110,7 @@ bool GDBRemoteCommunicationServerPlatform::PortMap::empty() const { // GDBRemoteCommunicationServerPlatform constructor GDBRemoteCommunicationServerPlatform::GDBRemoteCommunicationServerPlatform( const Socket::SocketProtocol socket_protocol, const char *socket_scheme) - : GDBRemoteCommunicationServerCommon("gdb-remote.server", - "gdb-remote.server.rx_packet"), + : GDBRemoteCommunicationServerCommon(), m_socket_protocol(socket_protocol), m_socket_scheme(socket_scheme), m_spawned_pids_mutex(), m_port_map(), m_port_offset(0) { m_pending_gdb_server.pid = LLDB_INVALID_PROCESS_ID; @@ -159,7 +159,7 @@ GDBRemoteCommunicationServerPlatform::~GDBRemoteCommunicationServerPlatform() = Status GDBRemoteCommunicationServerPlatform::LaunchGDBServer( const lldb_private::Args &args, std::string hostname, lldb::pid_t &pid, - llvm::Optional<uint16_t> &port, std::string &socket_name) { + std::optional<uint16_t> &port, std::string &socket_name) { if (!port) { llvm::Expected<uint16_t> available_port = m_port_map.GetNextAvailablePort(); if (available_port) @@ -195,10 +195,10 @@ Status GDBRemoteCommunicationServerPlatform::LaunchGDBServer( #if !defined(__APPLE__) url << m_socket_scheme << "://"; #endif - uint16_t *port_ptr = port.getPointer(); + uint16_t *port_ptr = &*port; if (m_socket_protocol == Socket::ProtocolTcp) { std::string platform_uri = GetConnection()->GetURI(); - llvm::Optional<URI> parsed_uri = URI::Parse(platform_uri); + std::optional<URI> parsed_uri = URI::Parse(platform_uri); url << '[' << parsed_uri->hostname.str() << "]:" << *port; } else { socket_name = GetDomainSocketPath("gdbserver").GetPath(); @@ -237,7 +237,7 @@ GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer( packet.SetFilePos(::strlen("qLaunchGDBServer;")); llvm::StringRef name; llvm::StringRef value; - llvm::Optional<uint16_t> port; + std::optional<uint16_t> port; while (packet.GetNameColonValue(name, value)) { if (name.equals("host")) hostname = std::string(value); @@ -587,7 +587,8 @@ GDBRemoteCommunicationServerPlatform::GetDomainSocketPath(const char *prefix) { FileSpec socket_path_spec(GetDomainSocketDir()); socket_path_spec.AppendPathComponent(socket_name.c_str()); - llvm::sys::fs::createUniqueFile(socket_path_spec.GetCString(), socket_path); + llvm::sys::fs::createUniqueFile(socket_path_spec.GetPath().c_str(), + socket_path); return FileSpec(socket_path.c_str()); } diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h index 8dbd5ba942f8..1853025466cf 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h @@ -11,12 +11,12 @@ #include <map> #include <mutex> +#include <optional> #include <set> #include "GDBRemoteCommunicationServerCommon.h" #include "lldb/Host/Socket.h" -#include "llvm/ADT/Optional.h" #include "llvm/Support/Error.h" namespace lldb_private { @@ -90,7 +90,7 @@ public: // Set port if you want to use a specific port number. // Otherwise port will be set to the port that was chosen for you. Status LaunchGDBServer(const lldb_private::Args &args, std::string hostname, - lldb::pid_t &pid, llvm::Optional<uint16_t> &port, + lldb::pid_t &pid, std::optional<uint16_t> &port, std::string &socket_name); void SetPendingGdbServer(lldb::pid_t pid, uint16_t port, diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp index 7ad4f4968eac..8ea93655d6bb 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp @@ -107,12 +107,12 @@ bool GDBRemoteRegisterContext::ReadRegister(const RegisterInfo *reg_info, Status error; return value.SetFromMemoryData( - reg_info, combined_data.data(), combined_data.size(), + *reg_info, combined_data.data(), combined_data.size(), m_reg_data.GetByteOrder(), error) == combined_data.size(); } else { const bool partial_data_ok = false; Status error(value.SetValueFromData( - reg_info, m_reg_data, reg_info->byte_offset, partial_data_ok)); + *reg_info, m_reg_data, reg_info->byte_offset, partial_data_ok)); return error.Success(); } } diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index 3e1a6fb6620a..de8f2df52f23 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -60,7 +60,6 @@ #include "lldb/Utility/Args.h" #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/LLDBLog.h" -#include "lldb/Utility/Reproducer.h" #include "lldb/Utility/State.h" #include "lldb/Utility/StreamString.h" #include "lldb/Utility/Timer.h" @@ -69,6 +68,7 @@ #include <map> #include <memory> #include <mutex> +#include <optional> #include <sstream> #include <thread> @@ -85,6 +85,7 @@ #include "llvm/ADT/ScopeExit.h" #include "llvm/ADT/StringSwitch.h" +#include "llvm/Support/FormatAdapters.h" #include "llvm/Support/Threading.h" #include "llvm/Support/raw_ostream.h" @@ -166,13 +167,13 @@ public: } }; +} // namespace + static PluginProperties &GetGlobalPluginProperties() { static PluginProperties g_settings; return g_settings; } -} // namespace - // TODO Randomly assigning a port is unsafe. We should get an unused // ephemeral port from the kernel and make sure we reserve it before passing it // to debugserver. @@ -193,14 +194,13 @@ void ProcessGDBRemote::Terminate() { PluginManager::UnregisterPlugin(ProcessGDBRemote::CreateInstance); } -lldb::ProcessSP -ProcessGDBRemote::CreateInstance(lldb::TargetSP target_sp, - ListenerSP listener_sp, - const FileSpec *crash_file_path, - bool can_connect) { +lldb::ProcessSP ProcessGDBRemote::CreateInstance( + lldb::TargetSP target_sp, ListenerSP listener_sp, + const FileSpec *crash_file_path, bool can_connect) { lldb::ProcessSP process_sp; if (crash_file_path == nullptr) - process_sp = std::make_shared<ProcessGDBRemote>(target_sp, listener_sp); + process_sp = std::shared_ptr<ProcessGDBRemote>( + new ProcessGDBRemote(target_sp, listener_sp)); return process_sp; } @@ -267,12 +267,6 @@ ProcessGDBRemote::ProcessGDBRemote(lldb::TargetSP target_sp, m_async_broadcaster.SetEventName(eBroadcastBitAsyncThreadDidExit, "async thread did exit"); - if (repro::Generator *g = repro::Reproducer::Instance().GetGenerator()) { - repro::GDBRemoteProvider &provider = - g->GetOrCreate<repro::GDBRemoteProvider>(); - m_gdb_comm.SetPacketRecorder(provider.GetNewPacketRecorder()); - } - Log *log = GetLog(GDBRLog::Async); const uint32_t async_event_mask = @@ -286,14 +280,6 @@ ProcessGDBRemote::ProcessGDBRemote(lldb::TargetSP target_sp, __FUNCTION__); } - const uint32_t gdb_event_mask = Communication::eBroadcastBitReadThreadDidExit; - if (m_async_listener_sp->StartListeningForEvents( - &m_gdb_comm, gdb_event_mask) != gdb_event_mask) { - LLDB_LOGF(log, - "ProcessGDBRemote::%s failed to listen for m_gdb_comm events", - __FUNCTION__); - } - const uint64_t timeout_seconds = GetGlobalPluginProperties().GetPacketTimeout(); if (timeout_seconds > 0) @@ -519,16 +505,16 @@ void ProcessGDBRemote::BuildDynamicRegisterInfo(bool force) { AddRemoteRegisters(registers, arch_to_use); } -Status ProcessGDBRemote::WillLaunch(lldb_private::Module *module) { +Status ProcessGDBRemote::DoWillLaunch(lldb_private::Module *module) { return WillLaunchOrAttach(); } -Status ProcessGDBRemote::WillAttachToProcessWithID(lldb::pid_t pid) { +Status ProcessGDBRemote::DoWillAttachToProcessWithID(lldb::pid_t pid) { return WillLaunchOrAttach(); } -Status ProcessGDBRemote::WillAttachToProcessWithName(const char *process_name, - bool wait_for_launch) { +Status ProcessGDBRemote::DoWillAttachToProcessWithName(const char *process_name, + bool wait_for_launch) { return WillLaunchOrAttach(); } @@ -569,95 +555,6 @@ Status ProcessGDBRemote::DoConnectRemote(llvm::StringRef remote_url) { } } - // The remote stub may know about the "main binary" in - // the context of a firmware debug session, and can - // give us a UUID and an address/slide of where the - // binary is loaded in memory. - UUID standalone_uuid; - addr_t standalone_value; - bool standalone_value_is_offset; - if (m_gdb_comm.GetProcessStandaloneBinary( - standalone_uuid, standalone_value, standalone_value_is_offset)) { - ModuleSP module_sp; - - if (standalone_uuid.IsValid()) { - ModuleSpec module_spec; - module_spec.GetUUID() = standalone_uuid; - - // Look up UUID in global module cache before attempting - // a more expensive search. - Status error = ModuleList::GetSharedModule(module_spec, module_sp, - nullptr, nullptr, nullptr); - - if (!module_sp) { - // Force a an external lookup, if that tool is available. - if (!module_spec.GetSymbolFileSpec()) { - Status error; - Symbols::DownloadObjectAndSymbolFile(module_spec, error, true); - } - - if (FileSystem::Instance().Exists(module_spec.GetFileSpec())) { - module_sp = std::make_shared<Module>(module_spec); - } - } - - // If we couldn't find the binary anywhere else, as a last resort, - // read it out of memory. - if (!module_sp.get() && standalone_value != LLDB_INVALID_ADDRESS && - !standalone_value_is_offset) { - char namebuf[80]; - snprintf(namebuf, sizeof(namebuf), "mem-image-0x%" PRIx64, - standalone_value); - module_sp = - ReadModuleFromMemory(FileSpec(namebuf), standalone_value); - } - - Log *log = GetLog(LLDBLog::DynamicLoader); - if (module_sp.get()) { - target.GetImages().AppendIfNeeded(module_sp, false); - - bool changed = false; - if (module_sp->GetObjectFile()) { - if (standalone_value != LLDB_INVALID_ADDRESS) { - if (log) - log->Printf("Loading binary UUID %s at %s 0x%" PRIx64, - standalone_uuid.GetAsString().c_str(), - standalone_value_is_offset ? "offset" : "address", - standalone_value); - module_sp->SetLoadAddress(target, standalone_value, - standalone_value_is_offset, changed); - } else { - // No address/offset/slide, load the binary at file address, - // offset 0. - if (log) - log->Printf("Loading binary UUID %s at file address", - standalone_uuid.GetAsString().c_str()); - const bool value_is_slide = true; - module_sp->SetLoadAddress(target, 0, value_is_slide, changed); - } - } else { - // In-memory image, load at its true address, offset 0. - if (log) - log->Printf("Loading binary UUID %s from memory", - standalone_uuid.GetAsString().c_str()); - const bool value_is_slide = true; - module_sp->SetLoadAddress(target, 0, value_is_slide, changed); - } - - ModuleList added_module; - added_module.Append(module_sp, false); - target.ModulesDidLoad(added_module); - } else { - if (log) - log->Printf("Unable to find binary with UUID %s and load it at " - "%s 0x%" PRIx64, - standalone_uuid.GetAsString().c_str(), - standalone_value_is_offset ? "offset" : "address", - standalone_value); - } - } - } - const StateType state = SetThreadStopInfo(response); if (state != eStateInvalid) { SetPrivateState(state); @@ -745,9 +642,9 @@ Status ProcessGDBRemote::DoLaunch(lldb_private::Module *exe_module, "ProcessGDBRemote::%s provided with STDIO paths via " "launch_info: stdin=%s, stdout=%s, stderr=%s", __FUNCTION__, - stdin_file_spec ? stdin_file_spec.GetCString() : "<null>", - stdout_file_spec ? stdout_file_spec.GetCString() : "<null>", - stderr_file_spec ? stderr_file_spec.GetCString() : "<null>"); + stdin_file_spec ? stdin_file_spec.GetPath().c_str() : "<null>", + stdout_file_spec ? stdout_file_spec.GetPath().c_str() : "<null>", + stderr_file_spec ? stderr_file_spec.GetPath().c_str() : "<null>"); else LLDB_LOGF(log, "ProcessGDBRemote::%s no STDIO paths given via launch_info", @@ -810,18 +707,18 @@ Status ProcessGDBRemote::DoLaunch(lldb_private::Module *exe_module, "(IsHost() is true) using secondary: stdin=%s, stdout=%s, " "stderr=%s", __FUNCTION__, - stdin_file_spec ? stdin_file_spec.GetCString() : "<null>", - stdout_file_spec ? stdout_file_spec.GetCString() : "<null>", - stderr_file_spec ? stderr_file_spec.GetCString() : "<null>"); + stdin_file_spec ? stdin_file_spec.GetPath().c_str() : "<null>", + stdout_file_spec ? stdout_file_spec.GetPath().c_str() : "<null>", + stderr_file_spec ? stderr_file_spec.GetPath().c_str() : "<null>"); } LLDB_LOGF(log, "ProcessGDBRemote::%s final STDIO paths after all " "adjustments: stdin=%s, stdout=%s, stderr=%s", __FUNCTION__, - stdin_file_spec ? stdin_file_spec.GetCString() : "<null>", - stdout_file_spec ? stdout_file_spec.GetCString() : "<null>", - stderr_file_spec ? stderr_file_spec.GetCString() : "<null>"); + stdin_file_spec ? stdin_file_spec.GetPath().c_str() : "<null>", + stdout_file_spec ? stdout_file_spec.GetPath().c_str() : "<null>", + stderr_file_spec ? stderr_file_spec.GetPath().c_str() : "<null>"); if (stdin_file_spec) m_gdb_comm.SetSTDIN(stdin_file_spec); @@ -852,17 +749,17 @@ Status ProcessGDBRemote::DoLaunch(lldb_private::Module *exe_module, GDBRemoteCommunication::ScopedTimeout timeout(m_gdb_comm, std::chrono::seconds(10)); - int arg_packet_err = m_gdb_comm.SendArgumentsPacket(launch_info); - if (arg_packet_err == 0) { - std::string error_str; - if (m_gdb_comm.GetLaunchSuccess(error_str)) { - SetID(m_gdb_comm.GetCurrentProcessID()); - } else { - error.SetErrorString(error_str.c_str()); - } + // Since we can't send argv0 separate from the executable path, we need to + // make sure to use the actual executable path found in the launch_info... + Args args = launch_info.GetArguments(); + if (FileSpec exe_file = launch_info.GetExecutableFile()) + args.ReplaceArgumentAtIndex(0, exe_file.GetPath(false)); + if (llvm::Error err = m_gdb_comm.LaunchProcess(args)) { + error.SetErrorStringWithFormatv("Cannot launch '{0}': {1}", + args.GetArgumentAtIndex(0), + llvm::fmt_consume(std::move(err))); } else { - error.SetErrorStringWithFormat("'A' packet returned an error: %i", - arg_packet_err); + SetID(m_gdb_comm.GetCurrentProcessID()); } } @@ -962,12 +859,12 @@ Status ProcessGDBRemote::ConnectToDebugserver(llvm::StringRef connect_url) { entry.c_str(), response); } }; - + PlatformSP platform_sp = GetTarget().GetPlatform(); if (platform_sp) { handle_cmds(platform_sp->GetExtraStartupCommands()); } - + // Then dispatch any process commands: handle_cmds(GetExtraStartupCommands()); @@ -996,8 +893,8 @@ void ProcessGDBRemote::DidLaunchOrAttach(ArchSpec &process_arch) { process_arch.GetTriple().getTriple()); } - if (int addresssable_bits = m_gdb_comm.GetAddressingBits()) { - lldb::addr_t address_mask = ~((1ULL << addresssable_bits) - 1); + if (int addressable_bits = m_gdb_comm.GetAddressingBits()) { + lldb::addr_t address_mask = ~((1ULL << addressable_bits) - 1); SetCodeAddressMask(address_mask); SetDataAddressMask(address_mask); } @@ -1058,6 +955,9 @@ void ProcessGDBRemote::DidLaunchOrAttach(ArchSpec &process_arch) { } } + // Target and Process are reasonably initailized; + // load any binaries we have metadata for / set load address. + LoadStubBinaries(); MaybeLoadExecutableModule(); // Find out which StructuredDataPlugins are supported by the debug monitor. @@ -1079,12 +979,65 @@ void ProcessGDBRemote::DidLaunchOrAttach(ArchSpec &process_arch) { } } +void ProcessGDBRemote::LoadStubBinaries() { + // The remote stub may know about the "main binary" in + // the context of a firmware debug session, and can + // give us a UUID and an address/slide of where the + // binary is loaded in memory. + UUID standalone_uuid; + addr_t standalone_value; + bool standalone_value_is_offset; + if (m_gdb_comm.GetProcessStandaloneBinary(standalone_uuid, standalone_value, + standalone_value_is_offset)) { + ModuleSP module_sp; + + if (standalone_uuid.IsValid()) { + const bool force_symbol_search = true; + const bool notify = true; + DynamicLoader::LoadBinaryWithUUIDAndAddress( + this, "", standalone_uuid, standalone_value, + standalone_value_is_offset, force_symbol_search, notify); + } + } + + // The remote stub may know about a list of binaries to + // force load into the process -- a firmware type situation + // where multiple binaries are present in virtual memory, + // and we are only given the addresses of the binaries. + // Not intended for use with userland debugging, when we use + // a DynamicLoader plugin that knows how to find the loaded + // binaries, and will track updates as binaries are added. + + std::vector<addr_t> bin_addrs = m_gdb_comm.GetProcessStandaloneBinaries(); + if (bin_addrs.size()) { + UUID uuid; + const bool value_is_slide = false; + for (addr_t addr : bin_addrs) { + const bool notify = true; + // First see if this is a special platform + // binary that may determine the DynamicLoader and + // Platform to be used in this Process and Target. + if (GetTarget() + .GetDebugger() + .GetPlatformList() + .LoadPlatformBinaryAndSetup(this, addr, notify)) + continue; + + const bool force_symbol_search = true; + // Second manually load this binary into the Target. + DynamicLoader::LoadBinaryWithUUIDAndAddress(this, llvm::StringRef(), uuid, + addr, value_is_slide, + force_symbol_search, notify); + } + } +} + void ProcessGDBRemote::MaybeLoadExecutableModule() { ModuleSP module_sp = GetTarget().GetExecutableModule(); if (!module_sp) return; - llvm::Optional<QOffsets> offsets = m_gdb_comm.GetQOffsets(); + std::optional<QOffsets> offsets = m_gdb_comm.GetQOffsets(); if (!offsets) return; @@ -1226,7 +1179,7 @@ Status ProcessGDBRemote::DoResume() { ListenerSP listener_sp( Listener::MakeListener("gdb-remote.resume-packet-sent")); if (listener_sp->StartListeningForEvents( - &m_gdb_comm, GDBRemoteCommunication::eBroadcastBitRunPacketSent)) { + &m_gdb_comm, GDBRemoteClientBase::eBroadcastBitRunPacketSent)) { listener_sp->StartListeningForEvents( &m_async_broadcaster, ProcessGDBRemote::eBroadcastBitAsyncThreadDidExit); @@ -1236,11 +1189,18 @@ Status ProcessGDBRemote::DoResume() { StreamString continue_packet; bool continue_packet_error = false; if (m_gdb_comm.HasAnyVContSupport()) { + std::string pid_prefix; + if (m_gdb_comm.GetMultiprocessSupported()) + pid_prefix = llvm::formatv("p{0:x-}.", GetID()); + if (m_continue_c_tids.size() == num_threads || (m_continue_c_tids.empty() && m_continue_C_tids.empty() && m_continue_s_tids.empty() && m_continue_S_tids.empty())) { - // All threads are continuing, just send a "c" packet - continue_packet.PutCString("c"); + // All threads are continuing + if (m_gdb_comm.GetMultiprocessSupported()) + continue_packet.Format("vCont;c:{0}-1", pid_prefix); + else + continue_packet.PutCString("c"); } else { continue_packet.PutCString("vCont"); @@ -1250,7 +1210,7 @@ Status ProcessGDBRemote::DoResume() { t_pos = m_continue_c_tids.begin(), t_end = m_continue_c_tids.end(); t_pos != t_end; ++t_pos) - continue_packet.Printf(";c:%4.4" PRIx64, *t_pos); + continue_packet.Format(";c:{0}{1:x-}", pid_prefix, *t_pos); } else continue_packet_error = true; } @@ -1261,8 +1221,8 @@ Status ProcessGDBRemote::DoResume() { s_pos = m_continue_C_tids.begin(), s_end = m_continue_C_tids.end(); s_pos != s_end; ++s_pos) - continue_packet.Printf(";C%2.2x:%4.4" PRIx64, s_pos->second, - s_pos->first); + continue_packet.Format(";C{0:x-2}:{1}{2:x-}", s_pos->second, + pid_prefix, s_pos->first); } else continue_packet_error = true; } @@ -1273,7 +1233,7 @@ Status ProcessGDBRemote::DoResume() { t_pos = m_continue_s_tids.begin(), t_end = m_continue_s_tids.end(); t_pos != t_end; ++t_pos) - continue_packet.Printf(";s:%4.4" PRIx64, *t_pos); + continue_packet.Format(";s:{0}{1:x-}", pid_prefix, *t_pos); } else continue_packet_error = true; } @@ -1284,8 +1244,8 @@ Status ProcessGDBRemote::DoResume() { s_pos = m_continue_S_tids.begin(), s_end = m_continue_S_tids.end(); s_pos != s_end; ++s_pos) - continue_packet.Printf(";S%2.2x:%4.4" PRIx64, s_pos->second, - s_pos->first); + continue_packet.Format(";S{0:x-2}:{1}{2:x-}", s_pos->second, + pid_prefix, s_pos->first); } else continue_packet_error = true; } @@ -1652,281 +1612,276 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo( // queue_serial are valid LazyBool associated_with_dispatch_queue, addr_t dispatch_queue_t, std::string &queue_name, QueueKind queue_kind, uint64_t queue_serial) { - ThreadSP thread_sp; - if (tid != LLDB_INVALID_THREAD_ID) { - // Scope for "locker" below - { - // m_thread_list_real does have its own mutex, but we need to hold onto - // the mutex between the call to m_thread_list_real.FindThreadByID(...) - // and the m_thread_list_real.AddThread(...) so it doesn't change on us - std::lock_guard<std::recursive_mutex> guard( - m_thread_list_real.GetMutex()); - thread_sp = m_thread_list_real.FindThreadByProtocolID(tid, false); - - if (!thread_sp) { - // Create the thread if we need to - thread_sp = std::make_shared<ThreadGDBRemote>(*this, tid); - m_thread_list_real.AddThread(thread_sp); - } - } - - if (thread_sp) { - ThreadGDBRemote *gdb_thread = - static_cast<ThreadGDBRemote *>(thread_sp.get()); - RegisterContextSP gdb_reg_ctx_sp(gdb_thread->GetRegisterContext()); - - gdb_reg_ctx_sp->InvalidateIfNeeded(true); - auto iter = std::find(m_thread_ids.begin(), m_thread_ids.end(), tid); - if (iter != m_thread_ids.end()) { - SetThreadPc(thread_sp, iter - m_thread_ids.begin()); - } + if (tid == LLDB_INVALID_THREAD_ID) + return nullptr; - for (const auto &pair : expedited_register_map) { - StringExtractor reg_value_extractor(pair.second); - WritableDataBufferSP buffer_sp(new DataBufferHeap( - reg_value_extractor.GetStringRef().size() / 2, 0)); - reg_value_extractor.GetHexBytes(buffer_sp->GetData(), '\xcc'); - uint32_t lldb_regnum = - gdb_reg_ctx_sp->ConvertRegisterKindToRegisterNumber( - eRegisterKindProcessPlugin, pair.first); - gdb_thread->PrivateSetRegisterValue(lldb_regnum, buffer_sp->GetData()); - } + ThreadSP thread_sp; + // Scope for "locker" below + { + // m_thread_list_real does have its own mutex, but we need to hold onto the + // mutex between the call to m_thread_list_real.FindThreadByID(...) and the + // m_thread_list_real.AddThread(...) so it doesn't change on us + std::lock_guard<std::recursive_mutex> guard(m_thread_list_real.GetMutex()); + thread_sp = m_thread_list_real.FindThreadByProtocolID(tid, false); + + if (!thread_sp) { + // Create the thread if we need to + thread_sp = std::make_shared<ThreadGDBRemote>(*this, tid); + m_thread_list_real.AddThread(thread_sp); + } + } - // AArch64 SVE specific code below calls AArch64SVEReconfigure to update - // SVE register sizes and offsets if value of VG register has changed - // since last stop. - const ArchSpec &arch = GetTarget().GetArchitecture(); - if (arch.IsValid() && arch.GetTriple().isAArch64()) { - GDBRemoteRegisterContext *reg_ctx_sp = - static_cast<GDBRemoteRegisterContext *>( - gdb_thread->GetRegisterContext().get()); - - if (reg_ctx_sp) - reg_ctx_sp->AArch64SVEReconfigure(); - } + ThreadGDBRemote *gdb_thread = static_cast<ThreadGDBRemote *>(thread_sp.get()); + RegisterContextSP gdb_reg_ctx_sp(gdb_thread->GetRegisterContext()); - thread_sp->SetName(thread_name.empty() ? nullptr : thread_name.c_str()); + gdb_reg_ctx_sp->InvalidateIfNeeded(true); - gdb_thread->SetThreadDispatchQAddr(thread_dispatch_qaddr); - // Check if the GDB server was able to provide the queue name, kind and - // serial number - if (queue_vars_valid) - gdb_thread->SetQueueInfo(std::move(queue_name), queue_kind, - queue_serial, dispatch_queue_t, - associated_with_dispatch_queue); - else - gdb_thread->ClearQueueInfo(); + auto iter = std::find(m_thread_ids.begin(), m_thread_ids.end(), tid); + if (iter != m_thread_ids.end()) + SetThreadPc(thread_sp, iter - m_thread_ids.begin()); - gdb_thread->SetAssociatedWithLibdispatchQueue( - associated_with_dispatch_queue); + for (const auto &pair : expedited_register_map) { + StringExtractor reg_value_extractor(pair.second); + WritableDataBufferSP buffer_sp( + new DataBufferHeap(reg_value_extractor.GetStringRef().size() / 2, 0)); + reg_value_extractor.GetHexBytes(buffer_sp->GetData(), '\xcc'); + uint32_t lldb_regnum = gdb_reg_ctx_sp->ConvertRegisterKindToRegisterNumber( + eRegisterKindProcessPlugin, pair.first); + gdb_thread->PrivateSetRegisterValue(lldb_regnum, buffer_sp->GetData()); + } - if (dispatch_queue_t != LLDB_INVALID_ADDRESS) - gdb_thread->SetQueueLibdispatchQueueAddress(dispatch_queue_t); + // AArch64 SVE specific code below calls AArch64SVEReconfigure to update + // SVE register sizes and offsets if value of VG register has changed + // since last stop. + const ArchSpec &arch = GetTarget().GetArchitecture(); + if (arch.IsValid() && arch.GetTriple().isAArch64()) { + GDBRemoteRegisterContext *reg_ctx_sp = + static_cast<GDBRemoteRegisterContext *>( + gdb_thread->GetRegisterContext().get()); - // Make sure we update our thread stop reason just once - if (!thread_sp->StopInfoIsUpToDate()) { - thread_sp->SetStopInfo(StopInfoSP()); - // If there's a memory thread backed by this thread, we need to use it - // to calculate StopInfo. - if (ThreadSP memory_thread_sp = - m_thread_list.GetBackingThread(thread_sp)) - thread_sp = memory_thread_sp; + if (reg_ctx_sp) + reg_ctx_sp->AArch64SVEReconfigure(); + } - if (exc_type != 0) { - const size_t exc_data_size = exc_data.size(); + thread_sp->SetName(thread_name.empty() ? nullptr : thread_name.c_str()); - thread_sp->SetStopInfo( - StopInfoMachException::CreateStopReasonWithMachException( - *thread_sp, exc_type, exc_data_size, - exc_data_size >= 1 ? exc_data[0] : 0, - exc_data_size >= 2 ? exc_data[1] : 0, - exc_data_size >= 3 ? exc_data[2] : 0)); - } else { - bool handled = false; - bool did_exec = false; - if (!reason.empty()) { - if (reason == "trace") { - addr_t pc = thread_sp->GetRegisterContext()->GetPC(); - lldb::BreakpointSiteSP bp_site_sp = thread_sp->GetProcess() - ->GetBreakpointSiteList() - .FindByAddress(pc); - - // If the current pc is a breakpoint site then the StopInfo - // should be set to Breakpoint Otherwise, it will be set to - // Trace. - if (bp_site_sp && bp_site_sp->ValidForThisThread(*thread_sp)) { - thread_sp->SetStopInfo( - StopInfo::CreateStopReasonWithBreakpointSiteID( - *thread_sp, bp_site_sp->GetID())); - } else - thread_sp->SetStopInfo( - StopInfo::CreateStopReasonToTrace(*thread_sp)); - handled = true; - } else if (reason == "breakpoint") { - addr_t pc = thread_sp->GetRegisterContext()->GetPC(); - lldb::BreakpointSiteSP bp_site_sp = thread_sp->GetProcess() - ->GetBreakpointSiteList() - .FindByAddress(pc); - if (bp_site_sp) { - // If the breakpoint is for this thread, then we'll report the - // hit, but if it is for another thread, we can just report no - // reason. We don't need to worry about stepping over the - // breakpoint here, that will be taken care of when the thread - // resumes and notices that there's a breakpoint under the pc. - handled = true; - if (bp_site_sp->ValidForThisThread(*thread_sp)) { - thread_sp->SetStopInfo( - StopInfo::CreateStopReasonWithBreakpointSiteID( - *thread_sp, bp_site_sp->GetID())); - } else { - StopInfoSP invalid_stop_info_sp; - thread_sp->SetStopInfo(invalid_stop_info_sp); - } - } - } else if (reason == "trap") { - // Let the trap just use the standard signal stop reason below... - } else if (reason == "watchpoint") { - StringExtractor desc_extractor(description.c_str()); - addr_t wp_addr = desc_extractor.GetU64(LLDB_INVALID_ADDRESS); - uint32_t wp_index = desc_extractor.GetU32(LLDB_INVALID_INDEX32); - addr_t wp_hit_addr = desc_extractor.GetU64(LLDB_INVALID_ADDRESS); - watch_id_t watch_id = LLDB_INVALID_WATCH_ID; - if (wp_addr != LLDB_INVALID_ADDRESS) { - WatchpointSP wp_sp; - ArchSpec::Core core = GetTarget().GetArchitecture().GetCore(); - if ((core >= ArchSpec::kCore_mips_first && - core <= ArchSpec::kCore_mips_last) || - (core >= ArchSpec::eCore_arm_generic && - core <= ArchSpec::eCore_arm_aarch64)) - wp_sp = GetTarget().GetWatchpointList().FindByAddress( - wp_hit_addr); - if (!wp_sp) - wp_sp = - GetTarget().GetWatchpointList().FindByAddress(wp_addr); - if (wp_sp) { - wp_sp->SetHardwareIndex(wp_index); - watch_id = wp_sp->GetID(); - } - } - if (watch_id == LLDB_INVALID_WATCH_ID) { - Log *log(GetLog(GDBRLog::Watchpoints)); - LLDB_LOGF(log, "failed to find watchpoint"); - } - thread_sp->SetStopInfo(StopInfo::CreateStopReasonWithWatchpointID( - *thread_sp, watch_id, wp_hit_addr)); - handled = true; - } else if (reason == "exception") { - thread_sp->SetStopInfo(StopInfo::CreateStopReasonWithException( - *thread_sp, description.c_str())); - handled = true; - } else if (reason == "exec") { - did_exec = true; - thread_sp->SetStopInfo( - StopInfo::CreateStopReasonWithExec(*thread_sp)); - handled = true; - } else if (reason == "processor trace") { - thread_sp->SetStopInfo(StopInfo::CreateStopReasonProcessorTrace( - *thread_sp, description.c_str())); - } else if (reason == "fork") { - StringExtractor desc_extractor(description.c_str()); - lldb::pid_t child_pid = desc_extractor.GetU64( - LLDB_INVALID_PROCESS_ID); - lldb::tid_t child_tid = desc_extractor.GetU64( - LLDB_INVALID_THREAD_ID); - thread_sp->SetStopInfo(StopInfo::CreateStopReasonFork( - *thread_sp, child_pid, child_tid)); - handled = true; - } else if (reason == "vfork") { - StringExtractor desc_extractor(description.c_str()); - lldb::pid_t child_pid = desc_extractor.GetU64( - LLDB_INVALID_PROCESS_ID); - lldb::tid_t child_tid = desc_extractor.GetU64( - LLDB_INVALID_THREAD_ID); - thread_sp->SetStopInfo(StopInfo::CreateStopReasonVFork( - *thread_sp, child_pid, child_tid)); - handled = true; - } else if (reason == "vforkdone") { - thread_sp->SetStopInfo( - StopInfo::CreateStopReasonVForkDone(*thread_sp)); - handled = true; - } - } else if (!signo) { - addr_t pc = thread_sp->GetRegisterContext()->GetPC(); - lldb::BreakpointSiteSP bp_site_sp = - thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress( - pc); - - // If the current pc is a breakpoint site then the StopInfo should - // be set to Breakpoint even though the remote stub did not set it - // as such. This can happen when the thread is involuntarily - // interrupted (e.g. due to stops on other threads) just as it is - // about to execute the breakpoint instruction. - if (bp_site_sp && bp_site_sp->ValidForThisThread(*thread_sp)) { + gdb_thread->SetThreadDispatchQAddr(thread_dispatch_qaddr); + // Check if the GDB server was able to provide the queue name, kind and serial + // number + if (queue_vars_valid) + gdb_thread->SetQueueInfo(std::move(queue_name), queue_kind, queue_serial, + dispatch_queue_t, associated_with_dispatch_queue); + else + gdb_thread->ClearQueueInfo(); + + gdb_thread->SetAssociatedWithLibdispatchQueue(associated_with_dispatch_queue); + + if (dispatch_queue_t != LLDB_INVALID_ADDRESS) + gdb_thread->SetQueueLibdispatchQueueAddress(dispatch_queue_t); + + // Make sure we update our thread stop reason just once, but don't overwrite + // the stop info for threads that haven't moved: + StopInfoSP current_stop_info_sp = thread_sp->GetPrivateStopInfo(false); + if (thread_sp->GetTemporaryResumeState() == eStateSuspended && + current_stop_info_sp) { + thread_sp->SetStopInfo(current_stop_info_sp); + return thread_sp; + } + + if (!thread_sp->StopInfoIsUpToDate()) { + thread_sp->SetStopInfo(StopInfoSP()); + // If there's a memory thread backed by this thread, we need to use it to + // calculate StopInfo. + if (ThreadSP memory_thread_sp = m_thread_list.GetBackingThread(thread_sp)) + thread_sp = memory_thread_sp; + + if (exc_type != 0) { + const size_t exc_data_size = exc_data.size(); + + thread_sp->SetStopInfo( + StopInfoMachException::CreateStopReasonWithMachException( + *thread_sp, exc_type, exc_data_size, + exc_data_size >= 1 ? exc_data[0] : 0, + exc_data_size >= 2 ? exc_data[1] : 0, + exc_data_size >= 3 ? exc_data[2] : 0)); + } else { + bool handled = false; + bool did_exec = false; + if (!reason.empty()) { + if (reason == "trace") { + addr_t pc = thread_sp->GetRegisterContext()->GetPC(); + lldb::BreakpointSiteSP bp_site_sp = + thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress( + pc); + + // If the current pc is a breakpoint site then the StopInfo should be + // set to Breakpoint Otherwise, it will be set to Trace. + if (bp_site_sp && bp_site_sp->ValidForThisThread(*thread_sp)) { + thread_sp->SetStopInfo( + StopInfo::CreateStopReasonWithBreakpointSiteID( + *thread_sp, bp_site_sp->GetID())); + } else + thread_sp->SetStopInfo( + StopInfo::CreateStopReasonToTrace(*thread_sp)); + handled = true; + } else if (reason == "breakpoint") { + addr_t pc = thread_sp->GetRegisterContext()->GetPC(); + lldb::BreakpointSiteSP bp_site_sp = + thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress( + pc); + if (bp_site_sp) { + // If the breakpoint is for this thread, then we'll report the hit, + // but if it is for another thread, we can just report no reason. + // We don't need to worry about stepping over the breakpoint here, + // that will be taken care of when the thread resumes and notices + // that there's a breakpoint under the pc. + handled = true; + if (bp_site_sp->ValidForThisThread(*thread_sp)) { thread_sp->SetStopInfo( StopInfo::CreateStopReasonWithBreakpointSiteID( *thread_sp, bp_site_sp->GetID())); - handled = true; + } else { + StopInfoSP invalid_stop_info_sp; + thread_sp->SetStopInfo(invalid_stop_info_sp); } } - - if (!handled && signo && !did_exec) { - if (signo == SIGTRAP) { - // Currently we are going to assume SIGTRAP means we are either - // hitting a breakpoint or hardware single stepping. - handled = true; - addr_t pc = thread_sp->GetRegisterContext()->GetPC() + - m_breakpoint_pc_offset; - lldb::BreakpointSiteSP bp_site_sp = thread_sp->GetProcess() - ->GetBreakpointSiteList() - .FindByAddress(pc); - - if (bp_site_sp) { - // If the breakpoint is for this thread, then we'll report the - // hit, but if it is for another thread, we can just report no - // reason. We don't need to worry about stepping over the - // breakpoint here, that will be taken care of when the thread - // resumes and notices that there's a breakpoint under the pc. - if (bp_site_sp->ValidForThisThread(*thread_sp)) { - if (m_breakpoint_pc_offset != 0) - thread_sp->GetRegisterContext()->SetPC(pc); - thread_sp->SetStopInfo( - StopInfo::CreateStopReasonWithBreakpointSiteID( - *thread_sp, bp_site_sp->GetID())); - } else { - StopInfoSP invalid_stop_info_sp; - thread_sp->SetStopInfo(invalid_stop_info_sp); - } - } else { - // If we were stepping then assume the stop was the result of - // the trace. If we were not stepping then report the SIGTRAP. - // FIXME: We are still missing the case where we single step - // over a trap instruction. - if (thread_sp->GetTemporaryResumeState() == eStateStepping) - thread_sp->SetStopInfo( - StopInfo::CreateStopReasonToTrace(*thread_sp)); - else - thread_sp->SetStopInfo(StopInfo::CreateStopReasonWithSignal( - *thread_sp, signo, description.c_str())); - } + } else if (reason == "trap") { + // Let the trap just use the standard signal stop reason below... + } else if (reason == "watchpoint") { + StringExtractor desc_extractor(description.c_str()); + addr_t wp_addr = desc_extractor.GetU64(LLDB_INVALID_ADDRESS); + uint32_t wp_index = desc_extractor.GetU32(LLDB_INVALID_INDEX32); + addr_t wp_hit_addr = desc_extractor.GetU64(LLDB_INVALID_ADDRESS); + watch_id_t watch_id = LLDB_INVALID_WATCH_ID; + if (wp_addr != LLDB_INVALID_ADDRESS) { + WatchpointSP wp_sp; + ArchSpec::Core core = GetTarget().GetArchitecture().GetCore(); + if ((core >= ArchSpec::kCore_mips_first && + core <= ArchSpec::kCore_mips_last) || + (core >= ArchSpec::eCore_arm_generic && + core <= ArchSpec::eCore_arm_aarch64)) + wp_sp = + GetTarget().GetWatchpointList().FindByAddress(wp_hit_addr); + if (!wp_sp) + wp_sp = GetTarget().GetWatchpointList().FindByAddress(wp_addr); + if (wp_sp) { + wp_sp->SetHardwareIndex(wp_index); + watch_id = wp_sp->GetID(); } - if (!handled) - thread_sp->SetStopInfo(StopInfo::CreateStopReasonWithSignal( - *thread_sp, signo, description.c_str())); } + if (watch_id == LLDB_INVALID_WATCH_ID) { + Log *log(GetLog(GDBRLog::Watchpoints)); + LLDB_LOGF(log, "failed to find watchpoint"); + } + thread_sp->SetStopInfo(StopInfo::CreateStopReasonWithWatchpointID( + *thread_sp, watch_id, wp_hit_addr)); + handled = true; + } else if (reason == "exception") { + thread_sp->SetStopInfo(StopInfo::CreateStopReasonWithException( + *thread_sp, description.c_str())); + handled = true; + } else if (reason == "exec") { + did_exec = true; + thread_sp->SetStopInfo( + StopInfo::CreateStopReasonWithExec(*thread_sp)); + handled = true; + } else if (reason == "processor trace") { + thread_sp->SetStopInfo(StopInfo::CreateStopReasonProcessorTrace( + *thread_sp, description.c_str())); + } else if (reason == "fork") { + StringExtractor desc_extractor(description.c_str()); + lldb::pid_t child_pid = + desc_extractor.GetU64(LLDB_INVALID_PROCESS_ID); + lldb::tid_t child_tid = desc_extractor.GetU64(LLDB_INVALID_THREAD_ID); + thread_sp->SetStopInfo( + StopInfo::CreateStopReasonFork(*thread_sp, child_pid, child_tid)); + handled = true; + } else if (reason == "vfork") { + StringExtractor desc_extractor(description.c_str()); + lldb::pid_t child_pid = + desc_extractor.GetU64(LLDB_INVALID_PROCESS_ID); + lldb::tid_t child_tid = desc_extractor.GetU64(LLDB_INVALID_THREAD_ID); + thread_sp->SetStopInfo(StopInfo::CreateStopReasonVFork( + *thread_sp, child_pid, child_tid)); + handled = true; + } else if (reason == "vforkdone") { + thread_sp->SetStopInfo( + StopInfo::CreateStopReasonVForkDone(*thread_sp)); + handled = true; + } + } else if (!signo) { + addr_t pc = thread_sp->GetRegisterContext()->GetPC(); + lldb::BreakpointSiteSP bp_site_sp = + thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress(pc); + + // If the current pc is a breakpoint site then the StopInfo should be + // set to Breakpoint even though the remote stub did not set it as such. + // This can happen when the thread is involuntarily interrupted (e.g. + // due to stops on other threads) just as it is about to execute the + // breakpoint instruction. + if (bp_site_sp && bp_site_sp->ValidForThisThread(*thread_sp)) { + thread_sp->SetStopInfo(StopInfo::CreateStopReasonWithBreakpointSiteID( + *thread_sp, bp_site_sp->GetID())); + handled = true; + } + } - if (!description.empty()) { - lldb::StopInfoSP stop_info_sp(thread_sp->GetStopInfo()); - if (stop_info_sp) { - const char *stop_info_desc = stop_info_sp->GetDescription(); - if (!stop_info_desc || !stop_info_desc[0]) - stop_info_sp->SetDescription(description.c_str()); + if (!handled && signo && !did_exec) { + if (signo == SIGTRAP) { + // Currently we are going to assume SIGTRAP means we are either + // hitting a breakpoint or hardware single stepping. + handled = true; + addr_t pc = + thread_sp->GetRegisterContext()->GetPC() + m_breakpoint_pc_offset; + lldb::BreakpointSiteSP bp_site_sp = + thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress( + pc); + + if (bp_site_sp) { + // If the breakpoint is for this thread, then we'll report the hit, + // but if it is for another thread, we can just report no reason. + // We don't need to worry about stepping over the breakpoint here, + // that will be taken care of when the thread resumes and notices + // that there's a breakpoint under the pc. + if (bp_site_sp->ValidForThisThread(*thread_sp)) { + if (m_breakpoint_pc_offset != 0) + thread_sp->GetRegisterContext()->SetPC(pc); + thread_sp->SetStopInfo( + StopInfo::CreateStopReasonWithBreakpointSiteID( + *thread_sp, bp_site_sp->GetID())); } else { - thread_sp->SetStopInfo(StopInfo::CreateStopReasonWithException( - *thread_sp, description.c_str())); + StopInfoSP invalid_stop_info_sp; + thread_sp->SetStopInfo(invalid_stop_info_sp); } + } else { + // If we were stepping then assume the stop was the result of the + // trace. If we were not stepping then report the SIGTRAP. + // FIXME: We are still missing the case where we single step over a + // trap instruction. + if (thread_sp->GetTemporaryResumeState() == eStateStepping) + thread_sp->SetStopInfo( + StopInfo::CreateStopReasonToTrace(*thread_sp)); + else + thread_sp->SetStopInfo(StopInfo::CreateStopReasonWithSignal( + *thread_sp, signo, description.c_str())); } } + if (!handled) + thread_sp->SetStopInfo(StopInfo::CreateStopReasonWithSignal( + *thread_sp, signo, description.c_str())); + } + + if (!description.empty()) { + lldb::StopInfoSP stop_info_sp(thread_sp->GetStopInfo()); + if (stop_info_sp) { + const char *stop_info_desc = stop_info_sp->GetDescription(); + if (!stop_info_desc || !stop_info_desc[0]) + stop_info_sp->SetDescription(description.c_str()); + } else { + thread_sp->SetStopInfo(StopInfo::CreateStopReasonWithException( + *thread_sp, description.c_str())); + } } } } @@ -2915,7 +2870,7 @@ size_t ProcessGDBRemote::PutSTDIN(const char *src, size_t src_len, Status &error) { if (m_stdio_communication.IsConnected()) { ConnectionStatus status; - m_stdio_communication.Write(src, src_len, status, nullptr); + m_stdio_communication.WriteAll(src, src_len, status, nullptr); } else if (m_stdin_forward) { m_gdb_comm.SendStdinNotification(src, src_len); } @@ -3498,7 +3453,7 @@ thread_result_t ProcessGDBRemote::AsyncThread() { ") listener.WaitForEvent (NULL, event_sp)...", __FUNCTION__, GetID()); - if (m_async_listener_sp->GetEvent(event_sp, llvm::None)) { + if (m_async_listener_sp->GetEvent(event_sp, std::nullopt)) { const uint32_t event_type = event_sp->GetType(); if (event_sp->BroadcasterIs(&m_async_broadcaster)) { LLDB_LOGF(log, @@ -3610,21 +3565,6 @@ thread_result_t ProcessGDBRemote::AsyncThread() { done = true; break; } - } else if (event_sp->BroadcasterIs(&m_gdb_comm)) { - switch (event_type) { - case Communication::eBroadcastBitReadThreadDidExit: - SetExitStatus(-1, "lost connection"); - done = true; - break; - - default: - LLDB_LOGF(log, - "ProcessGDBRemote::%s(pid = %" PRIu64 - ") got unknown event 0x%8.8x", - __FUNCTION__, GetID(), event_type); - done = true; - break; - } } } else { LLDB_LOGF(log, @@ -3894,6 +3834,29 @@ ProcessGDBRemote::GetLoadedDynamicLibrariesInfos_sender( return object_sp; } +StructuredData::ObjectSP ProcessGDBRemote::GetDynamicLoaderProcessState() { + StructuredData::ObjectSP object_sp; + StructuredData::ObjectSP args_dict(new StructuredData::Dictionary()); + + if (m_gdb_comm.GetDynamicLoaderProcessStateSupported()) { + StringExtractorGDBRemote response; + response.SetResponseValidatorToJSON(); + if (m_gdb_comm.SendPacketAndWaitForResponse("jGetDyldProcessState", + response) == + GDBRemoteCommunication::PacketResult::Success) { + StringExtractorGDBRemote::ResponseType response_type = + response.GetResponseType(); + if (response_type == StringExtractorGDBRemote::eResponse) { + if (!response.Empty()) { + object_sp = + StructuredData::ParseJSON(std::string(response.GetStringRef())); + } + } + } + } + return object_sp; +} + StructuredData::ObjectSP ProcessGDBRemote::GetSharedCacheInfo() { StructuredData::ObjectSP object_sp; StructuredData::ObjectSP args_dict(new StructuredData::Dictionary()); @@ -4075,8 +4038,10 @@ bool ParseRegisters(XMLNode feature_node, GdbServerTargetInfo &target_info, if (!feature_node) return false; + Log *log(GetLog(GDBRLog::Process)); + feature_node.ForEachChildElementWithName( - "reg", [&target_info, ®isters](const XMLNode ®_node) -> bool { + "reg", [&target_info, ®isters, log](const XMLNode ®_node) -> bool { std::string gdb_group; std::string gdb_type; DynamicRegisterInfo::Register reg_info; @@ -4085,9 +4050,9 @@ bool ParseRegisters(XMLNode feature_node, GdbServerTargetInfo &target_info, // FIXME: we're silently ignoring invalid data here reg_node.ForEachAttribute([&target_info, &gdb_group, &gdb_type, - &encoding_set, &format_set, ®_info]( - const llvm::StringRef &name, - const llvm::StringRef &value) -> bool { + &encoding_set, &format_set, ®_info, + log](const llvm::StringRef &name, + const llvm::StringRef &value) -> bool { if (name == "name") { reg_info.name.SetString(value); } else if (name == "bitsize") { @@ -4144,10 +4109,10 @@ bool ParseRegisters(XMLNode feature_node, GdbServerTargetInfo &target_info, SplitCommaSeparatedRegisterNumberString( value, reg_info.invalidate_regs, 0); } else { - Log *log(GetLog(GDBRLog::Process)); LLDB_LOGF(log, - "ProcessGDBRemote::%s unhandled reg attribute %s = %s", - __FUNCTION__, name.data(), value.data()); + "ProcessGDBRemote::ParseRegisters unhandled reg " + "attribute %s = %s", + name.data(), value.data()); } return true; // Keep iterating through all attributes }); @@ -4169,6 +4134,12 @@ bool ParseRegisters(XMLNode feature_node, GdbServerTargetInfo &target_info, // them as vector (similarly to xmm/ymm) reg_info.format = eFormatVectorOfUInt8; reg_info.encoding = eEncodingVector; + } else { + LLDB_LOGF( + log, + "ProcessGDBRemote::ParseRegisters Could not determine lldb" + "format and encoding for gdb type %s", + gdb_type.c_str()); } } @@ -4186,7 +4157,6 @@ bool ParseRegisters(XMLNode feature_node, GdbServerTargetInfo &target_info, } if (reg_info.byte_size == 0) { - Log *log(GetLog(GDBRLog::Process)); LLDB_LOGF(log, "ProcessGDBRemote::%s Skipping zero bitsize register %s", __FUNCTION__, reg_info.name.AsCString()); diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h index 50cef8e499dc..83f0adfe35af 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h @@ -12,6 +12,7 @@ #include <atomic> #include <map> #include <mutex> +#include <optional> #include <string> #include <vector> @@ -49,8 +50,6 @@ class ThreadGDBRemote; class ProcessGDBRemote : public Process, private GDBRemoteClientBase::ContinueDelegate { public: - ProcessGDBRemote(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp); - ~ProcessGDBRemote() override; static lldb::ProcessSP CreateInstance(lldb::TargetSP target_sp, @@ -79,16 +78,16 @@ public: CommandObject *GetPluginCommandObject() override; // Creating a new process, or attaching to an existing one - Status WillLaunch(Module *module) override; + Status DoWillLaunch(Module *module) override; Status DoLaunch(Module *exe_module, ProcessLaunchInfo &launch_info) override; void DidLaunch() override; - Status WillAttachToProcessWithID(lldb::pid_t pid) override; + Status DoWillAttachToProcessWithID(lldb::pid_t pid) override; - Status WillAttachToProcessWithName(const char *process_name, - bool wait_for_launch) override; + Status DoWillAttachToProcessWithName(const char *process_name, + bool wait_for_launch) override; Status DoConnectRemote(llvm::StringRef remote_url) override; @@ -224,6 +223,8 @@ public: StructuredData::ObjectSP GetSharedCacheInfo() override; + StructuredData::ObjectSP GetDynamicLoaderProcessState() override; + std::string HarmonizeThreadIdsForProfileData( StringExtractorGDBRemote &inputStringExtractor); @@ -239,6 +240,8 @@ protected: friend class GDBRemoteCommunicationClient; friend class GDBRemoteRegisterContext; + ProcessGDBRemote(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp); + bool SupportsMemoryTagging() override; /// Broadcaster event bits definitions. @@ -251,7 +254,7 @@ protected: GDBRemoteCommunicationClient m_gdb_comm; std::atomic<lldb::pid_t> m_debugserver_pid; - llvm::Optional<StringExtractorGDBRemote> m_last_stop_packet; + std::optional<StringExtractorGDBRemote> m_last_stop_packet; std::recursive_mutex m_last_stop_packet_mutex; GDBRemoteDynamicRegisterInfoSP m_register_info_sp; @@ -308,8 +311,6 @@ protected: bool HasExited(lldb::StateType state) { return state == lldb::eStateExited; } - bool ProcessIDIsValid() const; - void Clear(); bool DoUpdateThreadList(ThreadList &old_thread_list, @@ -373,6 +374,7 @@ protected: bool UpdateThreadIDList(); void DidLaunchOrAttach(ArchSpec &process_arch); + void LoadStubBinaries(); void MaybeLoadExecutableModule(); Status ConnectToDebugserver(llvm::StringRef host_port); diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp index ecf363aa2e73..be9fae938e22 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp @@ -19,6 +19,7 @@ // C++ includes #include <algorithm> #include <map> +#include <optional> #include <vector> #include <utility> @@ -68,13 +69,13 @@ UUID MinidumpParser::GetModuleUUID(const minidump::Module *module) { return UUID(); if (GetArchitecture().GetTriple().isOSBinFormatELF()) { if (pdb70_uuid->Age != 0) - return UUID::fromOptionalData(pdb70_uuid, sizeof(*pdb70_uuid)); - return UUID::fromOptionalData(&pdb70_uuid->Uuid, + return UUID(pdb70_uuid, sizeof(*pdb70_uuid)); + return UUID(&pdb70_uuid->Uuid, sizeof(pdb70_uuid->Uuid)); } - return UUID::fromCvRecord(*pdb70_uuid); + return UUID(*pdb70_uuid); } else if (cv_signature == CvSignature::ElfBuildId) - return UUID::fromOptionalData(cv_record); + return UUID(cv_record); return UUID(); } @@ -220,27 +221,27 @@ const MinidumpMiscInfo *MinidumpParser::GetMiscInfo() { return MinidumpMiscInfo::Parse(data); } -llvm::Optional<LinuxProcStatus> MinidumpParser::GetLinuxProcStatus() { +std::optional<LinuxProcStatus> MinidumpParser::GetLinuxProcStatus() { llvm::ArrayRef<uint8_t> data = GetStream(StreamType::LinuxProcStatus); if (data.size() == 0) - return llvm::None; + return std::nullopt; return LinuxProcStatus::Parse(data); } -llvm::Optional<lldb::pid_t> MinidumpParser::GetPid() { +std::optional<lldb::pid_t> MinidumpParser::GetPid() { const MinidumpMiscInfo *misc_info = GetMiscInfo(); if (misc_info != nullptr) { return misc_info->GetPid(); } - llvm::Optional<LinuxProcStatus> proc_status = GetLinuxProcStatus(); + std::optional<LinuxProcStatus> proc_status = GetLinuxProcStatus(); if (proc_status) { return proc_status->GetPid(); } - return llvm::None; + return std::nullopt; } llvm::ArrayRef<minidump::Module> MinidumpParser::GetModuleList() { @@ -351,7 +352,7 @@ std::vector<const minidump::Module *> MinidumpParser::GetFilteredModuleList() { // Create memory regions from the linux maps only. We do this to avoid issues // with breakpad generated minidumps where if someone has mmap'ed a shared - // library into memory to accesss its data in the object file, we can get a + // library into memory to access its data in the object file, we can get a // minidump with two mappings for a binary: one whose base image points to a // memory region that is read + execute and one that is read only. MemoryRegionInfos linux_regions; @@ -426,7 +427,7 @@ const minidump::ExceptionStream *MinidumpParser::GetExceptionStream() { return nullptr; } -llvm::Optional<minidump::Range> +std::optional<minidump::Range> MinidumpParser::FindMemoryRange(lldb::addr_t addr) { llvm::ArrayRef<uint8_t> data64 = GetStream(StreamType::Memory64List); Log *log = GetLog(LLDBLog::Modules); @@ -442,14 +443,14 @@ MinidumpParser::FindMemoryRange(lldb::addr_t addr) { const size_t range_size = loc_desc.DataSize; if (loc_desc.RVA + loc_desc.DataSize > GetData().size()) - return llvm::None; + return std::nullopt; if (range_start <= addr && addr < range_start + range_size) { auto ExpectedSlice = GetMinidumpFile().getRawData(loc_desc); if (!ExpectedSlice) { LLDB_LOG_ERROR(log, ExpectedSlice.takeError(), "Failed to get memory slice: {0}"); - return llvm::None; + return std::nullopt; } return minidump::Range(range_start, *ExpectedSlice); } @@ -468,14 +469,14 @@ MinidumpParser::FindMemoryRange(lldb::addr_t addr) { MinidumpMemoryDescriptor64::ParseMemory64List(data64); if (memory64_list.empty()) - return llvm::None; + return std::nullopt; for (const auto &memory_desc64 : memory64_list) { const lldb::addr_t range_start = memory_desc64.start_of_memory_range; const size_t range_size = memory_desc64.data_size; if (base_rva + range_size > GetData().size()) - return llvm::None; + return std::nullopt; if (range_start <= addr && addr < range_start + range_size) { return minidump::Range(range_start, @@ -485,7 +486,7 @@ MinidumpParser::FindMemoryRange(lldb::addr_t addr) { } } - return llvm::None; + return std::nullopt; } llvm::ArrayRef<uint8_t> MinidumpParser::GetMemory(lldb::addr_t addr, @@ -494,7 +495,7 @@ llvm::ArrayRef<uint8_t> MinidumpParser::GetMemory(lldb::addr_t addr, // ranges a Minidump typically has, so I'm not sure if searching for the // appropriate range linearly each time is stupid. Perhaps we should build // an index for faster lookups. - llvm::Optional<minidump::Range> range = FindMemoryRange(addr); + std::optional<minidump::Range> range = FindMemoryRange(addr); if (!range) return {}; diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/minidump/MinidumpParser.h b/contrib/llvm-project/lldb/source/Plugins/Process/minidump/MinidumpParser.h index ff7134ff1815..050ba086f46f 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/minidump/MinidumpParser.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/minidump/MinidumpParser.h @@ -19,7 +19,6 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/Optional.h" #include "llvm/ADT/StringRef.h" #include "llvm/Object/Minidump.h" @@ -27,6 +26,7 @@ // C++ includes #include <cstring> +#include <optional> #include <unordered_map> namespace lldb_private { @@ -70,9 +70,9 @@ public: const MinidumpMiscInfo *GetMiscInfo(); - llvm::Optional<LinuxProcStatus> GetLinuxProcStatus(); + std::optional<LinuxProcStatus> GetLinuxProcStatus(); - llvm::Optional<lldb::pid_t> GetPid(); + std::optional<lldb::pid_t> GetPid(); llvm::ArrayRef<minidump::Module> GetModuleList(); @@ -84,7 +84,7 @@ public: const llvm::minidump::ExceptionStream *GetExceptionStream(); - llvm::Optional<Range> FindMemoryRange(lldb::addr_t addr); + std::optional<Range> FindMemoryRange(lldb::addr_t addr); llvm::ArrayRef<uint8_t> GetMemory(lldb::addr_t addr, size_t size); diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/minidump/MinidumpTypes.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/minidump/MinidumpTypes.cpp index abddd79ad7dc..5b919828428f 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/minidump/MinidumpTypes.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/minidump/MinidumpTypes.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "MinidumpTypes.h" +#include <optional> // C includes // C++ includes @@ -24,17 +25,17 @@ const MinidumpMiscInfo *MinidumpMiscInfo::Parse(llvm::ArrayRef<uint8_t> &data) { return misc_info; } -llvm::Optional<lldb::pid_t> MinidumpMiscInfo::GetPid() const { +std::optional<lldb::pid_t> MinidumpMiscInfo::GetPid() const { uint32_t pid_flag = static_cast<uint32_t>(MinidumpMiscInfoFlags::ProcessID); if (flags1 & pid_flag) - return llvm::Optional<lldb::pid_t>(process_id); + return std::optional<lldb::pid_t>(process_id); - return llvm::None; + return std::nullopt; } // Linux Proc Status // it's stored as an ascii string in the file -llvm::Optional<LinuxProcStatus> +std::optional<LinuxProcStatus> LinuxProcStatus::Parse(llvm::ArrayRef<uint8_t> &data) { LinuxProcStatus result; result.proc_status = @@ -52,7 +53,7 @@ LinuxProcStatus::Parse(llvm::ArrayRef<uint8_t> &data) { } } - return llvm::None; + return std::nullopt; } lldb::pid_t LinuxProcStatus::GetPid() const { return pid; } @@ -71,7 +72,7 @@ MinidumpMemoryDescriptor64::ParseMemory64List(llvm::ArrayRef<uint8_t> &data) { return {}; return std::make_pair( - llvm::makeArrayRef( + llvm::ArrayRef( reinterpret_cast<const MinidumpMemoryDescriptor64 *>(data.data()), *mem_ranges_count), *base_rva); diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/minidump/MinidumpTypes.h b/contrib/llvm-project/lldb/source/Plugins/Process/minidump/MinidumpTypes.h index c05fcfef05a6..fe99abf9e24e 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/minidump/MinidumpTypes.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/minidump/MinidumpTypes.h @@ -13,12 +13,12 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/BitmaskEnum.h" -#include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/BinaryFormat/Minidump.h" #include "llvm/Support/ConvertUTF.h" #include "llvm/Support/Endian.h" +#include <optional> // C includes // C++ includes @@ -83,7 +83,7 @@ struct MinidumpMiscInfo { static const MinidumpMiscInfo *Parse(llvm::ArrayRef<uint8_t> &data); - llvm::Optional<lldb::pid_t> GetPid() const; + std::optional<lldb::pid_t> GetPid() const; }; static_assert(sizeof(MinidumpMiscInfo) == 24, "sizeof MinidumpMiscInfo is not correct!"); @@ -94,7 +94,7 @@ public: llvm::StringRef proc_status; lldb::pid_t pid; - static llvm::Optional<LinuxProcStatus> Parse(llvm::ArrayRef<uint8_t> &data); + static std::optional<LinuxProcStatus> Parse(llvm::ArrayRef<uint8_t> &data); lldb::pid_t GetPid() const; diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp index 64219e1a960b..5911b137ef41 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp @@ -37,6 +37,7 @@ #include "Plugins/Process/Utility/StopInfoMachException.h" #include <memory> +#include <optional> using namespace lldb; using namespace lldb_private; @@ -290,8 +291,9 @@ Status ProcessMinidump::DoLoadCore() { SetUnixSignals(UnixSignals::Create(GetArchitecture())); ReadModuleList(); - - llvm::Optional<lldb::pid_t> pid = m_minidump_parser->GetPid(); + if (ModuleSP module = GetTarget().GetExecutableModule()) + GetTarget().MergeArchitecture(module->GetArchitecture()); + std::optional<lldb::pid_t> pid = m_minidump_parser->GetPid(); if (!pid) { Debugger::ReportWarning("unable to retrieve process ID from minidump file, " "setting process ID to 1", @@ -568,7 +570,7 @@ void ProcessMinidump::ReadModuleList() { partial_module_spec.GetUUID().Clear(); module_sp = GetOrCreateModule(uuid, name, partial_module_spec); if (!module_sp) { - partial_module_spec.GetFileSpec().GetDirectory().Clear(); + partial_module_spec.GetFileSpec().ClearDirectory(); module_sp = GetOrCreateModule(uuid, name, partial_module_spec); } } diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/minidump/ProcessMinidump.h b/contrib/llvm-project/lldb/source/Plugins/Process/minidump/ProcessMinidump.h index 5360269199cd..0e4e52c0113f 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/minidump/ProcessMinidump.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/minidump/ProcessMinidump.h @@ -20,7 +20,7 @@ #include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" - +#include <optional> namespace lldb_private { @@ -87,7 +87,7 @@ public: return error; } - llvm::Optional<MinidumpParser> m_minidump_parser; + std::optional<MinidumpParser> m_minidump_parser; protected: void Clear(); @@ -113,7 +113,7 @@ private: const minidump::ExceptionStream *m_active_exception; lldb::CommandObjectSP m_command_sp; bool m_is_wow64; - llvm::Optional<MemoryRegionInfos> m_memory_regions; + std::optional<MemoryRegionInfos> m_memory_regions; void BuildMemoryRegions(); }; diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM.cpp index 7184dbacb08d..9e1e4317cd14 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM.cpp @@ -336,7 +336,7 @@ static RegisterInfo g_reg_infos[] = { DEF_Q(14), DEF_Q(15)}; -constexpr size_t k_num_reg_infos = llvm::array_lengthof(g_reg_infos); +constexpr size_t k_num_reg_infos = std::size(g_reg_infos); // ARM general purpose registers. const uint32_t g_gpr_regnums[] = { @@ -445,26 +445,26 @@ const uint32_t g_fpu_regnums[] = { }; // Skip the last LLDB_INVALID_REGNUM in each count below by subtracting 1 -constexpr size_t k_num_gpr_regs = llvm::array_lengthof(g_gpr_regnums) - 1; -constexpr size_t k_num_fpu_regs = llvm::array_lengthof(g_fpu_regnums) - 1; +constexpr size_t k_num_gpr_regs = std::size(g_gpr_regnums) - 1; +constexpr size_t k_num_fpu_regs = std::size(g_fpu_regnums) - 1; static RegisterSet g_reg_sets[] = { {"General Purpose Registers", "gpr", k_num_gpr_regs, g_gpr_regnums}, {"Floating Point Registers", "fpu", k_num_fpu_regs, g_fpu_regnums}, }; -constexpr size_t k_num_reg_sets = llvm::array_lengthof(g_reg_sets); +constexpr size_t k_num_reg_sets = std::size(g_reg_sets); RegisterContextMinidump_ARM::RegisterContextMinidump_ARM( lldb_private::Thread &thread, const DataExtractor &data, bool apple) : RegisterContext(thread, 0), m_apple(apple) { lldb::offset_t offset = 0; m_regs.context_flags = data.GetU32(&offset); - for (unsigned i = 0; i < llvm::array_lengthof(m_regs.r); ++i) + for (unsigned i = 0; i < std::size(m_regs.r); ++i) m_regs.r[i] = data.GetU32(&offset); m_regs.cpsr = data.GetU32(&offset); m_regs.fpscr = data.GetU64(&offset); - for (unsigned i = 0; i < llvm::array_lengthof(m_regs.d); ++i) + for (unsigned i = 0; i < std::size(m_regs.d); ++i) m_regs.d[i] = data.GetU64(&offset); lldbassert(k_num_regs == k_num_reg_infos); } @@ -521,7 +521,7 @@ bool RegisterContextMinidump_ARM::ReadRegister(const RegisterInfo *reg_info, RegisterValue ®_value) { Status error; reg_value.SetFromMemoryData( - reg_info, (const uint8_t *)&m_regs + reg_info->byte_offset, + *reg_info, (const uint8_t *)&m_regs + reg_info->byte_offset, reg_info->byte_size, lldb::eByteOrderLittle, error); return error.Success(); } diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM64.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM64.cpp index e606ec9c3b64..78190182f548 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM64.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM64.cpp @@ -544,7 +544,7 @@ static RegisterInfo g_reg_infos[] = { DEF_H(31), }; -constexpr size_t k_num_reg_infos = llvm::array_lengthof(g_reg_infos); +constexpr size_t k_num_reg_infos = std::size(g_reg_infos); // ARM64 general purpose registers. const uint32_t g_gpr_regnums[] = { @@ -751,15 +751,15 @@ const uint32_t g_fpu_regnums[] = { }; // Skip the last LLDB_INVALID_REGNUM in each count below by subtracting 1 -constexpr size_t k_num_gpr_regs = llvm::array_lengthof(g_gpr_regnums) - 1; -constexpr size_t k_num_fpu_regs = llvm::array_lengthof(g_fpu_regnums) - 1; +constexpr size_t k_num_gpr_regs = std::size(g_gpr_regnums) - 1; +constexpr size_t k_num_fpu_regs = std::size(g_fpu_regnums) - 1; static RegisterSet g_reg_sets[] = { {"General Purpose Registers", "gpr", k_num_gpr_regs, g_gpr_regnums}, {"Floating Point Registers", "fpu", k_num_fpu_regs, g_fpu_regnums}, }; -constexpr size_t k_num_reg_sets = llvm::array_lengthof(g_reg_sets); +constexpr size_t k_num_reg_sets = std::size(g_reg_sets); RegisterContextMinidump_ARM64::RegisterContextMinidump_ARM64( lldb_private::Thread &thread, const DataExtractor &data) @@ -775,7 +775,7 @@ RegisterContextMinidump_ARM64::RegisterContextMinidump_ARM64( auto regs_data = data.GetData(&offset, sizeof(m_regs.v)); if (regs_data) memcpy(m_regs.v, regs_data, sizeof(m_regs.v)); - static_assert(k_num_regs == k_num_reg_infos, ""); + static_assert(k_num_regs == k_num_reg_infos); } size_t RegisterContextMinidump_ARM64::GetRegisterCount() { return k_num_regs; } @@ -806,7 +806,7 @@ bool RegisterContextMinidump_ARM64::ReadRegister(const RegisterInfo *reg_info, RegisterValue ®_value) { Status error; reg_value.SetFromMemoryData( - reg_info, (const uint8_t *)&m_regs + reg_info->byte_offset, + *reg_info, (const uint8_t *)&m_regs + reg_info->byte_offset, reg_info->byte_size, lldb::eByteOrderLittle, error); return error.Success(); } diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp index cd2d4fe4fd23..58629a5406f6 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp @@ -18,7 +18,9 @@ #include "lldb/Interpreter/OptionArgParser.h" #include "lldb/Interpreter/OptionGroupBoolean.h" #include "lldb/Interpreter/ScriptInterpreter.h" +#include "lldb/Interpreter/ScriptedMetadata.h" #include "lldb/Target/MemoryRegionInfo.h" +#include "lldb/Target/Queue.h" #include "lldb/Target/RegisterContext.h" #include "lldb/Utility/LLDBLog.h" #include "lldb/Utility/State.h" @@ -40,7 +42,7 @@ static constexpr lldb::ScriptLanguage g_supported_script_languages[] = { bool ScriptedProcess::IsScriptLanguageSupported(lldb::ScriptLanguage language) { llvm::ArrayRef<lldb::ScriptLanguage> supported_languages = - llvm::makeArrayRef(g_supported_script_languages); + llvm::ArrayRef(g_supported_script_languages); return llvm::is_contained(supported_languages, language); } @@ -58,12 +60,11 @@ lldb::ProcessSP ScriptedProcess::CreateInstance(lldb::TargetSP target_sp, !IsScriptLanguageSupported(target_sp->GetDebugger().GetScriptLanguage())) return nullptr; - Status error; - ScriptedProcess::ScriptedProcessInfo scripted_process_info( - target_sp->GetProcessLaunchInfo()); + ScriptedMetadata scripted_metadata(target_sp->GetProcessLaunchInfo()); - auto process_sp = std::make_shared<ScriptedProcess>( - target_sp, listener_sp, scripted_process_info, error); + Status error; + auto process_sp = std::shared_ptr<ScriptedProcess>( + new ScriptedProcess(target_sp, listener_sp, scripted_metadata, error)); if (error.Fail() || !process_sp || !process_sp->m_script_object_sp || !process_sp->m_script_object_sp->IsValid()) { @@ -79,12 +80,11 @@ bool ScriptedProcess::CanDebug(lldb::TargetSP target_sp, return true; } -ScriptedProcess::ScriptedProcess( - lldb::TargetSP target_sp, lldb::ListenerSP listener_sp, - const ScriptedProcess::ScriptedProcessInfo &scripted_process_info, - Status &error) - : Process(target_sp, listener_sp), - m_scripted_process_info(scripted_process_info) { +ScriptedProcess::ScriptedProcess(lldb::TargetSP target_sp, + lldb::ListenerSP listener_sp, + const ScriptedMetadata &scripted_metadata, + Status &error) + : Process(target_sp, listener_sp), m_scripted_metadata(scripted_metadata) { if (!target_sp) { error.SetErrorStringWithFormat("ScriptedProcess::%s () - ERROR: %s", @@ -104,8 +104,8 @@ ScriptedProcess::ScriptedProcess( ExecutionContext exe_ctx(target_sp, /*get_process=*/false); StructuredData::GenericSP object_sp = GetInterface().CreatePluginObject( - m_scripted_process_info.GetClassName().c_str(), exe_ctx, - m_scripted_process_info.GetArgsSP()); + m_scripted_metadata.GetClassName(), exe_ctx, + m_scripted_metadata.GetArgsSP()); if (!object_sp || !object_sp->IsValid()) { error.SetErrorStringWithFormat("ScriptedProcess::%s () - ERROR: %s", @@ -411,7 +411,7 @@ ScriptedProcess::GetLoadedDynamicLibrariesInfos() { StructuredData::ArraySP loaded_images_sp = GetInterface().GetLoadedImages(); if (!loaded_images_sp || !loaded_images_sp->GetSize()) - return GetInterface().ErrorWithMessage<StructuredData::ObjectSP>( + return ScriptedInterface::ErrorWithMessage<StructuredData::ObjectSP>( LLVM_PRETTY_FUNCTION, "No loaded images.", error); ModuleList module_list; @@ -477,7 +477,7 @@ ScriptedProcess::GetLoadedDynamicLibrariesInfos() { }; if (!loaded_images_sp->ForEach(reload_image)) - return GetInterface().ErrorWithMessage<StructuredData::ObjectSP>( + return ScriptedInterface::ErrorWithMessage<StructuredData::ObjectSP>( LLVM_PRETTY_FUNCTION, "Couldn't reload all images.", error); target.ModulesDidLoad(module_list); @@ -485,6 +485,30 @@ ScriptedProcess::GetLoadedDynamicLibrariesInfos() { return loaded_images_sp; } +lldb_private::StructuredData::DictionarySP ScriptedProcess::GetMetadata() { + CheckInterpreterAndScriptObject(); + + StructuredData::DictionarySP metadata_sp = GetInterface().GetMetadata(); + + Status error; + if (!metadata_sp || !metadata_sp->GetSize()) + return ScriptedInterface::ErrorWithMessage<StructuredData::DictionarySP>( + LLVM_PRETTY_FUNCTION, "No metadata.", error); + + return metadata_sp; +} + +void ScriptedProcess::UpdateQueueListIfNeeded() { + CheckInterpreterAndScriptObject(); + for (ThreadSP thread_sp : Threads()) { + if (const char *queue_name = thread_sp->GetQueueName()) { + QueueSP queue_sp = std::make_shared<Queue>( + m_process->shared_from_this(), thread_sp->GetQueueID(), queue_name); + m_queue_list.AddQueue(queue_sp); + } + } +} + ScriptedProcessInterface &ScriptedProcess::GetInterface() const { return m_interpreter->GetScriptedProcessInterface(); } diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/scripted/ScriptedProcess.h b/contrib/llvm-project/lldb/source/Plugins/Process/scripted/ScriptedProcess.h index 7edd95e230a1..6e13e68c4828 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/scripted/ScriptedProcess.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/scripted/ScriptedProcess.h @@ -9,6 +9,7 @@ #ifndef LLDB_SOURCE_PLUGINS_SCRIPTED_PROCESS_H #define LLDB_SOURCE_PLUGINS_SCRIPTED_PROCESS_H +#include "lldb/Interpreter/ScriptedMetadata.h" #include "lldb/Target/Process.h" #include "lldb/Utility/ConstString.h" #include "lldb/Utility/Status.h" @@ -18,24 +19,7 @@ #include <mutex> namespace lldb_private { - class ScriptedProcess : public Process { -protected: - class ScriptedProcessInfo { - public: - ScriptedProcessInfo(const ProcessLaunchInfo &launch_info) { - m_class_name = launch_info.GetScriptedProcessClassName(); - m_args_sp = launch_info.GetScriptedProcessDictionarySP(); - } - - std::string GetClassName() const { return m_class_name; } - StructuredData::DictionarySP GetArgsSP() const { return m_args_sp; } - - private: - std::string m_class_name; - StructuredData::DictionarySP m_args_sp; - }; - public: static lldb::ProcessSP CreateInstance(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp, @@ -50,10 +34,6 @@ public: static llvm::StringRef GetPluginDescriptionStatic(); - ScriptedProcess(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp, - const ScriptedProcess::ScriptedProcessInfo &launch_info, - Status &error); - ~ScriptedProcess() override; bool CanDebug(lldb::TargetSP target_sp, @@ -63,8 +43,6 @@ public: llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); } - SystemRuntime *GetSystemRuntime() override { return nullptr; } - Status DoLoadCore() override; Status DoLaunch(Module *exe_module, ProcessLaunchInfo &launch_info) override; @@ -92,7 +70,14 @@ public: lldb_private::StructuredData::ObjectSP GetLoadedDynamicLibrariesInfos() override; + lldb_private::StructuredData::DictionarySP GetMetadata() override; + + void UpdateQueueListIfNeeded() override; + protected: + ScriptedProcess(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp, + const ScriptedMetadata &scripted_metadata, Status &error); + Status DoStop(); void Clear(); @@ -111,7 +96,7 @@ private: static bool IsScriptLanguageSupported(lldb::ScriptLanguage language); // Member variables. - const ScriptedProcessInfo m_scripted_process_info; + const ScriptedMetadata m_scripted_metadata; lldb_private::ScriptInterpreter *m_interpreter = nullptr; lldb_private::StructuredData::ObjectSP m_script_object_sp = nullptr; //@} diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/scripted/ScriptedThread.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/scripted/ScriptedThread.cpp index e28f66015dd5..ad0d26af8879 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/scripted/ScriptedThread.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/scripted/ScriptedThread.cpp @@ -9,6 +9,7 @@ #include "ScriptedThread.h" #include "Plugins/Process/Utility/RegisterContextThreadMemory.h" +#include "Plugins/Process/Utility/StopInfoMachException.h" #include "lldb/Target/OperatingSystem.h" #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" @@ -17,6 +18,7 @@ #include "lldb/Utility/DataBufferHeap.h" #include "lldb/Utility/LLDBLog.h" #include <memory> +#include <optional> using namespace lldb; using namespace lldb_private; @@ -44,7 +46,7 @@ ScriptedThread::Create(ScriptedProcess &process, llvm::StringRef thread_class_name; if (!script_object) { - llvm::Optional<std::string> class_name = + std::optional<std::string> class_name = process.GetInterface().GetScriptedThreadPluginName(); if (!class_name || class_name->empty()) return llvm::createStringError( @@ -56,8 +58,8 @@ ScriptedThread::Create(ScriptedProcess &process, ExecutionContext exe_ctx(process); StructuredData::GenericSP owned_script_object_sp = scripted_thread_interface->CreatePluginObject( - thread_class_name, exe_ctx, - process.m_scripted_process_info.GetArgsSP(), script_object); + thread_class_name, exe_ctx, process.m_scripted_metadata.GetArgsSP(), + script_object); if (!owned_script_object_sp) return llvm::createStringError(llvm::inconvertibleErrorCode(), @@ -84,7 +86,7 @@ ScriptedThread::~ScriptedThread() { DestroyThread(); } const char *ScriptedThread::GetName() { CheckInterpreterAndScriptObject(); - llvm::Optional<std::string> thread_name = GetInterface()->GetName(); + std::optional<std::string> thread_name = GetInterface()->GetName(); if (!thread_name) return nullptr; return ConstString(thread_name->c_str()).AsCString(); @@ -92,7 +94,7 @@ const char *ScriptedThread::GetName() { const char *ScriptedThread::GetQueueName() { CheckInterpreterAndScriptObject(); - llvm::Optional<std::string> queue_name = GetInterface()->GetQueue(); + std::optional<std::string> queue_name = GetInterface()->GetQueue(); if (!queue_name) return nullptr; return ConstString(queue_name->c_str()).AsCString(); @@ -119,7 +121,7 @@ ScriptedThread::CreateRegisterContextForFrame(StackFrame *frame) { lldb::RegisterContextSP reg_ctx_sp; Status error; - llvm::Optional<std::string> reg_data = GetInterface()->GetRegisterContext(); + std::optional<std::string> reg_data = GetInterface()->GetRegisterContext(); if (!reg_data) return ScriptedInterface::ErrorWithMessage<lldb::RegisterContextSP>( LLVM_PRETTY_FUNCTION, "Failed to get scripted thread registers data.", @@ -163,16 +165,14 @@ bool ScriptedThread::LoadArtificialStackFrames() { llvm::Twine( "StackFrame array size (" + llvm::Twine(arr_size) + llvm::Twine( - ") is greater than maximum autorized for a StackFrameList.")) + ") is greater than maximum authorized for a StackFrameList.")) .str(), error, LLDBLog::Thread); StackFrameListSP frames = GetStackFrameList(); for (size_t idx = 0; idx < arr_size; idx++) { - StructuredData::Dictionary *dict; - if (!arr_sp->GetItemAtIndexAsDictionary(idx, dict) || !dict) return ScriptedInterface::ErrorWithMessage<bool>( LLVM_PRETTY_FUNCTION, @@ -259,11 +259,46 @@ bool ScriptedThread::CalculateStopInfo() { StopInfo::CreateStopReasonWithSignal(*this, signal, description.data()); } break; case lldb::eStopReasonException: { - llvm::StringRef description; - data_dict->GetValueForKeyAsString("desc", description); - +#if defined(__APPLE__) + StructuredData::Dictionary *mach_exception; + if (data_dict->GetValueForKeyAsDictionary("mach_exception", + mach_exception)) { + llvm::StringRef value; + mach_exception->GetValueForKeyAsString("type", value); + auto exc_type = + StopInfoMachException::MachException::ExceptionCode(value.data()); + + if (!exc_type) + return false; + + uint32_t exc_data_size = 0; + llvm::SmallVector<uint64_t, 3> raw_codes; + + StructuredData::Array *exc_rawcodes; + mach_exception->GetValueForKeyAsArray("rawCodes", exc_rawcodes); + if (exc_rawcodes) { + auto fetch_data = [&raw_codes](StructuredData::Object *obj) { + if (!obj) + return false; + raw_codes.push_back(obj->GetIntegerValue()); + return true; + }; + + exc_rawcodes->ForEach(fetch_data); + exc_data_size = raw_codes.size(); + } + + stop_info_sp = StopInfoMachException::CreateStopReasonWithMachException( + *this, *exc_type, exc_data_size, + exc_data_size >= 1 ? raw_codes[0] : 0, + exc_data_size >= 2 ? raw_codes[1] : 0, + exc_data_size >= 3 ? raw_codes[2] : 0); + + break; + } +#endif stop_info_sp = - StopInfo::CreateStopReasonWithException(*this, description.data()); + StopInfo::CreateStopReasonWithException(*this, "EXC_BAD_ACCESS"); } break; default: return ScriptedInterface::ErrorWithMessage<bool>( @@ -298,11 +333,10 @@ std::shared_ptr<DynamicRegisterInfo> ScriptedThread::GetDynamicRegisterInfo() { Status error; if (!reg_info) - return GetInterface() - ->ErrorWithMessage<std::shared_ptr<DynamicRegisterInfo>>( - LLVM_PRETTY_FUNCTION, - "Failed to get scripted thread registers info.", error, - LLDBLog::Thread); + return ScriptedInterface::ErrorWithMessage< + std::shared_ptr<DynamicRegisterInfo>>( + LLVM_PRETTY_FUNCTION, "Failed to get scripted thread registers info.", + error, LLDBLog::Thread); m_register_info_sp = std::make_shared<DynamicRegisterInfo>( *reg_info, m_scripted_process.GetTarget().GetArchitecture()); @@ -310,3 +344,16 @@ std::shared_ptr<DynamicRegisterInfo> ScriptedThread::GetDynamicRegisterInfo() { return m_register_info_sp; } + +StructuredData::ObjectSP ScriptedThread::FetchThreadExtendedInfo() { + CheckInterpreterAndScriptObject(); + + Status error; + StructuredData::ArraySP extended_info_sp = GetInterface()->GetExtendedInfo(); + + if (!extended_info_sp || !extended_info_sp->GetSize()) + return ScriptedInterface::ErrorWithMessage<StructuredData::ObjectSP>( + LLVM_PRETTY_FUNCTION, "No extended information found", error); + + return extended_info_sp; +} diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/scripted/ScriptedThread.h b/contrib/llvm-project/lldb/source/Plugins/Process/scripted/ScriptedThread.h index 959f498edf24..cd224d60ceef 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/scripted/ScriptedThread.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/scripted/ScriptedThread.h @@ -58,6 +58,8 @@ public: void ClearStackFrames() override; + StructuredData::ObjectSP FetchThreadExtendedInfo() override; + private: void CheckInterpreterAndScriptObject() const; lldb::ScriptedThreadInterfaceSP GetInterface() const; diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp index 5b9d1b7c1520..ec0992583145 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp @@ -40,8 +40,8 @@ public: ScriptInterpreterLua &script_interpreter, ActiveIOHandler active_io_handler = eIOHandlerNone) : IOHandlerEditline(debugger, IOHandler::Type::LuaInterpreter, "lua", - ">>> ", "..> ", true, debugger.GetUseColor(), 0, - *this, nullptr), + llvm::StringRef(">>> "), llvm::StringRef("..> "), + true, debugger.GetUseColor(), 0, *this), m_script_interpreter(script_interpreter), m_active_io_handler(active_io_handler) { llvm::cantFail(m_script_interpreter.GetLua().ChangeIO( diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp index ae61736fbbb3..22918561692c 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp @@ -20,7 +20,6 @@ #include "lldb/Utility/Log.h" #include "lldb/Utility/Stream.h" -#include "llvm/ADT/StringSwitch.h" #include "llvm/Support/Casting.h" #include "llvm/Support/ConvertUTF.h" #include "llvm/Support/Errno.h" @@ -923,7 +922,7 @@ const char *PythonException::toCString() const { PythonException::PythonException(const char *caller) { assert(PyErr_Occurred()); - m_exception_type = m_exception = m_traceback = m_repr_bytes = NULL; + m_exception_type = m_exception = m_traceback = m_repr_bytes = nullptr; PyErr_Fetch(&m_exception_type, &m_exception, &m_traceback); PyErr_NormalizeException(&m_exception_type, &m_exception, &m_traceback); PyErr_Clear(); @@ -951,7 +950,7 @@ void PythonException::Restore() { } else { PyErr_SetString(PyExc_Exception, toCString()); } - m_exception_type = m_exception = m_traceback = NULL; + m_exception_type = m_exception = m_traceback = nullptr; } PythonException::~PythonException() { diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h index 76ad47f2907e..365d499bead8 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h @@ -185,22 +185,34 @@ inline const char *py2_const_cast(const char *s) { return s; } enum class PyInitialValue { Invalid, Empty }; +// DOC: https://docs.python.org/3/c-api/arg.html#building-values template <typename T, typename Enable = void> struct PythonFormat; -template <> struct PythonFormat<unsigned long long> { - static constexpr char format = 'K'; - static auto get(unsigned long long value) { return value; } +template <typename T, char F> struct PassthroughFormat { + static constexpr char format = F; + static constexpr T get(T t) { return t; } }; -template <> struct PythonFormat<long long> { - static constexpr char format = 'L'; - static auto get(long long value) { return value; } -}; - -template <> struct PythonFormat<PyObject *> { - static constexpr char format = 'O'; - static auto get(PyObject *value) { return value; } -}; +template <> struct PythonFormat<char *> : PassthroughFormat<char *, 's'> {}; +template <> struct PythonFormat<char> : PassthroughFormat<char, 'b'> {}; +template <> +struct PythonFormat<unsigned char> : PassthroughFormat<unsigned char, 'B'> {}; +template <> struct PythonFormat<short> : PassthroughFormat<short, 'h'> {}; +template <> +struct PythonFormat<unsigned short> : PassthroughFormat<unsigned short, 'H'> {}; +template <> struct PythonFormat<int> : PassthroughFormat<int, 'i'> {}; +template <> +struct PythonFormat<unsigned int> : PassthroughFormat<unsigned int, 'I'> {}; +template <> struct PythonFormat<long> : PassthroughFormat<long, 'l'> {}; +template <> +struct PythonFormat<unsigned long> : PassthroughFormat<unsigned long, 'k'> {}; +template <> +struct PythonFormat<long long> : PassthroughFormat<long long, 'L'> {}; +template <> +struct PythonFormat<unsigned long long> + : PassthroughFormat<unsigned long long, 'K'> {}; +template <> +struct PythonFormat<PyObject *> : PassthroughFormat<PyObject *, 'O'> {}; template <typename T> struct PythonFormat< diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.cpp b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.cpp index 2753847f39f8..3cbd3b5efecc 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.cpp @@ -40,7 +40,7 @@ static char *simple_readline(FILE *stdin, FILE *stdout, const char *prompt) { char *line = readline(prompt); if (!line) { char *ret = (char *)PyMem_RawMalloc(1); - if (ret != NULL) + if (ret != nullptr) *ret = '\0'; return ret; } diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.cpp b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.cpp deleted file mode 100644 index 7c7c5d73680a..000000000000 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.cpp +++ /dev/null @@ -1,48 +0,0 @@ -//===-- SWIGPythonBridge.cpp ----------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "lldb/Host/Config.h" -#include "lldb/lldb-enumerations.h" - -#if LLDB_ENABLE_PYTHON - -// LLDB Python header must be included first -#include "lldb-python.h" - -#include "SWIGPythonBridge.h" - -using namespace lldb; - -namespace lldb_private { - -template <typename T> const char *GetPythonValueFormatString(T t); -template <> const char *GetPythonValueFormatString(char *) { return "s"; } -template <> const char *GetPythonValueFormatString(char) { return "b"; } -template <> const char *GetPythonValueFormatString(unsigned char) { - return "B"; -} -template <> const char *GetPythonValueFormatString(short) { return "h"; } -template <> const char *GetPythonValueFormatString(unsigned short) { - return "H"; -} -template <> const char *GetPythonValueFormatString(int) { return "i"; } -template <> const char *GetPythonValueFormatString(unsigned int) { return "I"; } -template <> const char *GetPythonValueFormatString(long) { return "l"; } -template <> const char *GetPythonValueFormatString(unsigned long) { - return "k"; -} -template <> const char *GetPythonValueFormatString(long long) { return "L"; } -template <> const char *GetPythonValueFormatString(unsigned long long) { - return "K"; -} -template <> const char *GetPythonValueFormatString(float) { return "f"; } -template <> const char *GetPythonValueFormatString(double) { return "d"; } - -} // namespace lldb_private - -#endif // LLDB_ENABLE_PYTHON diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h index 4df235356737..3dc2864f8d42 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h @@ -9,6 +9,7 @@ #ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SWIGPYTHONBRIDGE_H #define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SWIGPYTHONBRIDGE_H +#include <optional> #include <string> #include "lldb/Host/Config.h" @@ -23,28 +24,68 @@ #include "lldb/lldb-types.h" #include "llvm/Support/Error.h" -namespace lldb_private { +namespace lldb { +class SBEvent; +class SBCommandReturnObject; +class SBValue; +class SBStream; +class SBStructuredData; +} // namespace lldb -// GetPythonValueFormatString provides a system independent type safe way to -// convert a variable's type into a python value format. Python value formats -// are defined in terms of builtin C types and could change from system to as -// the underlying typedef for uint* types, size_t, off_t and other values -// change. - -template <typename T> const char *GetPythonValueFormatString(T t); -template <> const char *GetPythonValueFormatString(char *); -template <> const char *GetPythonValueFormatString(char); -template <> const char *GetPythonValueFormatString(unsigned char); -template <> const char *GetPythonValueFormatString(short); -template <> const char *GetPythonValueFormatString(unsigned short); -template <> const char *GetPythonValueFormatString(int); -template <> const char *GetPythonValueFormatString(unsigned int); -template <> const char *GetPythonValueFormatString(long); -template <> const char *GetPythonValueFormatString(unsigned long); -template <> const char *GetPythonValueFormatString(long long); -template <> const char *GetPythonValueFormatString(unsigned long long); -template <> const char *GetPythonValueFormatString(float t); -template <> const char *GetPythonValueFormatString(double t); +namespace lldb_private { +namespace python { + +typedef struct swig_type_info swig_type_info; + +python::PythonObject ToSWIGHelper(void *obj, swig_type_info *info); + +/// A class that automatically clears an SB object when it goes out of scope. +/// Use for cases where the SB object points to a temporary/unowned entity. +template <typename T> class ScopedPythonObject : PythonObject { +public: + ScopedPythonObject(T *sb, swig_type_info *info) + : PythonObject(ToSWIGHelper(sb, info)), m_sb(sb) {} + ~ScopedPythonObject() { + if (m_sb) + *m_sb = T(); + } + ScopedPythonObject(ScopedPythonObject &&rhs) + : PythonObject(std::move(rhs)), m_sb(std::exchange(rhs.m_sb, nullptr)) {} + ScopedPythonObject(const ScopedPythonObject &) = delete; + ScopedPythonObject &operator=(const ScopedPythonObject &) = delete; + ScopedPythonObject &operator=(ScopedPythonObject &&) = delete; + + const PythonObject &obj() const { return *this; } + +private: + T *m_sb; +}; + +PythonObject ToSWIGWrapper(lldb::ValueObjectSP value_sp); +PythonObject ToSWIGWrapper(lldb::TargetSP target_sp); +PythonObject ToSWIGWrapper(lldb::ProcessSP process_sp); +PythonObject ToSWIGWrapper(lldb::ThreadPlanSP thread_plan_sp); +PythonObject ToSWIGWrapper(lldb::BreakpointSP breakpoint_sp); +PythonObject ToSWIGWrapper(const Status &status); +PythonObject ToSWIGWrapper(const StructuredDataImpl &data_impl); +PythonObject ToSWIGWrapper(lldb::ThreadSP thread_sp); +PythonObject ToSWIGWrapper(lldb::StackFrameSP frame_sp); +PythonObject ToSWIGWrapper(lldb::DebuggerSP debugger_sp); +PythonObject ToSWIGWrapper(lldb::WatchpointSP watchpoint_sp); +PythonObject ToSWIGWrapper(lldb::BreakpointLocationSP bp_loc_sp); +PythonObject ToSWIGWrapper(lldb::ExecutionContextRefSP ctx_sp); +PythonObject ToSWIGWrapper(const TypeSummaryOptions &summary_options); +PythonObject ToSWIGWrapper(const SymbolContext &sym_ctx); + +PythonObject ToSWIGWrapper(std::unique_ptr<lldb::SBValue> value_sb); +PythonObject ToSWIGWrapper(std::unique_ptr<lldb::SBStream> stream_sb); +PythonObject ToSWIGWrapper(std::unique_ptr<lldb::SBStructuredData> data_sb); + +python::ScopedPythonObject<lldb::SBCommandReturnObject> +ToSWIGWrapper(CommandReturnObject &cmd_retobj); +python::ScopedPythonObject<lldb::SBEvent> ToSWIGWrapper(Event *event); + +} // namespace python void *LLDBSWIGPython_CastPyObjectToSBData(PyObject *data); void *LLDBSWIGPython_CastPyObjectToSBError(PyObject *data); @@ -55,14 +96,10 @@ void *LLDBSWIGPython_CastPyObjectToSBMemoryRegionInfo(PyObject *data); // Although these are scripting-language specific, their definition depends on // the public API. -python::PythonObject LLDBSwigPythonCreateScriptedProcess( +python::PythonObject LLDBSwigPythonCreateScriptedObject( const char *python_class_name, const char *session_dictionary_name, - const lldb::TargetSP &target_sp, const StructuredDataImpl &args_impl, - std::string &error_string); - -python::PythonObject LLDBSwigPythonCreateScriptedThread( - const char *python_class_name, const char *session_dictionary_name, - const lldb::ProcessSP &process_sp, const StructuredDataImpl &args_impl, + lldb::ExecutionContextRefSP exe_ctx_sp, + const lldb_private::StructuredDataImpl &args_impl, std::string &error_string); llvm::Expected<bool> LLDBSwigPythonBreakpointCallbackFunction( @@ -75,6 +112,10 @@ bool LLDBSwigPythonWatchpointCallbackFunction( const char *python_function_name, const char *session_dictionary_name, const lldb::StackFrameSP &sb_frame, const lldb::WatchpointSP &sb_wp); +bool LLDBSwigPythonFormatterCallbackFunction( + const char *python_function_name, const char *session_dictionary_name, + lldb::TypeImplSP type_impl_sp); + bool LLDBSwigPythonCallTypeScript(const char *python_function_name, const void *session_dictionary, const lldb::ValueObjectSP &valobj_sp, @@ -167,7 +208,7 @@ bool LLDBSWIGPythonRunScriptKeywordProcess(const char *python_function_name, const lldb::ProcessSP &process, std::string &output); -llvm::Optional<std::string> +std::optional<std::string> LLDBSWIGPythonRunScriptKeywordThread(const char *python_function_name, const char *session_dictionary_name, lldb::ThreadSP thread); @@ -177,7 +218,7 @@ bool LLDBSWIGPythonRunScriptKeywordTarget(const char *python_function_name, const lldb::TargetSP &target, std::string &output); -llvm::Optional<std::string> +std::optional<std::string> LLDBSWIGPythonRunScriptKeywordFrame(const char *python_function_name, const char *session_dictionary_name, lldb::StackFrameSP frame); diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp index a21adcfbdbd6..7026815e120d 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp @@ -18,6 +18,7 @@ #include "PythonReadline.h" #include "SWIGPythonBridge.h" #include "ScriptInterpreterPythonImpl.h" +#include "ScriptedPlatformPythonInterface.h" #include "ScriptedProcessPythonInterface.h" #include "lldb/API/SBError.h" @@ -25,9 +26,9 @@ #include "lldb/API/SBValue.h" #include "lldb/Breakpoint/StoppointCallbackContext.h" #include "lldb/Breakpoint/WatchpointOptions.h" -#include "lldb/Core/Communication.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/PluginManager.h" +#include "lldb/Core/ThreadedCommunication.h" #include "lldb/Core/ValueObject.h" #include "lldb/DataFormatters/TypeSummary.h" #include "lldb/Host/FileSystem.h" @@ -50,6 +51,7 @@ #include <cstdlib> #include <memory> #include <mutex> +#include <optional> #include <string> using namespace lldb; @@ -96,7 +98,7 @@ public: // Python's readline is incompatible with libedit being linked into lldb. // Provide a patched version local to the embedded interpreter. bool ReadlinePatched = false; - for (auto *p = PyImport_Inittab; p->name != NULL; p++) { + for (auto *p = PyImport_Inittab; p->name != nullptr; p++) { if (strcmp(p->name, "readline") == 0) { p->initfunc = initlldb_readline; break; @@ -241,7 +243,7 @@ void ScriptInterpreterPython::ComputePythonDir( llvm::sys::path::append(path, LLDB_PYTHON_RELATIVE_LIBDIR); #if defined(_WIN32) - // This will be injected directly through FileSpec.GetDirectory().SetString(), + // This will be injected directly through FileSpec.SetDirectory(), // so we need to normalize manually. std::replace(path.begin(), path.end(), '\\', '/'); #endif @@ -260,7 +262,7 @@ FileSpec ScriptInterpreterPython::GetPythonDir() { #else ComputePythonDir(path); #endif - spec.GetDirectory().SetString(path); + spec.SetDirectory(path); return spec; }(); return g_spec; @@ -412,6 +414,8 @@ ScriptInterpreterPythonImpl::ScriptInterpreterPythonImpl(Debugger &debugger) m_command_thread_state(nullptr) { m_scripted_process_interface_up = std::make_unique<ScriptedProcessPythonInterface>(*this); + m_scripted_platform_interface_up = + std::make_unique<ScriptedPlatformPythonInterface>(*this); m_dictionary_name.append("_dict"); StreamString run_string; @@ -429,7 +433,7 @@ ScriptInterpreterPythonImpl::ScriptInterpreterPythonImpl(Debugger &debugger) // Reloading modules requires a different syntax in Python 2 and Python 3. // This provides a consistent syntax no matter what version of Python. run_string.Clear(); - run_string.Printf("run_one_line (%s, 'from six.moves import reload_module')", + run_string.Printf("run_one_line (%s, 'from importlib import reload as reload_module')", m_dictionary_name.c_str()); PyRun_SimpleString(run_string.GetData()); @@ -1259,8 +1263,6 @@ void ScriptInterpreterPythonImpl::SetWatchpointCommandCallback( wp_options->SetCallback( ScriptInterpreterPythonImpl::WatchpointCallbackFunction, baton_sp); } - - return; } Status ScriptInterpreterPythonImpl::ExportFunctionDefinitionToInterpreter( @@ -1371,7 +1373,7 @@ bool ScriptInterpreterPythonImpl::GenerateScriptAliasFunction( std::string auto_generated_function_name(GenerateUniqueName( "lldb_autogen_python_cmd_alias_func", num_created_functions)); - sstr.Printf("def %s (debugger, args, result, internal_dict):", + sstr.Printf("def %s (debugger, args, exe_ctx, result, internal_dict):", auto_generated_function_name.c_str()); if (!GenerateFunction(sstr.GetData(), user_input).Success()) @@ -1503,50 +1505,29 @@ StructuredData::DictionarySP ScriptInterpreterPythonImpl::OSPlugin_RegisterInfo( StructuredData::ObjectSP os_plugin_object_sp) { Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock); - static char callee_name[] = "get_register_info"; - if (!os_plugin_object_sp) - return StructuredData::DictionarySP(); + return {}; StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric(); if (!generic) - return nullptr; + return {}; PythonObject implementor(PyRefType::Borrowed, (PyObject *)generic->GetValue()); if (!implementor.IsAllocated()) - return StructuredData::DictionarySP(); - - PythonObject pmeth(PyRefType::Owned, - PyObject_GetAttrString(implementor.get(), callee_name)); - - if (PyErr_Occurred()) - PyErr_Clear(); - - if (!pmeth.IsAllocated()) - return StructuredData::DictionarySP(); + return {}; - if (PyCallable_Check(pmeth.get()) == 0) { - if (PyErr_Occurred()) - PyErr_Clear(); + llvm::Expected<PythonObject> expected_py_return = + implementor.CallMethod("get_register_info"); - return StructuredData::DictionarySP(); + if (!expected_py_return) { + llvm::consumeError(expected_py_return.takeError()); + return {}; } - if (PyErr_Occurred()) - PyErr_Clear(); - - // right now we know this function exists and is callable.. - PythonObject py_return( - PyRefType::Owned, - PyObject_CallMethod(implementor.get(), callee_name, nullptr)); + PythonObject py_return = std::move(expected_py_return.get()); - // if it fails, print the error but otherwise go on - if (PyErr_Occurred()) { - PyErr_Print(); - PyErr_Clear(); - } if (py_return.get()) { PythonDictionary result_dict(PyRefType::Borrowed, py_return.get()); return result_dict.CreateStructuredDictionary(); @@ -1557,51 +1538,28 @@ StructuredData::DictionarySP ScriptInterpreterPythonImpl::OSPlugin_RegisterInfo( StructuredData::ArraySP ScriptInterpreterPythonImpl::OSPlugin_ThreadsInfo( StructuredData::ObjectSP os_plugin_object_sp) { Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock); - - static char callee_name[] = "get_thread_info"; - if (!os_plugin_object_sp) - return StructuredData::ArraySP(); + return {}; StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric(); if (!generic) - return nullptr; + return {}; PythonObject implementor(PyRefType::Borrowed, (PyObject *)generic->GetValue()); if (!implementor.IsAllocated()) - return StructuredData::ArraySP(); - - PythonObject pmeth(PyRefType::Owned, - PyObject_GetAttrString(implementor.get(), callee_name)); + return {}; - if (PyErr_Occurred()) - PyErr_Clear(); + llvm::Expected<PythonObject> expected_py_return = + implementor.CallMethod("get_thread_info"); - if (!pmeth.IsAllocated()) - return StructuredData::ArraySP(); - - if (PyCallable_Check(pmeth.get()) == 0) { - if (PyErr_Occurred()) - PyErr_Clear(); - - return StructuredData::ArraySP(); + if (!expected_py_return) { + llvm::consumeError(expected_py_return.takeError()); + return {}; } - if (PyErr_Occurred()) - PyErr_Clear(); - - // right now we know this function exists and is callable.. - PythonObject py_return( - PyRefType::Owned, - PyObject_CallMethod(implementor.get(), callee_name, nullptr)); - - // if it fails, print the error but otherwise go on - if (PyErr_Occurred()) { - PyErr_Print(); - PyErr_Clear(); - } + PythonObject py_return = std::move(expected_py_return.get()); if (py_return.get()) { PythonList result_list(PyRefType::Borrowed, py_return.get()); @@ -1615,56 +1573,33 @@ ScriptInterpreterPythonImpl::OSPlugin_RegisterContextData( StructuredData::ObjectSP os_plugin_object_sp, lldb::tid_t tid) { Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock); - static char callee_name[] = "get_register_data"; - static char *param_format = - const_cast<char *>(GetPythonValueFormatString(tid)); - if (!os_plugin_object_sp) - return StructuredData::StringSP(); + return {}; StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric(); if (!generic) - return nullptr; + return {}; PythonObject implementor(PyRefType::Borrowed, (PyObject *)generic->GetValue()); if (!implementor.IsAllocated()) - return StructuredData::StringSP(); - - PythonObject pmeth(PyRefType::Owned, - PyObject_GetAttrString(implementor.get(), callee_name)); - - if (PyErr_Occurred()) - PyErr_Clear(); + return {}; - if (!pmeth.IsAllocated()) - return StructuredData::StringSP(); + llvm::Expected<PythonObject> expected_py_return = + implementor.CallMethod("get_register_data", tid); - if (PyCallable_Check(pmeth.get()) == 0) { - if (PyErr_Occurred()) - PyErr_Clear(); - return StructuredData::StringSP(); + if (!expected_py_return) { + llvm::consumeError(expected_py_return.takeError()); + return {}; } - if (PyErr_Occurred()) - PyErr_Clear(); - - // right now we know this function exists and is callable.. - PythonObject py_return( - PyRefType::Owned, - PyObject_CallMethod(implementor.get(), callee_name, param_format, tid)); - - // if it fails, print the error but otherwise go on - if (PyErr_Occurred()) { - PyErr_Print(); - PyErr_Clear(); - } + PythonObject py_return = std::move(expected_py_return.get()); if (py_return.get()) { PythonBytes result(PyRefType::Borrowed, py_return.get()); return result.CreateStructuredString(); } - return StructuredData::StringSP(); + return {}; } StructuredData::DictionarySP ScriptInterpreterPythonImpl::OSPlugin_CreateThread( @@ -1672,52 +1607,28 @@ StructuredData::DictionarySP ScriptInterpreterPythonImpl::OSPlugin_CreateThread( lldb::addr_t context) { Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock); - static char callee_name[] = "create_thread"; - std::string param_format; - param_format += GetPythonValueFormatString(tid); - param_format += GetPythonValueFormatString(context); - if (!os_plugin_object_sp) - return StructuredData::DictionarySP(); + return {}; StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric(); if (!generic) - return nullptr; + return {}; PythonObject implementor(PyRefType::Borrowed, (PyObject *)generic->GetValue()); if (!implementor.IsAllocated()) - return StructuredData::DictionarySP(); - - PythonObject pmeth(PyRefType::Owned, - PyObject_GetAttrString(implementor.get(), callee_name)); - - if (PyErr_Occurred()) - PyErr_Clear(); + return {}; - if (!pmeth.IsAllocated()) - return StructuredData::DictionarySP(); + llvm::Expected<PythonObject> expected_py_return = + implementor.CallMethod("create_thread", tid, context); - if (PyCallable_Check(pmeth.get()) == 0) { - if (PyErr_Occurred()) - PyErr_Clear(); - return StructuredData::DictionarySP(); + if (!expected_py_return) { + llvm::consumeError(expected_py_return.takeError()); + return {}; } - if (PyErr_Occurred()) - PyErr_Clear(); - - // right now we know this function exists and is callable.. - PythonObject py_return(PyRefType::Owned, - PyObject_CallMethod(implementor.get(), callee_name, - ¶m_format[0], tid, context)); - - // if it fails, print the error but otherwise go on - if (PyErr_Occurred()) { - PyErr_Print(); - PyErr_Clear(); - } + PythonObject py_return = std::move(expected_py_return.get()); if (py_return.get()) { PythonDictionary result_dict(PyRefType::Borrowed, py_return.get()); @@ -2156,6 +2067,14 @@ bool ScriptInterpreterPythonImpl::GetScriptedSummary( return ret_val; } +bool ScriptInterpreterPythonImpl::FormatterCallbackFunction( + const char *python_function_name, TypeImplSP type_impl_sp) { + Locker py_lock(this, + Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); + return LLDBSwigPythonFormatterCallbackFunction( + python_function_name, m_dictionary_name.c_str(), type_impl_sp); +} + bool ScriptInterpreterPythonImpl::BreakpointCallbackFunction( void *baton, StoppointCallbackContext *context, user_id_t break_id, user_id_t break_loc_id) { @@ -2430,51 +2349,31 @@ ConstString ScriptInterpreterPythonImpl::GetSyntheticTypeName( Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - static char callee_name[] = "get_type_name"; - - ConstString ret_val; - bool got_string = false; - std::string buffer; - if (!implementor_sp) - return ret_val; + return {}; StructuredData::Generic *generic = implementor_sp->GetAsGeneric(); if (!generic) - return ret_val; + return {}; + PythonObject implementor(PyRefType::Borrowed, (PyObject *)generic->GetValue()); if (!implementor.IsAllocated()) - return ret_val; - - PythonObject pmeth(PyRefType::Owned, - PyObject_GetAttrString(implementor.get(), callee_name)); + return {}; - if (PyErr_Occurred()) - PyErr_Clear(); + llvm::Expected<PythonObject> expected_py_return = + implementor.CallMethod("get_type_name"); - if (!pmeth.IsAllocated()) - return ret_val; - - if (PyCallable_Check(pmeth.get()) == 0) { - if (PyErr_Occurred()) - PyErr_Clear(); - return ret_val; + if (!expected_py_return) { + llvm::consumeError(expected_py_return.takeError()); + return {}; } - if (PyErr_Occurred()) - PyErr_Clear(); + PythonObject py_return = std::move(expected_py_return.get()); - // right now we know this function exists and is callable.. - PythonObject py_return( - PyRefType::Owned, - PyObject_CallMethod(implementor.get(), callee_name, nullptr)); - - // if it fails, print the error but otherwise go on - if (PyErr_Occurred()) { - PyErr_Print(); - PyErr_Clear(); - } + ConstString ret_val; + bool got_string = false; + std::string buffer; if (py_return.IsAllocated() && PythonString::Check(py_return.get())) { PythonString py_string(PyRefType::Borrowed, py_return.get()); @@ -2530,7 +2429,7 @@ bool ScriptInterpreterPythonImpl::RunScriptFormatKeyword( Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - if (llvm::Optional<std::string> result = LLDBSWIGPythonRunScriptKeywordThread( + if (std::optional<std::string> result = LLDBSWIGPythonRunScriptKeywordThread( impl_function, m_dictionary_name.c_str(), thread->shared_from_this())) { output = std::move(*result); @@ -2579,7 +2478,7 @@ bool ScriptInterpreterPythonImpl::RunScriptFormatKeyword( Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - if (llvm::Optional<std::string> result = LLDBSWIGPythonRunScriptKeywordFrame( + if (std::optional<std::string> result = LLDBSWIGPythonRunScriptKeywordFrame( impl_function, m_dictionary_name.c_str(), frame->shared_from_this())) { output = std::move(*result); @@ -2888,9 +2787,10 @@ bool ScriptInterpreterPythonImpl::RunScriptBasedCommand( if (!ret_val) error.SetErrorString("unable to execute script function"); - else - error.Clear(); + else if (cmd_retobj.GetStatus() == eReturnStatusFailed) + return false; + error.Clear(); return ret_val; } @@ -2932,9 +2832,10 @@ bool ScriptInterpreterPythonImpl::RunScriptBasedCommand( if (!ret_val) error.SetErrorString("unable to execute script function"); - else - error.Clear(); + else if (cmd_retobj.GetStatus() == eReturnStatusFailed) + return false; + error.Clear(); return ret_val; } @@ -2978,8 +2879,6 @@ bool ScriptInterpreterPythonImpl::GetShortHelpForCommandObject( Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock); - static char callee_name[] = "get_short_help"; - if (!cmd_obj_sp) return false; @@ -2989,34 +2888,15 @@ bool ScriptInterpreterPythonImpl::GetShortHelpForCommandObject( if (!implementor.IsAllocated()) return false; - PythonObject pmeth(PyRefType::Owned, - PyObject_GetAttrString(implementor.get(), callee_name)); - - if (PyErr_Occurred()) - PyErr_Clear(); - - if (!pmeth.IsAllocated()) - return false; + llvm::Expected<PythonObject> expected_py_return = + implementor.CallMethod("get_short_help"); - if (PyCallable_Check(pmeth.get()) == 0) { - if (PyErr_Occurred()) - PyErr_Clear(); + if (!expected_py_return) { + llvm::consumeError(expected_py_return.takeError()); return false; } - if (PyErr_Occurred()) - PyErr_Clear(); - - // Right now we know this function exists and is callable. - PythonObject py_return( - PyRefType::Owned, - PyObject_CallMethod(implementor.get(), callee_name, nullptr)); - - // If it fails, print the error but otherwise go on. - if (PyErr_Occurred()) { - PyErr_Print(); - PyErr_Clear(); - } + PythonObject py_return = std::move(expected_py_return.get()); if (py_return.IsAllocated() && PythonString::Check(py_return.get())) { PythonString py_string(PyRefType::Borrowed, py_return.get()); @@ -3079,13 +2959,10 @@ uint32_t ScriptInterpreterPythonImpl::GetFlagsForCommandObject( bool ScriptInterpreterPythonImpl::GetLongHelpForCommandObject( StructuredData::GenericSP cmd_obj_sp, std::string &dest) { - bool got_string = false; dest.clear(); Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock); - static char callee_name[] = "get_long_help"; - if (!cmd_obj_sp) return false; @@ -3095,36 +2972,17 @@ bool ScriptInterpreterPythonImpl::GetLongHelpForCommandObject( if (!implementor.IsAllocated()) return false; - PythonObject pmeth(PyRefType::Owned, - PyObject_GetAttrString(implementor.get(), callee_name)); - - if (PyErr_Occurred()) - PyErr_Clear(); - - if (!pmeth.IsAllocated()) - return false; - - if (PyCallable_Check(pmeth.get()) == 0) { - if (PyErr_Occurred()) - PyErr_Clear(); + llvm::Expected<PythonObject> expected_py_return = + implementor.CallMethod("get_long_help"); + if (!expected_py_return) { + llvm::consumeError(expected_py_return.takeError()); return false; } - if (PyErr_Occurred()) - PyErr_Clear(); - - // right now we know this function exists and is callable.. - PythonObject py_return( - PyRefType::Owned, - PyObject_CallMethod(implementor.get(), callee_name, nullptr)); - - // if it fails, print the error but otherwise go on - if (PyErr_Occurred()) { - PyErr_Print(); - PyErr_Clear(); - } + PythonObject py_return = std::move(expected_py_return.get()); + bool got_string = false; if (py_return.IsAllocated() && PythonString::Check(py_return.get())) { PythonString str(PyRefType::Borrowed, py_return.get()); llvm::StringRef str_data(str.GetString()); diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h index 3b80c67d201a..f4875bfb8d18 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h @@ -202,6 +202,9 @@ public: const TypeSummaryOptions &options, std::string &retval) override; + bool FormatterCallbackFunction(const char *function_name, + lldb::TypeImplSP type_impl_sp) override; + bool GetDocumentationForItem(const char *item, std::string &dest) override; bool GetShortHelpForCommandObject(StructuredData::GenericSP cmd_obj_sp, diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPlatformPythonInterface.cpp b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPlatformPythonInterface.cpp new file mode 100644 index 000000000000..9fbf50114694 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPlatformPythonInterface.cpp @@ -0,0 +1,108 @@ +//===-- ScriptedPlatformPythonInterface.cpp -------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lldb/Host/Config.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/Status.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 "ScriptedPlatformPythonInterface.h" + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::python; +using Locker = ScriptInterpreterPythonImpl::Locker; + +ScriptedPlatformPythonInterface::ScriptedPlatformPythonInterface( + ScriptInterpreterPythonImpl &interpreter) + : ScriptedPlatformInterface(), ScriptedPythonInterface(interpreter) {} + +StructuredData::GenericSP ScriptedPlatformPythonInterface::CreatePluginObject( + llvm::StringRef class_name, ExecutionContext &exe_ctx, + StructuredData::DictionarySP args_sp, StructuredData::Generic *script_obj) { + if (class_name.empty()) + return {}; + + StructuredDataImpl args_impl(args_sp); + std::string error_string; + + Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN, + Locker::FreeLock); + + lldb::ExecutionContextRefSP exe_ctx_ref_sp = + std::make_shared<ExecutionContextRef>(exe_ctx); + + PythonObject ret_val = LLDBSwigPythonCreateScriptedObject( + class_name.str().c_str(), m_interpreter.GetDictionaryName(), + exe_ctx_ref_sp, args_impl, error_string); + + m_object_instance_sp = + StructuredData::GenericSP(new StructuredPythonObject(std::move(ret_val))); + + return m_object_instance_sp; +} + +StructuredData::DictionarySP ScriptedPlatformPythonInterface::ListProcesses() { + Status error; + StructuredData::DictionarySP dict_sp = + Dispatch<StructuredData::DictionarySP>("list_processes", error); + + if (!dict_sp || !dict_sp->IsValid() || error.Fail()) { + return ScriptedInterface::ErrorWithMessage<StructuredData::DictionarySP>( + LLVM_PRETTY_FUNCTION, + llvm::Twine("Null or invalid object (" + + llvm::Twine(error.AsCString()) + llvm::Twine(").")) + .str(), + error); + } + + return dict_sp; +} + +StructuredData::DictionarySP +ScriptedPlatformPythonInterface::GetProcessInfo(lldb::pid_t pid) { + Status error; + StructuredData::DictionarySP dict_sp = + Dispatch<StructuredData::DictionarySP>("get_process_info", error, pid); + + if (!dict_sp || !dict_sp->IsValid() || error.Fail()) { + return ScriptedInterface::ErrorWithMessage<StructuredData::DictionarySP>( + LLVM_PRETTY_FUNCTION, + llvm::Twine("Null or invalid object (" + + llvm::Twine(error.AsCString()) + llvm::Twine(").")) + .str(), + error); + } + + return dict_sp; +} + +Status ScriptedPlatformPythonInterface::AttachToProcess( + ProcessAttachInfoSP attach_info) { + // FIXME: Pass `attach_info` to method call + return GetStatusFromMethod("attach_to_process"); +} + +Status ScriptedPlatformPythonInterface::LaunchProcess( + ProcessLaunchInfoSP launch_info) { + // FIXME: Pass `launch_info` to method call + return GetStatusFromMethod("launch_process"); +} + +Status ScriptedPlatformPythonInterface::KillProcess(lldb::pid_t pid) { + return GetStatusFromMethod("kill_process", pid); +} + +#endif // LLDB_ENABLE_PYTHON diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPlatformPythonInterface.h b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPlatformPythonInterface.h new file mode 100644 index 000000000000..1e3ad9962325 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPlatformPythonInterface.h @@ -0,0 +1,44 @@ +//===-- ScriptedPlatformPythonInterface.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_SCRIPTEDPLATFORMPYTHONINTERFACE_H +#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDPLATFORMPYTHONINTERFACE_H + +#include "lldb/Host/Config.h" + +#if LLDB_ENABLE_PYTHON + +#include "ScriptedPythonInterface.h" +#include "lldb/Interpreter/ScriptedPlatformInterface.h" + +namespace lldb_private { +class ScriptedPlatformPythonInterface : public ScriptedPlatformInterface, + public ScriptedPythonInterface { +public: + ScriptedPlatformPythonInterface(ScriptInterpreterPythonImpl &interpreter); + + StructuredData::GenericSP + CreatePluginObject(const llvm::StringRef class_name, + ExecutionContext &exe_ctx, + StructuredData::DictionarySP args_sp, + StructuredData::Generic *script_obj = nullptr) override; + + StructuredData::DictionarySP ListProcesses() override; + + StructuredData::DictionarySP GetProcessInfo(lldb::pid_t) override; + + Status AttachToProcess(lldb::ProcessAttachInfoSP attach_info) override; + + Status LaunchProcess(lldb::ProcessLaunchInfoSP launch_info) override; + + Status KillProcess(lldb::pid_t pid) override; +}; +} // namespace lldb_private + +#endif // LLDB_ENABLE_PYTHON +#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDPLATFORMPYTHONINTERFACE_H diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp index 576bf69c9258..6f087e8390ce 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp @@ -8,6 +8,7 @@ #include "lldb/Host/Config.h" #include "lldb/Utility/Log.h" +#include "lldb/Utility/Status.h" #include "lldb/lldb-enumerations.h" #if LLDB_ENABLE_PYTHON @@ -19,6 +20,7 @@ #include "ScriptInterpreterPythonImpl.h" #include "ScriptedProcessPythonInterface.h" #include "ScriptedThreadPythonInterface.h" +#include <optional> using namespace lldb; using namespace lldb_private; @@ -35,16 +37,18 @@ StructuredData::GenericSP ScriptedProcessPythonInterface::CreatePluginObject( if (class_name.empty()) return {}; - TargetSP target_sp = exe_ctx.GetTargetSP(); StructuredDataImpl args_impl(args_sp); std::string error_string; Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock); - PythonObject ret_val = LLDBSwigPythonCreateScriptedProcess( - class_name.str().c_str(), m_interpreter.GetDictionaryName(), target_sp, - args_impl, error_string); + lldb::ExecutionContextRefSP exe_ctx_ref_sp = + std::make_shared<ExecutionContextRef>(exe_ctx); + + PythonObject ret_val = LLDBSwigPythonCreateScriptedObject( + class_name.str().c_str(), m_interpreter.GetDictionaryName(), + exe_ctx_ref_sp, args_impl, error_string); m_object_instance_sp = StructuredData::GenericSP(new StructuredPythonObject(std::move(ret_val))); @@ -74,10 +78,10 @@ Status ScriptedProcessPythonInterface::Stop() { return GetStatusFromMethod("stop"); } -llvm::Optional<MemoryRegionInfo> +std::optional<MemoryRegionInfo> ScriptedProcessPythonInterface::GetMemoryRegionContainingAddress( lldb::addr_t address, Status &error) { - auto mem_region = Dispatch<llvm::Optional<MemoryRegionInfo>>( + auto mem_region = Dispatch<std::optional<MemoryRegionInfo>>( "get_memory_region_containing_address", error, address); if (error.Fail()) { @@ -120,8 +124,15 @@ ScriptedProcessPythonInterface::GetRegistersForThread(lldb::tid_t tid) { lldb::DataExtractorSP ScriptedProcessPythonInterface::ReadMemoryAtAddress( lldb::addr_t address, size_t size, Status &error) { - return Dispatch<lldb::DataExtractorSP>("read_memory_at_address", error, - address, size); + Status py_error; + lldb::DataExtractorSP data_sp = Dispatch<lldb::DataExtractorSP>( + "read_memory_at_address", py_error, address, size, error); + + // If there was an error on the python call, surface it to the user. + if (py_error.Fail()) + error = py_error; + + return data_sp; } StructuredData::ArraySP ScriptedProcessPythonInterface::GetLoadedImages() { @@ -161,7 +172,7 @@ bool ScriptedProcessPythonInterface::IsAlive() { return obj->GetBooleanValue(); } -llvm::Optional<std::string> +std::optional<std::string> ScriptedProcessPythonInterface::GetScriptedThreadPluginName() { Status error; StructuredData::ObjectSP obj = Dispatch("get_scripted_thread_plugin", error); @@ -177,4 +188,15 @@ ScriptedProcessPythonInterface::CreateScriptedThreadInterface() { return std::make_shared<ScriptedThreadPythonInterface>(m_interpreter); } +StructuredData::DictionarySP ScriptedProcessPythonInterface::GetMetadata() { + Status error; + StructuredData::DictionarySP dict = + Dispatch<StructuredData::DictionarySP>("get_process_metadata", error); + + if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, dict, error)) + return {}; + + return dict; +} + #endif diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.h b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.h index 7f458b1dd9bd..6b4ee3021cfa 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.h +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.h @@ -15,6 +15,7 @@ #include "ScriptedPythonInterface.h" #include "lldb/Interpreter/ScriptedProcessInterface.h" +#include <optional> namespace lldb_private { class ScriptedProcessPythonInterface : public ScriptedProcessInterface, @@ -36,7 +37,7 @@ public: Status Stop() override; - llvm::Optional<MemoryRegionInfo> + std::optional<MemoryRegionInfo> GetMemoryRegionContainingAddress(lldb::addr_t address, Status &error) override; @@ -55,7 +56,9 @@ public: bool IsAlive() override; - llvm::Optional<std::string> GetScriptedThreadPluginName() override; + std::optional<std::string> GetScriptedThreadPluginName() override; + + StructuredData::DictionarySP GetMetadata() override; private: lldb::ScriptedThreadInterfaceSP CreateScriptedThreadInterface() override; diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.cpp b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.cpp index d5c527c61a5c..789b39abf587 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.cpp @@ -18,6 +18,7 @@ #include "SWIGPythonBridge.h" #include "ScriptInterpreterPythonImpl.h" #include "ScriptedPythonInterface.h" +#include <optional> using namespace lldb; using namespace lldb_private; @@ -26,14 +27,6 @@ ScriptedPythonInterface::ScriptedPythonInterface( ScriptInterpreterPythonImpl &interpreter) : ScriptedInterface(), m_interpreter(interpreter) {} -Status -ScriptedPythonInterface::GetStatusFromMethod(llvm::StringRef method_name) { - Status error; - Dispatch<Status>(method_name, error); - - return error; -} - template <> StructuredData::ArraySP ScriptedPythonInterface::ExtractValueFromPythonObject<StructuredData::ArraySP>( @@ -55,11 +48,11 @@ Status ScriptedPythonInterface::ExtractValueFromPythonObject<Status>( python::PythonObject &p, Status &error) { if (lldb::SBError *sb_error = reinterpret_cast<lldb::SBError *>( LLDBSWIGPython_CastPyObjectToSBError(p.get()))) - error = m_interpreter.GetStatusFromSBError(*sb_error); + return m_interpreter.GetStatusFromSBError(*sb_error); else error.SetErrorString("Couldn't cast lldb::SBError to lldb::Status."); - return error; + return {}; } template <> @@ -79,9 +72,9 @@ ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::DataExtractorSP>( } template <> -llvm::Optional<MemoryRegionInfo> +std::optional<MemoryRegionInfo> ScriptedPythonInterface::ExtractValueFromPythonObject< - llvm::Optional<MemoryRegionInfo>>(python::PythonObject &p, Status &error) { + std::optional<MemoryRegionInfo>>(python::PythonObject &p, Status &error) { lldb::SBMemoryRegionInfo *sb_mem_reg_info = reinterpret_cast<lldb::SBMemoryRegionInfo *>( diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.h b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.h index 7c2fadc21d42..01dc07b49737 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.h +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.h @@ -9,10 +9,15 @@ #ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDPYTHONINTERFACE_H #define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDPYTHONINTERFACE_H -#include "lldb/Host/Config.h" - #if LLDB_ENABLE_PYTHON +#include <optional> +#include <sstream> +#include <tuple> +#include <type_traits> +#include <utility> + +#include "lldb/Host/Config.h" #include "lldb/Interpreter/ScriptedInterface.h" #include "lldb/Utility/DataBufferHeap.h" @@ -34,7 +39,7 @@ protected: } template <typename T = StructuredData::ObjectSP, typename... Args> - T Dispatch(llvm::StringRef method_name, Status &error, Args... args) { + T Dispatch(llvm::StringRef method_name, Status &error, Args &&...args) { using namespace python; using Locker = ScriptInterpreterPythonImpl::Locker; @@ -56,59 +61,112 @@ protected: return ErrorWithMessage<T>(caller_signature, "Python implementor not allocated.", error); - PythonObject pmeth( - PyRefType::Owned, - PyObject_GetAttrString(implementor.get(), method_name.str().c_str())); + std::tuple<Args...> original_args = std::forward_as_tuple(args...); + auto transformed_args = TransformArgs(original_args); + + llvm::Expected<PythonObject> expected_return_object = + llvm::make_error<llvm::StringError>("Not initialized.", + llvm::inconvertibleErrorCode()); + std::apply( + [&implementor, &method_name, &expected_return_object](auto &&...args) { + llvm::consumeError(expected_return_object.takeError()); + expected_return_object = + implementor.CallMethod(method_name.data(), args...); + }, + transformed_args); + + if (llvm::Error e = expected_return_object.takeError()) { + error.SetErrorString(llvm::toString(std::move(e)).c_str()); + return ErrorWithMessage<T>(caller_signature, + "Python method could not be called.", error); + } - if (PyErr_Occurred()) - PyErr_Clear(); + PythonObject py_return = std::move(expected_return_object.get()); - if (!pmeth.IsAllocated()) - return ErrorWithMessage<T>(caller_signature, - "Python method not allocated.", error); + if (!py_return.IsAllocated()) + return ErrorWithMessage<T>(caller_signature, "Returned object is null.", + error); - if (PyCallable_Check(pmeth.get()) == 0) { - if (PyErr_Occurred()) - PyErr_Clear(); - return ErrorWithMessage<T>(caller_signature, - "Python method not callable.", error); - } + // Now that we called the python method with the transformed arguments, + // we need to interate again over both the original and transformed + // parameter pack, and transform back the parameter that were passed in + // the original parameter pack as references or pointers. + if (sizeof...(Args) > 0) + if (!ReassignPtrsOrRefsArgs(original_args, transformed_args)) + return ErrorWithMessage<T>( + caller_signature, + "Couldn't re-assign reference and pointer arguments.", error); - if (PyErr_Occurred()) - PyErr_Clear(); + return ExtractValueFromPythonObject<T>(py_return, error); + } - // TODO: make `const char *` when removing support for Python 2. - char *format = nullptr; - std::string format_buffer; + template <typename... Args> + Status GetStatusFromMethod(llvm::StringRef method_name, Args &&...args) { + Status error; + Dispatch<Status>(method_name, error, std::forward<Args>(args)...); - if (sizeof...(Args) > 0) { - FormatArgs(format_buffer, args...); - // TODO: make `const char *` when removing support for Python 2. - format = const_cast<char *>(format_buffer.c_str()); - } + return error; + } - // TODO: make `const char *` when removing support for Python 2. - PythonObject py_return( - PyRefType::Owned, - PyObject_CallMethod(implementor.get(), - const_cast<char *>(method_name.data()), format, - args...)); + template <typename T> T Transform(T object) { + // No Transformation for generic usage + return {object}; + } - if (PyErr_Occurred()) { - PyErr_Print(); - PyErr_Clear(); - return ErrorWithMessage<T>(caller_signature, - "Python method could not be called.", error); - } + python::PythonObject Transform(Status arg) { + return python::ToSWIGWrapper(arg); + } - if (!py_return.IsAllocated()) - return ErrorWithMessage<T>(caller_signature, "Returned object is null.", - error); + template <typename T, typename U> + void ReverseTransform(T &original_arg, U transformed_arg, Status &error) { + // If U is not a PythonObject, don't touch it! + return; + } - return ExtractValueFromPythonObject<T>(py_return, error); + template <typename T> + void ReverseTransform(T &original_arg, python::PythonObject transformed_arg, + Status &error) { + original_arg = ExtractValueFromPythonObject<T>(transformed_arg, error); + } + + template <std::size_t... I, typename... Args> + auto TransformTuple(const std::tuple<Args...> &args, + std::index_sequence<I...>) { + return std::make_tuple(Transform(std::get<I>(args))...); + } + + // This will iterate over the Dispatch parameter pack and replace in-place + // every `lldb_private` argument that has a SB counterpart. + template <typename... Args> + auto TransformArgs(const std::tuple<Args...> &args) { + return TransformTuple(args, std::make_index_sequence<sizeof...(Args)>()); + } + + template <typename T, typename U> + void TransformBack(T &original_arg, U transformed_arg, Status &error) { + ReverseTransform(original_arg, transformed_arg, error); } - Status GetStatusFromMethod(llvm::StringRef method_name); + template <std::size_t... I, typename... Ts, typename... Us> + bool ReassignPtrsOrRefsArgs(std::tuple<Ts...> &original_args, + std::tuple<Us...> &transformed_args, + std::index_sequence<I...>) { + Status error; + (TransformBack(std::get<I>(original_args), std::get<I>(transformed_args), + error), + ...); + return error.Success(); + } + + template <typename... Ts, typename... Us> + bool ReassignPtrsOrRefsArgs(std::tuple<Ts...> &original_args, + std::tuple<Us...> &transformed_args) { + if (sizeof...(Ts) != sizeof...(Us)) + return false; + + return ReassignPtrsOrRefsArgs(original_args, transformed_args, + std::make_index_sequence<sizeof...(Ts)>()); + } template <typename T, typename... Args> void FormatArgs(std::string &fmt, T arg, Args... args) const { @@ -117,7 +175,7 @@ protected: } template <typename T> void FormatArgs(std::string &fmt, T arg) const { - fmt += GetPythonValueFormatString(arg); + fmt += python::PythonFormat<T>::format; } void FormatArgs(std::string &fmt) const {} @@ -146,9 +204,9 @@ ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::DataExtractorSP>( python::PythonObject &p, Status &error); template <> -llvm::Optional<MemoryRegionInfo> +std::optional<MemoryRegionInfo> ScriptedPythonInterface::ExtractValueFromPythonObject< - llvm::Optional<MemoryRegionInfo>>(python::PythonObject &p, Status &error); + std::optional<MemoryRegionInfo>>(python::PythonObject &p, Status &error); } // namespace lldb_private diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedThreadPythonInterface.cpp b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedThreadPythonInterface.cpp index 3ff592fb83cd..1b31ed2e5881 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedThreadPythonInterface.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedThreadPythonInterface.cpp @@ -18,6 +18,7 @@ #include "SWIGPythonBridge.h" #include "ScriptInterpreterPythonImpl.h" #include "ScriptedThreadPythonInterface.h" +#include <optional> using namespace lldb; using namespace lldb_private; @@ -34,7 +35,6 @@ StructuredData::GenericSP ScriptedThreadPythonInterface::CreatePluginObject( if (class_name.empty() && !script_obj) return {}; - ProcessSP process_sp = exe_ctx.GetProcessSP(); StructuredDataImpl args_impl(args_sp); std::string error_string; @@ -43,11 +43,13 @@ StructuredData::GenericSP ScriptedThreadPythonInterface::CreatePluginObject( PythonObject ret_val; - if (!script_obj) - ret_val = LLDBSwigPythonCreateScriptedThread( - class_name.str().c_str(), m_interpreter.GetDictionaryName(), process_sp, - args_impl, error_string); - else + if (!script_obj) { + lldb::ExecutionContextRefSP exe_ctx_ref_sp = + std::make_shared<ExecutionContextRef>(exe_ctx); + ret_val = LLDBSwigPythonCreateScriptedObject( + class_name.str().c_str(), m_interpreter.GetDictionaryName(), + exe_ctx_ref_sp, args_impl, error_string); + } else ret_val = PythonObject(PyRefType::Borrowed, static_cast<PyObject *>(script_obj->GetValue())); @@ -70,7 +72,7 @@ lldb::tid_t ScriptedThreadPythonInterface::GetThreadID() { return obj->GetIntegerValue(LLDB_INVALID_THREAD_ID); } -llvm::Optional<std::string> ScriptedThreadPythonInterface::GetName() { +std::optional<std::string> ScriptedThreadPythonInterface::GetName() { Status error; StructuredData::ObjectSP obj = Dispatch("get_name", error); @@ -90,7 +92,7 @@ lldb::StateType ScriptedThreadPythonInterface::GetState() { return static_cast<StateType>(obj->GetIntegerValue(eStateInvalid)); } -llvm::Optional<std::string> ScriptedThreadPythonInterface::GetQueue() { +std::optional<std::string> ScriptedThreadPythonInterface::GetQueue() { Status error; StructuredData::ObjectSP obj = Dispatch("get_queue", error); @@ -133,8 +135,7 @@ StructuredData::DictionarySP ScriptedThreadPythonInterface::GetRegisterInfo() { return dict; } -llvm::Optional<std::string> -ScriptedThreadPythonInterface::GetRegisterContext() { +std::optional<std::string> ScriptedThreadPythonInterface::GetRegisterContext() { Status error; StructuredData::ObjectSP obj = Dispatch("get_register_context", error); @@ -144,4 +145,15 @@ ScriptedThreadPythonInterface::GetRegisterContext() { return obj->GetAsString()->GetValue().str(); } +StructuredData::ArraySP ScriptedThreadPythonInterface::GetExtendedInfo() { + Status error; + StructuredData::ArraySP arr = + Dispatch<StructuredData::ArraySP>("get_extended_info", error); + + if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, arr, error)) + return {}; + + return arr; +} + #endif diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedThreadPythonInterface.h b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedThreadPythonInterface.h index 59bb182ae3f3..eac4941f8814 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedThreadPythonInterface.h +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedThreadPythonInterface.h @@ -15,6 +15,7 @@ #include "ScriptedPythonInterface.h" #include "lldb/Interpreter/ScriptedProcessInterface.h" +#include <optional> namespace lldb_private { class ScriptedThreadPythonInterface : public ScriptedThreadInterface, @@ -29,11 +30,11 @@ public: lldb::tid_t GetThreadID() override; - llvm::Optional<std::string> GetName() override; + std::optional<std::string> GetName() override; lldb::StateType GetState() override; - llvm::Optional<std::string> GetQueue() override; + std::optional<std::string> GetQueue() override; StructuredData::DictionarySP GetStopReason() override; @@ -41,7 +42,9 @@ public: StructuredData::DictionarySP GetRegisterInfo() override; - llvm::Optional<std::string> GetRegisterContext() override; + std::optional<std::string> GetRegisterContext() override; + + StructuredData::ArraySP GetExtendedInfo() override; }; } // namespace lldb_private diff --git a/contrib/llvm-project/lldb/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp b/contrib/llvm-project/lldb/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp index 85366d3f9f4b..95182c97baff 100644 --- a/contrib/llvm-project/lldb/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp @@ -557,7 +557,7 @@ public: } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_enable_option_table); + return llvm::ArrayRef(g_enable_option_table); } StructuredData::DictionarySP BuildConfigurationData(bool enabled) { diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp index b5615c358b95..6d916df65b9d 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp @@ -21,6 +21,7 @@ #include "lldb/Utility/Log.h" #include "lldb/Utility/StreamString.h" #include "llvm/ADT/StringExtras.h" +#include <optional> using namespace lldb; using namespace lldb_private; @@ -294,7 +295,7 @@ size_t SymbolFileBreakpad::ParseBlocksRecursive(Function &func) { ParseInlineOriginRecords(); // A vector of current each level's parent block. For example, when parsing // "INLINE 0 ...", the current level is 0 and its parent block is the - // funciton block at index 0. + // function block at index 0. std::vector<Block *> blocks; Block &block = func.GetBlock(false); block.AddRange(Block::Range(0, func.GetAddressRange().GetByteSize())); @@ -421,12 +422,13 @@ uint32_t SymbolFileBreakpad::ResolveSymbolContext( } void SymbolFileBreakpad::FindFunctions( - ConstString name, const CompilerDeclContext &parent_decl_ctx, - FunctionNameType name_type_mask, bool include_inlines, + const Module::LookupInfo &lookup_info, + const CompilerDeclContext &parent_decl_ctx, bool include_inlines, SymbolContextList &sc_list) { std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); // TODO: Implement this with supported FunctionNameType. + ConstString name = lookup_info.GetLookupName(); for (uint32_t i = 0; i < GetNumCompileUnits(); ++i) { CompUnitSP cu_sp = GetCompileUnitAtIndex(i); FunctionSP func_sp = GetOrCreateFunction(*cu_sp); @@ -468,7 +470,7 @@ void SymbolFileBreakpad::AddSymbols(Symtab &symtab) { const SectionList &list = *module.GetSectionList(); llvm::DenseSet<addr_t> found_symbol_addresses; std::vector<Symbol> symbols; - auto add_symbol = [&](addr_t address, llvm::Optional<addr_t> size, + auto add_symbol = [&](addr_t address, std::optional<addr_t> size, llvm::StringRef name) { address += base; SectionSP section_sp = list.FindSectionContainingFileAddress(address); @@ -494,7 +496,7 @@ void SymbolFileBreakpad::AddSymbols(Symtab &symtab) { for (llvm::StringRef line : lines(Record::Public)) { if (auto record = PublicRecord::parse(line)) - add_symbol(record->Address, llvm::None, record->Name); + add_symbol(record->Address, std::nullopt, record->Name); else LLDB_LOG(log, "Failed to parse: {0}. Skipping record.", line); } @@ -518,7 +520,7 @@ SymbolFileBreakpad::GetParameterStackSize(Symbol &symbol) { "Parameter size unknown."); } -static llvm::Optional<std::pair<llvm::StringRef, llvm::StringRef>> +static std::optional<std::pair<llvm::StringRef, llvm::StringRef>> GetRule(llvm::StringRef &unwind_rules) { // Unwind rules are of the form // register1: expression1 register2: expression2 ... @@ -527,7 +529,7 @@ GetRule(llvm::StringRef &unwind_rules) { llvm::StringRef lhs, rest; std::tie(lhs, rest) = getToken(unwind_rules); if (!lhs.consume_back(":")) - return llvm::None; + return std::nullopt; // Seek forward to the next register: expression pair llvm::StringRef::size_type pos = rest.find(": "); @@ -540,7 +542,7 @@ GetRule(llvm::StringRef &unwind_rules) { // Go back one token to find the end of the current rule. pos = rest.rfind(' ', pos); if (pos == llvm::StringRef::npos) - return llvm::None; + return std::nullopt; llvm::StringRef rhs = rest.take_front(pos); unwind_rules = rest.drop_front(pos); @@ -654,7 +656,7 @@ SymbolFileBreakpad::ParseCFIUnwindPlan(const Bookmark &bookmark, LineIterator It(*m_objfile_sp, Record::StackCFI, bookmark), End(*m_objfile_sp); - llvm::Optional<StackCFIRecord> init_record = StackCFIRecord::parse(*It); + std::optional<StackCFIRecord> init_record = StackCFIRecord::parse(*It); assert(init_record && init_record->Size && "Record already parsed successfully in ParseUnwindData!"); @@ -673,7 +675,7 @@ SymbolFileBreakpad::ParseCFIUnwindPlan(const Bookmark &bookmark, return nullptr; plan_sp->AppendRow(row_sp); for (++It; It != End; ++It) { - llvm::Optional<StackCFIRecord> record = StackCFIRecord::parse(*It); + std::optional<StackCFIRecord> record = StackCFIRecord::parse(*It); if (!record) return nullptr; if (record->Size) @@ -697,7 +699,7 @@ SymbolFileBreakpad::ParseWinUnwindPlan(const Bookmark &bookmark, return nullptr; LineIterator It(*m_objfile_sp, Record::StackWin, bookmark); - llvm::Optional<StackWinRecord> record = StackWinRecord::parse(*It); + std::optional<StackWinRecord> record = StackWinRecord::parse(*It); assert(record && "Record already parsed successfully in ParseUnwindData!"); auto plan_sp = std::make_shared<UnwindPlan>(lldb::eRegisterKindLLDB); @@ -847,7 +849,7 @@ void SymbolFileBreakpad::ParseLineTableAndSupportFiles(CompileUnit &cu, std::vector<std::unique_ptr<LineSequence>> sequences; std::unique_ptr<LineSequence> line_seq_up = LineTable::CreateLineSequenceContainer(); - llvm::Optional<addr_t> next_addr; + std::optional<addr_t> next_addr; auto finish_sequence = [&]() { LineTable::AppendLineEntryToSequence( line_seq_up.get(), *next_addr, /*line=*/0, /*column=*/0, diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h index 639d2e272adf..6d9336966517 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h @@ -15,6 +15,7 @@ #include "lldb/Symbol/PostfixExpression.h" #include "lldb/Symbol/SymbolFile.h" #include "lldb/Symbol/UnwindPlan.h" +#include <optional> namespace lldb_private { @@ -92,10 +93,10 @@ public: return 0; } Type *ResolveTypeUID(lldb::user_id_t type_uid) override { return nullptr; } - llvm::Optional<ArrayInfo> GetDynamicArrayInfoForUID( + std::optional<ArrayInfo> GetDynamicArrayInfoForUID( lldb::user_id_t type_uid, const lldb_private::ExecutionContext *exe_ctx) override { - return llvm::None; + return std::nullopt; } bool CompleteType(CompilerType &compiler_type) override { return false; } @@ -110,9 +111,8 @@ public: void GetTypes(SymbolContextScope *sc_scope, lldb::TypeClass type_mask, TypeList &type_list) override {} - void FindFunctions(ConstString name, + void FindFunctions(const Module::LookupInfo &lookup_info, const CompilerDeclContext &parent_decl_ctx, - lldb::FunctionNameType name_type_mask, bool include_inlines, SymbolContextList &sc_list) override; void FindFunctions(const RegularExpression ®ex, bool include_inlines, @@ -127,7 +127,7 @@ public: llvm::DenseSet<SymbolFile *> &searched_symbol_files, TypeMap &types) override; - llvm::Expected<TypeSystem &> + llvm::Expected<lldb::TypeSystemSP> GetTypeSystemForLanguage(lldb::LanguageType language) override { return llvm::make_error<llvm::StringError>( "SymbolFileBreakpad does not support GetTypeSystemForLanguage", @@ -202,7 +202,7 @@ private: } Bookmark bookmark; - llvm::Optional<FileSpecList> support_files; + std::optional<FileSpecList> support_files; std::unique_ptr<LineTable> line_table_up; }; @@ -227,16 +227,16 @@ private: using CompUnitMap = RangeDataVector<lldb::addr_t, lldb::addr_t, CompUnitData>; - llvm::Optional<std::vector<FileSpec>> m_files; - llvm::Optional<CompUnitMap> m_cu_data; - llvm::Optional<std::vector<llvm::StringRef>> m_inline_origins; + std::optional<std::vector<FileSpec>> m_files; + std::optional<CompUnitMap> m_cu_data; + std::optional<std::vector<llvm::StringRef>> m_inline_origins; using UnwindMap = RangeDataVector<lldb::addr_t, lldb::addr_t, Bookmark>; struct UnwindData { UnwindMap cfi; UnwindMap win; }; - llvm::Optional<UnwindData> m_unwind_data; + std::optional<UnwindData> m_unwind_data; llvm::BumpPtrAllocator m_allocator; }; diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp index 4877169b3213..f6a49ba6141a 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp @@ -180,12 +180,13 @@ void AppleDWARFIndex::GetNamespaces( } void AppleDWARFIndex::GetFunctions( - ConstString name, SymbolFileDWARF &dwarf, - const CompilerDeclContext &parent_decl_ctx, uint32_t name_type_mask, + const Module::LookupInfo &lookup_info, SymbolFileDWARF &dwarf, + const CompilerDeclContext &parent_decl_ctx, llvm::function_ref<bool(DWARFDIE die)> callback) { + ConstString name = lookup_info.GetLookupName(); m_apple_names_up->FindByName(name.GetStringRef(), [&](DIERef die_ref) { - return ProcessFunctionDIE(name.GetStringRef(), die_ref, dwarf, - parent_decl_ctx, name_type_mask, callback); + return ProcessFunctionDIE(lookup_info, die_ref, dwarf, parent_decl_ctx, + callback); }); } diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.h index ef3cb5dee035..3a5b8eef9cf4 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.h @@ -52,9 +52,9 @@ public: llvm::function_ref<bool(DWARFDIE die)> callback) override; void GetNamespaces(ConstString name, llvm::function_ref<bool(DWARFDIE die)> callback) override; - void GetFunctions(ConstString name, SymbolFileDWARF &dwarf, + void GetFunctions(const Module::LookupInfo &lookup_info, + SymbolFileDWARF &dwarf, const CompilerDeclContext &parent_decl_ctx, - uint32_t name_type_mask, llvm::function_ref<bool(DWARFDIE die)> callback) override; void GetFunctions(const RegularExpression ®ex, llvm::function_ref<bool(DWARFDIE die)> callback) override; diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DIERef.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DIERef.cpp index 25cb368763c1..53e154fd651d 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DIERef.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DIERef.cpp @@ -10,6 +10,7 @@ #include "lldb/Utility/DataEncoder.h" #include "lldb/Utility/DataExtractor.h" #include "llvm/Support/Format.h" +#include <optional> using namespace lldb; using namespace lldb_private; @@ -26,8 +27,8 @@ constexpr uint32_t k_dwo_num_mask = 0x3FFFFFFF; constexpr uint32_t k_dwo_num_valid_bitmask = (1u << 30); constexpr uint32_t k_section_bitmask = (1u << 31); -llvm::Optional<DIERef> DIERef::Decode(const DataExtractor &data, - lldb::offset_t *offset_ptr) { +std::optional<DIERef> DIERef::Decode(const DataExtractor &data, + lldb::offset_t *offset_ptr) { const uint32_t bitfield_storage = data.GetU32(offset_ptr); uint32_t dwo_num = bitfield_storage & k_dwo_num_mask; bool dwo_num_valid = (bitfield_storage & (k_dwo_num_valid_bitmask)) != 0; @@ -36,11 +37,11 @@ llvm::Optional<DIERef> DIERef::Decode(const DataExtractor &data, // it will return 0 dw_offset_t die_offset = data.GetU32(offset_ptr); if (die_offset == 0) - return llvm::None; + return std::nullopt; if (dwo_num_valid) return DIERef(dwo_num, section, die_offset); else - return DIERef(llvm::None, section, die_offset); + return DIERef(std::nullopt, section, die_offset); } void DIERef::Encode(DataEncoder &encoder) const { diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DIERef.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DIERef.h index 4370039d1a8d..af7e5e950840 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DIERef.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DIERef.h @@ -10,9 +10,9 @@ #define LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DIEREF_H #include "lldb/Core/dwarf.h" -#include "llvm/ADT/Optional.h" #include "llvm/Support/FormatProviders.h" #include <cassert> +#include <optional> #include <vector> /// Identifies a DWARF debug info entry within a given Module. It contains three @@ -27,17 +27,17 @@ class DIERef { public: enum Section : uint8_t { DebugInfo, DebugTypes }; - DIERef(llvm::Optional<uint32_t> dwo_num, Section section, + DIERef(std::optional<uint32_t> dwo_num, Section section, dw_offset_t die_offset) : m_dwo_num(dwo_num.value_or(0)), m_dwo_num_valid(bool(dwo_num)), m_section(section), m_die_offset(die_offset) { assert(this->dwo_num() == dwo_num && "Dwo number out of range?"); } - llvm::Optional<uint32_t> dwo_num() const { + std::optional<uint32_t> dwo_num() const { if (m_dwo_num_valid) return m_dwo_num; - return llvm::None; + return std::nullopt; } Section section() const { return static_cast<Section>(m_section); } @@ -71,10 +71,10 @@ public: /// from that gets updated as data gets decoded. /// /// \return - /// Returns a valid DIERef if decoding succeeded, llvm::None if there was + /// Returns a valid DIERef if decoding succeeded, std::nullopt if there was /// unsufficient or invalid values that were decoded. - static llvm::Optional<DIERef> Decode(const lldb_private::DataExtractor &data, - lldb::offset_t *offset_ptr); + static std::optional<DIERef> Decode(const lldb_private::DataExtractor &data, + lldb::offset_t *offset_ptr); /// Encode this object into a data encoder object. /// @@ -91,7 +91,7 @@ private: uint32_t m_section : 1; dw_offset_t m_die_offset; }; -static_assert(sizeof(DIERef) == 8, ""); +static_assert(sizeof(DIERef) == 8); typedef std::vector<DIERef> DIEArray; diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.cpp index 364d34c73375..dbece346b99a 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.cpp @@ -13,17 +13,18 @@ #include "lldb/Core/ValueObject.h" #include "lldb/Symbol/SymbolFile.h" #include "lldb/Target/StackFrame.h" +#include <optional> using namespace lldb; using namespace lldb_private; using namespace lldb_private::dwarf; -llvm::Optional<SymbolFile::ArrayInfo> +std::optional<SymbolFile::ArrayInfo> DWARFASTParser::ParseChildArrayInfo(const DWARFDIE &parent_die, const ExecutionContext *exe_ctx) { SymbolFile::ArrayInfo array_info; if (!parent_die) - return llvm::None; + return std::nullopt; for (DWARFDIE die : parent_die.children()) { const dw_tag_t tag = die.Tag(); diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h index 97b0ea1874e1..18825ae060b1 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h @@ -15,6 +15,7 @@ #include "lldb/Symbol/CompilerDecl.h" #include "lldb/Symbol/CompilerDeclContext.h" #include "lldb/lldb-enumerations.h" +#include <optional> class DWARFDIE; namespace lldb_private { @@ -31,6 +32,9 @@ public: const DWARFDIE &die, bool *type_is_new_ptr) = 0; + virtual lldb_private::ConstString + ConstructDemangledNameFromDWARF(const DWARFDIE &die) = 0; + virtual lldb_private::Function * ParseFunctionFromDWARF(lldb_private::CompileUnit &comp_unit, const DWARFDIE &die, @@ -52,7 +56,10 @@ public: virtual void EnsureAllDIEsInDeclContextHaveBeenParsed( lldb_private::CompilerDeclContext decl_context) = 0; - static llvm::Optional<lldb_private::SymbolFile::ArrayInfo> + virtual lldb_private::ConstString + GetDIEClassTemplateParams(const DWARFDIE &die) = 0; + + static std::optional<lldb_private::SymbolFile::ArrayInfo> ParseChildArrayInfo(const DWARFDIE &parent_die, const lldb_private::ExecutionContext *exe_ctx = nullptr); diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index 10dc8d1fb7c3..56bd089b86a1 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -36,15 +36,16 @@ #include "lldb/Utility/Log.h" #include "lldb/Utility/StreamString.h" -#include "llvm/Demangle/Demangle.h" - #include "clang/AST/CXXInheritance.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" +#include "clang/AST/Type.h" +#include "llvm/Demangle/Demangle.h" #include <map> #include <memory> +#include <optional> #include <vector> //#define ENABLE_DEBUG_PRINTF // COMMENT OUT THIS LINE PRIOR TO CHECKIN @@ -197,14 +198,11 @@ TypeSP DWARFASTParserClang::ParseTypeFromClangModule(const SymbolContext &sc, GetClangASTImporter().RequireCompleteType(ClangUtil::GetQualType(type)); SymbolFileDWARF *dwarf = die.GetDWARF(); - TypeSP type_sp(new Type(die.GetID(), dwarf, pcm_type_sp->GetName(), - pcm_type_sp->GetByteSize(nullptr), nullptr, - LLDB_INVALID_UID, Type::eEncodingInvalid, - &pcm_type_sp->GetDeclaration(), type, - Type::ResolveState::Forward, - TypePayloadClang(GetOwningClangModule(die)))); - - dwarf->GetTypeList().Insert(type_sp); + auto type_sp = dwarf->MakeType( + die.GetID(), pcm_type_sp->GetName(), pcm_type_sp->GetByteSize(nullptr), + nullptr, LLDB_INVALID_UID, Type::eEncodingInvalid, + &pcm_type_sp->GetDeclaration(), type, Type::ResolveState::Forward, + TypePayloadClang(GetOwningClangModule(die))); dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); clang::TagDecl *tag_decl = TypeSystemClang::GetAsTagDecl(type); if (tag_decl) { @@ -223,30 +221,10 @@ static void ForcefullyCompleteType(CompilerType type) { lldbassert(started && "Unable to start a class type definition."); TypeSystemClang::CompleteTagDeclarationDefinition(type); const clang::TagDecl *td = ClangUtil::GetAsTagDecl(type); - auto &ts = llvm::cast<TypeSystemClang>(*type.GetTypeSystem()); - ts.GetMetadata(td)->SetIsForcefullyCompleted(); -} - -/// Complete a type from debug info, or mark it as forcefully completed if -/// there is no definition of the type in the current Module. Call this function -/// in contexts where the usual C++ rules require a type to be complete (base -/// class, member, etc.). -static void RequireCompleteType(CompilerType type) { - // Technically, enums can be incomplete too, but we don't handle those as they - // are emitted even under -flimit-debug-info. - if (!TypeSystemClang::IsCXXClassType(type)) - return; - - if (type.GetCompleteType()) - return; - - // No complete definition in this module. Mark the class as complete to - // satisfy local ast invariants, but make a note of the fact that - // it is not _really_ complete so we can later search for a definition in a - // different module. - // Since we provide layout assistance, layouts of types containing this class - // will be correct even if we are not able to find the definition elsewhere. - ForcefullyCompleteType(type); + auto ts_sp = type.GetTypeSystem(); + auto ts = ts_sp.dyn_cast_or_null<TypeSystemClang>(); + if (ts) + ts->SetDeclIsForcefullyCompleted(td); } /// This function serves a similar purpose as RequireCompleteType above, but it @@ -277,8 +255,8 @@ static void PrepareContextToReceiveMembers(TypeSystemClang &ast, if (ast_importer.RequireCompleteType(qual_type)) return; die.GetDWARF()->GetObjectFile()->GetModule()->ReportError( - "Unable to complete the Decl context for DIE '%s' at offset " - "0x%8.8x.\nPlease file a bug report.", + "Unable to complete the Decl context for DIE {0} at offset " + "{1:x16}.\nPlease file a bug report.", type_name_cstr ? type_name_cstr : "", die.GetOffset()); } @@ -412,6 +390,12 @@ ParsedDWARFTypeAttributes::ParsedDWARFTypeAttributes(const DWARFDIE &die) { case DW_AT_export_symbols: exports_symbols = form_value.Boolean(); break; + case DW_AT_rvalue_reference: + ref_qual = clang::RQ_RValue; + break; + case DW_AT_reference: + ref_qual = clang::RQ_LValue; + break; } } } @@ -442,7 +426,8 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc, dwarf->GetObjectFile()->GetModule()->LogMessage( log, "DWARFASTParserClang::ParseTypeFromDWARF " - "(die = 0x%8.8x, decl_ctx = %p (die 0x%8.8x)) %s name = '%s')", + "(die = {0:x16}, decl_ctx = {1:p} (die " + "{2:x16})) {3} name = '{4}')", die.GetOffset(), static_cast<void *>(context), context_die.GetOffset(), die.GetTagAsCString(), die.GetName()); } @@ -519,7 +504,8 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc, } default: dwarf->GetObjectFile()->GetModule()->ReportError( - "{0x%8.8x}: unhandled type tag 0x%4.4x (%s), please file a bug and " + "[{0:x16}]: unhandled type tag {1:x4} ({2}), " + "please file a bug and " "attach the file at the start of this error message", die.GetOffset(), tag, DW_TAG_value_to_name(tag)); break; @@ -608,7 +594,7 @@ DWARFASTParserClang::ParseTypeModifier(const SymbolContext &sc, } // Fall through to base type below in case we can handle the type // there... - LLVM_FALLTHROUGH; + [[fallthrough]]; case DW_TAG_base_type: resolve_state = Type::ResolveState::Full; @@ -688,7 +674,7 @@ DWARFASTParserClang::ParseTypeModifier(const SymbolContext &sc, if (log) dwarf->GetObjectFile()->GetModule()->LogMessage( log, - "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' " + "SymbolFileDWARF::ParseType (die = {0:x16}) {1} '{2}' " "is Objective-C 'id' built-in type.", die.GetOffset(), die.GetTagAsCString(), die.GetName()); clang_type = m_ast.GetBasicType(eBasicTypeObjCID); @@ -699,7 +685,7 @@ DWARFASTParserClang::ParseTypeModifier(const SymbolContext &sc, if (log) dwarf->GetObjectFile()->GetModule()->LogMessage( log, - "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' " + "SymbolFileDWARF::ParseType (die = {0:x16}) {1} '{2}' " "is Objective-C 'Class' built-in type.", die.GetOffset(), die.GetTagAsCString(), die.GetName()); clang_type = m_ast.GetBasicType(eBasicTypeObjCClass); @@ -710,7 +696,7 @@ DWARFASTParserClang::ParseTypeModifier(const SymbolContext &sc, if (log) dwarf->GetObjectFile()->GetModule()->LogMessage( log, - "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' " + "SymbolFileDWARF::ParseType (die = {0:x16}) {1} '{2}' " "is Objective-C 'selector' built-in type.", die.GetOffset(), die.GetTagAsCString(), die.GetName()); clang_type = m_ast.GetBasicType(eBasicTypeObjCSel); @@ -731,8 +717,8 @@ DWARFASTParserClang::ParseTypeModifier(const SymbolContext &sc, if (log) dwarf->GetObjectFile()->GetModule()->LogMessage( log, - "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s " - "'%s' is 'objc_object*', which we overrode to " + "SymbolFileDWARF::ParseType (die = {0:x16}) {1} " + "'{2}' is 'objc_object*', which we overrode to " "'id'.", die.GetOffset(), die.GetTagAsCString(), die.GetName()); clang_type = m_ast.GetBasicType(eBasicTypeObjCID); @@ -745,8 +731,8 @@ DWARFASTParserClang::ParseTypeModifier(const SymbolContext &sc, } } - type_sp = std::make_shared<Type>( - die.GetID(), dwarf, attrs.name, attrs.byte_size, nullptr, + type_sp = dwarf->MakeType( + die.GetID(), attrs.name, attrs.byte_size, nullptr, dwarf->GetUID(attrs.type.Reference()), encoding_data_type, &attrs.decl, clang_type, resolve_state, TypePayloadClang(GetOwningClangModule(die))); @@ -754,6 +740,18 @@ DWARFASTParserClang::ParseTypeModifier(const SymbolContext &sc, return type_sp; } +ConstString +DWARFASTParserClang::GetDIEClassTemplateParams(const DWARFDIE &die) { + if (llvm::StringRef(die.GetName()).contains("<")) + return ConstString(); + + TypeSystemClang::TemplateParameterInfos template_param_infos; + if (ParseTemplateParameterInfos(die, template_param_infos)) { + return ConstString(m_ast.PrintTemplateParams(template_param_infos)); + } + return ConstString(); +} + TypeSP DWARFASTParserClang::ParseEnum(const SymbolContext &sc, const DWARFDIE &die, ParsedDWARFTypeAttributes &attrs) { @@ -767,17 +765,14 @@ TypeSP DWARFASTParserClang::ParseEnum(const SymbolContext &sc, if (type_sp) return type_sp; - DWARFDeclContext die_decl_ctx = SymbolFileDWARF::GetDWARFDeclContext(die); - - type_sp = dwarf->FindDefinitionTypeForDWARFDeclContext(die_decl_ctx); + type_sp = dwarf->FindDefinitionTypeForDWARFDeclContext(die); if (!type_sp) { SymbolFileDWARFDebugMap *debug_map_symfile = dwarf->GetDebugMapSymfile(); if (debug_map_symfile) { // We weren't able to find a full declaration in this DWARF, // see if we have a declaration anywhere else... - type_sp = debug_map_symfile->FindDefinitionTypeForDWARFDeclContext( - die_decl_ctx); + type_sp = debug_map_symfile->FindDefinitionTypeForDWARFDeclContext(die); } } @@ -785,8 +780,8 @@ TypeSP DWARFASTParserClang::ParseEnum(const SymbolContext &sc, if (log) { dwarf->GetObjectFile()->GetModule()->LogMessage( log, - "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a " - "forward declaration, complete type is 0x%8.8" PRIx64, + "SymbolFileDWARF({0:p}) - {1:x16}}: {2} type \"{3}\" is a " + "forward declaration, complete type is {4:x8}", static_cast<void *>(this), die.GetOffset(), DW_TAG_value_to_name(tag), attrs.name.GetCString(), type_sp->GetID()); @@ -808,8 +803,9 @@ TypeSP DWARFASTParserClang::ParseEnum(const SymbolContext &sc, CompilerType enumerator_clang_type; CompilerType clang_type; - clang_type.SetCompilerType( - &m_ast, dwarf->GetForwardDeclDieToClangType().lookup(die.GetDIE())); + clang_type = + CompilerType(m_ast.weak_from_this(), + dwarf->GetForwardDeclDieToClangType().lookup(die.GetDIE())); if (!clang_type) { if (attrs.type.IsValid()) { Type *enumerator_type = @@ -838,11 +834,11 @@ TypeSP DWARFASTParserClang::ParseEnum(const SymbolContext &sc, LinkDeclContextToDIE(TypeSystemClang::GetDeclContextForType(clang_type), die); - type_sp = std::make_shared<Type>( - die.GetID(), dwarf, attrs.name, attrs.byte_size, nullptr, - dwarf->GetUID(attrs.type.Reference()), Type::eEncodingIsUID, &attrs.decl, - clang_type, Type::ResolveState::Forward, - TypePayloadClang(GetOwningClangModule(die))); + type_sp = dwarf->MakeType(die.GetID(), attrs.name, attrs.byte_size, nullptr, + dwarf->GetUID(attrs.type.Reference()), + Type::eEncodingIsUID, &attrs.decl, clang_type, + Type::ResolveState::Forward, + TypePayloadClang(GetOwningClangModule(die))); if (TypeSystemClang::StartTagDeclarationDefinition(clang_type)) { if (die.HasChildren()) { @@ -854,7 +850,7 @@ TypeSP DWARFASTParserClang::ParseEnum(const SymbolContext &sc, TypeSystemClang::CompleteTagDeclarationDefinition(clang_type); } else { dwarf->GetObjectFile()->GetModule()->ReportError( - "DWARF DIE at 0x%8.8x named \"%s\" was not able to start its " + "DWARF DIE at {0:x16} named \"{1}\" was not able to start its " "definition.\nPlease file a bug and attach the file at the " "start of this error message", die.GetOffset(), attrs.name.GetCString()); @@ -974,9 +970,10 @@ TypeSP DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die, // clang_type will get the function prototype clang type after this // call - CompilerType clang_type = m_ast.CreateFunctionType( - return_clang_type, function_param_types.data(), - function_param_types.size(), is_variadic, type_quals, calling_convention); + CompilerType clang_type = + m_ast.CreateFunctionType(return_clang_type, function_param_types.data(), + function_param_types.size(), is_variadic, + type_quals, calling_convention, attrs.ref_qual); if (attrs.name) { bool type_handled = false; @@ -1016,7 +1013,7 @@ TypeSP DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die, m_ast.SetMetadataAsUserID(objc_method_decl, die.GetID()); } else { dwarf->GetObjectFile()->GetModule()->ReportError( - "{0x%8.8x}: invalid Objective-C method 0x%4.4x (%s), " + "[{0:x16}]: invalid Objective-C method {1:x4} ({2}), " "please file a bug and attach the file at the start of " "this error message", die.GetOffset(), tag, DW_TAG_value_to_name(tag)); @@ -1069,7 +1066,7 @@ TypeSP DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die, LinkDeclContextToDIE(spec_clang_decl_ctx, die); } else { dwarf->GetObjectFile()->GetModule()->ReportWarning( - "0x%8.8" PRIx64 ": DW_AT_specification(0x%8.8x" + "{0:x8}: DW_AT_specification({1:x16}" ") has no decl\n", die.GetID(), spec_die.GetOffset()); } @@ -1088,7 +1085,7 @@ TypeSP DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die, LinkDeclContextToDIE(abs_clang_decl_ctx, die); } else { dwarf->GetObjectFile()->GetModule()->ReportWarning( - "0x%8.8" PRIx64 ": DW_AT_abstract_origin(0x%8.8x" + "{0:x8}: DW_AT_abstract_origin({1:x16}" ") has no decl\n", die.GetID(), abs_die.GetOffset()); } @@ -1248,6 +1245,20 @@ TypeSP 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); if (!function_param_decls.empty()) { @@ -1273,13 +1284,14 @@ TypeSP DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die, } } } - return std::make_shared<Type>( - die.GetID(), dwarf, attrs.name, llvm::None, nullptr, LLDB_INVALID_UID, + return dwarf->MakeType( + die.GetID(), attrs.name, std::nullopt, nullptr, LLDB_INVALID_UID, Type::eEncodingIsUID, &attrs.decl, clang_type, Type::ResolveState::Full); } -TypeSP DWARFASTParserClang::ParseArrayType(const DWARFDIE &die, - ParsedDWARFTypeAttributes &attrs) { +TypeSP +DWARFASTParserClang::ParseArrayType(const DWARFDIE &die, + const ParsedDWARFTypeAttributes &attrs) { SymbolFileDWARF *dwarf = die.GetDWARF(); DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(), @@ -1291,18 +1303,19 @@ TypeSP DWARFASTParserClang::ParseArrayType(const DWARFDIE &die, if (!element_type) return nullptr; - llvm::Optional<SymbolFile::ArrayInfo> array_info = ParseChildArrayInfo(die); + std::optional<SymbolFile::ArrayInfo> array_info = ParseChildArrayInfo(die); + uint32_t byte_stride = attrs.byte_stride; + uint32_t bit_stride = attrs.bit_stride; if (array_info) { - attrs.byte_stride = array_info->byte_stride; - attrs.bit_stride = array_info->bit_stride; + byte_stride = array_info->byte_stride; + bit_stride = array_info->bit_stride; } - if (attrs.byte_stride == 0 && attrs.bit_stride == 0) - attrs.byte_stride = element_type->GetByteSize(nullptr).value_or(0); + if (byte_stride == 0 && bit_stride == 0) + byte_stride = element_type->GetByteSize(nullptr).value_or(0); CompilerType array_element_type = element_type->GetForwardCompilerType(); - RequireCompleteType(array_element_type); + TypeSystemClang::RequireCompleteType(array_element_type); - uint64_t array_element_bit_stride = - attrs.byte_stride * 8 + attrs.bit_stride; + uint64_t array_element_bit_stride = byte_stride * 8 + bit_stride; CompilerType clang_type; if (array_info && array_info->element_orders.size() > 0) { uint64_t num_elements = 0; @@ -1321,10 +1334,10 @@ TypeSP DWARFASTParserClang::ParseArrayType(const DWARFDIE &die, m_ast.CreateArrayType(array_element_type, 0, attrs.is_vector); } ConstString empty_name; - TypeSP type_sp = std::make_shared<Type>( - die.GetID(), dwarf, empty_name, array_element_bit_stride / 8, nullptr, - dwarf->GetUID(type_die), Type::eEncodingIsUID, &attrs.decl, clang_type, - Type::ResolveState::Full); + TypeSP type_sp = + dwarf->MakeType(die.GetID(), empty_name, array_element_bit_stride / 8, + nullptr, dwarf->GetUID(type_die), Type::eEncodingIsUID, + &attrs.decl, clang_type, Type::ResolveState::Full); type_sp->SetEncodingType(element_type); const clang::Type *type = ClangUtil::GetQualType(clang_type).getTypePtr(); m_ast.SetMetadataAsUserID(type, die.GetID()); @@ -1344,12 +1357,11 @@ TypeSP DWARFASTParserClang::ParsePointerToMemberType( CompilerType clang_type = TypeSystemClang::CreateMemberPointerType( class_clang_type, pointee_clang_type); - if (llvm::Optional<uint64_t> clang_type_size = + if (std::optional<uint64_t> clang_type_size = clang_type.GetByteSize(nullptr)) { - return std::make_shared<Type>(die.GetID(), dwarf, attrs.name, - *clang_type_size, nullptr, LLDB_INVALID_UID, - Type::eEncodingIsUID, nullptr, clang_type, - Type::ResolveState::Forward); + return dwarf->MakeType(die.GetID(), attrs.name, *clang_type_size, nullptr, + LLDB_INVALID_UID, Type::eEncodingIsUID, nullptr, + clang_type, Type::ResolveState::Forward); } return nullptr; } @@ -1360,9 +1372,8 @@ void DWARFASTParserClang::ParseInheritance( const lldb::ModuleSP &module_sp, std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> &base_classes, ClangASTImporter::LayoutInfo &layout_info) { - - TypeSystemClang *ast = - llvm::dyn_cast_or_null<TypeSystemClang>(class_clang_type.GetTypeSystem()); + auto ast = + class_clang_type.GetTypeSystem().dyn_cast_or_null<TypeSystemClang>(); if (ast == nullptr) return; @@ -1425,9 +1436,9 @@ void DWARFASTParserClang::ParseInheritance( Type *base_class_type = die.ResolveTypeUID(encoding_form.Reference()); if (base_class_type == nullptr) { - module_sp->ReportError("0x%8.8x: DW_TAG_inheritance failed to " - "resolve the base class at 0x%8.8x" - " from enclosing type 0x%8.8x. \nPlease file " + module_sp->ReportError("{0:x16}: DW_TAG_inheritance failed to " + "resolve the base class at {1:x16}" + " from enclosing type {2:x16}. \nPlease file " "a bug and attach the file at the start of " "this error message", die.GetOffset(), @@ -1500,6 +1511,61 @@ TypeSP DWARFASTParserClang::UpdateSymbolContextScopeForType( return type_sp; } +std::string +DWARFASTParserClang::GetCPlusPlusQualifiedName(const DWARFDIE &die) { + if (!die.IsValid()) + return ""; + const char *name = die.GetName(); + if (!name) + return ""; + std::string qualified_name; + DWARFDIE parent_decl_ctx_die = die.GetParentDeclContextDIE(); + // TODO: change this to get the correct decl context parent.... + while (parent_decl_ctx_die) { + // The name may not contain template parameters due to + // -gsimple-template-names; we must reconstruct the full name from child + // template parameter dies via GetDIEClassTemplateParams(). + const dw_tag_t parent_tag = parent_decl_ctx_die.Tag(); + switch (parent_tag) { + case DW_TAG_namespace: { + if (const char *namespace_name = parent_decl_ctx_die.GetName()) { + qualified_name.insert(0, "::"); + qualified_name.insert(0, namespace_name); + } else { + qualified_name.insert(0, "(anonymous namespace)::"); + } + parent_decl_ctx_die = parent_decl_ctx_die.GetParentDeclContextDIE(); + break; + } + + case DW_TAG_class_type: + case DW_TAG_structure_type: + case DW_TAG_union_type: { + if (const char *class_union_struct_name = parent_decl_ctx_die.GetName()) { + qualified_name.insert( + 0, GetDIEClassTemplateParams(parent_decl_ctx_die).AsCString("")); + qualified_name.insert(0, "::"); + qualified_name.insert(0, class_union_struct_name); + } + parent_decl_ctx_die = parent_decl_ctx_die.GetParentDeclContextDIE(); + break; + } + + default: + parent_decl_ctx_die.Clear(); + break; + } + } + + if (qualified_name.empty()) + qualified_name.append("::"); + + qualified_name.append(name); + qualified_name.append(GetDIEClassTemplateParams(die).AsCString("")); + + return qualified_name; +} + TypeSP DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc, const DWARFDIE &die, @@ -1525,8 +1591,8 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc, // For C++, we rely solely upon the one definition rule that says // only one thing can exist at a given decl context. We ignore the // file and line that things are declared on. - std::string qualified_name; - if (die.GetQualifiedName(qualified_name)) + std::string qualified_name = GetCPlusPlusQualifiedName(die); + if (!qualified_name.empty()) unique_typename = ConstString(qualified_name); unique_decl.Clear(); } @@ -1602,8 +1668,9 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc, if (log) { dwarf->GetObjectFile()->GetModule()->LogMessage( log, - "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is an " - "incomplete objc type, complete type is 0x%8.8" PRIx64, + "SymbolFileDWARF({0:p}) - {1:x16}: {2} type " + "\"{3}\" is an " + "incomplete objc type, complete type is {4:x8}", static_cast<void *>(this), die.GetOffset(), DW_TAG_value_to_name(tag), attrs.name.GetCString(), type_sp->GetID()); @@ -1627,7 +1694,7 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc, if (log) { dwarf->GetObjectFile()->GetModule()->LogMessage( log, - "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a " + "SymbolFileDWARF({0:p}) - {1:x16}: {2} type \"{3}\" is a " "forward declaration, trying to find complete type", static_cast<void *>(this), die.GetOffset(), DW_TAG_value_to_name(tag), attrs.name.GetCString()); @@ -1639,19 +1706,16 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc, if (type_sp) return type_sp; - DWARFDeclContext die_decl_ctx = SymbolFileDWARF::GetDWARFDeclContext(die); - // type_sp = FindDefinitionTypeForDIE (dwarf_cu, die, // type_name_const_str); - type_sp = dwarf->FindDefinitionTypeForDWARFDeclContext(die_decl_ctx); + type_sp = dwarf->FindDefinitionTypeForDWARFDeclContext(die); if (!type_sp) { SymbolFileDWARFDebugMap *debug_map_symfile = dwarf->GetDebugMapSymfile(); if (debug_map_symfile) { // We weren't able to find a full declaration in this DWARF, see // if we have a declaration anywhere else... - type_sp = debug_map_symfile->FindDefinitionTypeForDWARFDeclContext( - die_decl_ctx); + type_sp = debug_map_symfile->FindDefinitionTypeForDWARFDeclContext(die); } } @@ -1659,8 +1723,8 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc, if (log) { dwarf->GetObjectFile()->GetModule()->LogMessage( log, - "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a " - "forward declaration, complete type is 0x%8.8" PRIx64, + "SymbolFileDWARF({0:p}) - {1:x16}: {2} type \"{3}\" is a " + "forward declaration, complete type is {4:x8}", static_cast<void *>(this), die.GetOffset(), DW_TAG_value_to_name(tag), attrs.name.GetCString(), type_sp->GetID()); @@ -1679,8 +1743,9 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc, assert(tag_decl_kind != -1); (void)tag_decl_kind; bool clang_type_was_created = false; - clang_type.SetCompilerType( - &m_ast, dwarf->GetForwardDeclDieToClangType().lookup(die.GetDIE())); + clang_type = + CompilerType(m_ast.weak_from_this(), + dwarf->GetForwardDeclDieToClangType().lookup(die.GetDIE())); if (!clang_type) { clang::DeclContext *decl_ctx = GetClangDeclContextContainingDIE(die, nullptr); @@ -1700,36 +1765,34 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc, metadata.SetUserID(die.GetID()); metadata.SetIsDynamicCXXType(dwarf->ClassOrStructIsVirtual(die)); - if (attrs.name.GetStringRef().contains('<')) { - TypeSystemClang::TemplateParameterInfos template_param_infos; - if (ParseTemplateParameterInfos(die, template_param_infos)) { - clang::ClassTemplateDecl *class_template_decl = - m_ast.ParseClassTemplateDecl( - decl_ctx, GetOwningClangModule(die), attrs.accessibility, - attrs.name.GetCString(), tag_decl_kind, template_param_infos); - if (!class_template_decl) { - if (log) { - dwarf->GetObjectFile()->GetModule()->LogMessage( - log, - "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" " - "clang::ClassTemplateDecl failed to return a decl.", - static_cast<void *>(this), die.GetOffset(), - DW_TAG_value_to_name(tag), attrs.name.GetCString()); - } - return TypeSP(); + TypeSystemClang::TemplateParameterInfos template_param_infos; + if (ParseTemplateParameterInfos(die, template_param_infos)) { + clang::ClassTemplateDecl *class_template_decl = + m_ast.ParseClassTemplateDecl( + decl_ctx, GetOwningClangModule(die), attrs.accessibility, + attrs.name.GetCString(), tag_decl_kind, template_param_infos); + if (!class_template_decl) { + if (log) { + dwarf->GetObjectFile()->GetModule()->LogMessage( + log, + "SymbolFileDWARF({0:p}) - {1:x16}: {2} type \"{3}\" " + "clang::ClassTemplateDecl failed to return a decl.", + static_cast<void *>(this), die.GetOffset(), + DW_TAG_value_to_name(tag), attrs.name.GetCString()); } + return TypeSP(); + } - clang::ClassTemplateSpecializationDecl *class_specialization_decl = - m_ast.CreateClassTemplateSpecializationDecl( - decl_ctx, GetOwningClangModule(die), class_template_decl, - tag_decl_kind, template_param_infos); - clang_type = m_ast.CreateClassTemplateSpecializationType( - class_specialization_decl); - clang_type_was_created = true; + clang::ClassTemplateSpecializationDecl *class_specialization_decl = + m_ast.CreateClassTemplateSpecializationDecl( + decl_ctx, GetOwningClangModule(die), class_template_decl, + tag_decl_kind, template_param_infos); + clang_type = m_ast.CreateClassTemplateSpecializationType( + class_specialization_decl); + clang_type_was_created = true; - m_ast.SetMetadata(class_template_decl, metadata); - m_ast.SetMetadata(class_specialization_decl, metadata); - } + m_ast.SetMetadata(class_template_decl, metadata); + m_ast.SetMetadata(class_specialization_decl, metadata); } if (!clang_type_was_created) { @@ -1745,9 +1808,9 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc, // parameters in any class methods need it for the clang types for // function prototypes. LinkDeclContextToDIE(m_ast.GetDeclContextForType(clang_type), die); - type_sp = std::make_shared<Type>( - die.GetID(), dwarf, attrs.name, attrs.byte_size, nullptr, - LLDB_INVALID_UID, Type::eEncodingIsUID, &attrs.decl, clang_type, + type_sp = dwarf->MakeType( + die.GetID(), attrs.name, attrs.byte_size, nullptr, LLDB_INVALID_UID, + Type::eEncodingIsUID, &attrs.decl, clang_type, Type::ResolveState::Forward, TypePayloadClang(OptionalClangModuleID(), attrs.is_complete_objc_class)); @@ -1772,7 +1835,9 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc, TypeSystemClang::CompleteTagDeclarationDefinition(clang_type); } else { dwarf->GetObjectFile()->GetModule()->ReportError( - "DWARF DIE at 0x%8.8x named \"%s\" was not able to start its " + + "DWARF DIE at {0:x16} named \"{1}\" was not able to start " + "its " "definition.\nPlease file a bug and attach the file at the " "start of this error message", die.GetOffset(), attrs.name.GetCString()); @@ -1928,7 +1993,7 @@ bool DWARFASTParserClang::ParseTemplateDIE( } case DW_TAG_GNU_template_template_param: is_template_template_argument = true; - LLVM_FALLTHROUGH; + [[fallthrough]]; case DW_TAG_template_type_parameter: case DW_TAG_template_value_parameter: { DWARFAttributes attributes; @@ -1988,7 +2053,7 @@ bool DWARFASTParserClang::ParseTemplateDIE( clang_type.IsIntegerOrEnumerationType(is_signed); if (tag == DW_TAG_template_value_parameter && uval64_valid) { - llvm::Optional<uint64_t> size = clang_type.GetBitSize(nullptr); + std::optional<uint64_t> size = clang_type.GetBitSize(nullptr); if (!size) return false; llvm::APInt apint(*size, uval64, is_signed); @@ -2037,7 +2102,10 @@ bool DWARFASTParserClang::ParseTemplateParameterInfos( break; } } - return template_param_infos.args.size() == template_param_infos.names.size(); + return template_param_infos.args.size() == + template_param_infos.names.size() && + (!template_param_infos.args.empty() || + template_param_infos.packed_args); } bool DWARFASTParserClang::CompleteRecordType(const DWARFDIE &die, @@ -2099,7 +2167,8 @@ bool DWARFASTParserClang::CompleteRecordType(const DWARFDIE &die, clang::TypeSourceInfo *type_source_info = base_class->getTypeSourceInfo(); if (type_source_info) - RequireCompleteType(m_ast.GetType(type_source_info->getType())); + TypeSystemClang::RequireCompleteType( + m_ast.GetType(type_source_info->getType())); } m_ast.TransferBaseClasses(clang_type.GetOpaqueQualType(), @@ -2278,6 +2347,39 @@ size_t DWARFASTParserClang::ParseChildEnumerators( return enumerators_added; } +ConstString +DWARFASTParserClang::ConstructDemangledNameFromDWARF(const DWARFDIE &die) { + bool is_static = false; + bool is_variadic = false; + bool has_template_params = false; + unsigned type_quals = 0; + std::vector<CompilerType> param_types; + std::vector<clang::ParmVarDecl *> param_decls; + StreamString sstr; + + DWARFDeclContext decl_ctx = SymbolFileDWARF::GetDWARFDeclContext(die); + sstr << decl_ctx.GetQualifiedName(); + + clang::DeclContext *containing_decl_ctx = + GetClangDeclContextContainingDIE(die, nullptr); + ParseChildParameters(containing_decl_ctx, die, true, is_static, is_variadic, + has_template_params, param_types, param_decls, + type_quals); + sstr << "("; + for (size_t i = 0; i < param_types.size(); i++) { + if (i > 0) + sstr << ", "; + sstr << param_types[i].GetTypeName(); + } + if (is_variadic) + sstr << ", ..."; + sstr << ")"; + if (type_quals & clang::Qualifiers::Const) + sstr << " const"; + + return ConstString(sstr.GetString()); +} + Function * DWARFASTParserClang::ParseFunctionFromDWARF(CompileUnit &comp_unit, const DWARFDIE &die, @@ -2315,35 +2417,7 @@ DWARFASTParserClang::ParseFunctionFromDWARF(CompileUnit &comp_unit, // If the mangled name is not present in the DWARF, generate the // demangled name using the decl context. We skip if the function is // "main" as its name is never mangled. - bool is_static = false; - bool is_variadic = false; - bool has_template_params = false; - unsigned type_quals = 0; - std::vector<CompilerType> param_types; - std::vector<clang::ParmVarDecl *> param_decls; - StreamString sstr; - - DWARFDeclContext decl_ctx = SymbolFileDWARF::GetDWARFDeclContext(die); - sstr << decl_ctx.GetQualifiedName(); - - clang::DeclContext *containing_decl_ctx = - GetClangDeclContextContainingDIE(die, nullptr); - ParseChildParameters(containing_decl_ctx, die, true, is_static, - is_variadic, has_template_params, param_types, - param_decls, type_quals); - sstr << "("; - for (size_t i = 0; i < param_types.size(); i++) { - if (i > 0) - sstr << ", "; - sstr << param_types[i].GetTypeName(); - } - if (is_variadic) - sstr << ", ..."; - sstr << ")"; - if (type_quals & clang::Qualifiers::Const) - sstr << " const"; - - func_name.SetValue(ConstString(sstr.GetString()), false); + func_name.SetValue(ConstructDemangledNameFromDWARF(die), false); } else func_name.SetValue(ConstString(name), false); @@ -2389,8 +2463,8 @@ struct MemberAttributes { size_t bit_size = 0; uint64_t data_bit_offset = UINT64_MAX; AccessType accessibility = eAccessNone; - llvm::Optional<uint64_t> byte_size; - llvm::Optional<DWARFFormValue> const_value_form; + std::optional<uint64_t> byte_size; + std::optional<DWARFFormValue> const_value_form; DWARFFormValue encoding_form; /// Indicates the byte offset of the word from the base address of the /// structure. @@ -2568,18 +2642,18 @@ void DWARFASTParserClang::ParseObjCProperty( const PropertyAttributes propAttrs(die); if (!propAttrs.prop_name) { - module_sp->ReportError( - "0x%8.8" PRIx64 ": DW_TAG_APPLE_property has no name.", die.GetID()); + module_sp->ReportError("{0:x8}: DW_TAG_APPLE_property has no name.", + die.GetID()); return; } Type *member_type = die.ResolveTypeUID(attrs.encoding_form.Reference()); if (!member_type) { - module_sp->ReportError("0x%8.8" PRIx64 - ": DW_TAG_APPLE_property '%s' refers to type 0x%8.8x" - " which was unable to be parsed", - die.GetID(), propAttrs.prop_name, - attrs.encoding_form.Reference().GetOffset()); + module_sp->ReportError( + "{0:x8}: DW_TAG_APPLE_property '{1}' refers to type {2:x16}" + " which was unable to be parsed", + die.GetID(), propAttrs.prop_name, + attrs.encoding_form.Reference().GetOffset()); return; } @@ -2595,7 +2669,11 @@ llvm::Expected<llvm::APInt> DWARFASTParserClang::ExtractIntFromFormValue( const CompilerType &int_type, const DWARFFormValue &form_value) const { clang::QualType qt = ClangUtil::GetQualType(int_type); assert(qt->isIntegralOrEnumerationType()); - TypeSystemClang &ts = *llvm::cast<TypeSystemClang>(int_type.GetTypeSystem()); + auto ts_ptr = int_type.GetTypeSystem().dyn_cast_or_null<TypeSystemClang>(); + if (!ts_ptr) + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "TypeSystem not clang"); + TypeSystemClang &ts = *ts_ptr; clang::ASTContext &ast = ts.getASTContext(); const unsigned type_bits = ast.getIntWidth(qt); @@ -2692,6 +2770,7 @@ void DWARFASTParserClang::ParseSingleMember( // TODO: Support float/double static members as well. if (!attrs.const_value_form || !ct.IsIntegerOrEnumerationType(unused)) return; + llvm::Expected<llvm::APInt> const_value_or_err = ExtractIntFromFormValue(ct, *attrs.const_value_form); if (!const_value_or_err) { @@ -2700,6 +2779,7 @@ void DWARFASTParserClang::ParseSingleMember( v->getQualifiedNameAsString()); return; } + TypeSystemClang::SetIntegerInitializerForVariable(v, *const_value_or_err); } return; @@ -2709,14 +2789,14 @@ void DWARFASTParserClang::ParseSingleMember( if (!member_type) { if (attrs.name) module_sp->ReportError( - "0x%8.8" PRIx64 ": DW_TAG_member '%s' refers to type 0x%8.8x" + "{0:x8}: DW_TAG_member '{1}' refers to type {2:x16}" " which was unable to be parsed", die.GetID(), attrs.name, attrs.encoding_form.Reference().GetOffset()); else - module_sp->ReportError( - "0x%8.8" PRIx64 ": DW_TAG_member refers to type 0x%8.8x" - " which was unable to be parsed", - die.GetID(), attrs.encoding_form.Reference().GetOffset()); + module_sp->ReportError("{0:x8}: DW_TAG_member refers to type {1:x16}" + " which was unable to be parsed", + die.GetID(), + attrs.encoding_form.Reference().GetOffset()); return; } @@ -2729,7 +2809,7 @@ void DWARFASTParserClang::ParseSingleMember( uint64_t field_bit_offset = (attrs.member_byte_offset == UINT32_MAX ? 0 - : (attrs.member_byte_offset * 8)); + : (attrs.member_byte_offset * 8ULL)); if (attrs.bit_size > 0) { FieldInfo this_field_info; @@ -2766,10 +2846,10 @@ void DWARFASTParserClang::ParseSingleMember( this_field_info.bit_offset)))) { ObjectFile *objfile = die.GetDWARF()->GetObjectFile(); objfile->GetModule()->ReportWarning( - "0x%8.8" PRIx64 ": %s bitfield named \"%s\" has invalid " - "bit offset (0x%8.8" PRIx64 - ") member will be ignored. Please file a bug against the " - "compiler and include the preprocessed output for %s\n", + "{0:x16}: {1} bitfield named \"{2}\" has invalid " + "bit offset ({3:x8}) member will be ignored. Please file a bug " + "against the " + "compiler and include the preprocessed output for {4}\n", die.GetID(), DW_TAG_value_to_name(tag), attrs.name, this_field_info.bit_offset, GetUnitName(parent_die).c_str()); return; @@ -2788,7 +2868,7 @@ void DWARFASTParserClang::ParseSingleMember( die.GetCU()->Supports_unnamed_objc_bitfields(); if (detect_unnamed_bitfields) { - llvm::Optional<FieldInfo> unnamed_field_info; + std::optional<FieldInfo> unnamed_field_info; uint64_t last_field_end = 0; last_field_end = last_field_info.bit_offset + last_field_info.bit_size; @@ -2840,7 +2920,7 @@ void DWARFASTParserClang::ParseSingleMember( } else { last_field_info.bit_offset = field_bit_offset; - if (llvm::Optional<uint64_t> clang_type_size = + if (std::optional<uint64_t> clang_type_size = member_type->GetByteSize(nullptr)) { last_field_info.bit_size = *clang_type_size * character_width; } @@ -2885,11 +2965,10 @@ void DWARFASTParserClang::ParseSingleMember( (member_array_size != 0 || attrs.member_byte_offset > parent_byte_size)) { module_sp->ReportError( - "0x%8.8" PRIx64 ": DW_TAG_member '%s' refers to type 0x%8.8x" - " which extends beyond the bounds of 0x%8.8" PRIx64, + "{0:x8}: DW_TAG_member '{1}' refers to type {2:x16}" + " which extends beyond the bounds of {3:x8}", die.GetID(), attrs.name, - attrs.encoding_form.Reference().GetOffset(), - parent_die.GetID()); + attrs.encoding_form.Reference().GetOffset(), parent_die.GetID()); } member_clang_type = @@ -2898,7 +2977,7 @@ void DWARFASTParserClang::ParseSingleMember( } } - RequireCompleteType(member_clang_type); + TypeSystemClang::RequireCompleteType(member_clang_type); clang::FieldDecl *field_decl = TypeSystemClang::AddFieldToRecordType( class_clang_type, attrs.name, member_clang_type, attrs.accessibility, @@ -2923,8 +3002,8 @@ bool DWARFASTParserClang::ParseChildMembers( FieldInfo last_field_info; ModuleSP module_sp = parent_die.GetDWARF()->GetObjectFile()->GetModule(); - TypeSystemClang *ast = - llvm::dyn_cast_or_null<TypeSystemClang>(class_clang_type.GetTypeSystem()); + auto ts = class_clang_type.GetTypeSystem(); + auto ast = ts.dyn_cast_or_null<TypeSystemClang>(); if (ast == nullptr) return false; diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h index 733ffa230f1e..0733d22a0069 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h @@ -10,6 +10,7 @@ #define LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFASTPARSERCLANG_H #include "clang/AST/CharUnits.h" +#include "clang/AST/Type.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" @@ -24,6 +25,7 @@ #include "Plugins/ExpressionParser/Clang/ClangASTImporter.h" #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" +#include <optional> #include <vector> namespace lldb_private { @@ -45,6 +47,9 @@ public: const DWARFDIE &die, bool *type_is_new_ptr) override; + lldb_private::ConstString + ConstructDemangledNameFromDWARF(const DWARFDIE &die) override; + lldb_private::Function * ParseFunctionFromDWARF(lldb_private::CompileUnit &comp_unit, const DWARFDIE &die, @@ -84,6 +89,19 @@ public: ExtractIntFromFormValue(const lldb_private::CompilerType &int_type, const DWARFFormValue &form_value) const; + /// Returns the template parameters of a class DWARFDIE as a string. + /// + /// This is mostly useful for -gsimple-template-names which omits template + /// parameters from the DIE name and instead always adds template parameter + /// children DIEs. + /// + /// \param die The struct/class DWARFDIE containing template parameters. + /// \return A string, including surrounding '<>', of the template parameters. + /// If the DIE's name already has '<>', returns an empty ConstString because + /// it's assumed that the caller is using the DIE name anyway. + lldb_private::ConstString + GetDIEClassTemplateParams(const DWARFDIE &die) override; + protected: /// Protected typedefs and members. /// @{ @@ -117,11 +135,14 @@ protected: bool ParseTemplateDIE(const DWARFDIE &die, lldb_private::TypeSystemClang::TemplateParameterInfos &template_param_infos); + bool ParseTemplateParameterInfos( const DWARFDIE &parent_die, lldb_private::TypeSystemClang::TemplateParameterInfos &template_param_infos); + std::string GetCPlusPlusQualifiedName(const DWARFDIE &die); + bool ParseChildMembers( const DWARFDIE &die, lldb_private::CompilerType &class_compiler_type, std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> &base_classes, @@ -239,9 +260,8 @@ private: const DWARFDIE &die, ParsedDWARFTypeAttributes &attrs); lldb::TypeSP ParseSubroutine(const DWARFDIE &die, ParsedDWARFTypeAttributes &attrs); - // FIXME: attrs should be passed as a const reference. lldb::TypeSP ParseArrayType(const DWARFDIE &die, - ParsedDWARFTypeAttributes &attrs); + const ParsedDWARFTypeAttributes &attrs); lldb::TypeSP ParsePointerToMemberType(const DWARFDIE &die, const ParsedDWARFTypeAttributes &attrs); @@ -296,11 +316,15 @@ struct ParsedDWARFTypeAttributes { DWARFFormValue specification; DWARFFormValue type; lldb::LanguageType class_language = lldb::eLanguageTypeUnknown; - llvm::Optional<uint64_t> byte_size; + std::optional<uint64_t> byte_size; size_t calling_convention = llvm::dwarf::DW_CC_normal; uint32_t bit_stride = 0; uint32_t byte_stride = 0; uint32_t encoding = 0; + clang::RefQualifierKind ref_qual = + clang::RQ_None; ///< Indicates ref-qualifier of + ///< C++ member function if present. + ///< Is RQ_None otherwise. }; #endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFASTPARSERCLANG_H diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.cpp index fcb424029f5a..e631f99f09a0 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.cpp @@ -15,12 +15,13 @@ #include "lldb/Core/Module.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Utility/Log.h" +#include <optional> using namespace lldb_private; -llvm::Optional<DIERef> DWARFBaseDIE::GetDIERef() const { +std::optional<DIERef> DWARFBaseDIE::GetDIERef() const { if (!IsValid()) - return llvm::None; + return std::nullopt; return DIERef(m_cu->GetSymbolFileDWARF().GetDwoNum(), m_cu->GetDebugSection(), m_die->GetOffset()); @@ -53,6 +54,13 @@ uint64_t DWARFBaseDIE::GetAttributeValueAsUnsigned(const dw_attr_t attr, return fail_value; } +std::optional<uint64_t> +DWARFBaseDIE::GetAttributeValueAsOptionalUnsigned(const dw_attr_t attr) const { + if (IsValid()) + return m_die->GetAttributeValueAsOptionalUnsigned(GetCU(), attr); + return std::nullopt; +} + uint64_t DWARFBaseDIE::GetAttributeValueAsAddress(const dw_attr_t attr, uint64_t fail_value) const { if (IsValid()) diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h index 36df980f6ef0..51145ab0c4dc 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h @@ -13,6 +13,7 @@ #include "lldb/lldb-types.h" #include "llvm/Support/Error.h" +#include <optional> class DIERef; class DWARFASTParser; @@ -55,7 +56,7 @@ public: DWARFDebugInfoEntry *GetDIE() const { return m_die; } - llvm::Optional<DIERef> GetDIERef() const; + std::optional<DIERef> GetDIERef() const; void Set(DWARFUnit *cu, DWARFDebugInfoEntry *die) { if (cu && die) { @@ -107,6 +108,9 @@ public: uint64_t GetAttributeValueAsUnsigned(const dw_attr_t attr, uint64_t fail_value) const; + std::optional<uint64_t> + GetAttributeValueAsOptionalUnsigned(const dw_attr_t attr) const; + uint64_t GetAttributeValueAsAddress(const dw_attr_t attr, uint64_t fail_value) const; diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp index 9ca160b474fc..dbe86c6ccb9c 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp @@ -18,11 +18,13 @@ using namespace lldb; using namespace lldb_private; void DWARFCompileUnit::Dump(Stream *s) const { - s->Printf("0x%8.8x: Compile Unit: length = 0x%8.8x, version = 0x%4.4x, " - "abbr_offset = 0x%8.8x, addr_size = 0x%2.2x (next CU at " - "{0x%8.8x})\n", - GetOffset(), GetLength(), GetVersion(), GetAbbrevOffset(), - GetAddressByteSize(), GetNextUnitOffset()); + s->Format( + + "{0:x16}: Compile Unit: length = {1:x8}, version = {2:x}, " + "abbr_offset = {3:x8}, addr_size = {4:x2} (next CU at " + "[{5:x16}])\n", + GetOffset(), GetLength(), GetVersion(), (uint32_t)GetAbbrevOffset(), + GetAddressByteSize(), GetNextUnitOffset()); } void DWARFCompileUnit::BuildAddressRangeTable( @@ -53,28 +55,21 @@ void DWARFCompileUnit::BuildAddressRangeTable( } if (debug_aranges->GetNumRanges() == num_debug_aranges) { - // We got nothing from the debug info, maybe we have a line tables only - // situation. Check the line tables and build the arange table from this. + // We got nothing from the debug info, try to build the arange table from + // the debug map OSO aranges. SymbolContext sc; sc.comp_unit = m_dwarf.GetCompUnitForDWARFCompUnit(*this); if (sc.comp_unit) { SymbolFileDWARFDebugMap *debug_map_sym_file = m_dwarf.GetDebugMapSymfile(); - if (debug_map_sym_file == nullptr) { - if (LineTable *line_table = sc.comp_unit->GetLineTable()) { - LineTable::FileAddressRanges file_ranges; - const bool append = true; - const size_t num_ranges = - line_table->GetContiguousFileAddressRanges(file_ranges, append); - for (uint32_t idx = 0; idx < num_ranges; ++idx) { - const LineTable::FileAddressRanges::Entry &range = - file_ranges.GetEntryRef(idx); - debug_aranges->AppendRange(cu_offset, range.GetRangeBase(), - range.GetRangeEnd()); - } - } - } else - debug_map_sym_file->AddOSOARanges(&m_dwarf, debug_aranges); + if (debug_map_sym_file) { + auto *cu_info = + debug_map_sym_file->GetCompileUnitInfo(&GetSymbolFileDWARF()); + // If there are extra compile units the OSO entries aren't a reliable + // source of information. + if (cu_info->compile_units_sps.empty()) + debug_map_sym_file->AddOSOARanges(&m_dwarf, debug_aranges); + } } } diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFContext.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFContext.cpp index 37e28a09f3c4..f72dad88e157 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFContext.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFContext.cpp @@ -9,6 +9,7 @@ #include "DWARFContext.h" #include "lldb/Core/Section.h" +#include <optional> using namespace lldb; using namespace lldb_private; @@ -28,8 +29,8 @@ static DWARFDataExtractor LoadSection(SectionList *section_list, } const DWARFDataExtractor & -DWARFContext::LoadOrGetSection(llvm::Optional<SectionType> main_section_type, - llvm::Optional<SectionType> dwo_section_type, +DWARFContext::LoadOrGetSection(std::optional<SectionType> main_section_type, + std::optional<SectionType> dwo_section_type, SectionData &data) { llvm::call_once(data.flag, [&] { if (dwo_section_type && isDwo()) @@ -41,12 +42,12 @@ DWARFContext::LoadOrGetSection(llvm::Optional<SectionType> main_section_type, } const DWARFDataExtractor &DWARFContext::getOrLoadCuIndexData() { - return LoadOrGetSection(llvm::None, eSectionTypeDWARFDebugCuIndex, + return LoadOrGetSection(std::nullopt, eSectionTypeDWARFDebugCuIndex, m_data_debug_cu_index); } const DWARFDataExtractor &DWARFContext::getOrLoadTuIndexData() { - return LoadOrGetSection(llvm::None, eSectionTypeDWARFDebugTuIndex, + return LoadOrGetSection(std::nullopt, eSectionTypeDWARFDebugTuIndex, m_data_debug_tu_index); } @@ -56,12 +57,12 @@ const DWARFDataExtractor &DWARFContext::getOrLoadAbbrevData() { } const DWARFDataExtractor &DWARFContext::getOrLoadArangesData() { - return LoadOrGetSection(eSectionTypeDWARFDebugAranges, llvm::None, + return LoadOrGetSection(eSectionTypeDWARFDebugAranges, std::nullopt, m_data_debug_aranges); } const DWARFDataExtractor &DWARFContext::getOrLoadAddrData() { - return LoadOrGetSection(eSectionTypeDWARFDebugAddr, llvm::None, + return LoadOrGetSection(eSectionTypeDWARFDebugAddr, std::nullopt, m_data_debug_addr); } @@ -71,12 +72,12 @@ const DWARFDataExtractor &DWARFContext::getOrLoadDebugInfoData() { } const DWARFDataExtractor &DWARFContext::getOrLoadLineData() { - return LoadOrGetSection(eSectionTypeDWARFDebugLine, llvm::None, + return LoadOrGetSection(eSectionTypeDWARFDebugLine, std::nullopt, m_data_debug_line); } const DWARFDataExtractor &DWARFContext::getOrLoadLineStrData() { - return LoadOrGetSection(eSectionTypeDWARFDebugLineStr, llvm::None, + return LoadOrGetSection(eSectionTypeDWARFDebugLineStr, std::nullopt, m_data_debug_line_str); } @@ -92,12 +93,12 @@ const DWARFDataExtractor &DWARFContext::getOrLoadLocListsData() { } const DWARFDataExtractor &DWARFContext::getOrLoadMacroData() { - return LoadOrGetSection(eSectionTypeDWARFDebugMacro, llvm::None, + return LoadOrGetSection(eSectionTypeDWARFDebugMacro, std::nullopt, m_data_debug_macro); } const DWARFDataExtractor &DWARFContext::getOrLoadRangesData() { - return LoadOrGetSection(eSectionTypeDWARFDebugRanges, llvm::None, + return LoadOrGetSection(eSectionTypeDWARFDebugRanges, std::nullopt, m_data_debug_ranges); } diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFContext.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFContext.h index 92161a21d167..7df776b5f514 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFContext.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFContext.h @@ -11,10 +11,10 @@ #include "DWARFDataExtractor.h" #include "lldb/Core/Section.h" -#include "llvm/ADT/Optional.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h" #include "llvm/Support/Threading.h" #include <memory> +#include <optional> namespace lldb_private { class DWARFContext { @@ -46,8 +46,8 @@ private: SectionData m_data_debug_types; const DWARFDataExtractor & - LoadOrGetSection(llvm::Optional<lldb::SectionType> main_section_type, - llvm::Optional<lldb::SectionType> dwo_section_type, + LoadOrGetSection(std::optional<lldb::SectionType> main_section_type, + std::optional<lldb::SectionType> dwo_section_type, SectionData &data); const DWARFDataExtractor &getOrLoadCuIndexData(); diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp index 06cdd877f7dc..7b9da6fa166f 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp @@ -14,6 +14,8 @@ #include "DWARFDeclContext.h" #include "DWARFUnit.h" +#include "llvm/ADT/iterator.h" + using namespace lldb_private; using namespace lldb_private::dwarf; @@ -24,7 +26,9 @@ namespace { /// convenience, the starting die is included in the sequence as the first /// item. class ElaboratingDIEIterator - : public std::iterator<std::input_iterator_tag, DWARFDIE> { + : public llvm::iterator_facade_base< + ElaboratingDIEIterator, std::input_iterator_tag, DWARFDIE, + std::ptrdiff_t, DWARFDIE *, DWARFDIE *> { // The operating invariant is: top of m_worklist contains the "current" item // and the rest of the list are items yet to be visited. An empty worklist @@ -62,11 +66,6 @@ public: Next(); return *this; } - ElaboratingDIEIterator operator++(int) { - ElaboratingDIEIterator I = *this; - Next(); - return I; - } friend bool operator==(const ElaboratingDIEIterator &a, const ElaboratingDIEIterator &b) { @@ -74,10 +73,6 @@ public: return a.m_worklist.empty() == b.m_worklist.empty(); return a.m_worklist.back() == b.m_worklist.back(); } - friend bool operator!=(const ElaboratingDIEIterator &a, - const ElaboratingDIEIterator &b) { - return !(a == b); - } }; llvm::iterator_range<ElaboratingDIEIterator> @@ -215,13 +210,6 @@ const char *DWARFDIE::GetPubname() const { return nullptr; } -const char *DWARFDIE::GetQualifiedName(std::string &storage) const { - if (IsValid()) - return m_die->GetQualifiedName(m_cu, storage); - else - return nullptr; -} - // GetName // // Get value of the DW_AT_name attribute and place that value into the supplied @@ -320,6 +308,18 @@ void DWARFDIE::AppendTypeName(Stream &s) const { case DW_TAG_volatile_type: s.PutCString("volatile "); break; + case DW_TAG_LLVM_ptrauth_type: { + unsigned key = GetAttributeValueAsUnsigned(DW_AT_LLVM_ptrauth_key, 0); + bool isAddressDiscriminated = GetAttributeValueAsUnsigned( + DW_AT_LLVM_ptrauth_address_discriminated, 0); + unsigned extraDiscriminator = + GetAttributeValueAsUnsigned(DW_AT_LLVM_ptrauth_extra_discriminator, 0); + bool isaPointer = + GetAttributeValueAsUnsigned(DW_AT_LLVM_ptrauth_isa_pointer, 0); + s.Printf("__ptrauth(%d, %d, 0x0%x, %d)", key, isAddressDiscriminated, + extraDiscriminator, isaPointer); + break; + } default: return; } diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h index 7ce9550a081e..3564f757dbd8 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h @@ -30,8 +30,6 @@ public: const char *GetPubname() const; - const char *GetQualifiedName(std::string &storage) const; - using DWARFBaseDIE::GetName; void GetName(lldb_private::Stream &s) const; diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.cpp index cf483286a66d..a0e8dcc3d4f3 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.cpp @@ -22,8 +22,8 @@ DWARFDataExtractor::GetDWARFOffset(lldb::offset_t *offset_ptr) const { } llvm::DWARFDataExtractor DWARFDataExtractor::GetAsLLVM() const { - return llvm::DWARFDataExtractor( - llvm::makeArrayRef(GetDataStart(), GetByteSize()), - GetByteOrder() == lldb::eByteOrderLittle, GetAddressByteSize()); + return llvm::DWARFDataExtractor(llvm::ArrayRef(GetDataStart(), GetByteSize()), + GetByteOrder() == lldb::eByteOrderLittle, + GetAddressByteSize()); } } // namespace lldb_private diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp index 8933b0804a01..b631985d60c4 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp @@ -53,13 +53,21 @@ const DWARFDebugAranges &DWARFDebugInfo::GetCompileUnitAranges() { } // Manually build arange data for everything that wasn't in .debug_aranges. - const size_t num_units = GetNumUnits(); - for (size_t idx = 0; idx < num_units; ++idx) { - DWARFUnit *cu = GetUnitAtIndex(idx); - - dw_offset_t offset = cu->GetOffset(); - if (cus_with_data.find(offset) == cus_with_data.end()) - cu->BuildAddressRangeTable(m_cu_aranges_up.get()); + // The .debug_aranges accelerator is not guaranteed to be complete. + // Tools such as dsymutil can provide stronger guarantees than required by the + // standard. Without that guarantee, we have to iterate over every CU in the + // .debug_info and make sure there's a corresponding entry in the table and if + // not, add one for every subprogram. + ObjectFile *OF = m_dwarf.GetObjectFile(); + if (!OF || !OF->CanTrustAddressRanges()) { + const size_t num_units = GetNumUnits(); + for (size_t idx = 0; idx < num_units; ++idx) { + DWARFUnit *cu = GetUnitAtIndex(idx); + + dw_offset_t offset = cu->GetOffset(); + if (cus_with_data.find(offset) == cus_with_data.end()) + cu->BuildAddressRangeTable(m_cu_aranges_up.get()); + } } const bool minimize = true; diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp index c98953640a58..bb1fd60a834d 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp @@ -11,6 +11,7 @@ #include <cassert> #include <algorithm> +#include <optional> #include "llvm/Support/LEB128.h" @@ -18,6 +19,7 @@ #include "lldb/Expression/DWARFExpression.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Utility/Stream.h" +#include "lldb/Utility/StreamString.h" #include "DWARFCompileUnit.h" #include "DWARFDebugAbbrev.h" @@ -59,7 +61,8 @@ bool DWARFDebugInfoEntry::Extract(const DWARFDataExtractor &data, const auto *abbrevDecl = GetAbbreviationDeclarationPtr(cu); if (abbrevDecl == nullptr) { cu->GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError( - "{0x%8.8x}: invalid abbreviation code %u, please file a bug and " + "[{0:x16}]: invalid abbreviation code {1}, " + "please file a bug and " "attach the file at the start of this error message", m_offset, (unsigned)abbr_idx); // WE can't parse anymore if the DWARF is borked... @@ -74,7 +77,7 @@ bool DWARFDebugInfoEntry::Extract(const DWARFDataExtractor &data, dw_form_t form; for (i = 0; i < numAttributes; ++i) { form = abbrevDecl->GetFormByIndexUnchecked(i); - llvm::Optional<uint8_t> fixed_skip_size = + std::optional<uint8_t> fixed_skip_size = DWARFFormValue::GetFixedSize(form, cu); if (fixed_skip_size) offset += *fixed_skip_size; @@ -189,7 +192,8 @@ bool DWARFDebugInfoEntry::Extract(const DWARFDataExtractor &data, default: cu->GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError( - "{0x%8.8x}: Unsupported DW_FORM_0x%x, please file a bug and " + "[{0:x16}]: Unsupported DW_FORM_{1:x}, please file a bug " + "and " "attach the file at the start of this error message", m_offset, (unsigned)form); *offset_ptr = m_offset; @@ -213,9 +217,10 @@ static DWARFRangeList GetRangesOrReportError(DWARFUnit &unit, : unit.FindRnglistFromOffset(value.Unsigned()); if (expected_ranges) return std::move(*expected_ranges); + unit.GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError( - "{0x%8.8x}: DIE has DW_AT_ranges(%s 0x%" PRIx64 ") attribute, but " - "range extraction failed (%s), please file a bug " + "[{0:x16}]: DIE has DW_AT_ranges({1} {2:x16}) attribute, but " + "range extraction failed ({3}), please file a bug " "and attach the file at the start of this error message", die.GetOffset(), llvm::dwarf::FormEncodingString(value.Form()).str().c_str(), @@ -432,7 +437,7 @@ size_t DWARFDebugInfoEntry::GetAttributes(DWARFUnit *cu, // curr_depth is not zero break; } - LLVM_FALLTHROUGH; + [[fallthrough]]; default: attributes.Append(form_value, offset, attr); break; @@ -447,7 +452,8 @@ size_t DWARFDebugInfoEntry::GetAttributes(DWARFUnit *cu, recurse, curr_depth + 1); } } else { - llvm::Optional<uint8_t> fixed_skip_size = DWARFFormValue::GetFixedSize(form, cu); + std::optional<uint8_t> fixed_skip_size = + DWARFFormValue::GetFixedSize(form, cu); if (fixed_skip_size) offset += *fixed_skip_size; else @@ -546,6 +552,17 @@ uint64_t DWARFDebugInfoEntry::GetAttributeValueAsUnsigned( return fail_value; } +std::optional<uint64_t> +DWARFDebugInfoEntry::GetAttributeValueAsOptionalUnsigned( + const DWARFUnit *cu, const dw_attr_t attr, + bool check_specification_or_abstract_origin) const { + DWARFFormValue form_value; + if (GetAttributeValue(cu, attr, form_value, nullptr, + check_specification_or_abstract_origin)) + return form_value.Unsigned(); + return std::nullopt; +} + // GetAttributeValueAsReference // // Get the value of an attribute as reference and fix up and compile unit @@ -786,66 +803,6 @@ DWARFDebugInfoEntry::GetParentDeclContextDIE( return DWARFDIE(); } -const char *DWARFDebugInfoEntry::GetQualifiedName(DWARFUnit *cu, - std::string &storage) const { - DWARFAttributes attributes; - GetAttributes(cu, attributes, Recurse::yes); - return GetQualifiedName(cu, attributes, storage); -} - -const char * -DWARFDebugInfoEntry::GetQualifiedName(DWARFUnit *cu, - const DWARFAttributes &attributes, - std::string &storage) const { - - const char *name = GetName(cu); - - if (name) { - DWARFDIE parent_decl_ctx_die = GetParentDeclContextDIE(cu); - storage.clear(); - // TODO: change this to get the correct decl context parent.... - while (parent_decl_ctx_die) { - const dw_tag_t parent_tag = parent_decl_ctx_die.Tag(); - switch (parent_tag) { - case DW_TAG_namespace: { - const char *namespace_name = parent_decl_ctx_die.GetName(); - if (namespace_name) { - storage.insert(0, "::"); - storage.insert(0, namespace_name); - } else { - storage.insert(0, "(anonymous namespace)::"); - } - parent_decl_ctx_die = parent_decl_ctx_die.GetParentDeclContextDIE(); - } break; - - case DW_TAG_class_type: - case DW_TAG_structure_type: - case DW_TAG_union_type: { - const char *class_union_struct_name = parent_decl_ctx_die.GetName(); - - if (class_union_struct_name) { - storage.insert(0, "::"); - storage.insert(0, class_union_struct_name); - } - parent_decl_ctx_die = parent_decl_ctx_die.GetParentDeclContextDIE(); - } break; - - default: - parent_decl_ctx_die.Clear(); - break; - } - } - - if (storage.empty()) - storage.append("::"); - - storage.append(name); - } - if (storage.empty()) - return nullptr; - return storage.c_str(); -} - lldb::offset_t DWARFDebugInfoEntry::GetFirstAttributeOffset() const { return GetOffset() + llvm::getULEB128Size(m_abbr_idx); } diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h index 32f653e99a70..fcfffbfd38f0 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h @@ -17,6 +17,7 @@ #include "DWARFDebugAbbrev.h" #include "DWARFDebugRanges.h" #include <map> +#include <optional> #include <set> #include <vector> @@ -67,6 +68,10 @@ public: const DWARFUnit *cu, const dw_attr_t attr, uint64_t fail_value, bool check_specification_or_abstract_origin = false) const; + std::optional<uint64_t> GetAttributeValueAsOptionalUnsigned( + const DWARFUnit *cu, const dw_attr_t attr, + bool check_specification_or_abstract_origin = false) const; + DWARFDIE GetAttributeValueAsReference( const DWARFUnit *cu, const dw_attr_t attr, bool check_specification_or_abstract_origin = false) const; @@ -95,11 +100,6 @@ public: const char *GetPubname(const DWARFUnit *cu) const; - const char *GetQualifiedName(DWARFUnit *cu, std::string &storage) const; - - const char *GetQualifiedName(DWARFUnit *cu, const DWARFAttributes &attributes, - std::string &storage) const; - bool GetDIENamesAndRanges( DWARFUnit *cu, const char *&name, const char *&mangled, DWARFRangeList &rangeList, int &decl_file, int &decl_line, diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h index e46694405415..fa776f27d501 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h @@ -75,15 +75,10 @@ public: m_qualified_name.clear(); } - lldb::LanguageType GetLanguage() const { return m_language; } - - void SetLanguage(lldb::LanguageType language) { m_language = language; } - protected: typedef std::vector<Entry> collection; collection m_entries; mutable std::string m_qualified_name; - lldb::LanguageType m_language = lldb::eLanguageTypeUnknown; }; #endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFDECLCONTEXT_H diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp index 08b241683776..a1578b47ae94 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include <cassert> +#include <optional> #include "lldb/Core/Module.h" #include "lldb/Core/dwarf.h" @@ -187,16 +188,16 @@ static FormSize g_form_sizes[] = { {1, 8}, // 0x20 DW_FORM_ref_sig8 }; -llvm::Optional<uint8_t> -DWARFFormValue::GetFixedSize(dw_form_t form, const DWARFUnit *u) { +std::optional<uint8_t> DWARFFormValue::GetFixedSize(dw_form_t form, + const DWARFUnit *u) { if (form <= DW_FORM_ref_sig8 && g_form_sizes[form].valid) - return g_form_sizes[form].size; + return static_cast<uint8_t>(g_form_sizes[form].size); if (form == DW_FORM_addr && u) return u->GetAddressByteSize(); - return llvm::None; + return std::nullopt; } -llvm::Optional<uint8_t> DWARFFormValue::GetFixedSize() const { +std::optional<uint8_t> DWARFFormValue::GetFixedSize() const { return GetFixedSize(m_form, m_unit); } @@ -468,7 +469,7 @@ const char *DWARFFormValue::AsCString() const { m_form == DW_FORM_strx1 || m_form == DW_FORM_strx2 || m_form == DW_FORM_strx3 || m_form == DW_FORM_strx4) { - llvm::Optional<uint64_t> offset = + std::optional<uint64_t> offset = m_unit->GetStringOffsetSectionItem(m_value.value.uval); if (!offset) return nullptr; @@ -512,8 +513,7 @@ DWARFDIE DWARFFormValue::Reference() const { value += m_unit->GetOffset(); if (!m_unit->ContainsDIEOffset(value)) { m_unit->GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError( - "DW_FORM_ref* DIE reference 0x%" PRIx64 " is outside of its CU", - value); + "DW_FORM_ref* DIE reference {0:x16} is outside of its CU", value); return {}; } return const_cast<DWARFUnit *>(m_unit)->GetDIE(value); @@ -524,8 +524,7 @@ DWARFDIE DWARFFormValue::Reference() const { DIERef::Section::DebugInfo, value); if (!ref_cu) { m_unit->GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError( - "DW_FORM_ref_addr DIE reference 0x%" PRIx64 " has no matching CU", - value); + "DW_FORM_ref_addr DIE reference {0:x16} has no matching CU", value); return {}; } return ref_cu->GetDIE(value); diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h index 9406bcf0c038..90e07ea67f53 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h @@ -10,8 +10,8 @@ #define LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFFORMVALUE_H #include "DWARFDataExtractor.h" -#include "llvm/ADT/Optional.h" #include <cstddef> +#include <optional> class DWARFUnit; class SymbolFileDWARF; @@ -55,9 +55,9 @@ public: bool ExtractValue(const lldb_private::DWARFDataExtractor &data, lldb::offset_t *offset_ptr); const uint8_t *BlockData() const; - static llvm::Optional<uint8_t> GetFixedSize(dw_form_t form, - const DWARFUnit *u); - llvm::Optional<uint8_t> GetFixedSize() const; + static std::optional<uint8_t> GetFixedSize(dw_form_t form, + const DWARFUnit *u); + std::optional<uint8_t> GetFixedSize() const; DWARFDIE Reference() const; uint64_t Reference(dw_offset_t offset) const; bool Boolean() const { return m_value.value.uval != 0; } diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp index 5131584f5522..6e957f7eae62 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp @@ -11,7 +11,9 @@ #include "Plugins/SymbolFile/DWARF/DWARFDIE.h" #include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h" +#include "lldb/Core/Mangled.h" #include "lldb/Core/Module.h" +#include "lldb/Target/Language.h" using namespace lldb_private; using namespace lldb; @@ -19,15 +21,33 @@ using namespace lldb; DWARFIndex::~DWARFIndex() = default; bool DWARFIndex::ProcessFunctionDIE( - llvm::StringRef name, DIERef ref, SymbolFileDWARF &dwarf, - const CompilerDeclContext &parent_decl_ctx, uint32_t name_type_mask, + const Module::LookupInfo &lookup_info, DIERef ref, SymbolFileDWARF &dwarf, + const CompilerDeclContext &parent_decl_ctx, llvm::function_ref<bool(DWARFDIE die)> callback) { + llvm::StringRef name = lookup_info.GetLookupName().GetStringRef(); + FunctionNameType name_type_mask = lookup_info.GetNameTypeMask(); DWARFDIE die = dwarf.GetDIE(ref); if (!die) { ReportInvalidDIERef(ref, name); return true; } + if (!(name_type_mask & eFunctionNameTypeFull)) { + ConstString name_to_match_against; + if (const char *mangled_die_name = die.GetMangledName()) { + name_to_match_against = ConstString(mangled_die_name); + } else { + SymbolFileDWARF *symbols = die.GetDWARF(); + if (ConstString demangled_die_name = + symbols->ConstructFunctionDemangledName(die)) + name_to_match_against = demangled_die_name; + } + + if (!lookup_info.NameMatchesLookupInfo(name_to_match_against, + lookup_info.GetLanguageType())) + return true; + } + // Exit early if we're searching exclusively for methods or selectors and // we have a context specified (no methods in namespaces). uint32_t looking_for_nonmethods = @@ -82,6 +102,6 @@ bool DWARFIndex::DIERefCallbackImpl::operator()(DIERef ref) const { void DWARFIndex::ReportInvalidDIERef(DIERef ref, llvm::StringRef name) const { m_module.ReportErrorIfModifyDetected( "the DWARF debug information has been modified (accelerator table had " - "bad die 0x%8.8x for '%s')\n", + "bad die {0:x16} for '{1}')\n", ref.die_offset(), name.str().c_str()); } diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.h index c4995e721554..c8207931a819 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.h @@ -13,6 +13,7 @@ #include "Plugins/SymbolFile/DWARF/DWARFDIE.h" #include "Plugins/SymbolFile/DWARF/DWARFFormValue.h" +#include "lldb/Core/Module.h" #include "lldb/Target/Statistics.h" class DWARFDeclContext; @@ -54,9 +55,8 @@ public: GetNamespaces(ConstString name, llvm::function_ref<bool(DWARFDIE die)> callback) = 0; virtual void - GetFunctions(ConstString name, SymbolFileDWARF &dwarf, + GetFunctions(const Module::LookupInfo &lookup_info, SymbolFileDWARF &dwarf, const CompilerDeclContext &parent_decl_ctx, - uint32_t name_type_mask, llvm::function_ref<bool(DWARFDIE die)> callback) = 0; virtual void GetFunctions(const RegularExpression ®ex, @@ -74,10 +74,9 @@ protected: /// the function given by "ref" matches search criteria given by /// "parent_decl_ctx" and "name_type_mask", it is inserted into the "dies" /// vector. - bool ProcessFunctionDIE(llvm::StringRef name, DIERef ref, + bool ProcessFunctionDIE(const Module::LookupInfo &lookup_info, DIERef ref, SymbolFileDWARF &dwarf, const CompilerDeclContext &parent_decl_ctx, - uint32_t name_type_mask, llvm::function_ref<bool(DWARFDIE die)> callback); class DIERefCallbackImpl { diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFTypeUnit.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFTypeUnit.cpp index 48d578977c57..87af7177ca95 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFTypeUnit.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFTypeUnit.cpp @@ -15,9 +15,10 @@ using namespace lldb; using namespace lldb_private; void DWARFTypeUnit::Dump(Stream *s) const { - s->Printf("0x%8.8x: Type Unit: length = 0x%8.8x, version = 0x%4.4x, " - "abbr_offset = 0x%8.8x, addr_size = 0x%2.2x (next CU at " - "{0x%8.8x})\n", - GetOffset(), GetLength(), GetVersion(), GetAbbrevOffset(), - GetAddressByteSize(), GetNextUnitOffset()); + s->Format("{0:x16}: Type Unit: length = {1:x8}, version = {2:x4}, " + "abbr_offset = {3:x8}, addr_size = {4:x2} (next CU at " + "[{5:x16}])\n", + GetOffset(), (uint32_t)GetLength(), GetVersion(), + (uint32_t)GetAbbrevOffset(), GetAddressByteSize(), + GetNextUnitOffset()); } diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp index 7b4a5d8eca3e..ba8d0e9c9927 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp @@ -22,6 +22,7 @@ #include "DWARFTypeUnit.h" #include "LogChannelDWARF.h" #include "SymbolFileDWARFDwo.h" +#include <optional> using namespace lldb; using namespace lldb_private; @@ -51,8 +52,6 @@ void DWARFUnit::ExtractUnitDIENoDwoIfNeeded() { return; // Already parsed ElapsedTime elapsed(m_dwarf.GetDebugInfoParseTimeRef()); - LLDB_SCOPED_TIMERF("%8.8x: DWARFUnit::ExtractUnitDIENoDwoIfNeeded()", - GetOffset()); // Set the offset to that of the first DIE and calculate the start of the // next compilation unit header. @@ -76,21 +75,37 @@ void DWARFUnit::ExtractUnitDIEIfNeeded() { return; m_has_parsed_non_skeleton_unit = true; + m_dwo_error.Clear(); + + if (!m_dwo_id) + return; // No DWO file. std::shared_ptr<SymbolFileDWARFDwo> dwo_symbol_file = m_dwarf.GetDwoSymbolFileForCompileUnit(*this, m_first_die); if (!dwo_symbol_file) return; - DWARFUnit *dwo_cu = dwo_symbol_file->GetDWOCompileUnitForHash(m_dwo_id); + DWARFUnit *dwo_cu = dwo_symbol_file->GetDWOCompileUnitForHash(*m_dwo_id); - if (!dwo_cu) + if (!dwo_cu) { + SetDwoError(Status::createWithFormat( + "unable to load .dwo file from \"{0}\" due to ID ({1:x16}) mismatch " + "for skeleton DIE at {2:x8}", + dwo_symbol_file->GetObjectFile()->GetFileSpec().GetPath().c_str(), + *m_dwo_id, m_first_die.GetOffset())); return; // Can't fetch the compile unit from the dwo file. + } dwo_cu->SetUserData(this); DWARFBaseDIE dwo_cu_die = dwo_cu->GetUnitDIEOnly(); - if (!dwo_cu_die.IsValid()) - return; // Can't fetch the compile unit DIE from the dwo file. + if (!dwo_cu_die.IsValid()) { + // Can't fetch the compile unit DIE from the dwo file. + SetDwoError(Status::createWithFormat( + "unable to extract compile unit DIE from .dwo file for skeleton " + "DIE at {0:x16}", + m_first_die.GetOffset())); + return; + } // Here for DWO CU we want to use the address base set in the skeleton unit // (DW_AT_addr_base) if it is available and use the DW_AT_GNU_addr_base @@ -199,7 +214,11 @@ void DWARFUnit::ExtractDIEsRWLocked() { llvm::sys::ScopedWriter first_die_lock(m_first_die_mutex); ElapsedTime elapsed(m_dwarf.GetDebugInfoParseTimeRef()); - LLDB_SCOPED_TIMERF("%8.8x: DWARFUnit::ExtractDIEsIfNeeded()", GetOffset()); + LLDB_SCOPED_TIMERF( + "%s", + llvm::formatv("{0:x16}: DWARFUnit::ExtractDIEsIfNeeded()", GetOffset()) + .str() + .c_str()); // Set the offset to that of the first DIE and calculate the start of the // next compilation unit header. @@ -322,7 +341,7 @@ void DWARFUnit::SetDwoStrOffsetsBase() { if (const llvm::DWARFUnitIndex::Entry *entry = m_header.GetIndexEntry()) { if (const auto *contribution = entry->getContribution(llvm::DW_SECT_STR_OFFSETS)) - baseOffset = contribution->Offset; + baseOffset = contribution->getOffset32(); else return; } @@ -345,7 +364,7 @@ void DWARFUnit::SetDwoStrOffsetsBase() { SetStrOffsetsBase(baseOffset); } -uint64_t DWARFUnit::GetDWOId() { +std::optional<uint64_t> DWARFUnit::GetDWOId() { ExtractUnitDIENoDwoIfNeeded(); return m_dwo_id; } @@ -466,11 +485,11 @@ void DWARFUnit::SetLoclistsBase(dw_addr_t loclists_base) { if (!contribution) { GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError( "Failed to find location list contribution for CU with DWO Id " - "0x%" PRIx64, - this->GetDWOId()); + "{0:x16}", + *GetDWOId()); return; } - offset += contribution->Offset; + offset += contribution->getOffset32(); } m_loclists_base = loclists_base; @@ -484,8 +503,8 @@ void DWARFUnit::SetLoclistsBase(dw_addr_t loclists_base) { m_dwarf.GetDWARFContext().getOrLoadLocListsData().GetAsLLVM(), &offset)) { GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError( - "Failed to extract location list table at offset 0x%" PRIx64 - " (location list base: 0x%" PRIx64 "): %s", + "Failed to extract location list table at offset {0:x16} (location " + "list base: {1:x16}): {2}", offset, loclists_base, toString(std::move(E)).c_str()); } } @@ -508,8 +527,8 @@ DWARFDataExtractor DWARFUnit::GetLocationData() const { if (const llvm::DWARFUnitIndex::Entry *entry = m_header.GetIndexEntry()) { if (const auto *contribution = entry->getContribution( GetVersion() >= 5 ? llvm::DW_SECT_LOCLISTS : llvm::DW_SECT_EXT_LOC)) - return DWARFDataExtractor(data, contribution->Offset, - contribution->Length); + return DWARFDataExtractor(data, contribution->getOffset32(), + contribution->getLength32()); return DWARFDataExtractor(); } return data; @@ -521,11 +540,10 @@ DWARFDataExtractor DWARFUnit::GetRnglistData() const { if (const llvm::DWARFUnitIndex::Entry *entry = m_header.GetIndexEntry()) { if (const auto *contribution = entry->getContribution(llvm::DW_SECT_RNGLISTS)) - return DWARFDataExtractor(data, contribution->Offset, - contribution->Length); + return DWARFDataExtractor(data, contribution->getOffset32(), + contribution->getLength32()); GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError( - "Failed to find range list contribution for CU with signature " - "0x%" PRIx64, + "Failed to find range list contribution for CU with signature {0:x16}", entry->getSignature()); return DWARFDataExtractor(); @@ -539,7 +557,7 @@ void DWARFUnit::SetRangesBase(dw_addr_t ranges_base) { m_ranges_base = ranges_base; } -const llvm::Optional<llvm::DWARFDebugRnglistTable> & +const std::optional<llvm::DWARFDebugRnglistTable> & DWARFUnit::GetRnglistTable() { if (GetVersion() >= 5 && !m_rnglist_table_done) { m_rnglist_table_done = true; @@ -549,7 +567,7 @@ DWARFUnit::GetRnglistTable() { m_rnglist_table = std::move(table_or_error.get()); else GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError( - "Failed to extract range list table at offset 0x%" PRIx64 ": %s", + "Failed to extract range list table at offset {0:x16}: {1}", m_ranges_base, toString(table_or_error.takeError()).c_str()); } return m_rnglist_table; @@ -561,11 +579,14 @@ llvm::Expected<uint64_t> DWARFUnit::GetRnglistOffset(uint32_t Index) { return llvm::createStringError(std::errc::invalid_argument, "missing or invalid range list table"); if (!m_ranges_base) - return llvm::createStringError(std::errc::invalid_argument, - "DW_FORM_rnglistx cannot be used without " - "DW_AT_rnglists_base for CU at 0x%8.8x", - GetOffset()); - if (llvm::Optional<uint64_t> off = GetRnglistTable()->getOffsetEntry( + return llvm::createStringError( + std::errc::invalid_argument, + llvm::formatv("DW_FORM_rnglistx cannot be used without " + "DW_AT_rnglists_base for CU at {0:x16}", + GetOffset()) + .str() + .c_str()); + if (std::optional<uint64_t> off = GetRnglistTable()->getOffsetEntry( GetRnglistData().GetAsLLVM(), Index)) return *off + m_ranges_base; return llvm::createStringError( @@ -582,7 +603,7 @@ void DWARFUnit::SetStrOffsetsBase(dw_offset_t str_offsets_base) { dw_addr_t DWARFUnit::ReadAddressFromDebugAddrSection(uint32_t index) const { uint32_t index_size = GetAddressByteSize(); dw_offset_t addr_base = GetAddrBase(); - dw_addr_t offset = addr_base + index * index_size; + dw_addr_t offset = addr_base + static_cast<dw_addr_t>(index) * index_size; const DWARFDataExtractor &data = m_dwarf.GetDWARFContext().getOrLoadAddrData(); if (data.ValidOffsetForDataOfSize(offset, index_size)) @@ -595,7 +616,7 @@ void DWARFUnit::ClearDIEsRWLocked() { m_die_array.clear(); m_die_array.shrink_to_fit(); - if (m_dwo) + if (m_dwo && !m_dwo->m_cancel_scopes) m_dwo->ClearDIEsRWLocked(); } @@ -623,8 +644,8 @@ DWARFUnit::GetDIE(dw_offset_t die_offset) { if (!ContainsDIEOffset(die_offset)) { GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError( - "GetDIE for DIE 0x%" PRIx32 " is outside of its CU 0x%" PRIx32, - die_offset, GetOffset()); + "GetDIE for DIE {0:x16} is outside of its CU {0:x16}", die_offset, + GetOffset()); return DWARFDIE(); // Not found } @@ -889,8 +910,8 @@ DWARFUnitHeader::extract(const DWARFDataExtractor &data, header.m_index_entry = Index->getFromHash(header.m_type_hash); } else { Index = &context.GetAsLLVM().getCUIndex(); - if (*Index && header.m_version >= 5) - header.m_index_entry = Index->getFromHash(header.m_dwo_id); + if (*Index && header.m_version >= 5 && header.m_dwo_id) + header.m_index_entry = Index->getFromHash(*header.m_dwo_id); } if (!header.m_index_entry) header.m_index_entry = Index->getFromOffset(header.m_offset); @@ -903,7 +924,7 @@ DWARFUnitHeader::extract(const DWARFDataExtractor &data, "Package unit with a non-zero abbreviation offset"); } auto *unit_contrib = header.m_index_entry->getContribution(); - if (!unit_contrib || unit_contrib->Length != header.m_length + 4) { + if (!unit_contrib || unit_contrib->getLength32() != header.m_length + 4) { return llvm::createStringError(llvm::inconvertibleErrorCode(), "Inconsistent DWARF package unit index"); } @@ -914,7 +935,7 @@ DWARFUnitHeader::extract(const DWARFDataExtractor &data, llvm::inconvertibleErrorCode(), "DWARF package index missing abbreviation column"); } - header.m_abbr_offset = abbr_entry->Offset; + header.m_abbr_offset = abbr_entry->getOffset32(); } bool length_OK = data.ValidOffset(header.GetNextUnitOffset() - 1); @@ -997,7 +1018,7 @@ uint32_t DWARFUnit::GetHeaderByteSize() const { llvm_unreachable("invalid UnitType."); } -llvm::Optional<uint64_t> +std::optional<uint64_t> DWARFUnit::GetStringOffsetSectionItem(uint32_t index) const { offset_t offset = GetStrOffsetsBase() + index * 4; return m_dwarf.GetDWARFContext().getOrLoadStrOffsetsData().GetU32(&offset); @@ -1033,7 +1054,8 @@ DWARFUnit::FindRnglistFromOffset(dw_offset_t offset) { GetAddressByteSize(), [&](uint32_t index) { uint32_t index_size = GetAddressByteSize(); dw_offset_t addr_base = GetAddrBase(); - lldb::offset_t offset = addr_base + index * index_size; + lldb::offset_t offset = + addr_base + static_cast<lldb::offset_t>(index) * index_size; return llvm::object::SectionedAddress{ m_dwarf.GetDWARFContext().getOrLoadAddrData().GetMaxU64( &offset, index_size)}; @@ -1056,3 +1078,18 @@ DWARFUnit::FindRnglistFromIndex(uint32_t index) { return maybe_offset.takeError(); return FindRnglistFromOffset(*maybe_offset); } + + +bool DWARFUnit::HasAny(llvm::ArrayRef<dw_tag_t> tags) { + ExtractUnitDIEIfNeeded(); + if (m_dwo) + return m_dwo->HasAny(tags); + + for (const auto &die: m_die_array) { + for (const auto tag: tags) { + if (tag == die.Tag()) + return true; + } + } + return false; +} diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h index 40a1943b847a..a70628a3866a 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h @@ -16,6 +16,7 @@ #include "llvm/DebugInfo/DWARF/DWARFDebugRnglists.h" #include "llvm/Support/RWMutex.h" #include <atomic> +#include <optional> class DWARFUnit; class DWARFCompileUnit; @@ -51,7 +52,7 @@ class DWARFUnitHeader { uint64_t m_type_hash = 0; uint32_t m_type_offset = 0; - uint64_t m_dwo_id = 0; + std::optional<uint64_t> m_dwo_id; DWARFUnitHeader() = default; @@ -67,7 +68,7 @@ public: } uint64_t GetTypeHash() const { return m_type_hash; } dw_offset_t GetTypeOffset() const { return m_type_offset; } - uint64_t GetDWOId() const { return m_dwo_id; } + std::optional<uint64_t> GetDWOId() const { return m_dwo_id; } bool IsTypeUnit() const { return m_unit_type == llvm::dwarf::DW_UT_type || m_unit_type == llvm::dwarf::DW_UT_split_type; @@ -92,7 +93,7 @@ public: virtual ~DWARFUnit(); bool IsDWOUnit() { return m_is_dwo; } - uint64_t GetDWOId(); + std::optional<uint64_t> GetDWOId(); void ExtractUnitDIEIfNeeded(); void ExtractUnitDIENoDwoIfNeeded(); @@ -223,7 +224,7 @@ public: uint8_t GetUnitType() const { return m_header.GetUnitType(); } bool IsTypeUnit() const { return m_header.IsTypeUnit(); } - llvm::Optional<uint64_t> GetStringOffsetSectionItem(uint32_t index) const; + std::optional<uint64_t> GetStringOffsetSectionItem(uint32_t index) const; /// Return a list of address ranges resulting from a (possibly encoded) /// range list starting at a given offset in the appropriate ranges section. @@ -239,14 +240,14 @@ public: /// DW_FORM_rnglistx. llvm::Expected<uint64_t> GetRnglistOffset(uint32_t Index); - llvm::Optional<uint64_t> GetLoclistOffset(uint32_t Index) { + std::optional<uint64_t> GetLoclistOffset(uint32_t Index) { if (!m_loclist_table_header) - return llvm::None; + return std::nullopt; - llvm::Optional<uint64_t> Offset = m_loclist_table_header->getOffsetEntry( + std::optional<uint64_t> Offset = m_loclist_table_header->getOffsetEntry( m_dwarf.GetDWARFContext().getOrLoadLocListsData().GetAsLLVM(), Index); if (!Offset) - return llvm::None; + return std::nullopt; return *Offset + m_loclists_base; } @@ -257,6 +258,34 @@ public: lldb_private::DWARFDataExtractor GetLocationData() const; + /// Returns true if any DIEs in the unit match any DW_TAG values in \a tags. + /// + /// \param[in] tags + /// An array of dw_tag_t values to check all abbrevitions for. + /// + /// \returns + /// True if any DIEs match any tag in \a tags, false otherwise. + bool HasAny(llvm::ArrayRef<dw_tag_t> tags); + + + /// Get the fission .dwo file specific error for this compile unit. + /// + /// The skeleton compile unit only can have a DWO error. Any other type + /// of DWARFUnit will not have a valid DWO error. + /// + /// \returns + /// A valid DWO error if there is a problem with anything in the + /// locating or parsing inforamtion in the .dwo file + const lldb_private::Status &GetDwoError() const { return m_dwo_error; } + + /// Set the fission .dwo file specific error for this compile unit. + /// + /// This helps tracks issues that arise when trying to locate or parse a + /// .dwo file. Things like a missing .dwo file, DWO ID mismatch, and other + /// .dwo errors can be stored in each compile unit so the issues can be + /// communicated to the user. + void SetDwoError(const lldb_private::Status &error) { m_dwo_error = error; } + protected: DWARFUnit(SymbolFileDWARF &dwarf, lldb::user_id_t uid, const DWARFUnitHeader &header, @@ -285,7 +314,7 @@ protected: return &m_die_array[0]; } - const llvm::Optional<llvm::DWARFDebugRnglistTable> &GetRnglistTable(); + const std::optional<llvm::DWARFDebugRnglistTable> &GetRnglistTable(); lldb_private::DWARFDataExtractor GetRnglistData() const; @@ -313,30 +342,34 @@ protected: dw_addr_t m_base_addr = 0; DWARFProducer m_producer = eProducerInvalid; llvm::VersionTuple m_producer_version; - llvm::Optional<uint64_t> m_language_type; + std::optional<uint64_t> m_language_type; lldb_private::LazyBool m_is_optimized = lldb_private::eLazyBoolCalculate; - llvm::Optional<lldb_private::FileSpec> m_comp_dir; - llvm::Optional<lldb_private::FileSpec> m_file_spec; - llvm::Optional<dw_addr_t> m_addr_base; ///< Value of DW_AT_addr_base. + std::optional<lldb_private::FileSpec> m_comp_dir; + std::optional<lldb_private::FileSpec> m_file_spec; + std::optional<dw_addr_t> m_addr_base; ///< Value of DW_AT_addr_base. dw_addr_t m_loclists_base = 0; ///< Value of DW_AT_loclists_base. dw_addr_t m_ranges_base = 0; ///< Value of DW_AT_rnglists_base. - llvm::Optional<uint64_t> m_gnu_addr_base; - llvm::Optional<uint64_t> m_gnu_ranges_base; + std::optional<uint64_t> m_gnu_addr_base; + std::optional<uint64_t> m_gnu_ranges_base; /// Value of DW_AT_stmt_list. dw_offset_t m_line_table_offset = DW_INVALID_OFFSET; dw_offset_t m_str_offsets_base = 0; // Value of DW_AT_str_offsets_base. - llvm::Optional<llvm::DWARFDebugRnglistTable> m_rnglist_table; + std::optional<llvm::DWARFDebugRnglistTable> m_rnglist_table; bool m_rnglist_table_done = false; - llvm::Optional<llvm::DWARFListTableHeader> m_loclist_table_header; + std::optional<llvm::DWARFListTableHeader> m_loclist_table_header; const DIERef::Section m_section; bool m_is_dwo; bool m_has_parsed_non_skeleton_unit; /// Value of DW_AT_GNU_dwo_id (v4) or dwo_id from CU header (v5). - uint64_t m_dwo_id; + std::optional<uint64_t> m_dwo_id; + /// If we get an error when trying to load a .dwo file, save that error here. + /// Errors include .dwo/.dwp file not found, or the .dwp/.dwp file was found + /// but DWO ID doesn't match, etc. + lldb_private::Status m_dwo_error; private: void ParseProducerInfo(); diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp index ad22078ffa3e..68adb3705100 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp @@ -13,6 +13,7 @@ #include "lldb/Core/Module.h" #include "lldb/Utility/RegularExpression.h" #include "lldb/Utility/Stream.h" +#include <optional> using namespace lldb_private; using namespace lldb; @@ -41,28 +42,28 @@ DebugNamesDWARFIndex::GetUnits(const DebugNames &debug_names) { return result; } -llvm::Optional<DIERef> +std::optional<DIERef> DebugNamesDWARFIndex::ToDIERef(const DebugNames::Entry &entry) { - llvm::Optional<uint64_t> cu_offset = entry.getCUOffset(); + std::optional<uint64_t> cu_offset = entry.getCUOffset(); if (!cu_offset) - return llvm::None; + return std::nullopt; DWARFUnit *cu = m_debug_info.GetUnitAtOffset(DIERef::Section::DebugInfo, *cu_offset); if (!cu) - return llvm::None; + return std::nullopt; cu = &cu->GetNonSkeletonUnit(); - if (llvm::Optional<uint64_t> die_offset = entry.getDIEUnitOffset()) + if (std::optional<uint64_t> die_offset = entry.getDIEUnitOffset()) return DIERef(cu->GetSymbolFileDWARF().GetDwoNum(), DIERef::Section::DebugInfo, cu->GetOffset() + *die_offset); - return llvm::None; + return std::nullopt; } bool DebugNamesDWARFIndex::ProcessEntry( const DebugNames::Entry &entry, llvm::function_ref<bool(DWARFDIE die)> callback, llvm::StringRef name) { - llvm::Optional<DIERef> ref = ToDIERef(entry); + std::optional<DIERef> ref = ToDIERef(entry); if (!ref) return true; SymbolFileDWARF &dwarf = *llvm::cast<SymbolFileDWARF>( @@ -165,7 +166,7 @@ void DebugNamesDWARFIndex::GetCompleteObjCClass( entry.tag() != DW_TAG_class_type) continue; - llvm::Optional<DIERef> ref = ToDIERef(entry); + std::optional<DIERef> ref = ToDIERef(entry); if (!ref) continue; @@ -238,10 +239,10 @@ void DebugNamesDWARFIndex::GetNamespaces( } void DebugNamesDWARFIndex::GetFunctions( - ConstString name, SymbolFileDWARF &dwarf, - const CompilerDeclContext &parent_decl_ctx, uint32_t name_type_mask, + const Module::LookupInfo &lookup_info, SymbolFileDWARF &dwarf, + const CompilerDeclContext &parent_decl_ctx, llvm::function_ref<bool(DWARFDIE die)> callback) { - + ConstString name = lookup_info.GetLookupName(); std::set<DWARFDebugInfoEntry *> seen; for (const DebugNames::Entry &entry : m_debug_names_up->equal_range(name.GetStringRef())) { @@ -249,9 +250,9 @@ void DebugNamesDWARFIndex::GetFunctions( if (tag != DW_TAG_subprogram && tag != DW_TAG_inlined_subroutine) continue; - if (llvm::Optional<DIERef> ref = ToDIERef(entry)) { - if (!ProcessFunctionDIE(name.GetStringRef(), *ref, dwarf, parent_decl_ctx, - name_type_mask, [&](DWARFDIE die) { + if (std::optional<DIERef> ref = ToDIERef(entry)) { + if (!ProcessFunctionDIE(lookup_info, *ref, dwarf, parent_decl_ctx, + [&](DWARFDIE die) { if (!seen.insert(die.GetDIE()).second) return true; return callback(die); @@ -260,8 +261,7 @@ void DebugNamesDWARFIndex::GetFunctions( } } - m_fallback.GetFunctions(name, dwarf, parent_decl_ctx, name_type_mask, - callback); + m_fallback.GetFunctions(lookup_info, dwarf, parent_decl_ctx, callback); } void DebugNamesDWARFIndex::GetFunctions( diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h index c451ccd4857f..21a3d8dcc0e3 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h @@ -15,6 +15,7 @@ #include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h" #include "lldb/Utility/ConstString.h" #include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h" +#include <optional> namespace lldb_private { class DebugNamesDWARFIndex : public DWARFIndex { @@ -46,9 +47,9 @@ public: llvm::function_ref<bool(DWARFDIE die)> callback) override; void GetNamespaces(ConstString name, llvm::function_ref<bool(DWARFDIE die)> callback) override; - void GetFunctions(ConstString name, SymbolFileDWARF &dwarf, + void GetFunctions(const Module::LookupInfo &lookup_info, + SymbolFileDWARF &dwarf, const CompilerDeclContext &parent_decl_ctx, - uint32_t name_type_mask, llvm::function_ref<bool(DWARFDIE die)> callback) override; void GetFunctions(const RegularExpression ®ex, llvm::function_ref<bool(DWARFDIE die)> callback) override; @@ -77,7 +78,7 @@ private: std::unique_ptr<DebugNames> m_debug_names_up; ManualDWARFIndex m_fallback; - llvm::Optional<DIERef> ToDIERef(const DebugNames::Entry &entry); + std::optional<DIERef> ToDIERef(const DebugNames::Entry &entry); bool ProcessEntry(const DebugNames::Entry &entry, llvm::function_ref<bool(DWARFDIE die)> callback, llvm::StringRef name); diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp index fdc24e23d16b..c31a3d8ce913 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp @@ -174,7 +174,7 @@ void DWARFMappedHash::Prologue::AppendAtom(AtomType type, dw_form_t form) { case DW_FORM_GNU_addr_index: case DW_FORM_GNU_str_index: hash_data_has_fixed_byte_size = false; - LLVM_FALLTHROUGH; + [[fallthrough]]; case DW_FORM_flag: case DW_FORM_data1: case DW_FORM_ref1: @@ -184,7 +184,7 @@ void DWARFMappedHash::Prologue::AppendAtom(AtomType type, dw_form_t form) { case DW_FORM_block2: hash_data_has_fixed_byte_size = false; - LLVM_FALLTHROUGH; + [[fallthrough]]; case DW_FORM_data2: case DW_FORM_ref2: min_hash_data_byte_size += 2; @@ -192,7 +192,7 @@ void DWARFMappedHash::Prologue::AppendAtom(AtomType type, dw_form_t form) { case DW_FORM_block4: hash_data_has_fixed_byte_size = false; - LLVM_FALLTHROUGH; + [[fallthrough]]; case DW_FORM_data4: case DW_FORM_ref4: case DW_FORM_addr: diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h index efc08e47a280..0006949865de 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h @@ -65,7 +65,7 @@ public: DIEInfo(dw_offset_t o, dw_tag_t t, uint32_t f, uint32_t h); explicit operator DIERef() const { - return DIERef(llvm::None, DIERef::Section::DebugInfo, die_offset); + return DIERef(std::nullopt, DIERef::Section::DebugInfo, die_offset); } }; diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.cpp index d2b8fe19db53..6b063f3bd88d 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.cpp @@ -12,14 +12,16 @@ using namespace lldb_private; static constexpr Log::Category g_categories[] = { {{"comp"}, - {"log insertions of object files into DWARF debug maps"}, + {"log struct/union/class type completions"}, DWARFLog::TypeCompletion}, {{"info"}, {"log the parsing of .debug_info"}, DWARFLog::DebugInfo}, {{"line"}, {"log the parsing of .debug_line"}, DWARFLog::DebugLine}, {{"lookups"}, {"log any lookups that happen by name, regex, or address"}, DWARFLog::Lookups}, - {{"map"}, {"log struct/unions/class type completions"}, DWARFLog::DebugMap}, + {{"map"}, + {"log insertions of object files into DWARF debug maps"}, + DWARFLog::DebugMap}, }; static Log::Channel g_channel(g_categories, DWARFLog::DebugInfo); diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp index b743c84c10e0..a31622fc8b99 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp @@ -23,6 +23,7 @@ #include "lldb/Utility/Timer.h" #include "llvm/Support/FormatVariadic.h" #include "llvm/Support/ThreadPool.h" +#include <optional> using namespace lldb_private; using namespace lldb; @@ -81,7 +82,7 @@ void ManualDWARFIndex::Index() { // Keep memory down by clearing DIEs for any units if indexing // caused us to load the unit's DIEs. - std::vector<llvm::Optional<DWARFUnit::ScopedExtractDIEs>> clear_cu_dies( + std::vector<std::optional<DWARFUnit::ScopedExtractDIEs>> clear_cu_dies( units_to_index.size()); auto parser_fn = [&](size_t cu_idx) { IndexUnit(*units_to_index[cu_idx], dwp_dwarf, sets[cu_idx]); @@ -142,25 +143,42 @@ void ManualDWARFIndex::IndexUnit(DWARFUnit &unit, SymbolFileDWARFDwo *dwp, if (log) { m_module.LogMessage( - log, "ManualDWARFIndex::IndexUnit for unit at .debug_info[0x%8.8x]", + log, "ManualDWARFIndex::IndexUnit for unit at .debug_info[{0:x16}]", unit.GetOffset()); } const LanguageType cu_language = SymbolFileDWARF::GetLanguage(unit); - IndexUnitImpl(unit, cu_language, set); - - if (SymbolFileDWARFDwo *dwo_symbol_file = unit.GetDwoSymbolFile()) { - // Type units in a dwp file are indexed separately, so we just need to - // process the split unit here. However, if the split unit is in a dwo file, - // then we need to process type units here. - if (dwo_symbol_file == dwp) { - IndexUnitImpl(unit.GetNonSkeletonUnit(), cu_language, set); - } else { - DWARFDebugInfo &dwo_info = dwo_symbol_file->DebugInfo(); - for (size_t i = 0; i < dwo_info.GetNumUnits(); ++i) - IndexUnitImpl(*dwo_info.GetUnitAtIndex(i), cu_language, set); + // First check if the unit has a DWO ID. If it does then we only want to index + // the .dwo file or nothing at all. If we have a compile unit where we can't + // locate the .dwo/.dwp file we don't want to index anything from the skeleton + // compile unit because it is usally has no children unless + // -fsplit-dwarf-inlining was used at compile time. This option will add a + // copy of all DW_TAG_subprogram and any contained DW_TAG_inline_subroutine + // DIEs so that symbolication will still work in the absence of the .dwo/.dwp + // file, but the functions have no return types and all arguments and locals + // have been removed. So we don't want to index any of these hacked up + // function types. Types can still exist in the skeleton compile unit DWARF + // though as some functions have template parameter types and other things + // that cause extra copies of types to be included, but we should find these + // types in the .dwo file only as methods could have return types removed and + // we don't have to index incomplete types from the skeletone compile unit. + if (unit.GetDWOId()) { + if (SymbolFileDWARFDwo *dwo_symbol_file = unit.GetDwoSymbolFile()) { + // Type units in a dwp file are indexed separately, so we just need to + // process the split unit here. However, if the split unit is in a dwo file, + // then we need to process type units here. + if (dwo_symbol_file == dwp) { + IndexUnitImpl(unit.GetNonSkeletonUnit(), cu_language, set); + } else { + DWARFDebugInfo &dwo_info = dwo_symbol_file->DebugInfo(); + for (size_t i = 0; i < dwo_info.GetNumUnits(); ++i) + IndexUnitImpl(*dwo_info.GetUnitAtIndex(i), cu_language, set); + } } + } else { + // We either have a normal compile unit which we want to index. + IndexUnitImpl(unit, cu_language, set); } } @@ -411,10 +429,12 @@ void ManualDWARFIndex::GetNamespaces( } void ManualDWARFIndex::GetFunctions( - ConstString name, SymbolFileDWARF &dwarf, - const CompilerDeclContext &parent_decl_ctx, uint32_t name_type_mask, + const Module::LookupInfo &lookup_info, SymbolFileDWARF &dwarf, + const CompilerDeclContext &parent_decl_ctx, llvm::function_ref<bool(DWARFDIE die)> callback) { Index(); + ConstString name = lookup_info.GetLookupName(); + FunctionNameType name_type_mask = lookup_info.GetNameTypeMask(); if (name_type_mask & eFunctionNameTypeFull) { if (!m_set.function_fullnames.Find( diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h index 5c5e43de9ca6..d95cf501face 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h @@ -46,9 +46,9 @@ public: llvm::function_ref<bool(DWARFDIE die)> callback) override; void GetNamespaces(ConstString name, llvm::function_ref<bool(DWARFDIE die)> callback) override; - void GetFunctions(ConstString name, SymbolFileDWARF &dwarf, + void GetFunctions(const Module::LookupInfo &lookup_info, + SymbolFileDWARF &dwarf, const CompilerDeclContext &parent_decl_ctx, - uint32_t name_type_mask, llvm::function_ref<bool(DWARFDIE die)> callback) override; void GetFunctions(const RegularExpression ®ex, llvm::function_ref<bool(DWARFDIE die)> callback) override; diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp index de98403421e0..d6cee149f404 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp @@ -16,6 +16,7 @@ #include "lldb/Utility/RegularExpression.h" #include "lldb/Utility/Stream.h" #include "lldb/Utility/StreamString.h" +#include <optional> using namespace lldb; using namespace lldb_private; @@ -106,7 +107,7 @@ bool NameToDIE::Decode(const DataExtractor &data, lldb::offset_t *offset_ptr, // No empty strings allowed in the name to DIE maps. if (str.empty()) return false; - if (llvm::Optional<DIERef> die_ref = DIERef::Decode(data, offset_ptr)) + if (std::optional<DIERef> die_ref = DIERef::Decode(data, offset_ptr)) m_map.Append(ConstString(str), *die_ref); else return false; diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index 8ee709db9cdb..544c9e08d504 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -8,7 +8,6 @@ #include "SymbolFileDWARF.h" -#include "llvm/ADT/Optional.h" #include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Threading.h" @@ -82,6 +81,7 @@ #include <algorithm> #include <map> #include <memory> +#include <optional> #include <cctype> #include <cstring> @@ -130,13 +130,13 @@ public: } }; +} // namespace + static PluginProperties &GetGlobalPluginProperties() { static PluginProperties g_settings; return g_settings; } -} // namespace - static const llvm::DWARFDebugLine::LineTable * ParseLLVMLineTable(lldb_private::DWARFContext &context, llvm::DWARFDebugLine &line, dw_offset_t line_offset, @@ -188,7 +188,7 @@ static bool ParseLLVMLineTablePrologue(lldb_private::DWARFContext &context, return success; } -static llvm::Optional<std::string> +static std::optional<std::string> GetFileByIndex(const llvm::DWARFDebugLine::Prologue &prologue, size_t idx, llvm::StringRef compile_dir, FileSpec::Style style) { // Try to get an absolute path first. @@ -432,16 +432,16 @@ UniqueDWARFASTTypeMap &SymbolFileDWARF::GetUniqueDWARFASTTypeMap() { return m_unique_ast_type_map; } -llvm::Expected<TypeSystem &> +llvm::Expected<lldb::TypeSystemSP> SymbolFileDWARF::GetTypeSystemForLanguage(LanguageType language) { if (SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile()) return debug_map_symfile->GetTypeSystemForLanguage(language); auto type_system_or_err = m_objfile_sp->GetModule()->GetTypeSystemForLanguage(language); - if (type_system_or_err) { - type_system_or_err->SetSymbolFile(this); - } + if (type_system_or_err) + if (auto ts = *type_system_or_err) + ts->SetSymbolFile(this); return type_system_or_err; } @@ -556,7 +556,7 @@ uint32_t SymbolFileDWARF::CalculateAbilities() { for (auto form : invalid_forms) error.Printf(" %#x", form); m_objfile_sp->GetModule()->ReportWarning( - "%s", error.GetString().str().c_str()); + "{0}", error.GetString().str().c_str()); return 0; } } @@ -702,9 +702,9 @@ lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFCompileUnit &dwarf_cu) { // We already parsed this compile unit, had out a shared pointer to it cu_sp = comp_unit->shared_from_this(); } else { - if (dwarf_cu.GetOffset() == 0 && GetDebugMapSymfile()) { + if (GetDebugMapSymfile()) { // Let the debug map create the compile unit - cu_sp = m_debug_map_symfile->GetCompileUnit(this); + cu_sp = m_debug_map_symfile->GetCompileUnit(this, dwarf_cu); dwarf_cu.SetUserData(cu_sp.get()); } else { ModuleSP module_sp(m_objfile_sp->GetModule()); @@ -793,12 +793,12 @@ void SymbolFileDWARF::BuildCuTranslationTable() { } } -llvm::Optional<uint32_t> SymbolFileDWARF::GetDWARFUnitIndex(uint32_t cu_idx) { +std::optional<uint32_t> SymbolFileDWARF::GetDWARFUnitIndex(uint32_t cu_idx) { BuildCuTranslationTable(); if (m_lldb_cu_to_dwarf_unit.empty()) return cu_idx; if (cu_idx >= m_lldb_cu_to_dwarf_unit.size()) - return llvm::None; + return std::nullopt; return m_lldb_cu_to_dwarf_unit[cu_idx]; } @@ -810,7 +810,7 @@ uint32_t SymbolFileDWARF::CalculateNumCompileUnits() { CompUnitSP SymbolFileDWARF::ParseCompileUnitAtIndex(uint32_t cu_idx) { ASSERT_MODULE_LOCK(this); - if (llvm::Optional<uint32_t> dwarf_idx = GetDWARFUnitIndex(cu_idx)) { + if (std::optional<uint32_t> dwarf_idx = GetDWARFUnitIndex(cu_idx)) { if (auto *dwarf_cu = llvm::cast_or_null<DWARFCompileUnit>( DebugInfo().GetUnitAtIndex(*dwarf_idx))) return ParseCompileUnit(*dwarf_cu); @@ -830,7 +830,10 @@ Function *SymbolFileDWARF::ParseFunction(CompileUnit &comp_unit, "Unable to parse function"); return nullptr; } - DWARFASTParser *dwarf_ast = type_system_or_err->GetDWARFParser(); + auto ts = *type_system_or_err; + if (!ts) + return nullptr; + DWARFASTParser *dwarf_ast = ts->GetDWARFParser(); if (!dwarf_ast) return nullptr; @@ -862,6 +865,32 @@ Function *SymbolFileDWARF::ParseFunction(CompileUnit &comp_unit, return dwarf_ast->ParseFunctionFromDWARF(comp_unit, die, func_range); } +ConstString +SymbolFileDWARF::ConstructFunctionDemangledName(const DWARFDIE &die) { + ASSERT_MODULE_LOCK(this); + if (!die.IsValid()) { + return ConstString(); + } + + auto type_system_or_err = GetTypeSystemForLanguage(GetLanguage(*die.GetCU())); + if (auto err = type_system_or_err.takeError()) { + LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err), + "Unable to construct demangled name for function"); + return ConstString(); + } + + auto ts = *type_system_or_err; + if (!ts) { + LLDB_LOG(GetLog(LLDBLog::Symbols), "Type system no longer live"); + return ConstString(); + } + DWARFASTParser *dwarf_ast = ts->GetDWARFParser(); + if (!dwarf_ast) + return ConstString(); + + return dwarf_ast->ConstructDemangledNameFromDWARF(die); +} + lldb::addr_t SymbolFileDWARF::FixupAddress(lldb::addr_t file_addr) { SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile(); if (debug_map_symfile) @@ -993,10 +1022,9 @@ bool SymbolFileDWARF::ParseSupportFiles(DWARFUnit &dwarf_cu, dwarf_cu.GetOffset())) return false; + std::string comp_dir = dwarf_cu.GetCompilationDirectory().GetPath(); support_files = ParseSupportFilesFromPrologue( - module, prologue, dwarf_cu.GetPathStyle(), - dwarf_cu.GetCompilationDirectory().GetCString()); - + module, prologue, dwarf_cu.GetPathStyle(), comp_dir); return true; } @@ -1286,9 +1314,9 @@ size_t SymbolFileDWARF::ParseBlocksRecursive( range.GetByteSize())); else { GetObjectFile()->GetModule()->ReportError( - "0x%8.8" PRIx64 ": adding range [0x%" PRIx64 "-0x%" PRIx64 - ") which has a base that is less than the function's low PC " - "0x%" PRIx64 ". Please file a bug and attach the file at the " + "{0x:+8}: adding range [{1:x16}-{2:x16}) which has a base " + "that is less than the function's low PC {3:x16}. Please file " + "a bug and attach the file at the " "start of this error message", block->GetID(), range_base, range.GetRangeEnd(), subprogram_low_pc); @@ -1378,7 +1406,7 @@ user_id_t SymbolFileDWARF::GetUID(DIERef ref) { lldb::user_id_t(ref.section() == DIERef::Section::DebugTypes) << 63; } -llvm::Optional<SymbolFileDWARF::DecodedUID> +std::optional<SymbolFileDWARF::DecodedUID> SymbolFileDWARF::DecodeUID(lldb::user_id_t uid) { // This method can be called without going through the symbol vendor so we // need to lock the module. @@ -1394,16 +1422,16 @@ SymbolFileDWARF::DecodeUID(lldb::user_id_t uid) { SymbolFileDWARF *dwarf = debug_map->GetSymbolFileByOSOIndex( debug_map->GetOSOIndexFromUserID(uid)); return DecodedUID{ - *dwarf, {llvm::None, DIERef::Section::DebugInfo, dw_offset_t(uid)}}; + *dwarf, {std::nullopt, DIERef::Section::DebugInfo, dw_offset_t(uid)}}; } dw_offset_t die_offset = uid; if (die_offset == DW_INVALID_OFFSET) - return llvm::None; + return std::nullopt; DIERef::Section section = uid >> 63 ? DIERef::Section::DebugTypes : DIERef::Section::DebugInfo; - llvm::Optional<uint32_t> dwo_num; + std::optional<uint32_t> dwo_num; bool dwo_valid = uid >> 62 & 1; if (dwo_valid) dwo_num = uid >> 32 & 0x3fffffff; @@ -1417,7 +1445,7 @@ SymbolFileDWARF::GetDIE(lldb::user_id_t uid) { // need to lock the module. std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); - llvm::Optional<DecodedUID> decoded = DecodeUID(uid); + std::optional<DecodedUID> decoded = DecodeUID(uid); if (decoded) return decoded->dwarf.GetDIE(decoded->ref); @@ -1472,14 +1500,13 @@ Type *SymbolFileDWARF::ResolveTypeUID(lldb::user_id_t type_uid) { return nullptr; } -llvm::Optional<SymbolFile::ArrayInfo> -SymbolFileDWARF::GetDynamicArrayInfoForUID( +std::optional<SymbolFile::ArrayInfo> SymbolFileDWARF::GetDynamicArrayInfoForUID( lldb::user_id_t type_uid, const lldb_private::ExecutionContext *exe_ctx) { std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); if (DWARFDIE type_die = GetDIE(type_uid)) return DWARFASTParser::ParseChildArrayInfo(type_die, exe_ctx); else - return llvm::None; + return std::nullopt; } Type *SymbolFileDWARF::ResolveTypeUID(const DIERef &die_ref) { @@ -1492,7 +1519,7 @@ Type *SymbolFileDWARF::ResolveTypeUID(const DWARFDIE &die, Log *log = GetLog(DWARFLog::DebugInfo); if (log) GetObjectFile()->GetModule()->LogMessage( - log, "SymbolFileDWARF::ResolveTypeUID (die = 0x%8.8x) %s '%s'", + log, "SymbolFileDWARF::ResolveTypeUID (die = {0:x16}) {1} '{2}'", die.GetOffset(), die.GetTagAsCString(), die.GetName()); // We might be coming in in the middle of a type tree (a class within a @@ -1509,8 +1536,9 @@ Type *SymbolFileDWARF::ResolveTypeUID(const DWARFDIE &die, if (log) GetObjectFile()->GetModule()->LogMessage( log, - "SymbolFileDWARF::ResolveTypeUID (die = 0x%8.8x) %s '%s' " - "resolve parent forward type for 0x%8.8x", + "SymbolFileDWARF::ResolveTypeUID (die = {0:x16}) " + "{1} '{2}' " + "resolve parent forward type for {3:x16})", die.GetOffset(), die.GetTagAsCString(), die.GetName(), decl_ctx_die.GetOffset()); } break; @@ -1536,10 +1564,8 @@ bool SymbolFileDWARF::HasForwardDeclForClangType( compiler_type_no_qualifiers.GetOpaqueQualType())) { return true; } - TypeSystem *type_system = compiler_type.GetTypeSystem(); - - TypeSystemClang *clang_type_system = - llvm::dyn_cast_or_null<TypeSystemClang>(type_system); + auto type_system = compiler_type.GetTypeSystem(); + auto clang_type_system = type_system.dyn_cast_or_null<TypeSystemClang>(); if (!clang_type_system) return false; DWARFASTParserClang *ast_parser = @@ -1549,9 +1575,8 @@ bool SymbolFileDWARF::HasForwardDeclForClangType( bool SymbolFileDWARF::CompleteType(CompilerType &compiler_type) { std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); - - TypeSystemClang *clang_type_system = - llvm::dyn_cast_or_null<TypeSystemClang>(compiler_type.GetTypeSystem()); + auto clang_type_system = + compiler_type.GetTypeSystem().dyn_cast_or_null<TypeSystemClang>(); if (clang_type_system) { DWARFASTParserClang *ast_parser = static_cast<DWARFASTParserClang *>(clang_type_system->GetDWARFParser()); @@ -1583,7 +1608,7 @@ bool SymbolFileDWARF::CompleteType(CompilerType &compiler_type) { Log *log = GetLog(DWARFLog::DebugInfo | DWARFLog::TypeCompletion); if (log) GetObjectFile()->GetModule()->LogMessageVerboseBacktrace( - log, "0x%8.8" PRIx64 ": %s '%s' resolving forward declaration...", + log, "{0:x8}: {1} '{2}' resolving forward declaration...", dwarf_die.GetID(), dwarf_die.GetTagAsCString(), type->GetName().AsCString()); assert(compiler_type); @@ -1604,7 +1629,7 @@ Type *SymbolFileDWARF::ResolveType(const DWARFDIE &die, return type; GetObjectFile()->GetModule()->ReportError( - "Parsing a die that is being parsed die: 0x%8.8x: %s %s", + "Parsing a die that is being parsed die: {0:x16}: {1} {2}", die.GetOffset(), die.GetTagAsCString(), die.GetName()); } else @@ -1681,23 +1706,21 @@ SymbolFileDWARF::GetDIE(const DIERef &die_ref) { } /// Return the DW_AT_(GNU_)dwo_id. -/// FIXME: Technically 0 is a valid hash. -static uint64_t GetDWOId(DWARFCompileUnit &dwarf_cu, - const DWARFDebugInfoEntry &cu_die) { - uint64_t dwo_id = - cu_die.GetAttributeValueAsUnsigned(&dwarf_cu, DW_AT_GNU_dwo_id, 0); - if (!dwo_id) - dwo_id = cu_die.GetAttributeValueAsUnsigned(&dwarf_cu, DW_AT_dwo_id, 0); - return dwo_id; +static std::optional<uint64_t> GetDWOId(DWARFCompileUnit &dwarf_cu, + const DWARFDebugInfoEntry &cu_die) { + std::optional<uint64_t> dwo_id = + cu_die.GetAttributeValueAsOptionalUnsigned(&dwarf_cu, DW_AT_GNU_dwo_id); + if (dwo_id) + return dwo_id; + return cu_die.GetAttributeValueAsOptionalUnsigned(&dwarf_cu, DW_AT_dwo_id); } -llvm::Optional<uint64_t> SymbolFileDWARF::GetDWOId() { +std::optional<uint64_t> SymbolFileDWARF::GetDWOId() { if (GetNumCompileUnits() == 1) { if (auto comp_unit = GetCompileUnitAtIndex(0)) if (DWARFCompileUnit *cu = GetDWARFCompileUnit(comp_unit.get())) if (DWARFDebugInfoEntry *cu_die = cu->DIE().GetDIE()) - if (uint64_t dwo_id = ::GetDWOId(*cu, *cu_die)) - return dwo_id; + return ::GetDWOId(*cu, *cu_die); } return {}; } @@ -1714,24 +1737,35 @@ SymbolFileDWARF::GetDwoSymbolFileForCompileUnit( return nullptr; DWARFCompileUnit *dwarf_cu = llvm::dyn_cast<DWARFCompileUnit>(&unit); - // Only compile units can be split into two parts. - if (!dwarf_cu) + // Only compile units can be split into two parts and we should only + // look for a DWO file if there is a valid DWO ID. + if (!dwarf_cu || !dwarf_cu->GetDWOId().has_value()) return nullptr; const char *dwo_name = GetDWOName(*dwarf_cu, cu_die); - if (!dwo_name) + if (!dwo_name) { + unit.SetDwoError(Status::createWithFormat( + "missing DWO name in skeleton DIE {0:x16}", cu_die.GetOffset())); return nullptr; + } if (std::shared_ptr<SymbolFileDWARFDwo> dwp_sp = GetDwpSymbolFile()) return dwp_sp; + const char *comp_dir = nullptr; FileSpec dwo_file(dwo_name); FileSystem::Instance().Resolve(dwo_file); if (dwo_file.IsRelative()) { - const char *comp_dir = - cu_die.GetAttributeValueAsString(dwarf_cu, DW_AT_comp_dir, nullptr); - if (!comp_dir) + comp_dir = cu_die.GetAttributeValueAsString(dwarf_cu, DW_AT_comp_dir, + nullptr); + if (!comp_dir) { + unit.SetDwoError(Status::createWithFormat( + "unable to locate relative .dwo debug file \"{0}\" for " + "skeleton DIE {1:x16} without valid DW_AT_comp_dir " + "attribute", + dwo_name, cu_die.GetOffset())); return nullptr; + } dwo_file.SetFile(comp_dir, FileSpec::Style::native); if (dwo_file.IsRelative()) { @@ -1746,6 +1780,11 @@ SymbolFileDWARF::GetDwoSymbolFileForCompileUnit( } if (!FileSystem::Instance().Exists(dwo_file)) { + unit.SetDwoError(Status::createWithFormat( + "unable to locate .dwo debug file \"{0}\" for skeleton DIE " + "{1:x16}", + dwo_file.GetPath().c_str(), cu_die.GetOffset())); + if (m_dwo_warning_issued.test_and_set(std::memory_order_relaxed) == false) { GetObjectFile()->GetModule()->ReportWarning( "unable to locate separate debug file (dwo, dwp). Debugging will be " @@ -1761,8 +1800,13 @@ SymbolFileDWARF::GetDwoSymbolFileForCompileUnit( GetObjectFile()->GetModule(), &dwo_file, file_offset, FileSystem::Instance().GetByteSize(dwo_file), dwo_file_data_sp, dwo_file_data_offset); - if (dwo_obj_file == nullptr) + if (dwo_obj_file == nullptr) { + unit.SetDwoError(Status::createWithFormat( + "unable to load object file for .dwo debug file \"{0}\" for " + "unit DIE {1:x16}", + dwo_name, cu_die.GetOffset())); return nullptr; + } return std::make_shared<SymbolFileDWARFDwo>(*this, dwo_obj_file, dwarf_cu->GetID()); @@ -1836,8 +1880,8 @@ void SymbolFileDWARF::UpdateExternalModuleListIfNeeded() { nullptr, nullptr, nullptr); if (!module_sp) { GetObjectFile()->GetModule()->ReportWarning( - "0x%8.8x: unable to locate module needed for external types: " - "%s\nerror: %s\nDebugging will be degraded due to missing " + "{0:x16}: unable to locate module needed for external types: " + "{1}\nerror: {2}\nDebugging will be degraded due to missing " "types. Rebuilding the project will regenerate the needed " "module files.", die.GetOffset(), dwo_module_spec.GetFileSpec().GetPath().c_str(), @@ -1847,7 +1891,7 @@ void SymbolFileDWARF::UpdateExternalModuleListIfNeeded() { // Verify the DWO hash. // FIXME: Technically "0" is a valid hash. - uint64_t dwo_id = ::GetDWOId(*dwarf_cu, *die.GetDIE()); + std::optional<uint64_t> dwo_id = ::GetDWOId(*dwarf_cu, *die.GetDIE()); if (!dwo_id) continue; @@ -1855,13 +1899,14 @@ void SymbolFileDWARF::UpdateExternalModuleListIfNeeded() { llvm::dyn_cast_or_null<SymbolFileDWARF>(module_sp->GetSymbolFile()); if (!dwo_symfile) continue; - llvm::Optional<uint64_t> dwo_dwo_id = dwo_symfile->GetDWOId(); + std::optional<uint64_t> dwo_dwo_id = dwo_symfile->GetDWOId(); if (!dwo_dwo_id) continue; if (dwo_id != dwo_dwo_id) { GetObjectFile()->GetModule()->ReportWarning( - "0x%8.8x: Module %s is out-of-date (hash mismatch). Type information " + "{0:x16}: Module {1} is out-of-date (hash mismatch). Type " + "information " "from this module may be incomplete or inconsistent with the rest of " "the program. Rebuilding the project will regenerate the needed " "module files.", @@ -2041,7 +2086,7 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(const Address &so_addr, } } else { GetObjectFile()->GetModule()->ReportWarning( - "0x%8.8x: compile unit %u failed to create a valid " + "{0:x16}: compile unit {1} failed to create a valid " "lldb_private::CompileUnit class.", cu_offset, cu_idx); } @@ -2113,7 +2158,7 @@ bool SymbolFileDWARF::DeclContextMatchesThisSymbolFile( return false; } - if (decl_ctx_type_system == &type_system_or_err.get()) + if (decl_ctx_type_system == type_system_or_err->get()) return true; // The type systems match, return true // The namespace AST was valid, and it does not match... @@ -2135,8 +2180,8 @@ void SymbolFileDWARF::FindGlobalVariables( if (log) GetObjectFile()->GetModule()->LogMessage( log, - "SymbolFileDWARF::FindGlobalVariables (name=\"%s\", " - "parent_decl_ctx=%p, max_matches=%u, variables)", + "SymbolFileDWARF::FindGlobalVariables (name=\"{0}\", " + "parent_decl_ctx={1:p}, max_matches={2}, variables)", name.GetCString(), static_cast<const void *>(&parent_decl_ctx), max_matches); @@ -2201,8 +2246,8 @@ void SymbolFileDWARF::FindGlobalVariables( if (log && num_matches > 0) { GetObjectFile()->GetModule()->LogMessage( log, - "SymbolFileDWARF::FindGlobalVariables (name=\"%s\", " - "parent_decl_ctx=%p, max_matches=%u, variables) => %u", + "SymbolFileDWARF::FindGlobalVariables (name=\"{0}\", " + "parent_decl_ctx={1:p}, max_matches={2}, variables) => {3}", name.GetCString(), static_cast<const void *>(&parent_decl_ctx), max_matches, num_matches); } @@ -2217,8 +2262,8 @@ void SymbolFileDWARF::FindGlobalVariables(const RegularExpression ®ex, if (log) { GetObjectFile()->GetModule()->LogMessage( log, - "SymbolFileDWARF::FindGlobalVariables (regex=\"%s\", " - "max_matches=%u, variables)", + "SymbolFileDWARF::FindGlobalVariables (regex=\"{0}\", " + "max_matches={1}, variables)", regex.GetText().str().c_str(), max_matches); } @@ -2311,14 +2356,13 @@ bool SymbolFileDWARF::DIEInDeclContext(const CompilerDeclContext &decl_ctx, return false; } -void SymbolFileDWARF::FindFunctions(ConstString name, +void SymbolFileDWARF::FindFunctions(const Module::LookupInfo &lookup_info, const CompilerDeclContext &parent_decl_ctx, - FunctionNameType name_type_mask, bool include_inlines, SymbolContextList &sc_list) { std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); - LLDB_SCOPED_TIMERF("SymbolFileDWARF::FindFunctions (name = '%s')", - name.AsCString()); + ConstString name = lookup_info.GetLookupName(); + FunctionNameType name_type_mask = lookup_info.GetNameTypeMask(); // eFunctionNameTypeAuto should be pre-resolved by a call to // Module::LookupInfo::LookupInfo() @@ -2329,7 +2373,7 @@ void SymbolFileDWARF::FindFunctions(ConstString name, if (log) { GetObjectFile()->GetModule()->LogMessage( log, - "SymbolFileDWARF::FindFunctions (name=\"%s\", name_type_mask=0x%x, " + "SymbolFileDWARF::FindFunctions (name=\"{0}\", name_type_mask={1:x}, " "sc_list)", name.GetCString(), name_type_mask); } @@ -2348,12 +2392,29 @@ void SymbolFileDWARF::FindFunctions(ConstString name, llvm::DenseSet<const DWARFDebugInfoEntry *> resolved_dies; - m_index->GetFunctions(name, *this, parent_decl_ctx, name_type_mask, - [&](DWARFDIE die) { - if (resolved_dies.insert(die.GetDIE()).second) - ResolveFunction(die, include_inlines, sc_list); - return true; - }); + m_index->GetFunctions(lookup_info, *this, parent_decl_ctx, [&](DWARFDIE die) { + if (resolved_dies.insert(die.GetDIE()).second) + ResolveFunction(die, include_inlines, sc_list); + return true; + }); + // With -gsimple-template-names, a templated type's DW_AT_name will not + // contain the template parameters. Try again stripping '<' and anything + // after, filtering out entries with template parameters that don't match. + { + const llvm::StringRef name_ref = name.GetStringRef(); + auto it = name_ref.find('<'); + if (it != llvm::StringRef::npos) { + const llvm::StringRef name_no_template_params = name_ref.slice(0, it); + + Module::LookupInfo no_tp_lookup_info(lookup_info); + no_tp_lookup_info.SetLookupName(ConstString(name_no_template_params)); + m_index->GetFunctions(no_tp_lookup_info, *this, parent_decl_ctx, [&](DWARFDIE die) { + if (resolved_dies.insert(die.GetDIE()).second) + ResolveFunction(die, include_inlines, sc_list); + return true; + }); + } + } // Return the number of variable that were appended to the list const uint32_t num_matches = sc_list.GetSize() - original_size; @@ -2361,8 +2422,8 @@ void SymbolFileDWARF::FindFunctions(ConstString name, if (log && num_matches > 0) { GetObjectFile()->GetModule()->LogMessage( log, - "SymbolFileDWARF::FindFunctions (name=\"%s\", " - "name_type_mask=0x%x, include_inlines=%d, sc_list) => %u", + "SymbolFileDWARF::FindFunctions (name=\"{0}\", " + "name_type_mask={1:x}, include_inlines={2:d}, sc_list) => {3}", name.GetCString(), name_type_mask, include_inlines, num_matches); } } @@ -2378,7 +2439,7 @@ void SymbolFileDWARF::FindFunctions(const RegularExpression ®ex, if (log) { GetObjectFile()->GetModule()->LogMessage( - log, "SymbolFileDWARF::FindFunctions (regex=\"%s\", sc_list)", + log, "SymbolFileDWARF::FindFunctions (regex=\"{0}\", sc_list)", regex.GetText().str().c_str()); } @@ -2428,21 +2489,26 @@ void SymbolFileDWARF::FindTypes( if (parent_decl_ctx) GetObjectFile()->GetModule()->LogMessage( log, - "SymbolFileDWARF::FindTypes (sc, name=\"%s\", parent_decl_ctx = " - "%p (\"%s\"), max_matches=%u, type_list)", + "SymbolFileDWARF::FindTypes (sc, name=\"{0}\", parent_decl_ctx = " + "{1:p} (\"{2}\"), max_matches={3}, type_list)", name.GetCString(), static_cast<const void *>(&parent_decl_ctx), parent_decl_ctx.GetName().AsCString("<NULL>"), max_matches); else GetObjectFile()->GetModule()->LogMessage( log, - "SymbolFileDWARF::FindTypes (sc, name=\"%s\", parent_decl_ctx = " - "NULL, max_matches=%u, type_list)", + "SymbolFileDWARF::FindTypes (sc, name=\"{0}\", parent_decl_ctx = " + "NULL, max_matches={1}, type_list)", name.GetCString(), max_matches); } if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx)) return; + // Unlike FindFunctions(), FindTypes() following cannot produce false + // positives. + + const llvm::StringRef name_ref = name.GetStringRef(); + auto name_bracket_index = name_ref.find('<'); m_index->GetTypes(name, [&](DWARFDIE die) { if (!DIEInDeclContext(parent_decl_ctx, die)) return true; // The containing decl contexts don't match @@ -2451,12 +2517,58 @@ void SymbolFileDWARF::FindTypes( if (!matching_type) return true; + // With -gsimple-template-names, a templated type's DW_AT_name will not + // contain the template parameters. Make sure that if the original query + // didn't contain a '<', we filter out entries with template parameters. + if (name_bracket_index == llvm::StringRef::npos && + matching_type->IsTemplateType()) + return true; + // We found a type pointer, now find the shared pointer form our type // list types.InsertUnique(matching_type->shared_from_this()); return types.GetSize() < max_matches; }); + // With -gsimple-template-names, a templated type's DW_AT_name will not + // contain the template parameters. Try again stripping '<' and anything + // after, filtering out entries with template parameters that don't match. + if (types.GetSize() < max_matches) { + if (name_bracket_index != llvm::StringRef::npos) { + const llvm::StringRef name_no_template_params = + name_ref.slice(0, name_bracket_index); + const llvm::StringRef template_params = + name_ref.slice(name_bracket_index, name_ref.size()); + m_index->GetTypes(ConstString(name_no_template_params), [&](DWARFDIE die) { + if (!DIEInDeclContext(parent_decl_ctx, die)) + return true; // The containing decl contexts don't match + + const llvm::StringRef base_name = GetTypeForDIE(die)->GetBaseName().AsCString(); + auto it = base_name.find('<'); + // If the candidate qualified name doesn't have '<', it doesn't have + // template params to compare. + if (it == llvm::StringRef::npos) + return true; + + // Filter out non-matching instantiations by comparing template params. + const llvm::StringRef base_name_template_params = + base_name.slice(it, base_name.size()); + + if (template_params != base_name_template_params) + return true; + + Type *matching_type = ResolveType(die, true, true); + if (!matching_type) + return true; + + // We found a type pointer, now find the shared pointer form our type + // list. + types.InsertUnique(matching_type->shared_from_this()); + return types.GetSize() < max_matches; + }); + } + } + // Next search through the reachable Clang modules. This only applies for // DWARF objects compiled with -gmodules that haven't been processed by // dsymutil. @@ -2474,16 +2586,16 @@ void SymbolFileDWARF::FindTypes( if (parent_decl_ctx) { GetObjectFile()->GetModule()->LogMessage( log, - "SymbolFileDWARF::FindTypes (sc, name=\"%s\", parent_decl_ctx " - "= %p (\"%s\"), max_matches=%u, type_list) => %u", + "SymbolFileDWARF::FindTypes (sc, name=\"{0}\", parent_decl_ctx " + "= {1:p} (\"{2}\"), max_matches={3}, type_list) => {4}", name.GetCString(), static_cast<const void *>(&parent_decl_ctx), parent_decl_ctx.GetName().AsCString("<NULL>"), max_matches, types.GetSize()); } else { GetObjectFile()->GetModule()->LogMessage( log, - "SymbolFileDWARF::FindTypes (sc, name=\"%s\", parent_decl_ctx " - "= NULL, max_matches=%u, type_list) => %u", + "SymbolFileDWARF::FindTypes (sc, name=\"{0}\", parent_decl_ctx " + "= NULL, max_matches={1}, type_list) => {2}", name.GetCString(), max_matches, types.GetSize()); } } @@ -2541,7 +2653,7 @@ SymbolFileDWARF::FindNamespace(ConstString name, if (log) { GetObjectFile()->GetModule()->LogMessage( - log, "SymbolFileDWARF::FindNamespace (sc, name=\"%s\")", + log, "SymbolFileDWARF::FindNamespace (sc, name=\"{0}\")", name.GetCString()); } @@ -2565,8 +2677,8 @@ SymbolFileDWARF::FindNamespace(ConstString name, if (log && namespace_decl_ctx) { GetObjectFile()->GetModule()->LogMessage( log, - "SymbolFileDWARF::FindNamespace (sc, name=\"%s\") => " - "CompilerDeclContext(%p/%p) \"%s\"", + "SymbolFileDWARF::FindNamespace (sc, name=\"{0}\") => " + "CompilerDeclContext({1:p}/{2:p}) \"{3}\"", name.GetCString(), static_cast<const void *>(namespace_decl_ctx.GetTypeSystem()), static_cast<const void *>(namespace_decl_ctx.GetOpaqueDeclContext()), @@ -2849,121 +2961,142 @@ bool SymbolFileDWARF::DIEDeclContextsMatch(const DWARFDIE &die1, return true; } -TypeSP SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext( - const DWARFDeclContext &dwarf_decl_ctx) { +TypeSP +SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext(const DWARFDIE &die) { TypeSP type_sp; - const uint32_t dwarf_decl_ctx_count = dwarf_decl_ctx.GetSize(); - if (dwarf_decl_ctx_count > 0) { - const ConstString type_name(dwarf_decl_ctx[0].name); - const dw_tag_t tag = dwarf_decl_ctx[0].tag; + if (die.GetName()) { + const dw_tag_t tag = die.Tag(); - if (type_name) { - Log *log = GetLog(DWARFLog::TypeCompletion | DWARFLog::Lookups); - if (log) { - GetObjectFile()->GetModule()->LogMessage( - log, - "SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext(tag=%" - "s, qualified-name='%s')", - DW_TAG_value_to_name(dwarf_decl_ctx[0].tag), - dwarf_decl_ctx.GetQualifiedName()); - } + Log *log = GetLog(DWARFLog::TypeCompletion | DWARFLog::Lookups); + if (log) { + GetObjectFile()->GetModule()->LogMessage( + log, + "SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext(tag=%" + "s, name='{0}')", + DW_TAG_value_to_name(tag), die.GetName()); + } - // Get the type system that we are looking to find a type for. We will - // use this to ensure any matches we find are in a language that this - // type system supports - const LanguageType language = dwarf_decl_ctx.GetLanguage(); - TypeSystem *type_system = nullptr; - if (language != eLanguageTypeUnknown) { - auto type_system_or_err = GetTypeSystemForLanguage(language); - if (auto err = type_system_or_err.takeError()) { - LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err), - "Cannot get TypeSystem for language {}", - Language::GetNameForLanguageType(language)); - } else { - type_system = &type_system_or_err.get(); - } + // Get the type system that we are looking to find a type for. We will + // use this to ensure any matches we find are in a language that this + // type system supports + const LanguageType language = GetLanguage(*die.GetCU()); + TypeSystemSP type_system = nullptr; + if (language != eLanguageTypeUnknown) { + auto type_system_or_err = GetTypeSystemForLanguage(language); + if (auto err = type_system_or_err.takeError()) { + LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err), + "Cannot get TypeSystem for language {}", + Language::GetNameForLanguageType(language)); + } else { + type_system = *type_system_or_err; } + } - m_index->GetTypes(dwarf_decl_ctx, [&](DWARFDIE type_die) { - // Make sure type_die's language matches the type system we are - // looking for. We don't want to find a "Foo" type from Java if we - // are looking for a "Foo" type for C, C++, ObjC, or ObjC++. - if (type_system && - !type_system->SupportsLanguage(GetLanguage(*type_die.GetCU()))) - return true; - bool try_resolving_type = false; - - // Don't try and resolve the DIE we are looking for with the DIE - // itself! - const dw_tag_t type_tag = type_die.Tag(); - // Make sure the tags match - if (type_tag == tag) { - // The tags match, lets try resolving this type - try_resolving_type = true; - } else { - // The tags don't match, but we need to watch our for a forward - // declaration for a struct and ("struct foo") ends up being a - // class ("class foo { ... };") or vice versa. - switch (type_tag) { - case DW_TAG_class_type: - // We had a "class foo", see if we ended up with a "struct foo - // { ... };" - try_resolving_type = (tag == DW_TAG_structure_type); - break; - case DW_TAG_structure_type: - // We had a "struct foo", see if we ended up with a "class foo - // { ... };" - try_resolving_type = (tag == DW_TAG_class_type); - break; - default: - // Tags don't match, don't event try to resolve using this type - // whose name matches.... - break; - } - } + // See comments below about -gsimple-template-names for why we attempt to + // compute missing template parameter names. + ConstString template_params; + if (type_system) { + DWARFASTParser *dwarf_ast = type_system->GetDWARFParser(); + if (dwarf_ast) + template_params = dwarf_ast->GetDIEClassTemplateParams(die); + } - if (!try_resolving_type) { - if (log) { - std::string qualified_name; - type_die.GetQualifiedName(qualified_name); - GetObjectFile()->GetModule()->LogMessage( - log, - "SymbolFileDWARF::" - "FindDefinitionTypeForDWARFDeclContext(tag=%s, " - "qualified-name='%s') ignoring die=0x%8.8x (%s)", - DW_TAG_value_to_name(dwarf_decl_ctx[0].tag), - dwarf_decl_ctx.GetQualifiedName(), type_die.GetOffset(), - qualified_name.c_str()); - } - return true; + m_index->GetTypes(GetDWARFDeclContext(die), [&](DWARFDIE type_die) { + // Make sure type_die's language matches the type system we are + // looking for. We don't want to find a "Foo" type from Java if we + // are looking for a "Foo" type for C, C++, ObjC, or ObjC++. + if (type_system && + !type_system->SupportsLanguage(GetLanguage(*type_die.GetCU()))) + return true; + bool try_resolving_type = false; + + // Don't try and resolve the DIE we are looking for with the DIE + // itself! + const dw_tag_t type_tag = type_die.Tag(); + // Make sure the tags match + if (type_tag == tag) { + // The tags match, lets try resolving this type + try_resolving_type = true; + } else { + // The tags don't match, but we need to watch our for a forward + // declaration for a struct and ("struct foo") ends up being a + // class ("class foo { ... };") or vice versa. + switch (type_tag) { + case DW_TAG_class_type: + // We had a "class foo", see if we ended up with a "struct foo + // { ... };" + try_resolving_type = (tag == DW_TAG_structure_type); + break; + case DW_TAG_structure_type: + // We had a "struct foo", see if we ended up with a "class foo + // { ... };" + try_resolving_type = (tag == DW_TAG_class_type); + break; + default: + // Tags don't match, don't event try to resolve using this type + // whose name matches.... + break; } + } - DWARFDeclContext type_dwarf_decl_ctx = GetDWARFDeclContext(type_die); - + if (!try_resolving_type) { if (log) { GetObjectFile()->GetModule()->LogMessage( log, "SymbolFileDWARF::" - "FindDefinitionTypeForDWARFDeclContext(tag=%s, " - "qualified-name='%s') trying die=0x%8.8x (%s)", - DW_TAG_value_to_name(dwarf_decl_ctx[0].tag), - dwarf_decl_ctx.GetQualifiedName(), type_die.GetOffset(), - type_dwarf_decl_ctx.GetQualifiedName()); + "FindDefinitionTypeForDWARFDeclContext(tag={0}, " + "name='{1}') ignoring die={2:x16} ({3})", + DW_TAG_value_to_name(tag), die.GetName(), type_die.GetOffset(), + type_die.GetName()); } + return true; + } - // Make sure the decl contexts match all the way up - if (dwarf_decl_ctx != type_dwarf_decl_ctx) + DWARFDeclContext type_dwarf_decl_ctx = GetDWARFDeclContext(type_die); + + if (log) { + GetObjectFile()->GetModule()->LogMessage( + log, + "SymbolFileDWARF::" + "FindDefinitionTypeForDWARFDeclContext(tag={0}, " + "name='{1}') trying die={2:x16} ({3})", + DW_TAG_value_to_name(tag), die.GetName(), type_die.GetOffset(), + type_dwarf_decl_ctx.GetQualifiedName()); + } + + // Make sure the decl contexts match all the way up + if (GetDWARFDeclContext(die) != type_dwarf_decl_ctx) + return true; + + Type *resolved_type = ResolveType(type_die, false); + if (!resolved_type || resolved_type == DIE_IS_BEING_PARSED) + return true; + + // With -gsimple-template-names, the DIE name may not contain the template + // parameters. If the declaration has template parameters but doesn't + // contain '<', check that the child template parameters match. + if (template_params) { + llvm::StringRef test_base_name = + GetTypeForDIE(type_die)->GetBaseName().GetStringRef(); + auto i = test_base_name.find('<'); + + // Full name from clang AST doesn't contain '<' so this type_die isn't + // a template parameter, but we're expecting template parameters, so + // bail. + if (i == llvm::StringRef::npos) return true; - Type *resolved_type = ResolveType(type_die, false); - if (!resolved_type || resolved_type == DIE_IS_BEING_PARSED) + llvm::StringRef test_template_params = + test_base_name.slice(i, test_base_name.size()); + // Bail if template parameters don't match. + if (test_template_params != template_params.GetStringRef()) return true; + } - type_sp = resolved_type->shared_from_this(); - return false; - }); - } + type_sp = resolved_type->shared_from_this(); + return false; + }); } return type_sp; } @@ -2979,15 +3112,16 @@ TypeSP SymbolFileDWARF::ParseType(const SymbolContext &sc, const DWARFDIE &die, "Unable to parse type"); return {}; } + auto ts = *type_system_or_err; + if (!ts) + return {}; - DWARFASTParser *dwarf_ast = type_system_or_err->GetDWARFParser(); + DWARFASTParser *dwarf_ast = ts->GetDWARFParser(); if (!dwarf_ast) return {}; TypeSP type_sp = dwarf_ast->ParseTypeFromDWARF(sc, die, type_is_new_ptr); if (type_sp) { - GetTypeList().Insert(type_sp); - if (die.Tag() == DW_TAG_subprogram) { std::string scope_qualified_name(GetDeclContextForUID(die.GetID()) .GetScopeQualifiedName() @@ -3340,7 +3474,7 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc, StreamString strm; location->DumpLocation(&strm, eDescriptionLevelFull, nullptr); GetObjectFile()->GetModule()->ReportError( - "0x%8.8x: %s has an invalid location: %s", die.GetOffset(), + "{0:x16}: {1} has an invalid location: {2}", die.GetOffset(), die.GetTagAsCString(), strm.GetData()); } if (location_DW_OP_addr != LLDB_INVALID_ADDRESS) @@ -3394,7 +3528,8 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc, if (exe_file_addr != LLDB_INVALID_ADDRESS) { DWARFExpression *location = location_list.GetMutableExpressionAtAddress(); - if (location->Update_DW_OP_addr(exe_file_addr)) { + if (location->Update_DW_OP_addr(die.GetCU(), + exe_file_addr)) { linked_oso_file_addr = true; symbol_context_scope = exe_symbol; } @@ -3414,7 +3549,7 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc, // Update the file address for this variable DWARFExpression *location = location_list.GetMutableExpressionAtAddress(); - location->Update_DW_OP_addr(exe_file_addr); + location->Update_DW_OP_addr(die.GetCU(), exe_file_addr); } else { // Variable didn't make it into the final executable return nullptr; @@ -3560,8 +3695,8 @@ void SymbolFileDWARF::ParseAndAppendGlobalVariable( variable_list_sp = sc.comp_unit->GetVariableList(false); } else { GetObjectFile()->GetModule()->ReportError( - "parent 0x%8.8" PRIx64 " %s with no valid compile unit in " - "symbol context for 0x%8.8" PRIx64 " %s.\n", + "parent {0:x8} {1} with no valid compile unit in " + "symbol context for {2:x8} {3}.\n", sc_parent_die.GetID(), sc_parent_die.GetTagAsCString(), die.GetID(), die.GetTagAsCString()); return; @@ -3570,8 +3705,8 @@ void SymbolFileDWARF::ParseAndAppendGlobalVariable( default: GetObjectFile()->GetModule()->ReportError( - "didn't find appropriate parent DIE for variable list for " - "0x%8.8" PRIx64 " %s.\n", + "didn't find appropriate parent DIE for variable list for {0:x8} " + "{1}.\n", die.GetID(), die.GetTagAsCString()); return; } @@ -3767,16 +3902,16 @@ CollectCallSiteParameters(ModuleSP module, DWARFDIE call_site_die) { child.Tag() != DW_TAG_GNU_call_site_parameter) continue; - llvm::Optional<DWARFExpressionList> LocationInCallee; - llvm::Optional<DWARFExpressionList> LocationInCaller; + std::optional<DWARFExpressionList> LocationInCallee; + std::optional<DWARFExpressionList> LocationInCaller; DWARFAttributes attributes; const size_t num_attributes = child.GetAttributes(attributes); // Parse the location at index \p attr_index within this call site parameter - // DIE, or return None on failure. + // DIE, or return std::nullopt on failure. auto parse_simple_location = - [&](int attr_index) -> llvm::Optional<DWARFExpressionList> { + [&](int attr_index) -> std::optional<DWARFExpressionList> { DWARFFormValue form_value; if (!attributes.ExtractFormValueAtIndex(attr_index, form_value)) return {}; @@ -3831,8 +3966,8 @@ SymbolFileDWARF::CollectCallEdges(ModuleSP module, DWARFDIE function_die) { if (child.Tag() != DW_TAG_call_site && child.Tag() != DW_TAG_GNU_call_site) continue; - llvm::Optional<DWARFDIE> call_origin; - llvm::Optional<DWARFExpressionList> call_target; + std::optional<DWARFDIE> call_origin; + std::optional<DWARFExpressionList> call_target; addr_t return_pc = LLDB_INVALID_ADDRESS; addr_t call_inst_pc = LLDB_INVALID_ADDRESS; addr_t low_pc = LLDB_INVALID_ADDRESS; @@ -3988,8 +4123,8 @@ void SymbolFileDWARF::DumpClangAST(Stream &s) { auto ts_or_err = GetTypeSystemForLanguage(eLanguageTypeC_plus_plus); if (!ts_or_err) return; - TypeSystemClang *clang = - llvm::dyn_cast_or_null<TypeSystemClang>(&ts_or_err.get()); + auto ts = *ts_or_err; + TypeSystemClang *clang = llvm::dyn_cast_or_null<TypeSystemClang>(ts.get()); if (!clang) return; clang->Dump(s.AsRawOstream()); @@ -4032,7 +4167,8 @@ const std::shared_ptr<SymbolFileDWARFDwo> &SymbolFileDWARF::GetDwpSymbolFile() { return m_dwp_symfile; } -llvm::Expected<TypeSystem &> SymbolFileDWARF::GetTypeSystem(DWARFUnit &unit) { +llvm::Expected<lldb::TypeSystemSP> +SymbolFileDWARF::GetTypeSystem(DWARFUnit &unit) { return unit.GetSymbolFileDWARF().GetTypeSystemForLanguage(GetLanguage(unit)); } @@ -4043,7 +4179,9 @@ DWARFASTParser *SymbolFileDWARF::GetDWARFParser(DWARFUnit &unit) { "Unable to get DWARFASTParser"); return nullptr; } - return type_system_or_err->GetDWARFParser(); + if (auto ts = *type_system_or_err) + return ts->GetDWARFParser(); + return nullptr; } CompilerDecl SymbolFileDWARF::GetDecl(const DWARFDIE &die) { @@ -4070,7 +4208,6 @@ DWARFDeclContext SymbolFileDWARF::GetDWARFDeclContext(const DWARFDIE &die) { return {}; DWARFDeclContext dwarf_decl_ctx = die.GetDIE()->GetDWARFDeclContext(die.GetCU()); - dwarf_decl_ctx.SetLanguage(GetLanguage(*die.GetCU())); return dwarf_decl_ctx; } @@ -4103,3 +4240,35 @@ StatsDuration::Duration SymbolFileDWARF::GetDebugInfoIndexTime() { return m_index->GetIndexTime(); return {}; } + +Status SymbolFileDWARF::CalculateFrameVariableError(StackFrame &frame) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); + CompileUnit *cu = frame.GetSymbolContext(eSymbolContextCompUnit).comp_unit; + if (!cu) + return Status(); + + DWARFCompileUnit *dwarf_cu = GetDWARFCompileUnit(cu); + if (!dwarf_cu) + return Status(); + + // Check if we have a skeleton compile unit that had issues trying to load + // its .dwo/.dwp file. First pares the Unit DIE to make sure we see any .dwo + // related errors. + dwarf_cu->ExtractUnitDIEIfNeeded(); + const Status &dwo_error = dwarf_cu->GetDwoError(); + if (dwo_error.Fail()) + return dwo_error; + + // Don't return an error for assembly files as they typically don't have + // varaible information. + if (dwarf_cu->GetDWARFLanguageType() == DW_LANG_Mips_Assembler) + return Status(); + + // Check if this compile unit has any variable DIEs. If it doesn't then there + // is not variable information for the entire compile unit. + if (dwarf_cu->HasAny({DW_TAG_variable, DW_TAG_formal_parameter})) + return Status(); + + return Status("no variable information is available in debug info for this " + "compile unit"); +} diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h index cfd18f02053b..f4dd9dffdb30 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -12,6 +12,7 @@ #include <list> #include <map> #include <mutex> +#include <optional> #include <unordered_map> #include <vector> @@ -138,7 +139,7 @@ public: ParseVariablesForContext(const lldb_private::SymbolContext &sc) override; lldb_private::Type *ResolveTypeUID(lldb::user_id_t type_uid) override; - llvm::Optional<ArrayInfo> GetDynamicArrayInfoForUID( + std::optional<ArrayInfo> GetDynamicArrayInfoForUID( lldb::user_id_t type_uid, const lldb_private::ExecutionContext *exe_ctx) override; @@ -163,6 +164,9 @@ public: lldb::SymbolContextItem resolve_scope, lldb_private::SymbolContext &sc) override; + lldb_private::Status + CalculateFrameVariableError(lldb_private::StackFrame &frame) override; + uint32_t ResolveSymbolContext( const lldb_private::SourceLocationSpec &src_location_spec, lldb::SymbolContextItem resolve_scope, @@ -178,9 +182,8 @@ public: uint32_t max_matches, lldb_private::VariableList &variables) override; - void FindFunctions(lldb_private::ConstString name, + void FindFunctions(const lldb_private::Module::LookupInfo &lookup_info, const lldb_private::CompilerDeclContext &parent_decl_ctx, - lldb::FunctionNameType name_type_mask, bool include_inlines, lldb_private::SymbolContextList &sc_list) override; @@ -208,7 +211,7 @@ public: lldb::TypeClass type_mask, lldb_private::TypeList &type_list) override; - llvm::Expected<lldb_private::TypeSystem &> + llvm::Expected<lldb::TypeSystemSP> GetTypeSystemForLanguage(lldb::LanguageType language) override; lldb_private::CompilerDeclContext FindNamespace( @@ -266,7 +269,7 @@ public: return GetUID(die.GetDIERef()); } - lldb::user_id_t GetUID(const llvm::Optional<DIERef> &ref) { + lldb::user_id_t GetUID(const std::optional<DIERef> &ref) { return ref ? GetUID(*ref) : LLDB_INVALID_UID; } @@ -276,10 +279,10 @@ public: GetDwoSymbolFileForCompileUnit(DWARFUnit &dwarf_cu, const DWARFDebugInfoEntry &cu_die); - virtual llvm::Optional<uint32_t> GetDwoNum() { return llvm::None; } + virtual std::optional<uint32_t> GetDwoNum() { return std::nullopt; } /// If this is a DWARF object with a single CU, return its DW_AT_dwo_id. - llvm::Optional<uint64_t> GetDWOId(); + std::optional<uint64_t> GetDWOId(); static bool DIEInDeclContext(const lldb_private::CompilerDeclContext &parent_decl_ctx, @@ -298,8 +301,7 @@ public: lldb_private::FileSpec GetFile(DWARFUnit &unit, size_t file_idx); - static llvm::Expected<lldb_private::TypeSystem &> - GetTypeSystem(DWARFUnit &unit); + static llvm::Expected<lldb::TypeSystemSP> GetTypeSystem(DWARFUnit &unit); static DWARFASTParser *GetDWARFParser(DWARFUnit &unit); @@ -329,6 +331,22 @@ public: return m_parse_time; } + virtual lldb::offset_t + GetVendorDWARFOpcodeSize(const lldb_private::DataExtractor &data, + const lldb::offset_t data_offset, + const uint8_t op) const { + return LLDB_INVALID_OFFSET; + } + + virtual bool + ParseVendorDWARFOpcode(uint8_t op, const lldb_private::DataExtractor &opcodes, + lldb::offset_t &offset, + std::vector<lldb_private::Value> &stack) const { + return false; + } + + lldb_private::ConstString ConstructFunctionDemangledName(const DWARFDIE &die); + protected: typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb_private::Type *> DIEToTypePtr; @@ -426,7 +444,7 @@ protected: lldb_private::SymbolContext &sc); virtual lldb::TypeSP - FindDefinitionTypeForDWARFDeclContext(const DWARFDeclContext &die_decl_ctx); + FindDefinitionTypeForDWARFDeclContext(const DWARFDIE &die); virtual lldb::TypeSP FindCompleteObjCDefinitionTypeForDIE(const DWARFDIE &die, @@ -501,13 +519,13 @@ protected: } void BuildCuTranslationTable(); - llvm::Optional<uint32_t> GetDWARFUnitIndex(uint32_t cu_idx); + std::optional<uint32_t> GetDWARFUnitIndex(uint32_t cu_idx); struct DecodedUID { SymbolFileDWARF &dwarf; DIERef ref; }; - llvm::Optional<DecodedUID> DecodeUID(lldb::user_id_t uid); + std::optional<DecodedUID> DecodeUID(lldb::user_id_t uid); void FindDwpSymbolFile(); diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp index 7637726892a0..aeacf55896e0 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp @@ -7,7 +7,9 @@ //===----------------------------------------------------------------------===// #include "SymbolFileDWARFDebugMap.h" +#include "DWARFCompileUnit.h" #include "DWARFDebugAranges.h" +#include "DWARFDebugInfo.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleList.h" @@ -17,6 +19,7 @@ #include "lldb/Utility/RangeMap.h" #include "lldb/Utility/RegularExpression.h" #include "lldb/Utility/Timer.h" +#include "lldb/Utility/StreamString.h" //#define DEBUG_OSO_DMAP // DO NOT CHECKIN WITH THIS NOT COMMENTED OUT #if defined(DEBUG_OSO_DMAP) @@ -31,10 +34,13 @@ #include "lldb/Symbol/VariableList.h" #include "llvm/Support/ScopedPrinter.h" +#include "lldb/Target/StackFrame.h" + #include "LogChannelDWARF.h" #include "SymbolFileDWARF.h" #include <memory> +#include <optional> using namespace lldb; using namespace lldb_private; @@ -346,7 +352,8 @@ void SymbolFileDWARFDebugMap::InitOSO() { // "i" if (sibling_idx == UINT32_MAX) { m_objfile_sp->GetModule()->ReportError( - "N_SO in symbol with UID %u has invalid sibling in debug map, " + "N_SO in symbol with UID {0} has invalid sibling in debug " + "map, " "please file a bug and attach the binary listed in this error", so_symbol->GetID()); } else { @@ -362,22 +369,25 @@ void SymbolFileDWARFDebugMap::InitOSO() { } else { if (oso_symbol == nullptr) m_objfile_sp->GetModule()->ReportError( - "N_OSO symbol[%u] can't be found, please file a bug and attach " + "N_OSO symbol[{0}] can't be found, please file a bug and " + "attach " "the binary listed in this error", oso_idx); else if (so_symbol == nullptr) m_objfile_sp->GetModule()->ReportError( - "N_SO not found for N_OSO symbol[%u], please file a bug and " + "N_SO not found for N_OSO symbol[{0}], please file a bug and " "attach the binary listed in this error", oso_idx); else if (so_symbol->GetType() != eSymbolTypeSourceFile) m_objfile_sp->GetModule()->ReportError( - "N_SO has incorrect symbol type (%u) for N_OSO symbol[%u], " + "N_SO has incorrect symbol type ({0}) for N_OSO " + "symbol[{1}], " "please file a bug and attach the binary listed in this error", so_symbol->GetType(), oso_idx); else if (oso_symbol->GetType() != eSymbolTypeSourceFile) m_objfile_sp->GetModule()->ReportError( - "N_OSO has incorrect symbol type (%u) for N_OSO symbol[%u], " + "N_OSO has incorrect symbol type ({0}) for N_OSO " + "symbol[{1}], " "please file a bug and attach the binary listed in this error", oso_symbol->GetType(), oso_idx); } @@ -418,12 +428,14 @@ Module *SymbolFileDWARFDebugMap::GetModuleByCompUnitInfo( // modification timestamp, since it will never match. if (comp_unit_info->oso_mod_time != llvm::sys::TimePoint<>() && oso_mod_time != comp_unit_info->oso_mod_time) { + comp_unit_info->oso_load_error.SetErrorStringWithFormat( + "debug map object file \"%s\" changed (actual: 0x%8.8x, debug " + "map: 0x%8.8x) since this executable was linked, debug info " + "will not be loaded", oso_file.GetPath().c_str(), + (uint32_t)llvm::sys::toTimeT(oso_mod_time), + (uint32_t)llvm::sys::toTimeT(comp_unit_info->oso_mod_time)); obj_file->GetModule()->ReportError( - "debug map object file '%s' has changed (actual time is " - "%s, debug map time is %s" - ") since this executable was linked, file will be ignored", - oso_file.GetPath().c_str(), llvm::to_string(oso_mod_time).c_str(), - llvm::to_string(comp_unit_info->oso_mod_time).c_str()); + "{0}", comp_unit_info->oso_load_error.AsCString()); return nullptr; } @@ -432,6 +444,10 @@ Module *SymbolFileDWARFDebugMap::GetModuleByCompUnitInfo( if (!ObjectFile::SplitArchivePathWithObject(oso_path, oso_file, oso_object, must_exist)) { + comp_unit_info->oso_load_error.SetErrorStringWithFormat( + "debug map object file \"%s\" containing debug info does not " + "exist, debug info will not be loaded", + comp_unit_info->oso_path.GetCString()); return nullptr; } } @@ -454,6 +470,20 @@ Module *SymbolFileDWARFDebugMap::GetModuleByCompUnitInfo( obj_file->GetModule(), GetCompUnitInfoIndex(comp_unit_info), oso_file, oso_arch, oso_object ? &oso_object : nullptr, 0, oso_object ? comp_unit_info->oso_mod_time : llvm::sys::TimePoint<>()); + + if (!comp_unit_info->oso_sp->module_sp || !comp_unit_info->oso_sp->module_sp->GetObjectFile()) { + if (oso_object && FileSystem::Instance().Exists(oso_file)) { + // If we are loading a .o file from a .a file the "oso_object" will + // have a valid value name and if the .a file exists, either the .o + // file didn't exist in the .a file or the mod time didn't match. + comp_unit_info->oso_load_error.SetErrorStringWithFormat( + "\"%s\" object from the \"%s\" archive: " + "either the .o file doesn't exist in the archive or the " + "modification time (0x%8.8x) of the .o file doesn't match", + oso_object.AsCString(), oso_file.GetPath().c_str(), + (uint32_t)llvm::sys::toTimeT(comp_unit_info->oso_mod_time)); + } + } } } if (comp_unit_info->oso_sp) @@ -564,25 +594,42 @@ CompUnitSP SymbolFileDWARFDebugMap::ParseCompileUnitAtIndex(uint32_t cu_idx) { const uint32_t cu_count = GetNumCompileUnits(); if (cu_idx < cu_count) { - Module *oso_module = GetModuleByCompUnitInfo(&m_compile_unit_infos[cu_idx]); + auto &cu_info = m_compile_unit_infos[cu_idx]; + Module *oso_module = GetModuleByCompUnitInfo(&cu_info); if (oso_module) { FileSpec so_file_spec; if (GetFileSpecForSO(cu_idx, so_file_spec)) { // User zero as the ID to match the compile unit at offset zero in each - // .o file since each .o file can only have one compile unit for now. + // .o file. lldb::user_id_t cu_id = 0; - m_compile_unit_infos[cu_idx].compile_unit_sp = + cu_info.compile_units_sps.push_back( std::make_shared<CompileUnit>( m_objfile_sp->GetModule(), nullptr, so_file_spec, cu_id, - eLanguageTypeUnknown, eLazyBoolCalculate); - - if (m_compile_unit_infos[cu_idx].compile_unit_sp) { - SetCompileUnitAtIndex(cu_idx, - m_compile_unit_infos[cu_idx].compile_unit_sp); + eLanguageTypeUnknown, eLazyBoolCalculate)); + cu_info.id_to_index_map.insert({0, 0}); + SetCompileUnitAtIndex(cu_idx, cu_info.compile_units_sps[0]); + // If there's a symbol file also register all the extra compile units. + if (SymbolFileDWARF *oso_symfile = + GetSymbolFileByCompUnitInfo(&cu_info)) { + auto num_dwarf_units = oso_symfile->DebugInfo().GetNumUnits(); + for (size_t i = 0; i < num_dwarf_units; ++i) { + auto *dwarf_unit = oso_symfile->DebugInfo().GetUnitAtIndex(i); + if (auto *dwarf_cu = llvm::dyn_cast<DWARFCompileUnit>(dwarf_unit)) { + // The "main" one was already registered. + if (dwarf_cu->GetID() == 0) + continue; + cu_info.compile_units_sps.push_back(std::make_shared<CompileUnit>( + m_objfile_sp->GetModule(), nullptr, so_file_spec, + dwarf_cu->GetID(), eLanguageTypeUnknown, eLazyBoolCalculate)); + cu_info.id_to_index_map.insert( + {dwarf_cu->GetID(), cu_info.compile_units_sps.size() - 1}); + } + } } } } - comp_unit_sp = m_compile_unit_infos[cu_idx].compile_unit_sp; + if (!cu_info.compile_units_sps.empty()) + comp_unit_sp = cu_info.compile_units_sps[0]; } return comp_unit_sp; @@ -597,7 +644,12 @@ SymbolFileDWARFDebugMap::CompileUnitInfo * SymbolFileDWARFDebugMap::GetCompUnitInfo(const CompileUnit &comp_unit) { const uint32_t cu_count = GetNumCompileUnits(); for (uint32_t i = 0; i < cu_count; ++i) { - if (&comp_unit == m_compile_unit_infos[i].compile_unit_sp.get()) + auto &id_to_index_map = m_compile_unit_infos[i].id_to_index_map; + + auto it = id_to_index_map.find(comp_unit.GetID()); + if (it != id_to_index_map.end() && + &comp_unit == + m_compile_unit_infos[i].compile_units_sps[it->getSecond()].get()) return &m_compile_unit_infos[i]; } return nullptr; @@ -730,14 +782,14 @@ Type *SymbolFileDWARFDebugMap::ResolveTypeUID(lldb::user_id_t type_uid) { return nullptr; } -llvm::Optional<SymbolFile::ArrayInfo> +std::optional<SymbolFile::ArrayInfo> SymbolFileDWARFDebugMap::GetDynamicArrayInfoForUID( lldb::user_id_t type_uid, const lldb_private::ExecutionContext *exe_ctx) { const uint64_t oso_idx = GetOSOIndexFromUserID(type_uid); SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(oso_idx); if (oso_dwarf) return oso_dwarf->GetDynamicArrayInfoForUID(type_uid, exe_ctx); - return llvm::None; + return std::nullopt; } bool SymbolFileDWARFDebugMap::CompleteType(CompilerType &compiler_type) { @@ -1004,17 +1056,17 @@ static void RemoveFunctionsWithModuleNotEqualTo(const ModuleSP &module_sp, } void SymbolFileDWARFDebugMap::FindFunctions( - ConstString name, const CompilerDeclContext &parent_decl_ctx, - FunctionNameType name_type_mask, bool include_inlines, + const Module::LookupInfo &lookup_info, + const CompilerDeclContext &parent_decl_ctx, bool include_inlines, SymbolContextList &sc_list) { std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); LLDB_SCOPED_TIMERF("SymbolFileDWARFDebugMap::FindFunctions (name = %s)", - name.GetCString()); + lookup_info.GetLookupName().GetCString()); ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool { uint32_t sc_idx = sc_list.GetSize(); - oso_dwarf->FindFunctions(name, parent_decl_ctx, name_type_mask, - include_inlines, sc_list); + oso_dwarf->FindFunctions(lookup_info, parent_decl_ctx, include_inlines, + sc_list); if (!sc_list.IsEmpty()) { RemoveFunctionsWithModuleNotEqualTo(m_objfile_sp->GetModule(), sc_list, sc_idx); @@ -1078,10 +1130,10 @@ SymbolFileDWARFDebugMap::ParseCallEdgesInFunction(UserID func_id) { } TypeSP SymbolFileDWARFDebugMap::FindDefinitionTypeForDWARFDeclContext( - const DWARFDeclContext &die_decl_ctx) { + const DWARFDIE &die) { TypeSP type_sp; ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool { - type_sp = oso_dwarf->FindDefinitionTypeForDWARFDeclContext(die_decl_ctx); + type_sp = oso_dwarf->FindDefinitionTypeForDWARFDeclContext(die); return ((bool)type_sp); }); return type_sp; @@ -1217,18 +1269,21 @@ void SymbolFileDWARFDebugMap::DumpClangAST(Stream &s) { } lldb::CompUnitSP -SymbolFileDWARFDebugMap::GetCompileUnit(SymbolFileDWARF *oso_dwarf) { +SymbolFileDWARFDebugMap::GetCompileUnit(SymbolFileDWARF *oso_dwarf, DWARFCompileUnit &dwarf_cu) { if (oso_dwarf) { const uint32_t cu_count = GetNumCompileUnits(); for (uint32_t cu_idx = 0; cu_idx < cu_count; ++cu_idx) { SymbolFileDWARF *oso_symfile = GetSymbolFileByCompUnitInfo(&m_compile_unit_infos[cu_idx]); if (oso_symfile == oso_dwarf) { - if (!m_compile_unit_infos[cu_idx].compile_unit_sp) - m_compile_unit_infos[cu_idx].compile_unit_sp = - ParseCompileUnitAtIndex(cu_idx); - - return m_compile_unit_infos[cu_idx].compile_unit_sp; + if (m_compile_unit_infos[cu_idx].compile_units_sps.empty()) + ParseCompileUnitAtIndex(cu_idx); + + auto &id_to_index_map = m_compile_unit_infos[cu_idx].id_to_index_map; + auto it = id_to_index_map.find(dwarf_cu.GetID()); + if (it != id_to_index_map.end()) + return m_compile_unit_infos[cu_idx] + .compile_units_sps[it->getSecond()]; } } } @@ -1258,11 +1313,17 @@ void SymbolFileDWARFDebugMap::SetCompileUnit(SymbolFileDWARF *oso_dwarf, SymbolFileDWARF *oso_symfile = GetSymbolFileByCompUnitInfo(&m_compile_unit_infos[cu_idx]); if (oso_symfile == oso_dwarf) { - if (m_compile_unit_infos[cu_idx].compile_unit_sp) { - assert(m_compile_unit_infos[cu_idx].compile_unit_sp.get() == + if (!m_compile_unit_infos[cu_idx].compile_units_sps.empty()) { + assert(m_compile_unit_infos[cu_idx].compile_units_sps[0].get() == cu_sp.get()); } else { - m_compile_unit_infos[cu_idx].compile_unit_sp = cu_sp; + assert(cu_sp->GetID() == 0 && + "Setting first compile unit but with id different than 0!"); + auto &compile_units_sps = m_compile_unit_infos[cu_idx].compile_units_sps; + compile_units_sps.push_back(cu_sp); + m_compile_unit_infos[cu_idx].id_to_index_map.insert( + {cu_sp->GetID(), compile_units_sps.size() - 1}); + SetCompileUnitAtIndex(cu_idx, cu_sp); } } @@ -1430,3 +1491,48 @@ ModuleList SymbolFileDWARFDebugMap::GetDebugInfoModules() { }); return oso_modules; } + +Status SymbolFileDWARFDebugMap::CalculateFrameVariableError(StackFrame &frame) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); + + // We need to make sure that our PC value from the frame matches the module + // for this object file since we will lookup the PC file address in the debug + // map below. + Address pc_addr = frame.GetFrameCodeAddress(); + if (pc_addr.GetModule() == m_objfile_sp->GetModule()) { + Symtab *symtab = m_objfile_sp->GetSymtab(); + if (symtab) { + const DebugMap::Entry *debug_map_entry = + m_debug_map.FindEntryThatContains(pc_addr.GetFileAddress()); + if (debug_map_entry) { + Symbol *symbol = + symtab->SymbolAtIndex(debug_map_entry->data.GetExeSymbolIndex()); + if (symbol) { + uint32_t oso_idx = 0; + CompileUnitInfo *comp_unit_info = + GetCompileUnitInfoForSymbolWithID(symbol->GetID(), &oso_idx); + if (comp_unit_info) { + Module *oso_module = GetModuleByCompUnitInfo(comp_unit_info); + if (oso_module) { + // Check the .o file's DWARF in case it has an error to display. + SymbolFile *oso_sym_file = oso_module->GetSymbolFile(); + if (oso_sym_file) + return oso_sym_file->GetFrameVariableError(frame); + } + // If we don't have a valid OSO module here, then something went + // wrong as we have a symbol for the address in the debug map, but + // we weren't able to open the .o file. Display an appropriate + // error + if (comp_unit_info->oso_load_error.Fail()) + return comp_unit_info->oso_load_error; + else + return Status("unable to load debug map object file \"%s\" " + "exist, debug info will not be loaded", + comp_unit_info->oso_path.GetCString()); + } + } + } + } + } + return Status(); +} diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h index 52c4d77a10b6..5b364e423a6a 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h @@ -14,11 +14,13 @@ #include "llvm/Support/Chrono.h" #include <bitset> #include <map> +#include <optional> #include <vector> #include "UniqueDWARFASTType.h" class SymbolFileDWARF; +class DWARFCompileUnit; class DWARFDebugAranges; class DWARFDeclContext; @@ -82,7 +84,7 @@ public: ParseVariablesForContext(const lldb_private::SymbolContext &sc) override; lldb_private::Type *ResolveTypeUID(lldb::user_id_t type_uid) override; - llvm::Optional<ArrayInfo> GetDynamicArrayInfoForUID( + std::optional<ArrayInfo> GetDynamicArrayInfoForUID( lldb::user_id_t type_uid, const lldb_private::ExecutionContext *exe_ctx) override; @@ -101,6 +103,10 @@ public: const lldb_private::SourceLocationSpec &src_location_spec, lldb::SymbolContextItem resolve_scope, lldb_private::SymbolContextList &sc_list) override; + + lldb_private::Status + CalculateFrameVariableError(lldb_private::StackFrame &frame) override; + void FindGlobalVariables(lldb_private::ConstString name, const lldb_private::CompilerDeclContext &parent_decl_ctx, @@ -109,9 +115,8 @@ public: void FindGlobalVariables(const lldb_private::RegularExpression ®ex, uint32_t max_matches, lldb_private::VariableList &variables) override; - void FindFunctions(lldb_private::ConstString name, + void FindFunctions(const lldb_private::Module::LookupInfo &lookup_info, const lldb_private::CompilerDeclContext &parent_decl_ctx, - lldb::FunctionNameType name_type_mask, bool include_inlines, lldb_private::SymbolContextList &sc_list) override; void FindFunctions(const lldb_private::RegularExpression ®ex, @@ -169,8 +174,12 @@ protected: lldb_private::FileSpec so_file; lldb_private::ConstString oso_path; llvm::sys::TimePoint<> oso_mod_time; + lldb_private::Status oso_load_error; OSOInfoSP oso_sp; - lldb::CompUnitSP compile_unit_sp; + /// The compile units that an object file contains. + llvm::SmallVector<lldb::CompUnitSP, 2> compile_units_sps; + /// A map from the compile unit ID to its index in the vector. + llvm::SmallDenseMap<uint64_t, uint64_t, 2> id_to_index_map; uint32_t first_symbol_index = UINT32_MAX; uint32_t last_symbol_index = UINT32_MAX; uint32_t first_symbol_id = UINT32_MAX; @@ -178,10 +187,7 @@ protected: FileRangeMap file_range_map; bool file_range_map_valid = false; - CompileUnitInfo() - : so_file(), oso_path(), oso_mod_time(), oso_sp(), compile_unit_sp(), - - file_range_map() {} + CompileUnitInfo() = default; const FileRangeMap &GetFileRangeMap(SymbolFileDWARFDebugMap *exe_symfile); }; @@ -189,7 +195,17 @@ protected: // Protected Member Functions void InitOSO(); + /// This function actually returns the number of object files, which may be + /// less than the actual number of compile units, since an object file may + /// contain more than one compile unit. SymbolFileDWARFDebugMap looks up the + /// number of compile units by reading the nlist symbol table, which + /// currently, on macOS, only reports one compile unit per object file, and + /// there's no efficient way to calculate the actual number of compile units + /// upfront. uint32_t CalculateNumCompileUnits() override; + + /// This function actually returns the first compile unit the object file at + /// the given index contains. lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index) override; static uint32_t GetOSOIndexFromUserID(lldb::user_id_t uid) { @@ -259,12 +275,15 @@ protected: void SetCompileUnit(SymbolFileDWARF *oso_dwarf, const lldb::CompUnitSP &cu_sp); - lldb::CompUnitSP GetCompileUnit(SymbolFileDWARF *oso_dwarf); + /// Returns the compile unit associated with the dwarf compile unit. This may + /// be one of the extra compile units an object file contains which isn't + /// reachable by ParseCompileUnitAtIndex(uint32_t). + lldb::CompUnitSP GetCompileUnit(SymbolFileDWARF *oso_dwarf, + DWARFCompileUnit &dwarf_cu); CompileUnitInfo *GetCompileUnitInfo(SymbolFileDWARF *oso_dwarf); - lldb::TypeSP - FindDefinitionTypeForDWARFDeclContext(const DWARFDeclContext &die_decl_ctx); + lldb::TypeSP FindDefinitionTypeForDWARFDeclContext(const DWARFDIE &die); bool Supports_DW_AT_APPLE_objc_complete_type(SymbolFileDWARF *skip_dwarf_oso); diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp index fcb51dfa0e7a..a1223a519fef 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp @@ -17,6 +17,7 @@ #include "DWARFCompileUnit.h" #include "DWARFDebugInfo.h" #include "DWARFUnit.h" +#include <optional> using namespace lldb; using namespace lldb_private; @@ -41,7 +42,7 @@ DWARFCompileUnit *SymbolFileDWARFDwo::GetDWOCompileUnitForHash(uint64_t hash) { if (auto *unit_contrib = entry->getContribution()) return llvm::dyn_cast_or_null<DWARFCompileUnit>( DebugInfo().GetUnitAtOffset(DIERef::Section::DebugInfo, - unit_contrib->Offset)); + unit_contrib->getOffset32())); } return nullptr; } @@ -49,7 +50,8 @@ DWARFCompileUnit *SymbolFileDWARFDwo::GetDWOCompileUnitForHash(uint64_t hash) { DWARFCompileUnit *cu = FindSingleCompileUnit(); if (!cu) return nullptr; - if (hash != cu->GetDWOId()) + std::optional<uint64_t> dwo_id = cu->GetDWOId(); + if (!dwo_id || hash != *dwo_id) return nullptr; return cu; } @@ -76,6 +78,18 @@ DWARFCompileUnit *SymbolFileDWARFDwo::FindSingleCompileUnit() { return cu; } +lldb::offset_t SymbolFileDWARFDwo::GetVendorDWARFOpcodeSize( + const lldb_private::DataExtractor &data, const lldb::offset_t data_offset, + const uint8_t op) const { + return GetBaseSymbolFile().GetVendorDWARFOpcodeSize(data, data_offset, op); +} + +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); +} + SymbolFileDWARF::DIEToTypePtr &SymbolFileDWARFDwo::GetDIEToType() { return GetBaseSymbolFile().GetDIEToType(); } @@ -104,10 +118,9 @@ UniqueDWARFASTTypeMap &SymbolFileDWARFDwo::GetUniqueDWARFASTTypeMap() { return GetBaseSymbolFile().GetUniqueDWARFASTTypeMap(); } -lldb::TypeSP SymbolFileDWARFDwo::FindDefinitionTypeForDWARFDeclContext( - const DWARFDeclContext &die_decl_ctx) { - return GetBaseSymbolFile().FindDefinitionTypeForDWARFDeclContext( - die_decl_ctx); +lldb::TypeSP +SymbolFileDWARFDwo::FindDefinitionTypeForDWARFDeclContext(const DWARFDIE &die) { + return GetBaseSymbolFile().FindDefinitionTypeForDWARFDeclContext(die); } lldb::TypeSP SymbolFileDWARFDwo::FindCompleteObjCDefinitionTypeForDIE( @@ -117,7 +130,7 @@ lldb::TypeSP SymbolFileDWARFDwo::FindCompleteObjCDefinitionTypeForDIE( die, type_name, must_be_implementation); } -llvm::Expected<TypeSystem &> +llvm::Expected<lldb::TypeSystemSP> SymbolFileDWARFDwo::GetTypeSystemForLanguage(LanguageType language) { return GetBaseSymbolFile().GetTypeSystemForLanguage(language); } diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h index 93538aac3c54..3edf004d683e 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h @@ -10,6 +10,7 @@ #define LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_SYMBOLFILEDWARFDWO_H #include "SymbolFileDWARF.h" +#include <optional> class SymbolFileDWARFDwo : public SymbolFileDWARF { /// LLVM RTTI support. @@ -34,13 +35,23 @@ public: void GetObjCMethods(lldb_private::ConstString class_name, llvm::function_ref<bool(DWARFDIE die)> callback) override; - llvm::Expected<lldb_private::TypeSystem &> + llvm::Expected<lldb::TypeSystemSP> GetTypeSystemForLanguage(lldb::LanguageType language) override; DWARFDIE GetDIE(const DIERef &die_ref) override; - llvm::Optional<uint32_t> GetDwoNum() override { return GetID() >> 32; } + std::optional<uint32_t> GetDwoNum() override { return GetID() >> 32; } + + lldb::offset_t + GetVendorDWARFOpcodeSize(const lldb_private::DataExtractor &data, + const lldb::offset_t data_offset, + const uint8_t op) const override; + + bool ParseVendorDWARFOpcode( + uint8_t op, const lldb_private::DataExtractor &opcodes, + lldb::offset_t &offset, + std::vector<lldb_private::Value> &stack) const override; protected: DIEToTypePtr &GetDIEToType() override; @@ -53,14 +64,14 @@ protected: UniqueDWARFASTTypeMap &GetUniqueDWARFASTTypeMap() override; - lldb::TypeSP FindDefinitionTypeForDWARFDeclContext( - const DWARFDeclContext &die_decl_ctx) override; + lldb::TypeSP + FindDefinitionTypeForDWARFDeclContext(const DWARFDIE &die) override; lldb::TypeSP FindCompleteObjCDefinitionTypeForDIE( const DWARFDIE &die, lldb_private::ConstString type_name, bool must_be_implementation) override; - SymbolFileDWARF &GetBaseSymbolFile() { return m_base_symbol_file; } + SymbolFileDWARF &GetBaseSymbolFile() const { return m_base_symbol_file; } /// If this file contains exactly one compile unit, this function will return /// it. Otherwise it returns nullptr. diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/CodeViewRegisterMapping.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/CodeViewRegisterMapping.cpp index 3d8030916c84..3c10d4aa314b 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/CodeViewRegisterMapping.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/CodeViewRegisterMapping.cpp @@ -649,3 +649,100 @@ uint32_t lldb_private::npdb::GetLLDBRegisterNumber( return LLDB_INVALID_REGNUM; } } + +uint32_t +lldb_private::npdb::GetRegisterSize(llvm::codeview::RegisterId register_id) { + switch(register_id) { + case llvm::codeview::RegisterId::AL: + case llvm::codeview::RegisterId::BL: + case llvm::codeview::RegisterId::CL: + case llvm::codeview::RegisterId::DL: + case llvm::codeview::RegisterId::AH: + case llvm::codeview::RegisterId::BH: + case llvm::codeview::RegisterId::CH: + case llvm::codeview::RegisterId::DH: + case llvm::codeview::RegisterId::SIL: + case llvm::codeview::RegisterId::DIL: + case llvm::codeview::RegisterId::BPL: + case llvm::codeview::RegisterId::SPL: + case llvm::codeview::RegisterId::R8B: + case llvm::codeview::RegisterId::R9B: + case llvm::codeview::RegisterId::R10B: + case llvm::codeview::RegisterId::R11B: + case llvm::codeview::RegisterId::R12B: + case llvm::codeview::RegisterId::R13B: + case llvm::codeview::RegisterId::R14B: + case llvm::codeview::RegisterId::R15B: + return 1; + case llvm::codeview::RegisterId::AX: + case llvm::codeview::RegisterId::BX: + case llvm::codeview::RegisterId::CX: + case llvm::codeview::RegisterId::DX: + case llvm::codeview::RegisterId::SP: + case llvm::codeview::RegisterId::BP: + case llvm::codeview::RegisterId::SI: + case llvm::codeview::RegisterId::DI: + case llvm::codeview::RegisterId::R8W: + case llvm::codeview::RegisterId::R9W: + case llvm::codeview::RegisterId::R10W: + case llvm::codeview::RegisterId::R11W: + case llvm::codeview::RegisterId::R12W: + case llvm::codeview::RegisterId::R13W: + case llvm::codeview::RegisterId::R14W: + case llvm::codeview::RegisterId::R15W: + return 2; + case llvm::codeview::RegisterId::EAX: + case llvm::codeview::RegisterId::EBX: + case llvm::codeview::RegisterId::ECX: + case llvm::codeview::RegisterId::EDX: + case llvm::codeview::RegisterId::ESP: + case llvm::codeview::RegisterId::EBP: + case llvm::codeview::RegisterId::ESI: + case llvm::codeview::RegisterId::EDI: + case llvm::codeview::RegisterId::R8D: + case llvm::codeview::RegisterId::R9D: + case llvm::codeview::RegisterId::R10D: + case llvm::codeview::RegisterId::R11D: + case llvm::codeview::RegisterId::R12D: + case llvm::codeview::RegisterId::R13D: + case llvm::codeview::RegisterId::R14D: + case llvm::codeview::RegisterId::R15D: + return 4; + case llvm::codeview::RegisterId::RAX: + case llvm::codeview::RegisterId::RBX: + case llvm::codeview::RegisterId::RCX: + case llvm::codeview::RegisterId::RDX: + case llvm::codeview::RegisterId::RSI: + case llvm::codeview::RegisterId::RDI: + case llvm::codeview::RegisterId::RBP: + case llvm::codeview::RegisterId::RSP: + case llvm::codeview::RegisterId::R8: + case llvm::codeview::RegisterId::R9: + case llvm::codeview::RegisterId::R10: + case llvm::codeview::RegisterId::R11: + case llvm::codeview::RegisterId::R12: + case llvm::codeview::RegisterId::R13: + case llvm::codeview::RegisterId::R14: + case llvm::codeview::RegisterId::R15: + return 8; + case llvm::codeview::RegisterId::XMM0: + case llvm::codeview::RegisterId::XMM1: + case llvm::codeview::RegisterId::XMM2: + case llvm::codeview::RegisterId::XMM3: + case llvm::codeview::RegisterId::XMM4: + case llvm::codeview::RegisterId::XMM5: + case llvm::codeview::RegisterId::XMM6: + case llvm::codeview::RegisterId::XMM7: + case llvm::codeview::RegisterId::XMM8: + case llvm::codeview::RegisterId::XMM9: + case llvm::codeview::RegisterId::XMM10: + case llvm::codeview::RegisterId::XMM11: + case llvm::codeview::RegisterId::XMM12: + case llvm::codeview::RegisterId::XMM13: + case llvm::codeview::RegisterId::XMM14: + case llvm::codeview::RegisterId::XMM15: + return 16; + default: + return 0; + } +} diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/CodeViewRegisterMapping.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/CodeViewRegisterMapping.h index 02c7495565b8..1ed4fde9df32 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/CodeViewRegisterMapping.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/CodeViewRegisterMapping.h @@ -17,6 +17,7 @@ namespace npdb { uint32_t GetLLDBRegisterNumber(llvm::Triple::ArchType arch_type, llvm::codeview::RegisterId register_id); +uint32_t GetRegisterSize(llvm::codeview::RegisterId register_id); } // namespace npdb } // namespace lldb_private diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/CompileUnitIndex.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/CompileUnitIndex.cpp index d15c0ee99f96..e2e06491e8c1 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/CompileUnitIndex.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/CompileUnitIndex.cpp @@ -66,7 +66,7 @@ static void ParseBuildInfo(PdbIndex &index, const CVSymbol &sym, // S_BUILDINFO just points to an LF_BUILDINFO in the IPI stream. Let's do // a little extra work to pull out the LF_BUILDINFO. LazyRandomTypeCollection &types = index.ipi().typeCollection(); - llvm::Optional<CVType> cvt = types.tryGetType(bis.BuildId); + std::optional<CVType> cvt = types.tryGetType(bis.BuildId); if (!cvt || cvt->kind() != LF_BUILDINFO) return; diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/CompileUnitIndex.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/CompileUnitIndex.h index 4ad27de98695..c6e382d3825c 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/CompileUnitIndex.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/CompileUnitIndex.h @@ -13,7 +13,6 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/IntervalMap.h" -#include "llvm/ADT/Optional.h" #include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h" #include "llvm/DebugInfo/CodeView/StringsAndChecksums.h" #include "llvm/DebugInfo/CodeView/SymbolRecord.h" @@ -26,6 +25,7 @@ #include <map> #include <memory> +#include <optional> namespace lldb_private { @@ -62,10 +62,10 @@ struct CompilandIndexItem { std::map<lldb::addr_t, PdbSymUid> m_symbols_by_va; // S_COMPILE3 sym describing compilation settings for the module. - llvm::Optional<llvm::codeview::Compile3Sym> m_compile_opts; + std::optional<llvm::codeview::Compile3Sym> m_compile_opts; // S_OBJNAME sym describing object name. - llvm::Optional<llvm::codeview::ObjNameSym> m_obj_name; + std::optional<llvm::codeview::ObjNameSym> m_obj_name; // LF_BUILDINFO sym describing source file name, working directory, // command line, etc. This usually contains exactly 5 items which diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp index 3166c8ae65c6..9623daa416bb 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp @@ -24,6 +24,7 @@ #include "PdbUtil.h" #include "CodeViewRegisterMapping.h" #include "PdbFPOProgramToDWARFExpression.h" +#include <optional> using namespace lldb; using namespace lldb_private; @@ -128,39 +129,44 @@ static DWARFExpression MakeLocationExpressionInternal(lldb::ModuleSP module, return result; } +static bool MakeRegisterBasedLocationExpressionInternal( + Stream &stream, llvm::codeview::RegisterId reg, RegisterKind ®ister_kind, + std::optional<int32_t> relative_offset, lldb::ModuleSP module) { + uint32_t reg_num = GetRegisterNumber(module->GetArchitecture().GetMachine(), + reg, register_kind); + if (reg_num == LLDB_INVALID_REGNUM) + return false; + + if (reg_num > 31) { + llvm::dwarf::LocationAtom base = + relative_offset ? llvm::dwarf::DW_OP_bregx : llvm::dwarf::DW_OP_regx; + stream.PutHex8(base); + stream.PutULEB128(reg_num); + } else { + llvm::dwarf::LocationAtom base = + relative_offset ? llvm::dwarf::DW_OP_breg0 : llvm::dwarf::DW_OP_reg0; + stream.PutHex8(base + reg_num); + } + + if (relative_offset) + stream.PutSLEB128(*relative_offset); + + return true; +} + static DWARFExpression MakeRegisterBasedLocationExpressionInternal( - llvm::codeview::RegisterId reg, llvm::Optional<int32_t> relative_offset, + llvm::codeview::RegisterId reg, std::optional<int32_t> relative_offset, lldb::ModuleSP module) { return MakeLocationExpressionInternal( module, [&](Stream &stream, RegisterKind ®ister_kind) -> bool { - uint32_t reg_num = GetRegisterNumber( - module->GetArchitecture().GetMachine(), reg, register_kind); - if (reg_num == LLDB_INVALID_REGNUM) - return false; - - if (reg_num > 31) { - llvm::dwarf::LocationAtom base = relative_offset - ? llvm::dwarf::DW_OP_bregx - : llvm::dwarf::DW_OP_regx; - stream.PutHex8(base); - stream.PutULEB128(reg_num); - } else { - llvm::dwarf::LocationAtom base = relative_offset - ? llvm::dwarf::DW_OP_breg0 - : llvm::dwarf::DW_OP_reg0; - stream.PutHex8(base + reg_num); - } - - if (relative_offset) - stream.PutSLEB128(*relative_offset); - - return true; + return MakeRegisterBasedLocationExpressionInternal( + stream, reg, register_kind, relative_offset, module); }); } DWARFExpression lldb_private::npdb::MakeEnregisteredLocationExpression( llvm::codeview::RegisterId reg, lldb::ModuleSP module) { - return MakeRegisterBasedLocationExpressionInternal(reg, llvm::None, module); + return MakeRegisterBasedLocationExpressionInternal(reg, std::nullopt, module); } DWARFExpression lldb_private::npdb::MakeRegRelLocationExpression( @@ -243,7 +249,7 @@ DWARFExpression lldb_private::npdb::MakeConstantLocationExpression( Value.U = constant.getZExtValue(); } - bytes = llvm::makeArrayRef(reinterpret_cast<const uint8_t *>(&Value), 8) + bytes = llvm::ArrayRef(reinterpret_cast<const uint8_t *>(&Value), 8) .take_front(size); buffer->CopyData(bytes.data(), size); DataExtractor extractor(buffer, lldb::eByteOrderLittle, address_size); @@ -251,28 +257,43 @@ DWARFExpression lldb_private::npdb::MakeConstantLocationExpression( return result; } -DWARFExpression lldb_private::npdb::MakeEnregisteredLocationExpressionForClass( - std::map<uint64_t, std::pair<RegisterId, uint32_t>> &members_info, +DWARFExpression +lldb_private::npdb::MakeEnregisteredLocationExpressionForComposite( + const std::map<uint64_t, MemberValLocation> &offset_to_location, + std::map<uint64_t, size_t> &offset_to_size, size_t total_size, lldb::ModuleSP module) { return MakeLocationExpressionInternal( module, [&](Stream &stream, RegisterKind ®ister_kind) -> bool { - for (auto pair : members_info) { - std::pair<RegisterId, uint32_t> member_info = pair.second; - if (member_info.first != llvm::codeview::RegisterId::NONE) { - uint32_t reg_num = - GetRegisterNumber(module->GetArchitecture().GetMachine(), - member_info.first, register_kind); - if (reg_num == LLDB_INVALID_REGNUM) - return false; - if (reg_num > 31) { - stream.PutHex8(llvm::dwarf::DW_OP_regx); - stream.PutULEB128(reg_num); - } else { - stream.PutHex8(llvm::dwarf::DW_OP_reg0 + reg_num); - } + size_t cur_offset = 0; + bool is_simple_type = offset_to_size.empty(); + // Iterate through offset_to_location because offset_to_size might be + // empty if the variable is a simple type. + for (const auto &offset_loc : offset_to_location) { + if (cur_offset < offset_loc.first) { + stream.PutHex8(llvm::dwarf::DW_OP_piece); + stream.PutULEB128(offset_loc.first - cur_offset); + cur_offset = offset_loc.first; } + MemberValLocation loc = offset_loc.second; + std::optional<int32_t> offset = + loc.is_at_reg ? std::nullopt + : std::optional<int32_t>(loc.reg_offset); + if (!MakeRegisterBasedLocationExpressionInternal( + stream, (RegisterId)loc.reg_id, register_kind, offset, + module)) + return false; + if (!is_simple_type) { + stream.PutHex8(llvm::dwarf::DW_OP_piece); + stream.PutULEB128(offset_to_size[offset_loc.first]); + cur_offset = offset_loc.first + offset_to_size[offset_loc.first]; + } + } + // For simple type, it specifies the byte size of the value described by + // the previous dwarf expr. For udt, it's the remaining byte size at end + // of a struct. + if (total_size > cur_offset) { stream.PutHex8(llvm::dwarf::DW_OP_piece); - stream.PutULEB128(member_info.second); + stream.PutULEB128(total_size - cur_offset); } return true; }); diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.h index 1ed6c55fea74..2f12d8bf0dd7 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.h @@ -26,6 +26,12 @@ class TpiStream; } // namespace llvm namespace lldb_private { namespace npdb { +struct MemberValLocation { + uint16_t reg_id; + uint16_t reg_offset; + bool is_at_reg = true; +}; + DWARFExpression MakeEnregisteredLocationExpression(llvm::codeview::RegisterId reg, lldb::ModuleSP module); @@ -41,9 +47,9 @@ DWARFExpression MakeGlobalLocationExpression(uint16_t section, uint32_t offset, DWARFExpression MakeConstantLocationExpression( llvm::codeview::TypeIndex underlying_ti, llvm::pdb::TpiStream &tpi, const llvm::APSInt &constant, lldb::ModuleSP module); -DWARFExpression MakeEnregisteredLocationExpressionForClass( - std::map<uint64_t, std::pair<llvm::codeview::RegisterId, uint32_t>> - &members_info, +DWARFExpression MakeEnregisteredLocationExpressionForComposite( + const std::map<uint64_t, MemberValLocation> &offset_to_location, + std::map<uint64_t, size_t> &offset_to_size, size_t total_size, lldb::ModuleSP module); } // namespace npdb } // namespace lldb_private diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp index 25425f914088..1e9e1be62e3b 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp @@ -21,9 +21,10 @@ #include "lldb/Core/Module.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Utility/LLDBAssert.h" - #include "PdbUtil.h" #include "UdtRecordCompleter.h" +#include "SymbolFileNativePDB.h" +#include <optional> using namespace lldb_private; using namespace lldb_private::npdb; @@ -94,59 +95,6 @@ struct CreateMethodDecl : public TypeVisitorCallbacks { }; } // namespace -static llvm::Optional<PdbCompilandSymId> FindSymbolScope(PdbIndex &index, - PdbCompilandSymId id) { - CVSymbol sym = index.ReadSymbolRecord(id); - if (symbolOpensScope(sym.kind())) { - // If this exact symbol opens a scope, we can just directly access its - // parent. - id.offset = getScopeParentOffset(sym); - // Global symbols have parent offset of 0. Return llvm::None to indicate - // this. - if (id.offset == 0) - return llvm::None; - return id; - } - - // Otherwise we need to start at the beginning and iterate forward until we - // reach (or pass) this particular symbol - CompilandIndexItem &cii = index.compilands().GetOrCreateCompiland(id.modi); - const CVSymbolArray &syms = cii.m_debug_stream.getSymbolArray(); - - auto begin = syms.begin(); - auto end = syms.at(id.offset); - std::vector<PdbCompilandSymId> scope_stack; - - while (begin != end) { - if (begin.offset() > id.offset) { - // We passed it. We couldn't even find this symbol record. - lldbassert(false && "Invalid compiland symbol id!"); - return llvm::None; - } - - // We haven't found the symbol yet. Check if we need to open or close the - // scope stack. - if (symbolOpensScope(begin->kind())) { - // We can use the end offset of the scope to determine whether or not - // we can just outright skip this entire scope. - uint32_t scope_end = getScopeEndOffset(*begin); - if (scope_end < id.offset) { - begin = syms.at(scope_end); - } else { - // The symbol we're looking for is somewhere in this scope. - scope_stack.emplace_back(id.modi, begin.offset()); - } - } else if (symbolEndsScope(begin->kind())) { - scope_stack.pop_back(); - } - ++begin; - } - if (scope_stack.empty()) - return llvm::None; - // We have a match! Return the top of the stack - return scope_stack.back(); -} - static clang::TagTypeKind TranslateUdtKind(const TagRecord &cr) { switch (cr.Kind) { case TypeRecordKind::Class: @@ -181,7 +129,7 @@ AnyScopesHaveTemplateParams(llvm::ArrayRef<llvm::ms_demangle::Node *> scopes) { return false; } -static llvm::Optional<clang::CallingConv> +static std::optional<clang::CallingConv> TranslateCallingConvention(llvm::codeview::CallingConvention conv) { using CC = llvm::codeview::CallingConvention; switch (conv) { @@ -203,69 +151,15 @@ TranslateCallingConvention(llvm::codeview::CallingConvention conv) { case CC::NearVector: return clang::CallingConv::CC_X86VectorCall; default: - return llvm::None; + return std::nullopt; } } -static llvm::Optional<CVTagRecord> -GetNestedTagDefinition(const NestedTypeRecord &Record, - const CVTagRecord &parent, TpiStream &tpi) { - // An LF_NESTTYPE is essentially a nested typedef / using declaration, but it - // is also used to indicate the primary definition of a nested class. That is - // to say, if you have: - // struct A { - // struct B {}; - // using C = B; - // }; - // Then in the debug info, this will appear as: - // LF_STRUCTURE `A::B` [type index = N] - // LF_STRUCTURE `A` - // LF_NESTTYPE [name = `B`, index = N] - // LF_NESTTYPE [name = `C`, index = N] - // In order to accurately reconstruct the decl context hierarchy, we need to - // know which ones are actual definitions and which ones are just aliases. - - // If it's a simple type, then this is something like `using foo = int`. - if (Record.Type.isSimple()) - return llvm::None; - - CVType cvt = tpi.getType(Record.Type); - - if (!IsTagRecord(cvt)) - return llvm::None; - - // If it's an inner definition, then treat whatever name we have here as a - // single component of a mangled name. So we can inject it into the parent's - // mangled name to see if it matches. - CVTagRecord child = CVTagRecord::create(cvt); - std::string qname = std::string(parent.asTag().getUniqueName()); - if (qname.size() < 4 || child.asTag().getUniqueName().size() < 4) - return llvm::None; - - // qname[3] is the tag type identifier (struct, class, union, etc). Since the - // inner tag type is not necessarily the same as the outer tag type, re-write - // it to match the inner tag type. - qname[3] = child.asTag().getUniqueName()[3]; - std::string piece; - if (qname[3] == 'W') - piece = "4"; - piece += Record.Name; - piece.push_back('@'); - qname.insert(4, std::move(piece)); - if (qname != child.asTag().UniqueName) - return llvm::None; - - return std::move(child); -} - static bool IsAnonymousNamespaceName(llvm::StringRef name) { return name == "`anonymous namespace'" || name == "`anonymous-namespace'"; } -PdbAstBuilder::PdbAstBuilder(ObjectFile &obj, PdbIndex &index, TypeSystemClang &clang) - : m_index(index), m_clang(clang) { - BuildParentMap(); -} +PdbAstBuilder::PdbAstBuilder(TypeSystemClang &clang) : m_clang(clang) {} lldb_private::CompilerDeclContext PdbAstBuilder::GetTranslationUnitDecl() { return ToCompilerDeclContext(*m_clang.GetTranslationUnitDecl()); @@ -273,6 +167,8 @@ lldb_private::CompilerDeclContext PdbAstBuilder::GetTranslationUnitDecl() { std::pair<clang::DeclContext *, std::string> PdbAstBuilder::CreateDeclInfoForType(const TagRecord &record, TypeIndex ti) { + SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>( + m_clang.GetSymbolFile()->GetBackingSymbolFile()); // FIXME: Move this to GetDeclContextContainingUID. if (!record.hasUniqueName()) return CreateDeclInfoForUndecoratedName(record.Name); @@ -297,8 +193,8 @@ PdbAstBuilder::CreateDeclInfoForType(const TagRecord &record, TypeIndex ti) { // If this type doesn't have a parent type in the debug info, then the best we // can do is to say that it's either a series of namespaces (if the scope is // non-empty), or the translation unit (if the scope is empty). - auto parent_iter = m_parent_types.find(ti); - if (parent_iter == m_parent_types.end()) { + std::optional<TypeIndex> parent_index = pdb->GetParentType(ti); + if (!parent_index) { if (scopes.empty()) return {context, uname}; @@ -322,7 +218,7 @@ PdbAstBuilder::CreateDeclInfoForType(const TagRecord &record, TypeIndex ti) { // recurse into our lazy type creation / AST reconstruction logic to get an // LLDB TypeSP for the parent. This will cause the AST to automatically get // the right DeclContext created for any parent. - clang::QualType parent_qt = GetOrCreateType(parent_iter->second); + clang::QualType parent_qt = GetOrCreateType(*parent_index); if (parent_qt.isNull()) return {nullptr, ""}; @@ -330,120 +226,6 @@ PdbAstBuilder::CreateDeclInfoForType(const TagRecord &record, TypeIndex ti) { return {context, uname}; } -void PdbAstBuilder::BuildParentMap() { - LazyRandomTypeCollection &types = m_index.tpi().typeCollection(); - - llvm::DenseMap<TypeIndex, TypeIndex> forward_to_full; - llvm::DenseMap<TypeIndex, TypeIndex> full_to_forward; - - struct RecordIndices { - TypeIndex forward; - TypeIndex full; - }; - - llvm::StringMap<RecordIndices> record_indices; - - for (auto ti = types.getFirst(); ti; ti = types.getNext(*ti)) { - CVType type = types.getType(*ti); - if (!IsTagRecord(type)) - continue; - - CVTagRecord tag = CVTagRecord::create(type); - - RecordIndices &indices = record_indices[tag.asTag().getUniqueName()]; - if (tag.asTag().isForwardRef()) - indices.forward = *ti; - else - indices.full = *ti; - - if (indices.full != TypeIndex::None() && - indices.forward != TypeIndex::None()) { - forward_to_full[indices.forward] = indices.full; - full_to_forward[indices.full] = indices.forward; - } - - // We're looking for LF_NESTTYPE records in the field list, so ignore - // forward references (no field list), and anything without a nested class - // (since there won't be any LF_NESTTYPE records). - if (tag.asTag().isForwardRef() || !tag.asTag().containsNestedClass()) - continue; - - struct ProcessTpiStream : public TypeVisitorCallbacks { - ProcessTpiStream(PdbIndex &index, TypeIndex parent, - const CVTagRecord &parent_cvt, - llvm::DenseMap<TypeIndex, TypeIndex> &parents) - : index(index), parents(parents), parent(parent), - parent_cvt(parent_cvt) {} - - PdbIndex &index; - llvm::DenseMap<TypeIndex, TypeIndex> &parents; - - unsigned unnamed_type_index = 1; - TypeIndex parent; - const CVTagRecord &parent_cvt; - - llvm::Error visitKnownMember(CVMemberRecord &CVR, - NestedTypeRecord &Record) override { - std::string unnamed_type_name; - if (Record.Name.empty()) { - unnamed_type_name = - llvm::formatv("<unnamed-type-$S{0}>", unnamed_type_index).str(); - Record.Name = unnamed_type_name; - ++unnamed_type_index; - } - llvm::Optional<CVTagRecord> tag = - GetNestedTagDefinition(Record, parent_cvt, index.tpi()); - if (!tag) - return llvm::ErrorSuccess(); - - parents[Record.Type] = parent; - return llvm::ErrorSuccess(); - } - }; - - CVType field_list_cvt = m_index.tpi().getType(tag.asTag().FieldList); - ProcessTpiStream process(m_index, *ti, tag, m_parent_types); - FieldListRecord field_list; - if (llvm::Error error = TypeDeserializer::deserializeAs<FieldListRecord>( - field_list_cvt, field_list)) - llvm::consumeError(std::move(error)); - if (llvm::Error error = visitMemberRecordStream(field_list.Data, process)) - llvm::consumeError(std::move(error)); - } - - // Now that we know the forward -> full mapping of all type indices, we can - // re-write all the indices. At the end of this process, we want a mapping - // consisting of fwd -> full and full -> full for all child -> parent indices. - // We can re-write the values in place, but for the keys, we must save them - // off so that we don't modify the map in place while also iterating it. - std::vector<TypeIndex> full_keys; - std::vector<TypeIndex> fwd_keys; - for (auto &entry : m_parent_types) { - TypeIndex key = entry.first; - TypeIndex value = entry.second; - - auto iter = forward_to_full.find(value); - if (iter != forward_to_full.end()) - entry.second = iter->second; - - iter = forward_to_full.find(key); - if (iter != forward_to_full.end()) - fwd_keys.push_back(key); - else - full_keys.push_back(key); - } - for (TypeIndex fwd : fwd_keys) { - TypeIndex full = forward_to_full[fwd]; - m_parent_types[full] = m_parent_types[fwd]; - } - for (TypeIndex full : full_keys) { - TypeIndex fwd = full_to_forward[full]; - m_parent_types[fwd] = m_parent_types[full]; - } - - // Now that -} - static bool isLocalVariableType(SymbolKind K) { switch (K) { case S_REGISTER: @@ -456,51 +238,16 @@ static bool isLocalVariableType(SymbolKind K) { return false; } -static std::string -RenderScopeList(llvm::ArrayRef<llvm::ms_demangle::Node *> nodes) { - lldbassert(!nodes.empty()); - - std::string result = nodes.front()->toString(); - nodes = nodes.drop_front(); - while (!nodes.empty()) { - result += "::"; - result += nodes.front()->toString(llvm::ms_demangle::OF_NoTagSpecifier); - nodes = nodes.drop_front(); - } - return result; -} - -static llvm::Optional<PublicSym32> FindPublicSym(const SegmentOffset &addr, - SymbolStream &syms, - PublicsStream &publics) { - llvm::FixedStreamArray<ulittle32_t> addr_map = publics.getAddressMap(); - auto iter = std::lower_bound( - addr_map.begin(), addr_map.end(), addr, - [&](const ulittle32_t &x, const SegmentOffset &y) { - CVSymbol s1 = syms.readRecord(x); - lldbassert(s1.kind() == S_PUB32); - PublicSym32 p1; - llvm::cantFail(SymbolDeserializer::deserializeAs<PublicSym32>(s1, p1)); - if (p1.Segment < y.segment) - return true; - return p1.Offset < y.offset; - }); - if (iter == addr_map.end()) - return llvm::None; - CVSymbol sym = syms.readRecord(*iter); - lldbassert(sym.kind() == S_PUB32); - PublicSym32 p; - llvm::cantFail(SymbolDeserializer::deserializeAs<PublicSym32>(sym, p)); - if (p.Segment == addr.segment && p.Offset == addr.offset) - return p; - return llvm::None; -} - clang::Decl *PdbAstBuilder::GetOrCreateSymbolForId(PdbCompilandSymId id) { - CVSymbol cvs = m_index.ReadSymbolRecord(id); + SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>( + m_clang.GetSymbolFile()->GetBackingSymbolFile()); + PdbIndex &index = pdb->GetIndex(); + CVSymbol cvs = index.ReadSymbolRecord(id); if (isLocalVariableType(cvs.kind())) { clang::DeclContext *scope = GetParentDeclContext(id); + if (!scope) + return nullptr; clang::Decl *scope_decl = clang::Decl::castFromDeclContext(scope); PdbCompilandSymId scope_id = PdbSymUid(m_decl_to_status[scope_decl].uid).asCompilandSym(); @@ -526,7 +273,8 @@ clang::Decl *PdbAstBuilder::GetOrCreateSymbolForId(PdbCompilandSymId id) { } } -llvm::Optional<CompilerDecl> PdbAstBuilder::GetOrCreateDeclForUid(PdbSymUid uid) { +std::optional<CompilerDecl> +PdbAstBuilder::GetOrCreateDeclForUid(PdbSymUid uid) { if (clang::Decl *result = TryGetDecl(uid)) return ToCompilerDecl(*result); @@ -538,19 +286,19 @@ llvm::Optional<CompilerDecl> PdbAstBuilder::GetOrCreateDeclForUid(PdbSymUid uid) case PdbSymUidKind::Type: { clang::QualType qt = GetOrCreateType(uid.asTypeSym()); if (qt.isNull()) - return llvm::None; + return std::nullopt; if (auto *tag = qt->getAsTagDecl()) { result = tag; break; } - return llvm::None; + return std::nullopt; } default: - return llvm::None; + return std::nullopt; } if (!result) - return llvm::None; + return std::nullopt; m_uid_to_decl[toOpaqueUid(uid)] = result; return ToCompilerDecl(*result); } @@ -572,10 +320,13 @@ clang::DeclContext *PdbAstBuilder::GetOrCreateDeclContextForUid(PdbSymUid uid) { std::pair<clang::DeclContext *, std::string> PdbAstBuilder::CreateDeclInfoForUndecoratedName(llvm::StringRef name) { + SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>( + m_clang.GetSymbolFile()->GetBackingSymbolFile()); + PdbIndex &index = pdb->GetIndex(); MSVCUndecoratedNameParser parser(name); llvm::ArrayRef<MSVCUndecoratedNameSpecifier> specs = parser.GetSpecifiers(); - auto context = FromCompilerDeclContext(GetTranslationUnitDecl()); + auto *context = FromCompilerDeclContext(GetTranslationUnitDecl()); llvm::StringRef uname = specs.back().GetBaseName(); specs = specs.drop_back(); @@ -585,7 +336,7 @@ PdbAstBuilder::CreateDeclInfoForUndecoratedName(llvm::StringRef name) { llvm::StringRef scope_name = specs.back().GetFullName(); // It might be a class name, try that first. - std::vector<TypeIndex> types = m_index.tpi().findRecordsByName(scope_name); + std::vector<TypeIndex> types = index.tpi().findRecordsByName(scope_name); while (!types.empty()) { clang::QualType qt = GetOrCreateType(types.back()); if (qt.isNull()) @@ -604,73 +355,30 @@ PdbAstBuilder::CreateDeclInfoForUndecoratedName(llvm::StringRef name) { return {context, std::string(uname)}; } -clang::DeclContext * -PdbAstBuilder::GetParentDeclContextForSymbol(const CVSymbol &sym) { - if (!SymbolHasAddress(sym)) - return CreateDeclInfoForUndecoratedName(getSymbolName(sym)).first; - SegmentOffset addr = GetSegmentAndOffset(sym); - llvm::Optional<PublicSym32> pub = - FindPublicSym(addr, m_index.symrecords(), m_index.publics()); - if (!pub) - return CreateDeclInfoForUndecoratedName(getSymbolName(sym)).first; - - llvm::ms_demangle::Demangler demangler; - StringView name{pub->Name.begin(), pub->Name.size()}; - llvm::ms_demangle::SymbolNode *node = demangler.parse(name); - if (!node) - return FromCompilerDeclContext(GetTranslationUnitDecl()); - llvm::ArrayRef<llvm::ms_demangle::Node *> name_components{ - node->Name->Components->Nodes, node->Name->Components->Count - 1}; - - if (!name_components.empty()) { - // Render the current list of scope nodes as a fully qualified name, and - // look it up in the debug info as a type name. If we find something, - // this is a type (which may itself be prefixed by a namespace). If we - // don't, this is a list of namespaces. - std::string qname = RenderScopeList(name_components); - std::vector<TypeIndex> matches = m_index.tpi().findRecordsByName(qname); - while (!matches.empty()) { - clang::QualType qt = GetOrCreateType(matches.back()); - if (qt.isNull()) - continue; - clang::TagDecl *tag = qt->getAsTagDecl(); - if (tag) - return clang::TagDecl::castToDeclContext(tag); - matches.pop_back(); - } - } - - // It's not a type. It must be a series of namespaces. - auto context = FromCompilerDeclContext(GetTranslationUnitDecl()); - while (!name_components.empty()) { - std::string ns = name_components.front()->toString(); - context = GetOrCreateNamespaceDecl(ns.c_str(), *context); - name_components = name_components.drop_front(); - } - return context; -} - clang::DeclContext *PdbAstBuilder::GetParentDeclContext(PdbSymUid uid) { // We must do this *without* calling GetOrCreate on the current uid, as // that would be an infinite recursion. + SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>( + m_clang.GetSymbolFile()->GetBackingSymbolFile()); + PdbIndex& index = pdb->GetIndex(); switch (uid.kind()) { case PdbSymUidKind::CompilandSym: { - llvm::Optional<PdbCompilandSymId> scope = - FindSymbolScope(m_index, uid.asCompilandSym()); + std::optional<PdbCompilandSymId> scope = + pdb->FindSymbolScope(uid.asCompilandSym()); if (scope) return GetOrCreateDeclContextForUid(*scope); - CVSymbol sym = m_index.ReadSymbolRecord(uid.asCompilandSym()); - return GetParentDeclContextForSymbol(sym); + CVSymbol sym = index.ReadSymbolRecord(uid.asCompilandSym()); + return CreateDeclInfoForUndecoratedName(getSymbolName(sym)).first; } case PdbSymUidKind::Type: { // It could be a namespace, class, or global. We don't support nested // functions yet. Anyway, we just need to consult the parent type map. PdbTypeSymId type_id = uid.asTypeSym(); - auto iter = m_parent_types.find(type_id.index); - if (iter == m_parent_types.end()) + std::optional<TypeIndex> parent_index = pdb->GetParentType(type_id.index); + if (!parent_index) return FromCompilerDeclContext(GetTranslationUnitDecl()); - return GetOrCreateDeclContextForUid(PdbTypeSymId(iter->second)); + return GetOrCreateDeclContextForUid(PdbTypeSymId(*parent_index)); } case PdbSymUidKind::FieldListMember: // In this case the parent DeclContext is the one for the class that this @@ -683,11 +391,11 @@ clang::DeclContext *PdbAstBuilder::GetParentDeclContext(PdbSymUid uid) { // that up in the TPI stream. If it's found, it's a type, othewrise it's // a series of namespaces. // FIXME: do this. - CVSymbol global = m_index.ReadSymbolRecord(uid.asGlobalSym()); + CVSymbol global = index.ReadSymbolRecord(uid.asGlobalSym()); switch (global.kind()) { case SymbolKind::S_GDATA32: case SymbolKind::S_LDATA32: - return GetParentDeclContextForSymbol(global); + return CreateDeclInfoForUndecoratedName(getSymbolName(global)).first;; case SymbolKind::S_PROCREF: case SymbolKind::S_LPROCREF: { ProcRefSym ref{global.kind()}; @@ -735,19 +443,21 @@ bool PdbAstBuilder::CompleteTagDecl(clang::TagDecl &tag) { return true; PdbTypeSymId type_id = PdbSymUid(status.uid).asTypeSym(); - - lldbassert(IsTagRecord(type_id, m_index.tpi())); + PdbIndex &index = static_cast<SymbolFileNativePDB *>( + m_clang.GetSymbolFile()->GetBackingSymbolFile()) + ->GetIndex(); + lldbassert(IsTagRecord(type_id, index.tpi())); clang::QualType tag_qt = m_clang.getASTContext().getTypeDeclType(&tag); TypeSystemClang::SetHasExternalStorage(tag_qt.getAsOpaquePtr(), false); TypeIndex tag_ti = type_id.index; - CVType cvt = m_index.tpi().getType(tag_ti); + CVType cvt = index.tpi().getType(tag_ti); if (cvt.kind() == LF_MODIFIER) tag_ti = LookThroughModifierRecord(cvt); - PdbTypeSymId best_ti = GetBestPossibleDecl(tag_ti, m_index.tpi()); - cvt = m_index.tpi().getType(best_ti.index); + PdbTypeSymId best_ti = GetBestPossibleDecl(tag_ti, index.tpi()); + cvt = index.tpi().getType(best_ti.index); lldbassert(IsTagRecord(cvt)); if (IsForwardRefUdt(cvt)) { @@ -757,7 +467,7 @@ bool PdbAstBuilder::CompleteTagDecl(clang::TagDecl &tag) { } TypeIndex field_list_ti = GetFieldListIndex(cvt); - CVType field_list_cvt = m_index.tpi().getType(field_list_ti); + CVType field_list_cvt = index.tpi().getType(field_list_ti); if (field_list_cvt.kind() != LF_FIELDLIST) return false; FieldListRecord field_list; @@ -768,13 +478,13 @@ bool PdbAstBuilder::CompleteTagDecl(clang::TagDecl &tag) { // Visit all members of this class, then perform any finalization necessary // to complete the class. CompilerType ct = ToCompilerType(tag_qt); - UdtRecordCompleter completer(best_ti, ct, tag, *this, m_index, + UdtRecordCompleter completer(best_ti, ct, tag, *this, index, m_decl_to_status, m_cxx_record_map); llvm::Error error = llvm::codeview::visitMemberRecordStream(field_list.Data, completer); completer.complete(); - status.resolved = true; + m_decl_to_status[&tag].resolved = true; if (error) { llvm::consumeError(std::move(error)); return false; @@ -984,7 +694,10 @@ PdbAstBuilder::GetOrCreateVariableDecl(PdbCompilandSymId scope_id, if (!scope) return nullptr; - CVSymbol sym = m_index.ReadSymbolRecord(var_id); + SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>( + m_clang.GetSymbolFile()->GetBackingSymbolFile()); + PdbIndex &index = pdb->GetIndex(); + CVSymbol sym = index.ReadSymbolRecord(var_id); return CreateVariableDecl(PdbSymUid(var_id), sym, *scope); } @@ -992,7 +705,10 @@ clang::VarDecl *PdbAstBuilder::GetOrCreateVariableDecl(PdbGlobalSymId var_id) { if (clang::Decl *decl = TryGetDecl(var_id)) return llvm::dyn_cast<clang::VarDecl>(decl); - CVSymbol sym = m_index.ReadSymbolRecord(var_id); + SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>( + m_clang.GetSymbolFile()->GetBackingSymbolFile()); + PdbIndex &index = pdb->GetIndex(); + CVSymbol sym = index.ReadSymbolRecord(var_id); auto context = FromCompilerDeclContext(GetTranslationUnitDecl()); return CreateVariableDecl(PdbSymUid(var_id), sym, *context); } @@ -1002,7 +718,10 @@ PdbAstBuilder::GetOrCreateTypedefDecl(PdbGlobalSymId id) { if (clang::Decl *decl = TryGetDecl(id)) return llvm::dyn_cast<clang::TypedefNameDecl>(decl); - CVSymbol sym = m_index.ReadSymbolRecord(id); + SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>( + m_clang.GetSymbolFile()->GetBackingSymbolFile()); + PdbIndex &index = pdb->GetIndex(); + CVSymbol sym = index.ReadSymbolRecord(id); lldbassert(sym.kind() == S_UDT); UDTSym udt = llvm::cantFail(SymbolDeserializer::deserializeAs<UDTSym>(sym)); @@ -1010,7 +729,7 @@ PdbAstBuilder::GetOrCreateTypedefDecl(PdbGlobalSymId id) { PdbTypeSymId real_type_id{udt.Type, false}; clang::QualType qt = GetOrCreateType(real_type_id); - if (qt.isNull()) + if (qt.isNull() || !scope) return nullptr; std::string uname = std::string(DropNameScope(udt.Name)); @@ -1034,7 +753,10 @@ clang::QualType PdbAstBuilder::CreateType(PdbTypeSymId type) { if (type.index.isSimple()) return CreateSimpleType(type.index); - CVType cvt = m_index.tpi().getType(type.index); + SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>( + m_clang.GetSymbolFile()->GetBackingSymbolFile()); + PdbIndex &index = pdb->GetIndex(); + CVType cvt = index.tpi().getType(type.index); if (cvt.kind() == LF_MODIFIER) { ModifierRecord modifier; @@ -1090,7 +812,10 @@ clang::QualType PdbAstBuilder::GetOrCreateType(PdbTypeSymId type) { if (iter != m_uid_to_type.end()) return iter->second; - PdbTypeSymId best_type = GetBestPossibleDecl(type, m_index.tpi()); + SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>( + m_clang.GetSymbolFile()->GetBackingSymbolFile()); + PdbIndex &index = pdb->GetIndex(); + PdbTypeSymId best_type = GetBestPossibleDecl(type, index.tpi()); clang::QualType qt; if (best_type.index != type.index) { @@ -1110,7 +835,7 @@ clang::QualType PdbAstBuilder::GetOrCreateType(PdbTypeSymId type) { return {}; m_uid_to_type[toOpaqueUid(type)] = qt; - if (IsTagRecord(type, m_index.tpi())) { + if (IsTagRecord(type, index.tpi())) { clang::TagDecl *tag = qt->getAsTagDecl(); lldbassert(m_decl_to_status.count(tag) == 0); @@ -1129,6 +854,9 @@ PdbAstBuilder::CreateFunctionDecl(PdbCompilandSymId func_id, bool is_inline, clang::DeclContext *parent) { clang::FunctionDecl *function_decl = nullptr; if (parent->isRecord()) { + SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>( + m_clang.GetSymbolFile()->GetBackingSymbolFile()); + PdbIndex &index = pdb->GetIndex(); clang::QualType parent_qt = llvm::cast<clang::TypeDecl>(parent) ->getTypeForDecl() ->getCanonicalTypeInternal(); @@ -1142,29 +870,29 @@ PdbAstBuilder::CreateFunctionDecl(PdbCompilandSymId func_id, } } - CVType cvt = m_index.tpi().getType(func_ti); + CVType cvt = index.tpi().getType(func_ti); MemberFunctionRecord func_record(static_cast<TypeRecordKind>(cvt.kind())); llvm::cantFail(TypeDeserializer::deserializeAs<MemberFunctionRecord>( cvt, func_record)); TypeIndex class_index = func_record.getClassType(); - CVType parent_cvt = m_index.tpi().getType(class_index); + CVType parent_cvt = index.tpi().getType(class_index); TagRecord tag_record = CVTagRecord::create(parent_cvt).asTag(); // If it's a forward reference, try to get the real TypeIndex. if (tag_record.isForwardRef()) { llvm::Expected<TypeIndex> eti = - m_index.tpi().findFullDeclForForwardRef(class_index); + index.tpi().findFullDeclForForwardRef(class_index); if (eti) { - tag_record = CVTagRecord::create(m_index.tpi().getType(*eti)).asTag(); + tag_record = CVTagRecord::create(index.tpi().getType(*eti)).asTag(); } } if (!tag_record.FieldList.isSimple()) { - CVType field_list_cvt = m_index.tpi().getType(tag_record.FieldList); + CVType field_list_cvt = index.tpi().getType(tag_record.FieldList); FieldListRecord field_list; if (llvm::Error error = TypeDeserializer::deserializeAs<FieldListRecord>( field_list_cvt, field_list)) llvm::consumeError(std::move(error)); - CreateMethodDecl process(m_index, m_clang, func_ti, function_decl, + CreateMethodDecl process(index, m_clang, func_ti, function_decl, parent_opaque_ty, func_name, func_ct); if (llvm::Error err = visitMemberRecordStream(field_list.Data, process)) llvm::consumeError(std::move(err)); @@ -1191,8 +919,11 @@ PdbAstBuilder::CreateFunctionDecl(PdbCompilandSymId func_id, clang::FunctionDecl * PdbAstBuilder::GetOrCreateInlinedFunctionDecl(PdbCompilandSymId inlinesite_id) { + SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>( + m_clang.GetSymbolFile()->GetBackingSymbolFile()); + PdbIndex &index = pdb->GetIndex(); CompilandIndexItem *cii = - m_index.compilands().GetCompiland(inlinesite_id.modi); + index.compilands().GetCompiland(inlinesite_id.modi); CVSymbol sym = cii->m_debug_stream.readSymbolAtOffset(inlinesite_id.offset); InlineSiteSym inline_site(static_cast<SymbolRecordKind>(sym.kind())); cantFail(SymbolDeserializer::deserializeAs<InlineSiteSym>(sym, inline_site)); @@ -1229,7 +960,10 @@ clang::FunctionDecl * PdbAstBuilder::CreateFunctionDeclFromId(PdbTypeSymId func_tid, PdbCompilandSymId func_sid) { lldbassert(func_tid.is_ipi); - CVType func_cvt = m_index.ipi().getType(func_tid.index); + SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>( + m_clang.GetSymbolFile()->GetBackingSymbolFile()); + PdbIndex &index = pdb->GetIndex(); + CVType func_cvt = index.ipi().getType(func_tid.index); llvm::StringRef func_name; TypeIndex func_ti; clang::DeclContext *parent = nullptr; @@ -1251,7 +985,7 @@ PdbAstBuilder::CreateFunctionDeclFromId(PdbTypeSymId func_tid, func_ti = fir.getFunctionType(); parent = FromCompilerDeclContext(GetTranslationUnitDecl()); if (!fir.ParentScope.isNoneType()) { - CVType parent_cvt = m_index.ipi().getType(fir.ParentScope); + CVType parent_cvt = index.ipi().getType(fir.ParentScope); if (parent_cvt.kind() == LF_STRING_ID) { StringIdRecord sir; cantFail( @@ -1265,7 +999,7 @@ PdbAstBuilder::CreateFunctionDeclFromId(PdbTypeSymId func_tid, lldbassert(false && "Invalid function id type!"); } clang::QualType func_qt = GetOrCreateType(func_ti); - if (func_qt.isNull()) + if (func_qt.isNull() || !parent) return nullptr; CompilerType func_ct = ToCompilerType(func_qt); uint32_t param_count = @@ -1280,6 +1014,8 @@ PdbAstBuilder::GetOrCreateFunctionDecl(PdbCompilandSymId func_id) { return llvm::dyn_cast<clang::FunctionDecl>(decl); clang::DeclContext *parent = GetParentDeclContext(PdbSymUid(func_id)); + if (!parent) + return nullptr; std::string context_name; if (clang::NamespaceDecl *ns = llvm::dyn_cast<clang::NamespaceDecl>(parent)) { context_name = ns->getQualifiedNameAsString(); @@ -1287,7 +1023,10 @@ PdbAstBuilder::GetOrCreateFunctionDecl(PdbCompilandSymId func_id) { context_name = tag->getQualifiedNameAsString(); } - CVSymbol cvs = m_index.ReadSymbolRecord(func_id); + SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>( + m_clang.GetSymbolFile()->GetBackingSymbolFile()); + PdbIndex &index = pdb->GetIndex(); + CVSymbol cvs = index.ReadSymbolRecord(func_id); ProcSym proc(static_cast<SymbolRecordKind>(cvs.kind())); llvm::cantFail(SymbolDeserializer::deserializeAs<ProcSym>(cvs, proc)); @@ -1308,7 +1047,6 @@ PdbAstBuilder::GetOrCreateFunctionDecl(PdbCompilandSymId func_id) { llvm::StringRef proc_name = proc.Name; proc_name.consume_front(context_name); proc_name.consume_front("::"); - clang::FunctionDecl *function_decl = CreateFunctionDecl(func_id, proc_name, proc.FunctionType, func_ct, func_type->getNumParams(), storage, false, parent); @@ -1328,7 +1066,10 @@ PdbAstBuilder::GetOrCreateFunctionDecl(PdbCompilandSymId func_id) { void PdbAstBuilder::CreateFunctionParameters(PdbCompilandSymId func_id, clang::FunctionDecl &function_decl, uint32_t param_count) { - CompilandIndexItem *cii = m_index.compilands().GetCompiland(func_id.modi); + SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>( + m_clang.GetSymbolFile()->GetBackingSymbolFile()); + PdbIndex &index = pdb->GetIndex(); + CompilandIndexItem *cii = index.compilands().GetCompiland(func_id.modi); CVSymbolArray scope = cii->m_debug_stream.getSymbolArrayForScope(func_id.offset); @@ -1423,7 +1164,10 @@ clang::QualType PdbAstBuilder::CreateEnumType(PdbTypeSymId id, clang::QualType PdbAstBuilder::CreateArrayType(const ArrayRecord &ar) { clang::QualType element_type = GetOrCreateType(ar.ElementType); - uint64_t element_size = GetSizeOfType({ar.ElementType}, m_index.tpi()); + SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>( + m_clang.GetSymbolFile()->GetBackingSymbolFile()); + PdbIndex &index = pdb->GetIndex(); + uint64_t element_size = GetSizeOfType({ar.ElementType}, index.tpi()); if (element_type.isNull() || element_size == 0) return {}; uint64_t element_count = ar.Size / element_size; @@ -1436,13 +1180,16 @@ clang::QualType PdbAstBuilder::CreateArrayType(const ArrayRecord &ar) { clang::QualType PdbAstBuilder::CreateFunctionType( TypeIndex args_type_idx, TypeIndex return_type_idx, llvm::codeview::CallingConvention calling_convention) { - TpiStream &stream = m_index.tpi(); + SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>( + m_clang.GetSymbolFile()->GetBackingSymbolFile()); + PdbIndex &index = pdb->GetIndex(); + TpiStream &stream = index.tpi(); CVType args_cvt = stream.getType(args_type_idx); ArgListRecord args; llvm::cantFail( TypeDeserializer::deserializeAs<ArgListRecord>(args_cvt, args)); - llvm::ArrayRef<TypeIndex> arg_indices = llvm::makeArrayRef(args.ArgIndices); + llvm::ArrayRef<TypeIndex> arg_indices = llvm::ArrayRef(args.ArgIndices); bool is_variadic = IsCVarArgsFunction(arg_indices); if (is_variadic) arg_indices = arg_indices.drop_back(); @@ -1461,7 +1208,7 @@ clang::QualType PdbAstBuilder::CreateFunctionType( if (return_type.isNull()) return {}; - llvm::Optional<clang::CallingConv> cc = + std::optional<clang::CallingConv> cc = TranslateCallingConvention(calling_convention); if (!cc) return {}; @@ -1486,10 +1233,16 @@ static bool isBlockDecl(clang::DeclContext &context) { return llvm::isa<clang::BlockDecl>(&context); } -void PdbAstBuilder::ParseAllNamespacesPlusChildrenOf( - llvm::Optional<llvm::StringRef> parent) { - TypeIndex ti{m_index.tpi().TypeIndexBegin()}; - for (const CVType &cvt : m_index.tpi().typeArray()) { +void PdbAstBuilder::ParseNamespace(clang::DeclContext &context) { + clang::NamespaceDecl *ns = llvm::dyn_cast<clang::NamespaceDecl>(&context); + if (m_parsed_namespaces.contains(ns)) + return; + std::string qname = ns->getQualifiedNameAsString(); + SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>( + m_clang.GetSymbolFile()->GetBackingSymbolFile()); + PdbIndex &index = pdb->GetIndex(); + TypeIndex ti{index.tpi().TypeIndexBegin()}; + for (const CVType &cvt : index.tpi().typeArray()) { PdbTypeSymId tid{ti}; ++ti; @@ -1498,12 +1251,6 @@ void PdbAstBuilder::ParseAllNamespacesPlusChildrenOf( CVTagRecord tag = CVTagRecord::create(cvt); - if (!parent) { - clang::QualType qt = GetOrCreateType(tid); - CompleteType(qt); - continue; - } - // Call CreateDeclInfoForType unconditionally so that the namespace info // gets created. But only call CreateRecordType if the namespace name // matches. @@ -1514,41 +1261,68 @@ void PdbAstBuilder::ParseAllNamespacesPlusChildrenOf( continue; clang::NamespaceDecl *ns = llvm::cast<clang::NamespaceDecl>(context); - std::string actual_ns = ns->getQualifiedNameAsString(); - if (llvm::StringRef(actual_ns).startswith(*parent)) { - clang::QualType qt = GetOrCreateType(tid); - CompleteType(qt); - continue; + llvm::StringRef ns_name = ns->getName(); + if (ns_name.startswith(qname)) { + ns_name = ns_name.drop_front(qname.size()); + if (ns_name.startswith("::")) + GetOrCreateType(tid); } } + ParseAllFunctionsAndNonLocalVars(); + m_parsed_namespaces.insert(ns); +} - uint32_t module_count = m_index.dbi().modules().getModuleCount(); - for (uint16_t modi = 0; modi < module_count; ++modi) { - CompilandIndexItem &cii = m_index.compilands().GetOrCreateCompiland(modi); - const CVSymbolArray &symbols = cii.m_debug_stream.getSymbolArray(); - auto iter = symbols.begin(); - while (iter != symbols.end()) { - PdbCompilandSymId sym_id{modi, iter.offset()}; - - switch (iter->kind()) { - case S_GPROC32: - case S_LPROC32: - GetOrCreateFunctionDecl(sym_id); - iter = symbols.at(getScopeEndOffset(*iter)); - break; - case S_GDATA32: - case S_GTHREAD32: - case S_LDATA32: - case S_LTHREAD32: - GetOrCreateVariableDecl(PdbCompilandSymId(modi, 0), sym_id); - ++iter; - break; - default: - ++iter; +void PdbAstBuilder::ParseAllTypes() { + llvm::call_once(m_parse_all_types, [this]() { + SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>( + m_clang.GetSymbolFile()->GetBackingSymbolFile()); + PdbIndex &index = pdb->GetIndex(); + TypeIndex ti{index.tpi().TypeIndexBegin()}; + for (const CVType &cvt : index.tpi().typeArray()) { + PdbTypeSymId tid{ti}; + ++ti; + + if (!IsTagRecord(cvt)) continue; + + GetOrCreateType(tid); + } + }); +} + +void PdbAstBuilder::ParseAllFunctionsAndNonLocalVars() { + llvm::call_once(m_parse_functions_and_non_local_vars, [this]() { + SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>( + m_clang.GetSymbolFile()->GetBackingSymbolFile()); + PdbIndex &index = pdb->GetIndex(); + uint32_t module_count = index.dbi().modules().getModuleCount(); + for (uint16_t modi = 0; modi < module_count; ++modi) { + CompilandIndexItem &cii = index.compilands().GetOrCreateCompiland(modi); + const CVSymbolArray &symbols = cii.m_debug_stream.getSymbolArray(); + auto iter = symbols.begin(); + while (iter != symbols.end()) { + PdbCompilandSymId sym_id{modi, iter.offset()}; + + switch (iter->kind()) { + case S_GPROC32: + case S_LPROC32: + GetOrCreateFunctionDecl(sym_id); + iter = symbols.at(getScopeEndOffset(*iter)); + break; + case S_GDATA32: + case S_GTHREAD32: + case S_LDATA32: + case S_LTHREAD32: + GetOrCreateVariableDecl(PdbCompilandSymId(modi, 0), sym_id); + ++iter; + break; + default: + ++iter; + continue; + } } } - } + }); } static CVSymbolArray skipFunctionParameters(clang::Decl &decl, @@ -1578,11 +1352,14 @@ static CVSymbolArray skipFunctionParameters(clang::Decl &decl, } void PdbAstBuilder::ParseBlockChildren(PdbCompilandSymId block_id) { - CVSymbol sym = m_index.ReadSymbolRecord(block_id); + SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>( + m_clang.GetSymbolFile()->GetBackingSymbolFile()); + PdbIndex &index = pdb->GetIndex(); + CVSymbol sym = index.ReadSymbolRecord(block_id); lldbassert(sym.kind() == S_GPROC32 || sym.kind() == S_LPROC32 || sym.kind() == S_BLOCK32 || sym.kind() == S_INLINESITE); CompilandIndexItem &cii = - m_index.compilands().GetOrCreateCompiland(block_id.modi); + index.compilands().GetOrCreateCompiland(block_id.modi); CVSymbolArray symbols = cii.m_debug_stream.getSymbolArrayForScope(block_id.offset); @@ -1632,14 +1409,13 @@ void PdbAstBuilder::ParseDeclsForContext(clang::DeclContext &context) { // work (such as parsing the items that appear within the namespaces) at the // same time. if (context.isTranslationUnit()) { - ParseAllNamespacesPlusChildrenOf(llvm::None); + ParseAllTypes(); + ParseAllFunctionsAndNonLocalVars(); return; } if (context.isNamespace()) { - clang::NamespaceDecl &ns = *llvm::dyn_cast<clang::NamespaceDecl>(&context); - std::string qname = ns.getQualifiedNameAsString(); - ParseAllNamespacesPlusChildrenOf(llvm::StringRef{qname}); + ParseNamespace(context); return; } @@ -1654,7 +1430,7 @@ CompilerDecl PdbAstBuilder::ToCompilerDecl(clang::Decl &decl) { } CompilerType PdbAstBuilder::ToCompilerType(clang::QualType qt) { - return {&m_clang, qt.getAsOpaquePtr()}; + return {m_clang.weak_from_this(), qt.getAsOpaquePtr()}; } CompilerDeclContext diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h index 40425dd4c6e7..b7cad30c69c0 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h @@ -11,11 +11,13 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/Threading.h" #include "Plugins/ExpressionParser/Clang/ClangASTImporter.h" #include "PdbIndex.h" #include "PdbSymUid.h" +#include <optional> namespace clang { class TagDecl; @@ -51,11 +53,11 @@ struct DeclStatus { class PdbAstBuilder { public: // Constructors and Destructors - PdbAstBuilder(ObjectFile &obj, PdbIndex &index, TypeSystemClang &clang); + PdbAstBuilder(TypeSystemClang &clang); lldb_private::CompilerDeclContext GetTranslationUnitDecl(); - llvm::Optional<lldb_private::CompilerDecl> + std::optional<lldb_private::CompilerDecl> GetOrCreateDeclForUid(PdbSymUid uid); clang::DeclContext *GetOrCreateDeclContextForUid(PdbSymUid uid); clang::DeclContext *GetParentDeclContext(PdbSymUid uid); @@ -83,7 +85,7 @@ public: clang::DeclContext *FromCompilerDeclContext(CompilerDeclContext context); TypeSystemClang &clang() { return m_clang; } - ClangASTImporter &importer() { return m_importer; } + ClangASTImporter &GetClangASTImporter() { return m_importer; } void Dump(Stream &stream); @@ -113,9 +115,6 @@ private: clang::VarDecl *CreateVariableDecl(PdbSymUid uid, llvm::codeview::CVSymbol sym, clang::DeclContext &scope); - clang::DeclContext * - GetParentDeclContextForSymbol(const llvm::codeview::CVSymbol &sym); - clang::NamespaceDecl *GetOrCreateNamespaceDecl(const char *name, clang::DeclContext &context); clang::FunctionDecl *CreateFunctionDeclFromId(PdbTypeSymId func_tid, @@ -125,23 +124,23 @@ private: TypeIndex func_ti, CompilerType func_ct, uint32_t param_count, clang::StorageClass func_storage, bool is_inline, clang::DeclContext *parent); - void ParseAllNamespacesPlusChildrenOf(llvm::Optional<llvm::StringRef> parent); + void ParseNamespace(clang::DeclContext &parent); + void ParseAllTypes(); + void ParseAllFunctionsAndNonLocalVars(); void ParseDeclsForSimpleContext(clang::DeclContext &context); void ParseBlockChildren(PdbCompilandSymId block_id); - void BuildParentMap(); std::pair<clang::DeclContext *, std::string> CreateDeclInfoForType(const llvm::codeview::TagRecord &record, TypeIndex ti); std::pair<clang::DeclContext *, std::string> CreateDeclInfoForUndecoratedName(llvm::StringRef uname); clang::QualType CreateSimpleType(TypeIndex ti); - PdbIndex &m_index; TypeSystemClang &m_clang; ClangASTImporter m_importer; - - llvm::DenseMap<TypeIndex, TypeIndex> m_parent_types; + llvm::once_flag m_parse_functions_and_non_local_vars; + llvm::once_flag m_parse_all_types; llvm::DenseMap<clang::Decl *, DeclStatus> m_decl_to_status; llvm::DenseMap<lldb::user_id_t, clang::Decl *> m_uid_to_decl; llvm::DenseMap<lldb::user_id_t, clang::QualType> m_uid_to_type; @@ -151,6 +150,7 @@ private: llvm::DenseMap<lldb::opaque_compiler_type_t, llvm::SmallSet<std::pair<llvm::StringRef, CompilerType>, 8>> m_cxx_record_map; + llvm::DenseSet<clang::NamespaceDecl *> m_parsed_namespaces; }; } // namespace npdb diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/PdbIndex.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/PdbIndex.cpp index 3a76f8bff316..ea778fc6cca6 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/PdbIndex.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/PdbIndex.cpp @@ -22,6 +22,7 @@ #include "lldb/Utility/LLDBAssert.h" #include "lldb/lldb-defines.h" +#include <optional> using namespace lldb_private; using namespace lldb_private::npdb; @@ -72,15 +73,15 @@ lldb::addr_t PdbIndex::MakeVirtualAddress(uint16_t segment, static_cast<lldb::addr_t>(offset); } -llvm::Optional<uint16_t> -PdbIndex::GetModuleIndexForAddr(uint16_t segment, uint32_t offset) const { +std::optional<uint16_t> PdbIndex::GetModuleIndexForAddr(uint16_t segment, + uint32_t offset) const { return GetModuleIndexForVa(MakeVirtualAddress(segment, offset)); } -llvm::Optional<uint16_t> PdbIndex::GetModuleIndexForVa(lldb::addr_t va) const { +std::optional<uint16_t> PdbIndex::GetModuleIndexForVa(lldb::addr_t va) const { auto iter = m_va_to_modi.find(va); if (iter == m_va_to_modi.end()) - return llvm::None; + return std::nullopt; return iter.value(); } @@ -137,7 +138,7 @@ void PdbIndex::BuildAddrToSymbolMap(CompilandIndexItem &cci) { std::vector<SymbolAndUid> PdbIndex::FindSymbolsByVa(lldb::addr_t va) { std::vector<SymbolAndUid> result; - llvm::Optional<uint16_t> modi = GetModuleIndexForVa(va); + std::optional<uint16_t> modi = GetModuleIndexForVa(va); if (!modi) return result; diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/PdbIndex.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/PdbIndex.h index 138c63d79a59..796aa4c8dfd1 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/PdbIndex.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/PdbIndex.h @@ -11,7 +11,6 @@ #include "lldb/lldb-types.h" #include "llvm/ADT/IntervalMap.h" -#include "llvm/ADT/Optional.h" #include "llvm/DebugInfo/PDB/Native/PDBFile.h" #include "llvm/DebugInfo/PDB/PDBTypes.h" @@ -20,6 +19,7 @@ #include <map> #include <memory> +#include <optional> namespace llvm { namespace pdb { @@ -149,9 +149,9 @@ public: llvm::codeview::CVSymbol ReadSymbolRecord(PdbCompilandSymId cu_sym) const; llvm::codeview::CVSymbol ReadSymbolRecord(PdbGlobalSymId global) const; - llvm::Optional<uint16_t> GetModuleIndexForAddr(uint16_t segment, - uint32_t offset) const; - llvm::Optional<uint16_t> GetModuleIndexForVa(lldb::addr_t va) const; + std::optional<uint16_t> GetModuleIndexForAddr(uint16_t segment, + uint32_t offset) const; + std::optional<uint16_t> GetModuleIndexForVa(lldb::addr_t va) const; }; } // namespace npdb } // namespace lldb_private diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp index 7d730ecdd1f3..164bfa8b3726 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp @@ -19,6 +19,7 @@ #include "llvm/DebugInfo/PDB/Native/TpiStream.h" #include "Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h" +#include "Plugins/SymbolFile/NativePDB/CodeViewRegisterMapping.h" #include "lldb/Symbol/Block.h" #include "lldb/Utility/LLDBAssert.h" #include "lldb/Utility/LLDBLog.h" @@ -29,6 +30,8 @@ using namespace lldb_private::npdb; using namespace llvm::codeview; using namespace llvm::pdb; +// The returned range list is guaranteed to be sorted and no overlaps between +// adjacent ranges because fields in LocalVariableAddrGap are unsigned integers. static Variable::RangeList MakeRangeList(const PdbIndex &index, const LocalVariableAddrRange &range, llvm::ArrayRef<LocalVariableAddrGap> gaps) { @@ -52,21 +55,144 @@ MakeRangeList(const PdbIndex &index, const LocalVariableAddrRange &range, } namespace { -struct FindMembersSize : public TypeVisitorCallbacks { - FindMembersSize( - std::map<uint64_t, std::pair<RegisterId, uint32_t>> &members_info, - TpiStream &tpi) - : members_info(members_info), tpi(tpi) {} - std::map<uint64_t, std::pair<RegisterId, uint32_t>> &members_info; - TpiStream &tpi; - llvm::Error visitKnownMember(CVMemberRecord &cvr, - DataMemberRecord &member) override { - members_info.insert( - {member.getFieldOffset(), - {llvm::codeview::RegisterId::NONE, GetSizeOfType(member.Type, tpi)}}); - return llvm::Error::success(); +struct MemberLocations { + std::map<uint64_t, MemberValLocation> offset_to_location; + DWARFExpression expr; + bool is_dwarf = false; + + MemberLocations() = default; + MemberLocations(const DWARFExpression &expr) : expr(expr), is_dwarf(true) {} + MemberLocations(uint64_t offset, const MemberValLocation &member_loc) { + insert(offset, member_loc); } + + void insert(uint64_t offset, const MemberValLocation &member_loc) { + offset_to_location[offset] = member_loc; + } + + struct Comparator { + public: + bool operator()(const MemberLocations &, const MemberLocations &) const { + return false; + } + }; }; + +// A range map with address ranges to a map of pair of offset and locaitons. +typedef RangeDataVector<lldb::addr_t, lldb::addr_t, MemberLocations, 0, + MemberLocations::Comparator> + RangeMap; + +void AddMemberLocationRanges(RangeMap &location_map, uint64_t offset, + MemberValLocation member_loc, + const Variable::RangeList &ranges) { + RangeMap new_location_map; + auto add_overlap_region = [&](lldb::addr_t base, lldb::addr_t end, + RangeMap::Entry *entry) { + RangeMap::Entry overlap_region = {base, end - base, entry->data}; + overlap_region.data.insert(offset, member_loc); + new_location_map.Append(overlap_region); + }; + + for (const auto &range : ranges) { + lldb::addr_t base = range.GetRangeBase(); + lldb::addr_t end = range.GetRangeEnd(); + uint32_t base_idx = location_map.FindEntryIndexThatContainsOrFollows(base); + while (auto *entry = location_map.GetMutableEntryAtIndex(base_idx)) { + if (base >= end || entry->base >= end) + break; + if (entry->data.is_dwarf) + base = entry->GetRangeEnd(); + else { + lldb::addr_t entry_end = entry->GetRangeEnd(); + if (base > entry->base) { + if (end < entry_end) + new_location_map.Append({end, entry_end - end, entry->data}); + add_overlap_region(base, end < entry_end ? end : entry_end, entry); + entry->SetRangeEnd(base); + } else if (base < entry->base) { + new_location_map.Append( + {base, entry->base - base, {offset, member_loc}}); + if (entry_end == end) + entry->data.insert(offset, member_loc); + else { + add_overlap_region(entry->base, end, entry); + entry->ShrinkFront(end - entry->base); + } + } else { + if (end < entry_end) { + new_location_map.Append({end, entry_end, entry->data}); + entry->SetRangeEnd(end); + } + entry->data.insert(offset, member_loc); + } + base = entry_end; + } + ++base_idx; + } + if (base >= end) + continue; + new_location_map.Append({base, end - base, {offset, member_loc}}); + } + for (const auto &entry : new_location_map) + location_map.Append(entry); + if (!new_location_map.IsEmpty()) + location_map.Sort(); +} + +void AddDwarfRange(RangeMap &location_map, const DWARFExpression &expr, + const Variable::RangeList &ranges) { + if (!expr.IsValid()) + return; + RangeMap new_location_map; + for (const auto &range : ranges) { + lldb::addr_t base = range.GetRangeBase(); + lldb::addr_t end = range.GetRangeEnd(); + uint32_t base_idx = location_map.FindEntryIndexThatContains(base); + uint32_t end_idx = location_map.FindEntryIndexThatContains(end - 1); + // range is within an entry. + if (base_idx == end_idx && base_idx != UINT32_MAX) { + auto *entry = location_map.GetMutableEntryAtIndex(base_idx); + if (base > entry->base) { + new_location_map.Append({entry->base, base - entry->base, entry->data}); + entry->ShrinkFront(base - entry->base); + } + if (end == entry->GetRangeEnd()) + entry->data = expr; + else { + entry->ShrinkFront(end - base); + new_location_map.Append({base, end - base, expr}); + } + continue; + } + base_idx = location_map.FindEntryIndexThatContainsOrFollows(base); + if (auto *entry = location_map.GetMutableEntryAtIndex(base_idx)) { + if (entry->Contains(base) && entry->base != base) { + entry->SetRangeEnd(base); + ++base_idx; + } + } + end_idx = location_map.FindEntryIndexThatContainsOrFollows(end - 1); + if (auto *entry = location_map.GetMutableEntryAtIndex(end_idx)) { + if (entry->Contains(end - 1)) { + if (entry->GetRangeEnd() == end) + ++end_idx; + else + entry->ShrinkFront(end - entry->base); + } + } + + if (end_idx == UINT32_MAX) + end_idx = location_map.GetSize(); + // Erase existing ranges covered by new range. + location_map.Erase(base_idx, end_idx); + new_location_map.Append({base, end - base, expr}); + } + + for (const auto &entry : new_location_map) + location_map.Append(entry); + location_map.Sort(); +} } // namespace CVTagRecord CVTagRecord::create(CVType type) { @@ -612,207 +738,175 @@ VariableInfo lldb_private::npdb::GetVariableLocationInfo( if (sym.kind() == S_REGREL32) { RegRelativeSym reg(SymbolRecordKind::RegRelativeSym); cantFail(SymbolDeserializer::deserializeAs<RegRelativeSym>(sym, reg)); - result.location = - MakeRegRelLocationExpression(reg.Register, reg.Offset, module); - result.ranges.emplace(); + result.location = DWARFExpressionList( + module, MakeRegRelLocationExpression(reg.Register, reg.Offset, module), + nullptr); return result; } if (sym.kind() == S_REGISTER) { RegisterSym reg(SymbolRecordKind::RegisterSym); cantFail(SymbolDeserializer::deserializeAs<RegisterSym>(sym, reg)); - result.location = MakeEnregisteredLocationExpression(reg.Register, module); - result.ranges.emplace(); + result.location = DWARFExpressionList( + module, MakeEnregisteredLocationExpression(reg.Register, module), + nullptr); return result; } if (sym.kind() == S_LOCAL) { LocalSym local(SymbolRecordKind::LocalSym); - cantFail(SymbolDeserializer::deserializeAs<LocalSym>(sym, local)); + if (llvm::Error error = + SymbolDeserializer::deserializeAs<LocalSym>(sym, local)) { + llvm::consumeError(std::move(error)); + return result; + } PdbCompilandSymId loc_specifier_id(var_id.modi, var_id.offset + sym.RecordData.size()); - CVSymbol loc_specifier_cvs = index.ReadSymbolRecord(loc_specifier_id); - switch(loc_specifier_cvs.kind()) { - case S_DEFRANGE_FRAMEPOINTER_REL: { - DefRangeFramePointerRelSym loc( - SymbolRecordKind::DefRangeFramePointerRelSym); - cantFail(SymbolDeserializer::deserializeAs<DefRangeFramePointerRelSym>( - loc_specifier_cvs, loc)); - - Variable::RangeList ranges = MakeRangeList(index, loc.Range, loc.Gaps); - - PdbCompilandSymId func_scope_id = - PdbSymUid(func_block.GetID()).asCompilandSym(); - CVSymbol func_block_cvs = index.ReadSymbolRecord(func_scope_id); - lldbassert(func_block_cvs.kind() == S_GPROC32 || - func_block_cvs.kind() == S_LPROC32); - - PdbCompilandSymId frame_proc_id( - func_scope_id.modi, func_scope_id.offset + func_block_cvs.length()); - - RegisterId base_reg = - GetBaseFrameRegister(index, frame_proc_id, result.is_param); - if (base_reg == RegisterId::NONE) - break; - if (base_reg == RegisterId::VFRAME) { - llvm::StringRef program; - if (GetFrameDataProgram(index, ranges, program)) { - result.location = - MakeVFrameRelLocationExpression(program, loc.Hdr.Offset, module); - result.ranges = std::move(ranges); - } else { - // invalid variable + CVSymbol loc_specifier_cvs; + // Only used for S_DEFRANGE_FRAMEPOINTER_REL. + RegisterId base_reg = RegisterId::NONE; + size_t type_size = GetSizeOfType(result.type, index.tpi()); + // A map from offset of a field in parent to size of the field. + std::map<uint64_t, size_t> offset_to_size; + + // When overlaps happens, always prefer the one that doesn't split the value + // into multiple locations and the location parsed first is perfered. + RangeMap location_map; + + // Iterate through all location records after S_LOCAL. They describe the + // value of this variable at different locations. + bool finished = false; + while (!finished) { + loc_specifier_cvs = index.ReadSymbolRecord(loc_specifier_id); + switch (loc_specifier_cvs.kind()) { + case S_DEFRANGE_FRAMEPOINTER_REL: { + DefRangeFramePointerRelSym loc( + SymbolRecordKind::DefRangeFramePointerRelSym); + if (llvm::Error error = + SymbolDeserializer::deserializeAs<DefRangeFramePointerRelSym>( + loc_specifier_cvs, loc)) { + llvm::consumeError(std::move(error)); + return result; + } + Variable::RangeList raw_ranges = + MakeRangeList(index, loc.Range, loc.Gaps); + if (base_reg == RegisterId::NONE) { + PdbCompilandSymId func_scope_id = + PdbSymUid(func_block.GetID()).asCompilandSym(); + CVSymbol func_block_cvs = index.ReadSymbolRecord(func_scope_id); + lldbassert(func_block_cvs.kind() == S_GPROC32 || + func_block_cvs.kind() == S_LPROC32); + PdbCompilandSymId frame_proc_id(func_scope_id.modi, + func_scope_id.offset + + func_block_cvs.length()); + base_reg = + GetBaseFrameRegister(index, frame_proc_id, result.is_param); + if (base_reg == RegisterId::NONE) + break; } - } else { - result.location = - MakeRegRelLocationExpression(base_reg, loc.Hdr.Offset, module); - result.ranges = std::move(ranges); + DWARFExpression expr; + if (base_reg == RegisterId::VFRAME) { + llvm::StringRef program; + if (GetFrameDataProgram(index, raw_ranges, program)) + expr = MakeVFrameRelLocationExpression(program, loc.Hdr.Offset, + module); + else { + // invalid variable + } + } else + expr = MakeRegRelLocationExpression(base_reg, loc.Hdr.Offset, module); + AddDwarfRange(location_map, expr, raw_ranges); + break; } - break; - } - case S_DEFRANGE_REGISTER_REL: { - DefRangeRegisterRelSym loc(SymbolRecordKind::DefRangeRegisterRelSym); - cantFail(SymbolDeserializer::deserializeAs<DefRangeRegisterRelSym>( - loc_specifier_cvs, loc)); - - Variable::RangeList ranges = MakeRangeList(index, loc.Range, loc.Gaps); - - RegisterId base_reg = (RegisterId)(uint16_t)loc.Hdr.Register; - - if (base_reg == RegisterId::VFRAME) { - llvm::StringRef program; - if (GetFrameDataProgram(index, ranges, program)) { - result.location = MakeVFrameRelLocationExpression( - program, loc.Hdr.BasePointerOffset, module); - result.ranges = std::move(ranges); - } else { - // invalid variable + case S_DEFRANGE_REGISTER: { + DefRangeRegisterSym loc(SymbolRecordKind::DefRangeRegisterSym); + if (llvm::Error error = + SymbolDeserializer::deserializeAs<DefRangeRegisterSym>( + loc_specifier_cvs, loc)) { + llvm::consumeError(std::move(error)); + return result; } - } else { - result.location = MakeRegRelLocationExpression( - base_reg, loc.Hdr.BasePointerOffset, module); - result.ranges = std::move(ranges); + RegisterId reg_id = (RegisterId)(uint16_t)loc.Hdr.Register; + Variable::RangeList raw_ranges = + MakeRangeList(index, loc.Range, loc.Gaps); + DWARFExpression expr = + MakeEnregisteredLocationExpression(reg_id, module); + AddDwarfRange(location_map, expr, raw_ranges); + break; } - break; - } - case S_DEFRANGE_REGISTER: { - DefRangeRegisterSym loc(SymbolRecordKind::DefRangeRegisterSym); - cantFail(SymbolDeserializer::deserializeAs<DefRangeRegisterSym>( - loc_specifier_cvs, loc)); - - RegisterId base_reg = (RegisterId)(uint16_t)loc.Hdr.Register; - result.ranges = MakeRangeList(index, loc.Range, loc.Gaps); - result.location = MakeEnregisteredLocationExpression(base_reg, module); - break; - } - case S_DEFRANGE_SUBFIELD_REGISTER: { - // A map from offset in parent to pair of register id and size. If the - // variable is a simple type, then we don't know the number of subfields. - // Otherwise, the size of the map should be greater than or equal to the - // number of sub field record. - std::map<uint64_t, std::pair<RegisterId, uint32_t>> members_info; - bool is_simple_type = result.type.isSimple(); - if (!is_simple_type) { - CVType class_cvt = index.tpi().getType(result.type); - TypeIndex class_id = result.type; - if (class_cvt.kind() == LF_MODIFIER) - class_id = LookThroughModifierRecord(class_cvt); - if (IsForwardRefUdt(class_id, index.tpi())) { - auto expected_full_ti = - index.tpi().findFullDeclForForwardRef(class_id); - if (!expected_full_ti) { - llvm::consumeError(expected_full_ti.takeError()); - break; - } - class_cvt = index.tpi().getType(*expected_full_ti); + case S_DEFRANGE_REGISTER_REL: { + DefRangeRegisterRelSym loc(SymbolRecordKind::DefRangeRegisterRelSym); + if (llvm::Error error = + SymbolDeserializer::deserializeAs<DefRangeRegisterRelSym>( + loc_specifier_cvs, loc)) { + llvm::consumeError(std::move(error)); + return result; } - if (IsTagRecord(class_cvt)) { - TagRecord tag_record = CVTagRecord::create(class_cvt).asTag(); - CVType field_list_cvt = index.tpi().getType(tag_record.FieldList); - FieldListRecord field_list; - if (llvm::Error error = - TypeDeserializer::deserializeAs<FieldListRecord>( - field_list_cvt, field_list)) - llvm::consumeError(std::move(error)); - FindMembersSize find_members_size(members_info, index.tpi()); - if (llvm::Error err = visitMemberRecordStream(field_list.Data, - find_members_size)) { - llvm::consumeError(std::move(err)); - break; + Variable::RangeList raw_ranges = + MakeRangeList(index, loc.Range, loc.Gaps); + RegisterId reg_id = (RegisterId)(uint16_t)loc.Hdr.Register; + DWARFExpression expr; + if (reg_id == RegisterId::VFRAME) { + llvm::StringRef program; + if (GetFrameDataProgram(index, raw_ranges, program)) + expr = MakeVFrameRelLocationExpression( + program, loc.Hdr.BasePointerOffset, module); + else { + // invalid variable } } else { - // TODO: Handle poiner type. - break; + expr = MakeRegRelLocationExpression(reg_id, loc.Hdr.BasePointerOffset, + module); } + // FIXME: If it's UDT, we need to know the size of the value in byte. + if (!loc.hasSpilledUDTMember()) + AddDwarfRange(location_map, expr, raw_ranges); + break; } - - size_t member_idx = 0; - // Assuming S_DEFRANGE_SUBFIELD_REGISTER is followed only by - // S_DEFRANGE_SUBFIELD_REGISTER, need to verify. - while (loc_specifier_cvs.kind() == S_DEFRANGE_SUBFIELD_REGISTER) { - if (!is_simple_type && member_idx >= members_info.size()) - break; - + case S_DEFRANGE_SUBFIELD_REGISTER: { DefRangeSubfieldRegisterSym loc( SymbolRecordKind::DefRangeSubfieldRegisterSym); - cantFail(SymbolDeserializer::deserializeAs<DefRangeSubfieldRegisterSym>( - loc_specifier_cvs, loc)); - - if (result.ranges) { - result.ranges = Variable::RangeList::GetOverlaps( - *result.ranges, MakeRangeList(index, loc.Range, loc.Gaps)); - } else { - result.ranges = MakeRangeList(index, loc.Range, loc.Gaps); - result.ranges->Sort(); + if (llvm::Error error = + SymbolDeserializer::deserializeAs<DefRangeSubfieldRegisterSym>( + loc_specifier_cvs, loc)) { + llvm::consumeError(std::move(error)); + return result; } - if (is_simple_type) { - if (members_info.count(loc.Hdr.OffsetInParent)) { - // Malformed record. - result.ranges->Clear(); - return result; - } - members_info[loc.Hdr.OffsetInParent] = { - (RegisterId)(uint16_t)loc.Hdr.Register, 0}; - } else { - if (!members_info.count(loc.Hdr.OffsetInParent)) { - // Malformed record. - result.ranges->Clear(); - return result; - } - members_info[loc.Hdr.OffsetInParent].first = - (RegisterId)(uint16_t)loc.Hdr.Register; - } - // Go to next S_DEFRANGE_SUBFIELD_REGISTER. - loc_specifier_id = PdbCompilandSymId( - loc_specifier_id.modi, - loc_specifier_id.offset + loc_specifier_cvs.RecordData.size()); - loc_specifier_cvs = index.ReadSymbolRecord(loc_specifier_id); + Variable::RangeList ranges = MakeRangeList(index, loc.Range, loc.Gaps); + uint32_t reg_size = + GetRegisterSize((RegisterId)(uint16_t)loc.Hdr.Register); + if (reg_size == 0) + break; + offset_to_size[loc.Hdr.OffsetInParent] = reg_size; + AddMemberLocationRanges(location_map, loc.Hdr.OffsetInParent, + {loc.Hdr.Register, 0, true}, ranges); + break; } - // Fix size for simple type. - if (is_simple_type) { - auto cur = members_info.begin(); - auto end = members_info.end(); - auto next = cur; - ++next; - uint32_t size = 0; - while (next != end) { - cur->second.second = next->first - cur->first; - size += cur->second.second; - cur = next++; - } - cur->second.second = - GetTypeSizeForSimpleKind(result.type.getSimpleKind()) - size; + // FIXME: Handle other kinds. LLVM only generates the 4 types of records + // above. MSVC generates other location types. + case S_DEFRANGE: + case S_DEFRANGE_SUBFIELD: + case S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE: + break; + default: + finished = true; + break; } - result.location = - MakeEnregisteredLocationExpressionForClass(members_info, module); - break; + loc_specifier_id = PdbCompilandSymId( + loc_specifier_id.modi, + loc_specifier_id.offset + loc_specifier_cvs.RecordData.size()); } - default: - // FIXME: Handle other kinds. LLVM only generates the 4 types of records - // above. - break; + for (const auto &entry : location_map) { + DWARFExpression dwarf_expr = + entry.data.is_dwarf ? entry.data.expr + : MakeEnregisteredLocationExpressionForComposite( + entry.data.offset_to_location, + offset_to_size, type_size, module); + + result.location.AddExpression(entry.GetRangeBase(), entry.GetRangeEnd(), + dwarf_expr); } return result; } @@ -1010,6 +1104,11 @@ size_t lldb_private::npdb::GetSizeOfType(PdbTypeSymId id, return GetSizeOfTypeInternal<ClassRecord>(cvt); case LF_UNION: return GetSizeOfTypeInternal<UnionRecord>(cvt); + case LF_BITFIELD: { + BitFieldRecord record; + llvm::cantFail(TypeDeserializer::deserializeAs<BitFieldRecord>(cvt, record)); + return GetSizeOfType({record.Type}, tpi); + } default: break; } diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.h index 066bcc89fd3b..1f888f4de1fe 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.h @@ -13,7 +13,6 @@ #include "lldb/Symbol/Variable.h" #include "lldb/lldb-enumerations.h" -#include "llvm/ADT/Optional.h" #include "llvm/DebugInfo/CodeView/CodeView.h" #include "llvm/DebugInfo/CodeView/SymbolRecord.h" #include "llvm/DebugInfo/CodeView/TypeRecord.h" @@ -103,8 +102,7 @@ struct SegmentOffsetLength { struct VariableInfo { llvm::StringRef name; llvm::codeview::TypeIndex type; - llvm::Optional<DWARFExpression> location; - llvm::Optional<Variable::RangeList> ranges; + DWARFExpressionList location; bool is_param; }; diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp index 7e10e315be20..82d3707acfa4 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp @@ -8,12 +8,6 @@ #include "SymbolFileNativePDB.h" -#include "clang/AST/Attr.h" -#include "clang/AST/CharUnits.h" -#include "clang/AST/Decl.h" -#include "clang/AST/DeclCXX.h" -#include "clang/AST/Type.h" - #include "Plugins/ExpressionParser/Clang/ClangUtil.h" #include "Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h" #include "Plugins/ObjectFile/PDB/ObjectFilePDB.h" @@ -59,10 +53,10 @@ #include "llvm/Support/MemoryBuffer.h" #include "DWARFLocationExpression.h" -#include "PdbAstBuilder.h" #include "PdbSymUid.h" #include "PdbUtil.h" #include "UdtRecordCompleter.h" +#include <optional> using namespace lldb; using namespace lldb_private; @@ -120,7 +114,7 @@ loadMatchingPDBFile(std::string exe_path, llvm::BumpPtrAllocator &allocator) { if (!FileSystem::Instance().Exists(pdb_file)) { const auto exe_dir = FileSpec(exe_path).CopyByRemovingLastPathComponent(); const auto pdb_name = FileSpec(pdb_file).GetFilename().GetCString(); - pdb_file = exe_dir.CopyByAppendingPathComponent(pdb_name).GetCString(); + pdb_file = exe_dir.CopyByAppendingPathComponent(pdb_name).GetPathAsConstString().GetStringRef(); } // If the file is not a PDB or if it doesn't have a matching GUID, fail. @@ -233,6 +227,57 @@ static bool IsClassRecord(TypeLeafKind kind) { } } +static std::optional<CVTagRecord> +GetNestedTagDefinition(const NestedTypeRecord &Record, + const CVTagRecord &parent, TpiStream &tpi) { + // An LF_NESTTYPE is essentially a nested typedef / using declaration, but it + // is also used to indicate the primary definition of a nested class. That is + // to say, if you have: + // struct A { + // struct B {}; + // using C = B; + // }; + // Then in the debug info, this will appear as: + // LF_STRUCTURE `A::B` [type index = N] + // LF_STRUCTURE `A` + // LF_NESTTYPE [name = `B`, index = N] + // LF_NESTTYPE [name = `C`, index = N] + // In order to accurately reconstruct the decl context hierarchy, we need to + // know which ones are actual definitions and which ones are just aliases. + + // If it's a simple type, then this is something like `using foo = int`. + if (Record.Type.isSimple()) + return std::nullopt; + + CVType cvt = tpi.getType(Record.Type); + + if (!IsTagRecord(cvt)) + return std::nullopt; + + // If it's an inner definition, then treat whatever name we have here as a + // single component of a mangled name. So we can inject it into the parent's + // mangled name to see if it matches. + CVTagRecord child = CVTagRecord::create(cvt); + std::string qname = std::string(parent.asTag().getUniqueName()); + if (qname.size() < 4 || child.asTag().getUniqueName().size() < 4) + return std::nullopt; + + // qname[3] is the tag type identifier (struct, class, union, etc). Since the + // inner tag type is not necessarily the same as the outer tag type, re-write + // it to match the inner tag type. + qname[3] = child.asTag().getUniqueName()[3]; + std::string piece; + if (qname[3] == 'W') + piece = "4"; + piece += Record.Name; + piece.push_back('@'); + qname.insert(4, std::move(piece)); + if (qname != child.asTag().UniqueName) + return std::nullopt; + + return std::move(child); +} + void SymbolFileNativePDB::Initialize() { PluginManager::RegisterPlugin(GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance, @@ -310,10 +355,9 @@ void SymbolFileNativePDB::InitializeObject() { LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err), "Failed to initialize"); } else { - ts_or_err->SetSymbolFile(this); - auto *clang = llvm::cast_or_null<TypeSystemClang>(&ts_or_err.get()); - lldbassert(clang); - m_ast = std::make_unique<PdbAstBuilder>(*m_objfile_sp, *m_index, *clang); + if (auto ts = *ts_or_err) + ts->SetSymbolFile(this); + BuildParentMap(); } } @@ -338,6 +382,13 @@ Block &SymbolFileNativePDB::CreateBlock(PdbCompilandSymId block_id) { CompUnitSP comp_unit = GetOrCreateCompileUnit(*cii); lldb::user_id_t opaque_block_uid = toOpaqueUid(block_id); BlockSP child_block = std::make_shared<Block>(opaque_block_uid); + auto ts_or_err = GetTypeSystemForLanguage(comp_unit->GetLanguage()); + if (auto err = ts_or_err.takeError()) + return *child_block; + auto ts = *ts_or_err; + if (!ts) + return *child_block; + PdbAstBuilder* ast_builder = ts->GetNativePDBParser(); switch (sym.kind()) { case S_GPROC32: @@ -345,10 +396,13 @@ Block &SymbolFileNativePDB::CreateBlock(PdbCompilandSymId block_id) { // This is a function. It must be global. Creating the Function entry // for it automatically creates a block for it. FunctionSP func = GetOrCreateFunction(block_id, *comp_unit); - Block &block = func->GetBlock(false); - if (block.GetNumRanges() == 0) - block.AddRange(Block::Range(0, func->GetAddressRange().GetByteSize())); - return block; + if (func) { + Block &block = func->GetBlock(false); + if (block.GetNumRanges() == 0) + block.AddRange(Block::Range(0, func->GetAddressRange().GetByteSize())); + return block; + } + break; } case S_BLOCK32: { // This is a block. Its parent is either a function or another block. In @@ -360,8 +414,26 @@ Block &SymbolFileNativePDB::CreateBlock(PdbCompilandSymId block_id) { lldbassert(block.Parent != 0); PdbCompilandSymId parent_id(block_id.modi, block.Parent); Block &parent_block = GetOrCreateBlock(parent_id); + Function *func = parent_block.CalculateSymbolContextFunction(); + lldbassert(func); + lldb::addr_t block_base = + m_index->MakeVirtualAddress(block.Segment, block.CodeOffset); + lldb::addr_t func_base = + func->GetAddressRange().GetBaseAddress().GetFileAddress(); + if (block_base >= func_base) + child_block->AddRange(Block::Range(block_base - func_base, block.CodeSize)); + else { + GetObjectFile()->GetModule()->ReportError( + "S_BLOCK32 at modi: {0:d} offset: {1:d}: adding range " + "[{2:x16}-{3:x16}) which has a base that is less than the " + "function's " + "low PC 0x%" PRIx64 ". Please file a bug and attach the file at the " + "start of this error message", + block_id.modi, block_id.offset, block_base, + block_base + block.CodeSize, func_base); + } parent_block.AddChild(child_block); - m_ast->GetOrCreateBlockDecl(block_id); + ast_builder->GetOrCreateBlockDecl(block_id); m_blocks.insert({opaque_block_uid, child_block}); break; } @@ -372,7 +444,7 @@ Block &SymbolFileNativePDB::CreateBlock(PdbCompilandSymId block_id) { std::shared_ptr<InlineSite> inline_site = m_inline_sites[opaque_block_uid]; Block &parent_block = GetOrCreateBlock(inline_site->parent_id); parent_block.AddChild(child_block); - m_ast->GetOrCreateInlinedFunctionDecl(block_id); + ast_builder->GetOrCreateInlinedFunctionDecl(block_id); // Copy ranges from InlineSite to Block. for (size_t i = 0; i < inline_site->ranges.GetSize(); ++i) { auto *entry = inline_site->ranges.GetEntryAtIndex(i); @@ -433,7 +505,13 @@ lldb::FunctionSP SymbolFileNativePDB::CreateFunction(PdbCompilandSymId func_id, comp_unit.AddFunction(func_sp); - m_ast->GetOrCreateFunctionDecl(func_id); + auto ts_or_err = GetTypeSystemForLanguage(comp_unit.GetLanguage()); + if (auto err = ts_or_err.takeError()) + return func_sp; + auto ts = *ts_or_err; + if (!ts) + return func_sp; + ts->GetNativePDBParser()->GetOrCreateFunctionDecl(func_id); return func_sp; } @@ -474,10 +552,10 @@ lldb::TypeSP SymbolFileNativePDB::CreateModifierType(PdbTypeSymId type_id, Declaration decl; lldb::TypeSP modified_type = GetOrCreateType(mr.ModifiedType); - return std::make_shared<Type>(toOpaqueUid(type_id), this, ConstString(name), - modified_type->GetByteSize(nullptr), nullptr, - LLDB_INVALID_UID, Type::eEncodingIsUID, decl, - ct, Type::ResolveState::Full); + return MakeType(toOpaqueUid(type_id), ConstString(name), + modified_type->GetByteSize(nullptr), nullptr, + LLDB_INVALID_UID, Type::eEncodingIsUID, decl, ct, + Type::ResolveState::Full); } lldb::TypeSP @@ -494,10 +572,9 @@ SymbolFileNativePDB::CreatePointerType(PdbTypeSymId type_id, } Declaration decl; - return std::make_shared<Type>(toOpaqueUid(type_id), this, ConstString(), - pr.getSize(), nullptr, LLDB_INVALID_UID, - Type::eEncodingIsUID, decl, ct, - Type::ResolveState::Full); + return MakeType(toOpaqueUid(type_id), ConstString(), pr.getSize(), nullptr, + LLDB_INVALID_UID, Type::eEncodingIsUID, decl, ct, + Type::ResolveState::Full); } lldb::TypeSP SymbolFileNativePDB::CreateSimpleType(TypeIndex ti, @@ -505,9 +582,9 @@ lldb::TypeSP SymbolFileNativePDB::CreateSimpleType(TypeIndex ti, uint64_t uid = toOpaqueUid(PdbTypeSymId(ti, false)); if (ti == TypeIndex::NullptrT()) { Declaration decl; - return std::make_shared<Type>( - uid, this, ConstString("std::nullptr_t"), 0, nullptr, LLDB_INVALID_UID, - Type::eEncodingIsUID, decl, ct, Type::ResolveState::Full); + return MakeType(uid, ConstString("std::nullptr_t"), 0, nullptr, + LLDB_INVALID_UID, Type::eEncodingIsUID, decl, ct, + Type::ResolveState::Full); } if (ti.getSimpleMode() != SimpleTypeMode::Direct) { @@ -526,9 +603,8 @@ lldb::TypeSP SymbolFileNativePDB::CreateSimpleType(TypeIndex ti, return nullptr; } Declaration decl; - return std::make_shared<Type>( - uid, this, ConstString(), pointer_size, nullptr, LLDB_INVALID_UID, - Type::eEncodingIsUID, decl, ct, Type::ResolveState::Full); + return MakeType(uid, ConstString(), pointer_size, nullptr, LLDB_INVALID_UID, + Type::eEncodingIsUID, decl, ct, Type::ResolveState::Full); } if (ti.getSimpleKind() == SimpleTypeKind::NotTranslated) @@ -538,9 +614,8 @@ lldb::TypeSP SymbolFileNativePDB::CreateSimpleType(TypeIndex ti, llvm::StringRef type_name = GetSimpleTypeName(ti.getSimpleKind()); Declaration decl; - return std::make_shared<Type>(uid, this, ConstString(type_name), size, - nullptr, LLDB_INVALID_UID, Type::eEncodingIsUID, - decl, ct, Type::ResolveState::Full); + return MakeType(uid, ConstString(type_name), size, nullptr, LLDB_INVALID_UID, + Type::eEncodingIsUID, decl, ct, Type::ResolveState::Full); } static std::string GetUnqualifiedTypeName(const TagRecord &record) { @@ -571,10 +646,9 @@ SymbolFileNativePDB::CreateClassStructUnion(PdbTypeSymId type_id, // FIXME: Search IPI stream for LF_UDT_MOD_SRC_LINE. Declaration decl; - return std::make_shared<Type>(toOpaqueUid(type_id), this, ConstString(uname), - size, nullptr, LLDB_INVALID_UID, - Type::eEncodingIsUID, decl, ct, - Type::ResolveState::Forward); + return MakeType(toOpaqueUid(type_id), ConstString(uname), size, nullptr, + LLDB_INVALID_UID, Type::eEncodingIsUID, decl, ct, + Type::ResolveState::Forward); } lldb::TypeSP SymbolFileNativePDB::CreateTagType(PdbTypeSymId type_id, @@ -597,11 +671,10 @@ lldb::TypeSP SymbolFileNativePDB::CreateTagType(PdbTypeSymId type_id, Declaration decl; TypeSP underlying_type = GetOrCreateType(er.UnderlyingType); - return std::make_shared<lldb_private::Type>( - toOpaqueUid(type_id), this, ConstString(uname), - underlying_type->GetByteSize(nullptr), nullptr, LLDB_INVALID_UID, - lldb_private::Type::eEncodingIsUID, decl, ct, - lldb_private::Type::ResolveState::Forward); + return MakeType(toOpaqueUid(type_id), ConstString(uname), + underlying_type->GetByteSize(nullptr), nullptr, + LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl, + ct, lldb_private::Type::ResolveState::Forward); } TypeSP SymbolFileNativePDB::CreateArrayType(PdbTypeSymId type_id, @@ -610,33 +683,30 @@ TypeSP SymbolFileNativePDB::CreateArrayType(PdbTypeSymId type_id, TypeSP element_type = GetOrCreateType(ar.ElementType); Declaration decl; - TypeSP array_sp = std::make_shared<lldb_private::Type>( - toOpaqueUid(type_id), this, ConstString(), ar.Size, nullptr, - LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl, ct, - lldb_private::Type::ResolveState::Full); + TypeSP array_sp = + MakeType(toOpaqueUid(type_id), ConstString(), ar.Size, nullptr, + LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl, ct, + lldb_private::Type::ResolveState::Full); array_sp->SetEncodingType(element_type.get()); return array_sp; } - TypeSP SymbolFileNativePDB::CreateFunctionType(PdbTypeSymId type_id, const MemberFunctionRecord &mfr, CompilerType ct) { Declaration decl; - return std::make_shared<lldb_private::Type>( - toOpaqueUid(type_id), this, ConstString(), 0, nullptr, LLDB_INVALID_UID, - lldb_private::Type::eEncodingIsUID, decl, ct, - lldb_private::Type::ResolveState::Full); + return MakeType(toOpaqueUid(type_id), ConstString(), 0, nullptr, + LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl, + ct, lldb_private::Type::ResolveState::Full); } TypeSP SymbolFileNativePDB::CreateProcedureType(PdbTypeSymId type_id, const ProcedureRecord &pr, CompilerType ct) { Declaration decl; - return std::make_shared<lldb_private::Type>( - toOpaqueUid(type_id), this, ConstString(), 0, nullptr, LLDB_INVALID_UID, - lldb_private::Type::eEncodingIsUID, decl, ct, - lldb_private::Type::ResolveState::Full); + return MakeType(toOpaqueUid(type_id), ConstString(), 0, nullptr, + LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl, + ct, lldb_private::Type::ResolveState::Full); } TypeSP SymbolFileNativePDB::CreateType(PdbTypeSymId type_id, CompilerType ct) { @@ -701,7 +771,7 @@ TypeSP SymbolFileNativePDB::CreateType(PdbTypeSymId type_id, CompilerType ct) { TypeSP SymbolFileNativePDB::CreateAndCacheType(PdbTypeSymId type_id) { // If they search for a UDT which is a forward ref, try and resolve the full // decl and just map the forward ref uid to the full decl record. - llvm::Optional<PdbTypeSymId> full_decl_uid; + std::optional<PdbTypeSymId> full_decl_uid; if (IsForwardRefUdt(type_id, m_index->tpi())) { auto expected_full_ti = m_index->tpi().findFullDeclForForwardRef(type_id.index); @@ -726,12 +796,19 @@ TypeSP SymbolFileNativePDB::CreateAndCacheType(PdbTypeSymId type_id) { } PdbTypeSymId best_decl_id = full_decl_uid ? *full_decl_uid : type_id; + auto ts_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); + if (auto err = ts_or_err.takeError()) + return nullptr; + auto ts = *ts_or_err; + if (!ts) + return nullptr; - clang::QualType qt = m_ast->GetOrCreateType(best_decl_id); + PdbAstBuilder* ast_builder = ts->GetNativePDBParser(); + clang::QualType qt = ast_builder->GetOrCreateType(best_decl_id); if (qt.isNull()) return nullptr; - TypeSP result = CreateType(best_decl_id, m_ast->ToCompilerType(qt)); + TypeSP result = CreateType(best_decl_id, ast_builder->ToCompilerType(qt)); if (!result) return nullptr; @@ -774,7 +851,7 @@ VariableSP SymbolFileNativePDB::CreateGlobalVariable(PdbGlobalSymId var_id) { switch (sym.kind()) { case S_GDATA32: is_external = true; - LLVM_FALLTHROUGH; + [[fallthrough]]; case S_LDATA32: { DataSym ds(sym.kind()); llvm::cantFail(SymbolDeserializer::deserializeAs<DataSym>(sym, ds)); @@ -789,7 +866,7 @@ VariableSP SymbolFileNativePDB::CreateGlobalVariable(PdbGlobalSymId var_id) { } case S_GTHREAD32: is_external = true; - LLVM_FALLTHROUGH; + [[fallthrough]]; case S_LTHREAD32: { ThreadLocalDataSym tlds(sym.kind()); llvm::cantFail( @@ -807,7 +884,7 @@ VariableSP SymbolFileNativePDB::CreateGlobalVariable(PdbGlobalSymId var_id) { } CompUnitSP comp_unit; - llvm::Optional<uint16_t> modi = m_index->GetModuleIndexForVa(addr); + std::optional<uint16_t> modi = m_index->GetModuleIndexForVa(addr); if (!modi) { return nullptr; } @@ -820,8 +897,14 @@ VariableSP SymbolFileNativePDB::CreateGlobalVariable(PdbGlobalSymId var_id) { SymbolFileTypeSP type_sp = std::make_shared<SymbolFileType>(*this, toOpaqueUid(tid)); Variable::RangeList ranges; + auto ts_or_err = GetTypeSystemForLanguage(comp_unit->GetLanguage()); + if (auto err = ts_or_err.takeError()) + return nullptr; + auto ts = *ts_or_err; + if (!ts) + return nullptr; - m_ast->GetOrCreateVariableDecl(var_id); + ts->GetNativePDBParser()->GetOrCreateVariableDecl(var_id); ModuleSP module_sp = GetObjectFile()->GetModule(); DWARFExpressionList location( @@ -921,10 +1004,14 @@ Block &SymbolFileNativePDB::GetOrCreateBlock(PdbCompilandSymId block_id) { void SymbolFileNativePDB::ParseDeclsForContext( lldb_private::CompilerDeclContext decl_ctx) { - clang::DeclContext *context = m_ast->FromCompilerDeclContext(decl_ctx); + TypeSystem* ts_or_err = decl_ctx.GetTypeSystem(); + if (!ts_or_err) + return; + PdbAstBuilder* ast_builder = ts_or_err->GetNativePDBParser(); + clang::DeclContext *context = ast_builder->FromCompilerDeclContext(decl_ctx); if (!context) return; - m_ast->ParseDeclsForContext(*context); + ast_builder->ParseDeclsForContext(*context); } lldb::CompUnitSP SymbolFileNativePDB::ParseCompileUnitAtIndex(uint32_t index) { @@ -995,7 +1082,7 @@ uint32_t SymbolFileNativePDB::ResolveSymbolContext( lldb::addr_t file_addr = addr.GetFileAddress(); if (NeedsResolvedCompileUnit(resolve_scope)) { - llvm::Optional<uint16_t> modi = m_index->GetModuleIndexForVa(file_addr); + std::optional<uint16_t> modi = m_index->GetModuleIndexForVa(file_addr); if (!modi) return 0; CompUnitSP cu_sp = GetCompileUnitAtIndex(*modi); @@ -1024,16 +1111,25 @@ uint32_t SymbolFileNativePDB::ResolveSymbolContext( continue; if (type == PDB_SymType::Function) { sc.function = GetOrCreateFunction(csid, *sc.comp_unit).get(); - Block &block = sc.function->GetBlock(true); - addr_t func_base = - sc.function->GetAddressRange().GetBaseAddress().GetFileAddress(); - addr_t offset = file_addr - func_base; - sc.block = block.FindInnermostBlockByOffset(offset); + if (sc.function) { + Block &block = sc.function->GetBlock(true); + addr_t func_base = + sc.function->GetAddressRange().GetBaseAddress().GetFileAddress(); + addr_t offset = file_addr - func_base; + sc.block = block.FindInnermostBlockByOffset(offset); + } } if (type == PDB_SymType::Block) { - sc.block = &GetOrCreateBlock(csid); - sc.function = sc.block->CalculateSymbolContextFunction(); + Block &block = GetOrCreateBlock(csid); + sc.function = block.CalculateSymbolContextFunction(); + if (sc.function) { + sc.function->GetBlock(true); + addr_t func_base = + sc.function->GetAddressRange().GetBaseAddress().GetFileAddress(); + addr_t offset = file_addr - func_base; + sc.block = block.FindInnermostBlockByOffset(offset); + } } if (sc.function) resolved_flags |= eSymbolContextFunction; @@ -1329,11 +1425,11 @@ void SymbolFileNativePDB::ParseInlineSite(PdbCompilandSymId id, // Parse range and line info. uint32_t code_offset = 0; int32_t line_offset = 0; - llvm::Optional<uint32_t> code_offset_base; - llvm::Optional<uint32_t> code_offset_end; - llvm::Optional<int32_t> cur_line_offset; - llvm::Optional<int32_t> next_line_offset; - llvm::Optional<uint32_t> next_file_offset; + std::optional<uint32_t> code_offset_base; + std::optional<uint32_t> code_offset_end; + std::optional<int32_t> cur_line_offset; + std::optional<int32_t> next_line_offset; + std::optional<uint32_t> next_file_offset; bool is_terminal_entry = false; bool is_start_of_statement = true; @@ -1406,10 +1502,10 @@ void SymbolFileNativePDB::ParseInlineSite(PdbCompilandSymId id, file_offset = *next_file_offset; if (next_line_offset) { cur_line_offset = next_line_offset; - next_line_offset = llvm::None; + next_line_offset = std::nullopt; } - code_offset_base = is_terminal_entry ? llvm::None : code_offset_end; - code_offset_end = next_file_offset = llvm::None; + code_offset_base = is_terminal_entry ? std::nullopt : code_offset_end; + code_offset_end = next_file_offset = std::nullopt; } if (code_offset_base && cur_line_offset) { if (is_terminal_entry) { @@ -1534,7 +1630,16 @@ size_t SymbolFileNativePDB::ParseSymbolArrayInScope( return count; } -void SymbolFileNativePDB::DumpClangAST(Stream &s) { m_ast->Dump(s); } +void SymbolFileNativePDB::DumpClangAST(Stream &s) { + auto ts_or_err = GetTypeSystemForLanguage(eLanguageTypeC_plus_plus); + if (!ts_or_err) + return; + auto ts = *ts_or_err; + TypeSystemClang *clang = llvm::dyn_cast_or_null<TypeSystemClang>(ts.get()); + if (!clang) + return; + clang->GetNativePDBParser()->Dump(s); +} void SymbolFileNativePDB::FindGlobalVariables( ConstString name, const CompilerDeclContext &parent_decl_ctx, @@ -1563,10 +1668,15 @@ void SymbolFileNativePDB::FindGlobalVariables( } void SymbolFileNativePDB::FindFunctions( - ConstString name, const CompilerDeclContext &parent_decl_ctx, - FunctionNameType name_type_mask, bool include_inlines, + const Module::LookupInfo &lookup_info, + const CompilerDeclContext &parent_decl_ctx, bool include_inlines, SymbolContextList &sc_list) { std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); + ConstString name = lookup_info.GetLookupName(); + FunctionNameType name_type_mask = lookup_info.GetNameTypeMask(); + if (name_type_mask & eFunctionNameTypeFull) + name = lookup_info.GetName(); + // For now we only support lookup by method name or full name. if (!(name_type_mask & eFunctionNameTypeFull || name_type_mask & eFunctionNameTypeMethod)) @@ -1702,12 +1812,20 @@ VariableSP SymbolFileNativePDB::CreateLocalVariable(PdbCompilandSymId scope_id, func_block->GetStartAddress(addr); VariableInfo var_info = GetVariableLocationInfo(*m_index, var_id, *func_block, module); - if (!var_info.location || !var_info.ranges) + Function *func = func_block->CalculateSymbolContextFunction(); + if (!func) return nullptr; - + // Use empty dwarf expr if optimized away so that it won't be filtered out + // when lookuping local variables in this scope. + if (!var_info.location.IsValid()) + var_info.location = DWARFExpressionList(module, DWARFExpression(), nullptr); + var_info.location.SetFuncFileAddress( + func->GetAddressRange().GetBaseAddress().GetFileAddress()); CompilandIndexItem *cii = m_index->compilands().GetCompiland(var_id.modi); CompUnitSP comp_unit_sp = GetOrCreateCompileUnit(*cii); TypeSP type_sp = GetOrCreateType(var_info.type); + if (!type_sp) + return nullptr; std::string name = var_info.name.str(); Declaration decl; SymbolFileTypeSP sftype = @@ -1720,15 +1838,21 @@ VariableSP SymbolFileNativePDB::CreateLocalVariable(PdbCompilandSymId scope_id, bool artificial = false; bool location_is_constant_data = false; bool static_member = false; - DWARFExpressionList locaiton_list = DWARFExpressionList( - module, *var_info.location, nullptr); + Variable::RangeList scope_ranges; VariableSP var_sp = std::make_shared<Variable>( toOpaqueUid(var_id), name.c_str(), name.c_str(), sftype, var_scope, - &block, *var_info.ranges, &decl, locaiton_list, external, artificial, + &block, scope_ranges, &decl, var_info.location, external, artificial, location_is_constant_data, static_member); - if (!is_param) - m_ast->GetOrCreateVariableDecl(scope_id, var_id); + if (!is_param) { + auto ts_or_err = GetTypeSystemForLanguage(comp_unit_sp->GetLanguage()); + if (auto err = ts_or_err.takeError()) + return nullptr; + auto ts = *ts_or_err; + if (!ts) + return nullptr; + ts->GetNativePDBParser()->GetOrCreateVariableDecl(scope_id, var_id); + } m_local_variables[toOpaqueUid(var_id)] = var_sp; return var_sp; } @@ -1750,14 +1874,20 @@ TypeSP SymbolFileNativePDB::CreateTypedef(PdbGlobalSymId id) { TypeSP target_type = GetOrCreateType(udt.Type); - (void)m_ast->GetOrCreateTypedefDecl(id); + auto ts_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); + if (auto err = ts_or_err.takeError()) + return nullptr; + auto ts = *ts_or_err; + if (!ts) + return nullptr; + + ts->GetNativePDBParser()->GetOrCreateTypedefDecl(id); Declaration decl; - return std::make_shared<lldb_private::Type>( - toOpaqueUid(id), this, ConstString(udt.Name), - target_type->GetByteSize(nullptr), nullptr, target_type->GetID(), - lldb_private::Type::eEncodingIsTypedefUID, decl, - target_type->GetForwardCompilerType(), + return MakeType( + toOpaqueUid(id), ConstString(udt.Name), target_type->GetByteSize(nullptr), + nullptr, target_type->GetID(), lldb_private::Type::eEncodingIsTypedefUID, + decl, target_type->GetForwardCompilerType(), lldb_private::Type::ResolveState::Forward); } @@ -1783,9 +1913,24 @@ size_t SymbolFileNativePDB::ParseVariablesForBlock(PdbCompilandSymId block_id) { ProcSym proc(static_cast<SymbolRecordKind>(sym.kind())); cantFail(SymbolDeserializer::deserializeAs<ProcSym>(sym, proc)); CVType signature = m_index->tpi().getType(proc.FunctionType); - ProcedureRecord sig; - cantFail(TypeDeserializer::deserializeAs<ProcedureRecord>(signature, sig)); - params_remaining = sig.getParameterCount(); + if (signature.kind() == LF_PROCEDURE) { + ProcedureRecord sig; + if (llvm::Error e = TypeDeserializer::deserializeAs<ProcedureRecord>( + signature, sig)) { + llvm::consumeError(std::move(e)); + return 0; + } + params_remaining = sig.getParameterCount(); + } else if (signature.kind() == LF_MFUNCTION) { + MemberFunctionRecord sig; + if (llvm::Error e = TypeDeserializer::deserializeAs<MemberFunctionRecord>( + signature, sig)) { + llvm::consumeError(std::move(e)); + return 0; + } + params_remaining = sig.getParameterCount(); + } else + return 0; break; } case S_BLOCK32: @@ -1884,26 +2029,50 @@ size_t SymbolFileNativePDB::ParseVariablesForContext(const SymbolContext &sc) { } CompilerDecl SymbolFileNativePDB::GetDeclForUID(lldb::user_id_t uid) { - if (auto decl = m_ast->GetOrCreateDeclForUid(uid)) - return *decl; - else + auto ts_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); + if (auto err = ts_or_err.takeError()) return CompilerDecl(); + auto ts = *ts_or_err; + if (!ts) + return {}; + + if (auto decl = ts->GetNativePDBParser()->GetOrCreateDeclForUid(uid)) + return *decl; + return CompilerDecl(); } CompilerDeclContext SymbolFileNativePDB::GetDeclContextForUID(lldb::user_id_t uid) { + auto ts_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); + if (auto err = ts_or_err.takeError()) + return {}; + auto ts = *ts_or_err; + if (!ts) + return {}; + + PdbAstBuilder *ast_builder = ts->GetNativePDBParser(); clang::DeclContext *context = - m_ast->GetOrCreateDeclContextForUid(PdbSymUid(uid)); + ast_builder->GetOrCreateDeclContextForUid(PdbSymUid(uid)); if (!context) return {}; - return m_ast->ToCompilerDeclContext(*context); + return ast_builder->ToCompilerDeclContext(*context); } CompilerDeclContext SymbolFileNativePDB::GetDeclContextContainingUID(lldb::user_id_t uid) { - clang::DeclContext *context = m_ast->GetParentDeclContext(PdbSymUid(uid)); - return m_ast->ToCompilerDeclContext(*context); + auto ts_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); + if (auto err = ts_or_err.takeError()) + return CompilerDeclContext(); + auto ts = *ts_or_err; + if (!ts) + return {}; + + PdbAstBuilder *ast_builder = ts->GetNativePDBParser(); + clang::DeclContext *context = ast_builder->GetParentDeclContext(PdbSymUid(uid)); + if (!context) + return CompilerDeclContext(); + return ast_builder->ToCompilerDeclContext(*context); } Type *SymbolFileNativePDB::ResolveTypeUID(lldb::user_id_t type_uid) { @@ -1924,21 +2093,33 @@ Type *SymbolFileNativePDB::ResolveTypeUID(lldb::user_id_t type_uid) { return nullptr; TypeSP type_sp = CreateAndCacheType(type_id); + if (!type_sp) + return nullptr; return &*type_sp; } -llvm::Optional<SymbolFile::ArrayInfo> +std::optional<SymbolFile::ArrayInfo> SymbolFileNativePDB::GetDynamicArrayInfoForUID( lldb::user_id_t type_uid, const lldb_private::ExecutionContext *exe_ctx) { - return llvm::None; + return std::nullopt; } - bool SymbolFileNativePDB::CompleteType(CompilerType &compiler_type) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); + auto ts = compiler_type.GetTypeSystem(); + auto clang_type_system = ts.dyn_cast_or_null<TypeSystemClang>(); + if (!clang_type_system) + return false; + + PdbAstBuilder *ast_builder = + static_cast<PdbAstBuilder *>(clang_type_system->GetNativePDBParser()); + if (ast_builder && + ast_builder->GetClangASTImporter().CanImport(compiler_type)) + return ast_builder->GetClangASTImporter().CompleteType(compiler_type); clang::QualType qt = clang::QualType::getFromOpaquePtr(compiler_type.GetOpaqueQualType()); - return m_ast->CompleteType(qt); + return ast_builder->CompleteType(qt); } void SymbolFileNativePDB::GetTypes(lldb_private::SymbolContextScope *sc_scope, @@ -1951,13 +2132,13 @@ SymbolFileNativePDB::FindNamespace(ConstString name, return {}; } -llvm::Expected<TypeSystem &> +llvm::Expected<lldb::TypeSystemSP> SymbolFileNativePDB::GetTypeSystemForLanguage(lldb::LanguageType language) { auto type_system_or_err = m_objfile_sp->GetModule()->GetTypeSystemForLanguage(language); - if (type_system_or_err) { - type_system_or_err->SetSymbolFile(this); - } + if (type_system_or_err) + if (auto ts = *type_system_or_err) + ts->SetSymbolFile(this); return type_system_or_err; } @@ -1965,3 +2146,176 @@ uint64_t SymbolFileNativePDB::GetDebugInfoSize() { // PDB files are a separate file that contains all debug info. return m_index->pdb().getFileSize(); } + +void SymbolFileNativePDB::BuildParentMap() { + LazyRandomTypeCollection &types = m_index->tpi().typeCollection(); + + llvm::DenseMap<TypeIndex, TypeIndex> forward_to_full; + llvm::DenseMap<TypeIndex, TypeIndex> full_to_forward; + + struct RecordIndices { + TypeIndex forward; + TypeIndex full; + }; + + llvm::StringMap<RecordIndices> record_indices; + + for (auto ti = types.getFirst(); ti; ti = types.getNext(*ti)) { + CVType type = types.getType(*ti); + if (!IsTagRecord(type)) + continue; + + CVTagRecord tag = CVTagRecord::create(type); + + RecordIndices &indices = record_indices[tag.asTag().getUniqueName()]; + if (tag.asTag().isForwardRef()) + indices.forward = *ti; + else + indices.full = *ti; + + if (indices.full != TypeIndex::None() && + indices.forward != TypeIndex::None()) { + forward_to_full[indices.forward] = indices.full; + full_to_forward[indices.full] = indices.forward; + } + + // We're looking for LF_NESTTYPE records in the field list, so ignore + // forward references (no field list), and anything without a nested class + // (since there won't be any LF_NESTTYPE records). + if (tag.asTag().isForwardRef() || !tag.asTag().containsNestedClass()) + continue; + + struct ProcessTpiStream : public TypeVisitorCallbacks { + ProcessTpiStream(PdbIndex &index, TypeIndex parent, + const CVTagRecord &parent_cvt, + llvm::DenseMap<TypeIndex, TypeIndex> &parents) + : index(index), parents(parents), parent(parent), + parent_cvt(parent_cvt) {} + + PdbIndex &index; + llvm::DenseMap<TypeIndex, TypeIndex> &parents; + + unsigned unnamed_type_index = 1; + TypeIndex parent; + const CVTagRecord &parent_cvt; + + llvm::Error visitKnownMember(CVMemberRecord &CVR, + NestedTypeRecord &Record) override { + std::string unnamed_type_name; + if (Record.Name.empty()) { + unnamed_type_name = + llvm::formatv("<unnamed-type-$S{0}>", unnamed_type_index).str(); + Record.Name = unnamed_type_name; + ++unnamed_type_index; + } + std::optional<CVTagRecord> tag = + GetNestedTagDefinition(Record, parent_cvt, index.tpi()); + if (!tag) + return llvm::ErrorSuccess(); + + parents[Record.Type] = parent; + return llvm::ErrorSuccess(); + } + }; + + CVType field_list_cvt = m_index->tpi().getType(tag.asTag().FieldList); + ProcessTpiStream process(*m_index, *ti, tag, m_parent_types); + FieldListRecord field_list; + if (llvm::Error error = TypeDeserializer::deserializeAs<FieldListRecord>( + field_list_cvt, field_list)) + llvm::consumeError(std::move(error)); + if (llvm::Error error = visitMemberRecordStream(field_list.Data, process)) + llvm::consumeError(std::move(error)); + } + + // Now that we know the forward -> full mapping of all type indices, we can + // re-write all the indices. At the end of this process, we want a mapping + // consisting of fwd -> full and full -> full for all child -> parent indices. + // We can re-write the values in place, but for the keys, we must save them + // off so that we don't modify the map in place while also iterating it. + std::vector<TypeIndex> full_keys; + std::vector<TypeIndex> fwd_keys; + for (auto &entry : m_parent_types) { + TypeIndex key = entry.first; + TypeIndex value = entry.second; + + auto iter = forward_to_full.find(value); + if (iter != forward_to_full.end()) + entry.second = iter->second; + + iter = forward_to_full.find(key); + if (iter != forward_to_full.end()) + fwd_keys.push_back(key); + else + full_keys.push_back(key); + } + for (TypeIndex fwd : fwd_keys) { + TypeIndex full = forward_to_full[fwd]; + m_parent_types[full] = m_parent_types[fwd]; + } + for (TypeIndex full : full_keys) { + TypeIndex fwd = full_to_forward[full]; + m_parent_types[fwd] = m_parent_types[full]; + } +} + +std::optional<PdbCompilandSymId> +SymbolFileNativePDB::FindSymbolScope(PdbCompilandSymId id) { + CVSymbol sym = m_index->ReadSymbolRecord(id); + if (symbolOpensScope(sym.kind())) { + // If this exact symbol opens a scope, we can just directly access its + // parent. + id.offset = getScopeParentOffset(sym); + // Global symbols have parent offset of 0. Return std::nullopt to indicate + // this. + if (id.offset == 0) + return std::nullopt; + return id; + } + + // Otherwise we need to start at the beginning and iterate forward until we + // reach (or pass) this particular symbol + CompilandIndexItem &cii = m_index->compilands().GetOrCreateCompiland(id.modi); + const CVSymbolArray &syms = cii.m_debug_stream.getSymbolArray(); + + auto begin = syms.begin(); + auto end = syms.at(id.offset); + std::vector<PdbCompilandSymId> scope_stack; + + while (begin != end) { + if (begin.offset() > id.offset) { + // We passed it. We couldn't even find this symbol record. + lldbassert(false && "Invalid compiland symbol id!"); + return std::nullopt; + } + + // We haven't found the symbol yet. Check if we need to open or close the + // scope stack. + if (symbolOpensScope(begin->kind())) { + // We can use the end offset of the scope to determine whether or not + // we can just outright skip this entire scope. + uint32_t scope_end = getScopeEndOffset(*begin); + if (scope_end < id.offset) { + begin = syms.at(scope_end); + } else { + // The symbol we're looking for is somewhere in this scope. + scope_stack.emplace_back(id.modi, begin.offset()); + } + } else if (symbolEndsScope(begin->kind())) { + scope_stack.pop_back(); + } + ++begin; + } + if (scope_stack.empty()) + return std::nullopt; + // We have a match! Return the top of the stack + return scope_stack.back(); +} + +std::optional<llvm::codeview::TypeIndex> +SymbolFileNativePDB::GetParentType(llvm::codeview::TypeIndex ti) { + auto parent_iter = m_parent_types.find(ti); + if (parent_iter == m_parent_types.end()) + return std::nullopt; + return parent_iter->second; +} diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h index 187791b0fd01..90cd5251679e 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h @@ -19,6 +19,8 @@ #include "CompileUnitIndex.h" #include "PdbIndex.h" +#include "PdbAstBuilder.h" +#include <optional> namespace clang { class TagDecl; @@ -37,7 +39,6 @@ struct UnionRecord; namespace lldb_private { namespace npdb { -class PdbAstBuilder; class SymbolFileNativePDB : public SymbolFileCommon { friend class UdtRecordCompleter; @@ -115,7 +116,7 @@ public: CompilerDeclContext GetDeclContextForUID(lldb::user_id_t uid) override; CompilerDeclContext GetDeclContextContainingUID(lldb::user_id_t uid) override; Type *ResolveTypeUID(lldb::user_id_t type_uid) override; - llvm::Optional<ArrayInfo> GetDynamicArrayInfoForUID( + std::optional<ArrayInfo> GetDynamicArrayInfoForUID( lldb::user_id_t type_uid, const lldb_private::ExecutionContext *exe_ctx) override; @@ -130,14 +131,15 @@ public: void GetTypes(SymbolContextScope *sc_scope, lldb::TypeClass type_mask, TypeList &type_list) override; - void FindFunctions(ConstString name, + void FindFunctions(const Module::LookupInfo &lookup_info, const CompilerDeclContext &parent_decl_ctx, - lldb::FunctionNameType name_type_mask, bool include_inlines, SymbolContextList &sc_list) override; void FindFunctions(const RegularExpression ®ex, bool include_inlines, SymbolContextList &sc_list) override; + std::optional<PdbCompilandSymId> FindSymbolScope(PdbCompilandSymId id); + void FindTypes(ConstString name, const CompilerDeclContext &parent_decl_ctx, uint32_t max_matches, llvm::DenseSet<SymbolFile *> &searched_symbol_files, @@ -147,7 +149,7 @@ public: llvm::DenseSet<SymbolFile *> &searched_symbol_files, TypeMap &types) override; - llvm::Expected<TypeSystem &> + llvm::Expected<lldb::TypeSystemSP> GetTypeSystemForLanguage(lldb::LanguageType language) override; CompilerDeclContext @@ -159,8 +161,13 @@ public: llvm::pdb::PDBFile &GetPDBFile() { return m_index->pdb(); } const llvm::pdb::PDBFile &GetPDBFile() const { return m_index->pdb(); } + PdbIndex &GetIndex() { return *m_index; }; + void DumpClangAST(Stream &s) override; + std::optional<llvm::codeview::TypeIndex> + GetParentType(llvm::codeview::TypeIndex ti); + private: struct LineTableEntryComparator { bool operator()(const lldb_private::LineTable::Entry &lhs, @@ -181,6 +188,8 @@ private: InlineSite(PdbCompilandSymId parent_id) : parent_id(parent_id){}; }; + void BuildParentMap(); + uint32_t CalculateNumCompileUnits() override; lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index) override; @@ -259,12 +268,13 @@ private: lldb::addr_t m_obj_load_address = 0; bool m_done_full_type_scan = false; + // UID for anonymous union and anonymous struct as they don't have entities in + // pdb debug info. + lldb::user_id_t anonymous_id = LLDB_INVALID_UID - 1; std::unique_ptr<llvm::pdb::PDBFile> m_file_up; std::unique_ptr<PdbIndex> m_index; - std::unique_ptr<PdbAstBuilder> m_ast; - llvm::DenseMap<lldb::user_id_t, lldb::VariableSP> m_global_vars; llvm::DenseMap<lldb::user_id_t, lldb::VariableSP> m_local_variables; llvm::DenseMap<lldb::user_id_t, lldb::BlockSP> m_blocks; @@ -272,6 +282,8 @@ private: llvm::DenseMap<lldb::user_id_t, lldb::CompUnitSP> m_compilands; llvm::DenseMap<lldb::user_id_t, lldb::TypeSP> m_types; llvm::DenseMap<lldb::user_id_t, std::shared_ptr<InlineSite>> m_inline_sites; + llvm::DenseMap<llvm::codeview::TypeIndex, llvm::codeview::TypeIndex> + m_parent_types; }; } // namespace npdb diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp index c0308196c760..cf3868d077c3 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp @@ -6,20 +6,25 @@ #include "PdbUtil.h" #include "Plugins/ExpressionParser/Clang/ClangASTImporter.h" +#include "Plugins/ExpressionParser/Clang/ClangASTMetadata.h" #include "Plugins/ExpressionParser/Clang/ClangUtil.h" #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" +#include "SymbolFileNativePDB.h" +#include "lldb/Core/Address.h" #include "lldb/Symbol/Type.h" #include "lldb/Utility/LLDBAssert.h" #include "lldb/Utility/LLDBLog.h" #include "lldb/lldb-enumerations.h" #include "lldb/lldb-forward.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h" #include "llvm/DebugInfo/CodeView/TypeDeserializer.h" #include "llvm/DebugInfo/CodeView/TypeIndex.h" #include "llvm/DebugInfo/PDB/Native/GlobalsStream.h" #include "llvm/DebugInfo/PDB/Native/TpiStream.h" #include "llvm/DebugInfo/PDB/PDBTypes.h" +#include <optional> using namespace llvm::codeview; using namespace llvm::pdb; @@ -32,12 +37,13 @@ using Error = llvm::Error; UdtRecordCompleter::UdtRecordCompleter( PdbTypeSymId id, CompilerType &derived_ct, clang::TagDecl &tag_decl, PdbAstBuilder &ast_builder, PdbIndex &index, + llvm::DenseMap<clang::Decl *, DeclStatus> &decl_to_status, llvm::DenseMap<lldb::opaque_compiler_type_t, llvm::SmallSet<std::pair<llvm::StringRef, CompilerType>, 8>> &cxx_record_map) : m_id(id), m_derived_ct(derived_ct), m_tag_decl(tag_decl), m_ast_builder(ast_builder), m_index(index), - m_cxx_record_map(cxx_record_map) { + m_decl_to_status(decl_to_status), m_cxx_record_map(cxx_record_map) { CVType cvt = m_index.tpi().getType(m_id.index); switch (cvt.kind()) { case LF_ENUM: @@ -45,10 +51,14 @@ UdtRecordCompleter::UdtRecordCompleter( break; case LF_UNION: llvm::cantFail(TypeDeserializer::deserializeAs<UnionRecord>(cvt, m_cvr.ur)); + m_layout.bit_size = m_cvr.ur.getSize() * 8; + m_record.record.kind = Member::Union; break; case LF_CLASS: case LF_STRUCTURE: llvm::cantFail(TypeDeserializer::deserializeAs<ClassRecord>(cvt, m_cvr.cr)); + m_layout.bit_size = m_cvr.cr.getSize() * 8; + m_record.record.kind = Member::Struct; break; default: llvm_unreachable("unreachable!"); @@ -57,7 +67,7 @@ UdtRecordCompleter::UdtRecordCompleter( clang::QualType UdtRecordCompleter::AddBaseClassForTypeIndex( llvm::codeview::TypeIndex ti, llvm::codeview::MemberAccess access, - llvm::Optional<uint64_t> vtable_idx) { + std::optional<uint64_t> vtable_idx) { PdbTypeSymId type_id(ti); clang::QualType qt = m_ast_builder.GetOrCreateType(type_id); @@ -83,9 +93,10 @@ void UdtRecordCompleter::AddMethod(llvm::StringRef name, TypeIndex type_idx, m_ast_builder.GetOrCreateType(PdbTypeSymId(type_idx)); if (method_qt.isNull()) return; - m_ast_builder.CompleteType(method_qt); CompilerType method_ct = m_ast_builder.ToCompilerType(method_qt); - lldb::opaque_compiler_type_t derived_opaque_ty = m_derived_ct.GetOpaqueQualType(); + TypeSystemClang::RequireCompleteType(method_ct); + lldb::opaque_compiler_type_t derived_opaque_ty = + m_derived_ct.GetOpaqueQualType(); auto iter = m_cxx_record_map.find(derived_opaque_ty); if (iter != m_cxx_record_map.end()) { if (iter->getSecond().contains({name, method_ct})) { @@ -244,18 +255,14 @@ Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr, clang::QualType member_qt = m_ast_builder.GetOrCreateType(PdbTypeSymId(ti)); if (member_qt.isNull()) return Error::success(); - m_ast_builder.CompleteType(member_qt); - + TypeSystemClang::RequireCompleteType(m_ast_builder.ToCompilerType(member_qt)); lldb::AccessType access = TranslateMemberAccess(data_member.getAccess()); - - clang::FieldDecl *decl = TypeSystemClang::AddFieldToRecordType( - m_derived_ct, data_member.Name, m_ast_builder.ToCompilerType(member_qt), - access, bitfield_width); - // FIXME: Add a PdbSymUid namespace for field list members and update - // the m_uid_to_decl map with this decl. - - m_layout.field_offsets.insert(std::make_pair(decl, offset)); - + size_t field_size = + bitfield_width ? bitfield_width : GetSizeOfType(ti, m_index.tpi()) * 8; + if (field_size == 0) + return Error::success(); + m_record.CollectMember(data_member.Name, offset, field_size, member_qt, access, + bitfield_width); return Error::success(); } @@ -305,13 +312,187 @@ void UdtRecordCompleter::complete() { bases.push_back(std::move(ib.second)); TypeSystemClang &clang = m_ast_builder.clang(); + // Make sure all base classes refer to complete types and not forward + // declarations. If we don't do this, clang will crash with an + // assertion in the call to clang_type.TransferBaseClasses() + for (const auto &base_class : bases) { + clang::TypeSourceInfo *type_source_info = + base_class->getTypeSourceInfo(); + if (type_source_info) { + TypeSystemClang::RequireCompleteType( + clang.GetType(type_source_info->getType())); + } + } + clang.TransferBaseClasses(m_derived_ct.GetOpaqueQualType(), std::move(bases)); clang.AddMethodOverridesForCXXRecordType(m_derived_ct.GetOpaqueQualType()); + FinishRecord(); TypeSystemClang::BuildIndirectFields(m_derived_ct); TypeSystemClang::CompleteTagDeclarationDefinition(m_derived_ct); if (auto *record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(&m_tag_decl)) { - m_ast_builder.importer().SetRecordLayout(record_decl, m_layout); + m_ast_builder.GetClangASTImporter().SetRecordLayout(record_decl, m_layout); + } +} + +uint64_t +UdtRecordCompleter::AddMember(TypeSystemClang &clang, Member *field, + uint64_t bit_offset, CompilerType parent_ct, + ClangASTImporter::LayoutInfo &parent_layout, + clang::DeclContext *parent_decl_ctx) { + SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>( + clang.GetSymbolFile()->GetBackingSymbolFile()); + clang::FieldDecl *field_decl = nullptr; + uint64_t bit_size = 0; + switch (field->kind) { + case Member::Field: { + field_decl = TypeSystemClang::AddFieldToRecordType( + parent_ct, field->name, m_ast_builder.ToCompilerType(field->qt), + field->access, field->bitfield_width); + bit_size = field->bit_size; + break; + }; + case Member::Struct: + case Member::Union: { + clang::TagTypeKind kind = field->kind == Member::Struct + ? clang::TagTypeKind::TTK_Struct + : clang::TagTypeKind::TTK_Union; + ClangASTMetadata metadata; + metadata.SetUserID(pdb->anonymous_id); + metadata.SetIsDynamicCXXType(false); + CompilerType record_ct = clang.CreateRecordType( + parent_decl_ctx, OptionalClangModuleID(), lldb::eAccessPublic, "", kind, + lldb::eLanguageTypeC_plus_plus, &metadata); + TypeSystemClang::StartTagDeclarationDefinition(record_ct); + ClangASTImporter::LayoutInfo layout; + clang::DeclContext *decl_ctx = clang.GetDeclContextForType(record_ct); + for (const auto &member : field->fields) { + uint64_t member_offset = field->kind == Member::Struct + ? member->bit_offset - field->base_offset + : 0; + uint64_t member_bit_size = AddMember(clang, member.get(), member_offset, + record_ct, layout, decl_ctx); + if (field->kind == Member::Struct) + bit_size = std::max(bit_size, member_offset + member_bit_size); + else + bit_size = std::max(bit_size, member_bit_size); + } + layout.bit_size = bit_size; + TypeSystemClang::CompleteTagDeclarationDefinition(record_ct); + clang::RecordDecl *record_decl = clang.GetAsRecordDecl(record_ct); + m_ast_builder.GetClangASTImporter().SetRecordLayout(record_decl, layout); + field_decl = TypeSystemClang::AddFieldToRecordType( + parent_ct, "", record_ct, lldb::eAccessPublic, 0); + // Mark this record decl as completed. + DeclStatus status; + status.resolved = true; + status.uid = pdb->anonymous_id--; + m_decl_to_status.insert({record_decl, status}); + break; + }; + } + // FIXME: Add a PdbSymUid namespace for field list members and update + // the m_uid_to_decl map with this decl. + parent_layout.field_offsets.insert({field_decl, bit_offset}); + return bit_size; +} + +void UdtRecordCompleter::FinishRecord() { + TypeSystemClang &clang = m_ast_builder.clang(); + clang::DeclContext *decl_ctx = + m_ast_builder.GetOrCreateDeclContextForUid(m_id); + m_record.ConstructRecord(); + // Maybe we should check the construsted record size with the size in pdb. If + // they mismatch, it might be pdb has fields info missing. + for (const auto &field : m_record.record.fields) { + AddMember(clang, field.get(), field->bit_offset, m_derived_ct, m_layout, + decl_ctx); + } +} + +void UdtRecordCompleter::Record::CollectMember( + llvm::StringRef name, uint64_t offset, uint64_t field_size, + clang::QualType qt, lldb::AccessType access, uint64_t bitfield_width) { + fields_map[offset].push_back(std::make_unique<Member>( + name, offset, field_size, qt, access, bitfield_width)); + if (start_offset > offset) + start_offset = offset; +} + +void UdtRecordCompleter::Record::ConstructRecord() { + // For anonymous unions in a struct, msvc generated pdb doesn't have the + // entity for that union. So, we need to construct anonymous union and struct + // based on field offsets. The final AST is likely not matching the exact + // original AST, but the memory layout is preseved. + // After we collecting all fields in visitKnownMember, we have all fields in + // increasing offset order in m_fields. Since we are iterating in increase + // offset order, if the current offset is equal to m_start_offset, we insert + // it as direct field of top level record. If the current offset is greater + // than m_start_offset, we should be able to find a field in end_offset_map + // whose end offset is less than or equal to current offset. (if not, it might + // be missing field info. We will ignore the field in this case. e.g. Field A + // starts at 0 with size 4 bytes, and Field B starts at 2 with size 4 bytes. + // Normally, there must be something which ends at/before 2.) Then we will + // append current field to the end of parent record. If parent is struct, we + // can just grow it. If parent is a field, it's a field inside an union. We + // convert it into an anonymous struct containing old field and new field. + + // The end offset to a vector of field/struct that ends at the offset. + std::map<uint64_t, std::vector<Member *>> end_offset_map; + for (auto &pair : fields_map) { + uint64_t offset = pair.first; + auto &fields = pair.second; + lldbassert(offset >= start_offset); + Member *parent = &record; + if (offset > start_offset) { + // Find the field with largest end offset that is <= offset. If it's less + // than offset, it indicates there are padding bytes between end offset + // and offset. + lldbassert(!end_offset_map.empty()); + auto iter = end_offset_map.lower_bound(offset); + if (iter == end_offset_map.end()) + --iter; + else if (iter->first > offset) { + if (iter == end_offset_map.begin()) + continue; + --iter; + } + if (iter->second.empty()) + continue; + parent = iter->second.back(); + iter->second.pop_back(); + } + // If it's a field, then the field is inside a union, so we can safely + // increase its size by converting it to a struct to hold multiple fields. + if (parent->kind == Member::Field) + parent->ConvertToStruct(); + + if (fields.size() == 1) { + uint64_t end_offset = offset + fields.back()->bit_size; + parent->fields.push_back(std::move(fields.back())); + if (parent->kind == Member::Struct) { + end_offset_map[end_offset].push_back(parent); + } else { + lldbassert(parent == &record && + "If parent is union, it must be the top level record."); + end_offset_map[end_offset].push_back(parent->fields.back().get()); + } + } else { + if (parent->kind == Member::Struct) { + parent->fields.push_back(std::make_unique<Member>(Member::Union)); + parent = parent->fields.back().get(); + parent->bit_offset = offset; + } else { + lldbassert(parent == &record && + "If parent is union, it must be the top level record."); + } + for (auto &field : fields) { + int64_t bit_size = field->bit_size; + parent->fields.push_back(std::move(field)); + end_offset_map[offset + bit_size].push_back( + parent->fields.back().get()); + } + } } } diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.h index 9c6b5ed28bc2..e6e91d0f2c3e 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.h @@ -9,12 +9,13 @@ #ifndef LLDB_SOURCE_PLUGINS_SYMBOLFILE_NATIVEPDB_UDTRECORDCOMPLETER_H #define LLDB_SOURCE_PLUGINS_SYMBOLFILE_NATIVEPDB_UDTRECORDCOMPLETER_H +#include "PdbAstBuilder.h" +#include "PdbSymUid.h" #include "Plugins/ExpressionParser/Clang/ClangASTImporter.h" #include "llvm/DebugInfo/CodeView/CVRecord.h" #include "llvm/DebugInfo/CodeView/TypeRecord.h" #include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h" - -#include "PdbSymUid.h" +#include <optional> namespace clang { class CXXBaseSpecifier; @@ -54,6 +55,7 @@ class UdtRecordCompleter : public llvm::codeview::TypeVisitorCallbacks { PdbIndex &m_index; std::vector<IndexedBase> m_bases; ClangASTImporter::LayoutInfo m_layout; + llvm::DenseMap<clang::Decl *, DeclStatus> &m_decl_to_status; llvm::DenseMap<lldb::opaque_compiler_type_t, llvm::SmallSet<std::pair<llvm::StringRef, CompilerType>, 8>> &m_cxx_record_map; @@ -62,6 +64,7 @@ public: UdtRecordCompleter( PdbTypeSymId id, CompilerType &derived_ct, clang::TagDecl &tag_decl, PdbAstBuilder &ast_builder, PdbIndex &index, + llvm::DenseMap<clang::Decl *, DeclStatus> &decl_to_status, llvm::DenseMap<lldb::opaque_compiler_type_t, llvm::SmallSet<std::pair<llvm::StringRef, CompilerType>, 8>> &cxx_record_map); @@ -72,16 +75,69 @@ public: #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) #include "llvm/DebugInfo/CodeView/CodeViewTypes.def" + struct Member; + using MemberUP = std::unique_ptr<Member>; + + struct Member { + enum Kind { Field, Struct, Union } kind; + // Following are only used for field. + llvm::StringRef name; + uint64_t bit_offset; + uint64_t bit_size; + clang::QualType qt; + lldb::AccessType access; + uint32_t bitfield_width; + // Following are Only used for struct or union. + uint64_t base_offset; + llvm::SmallVector<MemberUP, 1> fields; + + Member() = default; + Member(Kind kind) + : kind(kind), name(), bit_offset(0), bit_size(0), qt(), + access(lldb::eAccessPublic), bitfield_width(0), base_offset(0) {} + Member(llvm::StringRef name, uint64_t bit_offset, uint64_t bit_size, + clang::QualType qt, lldb::AccessType access, uint32_t bitfield_width) + : kind(Field), name(name), bit_offset(bit_offset), bit_size(bit_size), + qt(qt), access(access), bitfield_width(bitfield_width), + base_offset(0) {} + void ConvertToStruct() { + kind = Struct; + base_offset = bit_offset; + fields.push_back(std::make_unique<Member>(name, bit_offset, bit_size, qt, + access, bitfield_width)); + name = llvm::StringRef(); + qt = clang::QualType(); + access = lldb::eAccessPublic; + bit_offset = bit_size = bitfield_width = 0; + } + }; + + struct Record { + // Top level record. + Member record; + uint64_t start_offset = UINT64_MAX; + std::map<uint64_t, llvm::SmallVector<MemberUP, 1>> fields_map; + void CollectMember(llvm::StringRef name, uint64_t offset, + uint64_t field_size, clang::QualType qt, + lldb::AccessType access, uint64_t bitfield_width); + void ConstructRecord(); + }; void complete(); private: + Record m_record; clang::QualType AddBaseClassForTypeIndex( llvm::codeview::TypeIndex ti, llvm::codeview::MemberAccess access, - llvm::Optional<uint64_t> vtable_idx = llvm::Optional<uint64_t>()); + std::optional<uint64_t> vtable_idx = std::optional<uint64_t>()); void AddMethod(llvm::StringRef name, llvm::codeview::TypeIndex type_idx, llvm::codeview::MemberAccess access, llvm::codeview::MethodOptions options, llvm::codeview::MemberAttributes attrs); + void FinishRecord(); + uint64_t AddMember(TypeSystemClang &clang, Member *field, uint64_t bit_offset, + CompilerType parent_ct, + ClangASTImporter::LayoutInfo &parent_layout, + clang::DeclContext *decl_ctx); }; } // namespace npdb diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp index c3f424d06c54..c9236da4842c 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp @@ -40,6 +40,7 @@ #include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h" #include "Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h" +#include <optional> using namespace lldb; using namespace lldb_private; @@ -120,24 +121,31 @@ GetBuiltinTypeForPDBEncodingAndBitSize(TypeSystemClang &clang_ast, return clang_ast.GetBasicType(eBasicTypeBool); case PDB_BuiltinType::Long: if (width == ast.getTypeSize(ast.LongTy)) - return CompilerType(&clang_ast, ast.LongTy.getAsOpaquePtr()); + return CompilerType(clang_ast.weak_from_this(), + ast.LongTy.getAsOpaquePtr()); if (width == ast.getTypeSize(ast.LongLongTy)) - return CompilerType(&clang_ast, ast.LongLongTy.getAsOpaquePtr()); + return CompilerType(clang_ast.weak_from_this(), + ast.LongLongTy.getAsOpaquePtr()); break; case PDB_BuiltinType::ULong: if (width == ast.getTypeSize(ast.UnsignedLongTy)) - return CompilerType(&clang_ast, ast.UnsignedLongTy.getAsOpaquePtr()); + return CompilerType(clang_ast.weak_from_this(), + ast.UnsignedLongTy.getAsOpaquePtr()); if (width == ast.getTypeSize(ast.UnsignedLongLongTy)) - return CompilerType(&clang_ast, ast.UnsignedLongLongTy.getAsOpaquePtr()); + return CompilerType(clang_ast.weak_from_this(), + ast.UnsignedLongLongTy.getAsOpaquePtr()); break; case PDB_BuiltinType::WCharT: if (width == ast.getTypeSize(ast.WCharTy)) - return CompilerType(&clang_ast, ast.WCharTy.getAsOpaquePtr()); + return CompilerType(clang_ast.weak_from_this(), + ast.WCharTy.getAsOpaquePtr()); break; case PDB_BuiltinType::Char16: - return CompilerType(&clang_ast, ast.Char16Ty.getAsOpaquePtr()); + return CompilerType(clang_ast.weak_from_this(), + ast.Char16Ty.getAsOpaquePtr()); case PDB_BuiltinType::Char32: - return CompilerType(&clang_ast, ast.Char32Ty.getAsOpaquePtr()); + return CompilerType(clang_ast.weak_from_this(), + ast.Char32Ty.getAsOpaquePtr()); case PDB_BuiltinType::Float: // Note: types `long double` and `double` have same bit size in MSVC and // there is no information in the PDB to distinguish them. So when falling @@ -457,10 +465,9 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) { clang_type = clang_type.AddVolatileModifier(); GetDeclarationForSymbol(type, decl); - return std::make_shared<lldb_private::Type>( - type.getSymIndexId(), m_ast.GetSymbolFile(), ConstString(name), - udt->getLength(), nullptr, LLDB_INVALID_UID, - lldb_private::Type::eEncodingIsUID, decl, clang_type, + return m_ast.GetSymbolFile()->MakeType( + type.getSymIndexId(), ConstString(name), udt->getLength(), nullptr, + LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl, clang_type, type_resolve_state); } break; case PDB_SymType::Enum: { @@ -527,10 +534,10 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) { ast_enum = ast_enum.AddVolatileModifier(); GetDeclarationForSymbol(type, decl); - return std::make_shared<lldb_private::Type>( - type.getSymIndexId(), m_ast.GetSymbolFile(), ConstString(name), bytes, - nullptr, LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl, - ast_enum, lldb_private::Type::ResolveState::Full); + return m_ast.GetSymbolFile()->MakeType( + type.getSymIndexId(), ConstString(name), bytes, nullptr, + LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl, ast_enum, + lldb_private::Type::ResolveState::Full); } break; case PDB_SymType::Typedef: { auto type_def = llvm::dyn_cast<PDBSymbolTypeTypedef>(&type); @@ -573,14 +580,13 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) { ast_typedef = ast_typedef.AddVolatileModifier(); GetDeclarationForSymbol(type, decl); - llvm::Optional<uint64_t> size; + std::optional<uint64_t> size; if (type_def->getLength()) size = type_def->getLength(); - return std::make_shared<lldb_private::Type>( - type_def->getSymIndexId(), m_ast.GetSymbolFile(), ConstString(name), - size, nullptr, target_type->GetID(), - lldb_private::Type::eEncodingIsTypedefUID, decl, ast_typedef, - lldb_private::Type::ResolveState::Full); + return m_ast.GetSymbolFile()->MakeType( + type_def->getSymIndexId(), ConstString(name), size, nullptr, + target_type->GetID(), lldb_private::Type::eEncodingIsTypedefUID, decl, + ast_typedef, lldb_private::Type::ResolveState::Full); } break; case PDB_SymType::Function: case PDB_SymType::FunctionSig: { @@ -654,18 +660,17 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) { arg_list.size(), is_variadic, type_quals, cc); GetDeclarationForSymbol(type, decl); - return std::make_shared<lldb_private::Type>( - type.getSymIndexId(), m_ast.GetSymbolFile(), ConstString(name), - llvm::None, nullptr, LLDB_INVALID_UID, - lldb_private::Type::eEncodingIsUID, decl, func_sig_ast_type, - lldb_private::Type::ResolveState::Full); + return m_ast.GetSymbolFile()->MakeType( + type.getSymIndexId(), ConstString(name), std::nullopt, nullptr, + LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl, + func_sig_ast_type, lldb_private::Type::ResolveState::Full); } break; case PDB_SymType::ArrayType: { auto array_type = llvm::dyn_cast<PDBSymbolTypeArray>(&type); assert(array_type); uint32_t num_elements = array_type->getCount(); uint32_t element_uid = array_type->getElementTypeId(); - llvm::Optional<uint64_t> bytes; + std::optional<uint64_t> bytes; if (uint64_t size = array_type->getLength()) bytes = size; @@ -686,16 +691,16 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) { if (TypeSystemClang::StartTagDeclarationDefinition(element_ast_type)) { TypeSystemClang::CompleteTagDeclarationDefinition(element_ast_type); } else { - // We are not able to start defintion. + // We are not able to start definition. return nullptr; } } CompilerType array_ast_type = m_ast.CreateArrayType( element_ast_type, num_elements, /*is_gnu_vector*/ false); - TypeSP type_sp = std::make_shared<lldb_private::Type>( - array_type->getSymIndexId(), m_ast.GetSymbolFile(), ConstString(), - bytes, nullptr, LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, - decl, array_ast_type, lldb_private::Type::ResolveState::Full); + TypeSP type_sp = m_ast.GetSymbolFile()->MakeType( + array_type->getSymIndexId(), ConstString(), bytes, nullptr, + LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl, + array_ast_type, lldb_private::Type::ResolveState::Full); type_sp->SetEncodingType(element_type); return type_sp; } break; @@ -706,7 +711,7 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) { if (builtin_kind == PDB_BuiltinType::None) return nullptr; - llvm::Optional<uint64_t> bytes; + std::optional<uint64_t> bytes; if (uint64_t size = builtin_type->getLength()) bytes = size; Encoding encoding = TranslateBuiltinEncoding(builtin_kind); @@ -721,9 +726,9 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) { auto type_name = GetPDBBuiltinTypeName(*builtin_type, builtin_ast_type); - return std::make_shared<lldb_private::Type>( - builtin_type->getSymIndexId(), m_ast.GetSymbolFile(), type_name, bytes, - nullptr, LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl, + return m_ast.GetSymbolFile()->MakeType( + builtin_type->getSymIndexId(), type_name, bytes, nullptr, + LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl, builtin_ast_type, lldb_private::Type::ResolveState::Full); } break; case PDB_SymType::PointerType: { @@ -751,8 +756,8 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) { pointee_type->GetForwardCompilerType()); assert(pointer_ast_type); - return std::make_shared<lldb_private::Type>( - pointer_type->getSymIndexId(), m_ast.GetSymbolFile(), ConstString(), + return m_ast.GetSymbolFile()->MakeType( + pointer_type->getSymIndexId(), ConstString(), pointer_type->getLength(), nullptr, LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl, pointer_ast_type, lldb_private::Type::ResolveState::Forward); @@ -776,11 +781,10 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) { if (pointer_type->isRestrictedType()) pointer_ast_type = pointer_ast_type.AddRestrictModifier(); - return std::make_shared<lldb_private::Type>( - pointer_type->getSymIndexId(), m_ast.GetSymbolFile(), ConstString(), - pointer_type->getLength(), nullptr, LLDB_INVALID_UID, - lldb_private::Type::eEncodingIsUID, decl, pointer_ast_type, - lldb_private::Type::ResolveState::Full); + return m_ast.GetSymbolFile()->MakeType( + pointer_type->getSymIndexId(), ConstString(), pointer_type->getLength(), + nullptr, LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl, + pointer_ast_type, lldb_private::Type::ResolveState::Full); } break; default: break; @@ -1253,7 +1257,7 @@ void PDBASTParser::AddRecordMembers( auto member_comp_type = member_type->GetLayoutCompilerType(); if (!member_comp_type.GetCompleteType()) { symbol_file.GetObjectFile()->GetModule()->ReportError( - ":: Class '%s' has a member '%s' of type '%s' " + ":: Class '{0}' has a member '{1}' of type '{2}' " "which does not have a complete definition.", record_type.GetTypeName().GetCString(), member_name.c_str(), member_comp_type.GetTypeName().GetCString()); @@ -1363,7 +1367,7 @@ void PDBASTParser::AddRecordBases( auto base_comp_type = base_type->GetFullCompilerType(); if (!base_comp_type.GetCompleteType()) { symbol_file.GetObjectFile()->GetModule()->ReportError( - ":: Class '%s' has a base class '%s' " + ":: Class '{0}' has a base class '{1}' " "which does not have a complete definition.", record_type.GetTypeName().GetCString(), base_comp_type.GetTypeName().GetCString()); @@ -1422,7 +1426,7 @@ PDBASTParser::AddRecordMethod(lldb_private::SymbolFile &symbol_file, CompilerType method_comp_type = method_type->GetFullCompilerType(); if (!method_comp_type.GetCompleteType()) { symbol_file.GetObjectFile()->GetModule()->ReportError( - ":: Class '%s' has a method '%s' whose type cannot be completed.", + ":: Class '{0}' has a method '{1}' whose type cannot be completed.", record_type.GetTypeName().GetCString(), method_comp_type.GetTypeName().GetCString()); if (TypeSystemClang::StartTagDeclarationDefinition(method_comp_type)) diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp index baa48532864b..cb75dd59d366 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp @@ -58,6 +58,7 @@ #if defined(_WIN32) #include "llvm/Config/llvm-config.h" +#include <optional> #endif using namespace lldb; @@ -318,8 +319,9 @@ SymbolFilePDB::ParseCompileUnitFunctionForPDBFunc(const PDBSymbolFunc &pdb_func, return nullptr; } + auto ts = *type_system_or_err; TypeSystemClang *clang_type_system = - llvm::dyn_cast_or_null<TypeSystemClang>(&type_system_or_err.get()); + llvm::dyn_cast_or_null<TypeSystemClang>(ts.get()); if (!clang_type_system) return nullptr; clang_type_system->GetPDBParser()->GetDeclForSymbol(pdb_func); @@ -568,8 +570,9 @@ lldb_private::Type *SymbolFilePDB::ResolveTypeUID(lldb::user_id_t type_uid) { return nullptr; } + auto ts = *type_system_or_err; TypeSystemClang *clang_type_system = - llvm::dyn_cast_or_null<TypeSystemClang>(&type_system_or_err.get()); + llvm::dyn_cast_or_null<TypeSystemClang>(ts.get()); if (!clang_type_system) return nullptr; PDBASTParser *pdb = clang_type_system->GetPDBParser(); @@ -583,14 +586,13 @@ lldb_private::Type *SymbolFilePDB::ResolveTypeUID(lldb::user_id_t type_uid) { lldb::TypeSP result = pdb->CreateLLDBTypeFromPDBType(*pdb_type); if (result) { m_types.insert(std::make_pair(type_uid, result)); - GetTypeList().Insert(result); } return result.get(); } -llvm::Optional<SymbolFile::ArrayInfo> SymbolFilePDB::GetDynamicArrayInfoForUID( +std::optional<SymbolFile::ArrayInfo> SymbolFilePDB::GetDynamicArrayInfoForUID( lldb::user_id_t type_uid, const lldb_private::ExecutionContext *exe_ctx) { - return llvm::None; + return std::nullopt; } bool SymbolFilePDB::CompleteType(lldb_private::CompilerType &compiler_type) { @@ -604,9 +606,9 @@ bool SymbolFilePDB::CompleteType(lldb_private::CompilerType &compiler_type) { "Unable to get dynamic array info for UID"); return false; } - + auto ts = *type_system_or_err; TypeSystemClang *clang_ast_ctx = - llvm::dyn_cast_or_null<TypeSystemClang>(&type_system_or_err.get()); + llvm::dyn_cast_or_null<TypeSystemClang>(ts.get()); if (!clang_ast_ctx) return false; @@ -626,9 +628,9 @@ lldb_private::CompilerDecl SymbolFilePDB::GetDeclForUID(lldb::user_id_t uid) { "Unable to get decl for UID"); return CompilerDecl(); } - + auto ts = *type_system_or_err; TypeSystemClang *clang_ast_ctx = - llvm::dyn_cast_or_null<TypeSystemClang>(&type_system_or_err.get()); + llvm::dyn_cast_or_null<TypeSystemClang>(ts.get()); if (!clang_ast_ctx) return CompilerDecl(); @@ -657,8 +659,9 @@ SymbolFilePDB::GetDeclContextForUID(lldb::user_id_t uid) { return CompilerDeclContext(); } + auto ts = *type_system_or_err; TypeSystemClang *clang_ast_ctx = - llvm::dyn_cast_or_null<TypeSystemClang>(&type_system_or_err.get()); + llvm::dyn_cast_or_null<TypeSystemClang>(ts.get()); if (!clang_ast_ctx) return CompilerDeclContext(); @@ -687,8 +690,9 @@ SymbolFilePDB::GetDeclContextContainingUID(lldb::user_id_t uid) { return CompilerDeclContext(); } + auto ts = *type_system_or_err; TypeSystemClang *clang_ast_ctx = - llvm::dyn_cast_or_null<TypeSystemClang>(&type_system_or_err.get()); + llvm::dyn_cast_or_null<TypeSystemClang>(ts.get()); if (!clang_ast_ctx) return CompilerDeclContext(); @@ -716,8 +720,9 @@ void SymbolFilePDB::ParseDeclsForContext( return; } + auto ts = *type_system_or_err; TypeSystemClang *clang_ast_ctx = - llvm::dyn_cast_or_null<TypeSystemClang>(&type_system_or_err.get()); + llvm::dyn_cast_or_null<TypeSystemClang>(ts.get()); if (!clang_ast_ctx) return; @@ -1057,7 +1062,7 @@ SymbolFilePDB::ParseVariables(const lldb_private::SymbolContext &sc, switch (lexical_parent->getSymTag()) { case PDB_SymType::Exe: assert(sc.comp_unit); - LLVM_FALLTHROUGH; + [[fallthrough]]; case PDB_SymType::Compiland: { if (sc.comp_unit) { local_variable_list_sp = sc.comp_unit->GetVariableList(false); @@ -1305,13 +1310,18 @@ void SymbolFilePDB::CacheFunctionNames() { } void SymbolFilePDB::FindFunctions( - lldb_private::ConstString name, + const lldb_private::Module::LookupInfo &lookup_info, const lldb_private::CompilerDeclContext &parent_decl_ctx, - FunctionNameType name_type_mask, bool include_inlines, + bool include_inlines, lldb_private::SymbolContextList &sc_list) { std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); + ConstString name = lookup_info.GetLookupName(); + FunctionNameType name_type_mask = lookup_info.GetNameTypeMask(); lldbassert((name_type_mask & eFunctionNameTypeAuto) == 0); + if (name_type_mask & eFunctionNameTypeFull) + name = lookup_info.GetName(); + if (name_type_mask == eFunctionNameTypeNone) return; if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx)) @@ -1459,8 +1469,9 @@ void SymbolFilePDB::DumpClangAST(Stream &s) { return; } - auto *clang_type_system = - llvm::dyn_cast_or_null<TypeSystemClang>(&type_system_or_err.get()); + auto ts = *type_system_or_err; + TypeSystemClang *clang_type_system = + llvm::dyn_cast_or_null<TypeSystemClang>(ts.get()); if (!clang_type_system) return; clang_type_system->Dump(s.AsRawOstream()); @@ -1613,9 +1624,7 @@ void SymbolFilePDB::GetTypesForPDBSymbol(const llvm::pdb::PDBSymbol &pdb_symbol, if (can_parse) { if (auto *type = ResolveTypeUID(pdb_symbol.getSymIndexId())) { - auto result = - std::find(type_collection.begin(), type_collection.end(), type); - if (result == type_collection.end()) + if (!llvm::is_contained(type_collection, type)) type_collection.push_back(type); } } @@ -1653,12 +1662,13 @@ void SymbolFilePDB::GetTypes(lldb_private::SymbolContextScope *sc_scope, } } -llvm::Expected<lldb_private::TypeSystem &> +llvm::Expected<lldb::TypeSystemSP> SymbolFilePDB::GetTypeSystemForLanguage(lldb::LanguageType language) { auto type_system_or_err = m_objfile_sp->GetModule()->GetTypeSystemForLanguage(language); if (type_system_or_err) { - type_system_or_err->SetSymbolFile(this); + if (auto ts = *type_system_or_err) + ts->SetSymbolFile(this); } return type_system_or_err; } @@ -1672,8 +1682,9 @@ PDBASTParser *SymbolFilePDB::GetPDBAstParser() { return nullptr; } + auto ts = *type_system_or_err; auto *clang_type_system = - llvm::dyn_cast_or_null<TypeSystemClang>(&type_system_or_err.get()); + llvm::dyn_cast_or_null<TypeSystemClang>(ts.get()); if (!clang_type_system) return nullptr; @@ -1691,9 +1702,9 @@ SymbolFilePDB::FindNamespace(lldb_private::ConstString name, "Unable to find namespace {}", name.AsCString()); return CompilerDeclContext(); } - + auto ts = *type_system_or_err; auto *clang_type_system = - llvm::dyn_cast_or_null<TypeSystemClang>(&type_system_or_err.get()); + llvm::dyn_cast_or_null<TypeSystemClang>(ts.get()); if (!clang_type_system) return CompilerDeclContext(); @@ -1940,7 +1951,7 @@ SymbolFilePDB::GetMangledForPDBFunc(const llvm::pdb::PDBSymbolFunc &pdb_func) { if (!func_decorated_name.empty()) { mangled.SetMangledName(ConstString(func_decorated_name)); - // For MSVC, format of C funciton's decorated name depends on calling + // For MSVC, format of C function's decorated name depends on calling // convention. Unfortunately none of the format is recognized by current // LLDB. For example, `_purecall` is a __cdecl C function. From PDB, // `__purecall` is retrieved as both its decorated and undecorated name @@ -1987,7 +1998,7 @@ bool SymbolFilePDB::DeclContextMatchesThisSymbolFile( return false; } - if (decl_ctx_type_system == &type_system_or_err.get()) + if (decl_ctx_type_system == type_system_or_err->get()) return true; // The type systems match, return true return false; @@ -2010,8 +2021,7 @@ uint32_t SymbolFilePDB::GetCompilandId(const llvm::pdb::PDBSymbolData &data) { auto &sec_cs = m_sec_contribs[sec]; auto offset = SectionContrib->getAddressOffset(); - auto it = - std::upper_bound(sec_cs.begin(), sec_cs.end(), offset, pred_upper); + auto it = llvm::upper_bound(sec_cs, offset, pred_upper); auto size = SectionContrib->getLength(); sec_cs.insert(it, {offset, size, comp_id}); @@ -2036,8 +2046,7 @@ uint32_t SymbolFilePDB::GetCompilandId(const llvm::pdb::PDBSymbolData &data) { if (DataSection) { // Search by section contributions auto &sec_cs = m_sec_contribs[DataSection]; - auto it = - std::upper_bound(sec_cs.begin(), sec_cs.end(), DataOffset, pred_upper); + auto it = llvm::upper_bound(sec_cs, DataOffset, pred_upper); if (it != sec_cs.begin()) { --it; if (DataOffset < it->Offset + it->Size) diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h index 5d4b51ba2e19..992bafd6a377 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h @@ -18,6 +18,7 @@ #include "llvm/DebugInfo/PDB/IPDBSession.h" #include "llvm/DebugInfo/PDB/PDB.h" #include "llvm/DebugInfo/PDB/PDBSymbolExe.h" +#include <optional> class PDBASTParser; @@ -83,7 +84,7 @@ public: ParseVariablesForContext(const lldb_private::SymbolContext &sc) override; lldb_private::Type *ResolveTypeUID(lldb::user_id_t type_uid) override; - llvm::Optional<ArrayInfo> GetDynamicArrayInfoForUID( + std::optional<ArrayInfo> GetDynamicArrayInfoForUID( lldb::user_id_t type_uid, const lldb_private::ExecutionContext *exe_ctx) override; @@ -119,9 +120,8 @@ public: uint32_t max_matches, lldb_private::VariableList &variables) override; - void FindFunctions(lldb_private::ConstString name, + void FindFunctions(const lldb_private::Module::LookupInfo &lookup_info, const lldb_private::CompilerDeclContext &parent_decl_ctx, - lldb::FunctionNameType name_type_mask, bool include_inlines, lldb_private::SymbolContextList &sc_list) override; @@ -154,7 +154,7 @@ public: lldb::TypeClass type_mask, lldb_private::TypeList &type_list) override; - llvm::Expected<lldb_private::TypeSystem &> + llvm::Expected<lldb::TypeSystemSP> GetTypeSystemForLanguage(lldb::LanguageType language) override; lldb_private::CompilerDeclContext FindNamespace( diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp index cc22eaeef779..6e4c6439974e 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp @@ -21,6 +21,7 @@ #include "lldb/Utility/Timer.h" #include <memory> +#include <optional> using namespace lldb; using namespace lldb_private; @@ -229,10 +230,10 @@ Type *SymbolFileSymtab::ResolveTypeUID(lldb::user_id_t type_uid) { return nullptr; } -llvm::Optional<SymbolFile::ArrayInfo> +std::optional<SymbolFile::ArrayInfo> SymbolFileSymtab::GetDynamicArrayInfoForUID( lldb::user_id_t type_uid, const lldb_private::ExecutionContext *exe_ctx) { - return llvm::None; + return std::nullopt; } bool SymbolFileSymtab::CompleteType(lldb_private::CompilerType &compiler_type) { diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h index 0a9fa5fce1b0..4cf4b5f37079 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h @@ -10,6 +10,7 @@ #define LLDB_SOURCE_PLUGINS_SYMBOLFILE_SYMTAB_SYMBOLFILESYMTAB_H #include <map> +#include <optional> #include <vector> #include "lldb/Symbol/SymbolFile.h" @@ -70,7 +71,7 @@ public: ParseVariablesForContext(const lldb_private::SymbolContext &sc) override; lldb_private::Type *ResolveTypeUID(lldb::user_id_t type_uid) override; - llvm::Optional<ArrayInfo> GetDynamicArrayInfoForUID( + std::optional<ArrayInfo> GetDynamicArrayInfoForUID( lldb::user_id_t type_uid, const lldb_private::ExecutionContext *exe_ctx) override; diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolVendor/PECOFF/SymbolVendorPECOFF.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolVendor/PECOFF/SymbolVendorPECOFF.cpp index 9b651243152c..0f8d3108998d 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolVendor/PECOFF/SymbolVendorPECOFF.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolVendor/PECOFF/SymbolVendorPECOFF.cpp @@ -102,8 +102,6 @@ SymbolVendorPECOFF::CreateInstance(const lldb::ModuleSP &module_sp, // This objfile is for debugging purposes. dsym_objfile_sp->SetType(ObjectFile::eTypeDebugInfo); - SymbolVendorPECOFF *symbol_vendor = new SymbolVendorPECOFF(module_sp); - // Get the module unified section list and add our debug sections to // that. SectionList *module_section_list = module_sp->GetSectionList(); @@ -132,6 +130,7 @@ SymbolVendorPECOFF::CreateInstance(const lldb::ModuleSP &module_sp, } } + SymbolVendorPECOFF *symbol_vendor = new SymbolVendorPECOFF(module_sp); symbol_vendor->AddSymbolFileRepresentation(dsym_objfile_sp); return symbol_vendor; } diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolVendor/wasm/SymbolVendorWasm.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolVendor/wasm/SymbolVendorWasm.cpp index 9da5b0133d37..6290843a8987 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolVendor/wasm/SymbolVendorWasm.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolVendor/wasm/SymbolVendorWasm.cpp @@ -9,6 +9,7 @@ #include "SymbolVendorWasm.h" #include <cstring> +#include <optional> #include "Plugins/ObjectFile/wasm/ObjectFileWasm.h" #include "lldb/Core/Module.h" @@ -78,7 +79,7 @@ SymbolVendorWasm::CreateInstance(const lldb::ModuleSP &module_sp, // A Wasm module may have a custom section named "external_debug_info" whose // content is the absolute or relative path of the Wasm module that contains // debug symbols for this module. - llvm::Optional<FileSpec> symbol_file_spec = + std::optional<FileSpec> symbol_file_spec = obj_file->GetExternalDebugInfoFileSpec(); if (!symbol_file_spec) return nullptr; diff --git a/contrib/llvm-project/lldb/source/Plugins/Trace/common/ThreadPostMortemTrace.cpp b/contrib/llvm-project/lldb/source/Plugins/Trace/common/ThreadPostMortemTrace.cpp index 37239b9d4c71..564a52eaaf82 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Trace/common/ThreadPostMortemTrace.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Trace/common/ThreadPostMortemTrace.cpp @@ -9,6 +9,7 @@ #include "ThreadPostMortemTrace.h" #include <memory> +#include <optional> #include "Plugins/Process/Utility/RegisterContextHistory.h" #include "lldb/Target/Process.h" @@ -37,6 +38,6 @@ ThreadPostMortemTrace::CreateRegisterContextForFrame(StackFrame *frame) { bool ThreadPostMortemTrace::CalculateStopInfo() { return false; } -const Optional<FileSpec> &ThreadPostMortemTrace::GetTraceFile() const { +const std::optional<FileSpec> &ThreadPostMortemTrace::GetTraceFile() const { return m_trace_file; } diff --git a/contrib/llvm-project/lldb/source/Plugins/Trace/common/ThreadPostMortemTrace.h b/contrib/llvm-project/lldb/source/Plugins/Trace/common/ThreadPostMortemTrace.h index cdb896cff5c5..39f53fe09f88 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Trace/common/ThreadPostMortemTrace.h +++ b/contrib/llvm-project/lldb/source/Plugins/Trace/common/ThreadPostMortemTrace.h @@ -10,6 +10,7 @@ #define LLDB_TARGET_THREADPOSTMORTEMTRACE_H #include "lldb/Target/Thread.h" +#include <optional> namespace lldb_private { @@ -30,7 +31,7 @@ public: /// The file that contains the list of instructions that were traced when /// this thread was being executed. ThreadPostMortemTrace(Process &process, lldb::tid_t tid, - const llvm::Optional<FileSpec> &trace_file) + const std::optional<FileSpec> &trace_file) : Thread(process, tid), m_trace_file(trace_file) {} void RefreshStateAfterStop() override; @@ -42,7 +43,7 @@ public: /// \return /// The trace file of this thread. - const llvm::Optional<FileSpec> &GetTraceFile() const; + const std::optional<FileSpec> &GetTraceFile() const; protected: bool CalculateStopInfo() override; @@ -50,7 +51,7 @@ protected: lldb::RegisterContextSP m_thread_reg_ctx_sp; private: - llvm::Optional<FileSpec> m_trace_file; + std::optional<FileSpec> m_trace_file; }; } // namespace lldb_private diff --git a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.cpp b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.cpp index dd28292c1daf..d4f7dc354e9f 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.cpp @@ -7,13 +7,13 @@ //===----------------------------------------------------------------------===// #include "CommandObjectTraceStartIntelPT.h" - #include "TraceIntelPT.h" #include "TraceIntelPTConstants.h" #include "lldb/Host/OptionParser.h" #include "lldb/Interpreter/CommandOptionArgumentTable.h" #include "lldb/Target/Process.h" #include "lldb/Target/Trace.h" +#include <optional> using namespace lldb; using namespace lldb_private; @@ -33,7 +33,7 @@ Status CommandObjectThreadTraceStartIntelPT::CommandOptions::SetOptionValue( switch (short_option) { case 's': { - if (Optional<uint64_t> bytes = + if (std::optional<uint64_t> bytes = ParsingUtils::ParseUserFriendlySizeExpression(option_arg)) m_ipt_trace_size = *bytes; else @@ -70,7 +70,7 @@ void CommandObjectThreadTraceStartIntelPT::CommandOptions:: llvm::ArrayRef<OptionDefinition> CommandObjectThreadTraceStartIntelPT::CommandOptions::GetDefinitions() { - return llvm::makeArrayRef(g_thread_trace_start_intel_pt_options); + return llvm::ArrayRef(g_thread_trace_start_intel_pt_options); } bool CommandObjectThreadTraceStartIntelPT::DoExecuteOnThreads( @@ -98,7 +98,7 @@ Status CommandObjectProcessTraceStartIntelPT::CommandOptions::SetOptionValue( switch (short_option) { case 's': { - if (Optional<uint64_t> bytes = + if (std::optional<uint64_t> bytes = ParsingUtils::ParseUserFriendlySizeExpression(option_arg)) m_ipt_trace_size = *bytes; else @@ -107,7 +107,7 @@ Status CommandObjectProcessTraceStartIntelPT::CommandOptions::SetOptionValue( break; } case 'l': { - if (Optional<uint64_t> bytes = + if (std::optional<uint64_t> bytes = ParsingUtils::ParseUserFriendlySizeExpression(option_arg)) m_process_buffer_size_limit = *bytes; else @@ -155,7 +155,7 @@ void CommandObjectProcessTraceStartIntelPT::CommandOptions:: llvm::ArrayRef<OptionDefinition> CommandObjectProcessTraceStartIntelPT::CommandOptions::GetDefinitions() { - return llvm::makeArrayRef(g_process_trace_start_intel_pt_options); + return llvm::ArrayRef(g_process_trace_start_intel_pt_options); } bool CommandObjectProcessTraceStartIntelPT::DoExecute( @@ -171,10 +171,10 @@ bool CommandObjectProcessTraceStartIntelPT::DoExecute( return result.Succeeded(); } -Optional<uint64_t> +std::optional<uint64_t> ParsingUtils::ParseUserFriendlySizeExpression(llvm::StringRef size_expression) { if (size_expression.empty()) { - return llvm::None; + return std::nullopt; } const uint64_t kBytesMultiplier = 1; const uint64_t kKibiBytesMultiplier = 1024; @@ -188,7 +188,7 @@ ParsingUtils::ParseUserFriendlySizeExpression(llvm::StringRef size_expression) { const auto non_digit_index = size_expression.find_first_not_of("0123456789"); if (non_digit_index == 0) { // expression starts from from non-digit char. - return llvm::None; + return std::nullopt; } const llvm::StringRef number_part = @@ -197,7 +197,7 @@ ParsingUtils::ParseUserFriendlySizeExpression(llvm::StringRef size_expression) { : size_expression.substr(0, non_digit_index); uint64_t parsed_number; if (number_part.getAsInteger(10, parsed_number)) { - return llvm::None; + return std::nullopt; } if (non_digit_index != llvm::StringRef::npos) { // if expression has units. @@ -205,7 +205,7 @@ ParsingUtils::ParseUserFriendlySizeExpression(llvm::StringRef size_expression) { auto it = multipliers.find(multiplier); if (it == multipliers.end()) - return llvm::None; + return std::nullopt; return parsed_number * it->second; } else { diff --git a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.h b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.h index 083184e4817c..254baaf3e673 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.h +++ b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.h @@ -13,6 +13,7 @@ #include "TraceIntelPT.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" +#include <optional> namespace lldb_private { namespace trace_intel_pt { @@ -33,7 +34,7 @@ public: uint64_t m_ipt_trace_size; bool m_enable_tsc; - llvm::Optional<uint64_t> m_psb_period; + std::optional<uint64_t> m_psb_period; }; CommandObjectThreadTraceStartIntelPT(TraceIntelPT &trace, @@ -77,7 +78,7 @@ public: uint64_t m_ipt_trace_size; uint64_t m_process_buffer_size_limit; bool m_enable_tsc; - llvm::Optional<uint64_t> m_psb_period; + std::optional<uint64_t> m_psb_period; bool m_per_cpu_tracing; bool m_disable_cgroup_filtering; }; @@ -121,9 +122,9 @@ namespace ParsingUtils { /// MB and MiB for 2^20 bytes; and B for bytes. A single integral number is /// considered bytes. /// \return -/// The converted number of bytes or \a llvm::None if the expression is +/// The converted number of bytes or \a std::nullopt if the expression is /// invalid. -llvm::Optional<uint64_t> +std::optional<uint64_t> ParseUserFriendlySizeExpression(llvm::StringRef size_expression); } // namespace ParsingUtils diff --git a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/DecodedThread.cpp b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/DecodedThread.cpp index 02f1d2f24d8c..58cd2290a8b7 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/DecodedThread.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/DecodedThread.cpp @@ -7,30 +7,16 @@ //===----------------------------------------------------------------------===// #include "DecodedThread.h" - -#include <intel-pt.h> - #include "TraceCursorIntelPT.h" - +#include <intel-pt.h> #include <memory> +#include <optional> using namespace lldb; using namespace lldb_private; using namespace lldb_private::trace_intel_pt; using namespace llvm; -bool lldb_private::trace_intel_pt::IsLibiptError(int libipt_status) { - return libipt_status < 0; -} - -bool lldb_private::trace_intel_pt::IsEndOfStream(int libipt_status) { - return libipt_status == -pte_eos; -} - -bool lldb_private::trace_intel_pt::IsTscUnavailable(int libipt_status) { - return libipt_status == -pte_no_time; -} - char IntelPTError::ID; IntelPTError::IntelPTError(int libipt_error_code, lldb::addr_t address) @@ -106,6 +92,11 @@ DecodedThread::GetInstructionLoadAddress(uint64_t item_index) const { return m_item_data[item_index].load_address; } +lldb::addr_t +DecodedThread::GetSyncPointOffsetByIndex(uint64_t item_index) const { + return m_psb_offsets.find(item_index)->second; +} + ThreadSP DecodedThread::GetThread() { return m_thread_sp; } DecodedThread::TraceItemStorage & @@ -119,9 +110,17 @@ DecodedThread::CreateNewTraceItem(lldb::TraceItemKind kind) { return m_item_data.back(); } +void DecodedThread::NotifySyncPoint(lldb::addr_t psb_offset) { + m_psb_offsets.try_emplace(GetItemsCount(), psb_offset); + AppendEvent(lldb::eTraceEventSyncPoint); +} + void DecodedThread::NotifyTsc(TSC tsc) { if (m_last_tsc && (*m_last_tsc)->second.tsc == tsc) return; + if (m_last_tsc) + assert(tsc >= (*m_last_tsc)->second.tsc && + "We can't have decreasing times"); m_last_tsc = m_tscs.emplace(GetItemsCount(), TSCRange{tsc, 0, GetItemsCount()}).first; @@ -151,30 +150,31 @@ void DecodedThread::NotifyCPU(lldb::cpu_id_t cpu_id) { } } -Optional<lldb::cpu_id_t> -DecodedThread::GetCPUByIndex(uint64_t item_index) const { +lldb::cpu_id_t DecodedThread::GetCPUByIndex(uint64_t item_index) const { auto it = m_cpus.upper_bound(item_index); - if (it == m_cpus.begin()) - return None; - return prev(it)->second; + return it == m_cpus.begin() ? LLDB_INVALID_CPU_ID : prev(it)->second; } -Optional<DecodedThread::TSCRange> +std::optional<DecodedThread::TSCRange> DecodedThread::GetTSCRangeByIndex(uint64_t item_index) const { auto next_it = m_tscs.upper_bound(item_index); if (next_it == m_tscs.begin()) - return None; + return std::nullopt; return prev(next_it)->second; } -Optional<DecodedThread::NanosecondsRange> +std::optional<DecodedThread::NanosecondsRange> DecodedThread::GetNanosecondsRangeByIndex(uint64_t item_index) { auto next_it = m_nanoseconds.upper_bound(item_index); if (next_it == m_nanoseconds.begin()) - return None; + return std::nullopt; return prev(next_it)->second; } +uint64_t DecodedThread::GetTotalInstructionCount() const { + return m_insn_count; +} + void DecodedThread::AppendEvent(lldb::TraceEvent event) { CreateNewTraceItem(lldb::eTraceItemKindEvent).event = event; m_events_stats.RecordEvent(event); @@ -182,46 +182,55 @@ void DecodedThread::AppendEvent(lldb::TraceEvent event) { void DecodedThread::AppendInstruction(const pt_insn &insn) { CreateNewTraceItem(lldb::eTraceItemKindInstruction).load_address = insn.ip; + m_insn_count++; } void DecodedThread::AppendError(const IntelPTError &error) { - // End of stream shouldn't be a public error - if (IsEndOfStream(error.GetLibiptErrorCode())) - return; CreateNewTraceItem(lldb::eTraceItemKindError).error = ConstString(error.message()).AsCString(); + m_error_stats.RecordError(/*fatal=*/false); } -void DecodedThread::AppendCustomError(StringRef err) { +void DecodedThread::AppendCustomError(StringRef err, bool fatal) { CreateNewTraceItem(lldb::eTraceItemKindError).error = ConstString(err).AsCString(); + m_error_stats.RecordError(fatal); } lldb::TraceEvent DecodedThread::GetEventByIndex(int item_index) const { return m_item_data[item_index].event; } -void DecodedThread::LibiptErrorsStats::RecordError(int libipt_error_code) { - libipt_errors_counts[pt_errstr(pt_errcode(libipt_error_code))]++; +const DecodedThread::EventsStats &DecodedThread::GetEventsStats() const { + return m_events_stats; +} + +void DecodedThread::EventsStats::RecordEvent(lldb::TraceEvent event) { + events_counts[event]++; total_count++; } -void DecodedThread::RecordTscError(int libipt_error_code) { - m_tsc_errors_stats.RecordError(libipt_error_code); +uint64_t DecodedThread::ErrorStats::GetTotalCount() const { + uint64_t total = 0; + for (const auto &[kind, count] : libipt_errors) + total += count; + + return total + other_errors + fatal_errors; } -const DecodedThread::LibiptErrorsStats & -DecodedThread::GetTscErrorsStats() const { - return m_tsc_errors_stats; +void DecodedThread::ErrorStats::RecordError(bool fatal) { + if (fatal) + fatal_errors++; + else + other_errors++; } -const DecodedThread::EventsStats &DecodedThread::GetEventsStats() const { - return m_events_stats; +void DecodedThread::ErrorStats::RecordError(int libipt_error_code) { + libipt_errors[pt_errstr(pt_errcode(libipt_error_code))]++; } -void DecodedThread::EventsStats::RecordEvent(lldb::TraceEvent event) { - events_counts[event]++; - total_count++; +const DecodedThread::ErrorStats &DecodedThread::GetErrorStats() const { + return m_error_stats; } lldb::TraceItemKind @@ -235,7 +244,7 @@ const char *DecodedThread::GetErrorByIndex(uint64_t item_index) const { DecodedThread::DecodedThread( ThreadSP thread_sp, - const llvm::Optional<LinuxPerfZeroTscConversion> &tsc_conversion) + const std::optional<LinuxPerfZeroTscConversion> &tsc_conversion) : m_thread_sp(thread_sp), m_tsc_conversion(tsc_conversion) {} size_t DecodedThread::CalculateApproximateMemoryUsage() const { diff --git a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/DecodedThread.h b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/DecodedThread.h index 9376a0af169d..b2a674aca182 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/DecodedThread.h +++ b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/DecodedThread.h @@ -9,29 +9,18 @@ #ifndef LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_DECODEDTHREAD_H #define LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_DECODEDTHREAD_H -#include <utility> -#include <vector> - -#include "llvm/Support/Errc.h" -#include "llvm/Support/Error.h" - +#include "intel-pt.h" #include "lldb/Target/Trace.h" #include "lldb/Utility/TraceIntelPTGDBRemotePackets.h" - -#include "intel-pt.h" +#include "llvm/Support/Errc.h" +#include "llvm/Support/Error.h" +#include <optional> +#include <utility> +#include <vector> namespace lldb_private { namespace trace_intel_pt { -/// libipt status utils -/// \{ -bool IsLibiptError(int libipt_status); - -bool IsEndOfStream(int libipt_status); - -bool IsTscUnavailable(int libipt_status); -/// \} - /// Class for representing a libipt decoding error. class IntelPTError : public llvm::ErrorInfo<IntelPTError> { public: @@ -73,15 +62,6 @@ class DecodedThread : public std::enable_shared_from_this<DecodedThread> { public: using TSC = uint64_t; - // Struct holding counts for libipts errors; - struct LibiptErrorsStats { - // libipt error -> count - llvm::DenseMap<const char *, int> libipt_errors_counts; - size_t total_count = 0; - - void RecordError(int libipt_error_code); - }; - /// A structure that represents a maximal range of trace items associated to /// the same TSC value. struct TSCRange { @@ -137,19 +117,41 @@ public: bool InRange(uint64_t item_index) const; }; - // Struct holding counts for events; + // Struct holding counts for events struct EventsStats { /// A count for each individual event kind. We use an unordered map instead /// of a DenseMap because DenseMap can't understand enums. - std::unordered_map<lldb::TraceEvent, size_t> events_counts; - size_t total_count = 0; + /// + /// Note: We can't use DenseMap because lldb::TraceEvent is not + /// automatically handled correctly by DenseMap. We'd need to implement a + /// custom DenseMapInfo struct for TraceEvent and that's a bit too much for + /// such a simple structure. + std::unordered_map<lldb::TraceEvent, uint64_t> events_counts; + uint64_t total_count = 0; void RecordEvent(lldb::TraceEvent event); }; + // Struct holding counts for errors + struct ErrorStats { + /// The following counters are mutually exclusive + /// \{ + uint64_t other_errors = 0; + uint64_t fatal_errors = 0; + // libipt error -> count + llvm::DenseMap<const char *, uint64_t> libipt_errors; + /// \} + + uint64_t GetTotalCount() const; + + void RecordError(int libipt_error_code); + + void RecordError(bool fatal); + }; + DecodedThread( lldb::ThreadSP thread_sp, - const llvm::Optional<LinuxPerfZeroTscConversion> &tsc_conversion); + const std::optional<LinuxPerfZeroTscConversion> &tsc_conversion); /// Get the total number of instruction, errors and events from the decoded /// trace. @@ -173,8 +175,12 @@ public: /// The trace item index to compare with. /// /// \return - /// The requested cpu id, or \a llvm::None if not available. - llvm::Optional<lldb::cpu_id_t> GetCPUByIndex(uint64_t item_index) const; + /// The requested cpu id, or \a LLDB_INVALID_CPU_ID if not available. + lldb::cpu_id_t GetCPUByIndex(uint64_t item_index) const; + + /// \return + /// The PSB offset associated with the given item index. + lldb::addr_t GetSyncPointOffsetByIndex(uint64_t item_index) const; /// Get a maximal range of trace items that include the given \p item_index /// that have the same TSC value. @@ -183,8 +189,8 @@ public: /// The trace item index to compare with. /// /// \return - /// The requested TSC range, or \a llvm::None if not available. - llvm::Optional<DecodedThread::TSCRange> + /// The requested TSC range, or \a std::nullopt if not available. + std::optional<DecodedThread::TSCRange> GetTSCRangeByIndex(uint64_t item_index) const; /// Get a maximal range of trace items that include the given \p item_index @@ -194,21 +200,17 @@ public: /// The trace item index to compare with. /// /// \return - /// The requested nanoseconds range, or \a llvm::None if not available. - llvm::Optional<DecodedThread::NanosecondsRange> + /// The requested nanoseconds range, or \a std::nullopt if not available. + std::optional<DecodedThread::NanosecondsRange> GetNanosecondsRangeByIndex(uint64_t item_index); /// \return /// The load address of the instruction at the given index. lldb::addr_t GetInstructionLoadAddress(uint64_t item_index) const; - /// Return an object with statistics of the TSC decoding errors that happened. - /// A TSC error is not a fatal error and doesn't create gaps in the trace. - /// Instead we only keep track of them as statistics. - /// /// \return - /// An object with the statistics of TSC decoding errors. - const LibiptErrorsStats &GetTscErrorsStats() const; + /// The number of instructions in this trace (not trace items). + uint64_t GetTotalInstructionCount() const; /// Return an object with statistics of the trace events that happened. /// @@ -216,13 +218,11 @@ public: /// The stats object of all the events. const EventsStats &GetEventsStats() const; - /// Record an error decoding a TSC timestamp. + /// Return an object with statistics of the trace errors that happened. /// - /// See \a GetTscErrors() for more documentation. - /// - /// \param[in] libipt_error_code - /// An error returned by the libipt library. - void RecordTscError(int libipt_error_code); + /// \return + /// The stats object of all the events. + const ErrorStats &GetErrorStats() const; /// The approximate size in bytes used by this instance, /// including all the already decoded instructions. @@ -238,11 +238,21 @@ public: /// If this a new CPU, an event will be created. void NotifyCPU(lldb::cpu_id_t cpu_id); + /// Notify this object that a new PSB has been seen. + void NotifySyncPoint(lldb::addr_t psb_offset); + /// Append a decoding error. void AppendError(const IntelPTError &error); /// Append a custom decoding. - void AppendCustomError(llvm::StringRef error); + /// + /// \param[in] error + /// The error message. + /// + /// \param[in] fatal + /// If \b true, then the whole decoded thread should be discarded because a + /// fatal anomaly has been found. + void AppendCustomError(llvm::StringRef error, bool fatal = false); /// Append an event. void AppendEvent(lldb::TraceEvent); @@ -286,33 +296,40 @@ private: /// TSCs are sporadic and we can think of them as ranges. std::map<uint64_t, TSCRange> m_tscs; /// This is the chronologically last TSC that has been added. - llvm::Optional<std::map<uint64_t, TSCRange>::iterator> m_last_tsc = - llvm::None; + std::optional<std::map<uint64_t, TSCRange>::iterator> m_last_tsc = + std::nullopt; /// This map contains the non-interpolated nanoseconds timestamps of the /// decoded trace items. It maps `item index -> nanoseconds`, where `item /// index` is the first index at which the mapped nanoseconds first appears. /// We use this representation because timestamps are sporadic and we think of /// them as ranges. std::map<uint64_t, NanosecondsRange> m_nanoseconds; - llvm::Optional<std::map<uint64_t, NanosecondsRange>::iterator> - m_last_nanoseconds = llvm::None; + std::optional<std::map<uint64_t, NanosecondsRange>::iterator> + m_last_nanoseconds = std::nullopt; - // The cpu information is stored as a map. It maps `instruction index -> CPU` + // The cpu information is stored as a map. It maps `item index -> CPU`. // A CPU is associated with the next instructions that follow until the next // cpu is seen. std::map<uint64_t, lldb::cpu_id_t> m_cpus; /// This is the chronologically last CPU ID. - llvm::Optional<uint64_t> m_last_cpu = llvm::None; + std::optional<uint64_t> m_last_cpu; + + // The PSB offsets are stored as a map. It maps `item index -> psb offset`. + llvm::DenseMap<uint64_t, lldb::addr_t> m_psb_offsets; /// TSC -> nanos conversion utility. - llvm::Optional<LinuxPerfZeroTscConversion> m_tsc_conversion; + std::optional<LinuxPerfZeroTscConversion> m_tsc_conversion; + + /// Statistics of all tracing errors. + ErrorStats m_error_stats; /// Statistics of all tracing events. EventsStats m_events_stats; - /// Statistics of libipt errors when decoding TSCs. - LibiptErrorsStats m_tsc_errors_stats; /// Total amount of time spent decoding. std::chrono::milliseconds m_total_decoding_time{0}; + + /// Total number of instructions in the trace. + uint64_t m_insn_count = 0; }; using DecodedThreadSP = std::shared_ptr<DecodedThread>; diff --git a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/LibiptDecoder.cpp b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/LibiptDecoder.cpp index 234b9f917d32..cdf81954eee9 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/LibiptDecoder.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/LibiptDecoder.cpp @@ -6,18 +6,309 @@ //===----------------------------------------------------------------------===// #include "LibiptDecoder.h" - #include "TraceIntelPT.h" - #include "lldb/Target/Process.h" +#include <optional> using namespace lldb; using namespace lldb_private; using namespace lldb_private::trace_intel_pt; using namespace llvm; -/// Class that decodes a raw buffer for a single thread using the low level -/// libipt library. +bool IsLibiptError(int status) { return status < 0; } + +bool IsEndOfStream(int status) { + assert(status >= 0 && "We can't check if we reached the end of the stream if " + "we got a failed status"); + return status & pts_eos; +} + +bool HasEvents(int status) { + assert(status >= 0 && "We can't check for events if we got a failed status"); + return status & pts_event_pending; +} + +// RAII deleter for libipt's decoders +auto InsnDecoderDeleter = [](pt_insn_decoder *decoder) { + pt_insn_free_decoder(decoder); +}; + +auto QueryDecoderDeleter = [](pt_query_decoder *decoder) { + pt_qry_free_decoder(decoder); +}; + +using PtInsnDecoderUP = + std::unique_ptr<pt_insn_decoder, decltype(InsnDecoderDeleter)>; + +using PtQueryDecoderUP = + std::unique_ptr<pt_query_decoder, decltype(QueryDecoderDeleter)>; + +/// Create a basic configuration object limited to a given buffer that can be +/// used for many different decoders. +static Expected<pt_config> CreateBasicLibiptConfig(TraceIntelPT &trace_intel_pt, + ArrayRef<uint8_t> buffer) { + Expected<pt_cpu> cpu_info = trace_intel_pt.GetCPUInfo(); + if (!cpu_info) + return cpu_info.takeError(); + + pt_config config; + pt_config_init(&config); + config.cpu = *cpu_info; + + int status = pt_cpu_errata(&config.errata, &config.cpu); + if (IsLibiptError(status)) + return make_error<IntelPTError>(status); + + // The libipt library does not modify the trace buffer, hence the + // following casts are safe. + config.begin = const_cast<uint8_t *>(buffer.data()); + config.end = const_cast<uint8_t *>(buffer.data() + buffer.size()); + return config; +} + +/// Callback used by libipt for reading the process memory. +/// +/// More information can be found in +/// https://github.com/intel/libipt/blob/master/doc/man/pt_image_set_callback.3.md +static int ReadProcessMemory(uint8_t *buffer, size_t size, + const pt_asid * /* unused */, uint64_t pc, + void *context) { + Process *process = static_cast<Process *>(context); + + Status error; + int bytes_read = process->ReadMemory(pc, buffer, size, error); + if (error.Fail()) + return -pte_nomap; + return bytes_read; +} + +/// Set up the memory image callback for the given decoder. +static Error SetupMemoryImage(pt_insn_decoder *decoder, Process &process) { + pt_image *image = pt_insn_get_image(decoder); + + int status = pt_image_set_callback(image, ReadProcessMemory, &process); + if (IsLibiptError(status)) + return make_error<IntelPTError>(status); + return Error::success(); +} + +/// Create an instruction decoder for the given buffer and the given process. +static Expected<PtInsnDecoderUP> +CreateInstructionDecoder(TraceIntelPT &trace_intel_pt, ArrayRef<uint8_t> buffer, + Process &process) { + Expected<pt_config> config = CreateBasicLibiptConfig(trace_intel_pt, buffer); + if (!config) + return config.takeError(); + + pt_insn_decoder *decoder_ptr = pt_insn_alloc_decoder(&*config); + if (!decoder_ptr) + return make_error<IntelPTError>(-pte_nomem); + + PtInsnDecoderUP decoder_up(decoder_ptr, InsnDecoderDeleter); + + if (Error err = SetupMemoryImage(decoder_ptr, process)) + return std::move(err); + + return decoder_up; +} + +/// Create a query decoder for the given buffer. The query decoder is the +/// highest level decoder that operates directly on packets and doesn't perform +/// actual instruction decoding. That's why it can be useful for inspecting a +/// raw trace without pinning it to a particular process. +static Expected<PtQueryDecoderUP> +CreateQueryDecoder(TraceIntelPT &trace_intel_pt, ArrayRef<uint8_t> buffer) { + Expected<pt_config> config = CreateBasicLibiptConfig(trace_intel_pt, buffer); + if (!config) + return config.takeError(); + + pt_query_decoder *decoder_ptr = pt_qry_alloc_decoder(&*config); + if (!decoder_ptr) + return make_error<IntelPTError>(-pte_nomem); + + return PtQueryDecoderUP(decoder_ptr, QueryDecoderDeleter); +} + +/// Class used to identify anomalies in traces, which should often indicate a +/// fatal error in the trace. +class PSBBlockAnomalyDetector { +public: + PSBBlockAnomalyDetector(pt_insn_decoder &decoder, + TraceIntelPT &trace_intel_pt, + DecodedThread &decoded_thread) + : m_decoder(decoder), m_decoded_thread(decoded_thread) { + m_infinite_decoding_loop_threshold = + trace_intel_pt.GetGlobalProperties() + .GetInfiniteDecodingLoopVerificationThreshold(); + m_extremely_large_decoding_threshold = + trace_intel_pt.GetGlobalProperties() + .GetExtremelyLargeDecodingThreshold(); + m_next_infinite_decoding_loop_threshold = + m_infinite_decoding_loop_threshold; + } + + /// \return + /// An \a llvm::Error if an anomaly that includes the last instruction item + /// in the trace, or \a llvm::Error::success otherwise. + Error DetectAnomaly() { + RefreshPacketOffset(); + uint64_t insn_added_since_last_packet_offset = + m_decoded_thread.GetTotalInstructionCount() - + m_insn_count_at_last_packet_offset; + + // We want to check if we might have fallen in an infinite loop. As this + // check is not a no-op, we want to do it when we have a strong suggestion + // that things went wrong. First, we check how many instructions we have + // decoded since we processed an Intel PT packet for the last time. This + // number should be low, because at some point we should see branches, jumps + // or interrupts that require a new packet to be processed. Once we reach + // certain threshold we start analyzing the trace. + // + // We use the number of decoded instructions since the last Intel PT packet + // as a proxy because, in fact, we don't expect a single packet to give, + // say, 100k instructions. That would mean that there are 100k sequential + // instructions without any single branch, which is highly unlikely, or that + // we found an infinite loop using direct jumps, e.g. + // + // 0x0A: nop or pause + // 0x0C: jump to 0x0A + // + // which is indeed code that is found in the kernel. I presume we reach + // this kind of code in the decoder because we don't handle self-modified + // code in post-mortem kernel traces. + // + // We are right now only signaling the anomaly as a trace error, but it + // would be more conservative to also discard all the trace items found in + // this PSB. I prefer not to do that for the time being to give more + // exposure to this kind of anomalies and help debugging. Discarding the + // trace items would just make investigation harded. + // + // Finally, if the user wants to see if a specific thread has an anomaly, + // it's enough to run the `thread trace dump info` command and look for the + // count of this kind of errors. + + if (insn_added_since_last_packet_offset >= + m_extremely_large_decoding_threshold) { + // In this case, we have decoded a massive amount of sequential + // instructions that don't loop. Honestly I wonder if this will ever + // happen, but better safe than sorry. + return createStringError( + inconvertibleErrorCode(), + "anomalous trace: possible infinite trace detected"); + } + if (insn_added_since_last_packet_offset == + m_next_infinite_decoding_loop_threshold) { + if (std::optional<uint64_t> loop_size = TryIdentifyInfiniteLoop()) { + return createStringError( + inconvertibleErrorCode(), + "anomalous trace: possible infinite loop detected of size %" PRIu64, + *loop_size); + } + m_next_infinite_decoding_loop_threshold *= 2; + } + return Error::success(); + } + +private: + std::optional<uint64_t> TryIdentifyInfiniteLoop() { + // The infinite decoding loops we'll encounter are due to sequential + // instructions that repeat themselves due to direct jumps, therefore in a + // cycle each individual address will only appear once. We use this + // information to detect cycles by finding the last 2 ocurrences of the last + // instruction added to the trace. Then we traverse the trace making sure + // that these two instructions where the ends of a repeating loop. + + // This is a utility that returns the most recent instruction index given a + // position in the trace. If the given position is an instruction, that + // position is returned. It skips non-instruction items. + auto most_recent_insn_index = + [&](uint64_t item_index) -> std::optional<uint64_t> { + while (true) { + if (m_decoded_thread.GetItemKindByIndex(item_index) == + lldb::eTraceItemKindInstruction) { + return item_index; + } + if (item_index == 0) + return std::nullopt; + item_index--; + } + return std::nullopt; + }; + // Similar to most_recent_insn_index but skips the starting position. + auto prev_insn_index = [&](uint64_t item_index) -> std::optional<uint64_t> { + if (item_index == 0) + return std::nullopt; + return most_recent_insn_index(item_index - 1); + }; + + // We first find the most recent instruction. + std::optional<uint64_t> last_insn_index_opt = + *prev_insn_index(m_decoded_thread.GetItemsCount()); + if (!last_insn_index_opt) + return std::nullopt; + uint64_t last_insn_index = *last_insn_index_opt; + + // We then find the most recent previous occurrence of that last + // instruction. + std::optional<uint64_t> last_insn_copy_index = + prev_insn_index(last_insn_index); + uint64_t loop_size = 1; + while (last_insn_copy_index && + m_decoded_thread.GetInstructionLoadAddress(*last_insn_copy_index) != + m_decoded_thread.GetInstructionLoadAddress(last_insn_index)) { + last_insn_copy_index = prev_insn_index(*last_insn_copy_index); + loop_size++; + } + if (!last_insn_copy_index) + return std::nullopt; + + // Now we check if the segment between these last positions of the last + // instruction address is in fact a repeating loop. + uint64_t loop_elements_visited = 1; + uint64_t insn_index_a = last_insn_index, + insn_index_b = *last_insn_copy_index; + while (loop_elements_visited < loop_size) { + if (std::optional<uint64_t> prev = prev_insn_index(insn_index_a)) + insn_index_a = *prev; + else + return std::nullopt; + if (std::optional<uint64_t> prev = prev_insn_index(insn_index_b)) + insn_index_b = *prev; + else + return std::nullopt; + if (m_decoded_thread.GetInstructionLoadAddress(insn_index_a) != + m_decoded_thread.GetInstructionLoadAddress(insn_index_b)) + return std::nullopt; + loop_elements_visited++; + } + return loop_size; + } + + // Refresh the internal counters if a new packet offset has been visited + void RefreshPacketOffset() { + lldb::addr_t new_packet_offset; + if (!IsLibiptError(pt_insn_get_offset(&m_decoder, &new_packet_offset)) && + new_packet_offset != m_last_packet_offset) { + m_last_packet_offset = new_packet_offset; + m_next_infinite_decoding_loop_threshold = + m_infinite_decoding_loop_threshold; + m_insn_count_at_last_packet_offset = + m_decoded_thread.GetTotalInstructionCount(); + } + } + + pt_insn_decoder &m_decoder; + DecodedThread &m_decoded_thread; + lldb::addr_t m_last_packet_offset = LLDB_INVALID_ADDRESS; + uint64_t m_insn_count_at_last_packet_offset = 0; + uint64_t m_infinite_decoding_loop_threshold; + uint64_t m_next_infinite_decoding_loop_threshold; + uint64_t m_extremely_large_decoding_threshold; +}; + +/// Class that decodes a raw buffer for a single PSB block using the low level +/// libipt library. It assumes that kernel and user mode instructions are not +/// mixed in the same PSB block. /// /// Throughout this code, the status of the decoder will be used to identify /// events needed to be processed or errors in the decoder. The values can be @@ -25,137 +316,214 @@ using namespace llvm; /// - positive or zero: not an error, but a list of bits signaling the status /// of the decoder, e.g. whether there are events that need to be decoded or /// not. -class LibiptDecoder { +class PSBBlockDecoder { public: /// \param[in] decoder - /// A well configured decoder. Using the current state of that decoder, - /// decoding will start at its next valid PSB. It's not assumed that the - /// decoder is already pointing at a valid PSB. + /// A decoder configured to start and end within the boundaries of the + /// given \p psb_block. + /// + /// \param[in] psb_block + /// The PSB block to decode. + /// + /// \param[in] next_block_ip + /// The starting ip at the next PSB block of the same thread if available. /// /// \param[in] decoded_thread /// A \a DecodedThread object where the decoded instructions will be /// appended to. It might have already some instructions. - LibiptDecoder(pt_insn_decoder &decoder, DecodedThread &decoded_thread) - : m_decoder(decoder), m_decoded_thread(decoded_thread) {} - - /// Decode all the instructions until the end of the trace. - /// The decoding flow is based on - /// https://github.com/intel/libipt/blob/master/doc/howto_libipt.md#the-instruction-flow-decode-loop. - void DecodeUntilEndOfTrace() { - // Multiple loops indicate gaps in the trace, which are found by the inner - // call to DecodeInstructionsAndEvents. - while (true) { - int status = pt_insn_sync_forward(&m_decoder); + /// + /// \param[in] tsc_upper_bound + /// Maximum allowed value of TSCs decoded from this PSB block. + /// Any of this PSB's data occurring after this TSC will be excluded. + PSBBlockDecoder(PtInsnDecoderUP &&decoder_up, const PSBBlock &psb_block, + std::optional<lldb::addr_t> next_block_ip, + DecodedThread &decoded_thread, TraceIntelPT &trace_intel_pt, + std::optional<DecodedThread::TSC> tsc_upper_bound) + : m_decoder_up(std::move(decoder_up)), m_psb_block(psb_block), + m_next_block_ip(next_block_ip), m_decoded_thread(decoded_thread), + m_anomaly_detector(*m_decoder_up, trace_intel_pt, decoded_thread), + m_tsc_upper_bound(tsc_upper_bound) {} + + /// \param[in] trace_intel_pt + /// The main Trace object that own the PSB block. + /// + /// \param[in] decoder + /// A decoder configured to start and end within the boundaries of the + /// given \p psb_block. + /// + /// \param[in] psb_block + /// The PSB block to decode. + /// + /// \param[in] buffer + /// The raw intel pt trace for this block. + /// + /// \param[in] process + /// The process to decode. It provides the memory image to use for + /// decoding. + /// + /// \param[in] next_block_ip + /// The starting ip at the next PSB block of the same thread if available. + /// + /// \param[in] decoded_thread + /// A \a DecodedThread object where the decoded instructions will be + /// appended to. It might have already some instructions. + static Expected<PSBBlockDecoder> + Create(TraceIntelPT &trace_intel_pt, const PSBBlock &psb_block, + ArrayRef<uint8_t> buffer, Process &process, + std::optional<lldb::addr_t> next_block_ip, + DecodedThread &decoded_thread, + std::optional<DecodedThread::TSC> tsc_upper_bound) { + Expected<PtInsnDecoderUP> decoder_up = + CreateInstructionDecoder(trace_intel_pt, buffer, process); + if (!decoder_up) + return decoder_up.takeError(); - if (IsLibiptError(status)) { - m_decoded_thread.AppendError(IntelPTError(status)); - break; - } + return PSBBlockDecoder(std::move(*decoder_up), psb_block, next_block_ip, + decoded_thread, trace_intel_pt, tsc_upper_bound); + } - DecodeInstructionsAndEvents(status); - } + void DecodePSBBlock() { + int status = pt_insn_sync_forward(m_decoder_up.get()); + assert(status >= 0 && + "Synchronization shouldn't fail because this PSB was previously " + "decoded correctly."); + + // We emit a TSC before a sync event to more easily associate a timestamp to + // the sync event. If present, the current block's TSC would be the first + // TSC we'll see when processing events. + if (m_psb_block.tsc) + m_decoded_thread.NotifyTsc(*m_psb_block.tsc); + + m_decoded_thread.NotifySyncPoint(m_psb_block.psb_offset); + + DecodeInstructionsAndEvents(status); } - /// Decode all the instructions that belong to the same PSB packet given its - /// offset. - void DecodePSB(uint64_t psb_offset) { - int status = pt_insn_sync_set(&m_decoder, psb_offset); - if (IsLibiptError(status)) { - m_decoded_thread.AppendError(IntelPTError(status)); - return; +private: + /// Append an instruction and return \b false if and only if a serious anomaly + /// has been detected. + bool AppendInstructionAndDetectAnomalies(const pt_insn &insn) { + m_decoded_thread.AppendInstruction(insn); + + if (Error err = m_anomaly_detector.DetectAnomaly()) { + m_decoded_thread.AppendCustomError(toString(std::move(err)), + /*fatal=*/true); + return false; } - DecodeInstructionsAndEvents(status, /*stop_on_psb_change=*/true); + return true; } + /// Decode all the instructions and events of the given PSB block. The + /// decoding loop might stop abruptly if an infinite decoding loop is + /// detected. + void DecodeInstructionsAndEvents(int status) { + pt_insn insn; -private: - /// Decode all the instructions and events until an error is found, the end - /// of the trace is reached, or optionally a new PSB is reached. - /// - /// \param[in] status - /// The status that was result of synchronizing to the most recent PSB. - /// - /// \param[in] stop_on_psb_change - /// If \b true, decoding stops if a different PSB is reached. - void DecodeInstructionsAndEvents(int status, - bool stop_on_psb_change = false) { - uint64_t psb_offset; - pt_insn_get_sync_offset(&m_decoder, - &psb_offset); // this can't fail because we got here - - while (ProcessPTEvents(status)) { - if (stop_on_psb_change) { - uint64_t cur_psb_offset; - // this can't fail because we got here - pt_insn_get_sync_offset(&m_decoder, &cur_psb_offset); - if (cur_psb_offset != psb_offset) - break; - } + while (true) { + status = ProcessPTEvents(status); + + if (IsLibiptError(status)) + return; + else if (IsEndOfStream(status)) + break; // The status returned by pt_insn_next will need to be processed // by ProcessPTEvents in the next loop if it is not an error. - pt_insn insn; std::memset(&insn, 0, sizeof insn); - if (IsLibiptError(status = - pt_insn_next(&m_decoder, &insn, sizeof(insn)))) { + status = pt_insn_next(m_decoder_up.get(), &insn, sizeof(insn)); + + if (IsLibiptError(status)) { m_decoded_thread.AppendError(IntelPTError(status, insn.ip)); + return; + } else if (IsEndOfStream(status)) { break; } - m_decoded_thread.AppendInstruction(insn); + + if (!AppendInstructionAndDetectAnomalies(insn)) + return; + } + + // We need to keep querying non-branching instructions until we hit the + // starting point of the next PSB. We won't see events at this point. This + // is based on + // https://github.com/intel/libipt/blob/master/doc/howto_libipt.md#parallel-decode + if (m_next_block_ip && insn.ip != 0) { + while (insn.ip != *m_next_block_ip) { + if (!AppendInstructionAndDetectAnomalies(insn)) + return; + + status = pt_insn_next(m_decoder_up.get(), &insn, sizeof(insn)); + + if (IsLibiptError(status)) { + m_decoded_thread.AppendError(IntelPTError(status, insn.ip)); + return; + } + } } } - /// Move the decoder forward to the next synchronization point (i.e. next PSB - /// packet). + /// Process the TSC of a decoded PT event. Specifically, check if this TSC + /// is below the TSC upper bound for this PSB. If the TSC exceeds the upper + /// bound, return an error to abort decoding. Otherwise add the it to the + /// underlying DecodedThread and decoding should continue as expected. /// - /// Once the decoder is at that synchronization point, it can start decoding - /// instructions. - /// - /// If errors are found, they will be appended to the trace. - /// - /// \return - /// The libipt decoder status after moving to the next PSB. Negative if - /// no PSB was found. - int FindNextSynchronizationPoint() { - // Try to sync the decoder. If it fails, then get the decoder_offset and - // try to sync again from the next synchronization point. If the - // new_decoder_offset is same as decoder_offset then we can't move to the - // next synchronization point. Otherwise, keep resyncing until either end - // of trace stream (eos) is reached or pt_insn_sync_forward() passes. - int status = pt_insn_sync_forward(&m_decoder); - - // We make this call to record any synchronization errors. - if (IsLibiptError(status)) - m_decoded_thread.AppendError(IntelPTError(status)); - - return status; + /// \param[in] tsc + /// The TSC of the a decoded event. + Error ProcessPTEventTSC(DecodedThread::TSC tsc) { + if (m_tsc_upper_bound && tsc >= *m_tsc_upper_bound) { + // This event and all the remaining events of this PSB have a TSC + // outside the range of the "owning" ThreadContinuousExecution. For + // now we drop all of these events/instructions, future work can + // improve upon this by determining the "owning" + // ThreadContinuousExecution of the remaining PSB data. + std::string err_msg = formatv("decoding truncated: TSC {0} exceeds " + "maximum TSC value {1}, will skip decoding" + " the remaining data of the PSB", + tsc, *m_tsc_upper_bound) + .str(); + + uint64_t offset; + int status = pt_insn_get_offset(m_decoder_up.get(), &offset); + if (!IsLibiptError(status)) { + err_msg = formatv("{2} (skipping {0} of {1} bytes)", offset, + m_psb_block.size, err_msg) + .str(); + } + m_decoded_thread.AppendCustomError(err_msg); + return createStringError(inconvertibleErrorCode(), err_msg); + } else { + m_decoded_thread.NotifyTsc(tsc); + return Error::success(); + } } - /// Before querying instructions, we need to query the events associated that - /// instruction e.g. timing events like ptev_tick, or paging events like - /// ptev_paging. + /// Before querying instructions, we need to query the events associated with + /// that instruction, e.g. timing and trace disablement events. /// /// \param[in] status /// The status gotten from the previous instruction decoding or PSB /// synchronization. /// /// \return - /// \b true if no errors were found processing the events. - bool ProcessPTEvents(int status) { - while (status & pts_event_pending) { + /// The pte_status after decoding events. + int ProcessPTEvents(int status) { + while (HasEvents(status)) { pt_event event; - status = pt_insn_event(&m_decoder, &event, sizeof(event)); + std::memset(&event, 0, sizeof event); + status = pt_insn_event(m_decoder_up.get(), &event, sizeof(event)); + if (IsLibiptError(status)) { m_decoded_thread.AppendError(IntelPTError(status)); - return false; + return status; } - if (event.has_tsc) - m_decoded_thread.NotifyTsc(event.tsc); + if (event.has_tsc) { + if (Error err = ProcessPTEventTSC(event.tsc)) { + consumeError(std::move(err)); + return -pte_internal; + } + } switch (event.type) { - case ptev_enabled: - // The kernel started or resumed tracing the program. - break; case ptev_disabled: // The CPU paused tracing the program, e.g. due to ip filtering. m_decoded_thread.AppendEvent(lldb::eTraceEventDisabledHW); @@ -168,7 +536,9 @@ private: break; case ptev_overflow: // The CPU internal buffer had an overflow error and some instructions - // were lost. + // were lost. A OVF packet comes with an FUP packet (harcoded address) + // according to the documentation, so we'll continue seeing instructions + // after this event. m_decoded_thread.AppendError(IntelPTError(-pte_overflow)); break; default: @@ -176,89 +546,40 @@ private: } } - return true; + return status; } private: - pt_insn_decoder &m_decoder; + PtInsnDecoderUP m_decoder_up; + PSBBlock m_psb_block; + std::optional<lldb::addr_t> m_next_block_ip; DecodedThread &m_decoded_thread; + PSBBlockAnomalyDetector m_anomaly_detector; + std::optional<DecodedThread::TSC> m_tsc_upper_bound; }; -/// Callback used by libipt for reading the process memory. -/// -/// More information can be found in -/// https://github.com/intel/libipt/blob/master/doc/man/pt_image_set_callback.3.md -static int ReadProcessMemory(uint8_t *buffer, size_t size, - const pt_asid * /* unused */, uint64_t pc, - void *context) { - Process *process = static_cast<Process *>(context); - - Status error; - int bytes_read = process->ReadMemory(pc, buffer, size, error); - if (error.Fail()) - return -pte_nomap; - return bytes_read; -} - -// RAII deleter for libipt's decoder -auto DecoderDeleter = [](pt_insn_decoder *decoder) { - pt_insn_free_decoder(decoder); -}; - -using PtInsnDecoderUP = - std::unique_ptr<pt_insn_decoder, decltype(DecoderDeleter)>; - -static Expected<PtInsnDecoderUP> -CreateInstructionDecoder(TraceIntelPT &trace_intel_pt, - ArrayRef<uint8_t> buffer) { - Expected<pt_cpu> cpu_info = trace_intel_pt.GetCPUInfo(); - if (!cpu_info) - return cpu_info.takeError(); - - pt_config config; - pt_config_init(&config); - config.cpu = *cpu_info; - int status = pte_ok; - - if (IsLibiptError(status = pt_cpu_errata(&config.errata, &config.cpu))) - return make_error<IntelPTError>(status); - - // The libipt library does not modify the trace buffer, hence the - // following casts are safe. - config.begin = const_cast<uint8_t *>(buffer.data()); - config.end = const_cast<uint8_t *>(buffer.data() + buffer.size()); - - pt_insn_decoder *decoder_ptr = pt_insn_alloc_decoder(&config); - if (!decoder_ptr) - return make_error<IntelPTError>(-pte_nomem); - - return PtInsnDecoderUP(decoder_ptr, DecoderDeleter); -} - -static Error SetupMemoryImage(PtInsnDecoderUP &decoder_up, Process &process) { - pt_image *image = pt_insn_get_image(decoder_up.get()); - - int status = pte_ok; - if (IsLibiptError( - status = pt_image_set_callback(image, ReadProcessMemory, &process))) - return make_error<IntelPTError>(status); - return Error::success(); -} - Error lldb_private::trace_intel_pt::DecodeSingleTraceForThread( DecodedThread &decoded_thread, TraceIntelPT &trace_intel_pt, ArrayRef<uint8_t> buffer) { - Expected<PtInsnDecoderUP> decoder_up = - CreateInstructionDecoder(trace_intel_pt, buffer); - if (!decoder_up) - return decoder_up.takeError(); - - if (Error err = SetupMemoryImage(*decoder_up, - *decoded_thread.GetThread()->GetProcess())) - return err; + Expected<std::vector<PSBBlock>> blocks = + SplitTraceIntoPSBBlock(trace_intel_pt, buffer, /*expect_tscs=*/false); + if (!blocks) + return blocks.takeError(); + + for (size_t i = 0; i < blocks->size(); i++) { + PSBBlock &block = blocks->at(i); + + Expected<PSBBlockDecoder> decoder = PSBBlockDecoder::Create( + trace_intel_pt, block, buffer.slice(block.psb_offset, block.size), + *decoded_thread.GetThread()->GetProcess(), + i + 1 < blocks->size() ? blocks->at(i + 1).starting_ip : None, + decoded_thread, std::nullopt); + if (!decoder) + return decoder.takeError(); + + decoder->DecodePSBBlock(); + } - LibiptDecoder libipt_decoder(*decoder_up.get(), decoded_thread); - libipt_decoder.DecodeUntilEndOfTrace(); return Error::success(); } @@ -266,93 +587,79 @@ Error lldb_private::trace_intel_pt::DecodeSystemWideTraceForThread( DecodedThread &decoded_thread, TraceIntelPT &trace_intel_pt, const DenseMap<lldb::cpu_id_t, llvm::ArrayRef<uint8_t>> &buffers, const std::vector<IntelPTThreadContinousExecution> &executions) { - DenseMap<lldb::cpu_id_t, LibiptDecoder> decoders; - for (auto &cpu_id_buffer : buffers) { - Expected<PtInsnDecoderUP> decoder_up = - CreateInstructionDecoder(trace_intel_pt, cpu_id_buffer.second); - if (!decoder_up) - return decoder_up.takeError(); - - if (Error err = SetupMemoryImage(*decoder_up, - *decoded_thread.GetThread()->GetProcess())) - return err; - - decoders.try_emplace(cpu_id_buffer.first, - LibiptDecoder(*decoder_up->release(), decoded_thread)); - } - bool has_seen_psbs = false; for (size_t i = 0; i < executions.size(); i++) { const IntelPTThreadContinousExecution &execution = executions[i]; - auto variant = execution.thread_execution.variant; - // We report the TSCs we are sure of - switch (variant) { - case ThreadContinuousExecution::Variant::Complete: - decoded_thread.NotifyTsc(execution.thread_execution.tscs.complete.start); - break; - case ThreadContinuousExecution::Variant::OnlyStart: + + // We emit the first valid tsc + if (execution.psb_blocks.empty()) { + decoded_thread.NotifyTsc(execution.thread_execution.GetLowestKnownTSC()); + } else { + assert(execution.psb_blocks.front().tsc && + "per cpu decoding expects TSCs"); decoded_thread.NotifyTsc( - execution.thread_execution.tscs.only_start.start); - break; - default: - break; + std::min(execution.thread_execution.GetLowestKnownTSC(), + *execution.psb_blocks.front().tsc)); } + // We then emit the CPU, which will be correctly associated with a tsc. decoded_thread.NotifyCPU(execution.thread_execution.cpu_id); // If we haven't seen a PSB yet, then it's fine not to show errors if (has_seen_psbs) { - if (execution.intelpt_subtraces.empty()) { + if (execution.psb_blocks.empty()) { decoded_thread.AppendCustomError( - formatv("Unable to find intel pt data for thread " + formatv("Unable to find intel pt data a thread " "execution on cpu id = {0}", execution.thread_execution.cpu_id) .str()); } - // If the first execution is incomplete because it doesn't have a previous - // context switch in its cpu, all good, otherwise we report the error. - if (variant == ThreadContinuousExecution::Variant::OnlyEnd || - variant == ThreadContinuousExecution::Variant::HintedStart) { + // A hinted start is a non-initial execution that doesn't have a switch + // in. An only end is an initial execution that doesn't have a switch in. + // Any of those cases represent a gap because we have seen a PSB before. + if (variant == ThreadContinuousExecution::Variant::HintedStart || + variant == ThreadContinuousExecution::Variant::OnlyEnd) { decoded_thread.AppendCustomError( - formatv("Unable to find the context switch in for the thread " - "execution starting on cpu id = {0}", + formatv("Unable to find the context switch in for a thread " + "execution on cpu id = {0}", execution.thread_execution.cpu_id) .str()); } } - LibiptDecoder &decoder = - decoders.find(execution.thread_execution.cpu_id)->second; - for (const IntelPTThreadSubtrace &intel_pt_execution : - execution.intelpt_subtraces) { - has_seen_psbs = true; - decoder.DecodePSB(intel_pt_execution.psb_offset); - } + for (size_t j = 0; j < execution.psb_blocks.size(); j++) { + const PSBBlock &psb_block = execution.psb_blocks[j]; + + Expected<PSBBlockDecoder> decoder = PSBBlockDecoder::Create( + trace_intel_pt, psb_block, + buffers.lookup(execution.thread_execution.cpu_id) + .slice(psb_block.psb_offset, psb_block.size), + *decoded_thread.GetThread()->GetProcess(), + j + 1 < execution.psb_blocks.size() + ? execution.psb_blocks[j + 1].starting_ip + : None, + decoded_thread, execution.thread_execution.GetEndTSC()); + if (!decoder) + return decoder.takeError(); - // We report the TSCs we are sure of - switch (variant) { - case ThreadContinuousExecution::Variant::Complete: - decoded_thread.NotifyTsc(execution.thread_execution.tscs.complete.end); - break; - case ThreadContinuousExecution::Variant::OnlyEnd: - decoded_thread.NotifyTsc(execution.thread_execution.tscs.only_end.end); - break; - default: - break; + has_seen_psbs = true; + decoder->DecodePSBBlock(); } // If we haven't seen a PSB yet, then it's fine not to show errors if (has_seen_psbs) { - // If the last execution is incomplete because it doesn't have a following - // context switch in its cpu, all good. - if ((variant == ThreadContinuousExecution::Variant::OnlyStart && - i + 1 != executions.size()) || - variant == ThreadContinuousExecution::Variant::HintedEnd) { + // A hinted end is a non-ending execution that doesn't have a switch out. + // An only start is an ending execution that doesn't have a switch out. + // Any of those cases represent a gap if we still have executions to + // process and we have seen a PSB before. + if (i + 1 != executions.size() && + (variant == ThreadContinuousExecution::Variant::OnlyStart || + variant == ThreadContinuousExecution::Variant::HintedEnd)) { decoded_thread.AppendCustomError( - formatv("Unable to find the context switch out for the thread " + formatv("Unable to find the context switch out for a thread " "execution on cpu id = {0}", execution.thread_execution.cpu_id) .str()); @@ -368,60 +675,109 @@ bool IntelPTThreadContinousExecution::operator<( // PSB packet, which is a valid TSC. Otherwise, We query the thread execution // itself for some tsc. auto get_tsc = [](const IntelPTThreadContinousExecution &exec) { - return exec.intelpt_subtraces.empty() - ? exec.thread_execution.GetLowestKnownTSC() - : exec.intelpt_subtraces.front().tsc; + return exec.psb_blocks.empty() ? exec.thread_execution.GetLowestKnownTSC() + : exec.psb_blocks.front().tsc; }; return get_tsc(*this) < get_tsc(o); } -Expected<std::vector<IntelPTThreadSubtrace>> -lldb_private::trace_intel_pt::SplitTraceInContinuousExecutions( - TraceIntelPT &trace_intel_pt, llvm::ArrayRef<uint8_t> buffer) { - Expected<PtInsnDecoderUP> decoder_up = - CreateInstructionDecoder(trace_intel_pt, buffer); +Expected<std::vector<PSBBlock>> +lldb_private::trace_intel_pt::SplitTraceIntoPSBBlock( + TraceIntelPT &trace_intel_pt, llvm::ArrayRef<uint8_t> buffer, + bool expect_tscs) { + // This follows + // https://github.com/intel/libipt/blob/master/doc/howto_libipt.md#parallel-decode + + Expected<PtQueryDecoderUP> decoder_up = + CreateQueryDecoder(trace_intel_pt, buffer); if (!decoder_up) return decoder_up.takeError(); - pt_insn_decoder *decoder = decoder_up.get().get(); + pt_query_decoder *decoder = decoder_up.get().get(); - std::vector<IntelPTThreadSubtrace> executions; + std::vector<PSBBlock> executions; - int status = pte_ok; - while (!IsLibiptError(status = pt_insn_sync_forward(decoder))) { - uint64_t tsc; - if (IsLibiptError(pt_insn_time(decoder, &tsc, nullptr, nullptr))) - return createStringError(inconvertibleErrorCode(), - "intel pt trace doesn't have TSC timestamps"); + while (true) { + uint64_t maybe_ip = LLDB_INVALID_ADDRESS; + int decoding_status = pt_qry_sync_forward(decoder, &maybe_ip); + if (IsLibiptError(decoding_status)) + break; uint64_t psb_offset; - pt_insn_get_sync_offset(decoder, - &psb_offset); // this can't fail because we got here + int offset_status = pt_qry_get_sync_offset(decoder, &psb_offset); + assert(offset_status >= 0 && + "This can't fail because we were able to synchronize"); + + std::optional<uint64_t> ip; + if (!(pts_ip_suppressed & decoding_status)) + ip = maybe_ip; + + std::optional<uint64_t> tsc; + // Now we fetch the first TSC that comes after the PSB. + while (HasEvents(decoding_status)) { + pt_event event; + decoding_status = pt_qry_event(decoder, &event, sizeof(event)); + if (IsLibiptError(decoding_status)) + break; + if (event.has_tsc) { + tsc = event.tsc; + break; + } + } + if (IsLibiptError(decoding_status)) { + // We continue to the next PSB. This effectively merges this PSB with the + // previous one, and that should be fine because this PSB might be the + // direct continuation of the previous thread and it's better to show an + // error in the decoded thread than to hide it. If this is the first PSB, + // we are okay losing it. Besides that, an error at processing events + // means that we wouldn't be able to get any instruction out of it. + continue; + } + + if (expect_tscs && !tsc) + return createStringError(inconvertibleErrorCode(), + "Found a PSB without TSC."); executions.push_back({ psb_offset, tsc, + 0, + ip, }); } + if (!executions.empty()) { + // We now adjust the sizes of each block + executions.back().size = buffer.size() - executions.back().psb_offset; + for (int i = (int)executions.size() - 2; i >= 0; i--) { + executions[i].size = + executions[i + 1].psb_offset - executions[i].psb_offset; + } + } return executions; } -Expected<Optional<uint64_t>> +Expected<std::optional<uint64_t>> lldb_private::trace_intel_pt::FindLowestTSCInTrace(TraceIntelPT &trace_intel_pt, ArrayRef<uint8_t> buffer) { - Expected<PtInsnDecoderUP> decoder_up = - CreateInstructionDecoder(trace_intel_pt, buffer); + Expected<PtQueryDecoderUP> decoder_up = + CreateQueryDecoder(trace_intel_pt, buffer); if (!decoder_up) return decoder_up.takeError(); - pt_insn_decoder *decoder = decoder_up.get().get(); - int status = pte_ok; - if (IsLibiptError(status = pt_insn_sync_forward(decoder))) - return None; + pt_query_decoder *decoder = decoder_up.get().get(); + uint64_t ip = LLDB_INVALID_ADDRESS; + int status = pt_qry_sync_forward(decoder, &ip); + if (IsLibiptError(status)) + return std::nullopt; - uint64_t tsc; - if (IsLibiptError(pt_insn_time(decoder, &tsc, nullptr, nullptr))) - return None; - return tsc; + while (HasEvents(status)) { + pt_event event; + status = pt_qry_event(decoder, &event, sizeof(event)); + if (IsLibiptError(status)) + return std::nullopt; + if (event.has_tsc) + return event.tsc; + } + return std::nullopt; } diff --git a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/LibiptDecoder.h b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/LibiptDecoder.h index 66f3798cd600..bc8a5b963d6f 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/LibiptDecoder.h +++ b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/LibiptDecoder.h @@ -12,19 +12,28 @@ #include "DecodedThread.h" #include "PerfContextSwitchDecoder.h" #include "forward-declarations.h" - #include "intel-pt.h" +#include <optional> namespace lldb_private { namespace trace_intel_pt { -/// This struct represents a point in the intel pt trace that the decoder can start decoding from without errors. -struct IntelPTThreadSubtrace { - /// The memory offset of a PSB packet that is a synchronization point for the decoder. A decoder normally looks first - /// for a PSB packet and then it starts decoding. +/// This struct represents a contiguous section of a trace that starts at a PSB +/// and ends right before the next PSB or the end of the trace. +struct PSBBlock { + /// The memory offset of a PSB packet that is a synchronization point for the + /// decoder. A decoder normally looks first for a PSB packet and then it + /// starts decoding. uint64_t psb_offset; /// The timestamp associated with the PSB packet above. - uint64_t tsc; + std::optional<uint64_t> tsc; + /// Size in bytes of this block + uint64_t size; + /// The first ip for this PSB block. + /// This is \a std::nullopt if tracing was disabled when the PSB block was + /// emitted. This means that eventually there's be an enablement event that + /// will come with an ip. + std::optional<lldb::addr_t> starting_ip; }; /// This struct represents a continuous execution of a thread in a cpu, @@ -32,7 +41,7 @@ struct IntelPTThreadSubtrace { /// that belong to this execution. struct IntelPTThreadContinousExecution { ThreadContinuousExecution thread_execution; - std::vector<IntelPTThreadSubtrace> intelpt_subtraces; + std::vector<PSBBlock> psb_blocks; IntelPTThreadContinousExecution( const ThreadContinuousExecution &thread_execution) @@ -79,28 +88,34 @@ llvm::Error DecodeSystemWideTraceForThread( const llvm::DenseMap<lldb::cpu_id_t, llvm::ArrayRef<uint8_t>> &buffers, const std::vector<IntelPTThreadContinousExecution> &executions); -/// Given an intel pt trace, split it in chunks delimited by PSB packets. Each of these chunks -/// is guaranteed to have been executed continuously. +/// Given an intel pt trace, split it in chunks delimited by PSB packets. Each +/// of these chunks is guaranteed to have been executed continuously. /// /// \param[in] trace_intel_pt -/// The main Trace object that contains all the information related to the trace session. +/// The main Trace object that contains all the information related to the +/// trace session. /// /// \param[in] buffer -/// The intel pt buffer that belongs to a single thread or to a single cpu core. +/// The intel pt buffer that belongs to a single thread or to a single cpu +/// core. +/// +/// \param[in] expect_tscs +/// If \b true, an error is return if a packet without TSC is found. /// /// \return -/// A list of continuous executions sorted by time, or an \a llvm::Error in case of failures. -llvm::Expected<std::vector<IntelPTThreadSubtrace>> -SplitTraceInContinuousExecutions(TraceIntelPT &trace_intel_pt, - llvm::ArrayRef<uint8_t> buffer); +/// A list of continuous executions sorted by time, or an \a llvm::Error in +/// case of failures. +llvm::Expected<std::vector<PSBBlock>> +SplitTraceIntoPSBBlock(TraceIntelPT &trace_intel_pt, + llvm::ArrayRef<uint8_t> buffer, bool expect_tscs); /// Find the lowest TSC in the given trace. /// /// \return -/// The lowest TSC value in this trace if available, \a llvm::None if the +/// The lowest TSC value in this trace if available, \a std::nullopt if the /// trace is empty or the trace contains no timing information, or an \a /// llvm::Error if it was not possible to set up the decoder. -llvm::Expected<llvm::Optional<uint64_t>> +llvm::Expected<std::optional<uint64_t>> FindLowestTSCInTrace(TraceIntelPT &trace_intel_pt, llvm::ArrayRef<uint8_t> buffer); diff --git a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/PerfContextSwitchDecoder.cpp b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/PerfContextSwitchDecoder.cpp index 0c468cf7852f..1aa2a3cc097b 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/PerfContextSwitchDecoder.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/PerfContextSwitchDecoder.cpp @@ -6,6 +6,7 @@ //===----------------------------------------------------------------------===// #include "PerfContextSwitchDecoder.h" +#include <optional> using namespace lldb; using namespace lldb_private; @@ -191,7 +192,7 @@ ThreadContinuousExecution ThreadContinuousExecution::CreateOnlyStartExecution( static Error RecoverExecutionsFromConsecutiveRecords( cpu_id_t cpu_id, const LinuxPerfZeroTscConversion &tsc_conversion, const ContextSwitchRecord ¤t_record, - const Optional<ContextSwitchRecord> &prev_record, + const std::optional<ContextSwitchRecord> &prev_record, std::function<void(const ThreadContinuousExecution &execution)> on_new_execution) { if (!prev_record) { @@ -252,7 +253,7 @@ lldb_private::trace_intel_pt::DecodePerfContextSwitchTrace( size_t offset = 0; auto do_decode = [&]() -> Error { - Optional<ContextSwitchRecord> prev_record; + std::optional<ContextSwitchRecord> prev_record; while (offset < data.size()) { const perf_event_header &perf_record = *reinterpret_cast<const perf_event_header *>(data.data() + offset); diff --git a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/PerfContextSwitchDecoder.h b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/PerfContextSwitchDecoder.h index a16a437e1888..4ea7738810ce 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/PerfContextSwitchDecoder.h +++ b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/PerfContextSwitchDecoder.h @@ -11,9 +11,7 @@ #include "lldb/Utility/TraceIntelPTGDBRemotePackets.h" #include "lldb/lldb-types.h" - #include "llvm/Support/Error.h" - #include <set> #include <vector> diff --git a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TaskTimer.cpp b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TaskTimer.cpp index 9603b25fc81c..55d48ae35ff0 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TaskTimer.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TaskTimer.cpp @@ -1,3 +1,11 @@ +//===-- TaskTimer.cpp -----------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + #include "TaskTimer.h" using namespace lldb; diff --git a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TaskTimer.h b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TaskTimer.h index 2b85ed30334f..fb196e8fc32a 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TaskTimer.h +++ b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TaskTimer.h @@ -10,10 +10,8 @@ #define LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_TASKTIMER_H #include "lldb/lldb-types.h" - #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringRef.h" - #include <chrono> #include <functional> #include <unordered_map> diff --git a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/ThreadDecoder.cpp b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/ThreadDecoder.cpp index 920992d9d636..75d74edd44a1 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/ThreadDecoder.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/ThreadDecoder.cpp @@ -6,13 +6,11 @@ //===----------------------------------------------------------------------===// #include "ThreadDecoder.h" - -#include "llvm/Support/MemoryBuffer.h" - #include "../common/ThreadPostMortemTrace.h" #include "LibiptDecoder.h" #include "TraceIntelPT.h" - +#include "llvm/Support/MemoryBuffer.h" +#include <optional> #include <utility> using namespace lldb; @@ -23,11 +21,12 @@ using namespace llvm; ThreadDecoder::ThreadDecoder(const ThreadSP &thread_sp, TraceIntelPT &trace) : m_thread_sp(thread_sp), m_trace(trace) {} -Expected<Optional<uint64_t>> ThreadDecoder::FindLowestTSC() { - Optional<uint64_t> lowest_tsc; +Expected<std::optional<uint64_t>> ThreadDecoder::FindLowestTSC() { + std::optional<uint64_t> lowest_tsc; Error err = m_trace.OnThreadBufferRead( m_thread_sp->GetID(), [&](llvm::ArrayRef<uint8_t> data) -> llvm::Error { - Expected<Optional<uint64_t>> tsc = FindLowestTSCInTrace(m_trace, data); + Expected<std::optional<uint64_t>> tsc = + FindLowestTSCInTrace(m_trace, data); if (!tsc) return tsc.takeError(); lowest_tsc = *tsc; @@ -39,7 +38,7 @@ Expected<Optional<uint64_t>> ThreadDecoder::FindLowestTSC() { } Expected<DecodedThreadSP> ThreadDecoder::Decode() { - if (!m_decoded_thread.hasValue()) { + if (!m_decoded_thread.has_value()) { if (Expected<DecodedThreadSP> decoded_thread = DoDecode()) { m_decoded_thread = *decoded_thread; } else { @@ -51,19 +50,18 @@ Expected<DecodedThreadSP> ThreadDecoder::Decode() { llvm::Expected<DecodedThreadSP> ThreadDecoder::DoDecode() { return m_trace.GetThreadTimer(m_thread_sp->GetID()) - .TimeTask( - "Decoding instructions", [&]() -> Expected<DecodedThreadSP> { - DecodedThreadSP decoded_thread_sp = std::make_shared<DecodedThread>( - m_thread_sp, m_trace.GetPerfZeroTscConversion()); + .TimeTask("Decoding instructions", [&]() -> Expected<DecodedThreadSP> { + DecodedThreadSP decoded_thread_sp = std::make_shared<DecodedThread>( + m_thread_sp, m_trace.GetPerfZeroTscConversion()); - Error err = m_trace.OnThreadBufferRead( - m_thread_sp->GetID(), [&](llvm::ArrayRef<uint8_t> data) { - return DecodeSingleTraceForThread(*decoded_thread_sp, m_trace, - data); - }); + Error err = m_trace.OnThreadBufferRead( + m_thread_sp->GetID(), [&](llvm::ArrayRef<uint8_t> data) { + return DecodeSingleTraceForThread(*decoded_thread_sp, m_trace, + data); + }); - if (err) - return std::move(err); - return decoded_thread_sp; - }); + if (err) + return std::move(err); + return decoded_thread_sp; + }); } diff --git a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/ThreadDecoder.h b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/ThreadDecoder.h index d580bc4dd335..289915c02810 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/ThreadDecoder.h +++ b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/ThreadDecoder.h @@ -9,12 +9,12 @@ #ifndef LLDB_SOURCE_PLUGINS_TRACE_THREAD_DECODER_H #define LLDB_SOURCE_PLUGINS_TRACE_THREAD_DECODER_H -#include "intel-pt.h" - #include "DecodedThread.h" #include "forward-declarations.h" +#include "intel-pt.h" #include "lldb/Target/Process.h" #include "lldb/Utility/FileSpec.h" +#include <optional> namespace lldb_private { namespace trace_intel_pt { @@ -37,10 +37,10 @@ public: llvm::Expected<DecodedThreadSP> Decode(); /// \return - /// The lowest TSC value in this trace if available, \a llvm::None if the - /// trace is empty or the trace contains no timing information, or an \a - /// llvm::Error if it was not possible to set up the decoder. - llvm::Expected<llvm::Optional<uint64_t>> FindLowestTSC(); + /// The lowest TSC value in this trace if available, \a std::nullopt if + /// the trace is empty or the trace contains no timing information, or an + /// \a llvm::Error if it was not possible to set up the decoder. + llvm::Expected<std::optional<uint64_t>> FindLowestTSC(); ThreadDecoder(const ThreadDecoder &other) = delete; ThreadDecoder &operator=(const ThreadDecoder &other) = delete; @@ -50,7 +50,7 @@ private: lldb::ThreadSP m_thread_sp; TraceIntelPT &m_trace; - llvm::Optional<DecodedThreadSP> m_decoded_thread; + std::optional<DecodedThreadSP> m_decoded_thread; }; } // namespace trace_intel_pt diff --git a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.cpp b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.cpp index a4d86fb48ebe..32e0bad0d19b 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.cpp @@ -9,8 +9,8 @@ #include "TraceCursorIntelPT.h" #include "DecodedThread.h" #include "TraceIntelPT.h" - #include <cstdlib> +#include <optional> using namespace lldb; using namespace lldb_private; @@ -19,12 +19,12 @@ using namespace llvm; TraceCursorIntelPT::TraceCursorIntelPT( ThreadSP thread_sp, DecodedThreadSP decoded_thread_sp, - const Optional<LinuxPerfZeroTscConversion> &tsc_conversion, - Optional<uint64_t> beginning_of_time_nanos) + const std::optional<LinuxPerfZeroTscConversion> &tsc_conversion, + std::optional<uint64_t> beginning_of_time_nanos) : TraceCursor(thread_sp), m_decoded_thread_sp(decoded_thread_sp), m_tsc_conversion(tsc_conversion), m_beginning_of_time_nanos(beginning_of_time_nanos) { - Seek(0, SeekType::End); + Seek(0, lldb::eTraceCursorSeekTypeEnd); } void TraceCursorIntelPT::Next() { @@ -49,7 +49,7 @@ void TraceCursorIntelPT::ClearTimingRangesIfInvalid() { } } -const Optional<DecodedThread::TSCRange> & +const std::optional<DecodedThread::TSCRange> & TraceCursorIntelPT::GetTSCRange() const { if (!m_tsc_range_calculated) { m_tsc_range_calculated = true; @@ -58,7 +58,7 @@ TraceCursorIntelPT::GetTSCRange() const { return m_tsc_range; } -const Optional<DecodedThread::NanosecondsRange> & +const std::optional<DecodedThread::NanosecondsRange> & TraceCursorIntelPT::GetNanosecondsRange() const { if (!m_nanoseconds_range_calculated) { m_nanoseconds_range_calculated = true; @@ -68,15 +68,16 @@ TraceCursorIntelPT::GetNanosecondsRange() const { return m_nanoseconds_range; } -bool TraceCursorIntelPT::Seek(int64_t offset, SeekType origin) { +bool TraceCursorIntelPT::Seek(int64_t offset, + lldb::TraceCursorSeekType origin) { switch (origin) { - case TraceCursor::SeekType::Beginning: + case lldb::eTraceCursorSeekTypeBeginning: m_pos = offset; break; - case TraceCursor::SeekType::End: + case lldb::eTraceCursorSeekTypeEnd: m_pos = m_decoded_thread_sp->GetItemsCount() - 1 + offset; break; - case TraceCursor::SeekType::Current: + case lldb::eTraceCursorSeekTypeCurrent: m_pos += offset; } @@ -102,21 +103,21 @@ lldb::addr_t TraceCursorIntelPT::GetLoadAddress() const { return m_decoded_thread_sp->GetInstructionLoadAddress(m_pos); } -Optional<uint64_t> TraceCursorIntelPT::GetHWClock() const { - if (const Optional<DecodedThread::TSCRange> &range = GetTSCRange()) +std::optional<uint64_t> TraceCursorIntelPT::GetHWClock() const { + if (const std::optional<DecodedThread::TSCRange> &range = GetTSCRange()) return range->tsc; - return None; + return std::nullopt; } -Optional<double> TraceCursorIntelPT::GetWallClockTime() const { - if (const Optional<DecodedThread::NanosecondsRange> &range = +std::optional<double> TraceCursorIntelPT::GetWallClockTime() const { + if (const std::optional<DecodedThread::NanosecondsRange> &range = GetNanosecondsRange()) return range->GetInterpolatedTime(m_pos, *m_beginning_of_time_nanos, *m_tsc_conversion); - return None; + return std::nullopt; } -Optional<lldb::cpu_id_t> TraceCursorIntelPT::GetCPU() const { +lldb::cpu_id_t TraceCursorIntelPT::GetCPU() const { return m_decoded_thread_sp->GetCPUByIndex(m_pos); } @@ -137,3 +138,9 @@ bool TraceCursorIntelPT::HasId(lldb::user_id_t id) const { } user_id_t TraceCursorIntelPT::GetId() const { return m_pos; } + +std::optional<std::string> TraceCursorIntelPT::GetSyncPointMetadata() const { + return formatv("offset = 0x{0:x}", + m_decoded_thread_sp->GetSyncPointOffsetByIndex(m_pos)) + .str(); +} diff --git a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.h b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.h index 3cd9ab831f5e..173426faacce 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.h +++ b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.h @@ -10,6 +10,7 @@ #define LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_TRACECURSORINTELPT_H #include "ThreadDecoder.h" +#include <optional> namespace lldb_private { namespace trace_intel_pt { @@ -18,10 +19,10 @@ class TraceCursorIntelPT : public TraceCursor { public: TraceCursorIntelPT( lldb::ThreadSP thread_sp, DecodedThreadSP decoded_thread_sp, - const llvm::Optional<LinuxPerfZeroTscConversion> &tsc_conversion, - llvm::Optional<uint64_t> beginning_of_time_nanos); + const std::optional<LinuxPerfZeroTscConversion> &tsc_conversion, + std::optional<uint64_t> beginning_of_time_nanos); - bool Seek(int64_t offset, SeekType origin) override; + bool Seek(int64_t offset, lldb::TraceCursorSeekType origin) override; void Next() override; @@ -33,9 +34,9 @@ public: lldb::TraceEvent GetEventType() const override; - llvm::Optional<lldb::cpu_id_t> GetCPU() const override; + lldb::cpu_id_t GetCPU() const override; - llvm::Optional<uint64_t> GetHWClock() const override; + std::optional<uint64_t> GetHWClock() const override; lldb::TraceItemKind GetItemKind() const override; @@ -45,7 +46,9 @@ public: bool HasId(lldb::user_id_t id) const override; - llvm::Optional<double> GetWallClockTime() const override; + std::optional<double> GetWallClockTime() const override; + + std::optional<std::string> GetSyncPointMetadata() const override; private: /// Clear the current TSC and nanoseconds ranges if after moving they are not @@ -53,10 +56,10 @@ private: void ClearTimingRangesIfInvalid(); /// Get or calculate the TSC range that includes the current trace item. - const llvm::Optional<DecodedThread::TSCRange> &GetTSCRange() const; + const std::optional<DecodedThread::TSCRange> &GetTSCRange() const; /// Get or calculate the TSC range that includes the current trace item. - const llvm::Optional<DecodedThread::NanosecondsRange> & + const std::optional<DecodedThread::NanosecondsRange> & GetNanosecondsRange() const; /// Storage of the actual instructions @@ -67,19 +70,19 @@ private: /// Timing information and cached values. /// \{ - /// TSC -> nanos conversion utility. \a None if not available at all. - llvm::Optional<LinuxPerfZeroTscConversion> m_tsc_conversion; - /// Lowest nanoseconds timestamp seen in any thread trace, \a None if not - /// available at all. - llvm::Optional<uint64_t> m_beginning_of_time_nanos; + /// TSC -> nanos conversion utility. \a std::nullopt if not available at all. + std::optional<LinuxPerfZeroTscConversion> m_tsc_conversion; + /// Lowest nanoseconds timestamp seen in any thread trace, \a std::nullopt if + /// not available at all. + std::optional<uint64_t> m_beginning_of_time_nanos; /// Range of trace items with the same TSC that includes the current trace - /// item, \a None if not calculated or not available. - llvm::Optional<DecodedThread::TSCRange> mutable m_tsc_range; + /// item, \a std::nullopt if not calculated or not available. + std::optional<DecodedThread::TSCRange> mutable m_tsc_range; bool mutable m_tsc_range_calculated = false; /// Range of trace items with the same non-interpolated timestamps in - /// nanoseconds that includes the current trace item, \a None if not + /// nanoseconds that includes the current trace item, \a std::nullopt if not /// calculated or not available. - llvm::Optional<DecodedThread::NanosecondsRange> mutable m_nanoseconds_range; + std::optional<DecodedThread::NanosecondsRange> mutable m_nanoseconds_range; bool mutable m_nanoseconds_range_calculated = false; /// \} }; diff --git a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp index f3f0a513e3fa..7b307a095688 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp @@ -8,18 +8,18 @@ #include "TraceIntelPT.h" -#include "TraceCursorIntelPT.h" - #include "../common/ThreadPostMortemTrace.h" #include "CommandObjectTraceStartIntelPT.h" #include "DecodedThread.h" -#include "TraceIntelPTConstants.h" +#include "TraceCursorIntelPT.h" #include "TraceIntelPTBundleLoader.h" #include "TraceIntelPTBundleSaver.h" +#include "TraceIntelPTConstants.h" #include "lldb/Core/PluginManager.h" +#include "lldb/Interpreter/OptionValueProperties.h" #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" -#include "llvm/ADT/None.h" +#include <optional> using namespace lldb; using namespace lldb_private; @@ -40,11 +40,57 @@ TraceIntelPT::GetThreadTraceStartCommand(CommandInterpreter &interpreter) { new CommandObjectThreadTraceStartIntelPT(*this, interpreter)); } +#define LLDB_PROPERTIES_traceintelpt +#include "TraceIntelPTProperties.inc" + +enum { +#define LLDB_PROPERTIES_traceintelpt +#include "TraceIntelPTPropertiesEnum.inc" +}; + +ConstString TraceIntelPT::PluginProperties::GetSettingName() { + return ConstString(TraceIntelPT::GetPluginNameStatic()); +} + +TraceIntelPT::PluginProperties::PluginProperties() : Properties() { + m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName()); + m_collection_sp->Initialize(g_traceintelpt_properties); +} + +uint64_t +TraceIntelPT::PluginProperties::GetInfiniteDecodingLoopVerificationThreshold() { + const uint32_t idx = ePropertyInfiniteDecodingLoopVerificationThreshold; + return m_collection_sp->GetPropertyAtIndexAsUInt64( + nullptr, idx, g_traceintelpt_properties[idx].default_uint_value); +} + +uint64_t TraceIntelPT::PluginProperties::GetExtremelyLargeDecodingThreshold() { + const uint32_t idx = ePropertyExtremelyLargeDecodingThreshold; + return m_collection_sp->GetPropertyAtIndexAsUInt64( + nullptr, idx, g_traceintelpt_properties[idx].default_uint_value); +} + +TraceIntelPT::PluginProperties &TraceIntelPT::GetGlobalProperties() { + static TraceIntelPT::PluginProperties g_settings; + return g_settings; +} + void TraceIntelPT::Initialize() { - PluginManager::RegisterPlugin(GetPluginNameStatic(), "Intel Processor Trace", - CreateInstanceForTraceBundle, - CreateInstanceForLiveProcess, - TraceIntelPTBundleLoader::GetSchema()); + PluginManager::RegisterPlugin( + GetPluginNameStatic(), "Intel Processor Trace", + CreateInstanceForTraceBundle, CreateInstanceForLiveProcess, + TraceIntelPTBundleLoader::GetSchema(), DebuggerInitialize); +} + +void TraceIntelPT::DebuggerInitialize(Debugger &debugger) { + if (!PluginManager::GetSettingForProcessPlugin( + debugger, PluginProperties::GetSettingName())) { + const bool is_global_setting = true; + PluginManager::CreateSettingForTracePlugin( + debugger, GetGlobalProperties().GetValueProperties(), + ConstString("Properties for the intel-pt trace plug-in."), + is_global_setting); + } } void TraceIntelPT::Terminate() { @@ -65,8 +111,7 @@ Expected<FileSpec> TraceIntelPT::SaveToDisk(FileSpec directory, bool compact) { Expected<TraceSP> TraceIntelPT::CreateInstanceForTraceBundle( const json::Value &bundle_description, StringRef bundle_dir, Debugger &debugger) { - return TraceIntelPTBundleLoader(debugger, bundle_description, - bundle_dir) + return TraceIntelPTBundleLoader(debugger, bundle_description, bundle_dir) .Load(); } @@ -80,11 +125,16 @@ TraceIntelPTSP TraceIntelPT::GetSharedPtr() { return std::static_pointer_cast<TraceIntelPT>(shared_from_this()); } +TraceIntelPT::TraceMode TraceIntelPT::GetTraceMode() { return trace_mode; } + TraceIntelPTSP TraceIntelPT::CreateInstanceForPostmortemTrace( - JSONTraceBundleDescription &bundle_description, ArrayRef<ProcessSP> traced_processes, - ArrayRef<ThreadPostMortemTraceSP> traced_threads) { - TraceIntelPTSP trace_sp(new TraceIntelPT(bundle_description, traced_processes)); - trace_sp->m_storage.tsc_conversion = bundle_description.tsc_perf_zero_conversion; + JSONTraceBundleDescription &bundle_description, + ArrayRef<ProcessSP> traced_processes, + ArrayRef<ThreadPostMortemTraceSP> traced_threads, TraceMode trace_mode) { + TraceIntelPTSP trace_sp( + new TraceIntelPT(bundle_description, traced_processes, trace_mode)); + trace_sp->m_storage.tsc_conversion = + bundle_description.tsc_perf_zero_conversion; if (bundle_description.cpus) { std::vector<cpu_id_t> cpus; @@ -99,17 +149,16 @@ TraceIntelPTSP TraceIntelPT::CreateInstanceForPostmortemTrace( cpus.push_back(cpu.id); } - std::vector<tid_t> tids; - for (const JSONProcess &process : bundle_description.processes) - for (const JSONThread &thread : process.threads) - tids.push_back(thread.tid); + if (trace_mode == TraceMode::UserMode) { + trace_sp->m_storage.multicpu_decoder.emplace(trace_sp); + } + } - trace_sp->m_storage.multicpu_decoder.emplace(trace_sp); - } else { + if (!bundle_description.cpus || trace_mode == TraceMode::KernelMode) { for (const ThreadPostMortemTraceSP &thread : traced_threads) { trace_sp->m_storage.thread_decoders.try_emplace( thread->GetID(), std::make_unique<ThreadDecoder>(thread, *trace_sp)); - if (const Optional<FileSpec> &trace_file = thread->GetTraceFile()) { + if (const std::optional<FileSpec> &trace_file = thread->GetTraceFile()) { trace_sp->SetPostMortemThreadDataFile( thread->GetID(), IntelPTDataKinds::kIptTrace, *trace_file); } @@ -122,9 +171,10 @@ TraceIntelPTSP TraceIntelPT::CreateInstanceForPostmortemTrace( } TraceIntelPT::TraceIntelPT(JSONTraceBundleDescription &bundle_description, - ArrayRef<ProcessSP> traced_processes) + ArrayRef<ProcessSP> traced_processes, + TraceMode trace_mode) : Trace(traced_processes, bundle_description.GetCpuIds()), - m_cpu_info(bundle_description.cpu_info) {} + m_cpu_info(bundle_description.cpu_info), trace_mode(trace_mode) {} Expected<DecodedThreadSP> TraceIntelPT::Decode(Thread &thread) { if (const char *error = RefreshLiveProcessState()) @@ -140,19 +190,19 @@ Expected<DecodedThreadSP> TraceIntelPT::Decode(Thread &thread) { return it->second->Decode(); } -Expected<Optional<uint64_t>> TraceIntelPT::FindBeginningOfTimeNanos() { +Expected<std::optional<uint64_t>> TraceIntelPT::FindBeginningOfTimeNanos() { Storage &storage = GetUpdatedStorage(); if (storage.beginning_of_time_nanos_calculated) return storage.beginning_of_time_nanos; storage.beginning_of_time_nanos_calculated = true; if (!storage.tsc_conversion) - return None; + return std::nullopt; - Optional<uint64_t> lowest_tsc; + std::optional<uint64_t> lowest_tsc; if (storage.multicpu_decoder) { - if (Expected<Optional<uint64_t>> tsc = + if (Expected<std::optional<uint64_t>> tsc = storage.multicpu_decoder->FindLowestTSC()) { lowest_tsc = *tsc; } else { @@ -161,7 +211,7 @@ Expected<Optional<uint64_t>> TraceIntelPT::FindBeginningOfTimeNanos() { } for (auto &decoder : storage.thread_decoders) { - Expected<Optional<uint64_t>> tsc = decoder.second->FindLowestTSC(); + Expected<std::optional<uint64_t>> tsc = decoder.second->FindLowestTSC(); if (!tsc) return tsc.takeError(); @@ -176,12 +226,12 @@ Expected<Optional<uint64_t>> TraceIntelPT::FindBeginningOfTimeNanos() { return storage.beginning_of_time_nanos; } -llvm::Expected<lldb::TraceCursorUP> +llvm::Expected<lldb::TraceCursorSP> TraceIntelPT::CreateNewCursor(Thread &thread) { if (Expected<DecodedThreadSP> decoded_thread = Decode(thread)) { - if (Expected<Optional<uint64_t>> beginning_of_time = + if (Expected<std::optional<uint64_t>> beginning_of_time = FindBeginningOfTimeNanos()) - return std::make_unique<TraceCursorIntelPT>( + return std::make_shared<TraceCursorIntelPT>( thread.shared_from_this(), *decoded_thread, m_storage.tsc_conversion, *beginning_of_time); else @@ -215,12 +265,12 @@ void TraceIntelPT::DumpTraceInfo(Thread &thread, Stream &s, bool verbose, DecodedThreadSP &decoded_thread_sp = *decoded_thread_sp_or_err; - Expected<Optional<uint64_t>> raw_size_or_error = GetRawTraceSize(thread); + Expected<std::optional<uint64_t>> raw_size_or_error = GetRawTraceSize(thread); if (!raw_size_or_error) { s.Format(" {0}\n", toString(raw_size_or_error.takeError())); return; } - Optional<uint64_t> raw_size = *raw_size_or_error; + std::optional<uint64_t> raw_size = *raw_size_or_error; s.Format("\n Trace technology: {0}\n", GetPluginName()); @@ -270,6 +320,20 @@ void TraceIntelPT::DumpTraceInfo(Thread &thread, Stream &s, bool verbose, event_to_count.second); } } + // Trace error stats + { + const DecodedThread::ErrorStats &error_stats = + decoded_thread_sp->GetErrorStats(); + s << "\n Errors:\n"; + s.Format(" Number of individual errors: {0}\n", + error_stats.GetTotalCount()); + s.Format(" Number of fatal errors: {0}\n", error_stats.fatal_errors); + for (const auto &[kind, count] : error_stats.libipt_errors) { + s.Format(" Number of libipt errors of kind [{0}]: {1}\n", kind, + count); + } + s.Format(" Number of other errors: {0}\n", error_stats.other_errors); + } if (storage.multicpu_decoder) { s << "\n Multi-cpu decoding:\n"; @@ -285,20 +349,6 @@ void TraceIntelPT::DumpTraceInfo(Thread &thread, Stream &s, bool verbose, s.Format(" Total number of unattributed PSB blocks found: {0}\n", storage.multicpu_decoder->GetUnattributedPSBBlocksCount()); } - - // Errors - { - s << "\n Errors:\n"; - const DecodedThread::LibiptErrorsStats &tsc_errors_stats = - decoded_thread_sp->GetTscErrorsStats(); - s.Format(" Number of TSC decoding errors: {0}\n", - tsc_errors_stats.total_count); - for (const auto &error_message_to_count : - tsc_errors_stats.libipt_errors_counts) { - s.Format(" {0}: {1}\n", error_message_to_count.first, - error_message_to_count.second); - } - } } void TraceIntelPT::DumpTraceInfoAsJson(Thread &thread, Stream &s, @@ -312,7 +362,7 @@ void TraceIntelPT::DumpTraceInfoAsJson(Thread &thread, Stream &s, return; } - Expected<Optional<uint64_t>> raw_size_or_error = GetRawTraceSize(thread); + Expected<std::optional<uint64_t>> raw_size_or_error = GetRawTraceSize(thread); if (!raw_size_or_error) { s << "error: " << toString(raw_size_or_error.takeError()) << "\n"; return; @@ -337,7 +387,7 @@ void TraceIntelPT::DumpTraceInfoAsJson(Thread &thread, Stream &s, uint64_t mem_used = decoded_thread_sp->CalculateApproximateMemoryUsage(); json_str.attributeObject("memoryUsage", [&] { json_str.attribute("totalInBytes", std::to_string(mem_used)); - Optional<double> avg; + std::optional<double> avg; if (insn_len != 0) avg = double(mem_used) / insn_len; json_str.attribute("avgPerItemInBytes", avg); @@ -364,6 +414,19 @@ void TraceIntelPT::DumpTraceInfoAsJson(Thread &thread, Stream &s, } }); }); + // Trace error stats + const DecodedThread::ErrorStats &error_stats = + decoded_thread_sp->GetErrorStats(); + json_str.attributeObject("errors", [&] { + json_str.attribute("totalCount", error_stats.GetTotalCount()); + json_str.attributeObject("libiptErrors", [&] { + for (const auto &[kind, count] : error_stats.libipt_errors) { + json_str.attribute(kind, count); + } + }); + json_str.attribute("fatalErrors", error_stats.fatal_errors); + json_str.attribute("otherErrors", error_stats.other_errors); + }); if (storage.multicpu_decoder) { json_str.attribute( @@ -373,21 +436,8 @@ void TraceIntelPT::DumpTraceInfoAsJson(Thread &thread, Stream &s, "PSBBlocks", storage.multicpu_decoder->GePSBBlocksCountForThread(tid)); } - - // Errors - const DecodedThread::LibiptErrorsStats &tsc_errors_stats = - decoded_thread_sp->GetTscErrorsStats(); - json_str.attributeObject("errorItems", [&] { - json_str.attribute("total", tsc_errors_stats.total_count); - json_str.attributeObject("individualErrors", [&] { - for (const auto &error_message_to_count : - tsc_errors_stats.libipt_errors_counts) { - json_str.attribute(error_message_to_count.first, - error_message_to_count.second); - } - }); - }); }); + json_str.attributeObject("globalStats", [&] { json_str.attributeObject("timingInSeconds", [&] { GetTimer().ForGlobal().ForEachTimedTask( @@ -412,10 +462,10 @@ void TraceIntelPT::DumpTraceInfoAsJson(Thread &thread, Stream &s, }); } -llvm::Expected<Optional<uint64_t>> +llvm::Expected<std::optional<uint64_t>> TraceIntelPT::GetRawTraceSize(Thread &thread) { if (GetUpdatedStorage().multicpu_decoder) - return None; // TODO: calculate the amount of intel pt raw trace associated + return std::nullopt; // TODO: calculate the amount of intel pt raw trace associated // with the given thread. if (GetLiveProcess()) return GetLiveThreadBinaryDataSize(thread.GetID(), @@ -494,7 +544,7 @@ Expected<pt_cpu> TraceIntelPT::GetCPUInfo() { return *m_cpu_info; } -llvm::Optional<LinuxPerfZeroTscConversion> +std::optional<LinuxPerfZeroTscConversion> TraceIntelPT::GetPerfZeroTscConversion() { return GetUpdatedStorage().tsc_conversion; } @@ -557,7 +607,7 @@ bool TraceIntelPT::IsTraced(lldb::tid_t tid) { // documentation file. Similarly, it should match the CLI help messages of the // TraceIntelPTOptions.td file. const char *TraceIntelPT::GetStartConfigurationHelp() { - static Optional<std::string> message; + static std::optional<std::string> message; if (!message) { message.emplace(formatv(R"(Parameters: @@ -591,8 +641,8 @@ const char *TraceIntelPT::GetStartConfigurationHelp() { Error TraceIntelPT::Start(uint64_t ipt_trace_size, uint64_t total_buffer_size_limit, bool enable_tsc, - Optional<uint64_t> psb_period, bool per_cpu_tracing, - bool disable_cgroup_filtering) { + std::optional<uint64_t> psb_period, + bool per_cpu_tracing, bool disable_cgroup_filtering) { TraceIntelPTStartRequest request; request.ipt_trace_size = ipt_trace_size; request.process_buffer_size_limit = total_buffer_size_limit; @@ -608,7 +658,7 @@ Error TraceIntelPT::Start(StructuredData::ObjectSP configuration) { uint64_t ipt_trace_size = kDefaultIptTraceSize; uint64_t process_buffer_size_limit = kDefaultProcessBufferSizeLimit; bool enable_tsc = kDefaultEnableTscValue; - Optional<uint64_t> psb_period = kDefaultPsbPeriod; + std::optional<uint64_t> psb_period = kDefaultPsbPeriod; bool per_cpu_tracing = kDefaultPerCpuTracing; bool disable_cgroup_filtering = kDefaultDisableCgroupFiltering; @@ -634,7 +684,7 @@ Error TraceIntelPT::Start(StructuredData::ObjectSP configuration) { llvm::Error TraceIntelPT::Start(llvm::ArrayRef<lldb::tid_t> tids, uint64_t ipt_trace_size, bool enable_tsc, - Optional<uint64_t> psb_period) { + std::optional<uint64_t> psb_period) { TraceIntelPTStartRequest request; request.ipt_trace_size = ipt_trace_size; request.enable_tsc = enable_tsc; @@ -650,14 +700,14 @@ Error TraceIntelPT::Start(llvm::ArrayRef<lldb::tid_t> tids, StructuredData::ObjectSP configuration) { uint64_t ipt_trace_size = kDefaultIptTraceSize; bool enable_tsc = kDefaultEnableTscValue; - Optional<uint64_t> psb_period = kDefaultPsbPeriod; + std::optional<uint64_t> psb_period = kDefaultPsbPeriod; if (configuration) { if (StructuredData::Dictionary *dict = configuration->GetAsDictionary()) { llvm::StringRef ipt_trace_size_not_parsed; if (dict->GetValueForKeyAsString("iptTraceSize", ipt_trace_size_not_parsed)) { - if (Optional<uint64_t> bytes = + if (std::optional<uint64_t> bytes = ParsingUtils::ParseUserFriendlySizeExpression( ipt_trace_size_not_parsed)) ipt_trace_size = *bytes; diff --git a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h index 7f2c3f8dda5d..20faabdce790 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h +++ b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h @@ -11,18 +11,35 @@ #include "TaskTimer.h" #include "ThreadDecoder.h" -#include "TraceIntelPTMultiCpuDecoder.h" #include "TraceIntelPTBundleLoader.h" - +#include "TraceIntelPTMultiCpuDecoder.h" #include "lldb/Utility/FileSpec.h" #include "lldb/lldb-types.h" #include "llvm/Support/raw_ostream.h" +#include <optional> namespace lldb_private { namespace trace_intel_pt { class TraceIntelPT : public Trace { public: + /// Properties to be used with the `settings` command. + class PluginProperties : public Properties { + public: + static ConstString GetSettingName(); + + PluginProperties(); + + ~PluginProperties() override = default; + + uint64_t GetInfiniteDecodingLoopVerificationThreshold(); + + uint64_t GetExtremelyLargeDecodingThreshold(); + }; + + /// Return the global properties for this trace plug-in. + static PluginProperties &GetGlobalProperties(); + void Dump(Stream *s) const override; llvm::Expected<FileSpec> SaveToDisk(FileSpec directory, @@ -52,15 +69,16 @@ public: /// /// \return /// A trace instance or an error in case of failures. - static llvm::Expected<lldb::TraceSP> - CreateInstanceForTraceBundle(const llvm::json::Value &trace_bundle_description, - llvm::StringRef bundle_dir, - Debugger &debugger); + static llvm::Expected<lldb::TraceSP> CreateInstanceForTraceBundle( + const llvm::json::Value &trace_bundle_description, + llvm::StringRef bundle_dir, Debugger &debugger); static llvm::Expected<lldb::TraceSP> CreateInstanceForLiveProcess(Process &process); static llvm::StringRef GetPluginNameStatic() { return "intel-pt"; } + + static void DebuggerInitialize(Debugger &debugger); /// \} lldb::CommandObjectSP @@ -71,12 +89,12 @@ public: llvm::StringRef GetSchema() override; - llvm::Expected<lldb::TraceCursorUP> CreateNewCursor(Thread &thread) override; + llvm::Expected<lldb::TraceCursorSP> CreateNewCursor(Thread &thread) override; void DumpTraceInfo(Thread &thread, Stream &s, bool verbose, bool json) override; - llvm::Expected<llvm::Optional<uint64_t>> GetRawTraceSize(Thread &thread); + llvm::Expected<std::optional<uint64_t>> GetRawTraceSize(Thread &thread); llvm::Error DoRefreshLiveProcessState(TraceGetStateResponse state, llvm::StringRef json_response) override; @@ -114,7 +132,7 @@ public: /// \a llvm::Error::success if the operation was successful, or /// \a llvm::Error otherwise. llvm::Error Start(uint64_t ipt_trace_size, uint64_t total_buffer_size_limit, - bool enable_tsc, llvm::Optional<uint64_t> psb_period, + bool enable_tsc, std::optional<uint64_t> psb_period, bool m_per_cpu_tracing, bool disable_cgroup_filtering); /// \copydoc Trace::Start @@ -142,7 +160,7 @@ public: /// \a llvm::Error::success if the operation was successful, or /// \a llvm::Error otherwise. llvm::Error Start(llvm::ArrayRef<lldb::tid_t> tids, uint64_t ipt_trace_size, - bool enable_tsc, llvm::Optional<uint64_t> psb_period); + bool enable_tsc, std::optional<uint64_t> psb_period); /// \copydoc Trace::Start llvm::Error Start(llvm::ArrayRef<lldb::tid_t> tids, @@ -157,7 +175,7 @@ public: llvm::Expected<pt_cpu> GetCPUInfo(); /// Get or fetch the values used to convert to and from TSCs and nanos. - llvm::Optional<LinuxPerfZeroTscConversion> GetPerfZeroTscConversion(); + std::optional<LinuxPerfZeroTscConversion> GetPerfZeroTscConversion(); /// \return /// The timer object for this trace. @@ -173,6 +191,10 @@ public: TraceIntelPTSP GetSharedPtr(); + enum class TraceMode { UserMode, KernelMode }; + + TraceMode GetTraceMode(); + private: friend class TraceIntelPTBundleLoader; @@ -184,28 +206,34 @@ private: /// The definition file for the postmortem bundle. /// /// \param[in] traced_processes - /// The processes traced in the live session. + /// The processes traced in the postmortem session. /// /// \param[in] trace_threads - /// The threads traced in the live session. They must belong to the + /// The threads traced in the postmortem session. They must belong to the /// processes mentioned above. /// + /// \param[in] trace_mode + /// The tracing mode of the postmortem session. + /// /// \return /// A TraceIntelPT shared pointer instance. /// \{ static TraceIntelPTSP CreateInstanceForPostmortemTrace( JSONTraceBundleDescription &bundle_description, llvm::ArrayRef<lldb::ProcessSP> traced_processes, - llvm::ArrayRef<lldb::ThreadPostMortemTraceSP> traced_threads); + llvm::ArrayRef<lldb::ThreadPostMortemTraceSP> traced_threads, + TraceMode trace_mode); /// This constructor is used by CreateInstanceForPostmortemTrace to get the /// instance ready before using shared pointers, which is a limitation of C++. TraceIntelPT(JSONTraceBundleDescription &bundle_description, - llvm::ArrayRef<lldb::ProcessSP> traced_processes); + llvm::ArrayRef<lldb::ProcessSP> traced_processes, + TraceMode trace_mode); /// \} /// Constructor for live processes - TraceIntelPT(Process &live_process) : Trace(live_process){}; + TraceIntelPT(Process &live_process) + : Trace(live_process), trace_mode(TraceMode::UserMode){}; /// Decode the trace of the given thread that, i.e. recontruct the traced /// instructions. @@ -222,10 +250,10 @@ private: /// \return /// The lowest timestamp in nanoseconds in all traces if available, \a - /// llvm::None if all the traces were empty or no trace contained no + /// std::nullopt if all the traces were empty or no trace contained no /// timing information, or an \a llvm::Error if it was not possible to set /// up the decoder for some trace. - llvm::Expected<llvm::Optional<uint64_t>> FindBeginningOfTimeNanos(); + llvm::Expected<std::optional<uint64_t>> FindBeginningOfTimeNanos(); // Dump out trace info in JSON format void DumpTraceInfoAsJson(Thread &thread, Stream &s, bool verbose); @@ -235,25 +263,28 @@ private: /// This variable should only be accessed directly by constructores or live /// process data refreshers. struct Storage { - llvm::Optional<TraceIntelPTMultiCpuDecoder> multicpu_decoder; + std::optional<TraceIntelPTMultiCpuDecoder> multicpu_decoder; /// These decoders are used for the non-per-cpu case llvm::DenseMap<lldb::tid_t, std::unique_ptr<ThreadDecoder>> thread_decoders; /// Helper variable used to track long running operations for telemetry. TaskTimer task_timer; /// It is provided by either a trace bundle or a live process to convert TSC /// counters to and from nanos. It might not be available on all hosts. - llvm::Optional<LinuxPerfZeroTscConversion> tsc_conversion; - llvm::Optional<uint64_t> beginning_of_time_nanos; + std::optional<LinuxPerfZeroTscConversion> tsc_conversion; + std::optional<uint64_t> beginning_of_time_nanos; bool beginning_of_time_nanos_calculated = false; } m_storage; /// It is provided by either a trace bundle or a live process' "cpuInfo" /// binary data. We don't put it in the Storage because this variable doesn't /// change. - llvm::Optional<pt_cpu> m_cpu_info; + std::optional<pt_cpu> m_cpu_info; /// Get the storage after refreshing the data in the case of a live process. Storage &GetUpdatedStorage(); + + /// The tracing mode of post mortem trace. + TraceMode trace_mode; }; } // namespace trace_intel_pt diff --git a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTBundleLoader.cpp b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTBundleLoader.cpp index 3715e46c659c..e183e592986a 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTBundleLoader.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTBundleLoader.cpp @@ -10,12 +10,13 @@ #include "../common/ThreadPostMortemTrace.h" #include "TraceIntelPT.h" +#include "TraceIntelPTConstants.h" #include "TraceIntelPTJSONStructs.h" - #include "lldb/Core/Debugger.h" #include "lldb/Core/Module.h" #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" +#include <optional> using namespace lldb; using namespace lldb_private; @@ -30,18 +31,18 @@ FileSpec TraceIntelPTBundleLoader::NormalizePath(const std::string &path) { } Error TraceIntelPTBundleLoader::ParseModule(Target &target, - const JSONModule &module) { + const JSONModule &module) { auto do_parse = [&]() -> Error { FileSpec system_file_spec(module.system_path); - FileSpec local_file_spec(module.file.hasValue() ? *module.file - : module.system_path); + FileSpec local_file_spec(module.file.has_value() ? *module.file + : module.system_path); ModuleSpec module_spec; module_spec.GetFileSpec() = local_file_spec; module_spec.GetPlatformFileSpec() = system_file_spec; - if (module.uuid.hasValue()) + if (module.uuid.has_value()) module_spec.GetUUID().SetFromStringRef(*module.uuid); Status error; @@ -64,7 +65,7 @@ Error TraceIntelPTBundleLoader::ParseModule(Target &target, } Error TraceIntelPTBundleLoader::CreateJSONError(json::Path::Root &root, - const json::Value &value) { + const json::Value &value) { std::string err; raw_string_ostream os(err); root.printErrorContext(value, os); @@ -75,10 +76,10 @@ Error TraceIntelPTBundleLoader::CreateJSONError(json::Path::Root &root, ThreadPostMortemTraceSP TraceIntelPTBundleLoader::ParseThread(Process &process, - const JSONThread &thread) { + const JSONThread &thread) { lldb::tid_t tid = static_cast<lldb::tid_t>(thread.tid); - Optional<FileSpec> trace_file; + std::optional<FileSpec> trace_file; if (thread.ipt_trace) trace_file = FileSpec(*thread.ipt_trace); @@ -89,11 +90,11 @@ TraceIntelPTBundleLoader::ParseThread(Process &process, } Expected<TraceIntelPTBundleLoader::ParsedProcess> -TraceIntelPTBundleLoader::ParseProcess(const JSONProcess &process) { +TraceIntelPTBundleLoader::CreateEmptyProcess(lldb::pid_t pid, + llvm::StringRef triple) { TargetSP target_sp; Status error = m_debugger.GetTargetList().CreateTarget( - m_debugger, /*user_exe_path*/ StringRef(), process.triple.value_or(""), - eLoadDependentsNo, + m_debugger, /*user_exe_path*/ StringRef(), triple, eLoadDependentsNo, /*platform_options*/ nullptr, target_sp); if (!target_sp) @@ -107,13 +108,26 @@ TraceIntelPTBundleLoader::ParseProcess(const JSONProcess &process) { /*crash_file*/ nullptr, /*can_connect*/ false); - process_sp->SetID(static_cast<lldb::pid_t>(process.pid)); + process_sp->SetID(static_cast<lldb::pid_t>(pid)); + + return parsed_process; +} + +Expected<TraceIntelPTBundleLoader::ParsedProcess> +TraceIntelPTBundleLoader::ParseProcess(const JSONProcess &process) { + Expected<ParsedProcess> parsed_process = + CreateEmptyProcess(process.pid, process.triple.value_or("")); + + if (!parsed_process) + return parsed_process.takeError(); + + ProcessSP process_sp = parsed_process->target_sp->GetProcessSP(); for (const JSONThread &thread : process.threads) - parsed_process.threads.push_back(ParseThread(*process_sp, thread)); + parsed_process->threads.push_back(ParseThread(*process_sp, thread)); for (const JSONModule &module : process.modules) - if (Error err = ParseModule(*target_sp, module)) + if (Error err = ParseModule(*parsed_process->target_sp, module)) return std::move(err); if (!process.threads.empty()) @@ -127,6 +141,57 @@ TraceIntelPTBundleLoader::ParseProcess(const JSONProcess &process) { return parsed_process; } +Expected<TraceIntelPTBundleLoader::ParsedProcess> +TraceIntelPTBundleLoader::ParseKernel( + const JSONTraceBundleDescription &bundle_description) { + Expected<ParsedProcess> parsed_process = + CreateEmptyProcess(kDefaultKernelProcessID, ""); + + if (!parsed_process) + return parsed_process.takeError(); + + ProcessSP process_sp = parsed_process->target_sp->GetProcessSP(); + + // Add cpus as fake threads + for (const JSONCpu &cpu : *bundle_description.cpus) { + ThreadPostMortemTraceSP thread_sp = std::make_shared<ThreadPostMortemTrace>( + *process_sp, static_cast<lldb::tid_t>(cpu.id), FileSpec(cpu.ipt_trace)); + thread_sp->SetName(formatv("kernel_cpu_{0}", cpu.id).str().c_str()); + process_sp->GetThreadList().AddThread(thread_sp); + parsed_process->threads.push_back(thread_sp); + } + + // Add kernel image + FileSpec file_spec(bundle_description.kernel->file); + ModuleSpec module_spec; + module_spec.GetFileSpec() = file_spec; + + Status error; + ModuleSP module_sp = + parsed_process->target_sp->GetOrCreateModule(module_spec, false, &error); + + if (error.Fail()) + return error.ToError(); + + lldb::addr_t load_address = + bundle_description.kernel->load_address + ? bundle_description.kernel->load_address->value + : kDefaultKernelLoadAddress; + + bool load_addr_changed = false; + module_sp->SetLoadAddress(*parsed_process->target_sp, load_address, false, + load_addr_changed); + + process_sp->GetThreadList().SetSelectedThreadByIndexID(0); + + // We invoke DidAttach to create a correct stopped state for the process and + // its threads. + ArchSpec process_arch; + process_sp->DidAttach(process_arch); + + return parsed_process; +} + Expected<std::vector<TraceIntelPTBundleLoader::ParsedProcess>> TraceIntelPTBundleLoader::LoadBundle( const JSONTraceBundleDescription &bundle_description) { @@ -139,11 +204,21 @@ TraceIntelPTBundleLoader::LoadBundle( return std::move(err); }; - for (const JSONProcess &process : bundle_description.processes) { - if (Expected<ParsedProcess> parsed_process = ParseProcess(process)) - parsed_processes.push_back(std::move(*parsed_process)); + if (bundle_description.processes) { + for (const JSONProcess &process : *bundle_description.processes) { + if (Expected<ParsedProcess> parsed_process = ParseProcess(process)) + parsed_processes.push_back(std::move(*parsed_process)); + else + return HandleError(parsed_process.takeError()); + } + } + + if (bundle_description.kernel) { + if (Expected<ParsedProcess> kernel_process = + ParseKernel(bundle_description)) + parsed_processes.push_back(std::move(*kernel_process)); else - return HandleError(parsed_process.takeError()); + return HandleError(kernel_process.takeError()); } return parsed_processes; @@ -162,11 +237,13 @@ StringRef TraceIntelPTBundleLoader::GetSchema() { "model": integer, "stepping": integer }, - "processes": [ + "processes?": [ { "pid": integer, "triple"?: string, // Optional clang/llvm target triple. + // This must be provided if the trace will be created not using the + // CLI or on a machine other than where the target was traced. "threads": [ // A list of known threads for the given process. When context switch // data is provided, LLDB will automatically create threads for the @@ -213,22 +290,36 @@ StringRef TraceIntelPTBundleLoader::GetSchema() { "timeMult": integer, "timeShift": integer, "timeZero": integer | string decimal | hex string, + }, + "kernel"?: { + "loadAddress"?: integer | string decimal | hex string, + // Kernel's image load address. Defaults to 0xffffffff81000000, which + // is a load address of x86 architecture if KASLR is not enabled. + "file": string, + // Path to the kernel image. } } Notes: -- All paths are either absolute or relative to folder containing the bundle description file. +- All paths are either absolute or relative to folder containing the bundle + description file. - "cpus" is provided if and only if processes[].threads[].iptTrace is not provided. - "tscPerfZeroConversion" must be provided if "cpus" is provided. - })"; +- If "kernel" is provided, then the "processes" section must be empty or not + passed at all, and the "cpus" section must be provided. This configuration + indicates that the kernel was traced and user processes weren't. Besides + that, the kernel is treated as a single process with one thread per CPU + core. This doesn't handle actual kernel threads, but instead treats + all the instructions executed by the kernel on each core as an + individual thread.})"; } return schema; } Error TraceIntelPTBundleLoader::AugmentThreadsFromContextSwitches( JSONTraceBundleDescription &bundle_description) { - if (!bundle_description.cpus) + if (!bundle_description.cpus || !bundle_description.processes) return Error::success(); if (!bundle_description.tsc_perf_zero_conversion) @@ -239,7 +330,7 @@ Error TraceIntelPTBundleLoader::AugmentThreadsFromContextSwitches( DenseMap<lldb::pid_t, JSONProcess *> indexed_processes; DenseMap<JSONProcess *, DenseSet<tid_t>> indexed_threads; - for (JSONProcess &process : bundle_description.processes) { + for (JSONProcess &process : *bundle_description.processes) { indexed_processes[process.pid] = &process; for (JSONThread &thread : process.threads) indexed_threads[&process].insert(thread.tid); @@ -260,8 +351,8 @@ Error TraceIntelPTBundleLoader::AugmentThreadsFromContextSwitches( FileSpec(cpu.context_switch_trace), [&](ArrayRef<uint8_t> data) -> Error { Expected<std::vector<ThreadContinuousExecution>> executions = - DecodePerfContextSwitchTrace(data, cpu.id, - *bundle_description.tsc_perf_zero_conversion); + DecodePerfContextSwitchTrace( + data, cpu.id, *bundle_description.tsc_perf_zero_conversion); if (!executions) return executions.takeError(); for (const ThreadContinuousExecution &execution : *executions) @@ -275,7 +366,8 @@ Error TraceIntelPTBundleLoader::AugmentThreadsFromContextSwitches( } Expected<TraceSP> TraceIntelPTBundleLoader::CreateTraceIntelPTInstance( - JSONTraceBundleDescription &bundle_description, std::vector<ParsedProcess> &parsed_processes) { + JSONTraceBundleDescription &bundle_description, + std::vector<ParsedProcess> &parsed_processes) { std::vector<ThreadPostMortemTraceSP> threads; std::vector<ProcessSP> processes; for (const ParsedProcess &parsed_process : parsed_processes) { @@ -284,8 +376,12 @@ Expected<TraceSP> TraceIntelPTBundleLoader::CreateTraceIntelPTInstance( parsed_process.threads.end()); } + TraceIntelPT::TraceMode trace_mode = bundle_description.kernel + ? TraceIntelPT::TraceMode::KernelMode + : TraceIntelPT::TraceMode::UserMode; + TraceSP trace_instance = TraceIntelPT::CreateInstanceForPostmortemTrace( - bundle_description, processes, threads); + bundle_description, processes, threads, trace_mode); for (const ParsedProcess &parsed_process : parsed_processes) parsed_process.target_sp->SetTrace(trace_instance); @@ -294,15 +390,17 @@ Expected<TraceSP> TraceIntelPTBundleLoader::CreateTraceIntelPTInstance( void TraceIntelPTBundleLoader::NormalizeAllPaths( JSONTraceBundleDescription &bundle_description) { - for (JSONProcess &process : bundle_description.processes) { - for (JSONModule &module : process.modules) { - module.system_path = NormalizePath(module.system_path).GetPath(); - if (module.file) - module.file = NormalizePath(*module.file).GetPath(); - } - for (JSONThread &thread : process.threads) { - if (thread.ipt_trace) - thread.ipt_trace = NormalizePath(*thread.ipt_trace).GetPath(); + if (bundle_description.processes) { + for (JSONProcess &process : *bundle_description.processes) { + for (JSONModule &module : process.modules) { + module.system_path = NormalizePath(module.system_path).GetPath(); + if (module.file) + module.file = NormalizePath(*module.file).GetPath(); + } + for (JSONThread &thread : process.threads) { + if (thread.ipt_trace) + thread.ipt_trace = NormalizePath(*thread.ipt_trace).GetPath(); + } } } if (bundle_description.cpus) { @@ -312,6 +410,10 @@ void TraceIntelPTBundleLoader::NormalizeAllPaths( cpu.ipt_trace = NormalizePath(cpu.ipt_trace).GetPath(); } } + if (bundle_description.kernel) { + bundle_description.kernel->file = + NormalizePath(bundle_description.kernel->file).GetPath(); + } } Expected<TraceSP> TraceIntelPTBundleLoader::Load() { diff --git a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTBundleLoader.h b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTBundleLoader.h index b0b926e1b7d4..691a3f4fa08c 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTBundleLoader.h +++ b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTBundleLoader.h @@ -29,13 +29,14 @@ public: /// The debugger that will own the targets to create. /// /// \param[in] bundle_description - /// The JSON description of a trace bundle that follows the schema of the intel pt trace plug-in. + /// The JSON description of a trace bundle that follows the schema of the + /// intel pt trace plug-in. /// /// \param[in] bundle_dir /// The folder where the trace bundle is located. TraceIntelPTBundleLoader(Debugger &debugger, - const llvm::json::Value &bundle_description, - llvm::StringRef bundle_dir) + const llvm::json::Value &bundle_description, + llvm::StringRef bundle_dir) : m_debugger(debugger), m_bundle_description(bundle_description), m_bundle_dir(bundle_dir) {} @@ -47,8 +48,8 @@ public: /// Target objects. In case of an error, no targets are created. /// /// \return - /// A \a lldb::TraceSP instance created according to the trace bundle information. In case of - /// errors, return a null pointer. + /// A \a lldb::TraceSP instance created according to the trace bundle + /// information. In case of errors, return a null pointer. llvm::Expected<lldb::TraceSP> Load(); private: @@ -66,6 +67,10 @@ private: CreateTraceIntelPTInstance(JSONTraceBundleDescription &bundle_description, std::vector<ParsedProcess> &parsed_processes); + /// Create an empty Process object with given pid and target. + llvm::Expected<ParsedProcess> CreateEmptyProcess(lldb::pid_t pid, + llvm::StringRef triple); + /// Create the corresponding Threads and Process objects given the JSON /// process definition. /// @@ -73,9 +78,14 @@ private: /// The JSON process definition llvm::Expected<ParsedProcess> ParseProcess(const JSONProcess &process); - /// Create a module associated with the given \p target using the definition from \p module. + /// Create a module associated with the given \p target using the definition + /// from \p module. llvm::Error ParseModule(Target &target, const JSONModule &module); + /// Create a kernel process and cpu threads given the JSON kernel definition. + llvm::Expected<ParsedProcess> + ParseKernel(const JSONTraceBundleDescription &bundle_description); + /// Create a user-friendly error message upon a JSON-parsing failure using the /// \a json::ObjectMapper functionality. /// @@ -102,10 +112,11 @@ private: /// \return /// An \a llvm::Error in case if failures, or \a llvm::Error::success /// otherwise. - llvm::Error AugmentThreadsFromContextSwitches(JSONTraceBundleDescription &bundle_description); + llvm::Error AugmentThreadsFromContextSwitches( + JSONTraceBundleDescription &bundle_description); - /// Modifiy the bundle description by normalizing all the paths relative to the - /// session file directory. + /// Modifiy the bundle description by normalizing all the paths relative to + /// the session file directory. void NormalizeAllPaths(JSONTraceBundleDescription &bundle_description); Debugger &m_debugger; @@ -116,5 +127,4 @@ private: } // namespace trace_intel_pt } // namespace lldb_private - #endif // LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_TRACEINTELPTBUNDLELOADER_H diff --git a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTBundleSaver.cpp b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTBundleSaver.cpp index 8be70dc2139b..a09bb372bb01 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTBundleSaver.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTBundleSaver.cpp @@ -7,11 +7,10 @@ //===----------------------------------------------------------------------===// #include "TraceIntelPTBundleSaver.h" - #include "PerfContextSwitchDecoder.h" #include "TraceIntelPT.h" +#include "TraceIntelPTConstants.h" #include "TraceIntelPTJSONStructs.h" - #include "lldb/Core/Module.h" #include "lldb/Core/ModuleList.h" #include "lldb/Target/Process.h" @@ -19,12 +18,11 @@ #include "lldb/Target/Target.h" #include "lldb/Target/ThreadList.h" #include "lldb/lldb-types.h" -#include "llvm/ADT/None.h" #include "llvm/Support/Error.h" #include "llvm/Support/JSON.h" - #include <fstream> #include <iostream> +#include <optional> #include <sstream> #include <string> @@ -103,7 +101,7 @@ BuildThreadsSection(Process &process, FileSpec directory) { FileSpec threads_dir = directory; threads_dir.AppendPathComponent("threads"); - sys::fs::create_directories(threads_dir.GetCString()); + sys::fs::create_directories(threads_dir.GetPath().c_str()); for (ThreadSP thread_sp : process.Threads()) { lldb::tid_t tid = thread_sp->GetID(); @@ -133,10 +131,10 @@ BuildThreadsSection(Process &process, FileSpec directory) { } /// \return -/// an \a llvm::Error in case of failures, \a None if the trace is not written -/// to disk because the trace is empty and the \p compact flag is present, or -/// the FileSpec of the trace file on disk. -static Expected<Optional<FileSpec>> +/// an \a llvm::Error in case of failures, \a std::nullopt if the trace is not +/// written to disk because the trace is empty and the \p compact flag is +/// present, or the FileSpec of the trace file on disk. +static Expected<std::optional<FileSpec>> WriteContextSwitchTrace(TraceIntelPT &trace_ipt, lldb::cpu_id_t cpu_id, const FileSpec &cpus_dir, bool compact) { FileSpec output_context_switch_trace = cpus_dir; @@ -172,7 +170,7 @@ WriteContextSwitchTrace(TraceIntelPT &trace_ipt, lldb::cpu_id_t cpu_id, return std::move(err); if (should_skip) - return None; + return std::nullopt; return output_context_switch_trace; } @@ -192,20 +190,20 @@ static Expected<FileSpec> WriteIntelPTTrace(TraceIntelPT &trace_ipt, return output_trace; } -static llvm::Expected<llvm::Optional<std::vector<JSONCpu>>> +static llvm::Expected<std::optional<std::vector<JSONCpu>>> BuildCpusSection(TraceIntelPT &trace_ipt, FileSpec directory, bool compact) { if (trace_ipt.GetTracedCpus().empty()) - return None; + return std::nullopt; std::vector<JSONCpu> json_cpus; FileSpec cpus_dir = directory; cpus_dir.AppendPathComponent("cpus"); - sys::fs::create_directories(cpus_dir.GetCString()); + sys::fs::create_directories(cpus_dir.GetPath().c_str()); for (lldb::cpu_id_t cpu_id : trace_ipt.GetTracedCpus()) { JSONCpu json_cpu; json_cpu.id = cpu_id; - Expected<Optional<FileSpec>> context_switch_trace_path = + Expected<std::optional<FileSpec>> context_switch_trace_path = WriteContextSwitchTrace(trace_ipt, cpu_id, cpus_dir, compact); if (!context_switch_trace_path) return context_switch_trace_path.takeError(); @@ -335,6 +333,25 @@ BuildProcessesSection(TraceIntelPT &trace_ipt, const FileSpec &directory) { return processes; } +static llvm::Expected<JSONKernel> +BuildKernelSection(TraceIntelPT &trace_ipt, const FileSpec &directory) { + JSONKernel json_kernel; + std::vector<Process *> processes = trace_ipt.GetAllProcesses(); + Process *kernel_process = processes[0]; + + assert(processes.size() == 1 && "User processeses exist in kernel mode"); + assert(kernel_process->GetID() == kDefaultKernelProcessID && + "Kernel process not exist"); + + Expected<std::vector<JSONModule>> json_modules = + BuildModulesSection(*kernel_process, directory); + if (!json_modules) + return json_modules.takeError(); + + JSONModule kernel_image = json_modules.get()[0]; + return JSONKernel{kernel_image.load_address, kernel_image.system_path}; +} + Expected<FileSpec> TraceIntelPTBundleSaver::SaveToDisk(TraceIntelPT &trace_ipt, FileSpec directory, bool compact) { @@ -348,20 +365,38 @@ Expected<FileSpec> TraceIntelPTBundleSaver::SaveToDisk(TraceIntelPT &trace_ipt, FileSystem::Instance().Resolve(directory); - Expected<std::vector<JSONProcess>> json_processes = - BuildProcessesSection(trace_ipt, directory); - - if (!json_processes) - return json_processes.takeError(); - - Expected<Optional<std::vector<JSONCpu>>> json_cpus = + Expected<std::optional<std::vector<JSONCpu>>> json_cpus = BuildCpusSection(trace_ipt, directory, compact); if (!json_cpus) return json_cpus.takeError(); - JSONTraceBundleDescription json_intel_pt_bundle_desc{"intel-pt", *cpu_info, *json_processes, - *json_cpus, - trace_ipt.GetPerfZeroTscConversion()}; + std::optional<std::vector<JSONProcess>> json_processes; + std::optional<JSONKernel> json_kernel; + + if (trace_ipt.GetTraceMode() == TraceIntelPT::TraceMode::KernelMode) { + Expected<std::optional<JSONKernel>> exp_json_kernel = + BuildKernelSection(trace_ipt, directory); + if (!exp_json_kernel) + return exp_json_kernel.takeError(); + else + json_kernel = *exp_json_kernel; + } else { + Expected<std::optional<std::vector<JSONProcess>>> exp_json_processes = + BuildProcessesSection(trace_ipt, directory); + if (!exp_json_processes) + return exp_json_processes.takeError(); + else + json_processes = *exp_json_processes; + } + + JSONTraceBundleDescription json_intel_pt_bundle_desc{ + "intel-pt", + *cpu_info, + json_processes, + *json_cpus, + trace_ipt.GetPerfZeroTscConversion(), + json_kernel}; - return SaveTraceBundleDescription(toJSON(json_intel_pt_bundle_desc), directory); + return SaveTraceBundleDescription(toJSON(json_intel_pt_bundle_desc), + directory); } diff --git a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTBundleSaver.h b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTBundleSaver.h index 7224636f0c74..f5a0301217c7 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTBundleSaver.h +++ b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTBundleSaver.h @@ -10,7 +10,6 @@ #define LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_TRACEINTELPTBUNDLESAVER_H #include "TraceIntelPT.h" - #include "TraceIntelPTJSONStructs.h" namespace lldb_private { diff --git a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTConstants.h b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTConstants.h index 43c86fca3425..e80f512457cf 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTConstants.h +++ b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTConstants.h @@ -9,9 +9,9 @@ #ifndef LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_CONSTANTS_H #define LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_CONSTANTS_H +#include "lldb/lldb-types.h" #include <cstddef> - -#include <llvm/ADT/Optional.h> +#include <optional> namespace lldb_private { namespace trace_intel_pt { @@ -19,10 +19,17 @@ namespace trace_intel_pt { const size_t kDefaultIptTraceSize = 4 * 1024; // 4KB const size_t kDefaultProcessBufferSizeLimit = 5 * 1024 * 1024; // 500MB const bool kDefaultEnableTscValue = false; -const llvm::Optional<size_t> kDefaultPsbPeriod = llvm::None; +const std::optional<size_t> kDefaultPsbPeriod; const bool kDefaultPerCpuTracing = false; const bool kDefaultDisableCgroupFiltering = false; +// Physical address where the kernel is loaded in x86 architecture. Refer to +// https://github.com/torvalds/linux/blob/master/Documentation/x86/x86_64/mm.rst +// for the start address of kernel text section. +// The kernel entry point is 0x1000000 by default when KASLR is disabled. +const lldb::addr_t kDefaultKernelLoadAddress = 0xffffffff81000000; +const lldb::pid_t kDefaultKernelProcessID = 1; + } // namespace trace_intel_pt } // namespace lldb_private diff --git a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTJSONStructs.cpp b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTJSONStructs.cpp index ca9813652d7a..52ca69420587 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTJSONStructs.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTJSONStructs.cpp @@ -7,8 +7,8 @@ //===----------------------------------------------------------------------===// #include "TraceIntelPTJSONStructs.h" - #include "llvm/Support/JSON.h" +#include <optional> #include <string> using namespace lldb; @@ -20,9 +20,10 @@ using namespace llvm::json; namespace lldb_private { namespace trace_intel_pt { -Optional<std::vector<lldb::cpu_id_t>> JSONTraceBundleDescription::GetCpuIds() { +std::optional<std::vector<lldb::cpu_id_t>> +JSONTraceBundleDescription::GetCpuIds() { if (!cpus) - return None; + return std::nullopt; std::vector<lldb::cpu_id_t> cpu_ids; for (const JSONCpu &cpu : *cpus) cpu_ids.push_back(cpu.id); @@ -116,21 +117,41 @@ bool fromJSON(const json::Value &value, pt_cpu &cpu_info, Path path) { return true; } +json::Value toJSON(const JSONKernel &kernel) { + json::Object json_module; + if (kernel.load_address) + json_module["loadAddress"] = toJSON(*kernel.load_address, true); + json_module["file"] = kernel.file; + return std::move(json_module); +} + +bool fromJSON(const json::Value &value, JSONKernel &kernel, Path path) { + ObjectMapper o(value, path); + return o && o.map("loadAddress", kernel.load_address) && + o.map("file", kernel.file); +} + json::Value toJSON(const JSONTraceBundleDescription &bundle_description) { - return Object{{"type", bundle_description.type}, - {"processes", bundle_description.processes}, - // We have to do this because the compiler fails at doing it - // automatically because pt_cpu is not in a namespace - {"cpuInfo", toJSON(bundle_description.cpu_info)}, - {"cpus", bundle_description.cpus}, - {"tscPerfZeroConversion", bundle_description.tsc_perf_zero_conversion}}; + return Object{ + {"type", bundle_description.type}, + {"processes", bundle_description.processes}, + // We have to do this because the compiler fails at doing it + // automatically because pt_cpu is not in a namespace + {"cpuInfo", toJSON(bundle_description.cpu_info)}, + {"cpus", bundle_description.cpus}, + {"tscPerfZeroConversion", bundle_description.tsc_perf_zero_conversion}, + {"kernel", bundle_description.kernel}}; } -bool fromJSON(const json::Value &value, JSONTraceBundleDescription &bundle_description, Path path) { +bool fromJSON(const json::Value &value, + JSONTraceBundleDescription &bundle_description, Path path) { ObjectMapper o(value, path); if (!(o && o.map("processes", bundle_description.processes) && - o.map("type", bundle_description.type) && o.map("cpus", bundle_description.cpus) && - o.map("tscPerfZeroConversion", bundle_description.tsc_perf_zero_conversion))) + o.map("type", bundle_description.type) && + o.map("cpus", bundle_description.cpus) && + o.map("tscPerfZeroConversion", + bundle_description.tsc_perf_zero_conversion) && + o.map("kernel", bundle_description.kernel))) return false; if (bundle_description.cpus && !bundle_description.tsc_perf_zero_conversion) { path.report( @@ -139,9 +160,28 @@ bool fromJSON(const json::Value &value, JSONTraceBundleDescription &bundle_descr } // We have to do this because the compiler fails at doing it automatically // because pt_cpu is not in a namespace - if (!fromJSON(*value.getAsObject()->get("cpuInfo"), bundle_description.cpu_info, - path.field("cpuInfo"))) + if (!fromJSON(*value.getAsObject()->get("cpuInfo"), + bundle_description.cpu_info, path.field("cpuInfo"))) return false; + + // When kernel section is present, this is kernel-only tracing. Thus, throw an + // error if the "processes" section is non-empty or the "cpus" section is not + // present. + if (bundle_description.kernel) { + if (bundle_description.processes && + !bundle_description.processes->empty()) { + path.report("\"processes\" must be empty when \"kernel\" is provided"); + return false; + } + if (!bundle_description.cpus) { + path.report("\"cpus\" is required when \"kernel\" is provided"); + return false; + } + } else if (!bundle_description.processes) { + // Usermode tracing requires processes section. + path.report("\"processes\" is required when \"kernel\" is not provided"); + return false; + } return true; } diff --git a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTJSONStructs.h b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTJSONStructs.h index 687c0a793609..93156aa4aa9e 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTJSONStructs.h +++ b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTJSONStructs.h @@ -9,14 +9,11 @@ #ifndef LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_TRACEINTELPTJSONSTRUCTS_H #define LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_TRACEINTELPTJSONSTRUCTS_H -#include "lldb/lldb-types.h" - #include "lldb/Utility/TraceIntelPTGDBRemotePackets.h" - -#include "llvm/ADT/Optional.h" +#include "lldb/lldb-types.h" #include "llvm/Support/JSON.h" - #include <intel-pt.h> +#include <optional> #include <vector> namespace lldb_private { @@ -24,19 +21,19 @@ namespace trace_intel_pt { struct JSONModule { std::string system_path; - llvm::Optional<std::string> file; + std::optional<std::string> file; JSONUINT64 load_address; - llvm::Optional<std::string> uuid; + std::optional<std::string> uuid; }; struct JSONThread { uint64_t tid; - llvm::Optional<std::string> ipt_trace; + std::optional<std::string> ipt_trace; }; struct JSONProcess { uint64_t pid; - llvm::Optional<std::string> triple; + std::optional<std::string> triple; std::vector<JSONThread> threads; std::vector<JSONModule> modules; }; @@ -47,14 +44,20 @@ struct JSONCpu { std::string context_switch_trace; }; +struct JSONKernel { + std::optional<JSONUINT64> load_address; + std::string file; +}; + struct JSONTraceBundleDescription { std::string type; pt_cpu cpu_info; - std::vector<JSONProcess> processes; - llvm::Optional<std::vector<JSONCpu>> cpus; - llvm::Optional<LinuxPerfZeroTscConversion> tsc_perf_zero_conversion; + std::optional<std::vector<JSONProcess>> processes; + std::optional<std::vector<JSONCpu>> cpus; + std::optional<LinuxPerfZeroTscConversion> tsc_perf_zero_conversion; + std::optional<JSONKernel> kernel; - llvm::Optional<std::vector<lldb::cpu_id_t>> GetCpuIds(); + std::optional<std::vector<lldb::cpu_id_t>> GetCpuIds(); }; llvm::json::Value toJSON(const JSONModule &module); @@ -67,6 +70,8 @@ llvm::json::Value toJSON(const JSONCpu &cpu); llvm::json::Value toJSON(const pt_cpu &cpu_info); +llvm::json::Value toJSON(const JSONKernel &kernel); + llvm::json::Value toJSON(const JSONTraceBundleDescription &bundle_description); bool fromJSON(const llvm::json::Value &value, JSONModule &module, @@ -84,7 +89,11 @@ bool fromJSON(const llvm::json::Value &value, JSONCpu &cpu, bool fromJSON(const llvm::json::Value &value, pt_cpu &cpu_info, llvm::json::Path path); -bool fromJSON(const llvm::json::Value &value, JSONTraceBundleDescription &bundle_description, +bool fromJSON(const llvm::json::Value &value, JSONModule &kernel, + llvm::json::Path path); + +bool fromJSON(const llvm::json::Value &value, + JSONTraceBundleDescription &bundle_description, llvm::json::Path path); } // namespace trace_intel_pt } // namespace lldb_private diff --git a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTMultiCpuDecoder.cpp b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTMultiCpuDecoder.cpp index 08f54b582e3f..e2ca8b4d1db0 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTMultiCpuDecoder.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTMultiCpuDecoder.cpp @@ -7,10 +7,9 @@ //===----------------------------------------------------------------------===// #include "TraceIntelPTMultiCpuDecoder.h" - #include "TraceIntelPT.h" - #include "llvm/Support/Error.h" +#include <optional> using namespace lldb; using namespace lldb_private; @@ -35,15 +34,15 @@ bool TraceIntelPTMultiCpuDecoder::TracesThread(lldb::tid_t tid) const { return m_tids.count(tid); } -Expected<Optional<uint64_t>> TraceIntelPTMultiCpuDecoder::FindLowestTSC() { - Optional<uint64_t> lowest_tsc; +Expected<std::optional<uint64_t>> TraceIntelPTMultiCpuDecoder::FindLowestTSC() { + std::optional<uint64_t> lowest_tsc; TraceIntelPTSP trace_sp = GetTrace(); Error err = GetTrace()->OnAllCpusBinaryDataRead( IntelPTDataKinds::kIptTrace, [&](const DenseMap<cpu_id_t, ArrayRef<uint8_t>> &buffers) -> Error { for (auto &cpu_id_to_buffer : buffers) { - Expected<Optional<uint64_t>> tsc = + Expected<std::optional<uint64_t>> tsc = FindLowestTSCInTrace(*trace_sp, cpu_id_to_buffer.second); if (!tsc) return tsc.takeError(); @@ -63,8 +62,7 @@ Expected<DecodedThreadSP> TraceIntelPTMultiCpuDecoder::Decode(Thread &thread) { TraceIntelPTSP trace_sp = GetTrace(); - return trace_sp - ->GetThreadTimer(thread.GetID()) + return trace_sp->GetThreadTimer(thread.GetID()) .TimeTask("Decoding instructions", [&]() -> Expected<DecodedThreadSP> { auto it = m_decoded_threads.find(thread.GetID()); if (it != m_decoded_threads.end()) @@ -92,23 +90,23 @@ Expected<DecodedThreadSP> TraceIntelPTMultiCpuDecoder::Decode(Thread &thread) { }); } -static Expected<std::vector<IntelPTThreadSubtrace>> -GetIntelPTSubtracesForCpu(TraceIntelPT &trace, cpu_id_t cpu_id) { - std::vector<IntelPTThreadSubtrace> intel_pt_subtraces; +static Expected<std::vector<PSBBlock>> GetPSBBlocksForCPU(TraceIntelPT &trace, + cpu_id_t cpu_id) { + std::vector<PSBBlock> psb_blocks; Error err = trace.OnCpuBinaryDataRead( cpu_id, IntelPTDataKinds::kIptTrace, [&](ArrayRef<uint8_t> data) -> Error { - Expected<std::vector<IntelPTThreadSubtrace>> split_trace = - SplitTraceInContinuousExecutions(trace, data); + Expected<std::vector<PSBBlock>> split_trace = + SplitTraceIntoPSBBlock(trace, data, /*expect_tscs=*/true); if (!split_trace) return split_trace.takeError(); - intel_pt_subtraces = std::move(*split_trace); + psb_blocks = std::move(*split_trace); return Error::success(); }); if (err) return std::move(err); - return intel_pt_subtraces; + return psb_blocks; } Expected<DenseMap<lldb::tid_t, std::vector<IntelPTThreadContinousExecution>>> @@ -117,7 +115,7 @@ TraceIntelPTMultiCpuDecoder::DoCorrelateContextSwitchesAndIntelPtTraces() { continuous_executions_per_thread; TraceIntelPTSP trace_sp = GetTrace(); - Optional<LinuxPerfZeroTscConversion> conv_opt = + std::optional<LinuxPerfZeroTscConversion> conv_opt = trace_sp->GetPerfZeroTscConversion(); if (!conv_opt) return createStringError( @@ -127,24 +125,24 @@ TraceIntelPTMultiCpuDecoder::DoCorrelateContextSwitchesAndIntelPtTraces() { LinuxPerfZeroTscConversion tsc_conversion = *conv_opt; for (cpu_id_t cpu_id : trace_sp->GetTracedCpus()) { - Expected<std::vector<IntelPTThreadSubtrace>> intel_pt_subtraces = - GetIntelPTSubtracesForCpu(*trace_sp, cpu_id); - if (!intel_pt_subtraces) - return intel_pt_subtraces.takeError(); + Expected<std::vector<PSBBlock>> psb_blocks = + GetPSBBlocksForCPU(*trace_sp, cpu_id); + if (!psb_blocks) + return psb_blocks.takeError(); - m_total_psb_blocks += intel_pt_subtraces->size(); + m_total_psb_blocks += psb_blocks->size(); // We'll be iterating through the thread continuous executions and the intel // pt subtraces sorted by time. - auto it = intel_pt_subtraces->begin(); + auto it = psb_blocks->begin(); auto on_new_thread_execution = [&](const ThreadContinuousExecution &thread_execution) { IntelPTThreadContinousExecution execution(thread_execution); - for (; it != intel_pt_subtraces->end() && - it->tsc < thread_execution.GetEndTSC(); + for (; it != psb_blocks->end() && + *it->tsc < thread_execution.GetEndTSC(); it++) { - if (it->tsc > thread_execution.GetStartTSC()) { - execution.intelpt_subtraces.push_back(*it); + if (*it->tsc > thread_execution.GetStartTSC()) { + execution.psb_blocks.push_back(*it); } else { m_unattributed_psb_blocks++; } @@ -166,7 +164,7 @@ TraceIntelPTMultiCpuDecoder::DoCorrelateContextSwitchesAndIntelPtTraces() { if (err) return std::move(err); - m_unattributed_psb_blocks += intel_pt_subtraces->end() - it; + m_unattributed_psb_blocks += psb_blocks->end() - it; } // We now sort the executions of each thread to have them ready for // instruction decoding @@ -227,7 +225,7 @@ TraceIntelPTMultiCpuDecoder::GePSBBlocksCountForThread(lldb::tid_t tid) const { if (it == m_continuous_executions_per_thread->end()) return 0; for (const IntelPTThreadContinousExecution &execution : it->second) - count += execution.intelpt_subtraces.size(); + count += execution.psb_blocks.size(); return count; } diff --git a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTMultiCpuDecoder.h b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTMultiCpuDecoder.h index 87c370e88ae6..1633cd1e8088 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTMultiCpuDecoder.h +++ b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTMultiCpuDecoder.h @@ -13,6 +13,7 @@ #include "PerfContextSwitchDecoder.h" #include "ThreadDecoder.h" #include "forward-declarations.h" +#include <optional> namespace lldb_private { namespace trace_intel_pt { @@ -67,10 +68,10 @@ public: size_t GetTotalPSBBlocksCount() const; /// \return - /// The lowest TSC value in this trace if available, \a llvm::None if the - /// trace is empty or the trace contains no timing information, or an \a - /// llvm::Error if it was not possible to set up the decoder. - llvm::Expected<llvm::Optional<uint64_t>> FindLowestTSC(); + /// The lowest TSC value in this trace if available, \a std::nullopt if + /// the trace is empty or the trace contains no timing information, or an + /// \a llvm::Error if it was not possible to set up the decoder. + llvm::Expected<std::optional<uint64_t>> FindLowestTSC(); private: /// Traverse the context switch traces and the basic intel pt continuous @@ -92,13 +93,13 @@ private: std::weak_ptr<TraceIntelPT> m_trace_wp; std::set<lldb::tid_t> m_tids; - llvm::Optional< + std::optional< llvm::DenseMap<lldb::tid_t, std::vector<IntelPTThreadContinousExecution>>> m_continuous_executions_per_thread; llvm::DenseMap<lldb::tid_t, DecodedThreadSP> m_decoded_threads; - /// This variable will be non-None if a severe error happened during the setup - /// of the decoder and we don't want decoding to be reattempted. - llvm::Optional<std::string> m_setup_error; + /// This variable will not be std::nullopt if a severe error happened during + /// the setup of the decoder and we don't want decoding to be reattempted. + std::optional<std::string> m_setup_error; uint64_t m_unattributed_psb_blocks = 0; uint64_t m_total_psb_blocks = 0; }; diff --git a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTOptions.td b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTOptions.td index 95bd5c3d1cce..4fb79448a3a0 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTOptions.td +++ b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTOptions.td @@ -6,92 +6,127 @@ include "../../../../source/Commands/OptionsBase.td" // the API help message of TraceIntelPT::GetStartConfigurationHelp(). let Command = "thread trace start intel pt" in { - def thread_trace_start_intel_pt_size: Option<"size", "s">, - Group<1>, - Arg<"Value">, - Desc<"Trace size in bytes per thread. It must be a power of 2 greater " - "than or equal to 4096 (2^12). The trace is circular keeping " - "the most recent data. Defaults to 4096 bytes. It's possible to " - "specify size using multiples of unit bytes, e.g., 4KB, 1MB, 1MiB, " - "where 1K is 1024 bytes and 1M is 1048576 bytes.">; - def thread_trace_start_intel_pt_tsc: Option<"tsc", "t">, - Group<1>, - Desc<"Enable the use of TSC timestamps. This is supported on all devices " - "that support intel-pt.">; - def thread_trace_start_intel_pt_psb_period: Option<"psb-period", "p">, - Group<1>, - Arg<"Value">, - Desc<"This value defines the period in which PSB packets will be " - "generated. A PSB packet is a synchronization packet that contains a " - "TSC timestamp and the current absolute instruction pointer. " - "This parameter can only be used if " - "/sys/bus/event_source/devices/intel_pt/caps/psb_cyc is 1. Otherwise, " - "the PSB period will be defined by the processor. If supported, valid " - "values for this period can be found in " - "/sys/bus/event_source/devices/intel_pt/caps/psb_periods which " - "contains a hexadecimal number, whose bits represent valid values " - "e.g. if bit 2 is set, then value 2 is valid. The psb_period value is " - "converted to the approximate number of raw trace bytes between PSB " - "packets as: 2 ^ (value + 11), e.g. value 3 means 16KiB between PSB " - "packets. Defaults to 0 if supported.">; + def thread_trace_start_intel_pt_size + : Option<"size", "s">, + Group<1>, + Arg<"Value">, + Desc< + "Trace size in bytes per thread. It must be a power of 2 greater " + "than or equal to 4096 (2^12). The trace is circular keeping " + "the most recent data. Defaults to 4096 bytes. It's possible to " + "specify size using multiples of unit bytes, e.g., 4KB, 1MB, 1MiB, " + "where 1K is 1024 bytes and 1M is 1048576 bytes.">; + def thread_trace_start_intel_pt_tsc + : Option<"tsc", "t">, + Group<1>, + Desc<"Enable the use of TSC timestamps. This is supported on all " + "devices " + "that support intel-pt.">; + def thread_trace_start_intel_pt_psb_period + : Option<"psb-period", "p">, + Group<1>, + Arg<"Value">, + Desc<"This value defines the period in which PSB packets will be " + "generated. A PSB packet is a synchronization packet that " + "contains a " + "TSC timestamp and the current absolute instruction pointer. " + "This parameter can only be used if " + "/sys/bus/event_source/devices/intel_pt/caps/psb_cyc is 1. " + "Otherwise, " + "the PSB period will be defined by the processor. If supported, " + "valid " + "values for this period can be found in " + "/sys/bus/event_source/devices/intel_pt/caps/psb_periods which " + "contains a hexadecimal number, whose bits represent valid values " + "e.g. if bit 2 is set, then value 2 is valid. The psb_period " + "value is " + "converted to the approximate number of raw trace bytes between " + "PSB " + "packets as: 2 ^ (value + 11), e.g. value 3 means 16KiB between " + "PSB " + "packets. Defaults to 0 if supported.">; } let Command = "process trace start intel pt" in { - def process_trace_start_intel_pt_buffer_size: Option<"buffer-size", "s">, - Group<1>, - Arg<"Value">, - Desc<"Size in bytes used by each individual per-thread or per-cpu trace " - "buffer. It must be a power of 2 greater than or equal to 4096 (2^12) " - "bytes. It's possible to specify a unit for these bytes, like 4KB, " - "16KiB or 1MB. Lower case units are allowed for convenience.">; - def process_trace_start_intel_pt_per_cpu_tracing: - Option<"per-cpu-tracing", "c">, - Group<1>, - Desc<"Instead of having an individual trace buffer per thread, which uses " - "a number trace buffers proportional to the number of running " - "threads, this option triggers the collection on a per cpu core " - "basis. This effectively traces the entire activity on all cpus " - "using a limited amount of trace buffers regardless of the number of " - "threads. This might cause data loss for less frequent threads. This " - "option forces the capture of TSC timestamps (see --tsc). Also, this " - "option can't be used simulatenously with any other trace sessions " - "because of its system-wide nature.">; - def process_trace_start_intel_pt_process_size_limit: - Option<"total-size-limit", "l">, - Group<1>, - Arg<"Value">, - Desc<"Maximum total trace size per process in bytes. This limit applies to " - "the sum of the sizes of all thread and cpu traces of this process, " - "excluding the ones created with the \"thread trace start\" command. " - "Whenever a thread is attempted to be traced due to this command and " - "the limit would be reached, the process is stopped with a " - "\"processor trace\" reason, so that the user can retrace the process " - "if needed. Defaults to 500MB. It's possible to specify a unit for " - "these bytes, like 4KB, 16KiB or 1MB. Lower case units are allowed " - "for convenience.">; - def process_trace_start_intel_pt_tsc: Option<"tsc", "t">, - Group<1>, - Desc<"Enable the use of TSC timestamps. This is supported on all devices " - "that support intel-pt.">; - def process_trace_start_intel_pt_psb_period: Option<"psb-period", "p">, - Group<1>, - Arg<"Value">, - Desc<"This value defines the period in which PSB packets will be " - "generated. A PSB packet is a synchronization packet that contains a " - "TSC timestamp and the current absolute instruction pointer. " - "This parameter can only be used if " - "/sys/bus/event_source/devices/intel_pt/caps/psb_cyc is 1. Otherwise, " - "the PSB period will be defined by the processor. If supported, valid " - "values for this period can be found in " - "/sys/bus/event_source/devices/intel_pt/caps/psb_periods which " - "contains a hexadecimal number, whose bits represent valid values " - "e.g. if bit 2 is set, then value 2 is valid. The psb_period value is " - "converted to the approximate number of raw trace bytes between PSB " - "packets as: 2 ^ (value + 11), e.g. value 3 means 16KiB between PSB " - "packets. Defaults to 0 if supported.">; - def process_trace_start_intel_pt_disable_cgroup_filtering: - Option<"disable-cgroup-filtering", "d">, - Desc<"Disable the automatic cgroup filtering that is applied if --per-cpu " - "is provided. Cgroup filtering allows collecting intel pt data " - "exclusively of processes of the same cgroup as the target.">; + def process_trace_start_intel_pt_buffer_size + : Option<"buffer-size", "s">, + Group<1>, + Arg<"Value">, + Desc< + "Size in bytes used by each individual per-thread or per-cpu trace " + "buffer. It must be a power of 2 greater than or equal to 4096 " + "(2^12) " + "bytes. It's possible to specify a unit for these bytes, like 4KB, " + "16KiB or 1MB. Lower case units are allowed for convenience.">; + def process_trace_start_intel_pt_per_cpu_tracing + : Option<"per-cpu-tracing", "c">, + Group<1>, + Desc< + "Instead of having an individual trace buffer per thread, which " + "uses " + "a number trace buffers proportional to the number of running " + "threads, this option triggers the collection on a per cpu core " + "basis. This effectively traces the entire activity on all cpus " + "using a limited amount of trace buffers regardless of the number " + "of " + "threads. This might cause data loss for less frequent threads. " + "This " + "option forces the capture of TSC timestamps (see --tsc). Also, " + "this " + "option can't be used simulatenously with any other trace sessions " + "because of its system-wide nature.">; + def process_trace_start_intel_pt_process_size_limit + : Option<"total-size-limit", "l">, + Group<1>, + Arg<"Value">, + Desc< + "Maximum total trace size per process in bytes. This limit applies " + "to " + "the sum of the sizes of all thread and cpu traces of this " + "process, " + "excluding the ones created with the \"thread trace start\" " + "command. " + "Whenever a thread is attempted to be traced due to this command " + "and " + "the limit would be reached, the process is stopped with a " + "\"processor trace\" reason, so that the user can retrace the " + "process " + "if needed. Defaults to 500MB. It's possible to specify a unit for " + "these bytes, like 4KB, 16KiB or 1MB. Lower case units are allowed " + "for convenience.">; + def process_trace_start_intel_pt_tsc + : Option<"tsc", "t">, + Group<1>, + Desc<"Enable the use of TSC timestamps. This is supported on all " + "devices " + "that support intel-pt.">; + def process_trace_start_intel_pt_psb_period + : Option<"psb-period", "p">, + Group<1>, + Arg<"Value">, + Desc<"This value defines the period in which PSB packets will be " + "generated. A PSB packet is a synchronization packet that " + "contains a " + "TSC timestamp and the current absolute instruction pointer. " + "This parameter can only be used if " + "/sys/bus/event_source/devices/intel_pt/caps/psb_cyc is 1. " + "Otherwise, " + "the PSB period will be defined by the processor. If supported, " + "valid " + "values for this period can be found in " + "/sys/bus/event_source/devices/intel_pt/caps/psb_periods which " + "contains a hexadecimal number, whose bits represent valid values " + "e.g. if bit 2 is set, then value 2 is valid. The psb_period " + "value is " + "converted to the approximate number of raw trace bytes between " + "PSB " + "packets as: 2 ^ (value + 11), e.g. value 3 means 16KiB between " + "PSB " + "packets. Defaults to 0 if supported.">; + def process_trace_start_intel_pt_disable_cgroup_filtering + : Option<"disable-cgroup-filtering", "d">, + Desc<"Disable the automatic cgroup filtering that is applied if " + "--per-cpu " + "is provided. Cgroup filtering allows collecting intel pt data " + "exclusively of processes of the same cgroup as the target.">; } diff --git a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTProperties.td b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTProperties.td new file mode 100644 index 000000000000..d338df1df5cb --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTProperties.td @@ -0,0 +1,24 @@ +include "../../../../include/lldb/Core/PropertiesBase.td" + +let Definition = "traceintelpt" in { + def InfiniteDecodingLoopVerificationThreshold: + Property<"infinite-decoding-loop-verification-threshold", "UInt64">, + Global, + DefaultUnsignedValue<10000>, + Desc<"Specify how many instructions following an individual Intel PT " + "packet must have been decoded before triggering the verification of " + "infinite decoding loops. If no decoding loop has been found after this " + "threshold T, another attempt will be done after 2T instructions, then " + "4T, 8T and so on, which guarantees a total linear time spent checking " + "this anomaly. If a loop is found, then decoding of the corresponding " + "PSB block is stopped. An error is hence emitted in the trace and " + "decoding is resumed in the next PSB block.">; + def ExtremelyLargeDecodingThreshold: + Property<"extremely-large-decoding-threshold", "UInt64">, + Global, + DefaultUnsignedValue<500000>, + Desc<"Specify how many instructions following an individual Intel PT " + "packet must have been decoded before stopping the decoding of the " + "corresponding PSB block. An error is hence emitted in the trace and " + "decoding is resumed in the next PSB block.">; +} diff --git a/contrib/llvm-project/lldb/source/Plugins/TraceExporter/common/TraceHTR.cpp b/contrib/llvm-project/lldb/source/Plugins/TraceExporter/common/TraceHTR.cpp index d8e44ee66de8..13c63f2f7e37 100644 --- a/contrib/llvm-project/lldb/source/Plugins/TraceExporter/common/TraceHTR.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/TraceExporter/common/TraceHTR.cpp @@ -12,6 +12,7 @@ #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" #include "llvm/Support/JSON.h" +#include <optional> #include <sstream> #include <string> @@ -22,10 +23,10 @@ size_t HTRBlockMetadata::GetNumInstructions() const { return m_num_instructions; } -llvm::Optional<llvm::StringRef> +std::optional<llvm::StringRef> HTRBlockMetadata::GetMostFrequentlyCalledFunction() const { size_t max_ncalls = 0; - llvm::Optional<llvm::StringRef> max_name = llvm::None; + std::optional<llvm::StringRef> max_name; for (const auto &it : m_func_calls) { ConstString name = it.first; size_t ncalls = it.second; @@ -80,7 +81,7 @@ llvm::ArrayRef<lldb::addr_t> HTRInstructionLayer::GetInstructionTrace() const { } void HTRInstructionLayer::AddCallInstructionMetadata( - lldb::addr_t load_addr, llvm::Optional<ConstString> func_name) { + lldb::addr_t load_addr, std::optional<ConstString> func_name) { m_call_isns.emplace(load_addr, func_name); } @@ -108,7 +109,7 @@ HTRBlockMetadata HTRInstructionLayer::GetMetadataByIndex(size_t index) const { auto func_name_it = m_call_isns.find(instruction_load_address); if (func_name_it != m_call_isns.end()) { - if (llvm::Optional<ConstString> func_name = func_name_it->second) { + if (std::optional<ConstString> func_name = func_name_it->second) { func_calls[*func_name] = 1; } } @@ -130,23 +131,23 @@ TraceHTR::TraceHTR(Thread &thread, TraceCursor &cursor) // Move cursor to the first instruction in the trace cursor.SetForwards(true); - cursor.Seek(0, TraceCursor::SeekType::Beginning); + cursor.Seek(0, lldb::eTraceCursorSeekTypeBeginning); // TODO: fix after persona0220's patch on a new way to access instruction // kinds /* Target &target = thread.GetProcess()->GetTarget(); auto function_name_from_load_address = - [&](lldb::addr_t load_address) -> llvm::Optional<ConstString> { + [&](lldb::addr_t load_address) -> std::optional<ConstString> { lldb_private::Address pc_addr; SymbolContext sc; if (target.ResolveLoadAddress(load_address, pc_addr) && pc_addr.CalculateSymbolContext(&sc)) return sc.GetFunctionName() - ? llvm::Optional<ConstString>(sc.GetFunctionName()) - : llvm::None; + ? std::optional<ConstString>(sc.GetFunctionName()) + : std::nullopt; else - return llvm::None; + return std::nullopt; }; while (cursor.HasValue()) { if (cursor.IsError()) { @@ -177,7 +178,7 @@ TraceHTR::TraceHTR(Thread &thread, TraceCursor &cursor) // Next instruction is not known - pass None to indicate the name // of the function being called is not known m_instruction_layer_up->AddCallInstructionMetadata( - current_instruction_load_address, llvm::None); + current_instruction_load_address, std::nullopt); } } } @@ -316,7 +317,7 @@ HTRBlockLayerUP lldb_private::BasicSuperBlockMerge(IHTRLayer &layer) { // Each super block always has the same first unit (we call this the // super block head) This gurantee allows us to use the super block head as // the unique key mapping to the super block it begins - llvm::Optional<size_t> superblock_head = llvm::None; + std::optional<size_t> superblock_head; auto construct_next_layer = [&](size_t merge_start, size_t n) -> void { if (!superblock_head) return; @@ -349,7 +350,7 @@ HTRBlockLayerUP lldb_private::BasicSuperBlockMerge(IHTRLayer &layer) { // Tail logic construct_next_layer(i - superblock_size + 1, superblock_size); // Reset the block_head since the prev super block has come to and end - superblock_head = llvm::None; + superblock_head = std::nullopt; superblock_size = 0; } else if (isHead) { if (superblock_size) { // this handles (tail, head) adjacency - @@ -369,7 +370,7 @@ HTRBlockLayerUP lldb_private::BasicSuperBlockMerge(IHTRLayer &layer) { // End previous super block construct_next_layer(i - superblock_size + 1, superblock_size); // Reset the block_head since the prev super block has come to and end - superblock_head = llvm::None; + superblock_head = std::nullopt; superblock_size = 0; } else { if (!superblock_head) @@ -440,7 +441,7 @@ llvm::json::Value lldb_private::toJSON(const TraceHTR &htr) { HTRBlockMetadata metadata = block.GetMetadata(); - llvm::Optional<llvm::StringRef> most_freq_func = + std::optional<llvm::StringRef> most_freq_func = metadata.GetMostFrequentlyCalledFunction(); std::stringstream stream; stream << "0x" << std::hex << metadata.GetFirstInstructionLoadAddress(); diff --git a/contrib/llvm-project/lldb/source/Plugins/TraceExporter/common/TraceHTR.h b/contrib/llvm-project/lldb/source/Plugins/TraceExporter/common/TraceHTR.h index 03babc5a36ab..58a9262370a8 100644 --- a/contrib/llvm-project/lldb/source/Plugins/TraceExporter/common/TraceHTR.h +++ b/contrib/llvm-project/lldb/source/Plugins/TraceExporter/common/TraceHTR.h @@ -1,9 +1,8 @@ //===-- TraceHTR.h --------------------------------------------------------===// // -// Part of the LLVM Project, under the Apache -// License v2.0 with LLVM Exceptions.// See https://llvm.org/LICENSE.txt for -// license information.// SPDX-License-Identifier: Apache-2.0 WITH -// LLVM-exception +// 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 // //===----------------------------------------------------------------------===// @@ -13,6 +12,7 @@ #include "lldb/Target/Thread.h" #include "lldb/Target/Trace.h" +#include <optional> #include <unordered_map> #include <unordered_set> @@ -58,8 +58,8 @@ public: /// /// \return /// The name of the function that is called the most from this block or - /// None if no function is called from this block. - llvm::Optional<llvm::StringRef> GetMostFrequentlyCalledFunction() const; + /// std::nullopt if no function is called from this block. + std::optional<llvm::StringRef> GetMostFrequentlyCalledFunction() const; /// Get the load address of the first instruction in the block. /// @@ -217,7 +217,7 @@ public: /// The name of the function the 'call' instruction is calling if it can /// be determined, None otherwise. void AddCallInstructionMetadata(lldb::addr_t load_addr, - llvm::Optional<ConstString> func_name); + std::optional<ConstString> func_name); /// Append the load address of an instruction to the dynamic instruction /// trace. @@ -234,9 +234,9 @@ private: // most instructions don't contain useful metadata // This map contains the load address of all the call instructions. - // load address maps to the name of the function it calls (None if function - // name can't be determined) - std::unordered_map<lldb::addr_t, llvm::Optional<ConstString>> m_call_isns; + // load address maps to the name of the function it calls (std::nullopt if + // function name can't be determined) + std::unordered_map<lldb::addr_t, std::optional<ConstString>> m_call_isns; }; /// HTR layer composed of blocks of the trace. diff --git a/contrib/llvm-project/lldb/source/Plugins/TraceExporter/ctf/CommandObjectThreadTraceExportCTF.cpp b/contrib/llvm-project/lldb/source/Plugins/TraceExporter/ctf/CommandObjectThreadTraceExportCTF.cpp index 384abd2166df..33d05ee2ac13 100644 --- a/contrib/llvm-project/lldb/source/Plugins/TraceExporter/ctf/CommandObjectThreadTraceExportCTF.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/TraceExporter/ctf/CommandObjectThreadTraceExportCTF.cpp @@ -54,12 +54,12 @@ Status CommandObjectThreadTraceExportCTF::CommandOptions::SetOptionValue( void CommandObjectThreadTraceExportCTF::CommandOptions::OptionParsingStarting( ExecutionContext *execution_context) { m_file.clear(); - m_thread_index = None; + m_thread_index = std::nullopt; } llvm::ArrayRef<OptionDefinition> CommandObjectThreadTraceExportCTF::CommandOptions::GetDefinitions() { - return llvm::makeArrayRef(g_thread_trace_export_ctf_options); + return llvm::ArrayRef(g_thread_trace_export_ctf_options); } bool CommandObjectThreadTraceExportCTF::DoExecute(Args &command, @@ -81,7 +81,7 @@ bool CommandObjectThreadTraceExportCTF::DoExecute(Args &command, return false; } else { auto do_work = [&]() -> Error { - Expected<TraceCursorUP> cursor = trace_sp->CreateNewCursor(*thread); + Expected<TraceCursorSP> cursor = trace_sp->CreateNewCursor(*thread); if (!cursor) return cursor.takeError(); TraceHTR htr(*thread, **cursor); diff --git a/contrib/llvm-project/lldb/source/Plugins/TraceExporter/ctf/CommandObjectThreadTraceExportCTF.h b/contrib/llvm-project/lldb/source/Plugins/TraceExporter/ctf/CommandObjectThreadTraceExportCTF.h index c6364cfe027d..c9f02a372ded 100644 --- a/contrib/llvm-project/lldb/source/Plugins/TraceExporter/ctf/CommandObjectThreadTraceExportCTF.h +++ b/contrib/llvm-project/lldb/source/Plugins/TraceExporter/ctf/CommandObjectThreadTraceExportCTF.h @@ -12,6 +12,7 @@ #include "TraceExporterCTF.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" +#include <optional> namespace lldb_private { namespace ctf { @@ -29,7 +30,7 @@ public: llvm::ArrayRef<OptionDefinition> GetDefinitions() override; - llvm::Optional<size_t> m_thread_index; + std::optional<size_t> m_thread_index; std::string m_file; }; diff --git a/contrib/llvm-project/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/contrib/llvm-project/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp index b47d86d76337..93249527270e 100644 --- a/contrib/llvm-project/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp @@ -1,4 +1,4 @@ -//===-- TypeSystemClang.cpp -----------------------------------------------===// +//===-- TypeSystemClang.cpp -----------------------------------------------==='// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -12,6 +12,7 @@ #include "llvm/Support/FormatVariadic.h" #include <mutex> +#include <memory> #include <string> #include <vector> @@ -73,10 +74,12 @@ #include "Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h" #include "Plugins/SymbolFile/DWARF/DWARFASTParserClang.h" #include "Plugins/SymbolFile/PDB/PDBASTParser.h" +#include "Plugins/SymbolFile/NativePDB/PdbAstBuilder.h" #include <cstdio> #include <mutex> +#include <optional> using namespace lldb; using namespace lldb_private; @@ -934,7 +937,7 @@ CompilerType TypeSystemClang::GetBasicType(lldb::BasicType basic_type) { GetOpaqueCompilerType(&ast, basic_type); if (clang_type) - return CompilerType(this, clang_type); + return CompilerType(weak_from_this(), clang_type); return CompilerType(); } @@ -1062,7 +1065,7 @@ CompilerType TypeSystemClang::GetBuiltinTypeForDWARFEncodingAndBitSize( break; case DW_ATE_signed_char: - if (ast.getLangOpts().CharIsSigned && type_name == "char") { + if (type_name == "char") { if (QualTypeMatchesBitSize(bit_size, ast, ast.CharTy)) return GetType(ast.CharTy); } @@ -1114,7 +1117,7 @@ CompilerType TypeSystemClang::GetBuiltinTypeForDWARFEncodingAndBitSize( break; case DW_ATE_unsigned_char: - if (!ast.getLangOpts().CharIsSigned && type_name == "char") { + if (type_name == "char") { if (QualTypeMatchesBitSize(bit_size, ast, ast.CharTy)) return GetType(ast.CharTy); } @@ -1168,9 +1171,8 @@ CompilerType TypeSystemClang::GetCStringType(bool is_const) { bool TypeSystemClang::AreTypesSame(CompilerType type1, CompilerType type2, bool ignore_qualifiers) { - TypeSystemClang *ast = - llvm::dyn_cast_or_null<TypeSystemClang>(type1.GetTypeSystem()); - if (!ast || ast != type2.GetTypeSystem()) + auto ast = type1.GetTypeSystem().dyn_cast_or_null<TypeSystemClang>(); + if (!ast || type1.GetTypeSystem() != type2.GetTypeSystem()) return false; if (type1.GetOpaqueQualType() == type2.GetOpaqueQualType()) @@ -1429,6 +1431,24 @@ static TemplateParameterList *CreateTemplateParameterList( return template_param_list; } +std::string TypeSystemClang::PrintTemplateParams( + const TemplateParameterInfos &template_param_infos) { + llvm::SmallVector<NamedDecl *, 8> ignore; + clang::TemplateParameterList *template_param_list = + CreateTemplateParameterList(getASTContext(), template_param_infos, + ignore); + llvm::SmallVector<clang::TemplateArgument, 2> args = + template_param_infos.args; + if (template_param_infos.hasParameterPack()) { + args.append(template_param_infos.packed_args->args); + } + std::string str; + llvm::raw_string_ostream os(str); + clang::printTemplateArgumentList(os, args, GetTypePrintingPolicy(), + template_param_list); + return str; +} + clang::FunctionTemplateDecl *TypeSystemClang::CreateFunctionTemplateDecl( clang::DeclContext *decl_ctx, OptionalClangModuleID owning_module, clang::FunctionDecl *func_decl, @@ -1444,7 +1464,8 @@ clang::FunctionTemplateDecl *TypeSystemClang::CreateFunctionTemplateDecl( func_tmpl_decl->setDeclContext(decl_ctx); func_tmpl_decl->setLocation(func_decl->getLocation()); func_tmpl_decl->setDeclName(func_decl->getDeclName()); - func_tmpl_decl->init(func_decl, template_param_list); + func_tmpl_decl->setTemplateParameters(template_param_list); + func_tmpl_decl->init(func_decl); SetOwningModule(func_tmpl_decl, owning_module); for (size_t i = 0, template_param_decl_count = template_param_decls.size(); @@ -1521,7 +1542,7 @@ static bool ClassTemplateAllowsToInstantiationArgs( // calculate the information related to parameter packs. // Contains the first pack parameter (or non if there are none). - llvm::Optional<NamedDecl *> pack_parameter; + std::optional<NamedDecl *> pack_parameter; // Contains the number of non-pack parameters. size_t non_pack_params = params.size(); for (size_t i = 0; i < params.size(); ++i) { @@ -1621,7 +1642,8 @@ ClassTemplateDecl *TypeSystemClang::CreateClassTemplateDecl( // What decl context do we use here? TU? The actual decl context? class_template_decl->setDeclContext(decl_ctx); class_template_decl->setDeclName(decl_name); - class_template_decl->init(template_cxx_decl, template_param_list); + class_template_decl->setTemplateParameters(template_param_list); + class_template_decl->init(template_cxx_decl); template_cxx_decl->setDescribedClassTemplate(class_template_decl); SetOwningModule(class_template_decl, owning_module); @@ -1770,7 +1792,7 @@ bool TypeSystemClang::FieldIsBitfield(FieldDecl *field, if (field->isBitField()) { Expr *bit_width_expr = field->getBitWidth(); if (bit_width_expr) { - if (Optional<llvm::APSInt> bit_width_apsint = + if (std::optional<llvm::APSInt> bit_width_apsint = bit_width_expr->getIntegerConstantExpr(ast)) { bitfield_bit_size = bit_width_apsint->getLimitedValue(UINT32_MAX); return true; @@ -1800,6 +1822,17 @@ bool TypeSystemClang::RecordHasFields(const RecordDecl *record_decl) { return true; } } + + // We always want forcefully completed types to show up so we can print a + // message in the summary that indicates that the type is incomplete. + // This will help users know when they are running into issues with + // -flimit-debug-info instead of just seeing nothing if this is a base class + // (since we were hiding empty base classes), or nothing when you turn open + // an valiable whose type was incomplete. + ClangASTMetadata *meta_data = GetMetadata(record_decl); + if (meta_data && meta_data->IsForcefullyCompleted()) + return true; + return false; } @@ -1827,7 +1860,7 @@ CompilerType TypeSystemClang::CreateObjCClass( return GetType(ast.getObjCInterfaceType(decl)); } -static inline bool BaseSpecifierIsEmpty(const CXXBaseSpecifier *b) { +bool TypeSystemClang::BaseSpecifierIsEmpty(const CXXBaseSpecifier *b) { return !TypeSystemClang::RecordHasFields(b->getType()->getAsCXXRecordDecl()); } @@ -1873,9 +1906,9 @@ NamespaceDecl *TypeSystemClang::GetUniqueNamespaceDeclaration( return namespace_decl; } - namespace_decl = - NamespaceDecl::Create(ast, decl_ctx, is_inline, SourceLocation(), - SourceLocation(), &identifier_info, nullptr); + namespace_decl = NamespaceDecl::Create(ast, decl_ctx, is_inline, + SourceLocation(), SourceLocation(), + &identifier_info, nullptr, false); decl_ctx->addDecl(namespace_decl); } else { @@ -1886,7 +1919,7 @@ NamespaceDecl *TypeSystemClang::GetUniqueNamespaceDeclaration( namespace_decl = NamespaceDecl::Create(ast, decl_ctx, false, SourceLocation(), - SourceLocation(), nullptr, nullptr); + SourceLocation(), nullptr, nullptr, false); translation_unit_decl->setAnonymousNamespace(namespace_decl); translation_unit_decl->addDecl(namespace_decl); assert(namespace_decl == translation_unit_decl->getAnonymousNamespace()); @@ -1898,7 +1931,7 @@ NamespaceDecl *TypeSystemClang::GetUniqueNamespaceDeclaration( return namespace_decl; namespace_decl = NamespaceDecl::Create(ast, decl_ctx, false, SourceLocation(), - SourceLocation(), nullptr, nullptr); + SourceLocation(), nullptr, nullptr, false); parent_namespace_decl->setAnonymousNamespace(namespace_decl); parent_namespace_decl->addDecl(namespace_decl); assert(namespace_decl == @@ -2128,11 +2161,12 @@ PrintingPolicy TypeSystemClang::GetTypePrintingPolicy() { return printing_policy; } -std::string TypeSystemClang::GetTypeNameForDecl(const NamedDecl *named_decl) { +std::string TypeSystemClang::GetTypeNameForDecl(const NamedDecl *named_decl, + bool qualified) { clang::PrintingPolicy printing_policy = GetTypePrintingPolicy(); std::string result; llvm::raw_string_ostream os(result); - named_decl->printQualifiedName(os, printing_policy); + named_decl->getNameForDiagnostic(os, printing_policy, qualified); return result; } @@ -2168,11 +2202,10 @@ FunctionDecl *TypeSystemClang::CreateFunctionDeclaration( return func_decl; } -CompilerType -TypeSystemClang::CreateFunctionType(const CompilerType &result_type, - const CompilerType *args, unsigned num_args, - bool is_variadic, unsigned type_quals, - clang::CallingConv cc) { +CompilerType TypeSystemClang::CreateFunctionType( + const CompilerType &result_type, const CompilerType *args, + unsigned num_args, bool is_variadic, unsigned type_quals, + clang::CallingConv cc, clang::RefQualifierKind ref_qual) { if (!result_type || !ClangUtil::IsClangType(result_type)) return CompilerType(); // invalid return type @@ -2201,7 +2234,7 @@ TypeSystemClang::CreateFunctionType(const CompilerType &result_type, proto_info.Variadic = is_variadic; proto_info.ExceptionSpec = EST_None; proto_info.TypeQuals = clang::Qualifiers::fromFastMask(type_quals); - proto_info.RefQualifier = RQ_None; + proto_info.RefQualifier = ref_qual; return GetType(getASTContext().getFunctionType( ClangUtil::GetQualType(result_type), qual_type_args, proto_info)); @@ -2855,9 +2888,9 @@ bool TypeSystemClang::IsArrayType(lldb::opaque_compiler_type_t type, case clang::Type::ConstantArray: if (element_type_ptr) element_type_ptr->SetCompilerType( - this, llvm::cast<clang::ConstantArrayType>(qual_type) - ->getElementType() - .getAsOpaquePtr()); + weak_from_this(), llvm::cast<clang::ConstantArrayType>(qual_type) + ->getElementType() + .getAsOpaquePtr()); if (size) *size = llvm::cast<clang::ConstantArrayType>(qual_type) ->getSize() @@ -2869,9 +2902,9 @@ bool TypeSystemClang::IsArrayType(lldb::opaque_compiler_type_t type, case clang::Type::IncompleteArray: if (element_type_ptr) element_type_ptr->SetCompilerType( - this, llvm::cast<clang::IncompleteArrayType>(qual_type) - ->getElementType() - .getAsOpaquePtr()); + weak_from_this(), llvm::cast<clang::IncompleteArrayType>(qual_type) + ->getElementType() + .getAsOpaquePtr()); if (size) *size = 0; if (is_incomplete) @@ -2881,9 +2914,9 @@ bool TypeSystemClang::IsArrayType(lldb::opaque_compiler_type_t type, case clang::Type::VariableArray: if (element_type_ptr) element_type_ptr->SetCompilerType( - this, llvm::cast<clang::VariableArrayType>(qual_type) - ->getElementType() - .getAsOpaquePtr()); + weak_from_this(), llvm::cast<clang::VariableArrayType>(qual_type) + ->getElementType() + .getAsOpaquePtr()); if (size) *size = 0; if (is_incomplete) @@ -2893,9 +2926,10 @@ bool TypeSystemClang::IsArrayType(lldb::opaque_compiler_type_t type, case clang::Type::DependentSizedArray: if (element_type_ptr) element_type_ptr->SetCompilerType( - this, llvm::cast<clang::DependentSizedArrayType>(qual_type) - ->getElementType() - .getAsOpaquePtr()); + weak_from_this(), + llvm::cast<clang::DependentSizedArrayType>(qual_type) + ->getElementType() + .getAsOpaquePtr()); if (size) *size = 0; if (is_incomplete) @@ -2936,7 +2970,8 @@ bool TypeSystemClang::IsVectorType(lldb::opaque_compiler_type_t type, *size = ext_vector_type->getNumElements(); if (element_type) *element_type = - CompilerType(this, ext_vector_type->getElementType().getAsOpaquePtr()); + CompilerType(weak_from_this(), + ext_vector_type->getElementType().getAsOpaquePtr()); } return true; } @@ -3103,7 +3138,8 @@ TypeSystemClang::IsHomogeneousAggregate(lldb::opaque_compiler_type_t type, ++num_fields; } if (base_type_ptr) - *base_type_ptr = CompilerType(this, base_qual_type.getAsOpaquePtr()); + *base_type_ptr = + CompilerType(weak_from_this(), base_qual_type.getAsOpaquePtr()); return num_fields; } } @@ -3137,7 +3173,7 @@ TypeSystemClang::GetFunctionArgumentAtIndex(lldb::opaque_compiler_type_t type, llvm::dyn_cast<clang::FunctionProtoType>(qual_type.getTypePtr()); if (func) { if (index < func->getNumParams()) - return CompilerType(this, func->getParamType(index).getAsOpaquePtr()); + return CompilerType(weak_from_this(), func->getParamType(index).getAsOpaquePtr()); } } return CompilerType(); @@ -3180,8 +3216,8 @@ bool TypeSystemClang::IsBlockPointerType( qual_type->castAs<clang::BlockPointerType>(); QualType pointee_type = block_pointer_type->getPointeeType(); QualType function_pointer_type = m_ast_up->getPointerType(pointee_type); - *function_pointer_type_ptr = - CompilerType(this, function_pointer_type.getAsOpaquePtr()); + *function_pointer_type_ptr = CompilerType( + weak_from_this(), function_pointer_type.getAsOpaquePtr()); } return true; } @@ -3272,20 +3308,21 @@ bool TypeSystemClang::IsPointerType(lldb::opaque_compiler_type_t type, case clang::Type::ObjCObjectPointer: if (pointee_type) pointee_type->SetCompilerType( - this, llvm::cast<clang::ObjCObjectPointerType>(qual_type) - ->getPointeeType() - .getAsOpaquePtr()); + weak_from_this(), + llvm::cast<clang::ObjCObjectPointerType>(qual_type) + ->getPointeeType() + .getAsOpaquePtr()); return true; case clang::Type::BlockPointer: if (pointee_type) pointee_type->SetCompilerType( - this, llvm::cast<clang::BlockPointerType>(qual_type) - ->getPointeeType() - .getAsOpaquePtr()); + weak_from_this(), llvm::cast<clang::BlockPointerType>(qual_type) + ->getPointeeType() + .getAsOpaquePtr()); return true; case clang::Type::Pointer: if (pointee_type) - pointee_type->SetCompilerType(this, + pointee_type->SetCompilerType(weak_from_this(), llvm::cast<clang::PointerType>(qual_type) ->getPointeeType() .getAsOpaquePtr()); @@ -3293,9 +3330,9 @@ bool TypeSystemClang::IsPointerType(lldb::opaque_compiler_type_t type, case clang::Type::MemberPointer: if (pointee_type) pointee_type->SetCompilerType( - this, llvm::cast<clang::MemberPointerType>(qual_type) - ->getPointeeType() - .getAsOpaquePtr()); + weak_from_this(), llvm::cast<clang::MemberPointerType>(qual_type) + ->getPointeeType() + .getAsOpaquePtr()); return true; default: break; @@ -3324,19 +3361,21 @@ bool TypeSystemClang::IsPointerOrReferenceType( case clang::Type::ObjCObjectPointer: if (pointee_type) pointee_type->SetCompilerType( - this, llvm::cast<clang::ObjCObjectPointerType>(qual_type) - ->getPointeeType().getAsOpaquePtr()); + weak_from_this(), + llvm::cast<clang::ObjCObjectPointerType>(qual_type) + ->getPointeeType() + .getAsOpaquePtr()); return true; case clang::Type::BlockPointer: if (pointee_type) pointee_type->SetCompilerType( - this, llvm::cast<clang::BlockPointerType>(qual_type) - ->getPointeeType() - .getAsOpaquePtr()); + weak_from_this(), llvm::cast<clang::BlockPointerType>(qual_type) + ->getPointeeType() + .getAsOpaquePtr()); return true; case clang::Type::Pointer: if (pointee_type) - pointee_type->SetCompilerType(this, + pointee_type->SetCompilerType(weak_from_this(), llvm::cast<clang::PointerType>(qual_type) ->getPointeeType() .getAsOpaquePtr()); @@ -3344,23 +3383,23 @@ bool TypeSystemClang::IsPointerOrReferenceType( case clang::Type::MemberPointer: if (pointee_type) pointee_type->SetCompilerType( - this, llvm::cast<clang::MemberPointerType>(qual_type) - ->getPointeeType() - .getAsOpaquePtr()); + weak_from_this(), llvm::cast<clang::MemberPointerType>(qual_type) + ->getPointeeType() + .getAsOpaquePtr()); return true; case clang::Type::LValueReference: if (pointee_type) pointee_type->SetCompilerType( - this, llvm::cast<clang::LValueReferenceType>(qual_type) - ->desugar() - .getAsOpaquePtr()); + weak_from_this(), llvm::cast<clang::LValueReferenceType>(qual_type) + ->desugar() + .getAsOpaquePtr()); return true; case clang::Type::RValueReference: if (pointee_type) pointee_type->SetCompilerType( - this, llvm::cast<clang::RValueReferenceType>(qual_type) - ->desugar() - .getAsOpaquePtr()); + weak_from_this(), llvm::cast<clang::RValueReferenceType>(qual_type) + ->desugar() + .getAsOpaquePtr()); return true; default: break; @@ -3382,18 +3421,18 @@ bool TypeSystemClang::IsReferenceType(lldb::opaque_compiler_type_t type, case clang::Type::LValueReference: if (pointee_type) pointee_type->SetCompilerType( - this, llvm::cast<clang::LValueReferenceType>(qual_type) - ->desugar() - .getAsOpaquePtr()); + weak_from_this(), llvm::cast<clang::LValueReferenceType>(qual_type) + ->desugar() + .getAsOpaquePtr()); if (is_rvalue) *is_rvalue = false; return true; case clang::Type::RValueReference: if (pointee_type) pointee_type->SetCompilerType( - this, llvm::cast<clang::RValueReferenceType>(qual_type) - ->desugar() - .getAsOpaquePtr()); + weak_from_this(), llvm::cast<clang::RValueReferenceType>(qual_type) + ->desugar() + .getAsOpaquePtr()); if (is_rvalue) *is_rvalue = true; return true; @@ -3547,7 +3586,7 @@ bool TypeSystemClang::IsPossibleDynamicType(lldb::opaque_compiler_type_t type, llvm::cast<clang::BuiltinType>(qual_type)->getKind() == clang::BuiltinType::ObjCId) { if (dynamic_pointee_type) - dynamic_pointee_type->SetCompilerType(this, type); + dynamic_pointee_type->SetCompilerType(weak_from_this(), type); return true; } break; @@ -3565,9 +3604,10 @@ bool TypeSystemClang::IsPossibleDynamicType(lldb::opaque_compiler_type_t type, } if (dynamic_pointee_type) dynamic_pointee_type->SetCompilerType( - this, llvm::cast<clang::ObjCObjectPointerType>(qual_type) - ->getPointeeType() - .getAsOpaquePtr()); + weak_from_this(), + llvm::cast<clang::ObjCObjectPointerType>(qual_type) + ->getPointeeType() + .getAsOpaquePtr()); return true; } break; @@ -3602,7 +3642,7 @@ bool TypeSystemClang::IsPossibleDynamicType(lldb::opaque_compiler_type_t type, case clang::BuiltinType::Void: if (dynamic_pointee_type) dynamic_pointee_type->SetCompilerType( - this, pointee_qual_type.getAsOpaquePtr()); + weak_from_this(), pointee_qual_type.getAsOpaquePtr()); return true; default: break; @@ -3634,7 +3674,7 @@ bool TypeSystemClang::IsPossibleDynamicType(lldb::opaque_compiler_type_t type, if (success) { if (dynamic_pointee_type) dynamic_pointee_type->SetCompilerType( - this, pointee_qual_type.getAsOpaquePtr()); + weak_from_this(), pointee_qual_type.getAsOpaquePtr()); return true; } } @@ -3646,7 +3686,7 @@ bool TypeSystemClang::IsPossibleDynamicType(lldb::opaque_compiler_type_t type, if (check_objc) { if (dynamic_pointee_type) dynamic_pointee_type->SetCompilerType( - this, pointee_qual_type.getAsOpaquePtr()); + weak_from_this(), pointee_qual_type.getAsOpaquePtr()); return true; } break; @@ -3693,18 +3733,18 @@ bool TypeSystemClang::SupportsLanguage(lldb::LanguageType language) { return TypeSystemClangSupportsLanguage(language); } -Optional<std::string> +std::optional<std::string> TypeSystemClang::GetCXXClassName(const CompilerType &type) { if (!type) - return llvm::None; + return std::nullopt; clang::QualType qual_type(ClangUtil::GetCanonicalQualType(type)); if (qual_type.isNull()) - return llvm::None; + return std::nullopt; clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl(); if (!cxx_record_decl) - return llvm::None; + return std::nullopt; return std::string(cxx_record_decl->getIdentifier()->getNameStart()); } @@ -3765,7 +3805,8 @@ bool TypeSystemClang::GetCompleteType(lldb::opaque_compiler_type_t type) { allow_completion); } -ConstString TypeSystemClang::GetTypeName(lldb::opaque_compiler_type_t type) { +ConstString TypeSystemClang::GetTypeName(lldb::opaque_compiler_type_t type, + bool base_only) { if (!type) return ConstString(); @@ -3787,6 +3828,12 @@ ConstString TypeSystemClang::GetTypeName(lldb::opaque_compiler_type_t type) { return ConstString(GetTypeNameForDecl(typedef_decl)); } + // For consistency, this follows the same code path that clang uses to emit + // debug info. This also handles when we don't want any scopes preceding the + // name. + if (auto *named_decl = qual_type->getAsTagDecl()) + return ConstString(GetTypeNameForDecl(named_decl, !base_only)); + return ConstString(qual_type.getAsString(GetTypePrintingPolicy())); } @@ -3833,14 +3880,15 @@ TypeSystemClang::GetTypeInfo(lldb::opaque_compiler_type_t type, case clang::BuiltinType::ObjCClass: if (pointee_or_element_clang_type) pointee_or_element_clang_type->SetCompilerType( - this, getASTContext().ObjCBuiltinClassTy.getAsOpaquePtr()); + weak_from_this(), + getASTContext().ObjCBuiltinClassTy.getAsOpaquePtr()); builtin_type_flags |= eTypeIsPointer | eTypeIsObjC; break; case clang::BuiltinType::ObjCSel: if (pointee_or_element_clang_type) pointee_or_element_clang_type->SetCompilerType( - this, getASTContext().CharTy.getAsOpaquePtr()); + weak_from_this(), getASTContext().CharTy.getAsOpaquePtr()); builtin_type_flags |= eTypeIsPointer | eTypeIsObjC; break; @@ -3883,7 +3931,7 @@ TypeSystemClang::GetTypeInfo(lldb::opaque_compiler_type_t type, case clang::Type::BlockPointer: if (pointee_or_element_clang_type) pointee_or_element_clang_type->SetCompilerType( - this, qual_type->getPointeeType().getAsOpaquePtr()); + weak_from_this(), qual_type->getPointeeType().getAsOpaquePtr()); return eTypeIsPointer | eTypeHasChildren | eTypeIsBlock; case clang::Type::Complex: { @@ -3907,9 +3955,9 @@ TypeSystemClang::GetTypeInfo(lldb::opaque_compiler_type_t type, case clang::Type::VariableArray: if (pointee_or_element_clang_type) pointee_or_element_clang_type->SetCompilerType( - this, llvm::cast<clang::ArrayType>(qual_type.getTypePtr()) - ->getElementType() - .getAsOpaquePtr()); + weak_from_this(), llvm::cast<clang::ArrayType>(qual_type.getTypePtr()) + ->getElementType() + .getAsOpaquePtr()); return eTypeHasChildren | eTypeIsArray; case clang::Type::DependentName: @@ -3922,10 +3970,10 @@ TypeSystemClang::GetTypeInfo(lldb::opaque_compiler_type_t type, case clang::Type::Enum: if (pointee_or_element_clang_type) pointee_or_element_clang_type->SetCompilerType( - this, llvm::cast<clang::EnumType>(qual_type) - ->getDecl() - ->getIntegerType() - .getAsOpaquePtr()); + weak_from_this(), llvm::cast<clang::EnumType>(qual_type) + ->getDecl() + ->getIntegerType() + .getAsOpaquePtr()); return eTypeIsEnumeration | eTypeHasValue; case clang::Type::FunctionProto: @@ -3939,9 +3987,10 @@ TypeSystemClang::GetTypeInfo(lldb::opaque_compiler_type_t type, case clang::Type::RValueReference: if (pointee_or_element_clang_type) pointee_or_element_clang_type->SetCompilerType( - this, llvm::cast<clang::ReferenceType>(qual_type.getTypePtr()) - ->getPointeeType() - .getAsOpaquePtr()); + weak_from_this(), + llvm::cast<clang::ReferenceType>(qual_type.getTypePtr()) + ->getPointeeType() + .getAsOpaquePtr()); return eTypeHasChildren | eTypeIsReference | eTypeHasValue; case clang::Type::MemberPointer: @@ -3950,7 +3999,7 @@ TypeSystemClang::GetTypeInfo(lldb::opaque_compiler_type_t type, case clang::Type::ObjCObjectPointer: if (pointee_or_element_clang_type) pointee_or_element_clang_type->SetCompilerType( - this, qual_type->getPointeeType().getAsOpaquePtr()); + weak_from_this(), qual_type->getPointeeType().getAsOpaquePtr()); return eTypeHasChildren | eTypeIsObjC | eTypeIsClass | eTypeIsPointer | eTypeHasValue; @@ -3962,7 +4011,7 @@ TypeSystemClang::GetTypeInfo(lldb::opaque_compiler_type_t type, case clang::Type::Pointer: if (pointee_or_element_clang_type) pointee_or_element_clang_type->SetCompilerType( - this, qual_type->getPointeeType().getAsOpaquePtr()); + weak_from_this(), qual_type->getPointeeType().getAsOpaquePtr()); return eTypeHasChildren | eTypeIsPointer | eTypeHasValue; case clang::Type::Record: @@ -4670,14 +4719,16 @@ TypeSystemClang::GetFloatTypeSemantics(size_t byte_size) { return ast.getFloatTypeSemantics(ast.FloatTy); else if (bit_size == ast.getTypeSize(ast.DoubleTy)) return ast.getFloatTypeSemantics(ast.DoubleTy); - else if (bit_size == ast.getTypeSize(ast.LongDoubleTy)) + else if (bit_size == ast.getTypeSize(ast.LongDoubleTy) || + bit_size == llvm::APFloat::semanticsSizeInBits( + ast.getFloatTypeSemantics(ast.LongDoubleTy))) return ast.getFloatTypeSemantics(ast.LongDoubleTy); else if (bit_size == ast.getTypeSize(ast.HalfTy)) return ast.getFloatTypeSemantics(ast.HalfTy); return llvm::APFloatBase::Bogus(); } -Optional<uint64_t> +std::optional<uint64_t> TypeSystemClang::GetBitSize(lldb::opaque_compiler_type_t type, ExecutionContextScope *exe_scope) { if (GetCompleteType(type)) { @@ -4688,7 +4739,7 @@ TypeSystemClang::GetBitSize(lldb::opaque_compiler_type_t type, if (GetCompleteType(type)) return getASTContext().getTypeSize(qual_type); else - return None; + return std::nullopt; break; case clang::Type::ObjCInterface: @@ -4719,7 +4770,7 @@ TypeSystemClang::GetBitSize(lldb::opaque_compiler_type_t type, } } } - LLVM_FALLTHROUGH; + [[fallthrough]]; default: const uint32_t bit_size = getASTContext().getTypeSize(qual_type); if (bit_size == 0) { @@ -4738,10 +4789,10 @@ TypeSystemClang::GetBitSize(lldb::opaque_compiler_type_t type, return bit_size; } } - return None; + return std::nullopt; } -llvm::Optional<size_t> +std::optional<size_t> TypeSystemClang::GetTypeBitAlign(lldb::opaque_compiler_type_t type, ExecutionContextScope *exe_scope) { if (GetCompleteType(type)) @@ -5095,7 +5146,9 @@ lldb::Encoding TypeSystemClang::GetEncoding(lldb::opaque_compiler_type_t type, case clang::Type::Record: break; case clang::Type::Enum: - return lldb::eEncodingSint; + return qual_type->isUnsignedIntegerOrEnumerationType() + ? lldb::eEncodingUint + : lldb::eEncodingSint; case clang::Type::DependentSizedArray: case clang::Type::DependentSizedExtVector: case clang::Type::UnresolvedUsing: @@ -5304,7 +5357,7 @@ static bool ObjCDeclHasIVars(clang::ObjCInterfaceDecl *class_interface_decl, return false; } -static Optional<SymbolFile::ArrayInfo> +static std::optional<SymbolFile::ArrayInfo> GetDynamicArrayInfo(TypeSystemClang &ast, SymbolFile *sym_file, clang::QualType qual_type, const ExecutionContext *exe_ctx) { @@ -5312,7 +5365,7 @@ GetDynamicArrayInfo(TypeSystemClang &ast, SymbolFile *sym_file, if (auto *metadata = ast.GetMetadata(qual_type.getTypePtr())) return sym_file->GetDynamicArrayInfoForUID(metadata->GetUserID(), exe_ctx); - return llvm::None; + return std::nullopt; } uint32_t TypeSystemClang::GetNumChildren(lldb::opaque_compiler_type_t type, @@ -5762,9 +5815,10 @@ CompilerType TypeSystemClang::GetFieldAtIndex(lldb::opaque_compiler_type_t type, objc_interface_type->getDecl(); if (class_interface_decl) { return CompilerType( - this, GetObjCFieldAtIndex(&getASTContext(), class_interface_decl, - idx, name, bit_offset_ptr, - bitfield_bit_size_ptr, is_bitfield_ptr)); + weak_from_this(), + GetObjCFieldAtIndex(&getASTContext(), class_interface_decl, idx, + name, bit_offset_ptr, bitfield_bit_size_ptr, + is_bitfield_ptr)); } } break; @@ -5780,9 +5834,10 @@ CompilerType TypeSystemClang::GetFieldAtIndex(lldb::opaque_compiler_type_t type, clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); return CompilerType( - this, GetObjCFieldAtIndex(&getASTContext(), class_interface_decl, - idx, name, bit_offset_ptr, - bitfield_bit_size_ptr, is_bitfield_ptr)); + weak_from_this(), + GetObjCFieldAtIndex(&getASTContext(), class_interface_decl, idx, + name, bit_offset_ptr, bitfield_bit_size_ptr, + is_bitfield_ptr)); } } break; @@ -6244,7 +6299,7 @@ CompilerType TypeSystemClang::GetChildCompilerTypeAtIndex( child_byte_offset = bit_offset / 8; CompilerType base_class_clang_type = GetType(base_class->getType()); child_name = base_class_clang_type.GetTypeName().AsCString(""); - Optional<uint64_t> size = + std::optional<uint64_t> size = base_class_clang_type.GetBitSize(get_exe_scope()); if (!size) return {}; @@ -6276,7 +6331,7 @@ CompilerType TypeSystemClang::GetChildCompilerTypeAtIndex( // alignment (field_type_info.second) from the AST context. CompilerType field_clang_type = GetType(field->getType()); assert(field_idx < record_layout.getFieldCount()); - Optional<uint64_t> size = + std::optional<uint64_t> size = field_clang_type.GetByteSize(get_exe_scope()); if (!size) return {}; @@ -6448,7 +6503,7 @@ CompilerType TypeSystemClang::GetChildCompilerTypeAtIndex( // We have a pointer to an simple type if (idx == 0 && pointee_clang_type.GetCompleteType()) { - if (Optional<uint64_t> size = + if (std::optional<uint64_t> size = pointee_clang_type.GetByteSize(get_exe_scope())) { child_byte_size = *size; child_byte_offset = 0; @@ -6471,7 +6526,7 @@ CompilerType TypeSystemClang::GetChildCompilerTypeAtIndex( ::snprintf(element_name, sizeof(element_name), "[%" PRIu64 "]", static_cast<uint64_t>(idx)); child_name.assign(element_name); - if (Optional<uint64_t> size = + if (std::optional<uint64_t> size = element_type.GetByteSize(get_exe_scope())) { child_byte_size = *size; child_byte_offset = (int32_t)idx * (int32_t)child_byte_size; @@ -6490,7 +6545,7 @@ CompilerType TypeSystemClang::GetChildCompilerTypeAtIndex( CompilerType element_type = GetType(array->getElementType()); if (element_type.GetCompleteType()) { child_name = std::string(llvm::formatv("[{0}]", idx)); - if (Optional<uint64_t> size = + if (std::optional<uint64_t> size = element_type.GetByteSize(get_exe_scope())) { child_byte_size = *size; child_byte_offset = (int32_t)idx * (int32_t)child_byte_size; @@ -6529,7 +6584,7 @@ CompilerType TypeSystemClang::GetChildCompilerTypeAtIndex( // We have a pointer to an simple type if (idx == 0) { - if (Optional<uint64_t> size = + if (std::optional<uint64_t> size = pointee_clang_type.GetByteSize(get_exe_scope())) { child_byte_size = *size; child_byte_offset = 0; @@ -6567,7 +6622,7 @@ CompilerType TypeSystemClang::GetChildCompilerTypeAtIndex( // We have a pointer to an simple type if (idx == 0) { - if (Optional<uint64_t> size = + if (std::optional<uint64_t> size = pointee_clang_type.GetByteSize(get_exe_scope())) { child_byte_size = *size; child_byte_offset = 0; @@ -6584,9 +6639,10 @@ CompilerType TypeSystemClang::GetChildCompilerTypeAtIndex( return CompilerType(); } -static uint32_t GetIndexForRecordBase(const clang::RecordDecl *record_decl, - const clang::CXXBaseSpecifier *base_spec, - bool omit_empty_base_classes) { +uint32_t TypeSystemClang::GetIndexForRecordBase( + const clang::RecordDecl *record_decl, + const clang::CXXBaseSpecifier *base_spec, + bool omit_empty_base_classes) { uint32_t child_idx = 0; const clang::CXXRecordDecl *cxx_record_decl = @@ -6611,9 +6667,9 @@ static uint32_t GetIndexForRecordBase(const clang::RecordDecl *record_decl, return UINT32_MAX; } -static uint32_t GetIndexForRecordChild(const clang::RecordDecl *record_decl, - clang::NamedDecl *canonical_decl, - bool omit_empty_base_classes) { +uint32_t TypeSystemClang::GetIndexForRecordChild( + const clang::RecordDecl *record_decl, clang::NamedDecl *canonical_decl, + bool omit_empty_base_classes) { uint32_t child_idx = TypeSystemClang::GetNumBaseClasses( llvm::dyn_cast<clang::CXXRecordDecl>(record_decl), omit_empty_base_classes); @@ -7095,6 +7151,17 @@ TypeSystemClang::GetIndexOfChildWithName(lldb::opaque_compiler_type_t type, return UINT32_MAX; } +bool TypeSystemClang::IsTemplateType(lldb::opaque_compiler_type_t type) { + if (!type) + return false; + CompilerType ct(weak_from_this(), type); + const clang::Type *clang_type = ClangUtil::GetQualType(ct).getTypePtr(); + if (auto *cxx_record_decl = dyn_cast<clang::TagType>(clang_type)) + return isa<clang::ClassTemplateSpecializationDecl>( + cxx_record_decl->getDecl()); + return false; +} + size_t TypeSystemClang::GetNumTemplateArguments(lldb::opaque_compiler_type_t type, bool expand_pack) { @@ -7186,8 +7253,7 @@ GetNthTemplateArgument(const clang::ClassTemplateSpecializationDecl *decl, // (including the ones preceding the parameter pack). const auto &pack = args[last_idx]; const size_t pack_idx = idx - last_idx; - const size_t pack_size = pack.pack_size(); - assert(pack_idx < pack_size && "parameter pack index out-of-bounds"); + assert(pack_idx < pack.pack_size() && "parameter pack index out-of-bounds"); return &pack.pack_elements()[pack_idx]; } @@ -7249,24 +7315,24 @@ TypeSystemClang::GetTypeTemplateArgument(lldb::opaque_compiler_type_t type, return GetType(arg->getAsType()); } -Optional<CompilerType::IntegralTemplateArgument> +std::optional<CompilerType::IntegralTemplateArgument> TypeSystemClang::GetIntegralTemplateArgument(lldb::opaque_compiler_type_t type, size_t idx, bool expand_pack) { const clang::ClassTemplateSpecializationDecl *template_decl = GetAsTemplateSpecialization(type); if (!template_decl) - return llvm::None; + return std::nullopt; const auto *arg = GetNthTemplateArgument(template_decl, idx, expand_pack); if (!arg || arg->getKind() != clang::TemplateArgument::Integral) - return llvm::None; + return std::nullopt; return {{arg->getAsIntegral(), GetType(arg->getIntegralType())}}; } CompilerType TypeSystemClang::GetTypeForFormatters(void *type) { if (type) - return ClangUtil::RemoveFastQualifiers(CompilerType(this, type)); + return ClangUtil::RemoveFastQualifiers(CompilerType(weak_from_this(), type)); return CompilerType(); } @@ -7320,8 +7386,8 @@ clang::FieldDecl *TypeSystemClang::AddFieldToRecordType( uint32_t bitfield_bit_size) { if (!type.IsValid() || !field_clang_type.IsValid()) return nullptr; - TypeSystemClang *ast = - llvm::dyn_cast_or_null<TypeSystemClang>(type.GetTypeSystem()); + auto ts = type.GetTypeSystem(); + auto ast = ts.dyn_cast_or_null<TypeSystemClang>(); if (!ast) return nullptr; clang::ASTContext &clang_ast = ast->getASTContext(); @@ -7414,7 +7480,8 @@ void TypeSystemClang::BuildIndirectFields(const CompilerType &type) { if (!type) return; - TypeSystemClang *ast = llvm::dyn_cast<TypeSystemClang>(type.GetTypeSystem()); + auto ts = type.GetTypeSystem(); + auto ast = ts.dyn_cast_or_null<TypeSystemClang>(); if (!ast) return; @@ -7520,8 +7587,8 @@ void TypeSystemClang::BuildIndirectFields(const CompilerType &type) { void TypeSystemClang::SetIsPacked(const CompilerType &type) { if (type) { - TypeSystemClang *ast = - llvm::dyn_cast<TypeSystemClang>(type.GetTypeSystem()); + auto ts = type.GetTypeSystem(); + auto ast = ts.dyn_cast_or_null<TypeSystemClang>(); if (ast) { clang::RecordDecl *record_decl = GetAsRecordDecl(type); @@ -7540,7 +7607,8 @@ clang::VarDecl *TypeSystemClang::AddVariableToRecordType( if (!type.IsValid() || !var_type.IsValid()) return nullptr; - TypeSystemClang *ast = llvm::dyn_cast<TypeSystemClang>(type.GetTypeSystem()); + auto ts = type.GetTypeSystem(); + auto ast = ts.dyn_cast_or_null<TypeSystemClang>(); if (!ast) return nullptr; @@ -7585,8 +7653,15 @@ void TypeSystemClang::SetIntegerInitializerForVariable( const EnumDecl *enum_decl = enum_type->getDecl(); qt = enum_decl->getIntegerType(); } - var->setInit(IntegerLiteral::Create(ast, init_value, qt.getUnqualifiedType(), - SourceLocation())); + // Bools are handled separately because the clang AST printer handles bools + // separately from other integral types. + if (qt->isSpecificBuiltinType(BuiltinType::Bool)) { + var->setInit(CXXBoolLiteralExpr::Create( + ast, !init_value.isZero(), qt.getUnqualifiedType(), SourceLocation())); + } else { + var->setInit(IntegerLiteral::Create( + ast, init_value, qt.getUnqualifiedType(), SourceLocation())); + } } void TypeSystemClang::SetFloatingInitializerForVariable( @@ -7840,8 +7915,8 @@ bool TypeSystemClang::TransferBaseClasses( bool TypeSystemClang::SetObjCSuperClass( const CompilerType &type, const CompilerType &superclass_clang_type) { - TypeSystemClang *ast = - llvm::dyn_cast_or_null<TypeSystemClang>(type.GetTypeSystem()); + auto ts = type.GetTypeSystem(); + auto ast = ts.dyn_cast_or_null<TypeSystemClang>(); if (!ast) return false; clang::ASTContext &clang_ast = ast->getASTContext(); @@ -7869,7 +7944,8 @@ bool TypeSystemClang::AddObjCClassProperty( if (!type || !property_clang_type.IsValid() || property_name == nullptr || property_name[0] == '\0') return false; - TypeSystemClang *ast = llvm::dyn_cast<TypeSystemClang>(type.GetTypeSystem()); + auto ts = type.GetTypeSystem(); + auto ast = ts.dyn_cast_or_null<TypeSystemClang>(); if (!ast) return false; clang::ASTContext &clang_ast = ast->getASTContext(); @@ -8088,8 +8164,8 @@ clang::ObjCMethodDecl *TypeSystemClang::AddMethodToObjCObjectType( if (class_interface_decl == nullptr) return nullptr; - TypeSystemClang *lldb_ast = - llvm::dyn_cast<TypeSystemClang>(type.GetTypeSystem()); + auto ts = type.GetTypeSystem(); + auto lldb_ast = ts.dyn_cast_or_null<TypeSystemClang>(); if (lldb_ast == nullptr) return nullptr; clang::ASTContext &ast = lldb_ast->getASTContext(); @@ -8292,8 +8368,8 @@ bool TypeSystemClang::CompleteTagDeclarationDefinition( if (qual_type.isNull()) return false; - TypeSystemClang *lldb_ast = - llvm::dyn_cast<TypeSystemClang>(type.GetTypeSystem()); + auto ts = type.GetTypeSystem(); + auto lldb_ast = ts.dyn_cast_or_null<TypeSystemClang>(); if (lldb_ast == nullptr) return false; @@ -8377,7 +8453,8 @@ clang::EnumConstantDecl *TypeSystemClang::AddEnumerationValueToEnumerationType( if (!enum_type || ConstString(name).IsEmpty()) return nullptr; - lldbassert(enum_type.GetTypeSystem() == static_cast<TypeSystem *>(this)); + lldbassert(enum_type.GetTypeSystem().GetSharedPointer().get() == + static_cast<TypeSystem *>(this)); lldb::opaque_compiler_type_t enum_opaque_compiler_type = enum_type.GetOpaqueQualType(); @@ -8444,8 +8521,8 @@ TypeSystemClang::CreateMemberPointerType(const CompilerType &type, const CompilerType &pointee_type) { if (type && pointee_type.IsValid() && type.GetTypeSystem() == pointee_type.GetTypeSystem()) { - TypeSystemClang *ast = - llvm::dyn_cast<TypeSystemClang>(type.GetTypeSystem()); + auto ts = type.GetTypeSystem(); + auto ast = ts.dyn_cast_or_null<TypeSystemClang>(); if (!ast) return CompilerType(); return ast->GetType(ast->getASTContext().getMemberPointerType( @@ -8911,7 +8988,7 @@ static bool DumpEnumValue(const clang::QualType &qual_type, Stream *s, for (auto *enumerator : enum_decl->enumerators()) { uint64_t val = enumerator->getInitVal().getSExtValue(); val = llvm::SignExtend64(val, 8*byte_size); - if (llvm::countPopulation(val) != 1 && (val & ~covered_bits) != 0) + if (llvm::popcount(val) != 1 && (val & ~covered_bits) != 0) can_be_bitfield = false; covered_bits |= val; ++num_enumerators; @@ -8947,9 +9024,10 @@ static bool DumpEnumValue(const clang::QualType &qual_type, Stream *s, // Sort in reverse order of the number of the population count, so that in // `enum {A, B, ALL = A|B }` we visit ALL first. Use a stable sort so that // A | C where A is declared before C is displayed in this order. - std::stable_sort(values.begin(), values.end(), [](const auto &a, const auto &b) { - return llvm::countPopulation(a.first) > llvm::countPopulation(b.first); - }); + std::stable_sort(values.begin(), values.end(), + [](const auto &a, const auto &b) { + return llvm::popcount(a.first) > llvm::popcount(b.first); + }); for (const auto &val : values) { if ((remaining_value & val.first) != val.first) @@ -9022,7 +9100,7 @@ bool TypeSystemClang::DumpTypeValue( bitfield_bit_offset, bitfield_bit_size); // format was not enum, just fall through and dump the value as // requested.... - LLVM_FALLTHROUGH; + [[fallthrough]]; default: // We are down to a scalar type that we just need to display. @@ -9141,7 +9219,7 @@ void TypeSystemClang::DumpTypeDescription(lldb::opaque_compiler_type_t type, StreamFile s(stdout, false); DumpTypeDescription(type, &s, level); - CompilerType ct(this, type); + CompilerType ct(weak_from_this(), type); const clang::Type *clang_type = ClangUtil::GetQualType(ct).getTypePtr(); ClangASTMetadata *metadata = GetMetadata(clang_type); if (metadata) { @@ -9206,14 +9284,8 @@ void TypeSystemClang::DumpTypeDescription(lldb::opaque_compiler_type_t type, if (level == eDescriptionLevelVerbose) record_decl->dump(llvm_ostrm); else { - if (auto *cxx_record_decl = - llvm::dyn_cast<clang::CXXRecordDecl>(record_decl)) - cxx_record_decl->print(llvm_ostrm, - getASTContext().getPrintingPolicy(), - s->GetIndentLevel()); - else - record_decl->print(llvm_ostrm, getASTContext().getPrintingPolicy(), - s->GetIndentLevel()); + record_decl->print(llvm_ostrm, getASTContext().getPrintingPolicy(), + s->GetIndentLevel()); } } break; @@ -9322,7 +9394,9 @@ clang::ClassTemplateDecl *TypeSystemClang::ParseClassTemplateDecl( const TypeSystemClang::TemplateParameterInfos &template_param_infos) { if (template_param_infos.IsValid()) { std::string template_basename(parent_name); - template_basename.erase(template_basename.find('<')); + // With -gsimple-template-names we may omit template parameters in the name. + if (auto i = template_basename.find('<'); i != std::string::npos) + template_basename.erase(i); return CreateClassTemplateDecl(decl_ctx, owning_module, access_type, template_basename.c_str(), tag_decl_kind, @@ -9362,6 +9436,12 @@ PDBASTParser *TypeSystemClang::GetPDBParser() { m_pdb_ast_parser_up = std::make_unique<PDBASTParser>(*this); return m_pdb_ast_parser_up.get(); } + +npdb::PdbAstBuilder *TypeSystemClang::GetNativePDBParser() { + if (!m_native_pdb_ast_parser_up) + m_native_pdb_ast_parser_up = std::make_unique<npdb::PdbAstBuilder>(*this); + return m_native_pdb_ast_parser_up.get(); +} #endif // LLDB_ENABLE_ALL bool TypeSystemClang::LayoutRecordType( @@ -9378,6 +9458,8 @@ bool TypeSystemClang::LayoutRecordType( #ifdef LLDB_ENABLE_ALL if (!importer && m_pdb_ast_parser_up) importer = &m_pdb_ast_parser_up->GetClangASTImporter(); + if (!importer && m_native_pdb_ast_parser_up) + importer = &m_native_pdb_ast_parser_up->GetClangASTImporter(); #endif // LLDB_ENABLE_ALL if (!importer) return false; @@ -9792,6 +9874,30 @@ TypeSystemClang::DeclContextGetTypeSystemClang(const CompilerDeclContext &dc) { return nullptr; } +void TypeSystemClang::RequireCompleteType(CompilerType type) { + // Technically, enums can be incomplete too, but we don't handle those as they + // are emitted even under -flimit-debug-info. + if (!TypeSystemClang::IsCXXClassType(type)) + return; + + if (type.GetCompleteType()) + return; + + // No complete definition in this module. Mark the class as complete to + // satisfy local ast invariants, but make a note of the fact that + // it is not _really_ complete so we can later search for a definition in a + // different module. + // Since we provide layout assistance, layouts of types containing this class + // will be correct even if we are not able to find the definition elsewhere. + bool started = TypeSystemClang::StartTagDeclarationDefinition(type); + lldbassert(started && "Unable to start a class type definition."); + TypeSystemClang::CompleteTagDeclarationDefinition(type); + const clang::TagDecl *td = ClangUtil::GetAsTagDecl(type); + auto ts = type.GetTypeSystem().dyn_cast_or_null<TypeSystemClang>(); + if (ts) + ts->SetDeclIsForcefullyCompleted(td); +} + namespace { /// A specialized scratch AST used within ScratchTypeSystemClang. /// These are the ASTs backing the different IsolatedASTKinds. They behave @@ -9820,7 +9926,7 @@ public: } // namespace char ScratchTypeSystemClang::ID; -const llvm::NoneType ScratchTypeSystemClang::DefaultAST = llvm::None; +const std::nullopt_t ScratchTypeSystemClang::DefaultAST = std::nullopt; ScratchTypeSystemClang::ScratchTypeSystemClang(Target &target, llvm::Triple triple) @@ -9840,9 +9946,9 @@ void ScratchTypeSystemClang::Finalize() { m_scratch_ast_source_up.reset(); } -TypeSystemClang * +TypeSystemClangSP ScratchTypeSystemClang::GetForTarget(Target &target, - llvm::Optional<IsolatedASTKind> ast_kind, + std::optional<IsolatedASTKind> ast_kind, bool create_on_demand) { auto type_system_or_err = target.GetScratchTypeSystemForLanguage( lldb::eLanguageTypeC, create_on_demand); @@ -9851,13 +9957,17 @@ ScratchTypeSystemClang::GetForTarget(Target &target, "Couldn't get scratch TypeSystemClang"); return nullptr; } - ScratchTypeSystemClang &scratch_ast = - llvm::cast<ScratchTypeSystemClang>(type_system_or_err.get()); + auto ts_sp = *type_system_or_err; + ScratchTypeSystemClang *scratch_ast = + llvm::dyn_cast_or_null<ScratchTypeSystemClang>(ts_sp.get()); + if (!scratch_ast) + return nullptr; // If no dedicated sub-AST was requested, just return the main AST. if (ast_kind == DefaultAST) - return &scratch_ast; + return std::static_pointer_cast<TypeSystemClang>(ts_sp); // Search the sub-ASTs. - return &scratch_ast.GetIsolatedAST(*ast_kind); + return std::static_pointer_cast<TypeSystemClang>( + scratch_ast->GetIsolatedAST(*ast_kind).shared_from_this()); } /// Returns a human-readable name that uniquely identifiers the sub-AST kind. @@ -9967,9 +10077,36 @@ TypeSystemClang &ScratchTypeSystemClang::GetIsolatedAST( return *found_ast->second; // Couldn't find the requested sub-AST, so create it now. - std::unique_ptr<TypeSystemClang> new_ast; - new_ast.reset(new SpecializedScratchAST(GetSpecializedASTName(feature), - m_triple, CreateASTSource())); - m_isolated_asts[feature] = std::move(new_ast); - return *m_isolated_asts[feature]; + std::shared_ptr<TypeSystemClang> new_ast_sp = + std::make_shared<SpecializedScratchAST>(GetSpecializedASTName(feature), + m_triple, CreateASTSource()); + m_isolated_asts.insert({feature, new_ast_sp}); + return *new_ast_sp; +} + +bool TypeSystemClang::IsForcefullyCompleted(lldb::opaque_compiler_type_t type) { + if (type) { + clang::QualType qual_type(GetQualType(type)); + const clang::RecordType *record_type = + llvm::dyn_cast<clang::RecordType>(qual_type.getTypePtr()); + if (record_type) { + const clang::RecordDecl *record_decl = record_type->getDecl(); + assert(record_decl); + ClangASTMetadata *metadata = GetMetadata(record_decl); + if (metadata) + return metadata->IsForcefullyCompleted(); + } + } + return false; +} + +bool TypeSystemClang::SetDeclIsForcefullyCompleted(const clang::TagDecl *td) { + if (td == nullptr) + return false; + ClangASTMetadata *metadata = GetMetadata(td); + if (metadata == nullptr) + return false; + m_has_forcefully_completed_types = true; + metadata->SetIsForcefullyCompleted(); + return true; } diff --git a/contrib/llvm-project/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h b/contrib/llvm-project/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h index 6ecbfdd4d1a5..2e7ebe62f303 100644 --- a/contrib/llvm-project/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h +++ b/contrib/llvm-project/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h @@ -13,8 +13,8 @@ #include <functional> #include <initializer_list> -#include <map> #include <memory> +#include <optional> #include <set> #include <string> #include <utility> @@ -23,6 +23,7 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/ASTFwd.h" #include "clang/AST/TemplateBase.h" +#include "clang/AST/Type.h" #include "clang/Basic/TargetInfo.h" #include "llvm/ADT/APSInt.h" #include "llvm/ADT/SmallVector.h" @@ -227,7 +228,7 @@ public: static bool AreTypesSame(CompilerType type1, CompilerType type2, bool ignore_qualifiers = false); - /// Creates a CompilerType form the given QualType with the current + /// Creates a CompilerType from the given QualType with the current /// TypeSystemClang instance as the CompilerType's typesystem. /// \param qt The QualType for a type that belongs to the ASTContext of this /// TypeSystemClang. @@ -240,7 +241,7 @@ public: // Check that the type actually belongs to this TypeSystemClang. assert(qt->getAsTagDecl() == nullptr || &qt->getAsTagDecl()->getASTContext() == &getASTContext()); - return CompilerType(this, qt.getAsOpaquePtr()); + return CompilerType(weak_from_this(), qt.getAsOpaquePtr()); } CompilerType GetTypeForDecl(clang::NamedDecl *decl); @@ -270,9 +271,10 @@ public: clang::NamedDecl *named_decl = *result.begin(); if (const RecordDeclType *record_decl = llvm::dyn_cast<RecordDeclType>(named_decl)) - compiler_type.SetCompilerType( - this, clang::QualType(record_decl->getTypeForDecl(), 0) - .getAsOpaquePtr()); + compiler_type = + CompilerType(weak_from_this(), + clang::QualType(record_decl->getTypeForDecl(), 0) + .getAsOpaquePtr()); } } @@ -302,8 +304,16 @@ public: static clang::AccessSpecifier UnifyAccessSpecifiers(clang::AccessSpecifier lhs, clang::AccessSpecifier rhs); - static uint32_t GetNumBaseClasses(const clang::CXXRecordDecl *cxx_record_decl, - bool omit_empty_base_classes); + uint32_t GetNumBaseClasses(const clang::CXXRecordDecl *cxx_record_decl, + bool omit_empty_base_classes); + + uint32_t GetIndexForRecordChild(const clang::RecordDecl *record_decl, + clang::NamedDecl *canonical_decl, + bool omit_empty_base_classes); + + uint32_t GetIndexForRecordBase(const clang::RecordDecl *record_decl, + const clang::CXXBaseSpecifier *base_spec, + bool omit_empty_base_classes); /// Synthesize a clang::Module and return its ID or a default-constructed ID. OptionalClangModuleID GetOrCreateClangModule(llvm::StringRef name, @@ -373,7 +383,9 @@ public: bool FieldIsBitfield(clang::FieldDecl *field, uint32_t &bitfield_bit_size); - static bool RecordHasFields(const clang::RecordDecl *record_decl); + bool RecordHasFields(const clang::RecordDecl *record_decl); + + bool BaseSpecifierIsEmpty(const clang::CXXBaseSpecifier *b); CompilerType CreateObjCClass(llvm::StringRef name, clang::DeclContext *decl_ctx, @@ -398,10 +410,11 @@ public: llvm::StringRef name, const CompilerType &function_Type, clang::StorageClass storage, bool is_inline); - CompilerType CreateFunctionType(const CompilerType &result_type, - const CompilerType *args, unsigned num_args, - bool is_variadic, unsigned type_quals, - clang::CallingConv cc = clang::CC_C); + CompilerType + CreateFunctionType(const CompilerType &result_type, const CompilerType *args, + unsigned num_args, bool is_variadic, unsigned type_quals, + clang::CallingConv cc = clang::CC_C, + clang::RefQualifierKind ref_qual = clang::RQ_None); clang::ParmVarDecl * CreateParameterDeclaration(clang::DeclContext *decl_ctx, @@ -442,6 +455,7 @@ public: DWARFASTParser *GetDWARFParser() override; #ifdef LLDB_ENABLE_ALL PDBASTParser *GetPDBParser() override; + npdb::PdbAstBuilder *GetNativePDBParser() override; #endif // LLDB_ENABLE_ALL // TypeSystemClang callbacks for external source lookups. @@ -634,15 +648,18 @@ public: bool SupportsLanguage(lldb::LanguageType language) override; - static llvm::Optional<std::string> GetCXXClassName(const CompilerType &type); + static std::optional<std::string> GetCXXClassName(const CompilerType &type); // Type Completion bool GetCompleteType(lldb::opaque_compiler_type_t type) override; + bool IsForcefullyCompleted(lldb::opaque_compiler_type_t type) override; + // Accessors - ConstString GetTypeName(lldb::opaque_compiler_type_t type) override; + ConstString GetTypeName(lldb::opaque_compiler_type_t type, + bool base_only) override; ConstString GetDisplayTypeName(lldb::opaque_compiler_type_t type) override; @@ -726,23 +743,22 @@ public: const llvm::fltSemantics &GetFloatTypeSemantics(size_t byte_size) override; - llvm::Optional<uint64_t> GetByteSize(lldb::opaque_compiler_type_t type, - ExecutionContextScope *exe_scope) { - if (llvm::Optional<uint64_t> bit_size = GetBitSize(type, exe_scope)) + std::optional<uint64_t> GetByteSize(lldb::opaque_compiler_type_t type, + ExecutionContextScope *exe_scope) { + if (std::optional<uint64_t> bit_size = GetBitSize(type, exe_scope)) return (*bit_size + 7) / 8; - return llvm::None; + return std::nullopt; } - llvm::Optional<uint64_t> - GetBitSize(lldb::opaque_compiler_type_t type, - ExecutionContextScope *exe_scope) override; + std::optional<uint64_t> GetBitSize(lldb::opaque_compiler_type_t type, + ExecutionContextScope *exe_scope) override; lldb::Encoding GetEncoding(lldb::opaque_compiler_type_t type, uint64_t &count) override; lldb::Format GetFormat(lldb::opaque_compiler_type_t type) override; - llvm::Optional<size_t> + std::optional<size_t> GetTypeBitAlign(lldb::opaque_compiler_type_t type, ExecutionContextScope *exe_scope) override; @@ -812,6 +828,8 @@ public: const char *name, bool omit_empty_base_classes, std::vector<uint32_t> &child_indexes) override; + bool IsTemplateType(lldb::opaque_compiler_type_t type) override; + size_t GetNumTemplateArguments(lldb::opaque_compiler_type_t type, bool expand_pack) override; @@ -820,7 +838,7 @@ public: bool expand_pack) override; CompilerType GetTypeTemplateArgument(lldb::opaque_compiler_type_t type, size_t idx, bool expand_pack) override; - llvm::Optional<CompilerType::IntegralTemplateArgument> + std::optional<CompilerType::IntegralTemplateArgument> GetIntegralTemplateArgument(lldb::opaque_compiler_type_t type, size_t idx, bool expand_pack) override; @@ -1043,13 +1061,26 @@ public: return m_source_manager_up.get(); } + /// Complete a type from debug info, or mark it as forcefully completed if + /// there is no definition of the type in the current Module. Call this + /// function in contexts where the usual C++ rules require a type to be + /// complete (base class, member, etc.). + static void RequireCompleteType(CompilerType type); + + bool SetDeclIsForcefullyCompleted(const clang::TagDecl *td); + + /// Return the template parameters (including surrounding <>) in string form. + std::string + PrintTemplateParams(const TemplateParameterInfos &template_param_infos); + private: /// Returns the PrintingPolicy used when generating the internal type names. /// These type names are mostly used for the formatter selection. clang::PrintingPolicy GetTypePrintingPolicy(); /// Returns the internal type name for the given NamedDecl using the /// type printing policy. - std::string GetTypeNameForDecl(const clang::NamedDecl *named_decl); + std::string GetTypeNameForDecl(const clang::NamedDecl *named_decl, + bool qualified = true); const clang::ClassTemplateSpecializationDecl * GetAsTemplateSpecialization(lldb::opaque_compiler_type_t type); @@ -1072,6 +1103,7 @@ private: std::unique_ptr<DWARFASTParserClang> m_dwarf_ast_parser_up; #ifdef LLDB_ENABLE_ALL std::unique_ptr<PDBASTParser> m_pdb_ast_parser_up; + std::unique_ptr<npdb::PdbAstBuilder> m_native_pdb_ast_parser_up; #endif // LLDB_ENABLE_ALL std::unique_ptr<clang::MangleContext> m_mangle_ctx_up; uint32_t m_pointer_byte_size = 0; @@ -1135,12 +1167,12 @@ public: }; /// Alias for requesting the default scratch TypeSystemClang in GetForTarget. - // This isn't constexpr as gtest/llvm::Optional comparison logic is trying + // This isn't constexpr as gtest/std::optional comparison logic is trying // to get the address of this for pretty-printing. - static const llvm::NoneType DefaultAST; + static const std::nullopt_t DefaultAST; /// Infers the appropriate sub-AST from Clang's LangOptions. - static llvm::Optional<IsolatedASTKind> + static std::optional<IsolatedASTKind> InferIsolatedASTKindFromLangOpts(const clang::LangOptions &l) { // If modules are activated we want the dedicated C++ module AST. // See IsolatedASTKind::CppModules for more info. @@ -1158,9 +1190,9 @@ public: /// this parameter is false, this function returns a nullptr. /// \return The scratch type system of the target or a nullptr in case an /// error occurred. - static TypeSystemClang * + static lldb::TypeSystemClangSP GetForTarget(Target &target, - llvm::Optional<IsolatedASTKind> ast_kind = DefaultAST, + std::optional<IsolatedASTKind> ast_kind = DefaultAST, bool create_on_demand = true); /// Returns the scratch TypeSystemClang for the given target. The returned @@ -1170,8 +1202,8 @@ public: /// \param lang_opts The LangOptions of a clang ASTContext that the caller /// wants to export type information from. This is used to /// find the best matching sub-AST that will be returned. - static TypeSystemClang *GetForTarget(Target &target, - const clang::LangOptions &lang_opts) { + static lldb::TypeSystemClangSP + GetForTarget(Target &target, const clang::LangOptions &lang_opts) { return GetForTarget(target, InferIsolatedASTKindFromLangOpts(lang_opts)); } @@ -1230,7 +1262,7 @@ private: /// Map from IsolatedASTKind to their actual TypeSystemClang instance. /// This map is lazily filled with sub-ASTs and should be accessed via /// `GetSubAST` (which lazily fills this map). - std::unordered_map<IsolatedASTKey, std::unique_ptr<TypeSystemClang>> + llvm::DenseMap<IsolatedASTKey, std::shared_ptr<TypeSystemClang>> m_isolated_asts; }; diff --git a/contrib/llvm-project/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp b/contrib/llvm-project/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp index 03515a32ff86..47fc210b5d64 100644 --- a/contrib/llvm-project/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp @@ -84,10 +84,8 @@ bool UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly( const bool show_address = true; const bool show_bytes = true; const bool show_control_flow_kind = true; - m_inst_emulator_up->GetRegisterInfo(unwind_plan.GetRegisterKind(), - unwind_plan.GetInitialCFARegister(), - m_cfa_reg_info); - + m_cfa_reg_info = *m_inst_emulator_up->GetRegisterInfo( + unwind_plan.GetRegisterKind(), unwind_plan.GetInitialCFARegister()); m_fp_is_cfa = false; m_register_values.clear(); m_pushed_regs.clear(); @@ -130,9 +128,8 @@ bool UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly( // cache the stack pointer register number (in whatever register // numbering this UnwindPlan uses) for quick reference during // instruction parsing. - RegisterInfo sp_reg_info; - m_inst_emulator_up->GetRegisterInfo( - eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp_reg_info); + RegisterInfo sp_reg_info = *m_inst_emulator_up->GetRegisterInfo( + eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP); // The architecture dependent condition code of the last processed // instruction. @@ -172,8 +169,8 @@ bool UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly( lldb::RegisterKind row_kind = m_unwind_plan_ptr->GetRegisterKind(); // set m_cfa_reg_info to the row's CFA reg. - m_inst_emulator_up->GetRegisterInfo(row_kind, row_cfa_regnum, - m_cfa_reg_info); + m_cfa_reg_info = *m_inst_emulator_up->GetRegisterInfo( + row_kind, row_cfa_regnum); // set m_fp_is_cfa. if (sp_reg_info.kinds[row_kind] == row_cfa_regnum) m_fp_is_cfa = false; @@ -219,8 +216,8 @@ bool UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly( lldb::RegisterKind row_kind = m_unwind_plan_ptr->GetRegisterKind(); // set m_cfa_reg_info to the row's CFA reg. - m_inst_emulator_up->GetRegisterInfo(row_kind, row_cfa_regnum, - m_cfa_reg_info); + m_cfa_reg_info = *m_inst_emulator_up->GetRegisterInfo( + row_kind, row_cfa_regnum); // set m_fp_is_cfa. if (sp_reg_info.kinds[row_kind] == row_cfa_regnum) m_fp_is_cfa = false; @@ -455,7 +452,7 @@ size_t UnwindAssemblyInstEmulation::WriteMemory( case EmulateInstruction::eContextPushRegisterOnStack: { uint32_t reg_num = LLDB_INVALID_REGNUM; uint32_t generic_regnum = LLDB_INVALID_REGNUM; - assert(context.info_type == + assert(context.GetInfoType() == EmulateInstruction::eInfoTypeRegisterToRegisterPlusOffset && "unhandled case, add code to handle this!"); const uint32_t unwind_reg_kind = m_unwind_plan_ptr->GetRegisterKind(); @@ -574,7 +571,8 @@ bool UnwindAssemblyInstEmulation::WriteRegister( // with the same amount. lldb::RegisterKind kind = m_unwind_plan_ptr->GetRegisterKind(); if (m_fp_is_cfa && reg_info->kinds[kind] == m_cfa_reg_info.kinds[kind] && - context.info_type == EmulateInstruction::eInfoTypeRegisterPlusOffset && + context.GetInfoType() == + EmulateInstruction::eInfoTypeRegisterPlusOffset && context.info.RegisterPlusOffset.reg.kinds[kind] == m_cfa_reg_info.kinds[kind]) { const int64_t offset = context.info.RegisterPlusOffset.signed_offset; @@ -585,18 +583,19 @@ bool UnwindAssemblyInstEmulation::WriteRegister( case EmulateInstruction::eContextAbsoluteBranchRegister: case EmulateInstruction::eContextRelativeBranchImmediate: { - if (context.info_type == EmulateInstruction::eInfoTypeISAAndImmediate && + if (context.GetInfoType() == EmulateInstruction::eInfoTypeISAAndImmediate && context.info.ISAAndImmediate.unsigned_data32 > 0) { m_forward_branch_offset = context.info.ISAAndImmediateSigned.signed_data32; - } else if (context.info_type == + } else if (context.GetInfoType() == EmulateInstruction::eInfoTypeISAAndImmediateSigned && context.info.ISAAndImmediateSigned.signed_data32 > 0) { m_forward_branch_offset = context.info.ISAAndImmediate.unsigned_data32; - } else if (context.info_type == EmulateInstruction::eInfoTypeImmediate && + } else if (context.GetInfoType() == + EmulateInstruction::eInfoTypeImmediate && context.info.unsigned_immediate > 0) { m_forward_branch_offset = context.info.unsigned_immediate; - } else if (context.info_type == + } else if (context.GetInfoType() == EmulateInstruction::eInfoTypeImmediateSigned && context.info.signed_immediate > 0) { m_forward_branch_offset = context.info.signed_immediate; @@ -609,7 +608,7 @@ bool UnwindAssemblyInstEmulation::WriteRegister( const uint32_t generic_regnum = reg_info->kinds[eRegisterKindGeneric]; if (reg_num != LLDB_INVALID_REGNUM && generic_regnum != LLDB_REGNUM_GENERIC_SP) { - switch (context.info_type) { + switch (context.GetInfoType()) { case EmulateInstruction::eInfoTypeAddress: if (m_pushed_regs.find(reg_num) != m_pushed_regs.end() && context.info.address == m_pushed_regs[reg_num]) { @@ -621,11 +620,10 @@ bool UnwindAssemblyInstEmulation::WriteRegister( // to using SP to calculate the CFA. if (m_fp_is_cfa) { m_fp_is_cfa = false; - RegisterInfo sp_reg_info; lldb::RegisterKind sp_reg_kind = eRegisterKindGeneric; uint32_t sp_reg_num = LLDB_REGNUM_GENERIC_SP; - m_inst_emulator_up->GetRegisterInfo(sp_reg_kind, sp_reg_num, - sp_reg_info); + RegisterInfo sp_reg_info = + *m_inst_emulator_up->GetRegisterInfo(sp_reg_kind, sp_reg_num); RegisterValue sp_reg_val; if (GetRegisterValue(sp_reg_info, sp_reg_val)) { m_cfa_reg_info = sp_reg_info; diff --git a/contrib/llvm-project/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h b/contrib/llvm-project/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h index 796e7e50a8b9..d03a8ce4e924 100644 --- a/contrib/llvm-project/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h +++ b/contrib/llvm-project/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h @@ -67,7 +67,7 @@ private: m_initial_sp(0), m_cfa_reg_info(), m_fp_is_cfa(false), m_register_values(), m_pushed_regs(), m_curr_row_modified(false), m_forward_branch_offset(0) { - if (m_inst_emulator_up.get()) { + if (m_inst_emulator_up) { m_inst_emulator_up->SetBaton(this); m_inst_emulator_up->SetCallbacks(ReadMemory, WriteMemory, ReadRegister, WriteRegister); diff --git a/contrib/llvm-project/lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp b/contrib/llvm-project/lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp index c796cbc75c1b..2032c5a68d05 100644 --- a/contrib/llvm-project/lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp @@ -682,10 +682,6 @@ bool x86AssemblyInspectionEngine::jmp_to_reg_p() { // The second byte is a ModR/M /4 byte, strip off the registers uint8_t second_byte_sans_reg = *(m_cur_insn + 1) & ~7; - // Don't handle 0x24 disp32, because the target address is - // knowable statically - pc_rel_branch_or_jump_p() will - // return the target address. - // [reg] if (second_byte_sans_reg == 0x20) return true; @@ -702,17 +698,6 @@ bool x86AssemblyInspectionEngine::jmp_to_reg_p() { if (second_byte_sans_reg == 0xe0) return true; - // disp32 - // jumps to an address stored in memory, the value can't be cached - // in an unwind plan. - if (second_byte_sans_reg == 0x24) - return true; - - // use SIB byte - // ff 24 fe jmpq *(%rsi,%rdi,8) - if (second_byte_sans_reg == 0x24) - return true; - return false; } @@ -966,7 +951,7 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly( // path jumps over the mid-function epilogue UnwindPlan::RowSP prologue_completed_row; // copy of prologue row of CFI - int prologue_completed_sp_bytes_offset_from_cfa; // The sp value before the + int prologue_completed_sp_bytes_offset_from_cfa = 0; // The sp value before the // epilogue started executed bool prologue_completed_is_aligned = false; std::vector<bool> prologue_completed_saved_registers; diff --git a/contrib/llvm-project/lldb/source/Symbol/ArmUnwindInfo.cpp b/contrib/llvm-project/lldb/source/Symbol/ArmUnwindInfo.cpp index ae6cddfbc463..60935a33827f 100644 --- a/contrib/llvm-project/lldb/source/Symbol/ArmUnwindInfo.cpp +++ b/contrib/llvm-project/lldb/source/Symbol/ArmUnwindInfo.cpp @@ -352,8 +352,8 @@ bool ArmUnwindInfo::GetUnwindPlan(Target &target, const Address &addr, const uint8_t * ArmUnwindInfo::GetExceptionHandlingTableEntry(const Address &addr) { - auto it = std::upper_bound(m_exidx_entries.begin(), m_exidx_entries.end(), - ArmExidxEntry{0, addr.GetFileAddress(), 0}); + auto it = llvm::upper_bound(m_exidx_entries, + ArmExidxEntry{0, addr.GetFileAddress(), 0}); if (it == m_exidx_entries.begin()) return nullptr; --it; diff --git a/contrib/llvm-project/lldb/source/Symbol/CompactUnwindInfo.cpp b/contrib/llvm-project/lldb/source/Symbol/CompactUnwindInfo.cpp index ce597523c061..64b0aa4f62ad 100644 --- a/contrib/llvm-project/lldb/source/Symbol/CompactUnwindInfo.cpp +++ b/contrib/llvm-project/lldb/source/Symbol/CompactUnwindInfo.cpp @@ -155,9 +155,8 @@ FLAGS_ANONYMOUS_ENUM(){ #endif #define EXTRACT_BITS(value, mask) \ - ((value >> \ - llvm::countTrailingZeros(static_cast<uint32_t>(mask), llvm::ZB_Width)) & \ - (((1 << llvm::countPopulation(static_cast<uint32_t>(mask)))) - 1)) + ((value >> llvm::countTrailingZeros(static_cast<uint32_t>(mask))) & \ + (((1 << llvm::popcount(static_cast<uint32_t>(mask)))) - 1)) // constructor @@ -516,7 +515,7 @@ bool CompactUnwindInfo::GetCompactUnwindInfoForFunction( key.function_offset = function_offset; std::vector<UnwindIndex>::const_iterator it; - it = std::lower_bound(m_indexes.begin(), m_indexes.end(), key); + it = llvm::lower_bound(m_indexes, key); if (it == m_indexes.end()) { return false; } diff --git a/contrib/llvm-project/lldb/source/Symbol/CompileUnit.cpp b/contrib/llvm-project/lldb/source/Symbol/CompileUnit.cpp index 2bae08c8b930..280425d5874b 100644 --- a/contrib/llvm-project/lldb/source/Symbol/CompileUnit.cpp +++ b/contrib/llvm-project/lldb/source/Symbol/CompileUnit.cpp @@ -13,6 +13,7 @@ #include "lldb/Symbol/VariableList.h" #include "lldb/Target/Language.h" #include "lldb/Utility/Timer.h" +#include <optional> using namespace lldb; using namespace lldb_private; @@ -216,10 +217,11 @@ VariableListSP CompileUnit::GetVariableList(bool can_create) { return m_variables; } -std::vector<uint32_t> FindFileIndexes(const FileSpecList &files, const FileSpec &file) { +std::vector<uint32_t> FindFileIndexes(const FileSpecList &files, + const FileSpec &file) { std::vector<uint32_t> result; uint32_t idx = -1; - while ((idx = files.FindFileIndex(idx + 1, file, /*full=*/true)) != + while ((idx = files.FindCompatibleIndex(idx + 1, file)) != UINT32_MAX) result.push_back(idx); return result; @@ -230,12 +232,14 @@ uint32_t CompileUnit::FindLineEntry(uint32_t start_idx, uint32_t line, LineEntry *line_entry_ptr) { if (!file_spec_ptr) file_spec_ptr = &GetPrimaryFile(); - std::vector<uint32_t> file_indexes = FindFileIndexes(GetSupportFiles(), *file_spec_ptr); + std::vector<uint32_t> file_indexes = FindFileIndexes(GetSupportFiles(), + *file_spec_ptr); if (file_indexes.empty()) return UINT32_MAX; // TODO: Handle SourceLocationSpec column information - SourceLocationSpec location_spec(*file_spec_ptr, line, /*column=*/llvm::None, + SourceLocationSpec location_spec(*file_spec_ptr, line, + /*column=*/std::nullopt, /*check_inlines=*/false, exact); LineTable *line_table = GetLineTable(); @@ -255,7 +259,6 @@ void CompileUnit::ResolveSymbolContext( // First find all of the file indexes that match our "file_spec". If // "file_spec" has an empty directory, then only compare the basenames when // finding file indexes - std::vector<uint32_t> file_indexes; bool file_spec_matches_cu_file_spec = FileSpec::Match(file_spec, this->GetPrimaryFile()); @@ -276,13 +279,8 @@ void CompileUnit::ResolveSymbolContext( return; } - uint32_t file_idx = - GetSupportFiles().FindFileIndex(0, file_spec, true); - while (file_idx != UINT32_MAX) { - file_indexes.push_back(file_idx); - file_idx = GetSupportFiles().FindFileIndex(file_idx + 1, file_spec, true); - } - + std::vector<uint32_t> file_indexes = FindFileIndexes(GetSupportFiles(), + file_spec); const size_t num_file_indexes = file_indexes.size(); if (num_file_indexes == 0) return; @@ -322,10 +320,9 @@ void CompileUnit::ResolveSymbolContext( // subsequent line exact matches below. const bool inlines = false; const bool exact = true; - const llvm::Optional<uint16_t> column = - src_location_spec.GetColumn() - ? llvm::Optional<uint16_t>(line_entry.column) - : llvm::None; + const std::optional<uint16_t> column = + src_location_spec.GetColumn() ? std::optional<uint16_t>(line_entry.column) + : std::nullopt; SourceLocationSpec found_entry(line_entry.file, line_entry.line, column, inlines, exact); @@ -334,14 +331,45 @@ void CompileUnit::ResolveSymbolContext( // If they only asked for the line entry, then we're done, we can // just copy that over. But if they wanted more than just the line // number, fill it in. + SymbolContext resolved_sc; + sc.line_entry = line_entry; if (resolve_scope == eSymbolContextLineEntry) { - sc.line_entry = line_entry; + sc_list.Append(sc); } else { - line_entry.range.GetBaseAddress().CalculateSymbolContext(&sc, + line_entry.range.GetBaseAddress().CalculateSymbolContext(&resolved_sc, resolve_scope); + // Sometimes debug info is bad and isn't able to resolve the line entry's + // address back to the same compile unit and/or line entry. If the compile + // unit changed, then revert back to just the compile unit and line entry. + // Prior to this fix, the above code might end up not being able to lookup + // the address, and then it would clear compile unit and the line entry in + // the symbol context and the breakpoint would fail to get set even though + // we have a valid line table entry in this compile unit. The address + // lookup can also end up finding another function in another compiler + // unit if the DWARF has overlappging address ranges. So if we end up with + // no compile unit or a different one after the above function call, + // revert back to the same results as if resolve_scope was set exactly to + // eSymbolContextLineEntry. + if (resolved_sc.comp_unit == this) { + sc_list.Append(resolved_sc); + } else { + if (resolved_sc.comp_unit == nullptr && resolved_sc.module_sp) { + // Only report an error if we don't map back to any compile unit. With + // link time optimizations, the debug info might have many compile + // units that have the same address range due to function outlining + // or other link time optimizations. If the compile unit is NULL, then + // address resolving is completely failing and more deserving of an + // error message the user can see. + resolved_sc.module_sp->ReportError( + "unable to resolve a line table file address {0:x16} back " + "to a compile unit, please file a bug and attach the address " + "and file.", + line_entry.range.GetBaseAddress().GetFileAddress()); + } + sc_list.Append(sc); + } } - sc_list.Append(sc); if (num_file_indexes == 1) line_idx = line_table->FindLineEntryIndexByFileIndex( line_idx + 1, file_indexes.front(), found_entry, &line_entry); diff --git a/contrib/llvm-project/lldb/source/Symbol/CompilerType.cpp b/contrib/llvm-project/lldb/source/Symbol/CompilerType.cpp index bef456583687..11a7d09680d3 100644 --- a/contrib/llvm-project/lldb/source/Symbol/CompilerType.cpp +++ b/contrib/llvm-project/lldb/source/Symbol/CompilerType.cpp @@ -22,6 +22,7 @@ #include <iterator> #include <mutex> +#include <optional> using namespace lldb; using namespace lldb_private; @@ -30,26 +31,30 @@ using namespace lldb_private; bool CompilerType::IsAggregateType() const { if (IsValid()) - return m_type_system->IsAggregateType(m_type); + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->IsAggregateType(m_type); return false; } bool CompilerType::IsAnonymousType() const { if (IsValid()) - return m_type_system->IsAnonymousType(m_type); + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->IsAnonymousType(m_type); return false; } bool CompilerType::IsScopedEnumerationType() const { if (IsValid()) - return m_type_system->IsScopedEnumerationType(m_type); + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->IsScopedEnumerationType(m_type); return false; } bool CompilerType::IsArrayType(CompilerType *element_type_ptr, uint64_t *size, bool *is_incomplete) const { if (IsValid()) - return m_type_system->IsArrayType(m_type, element_type_ptr, size, + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->IsArrayType(m_type, element_type_ptr, size, is_incomplete); if (element_type_ptr) @@ -64,43 +69,57 @@ bool CompilerType::IsArrayType(CompilerType *element_type_ptr, uint64_t *size, bool CompilerType::IsVectorType(CompilerType *element_type, uint64_t *size) const { if (IsValid()) - return m_type_system->IsVectorType(m_type, element_type, size); + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->IsVectorType(m_type, element_type, size); return false; } bool CompilerType::IsRuntimeGeneratedType() const { if (IsValid()) - return m_type_system->IsRuntimeGeneratedType(m_type); + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->IsRuntimeGeneratedType(m_type); return false; } bool CompilerType::IsCharType() const { if (IsValid()) - return m_type_system->IsCharType(m_type); + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->IsCharType(m_type); return false; } bool CompilerType::IsCompleteType() const { if (IsValid()) - return m_type_system->IsCompleteType(m_type); + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->IsCompleteType(m_type); + return false; +} + +bool CompilerType::IsForcefullyCompleted() const { + if (IsValid()) + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->IsForcefullyCompleted(m_type); return false; } bool CompilerType::IsConst() const { if (IsValid()) - return m_type_system->IsConst(m_type); + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->IsConst(m_type); return false; } bool CompilerType::IsCStringType(uint32_t &length) const { if (IsValid()) - return m_type_system->IsCStringType(m_type, length); + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->IsCStringType(m_type, length); return false; } bool CompilerType::IsFunctionType() const { if (IsValid()) - return m_type_system->IsFunctionType(m_type); + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->IsFunctionType(m_type); return false; } @@ -108,45 +127,52 @@ bool CompilerType::IsFunctionType() const { uint32_t CompilerType::IsHomogeneousAggregate(CompilerType *base_type_ptr) const { if (IsValid()) - return m_type_system->IsHomogeneousAggregate(m_type, base_type_ptr); + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->IsHomogeneousAggregate(m_type, base_type_ptr); return 0; } size_t CompilerType::GetNumberOfFunctionArguments() const { if (IsValid()) - return m_type_system->GetNumberOfFunctionArguments(m_type); + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->GetNumberOfFunctionArguments(m_type); return 0; } CompilerType CompilerType::GetFunctionArgumentAtIndex(const size_t index) const { if (IsValid()) - return m_type_system->GetFunctionArgumentAtIndex(m_type, index); + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->GetFunctionArgumentAtIndex(m_type, index); return CompilerType(); } bool CompilerType::IsFunctionPointerType() const { if (IsValid()) - return m_type_system->IsFunctionPointerType(m_type); + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->IsFunctionPointerType(m_type); return false; } bool CompilerType::IsBlockPointerType( CompilerType *function_pointer_type_ptr) const { if (IsValid()) - return m_type_system->IsBlockPointerType(m_type, function_pointer_type_ptr); + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->IsBlockPointerType(m_type, function_pointer_type_ptr); return false; } bool CompilerType::IsIntegerType(bool &is_signed) const { if (IsValid()) - return m_type_system->IsIntegerType(m_type, is_signed); + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->IsIntegerType(m_type, is_signed); return false; } bool CompilerType::IsEnumerationType(bool &is_signed) const { if (IsValid()) - return m_type_system->IsEnumerationType(m_type, is_signed); + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->IsEnumerationType(m_type, is_signed); return false; } @@ -156,7 +182,8 @@ bool CompilerType::IsIntegerOrEnumerationType(bool &is_signed) const { bool CompilerType::IsPointerType(CompilerType *pointee_type) const { if (IsValid()) { - return m_type_system->IsPointerType(m_type, pointee_type); + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->IsPointerType(m_type, pointee_type); } if (pointee_type) pointee_type->Clear(); @@ -165,7 +192,8 @@ bool CompilerType::IsPointerType(CompilerType *pointee_type) const { bool CompilerType::IsPointerOrReferenceType(CompilerType *pointee_type) const { if (IsValid()) { - return m_type_system->IsPointerOrReferenceType(m_type, pointee_type); + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->IsPointerOrReferenceType(m_type, pointee_type); } if (pointee_type) pointee_type->Clear(); @@ -175,7 +203,8 @@ bool CompilerType::IsPointerOrReferenceType(CompilerType *pointee_type) const { bool CompilerType::IsReferenceType(CompilerType *pointee_type, bool *is_rvalue) const { if (IsValid()) { - return m_type_system->IsReferenceType(m_type, pointee_type, is_rvalue); + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->IsReferenceType(m_type, pointee_type, is_rvalue); } if (pointee_type) pointee_type->Clear(); @@ -184,14 +213,16 @@ bool CompilerType::IsReferenceType(CompilerType *pointee_type, bool CompilerType::ShouldTreatScalarValueAsAddress() const { if (IsValid()) - return m_type_system->ShouldTreatScalarValueAsAddress(m_type); + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->ShouldTreatScalarValueAsAddress(m_type); return false; } bool CompilerType::IsFloatingPointType(uint32_t &count, bool &is_complex) const { if (IsValid()) { - return m_type_system->IsFloatingPointType(m_type, count, is_complex); + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->IsFloatingPointType(m_type, count, is_complex); } count = 0; is_complex = false; @@ -200,13 +231,15 @@ bool CompilerType::IsFloatingPointType(uint32_t &count, bool CompilerType::IsDefined() const { if (IsValid()) - return m_type_system->IsDefined(m_type); + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->IsDefined(m_type); return true; } bool CompilerType::IsPolymorphicClass() const { if (IsValid()) { - return m_type_system->IsPolymorphicClass(m_type); + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->IsPolymorphicClass(m_type); } return false; } @@ -215,28 +248,38 @@ bool CompilerType::IsPossibleDynamicType(CompilerType *dynamic_pointee_type, bool check_cplusplus, bool check_objc) const { if (IsValid()) - return m_type_system->IsPossibleDynamicType(m_type, dynamic_pointee_type, + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->IsPossibleDynamicType(m_type, dynamic_pointee_type, check_cplusplus, check_objc); return false; } bool CompilerType::IsScalarType() const { - if (!IsValid()) - return false; + if (IsValid()) + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->IsScalarType(m_type); + return false; +} - return m_type_system->IsScalarType(m_type); +bool CompilerType::IsTemplateType() const { + if (IsValid()) + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->IsTemplateType(m_type); + return false; } bool CompilerType::IsTypedefType() const { - if (!IsValid()) - return false; - return m_type_system->IsTypedefType(m_type); + if (IsValid()) + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->IsTypedefType(m_type); + return false; } bool CompilerType::IsVoidType() const { - if (!IsValid()) - return false; - return m_type_system->IsVoidType(m_type); + if (IsValid()) + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->IsVoidType(m_type); + return false; } bool CompilerType::IsPointerToScalarType() const { @@ -254,70 +297,82 @@ bool CompilerType::IsArrayOfScalarType() const { } bool CompilerType::IsBeingDefined() const { - if (!IsValid()) - return false; - return m_type_system->IsBeingDefined(m_type); + if (IsValid()) + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->IsBeingDefined(m_type); + return false; } // Type Completion bool CompilerType::GetCompleteType() const { - if (!IsValid()) - return false; - return m_type_system->GetCompleteType(m_type); + if (IsValid()) + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->GetCompleteType(m_type); + return false; } // AST related queries size_t CompilerType::GetPointerByteSize() const { - if (m_type_system) - return m_type_system->GetPointerByteSize(); + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->GetPointerByteSize(); return 0; } -ConstString CompilerType::GetTypeName() const { +ConstString CompilerType::GetTypeName(bool BaseOnly) const { if (IsValid()) { - return m_type_system->GetTypeName(m_type); + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->GetTypeName(m_type, BaseOnly); } return ConstString("<invalid>"); } ConstString CompilerType::GetDisplayTypeName() const { if (IsValid()) - return m_type_system->GetDisplayTypeName(m_type); + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->GetDisplayTypeName(m_type); return ConstString("<invalid>"); } uint32_t CompilerType::GetTypeInfo( CompilerType *pointee_or_element_compiler_type) const { - if (!IsValid()) - return 0; - - return m_type_system->GetTypeInfo(m_type, pointee_or_element_compiler_type); + if (IsValid()) + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->GetTypeInfo(m_type, + pointee_or_element_compiler_type); + return 0; } lldb::LanguageType CompilerType::GetMinimumLanguage() { - if (!IsValid()) - return lldb::eLanguageTypeC; - - return m_type_system->GetMinimumLanguage(m_type); + if (IsValid()) + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->GetMinimumLanguage(m_type); + return lldb::eLanguageTypeC; } lldb::TypeClass CompilerType::GetTypeClass() const { - if (!IsValid()) - return lldb::eTypeClassInvalid; - - return m_type_system->GetTypeClass(m_type); + if (IsValid()) + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->GetTypeClass(m_type); + return lldb::eTypeClassInvalid; } -void CompilerType::SetCompilerType(TypeSystem *type_system, +void CompilerType::SetCompilerType(lldb::TypeSystemWP type_system, lldb::opaque_compiler_type_t type) { m_type_system = type_system; m_type = type; } +void CompilerType::SetCompilerType(CompilerType::TypeSystemSPWrapper type_system, + lldb::opaque_compiler_type_t type) { + m_type_system = type_system.GetSharedPointer(); + m_type = type; +} + unsigned CompilerType::GetTypeQualifiers() const { if (IsValid()) - return m_type_system->GetTypeQualifiers(m_type); + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->GetTypeQualifiers(m_type); return 0; } @@ -326,146 +381,160 @@ unsigned CompilerType::GetTypeQualifiers() const { CompilerType CompilerType::GetArrayElementType(ExecutionContextScope *exe_scope) const { if (IsValid()) { - return m_type_system->GetArrayElementType(m_type, exe_scope); + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->GetArrayElementType(m_type, exe_scope); } return CompilerType(); } CompilerType CompilerType::GetArrayType(uint64_t size) const { if (IsValid()) { - return m_type_system->GetArrayType(m_type, size); + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->GetArrayType(m_type, size); } return CompilerType(); } CompilerType CompilerType::GetCanonicalType() const { if (IsValid()) - return m_type_system->GetCanonicalType(m_type); + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->GetCanonicalType(m_type); return CompilerType(); } CompilerType CompilerType::GetFullyUnqualifiedType() const { if (IsValid()) - return m_type_system->GetFullyUnqualifiedType(m_type); + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->GetFullyUnqualifiedType(m_type); return CompilerType(); } CompilerType CompilerType::GetEnumerationIntegerType() const { if (IsValid()) - return m_type_system->GetEnumerationIntegerType(m_type); + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->GetEnumerationIntegerType(m_type); return CompilerType(); } int CompilerType::GetFunctionArgumentCount() const { if (IsValid()) { - return m_type_system->GetFunctionArgumentCount(m_type); + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->GetFunctionArgumentCount(m_type); } return -1; } CompilerType CompilerType::GetFunctionArgumentTypeAtIndex(size_t idx) const { if (IsValid()) { - return m_type_system->GetFunctionArgumentTypeAtIndex(m_type, idx); + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->GetFunctionArgumentTypeAtIndex(m_type, idx); } return CompilerType(); } CompilerType CompilerType::GetFunctionReturnType() const { if (IsValid()) { - return m_type_system->GetFunctionReturnType(m_type); + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->GetFunctionReturnType(m_type); } return CompilerType(); } size_t CompilerType::GetNumMemberFunctions() const { if (IsValid()) { - return m_type_system->GetNumMemberFunctions(m_type); + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->GetNumMemberFunctions(m_type); } return 0; } TypeMemberFunctionImpl CompilerType::GetMemberFunctionAtIndex(size_t idx) { if (IsValid()) { - return m_type_system->GetMemberFunctionAtIndex(m_type, idx); + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->GetMemberFunctionAtIndex(m_type, idx); } return TypeMemberFunctionImpl(); } CompilerType CompilerType::GetNonReferenceType() const { if (IsValid()) - return m_type_system->GetNonReferenceType(m_type); + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->GetNonReferenceType(m_type); return CompilerType(); } CompilerType CompilerType::GetPointeeType() const { if (IsValid()) { - return m_type_system->GetPointeeType(m_type); + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->GetPointeeType(m_type); } return CompilerType(); } CompilerType CompilerType::GetPointerType() const { if (IsValid()) { - return m_type_system->GetPointerType(m_type); + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->GetPointerType(m_type); } return CompilerType(); } CompilerType CompilerType::GetLValueReferenceType() const { if (IsValid()) - return m_type_system->GetLValueReferenceType(m_type); - else - return CompilerType(); + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->GetLValueReferenceType(m_type); + return CompilerType(); } CompilerType CompilerType::GetRValueReferenceType() const { if (IsValid()) - return m_type_system->GetRValueReferenceType(m_type); - else - return CompilerType(); + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->GetRValueReferenceType(m_type); + return CompilerType(); } CompilerType CompilerType::GetAtomicType() const { if (IsValid()) - return m_type_system->GetAtomicType(m_type); + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->GetAtomicType(m_type); return CompilerType(); } CompilerType CompilerType::AddConstModifier() const { if (IsValid()) - return m_type_system->AddConstModifier(m_type); - else - return CompilerType(); + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->AddConstModifier(m_type); + return CompilerType(); } CompilerType CompilerType::AddVolatileModifier() const { if (IsValid()) - return m_type_system->AddVolatileModifier(m_type); - else - return CompilerType(); + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->AddVolatileModifier(m_type); + return CompilerType(); } CompilerType CompilerType::AddRestrictModifier() const { if (IsValid()) - return m_type_system->AddRestrictModifier(m_type); - else - return CompilerType(); + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->AddRestrictModifier(m_type); + return CompilerType(); } CompilerType CompilerType::CreateTypedef(const char *name, const CompilerDeclContext &decl_ctx, uint32_t payload) const { if (IsValid()) - return m_type_system->CreateTypedef(m_type, name, decl_ctx, payload); - else - return CompilerType(); + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->CreateTypedef(m_type, name, decl_ctx, payload); + return CompilerType(); } CompilerType CompilerType::GetTypedefedType() const { if (IsValid()) - return m_type_system->GetTypedefedType(m_type); - else - return CompilerType(); + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->GetTypedefedType(m_type); + return CompilerType(); } // Create related types using the current type's AST @@ -473,56 +542,62 @@ CompilerType CompilerType::GetTypedefedType() const { CompilerType CompilerType::GetBasicTypeFromAST(lldb::BasicType basic_type) const { if (IsValid()) - return m_type_system->GetBasicTypeFromAST(basic_type); + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->GetBasicTypeFromAST(basic_type); return CompilerType(); } // Exploring the type -llvm::Optional<uint64_t> +std::optional<uint64_t> CompilerType::GetBitSize(ExecutionContextScope *exe_scope) const { if (IsValid()) - return m_type_system->GetBitSize(m_type, exe_scope); + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->GetBitSize(m_type, exe_scope); return {}; } -llvm::Optional<uint64_t> +std::optional<uint64_t> CompilerType::GetByteSize(ExecutionContextScope *exe_scope) const { - if (llvm::Optional<uint64_t> bit_size = GetBitSize(exe_scope)) + if (std::optional<uint64_t> bit_size = GetBitSize(exe_scope)) return (*bit_size + 7) / 8; return {}; } -llvm::Optional<size_t> CompilerType::GetTypeBitAlign(ExecutionContextScope *exe_scope) const { +std::optional<size_t> +CompilerType::GetTypeBitAlign(ExecutionContextScope *exe_scope) const { if (IsValid()) - return m_type_system->GetTypeBitAlign(m_type, exe_scope); + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->GetTypeBitAlign(m_type, exe_scope); return {}; } lldb::Encoding CompilerType::GetEncoding(uint64_t &count) const { - if (!IsValid()) - return lldb::eEncodingInvalid; - - return m_type_system->GetEncoding(m_type, count); + if (IsValid()) + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->GetEncoding(m_type, count); + return lldb::eEncodingInvalid; } lldb::Format CompilerType::GetFormat() const { - if (!IsValid()) - return lldb::eFormatDefault; - - return m_type_system->GetFormat(m_type); + if (IsValid()) + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->GetFormat(m_type); + return lldb::eFormatDefault; } uint32_t CompilerType::GetNumChildren(bool omit_empty_base_classes, const ExecutionContext *exe_ctx) const { - if (!IsValid()) - return 0; - return m_type_system->GetNumChildren(m_type, omit_empty_base_classes, + if (IsValid()) + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->GetNumChildren(m_type, omit_empty_base_classes, exe_ctx); + return 0; } lldb::BasicType CompilerType::GetBasicTypeEnumeration() const { if (IsValid()) - return m_type_system->GetBasicTypeEnumeration(m_type); + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->GetBasicTypeEnumeration(m_type); return eBasicTypeInvalid; } @@ -531,34 +606,39 @@ void CompilerType::ForEachEnumerator( ConstString name, const llvm::APSInt &value)> const &callback) const { if (IsValid()) - return m_type_system->ForEachEnumerator(m_type, callback); + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->ForEachEnumerator(m_type, callback); } uint32_t CompilerType::GetNumFields() const { - if (!IsValid()) - return 0; - return m_type_system->GetNumFields(m_type); + if (IsValid()) + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->GetNumFields(m_type); + return 0; } CompilerType CompilerType::GetFieldAtIndex(size_t idx, std::string &name, uint64_t *bit_offset_ptr, uint32_t *bitfield_bit_size_ptr, bool *is_bitfield_ptr) const { - if (!IsValid()) - return CompilerType(); - return m_type_system->GetFieldAtIndex(m_type, idx, name, bit_offset_ptr, + if (IsValid()) + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->GetFieldAtIndex(m_type, idx, name, bit_offset_ptr, bitfield_bit_size_ptr, is_bitfield_ptr); + return CompilerType(); } uint32_t CompilerType::GetNumDirectBaseClasses() const { if (IsValid()) - return m_type_system->GetNumDirectBaseClasses(m_type); + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->GetNumDirectBaseClasses(m_type); return 0; } uint32_t CompilerType::GetNumVirtualBaseClasses() const { if (IsValid()) - return m_type_system->GetNumVirtualBaseClasses(m_type); + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->GetNumVirtualBaseClasses(m_type); return 0; } @@ -566,7 +646,8 @@ CompilerType CompilerType::GetDirectBaseClassAtIndex(size_t idx, uint32_t *bit_offset_ptr) const { if (IsValid()) - return m_type_system->GetDirectBaseClassAtIndex(m_type, idx, + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->GetDirectBaseClassAtIndex(m_type, idx, bit_offset_ptr); return CompilerType(); } @@ -575,7 +656,8 @@ CompilerType CompilerType::GetVirtualBaseClassAtIndex(size_t idx, uint32_t *bit_offset_ptr) const { if (IsValid()) - return m_type_system->GetVirtualBaseClassAtIndex(m_type, idx, + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->GetVirtualBaseClassAtIndex(m_type, idx, bit_offset_ptr); return CompilerType(); } @@ -607,13 +689,15 @@ CompilerType CompilerType::GetChildCompilerTypeAtIndex( uint32_t &child_bitfield_bit_offset, bool &child_is_base_class, bool &child_is_deref_of_parent, ValueObject *valobj, uint64_t &language_flags) const { - if (!IsValid()) - return CompilerType(); - return m_type_system->GetChildCompilerTypeAtIndex( - m_type, exe_ctx, idx, transparent_pointers, omit_empty_base_classes, - ignore_array_bounds, child_name, child_byte_size, child_byte_offset, - child_bitfield_bit_size, child_bitfield_bit_offset, child_is_base_class, - child_is_deref_of_parent, valobj, language_flags); + if (IsValid()) + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->GetChildCompilerTypeAtIndex( + m_type, exe_ctx, idx, transparent_pointers, omit_empty_base_classes, + ignore_array_bounds, child_name, child_byte_size, child_byte_offset, + child_bitfield_bit_size, child_bitfield_bit_offset, + child_is_base_class, child_is_deref_of_parent, valobj, + language_flags); + return CompilerType(); } // Look for a child member (doesn't include base classes, but it does include @@ -653,7 +737,8 @@ size_t CompilerType::GetIndexOfChildMemberWithName( const char *name, bool omit_empty_base_classes, std::vector<uint32_t> &child_indexes) const { if (IsValid() && name && name[0]) { - return m_type_system->GetIndexOfChildMemberWithName( + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->GetIndexOfChildMemberWithName( m_type, name, omit_empty_base_classes, child_indexes); } return 0; @@ -661,7 +746,8 @@ size_t CompilerType::GetIndexOfChildMemberWithName( size_t CompilerType::GetNumTemplateArguments(bool expand_pack) const { if (IsValid()) { - return m_type_system->GetNumTemplateArguments(m_type, expand_pack); + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->GetNumTemplateArguments(m_type, expand_pack); } return 0; } @@ -669,40 +755,46 @@ size_t CompilerType::GetNumTemplateArguments(bool expand_pack) const { TemplateArgumentKind CompilerType::GetTemplateArgumentKind(size_t idx, bool expand_pack) const { if (IsValid()) - return m_type_system->GetTemplateArgumentKind(m_type, idx, expand_pack); + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->GetTemplateArgumentKind(m_type, idx, expand_pack); return eTemplateArgumentKindNull; } CompilerType CompilerType::GetTypeTemplateArgument(size_t idx, bool expand_pack) const { if (IsValid()) { - return m_type_system->GetTypeTemplateArgument(m_type, idx, expand_pack); + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->GetTypeTemplateArgument(m_type, idx, expand_pack); } return CompilerType(); } -llvm::Optional<CompilerType::IntegralTemplateArgument> +std::optional<CompilerType::IntegralTemplateArgument> CompilerType::GetIntegralTemplateArgument(size_t idx, bool expand_pack) const { if (IsValid()) - return m_type_system->GetIntegralTemplateArgument(m_type, idx, expand_pack); - return llvm::None; + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->GetIntegralTemplateArgument(m_type, idx, expand_pack); + return std::nullopt; } CompilerType CompilerType::GetTypeForFormatters() const { if (IsValid()) - return m_type_system->GetTypeForFormatters(m_type); + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->GetTypeForFormatters(m_type); return CompilerType(); } LazyBool CompilerType::ShouldPrintAsOneLiner(ValueObject *valobj) const { if (IsValid()) - return m_type_system->ShouldPrintAsOneLiner(m_type, valobj); + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->ShouldPrintAsOneLiner(m_type, valobj); return eLazyBoolCalculate; } bool CompilerType::IsMeaninglessWithoutDynamicResolution() const { if (IsValid()) - return m_type_system->IsMeaninglessWithoutDynamicResolution(m_type); + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->IsMeaninglessWithoutDynamicResolution(m_type); return false; } @@ -714,7 +806,8 @@ uint32_t CompilerType::GetIndexOfChildWithName(const char *name, bool omit_empty_base_classes) const { if (IsValid() && name && name[0]) { - return m_type_system->GetIndexOfChildWithName(m_type, name, + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->GetIndexOfChildWithName(m_type, name, omit_empty_base_classes); } return UINT32_MAX; @@ -729,11 +822,11 @@ void CompilerType::DumpValue(ExecutionContext *exe_ctx, Stream *s, uint32_t bitfield_bit_offset, bool show_types, bool show_summary, bool verbose, uint32_t depth) { if (!IsValid()) - return; - m_type_system->DumpValue(m_type, exe_ctx, s, format, data, data_byte_offset, - data_byte_size, bitfield_bit_size, - bitfield_bit_offset, show_types, show_summary, - verbose, depth); + if (auto type_system_sp = GetTypeSystem()) + type_system_sp->DumpValue(m_type, exe_ctx, s, format, data, + data_byte_offset, data_byte_size, + bitfield_bit_size, bitfield_bit_offset, + show_types, show_summary, verbose, depth); } bool CompilerType::DumpTypeValue(Stream *s, lldb::Format format, @@ -742,11 +835,12 @@ bool CompilerType::DumpTypeValue(Stream *s, lldb::Format format, uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset, ExecutionContextScope *exe_scope) { - if (!IsValid()) - return false; - return m_type_system->DumpTypeValue(m_type, s, format, data, byte_offset, - byte_size, bitfield_bit_size, - bitfield_bit_offset, exe_scope); + if (IsValid()) + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->DumpTypeValue(m_type, s, format, data, byte_offset, + byte_size, bitfield_bit_size, + bitfield_bit_offset, exe_scope); + return false; } void CompilerType::DumpSummary(ExecutionContext *exe_ctx, Stream *s, @@ -754,28 +848,30 @@ void CompilerType::DumpSummary(ExecutionContext *exe_ctx, Stream *s, lldb::offset_t data_byte_offset, size_t data_byte_size) { if (IsValid()) - m_type_system->DumpSummary(m_type, exe_ctx, s, data, data_byte_offset, - data_byte_size); + if (auto type_system_sp = GetTypeSystem()) + type_system_sp->DumpSummary(m_type, exe_ctx, s, data, data_byte_offset, + data_byte_size); } void CompilerType::DumpTypeDescription(lldb::DescriptionLevel level) const { if (IsValid()) - m_type_system->DumpTypeDescription(m_type, level); + if (auto type_system_sp = GetTypeSystem()) + type_system_sp->DumpTypeDescription(m_type, level); } void CompilerType::DumpTypeDescription(Stream *s, lldb::DescriptionLevel level) const { - if (IsValid()) { - m_type_system->DumpTypeDescription(m_type, s, level); - } + if (IsValid()) + if (auto type_system_sp = GetTypeSystem()) + type_system_sp->DumpTypeDescription(m_type, s, level); } #ifndef NDEBUG LLVM_DUMP_METHOD void CompilerType::dump() const { if (IsValid()) - m_type_system->dump(m_type); - else - llvm::errs() << "<invalid>\n"; + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->dump(m_type); + llvm::errs() << "<invalid>\n"; } #endif @@ -795,7 +891,7 @@ bool CompilerType::GetValueAsScalar(const lldb_private::DataExtractor &data, if (encoding == lldb::eEncodingInvalid || count != 1) return false; - llvm::Optional<uint64_t> byte_size = GetByteSize(exe_scope); + std::optional<uint64_t> byte_size = GetByteSize(exe_scope); if (!byte_size) return false; lldb::offset_t offset = data_byte_offset; @@ -882,10 +978,32 @@ bool CompilerType::GetValueAsScalar(const lldb_private::DataExtractor &data, #ifndef NDEBUG bool CompilerType::Verify() const { - return !IsValid() || m_type_system->Verify(m_type); + if (!IsValid()) + return true; + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->Verify(m_type); + return true; } #endif +CompilerType::TypeSystemSPWrapper CompilerType::GetTypeSystem() const { + return {m_type_system.lock()}; +} + +bool CompilerType::TypeSystemSPWrapper::operator==( + const CompilerType::TypeSystemSPWrapper &other) const { + if (!m_typesystem_sp && !other.m_typesystem_sp) + return true; + if (m_typesystem_sp && other.m_typesystem_sp) + return m_typesystem_sp.get() == other.m_typesystem_sp.get(); + return false; +} + +TypeSystem *CompilerType::TypeSystemSPWrapper::operator->() const { + assert(m_typesystem_sp); + return m_typesystem_sp.get(); +} + bool lldb_private::operator==(const lldb_private::CompilerType &lhs, const lldb_private::CompilerType &rhs) { return lhs.GetTypeSystem() == rhs.GetTypeSystem() && diff --git a/contrib/llvm-project/lldb/source/Symbol/DWARFCallFrameInfo.cpp b/contrib/llvm-project/lldb/source/Symbol/DWARFCallFrameInfo.cpp index 4e51bd411a75..be9f64356b4e 100644 --- a/contrib/llvm-project/lldb/source/Symbol/DWARFCallFrameInfo.cpp +++ b/contrib/llvm-project/lldb/source/Symbol/DWARFCallFrameInfo.cpp @@ -22,6 +22,7 @@ #include "lldb/Utility/Timer.h" #include <cstring> #include <list> +#include <optional> using namespace lldb; using namespace lldb_private; @@ -167,7 +168,7 @@ bool DWARFCallFrameInfo::GetUnwindPlan(const AddressRange &range, module_sp->GetObjectFile() != &m_objfile) return false; - if (llvm::Optional<FDEEntryMap::Entry> entry = GetFirstFDEEntryInRange(range)) + if (std::optional<FDEEntryMap::Entry> entry = GetFirstFDEEntryInRange(range)) return FDEToUnwindPlan(entry->data, addr, unwind_plan); return false; } @@ -194,10 +195,10 @@ bool DWARFCallFrameInfo::GetAddressRange(Address addr, AddressRange &range) { return true; } -llvm::Optional<DWARFCallFrameInfo::FDEEntryMap::Entry> +std::optional<DWARFCallFrameInfo::FDEEntryMap::Entry> DWARFCallFrameInfo::GetFirstFDEEntryInRange(const AddressRange &range) { if (!m_section_sp || m_section_sp->IsEncrypted()) - return llvm::None; + return std::nullopt; GetFDEIndex(); @@ -208,7 +209,7 @@ DWARFCallFrameInfo::GetFirstFDEEntryInRange(const AddressRange &range) { FDEEntryMap::Range(start_file_addr, range.GetByteSize()))) return *fde; - return llvm::None; + return std::nullopt; } void DWARFCallFrameInfo::GetFunctionAddressAndSizeVector( @@ -772,12 +773,12 @@ bool DWARFCallFrameInfo::FDEToUnwindPlan(dw_offset_t dwarf_offset, // useful for compilers that move epilogue code into the body of a // function.) if (stack.empty()) { - LLDB_LOGF(log, - "DWARFCallFrameInfo::%s(dwarf_offset: %" PRIx32 - ", startaddr: %" PRIx64 - " encountered DW_CFA_restore_state but state stack " - "is empty. Corrupt unwind info?", - __FUNCTION__, dwarf_offset, startaddr.GetFileAddress()); + LLDB_LOG(log, + "DWARFCallFrameInfo::{0}(dwarf_offset: " + "{1:x16}, startaddr: [{2:x16}] encountered " + "DW_CFA_restore_state but state stack " + "is empty. Corrupt unwind info?", + __FUNCTION__, dwarf_offset, startaddr.GetFileAddress()); break; } lldb::addr_t offset = row->GetOffset(); diff --git a/contrib/llvm-project/lldb/source/Symbol/Function.cpp b/contrib/llvm-project/lldb/source/Symbol/Function.cpp index 8ec4bc90cd13..5ed0e66bdacb 100644 --- a/contrib/llvm-project/lldb/source/Symbol/Function.cpp +++ b/contrib/llvm-project/lldb/source/Symbol/Function.cpp @@ -306,7 +306,7 @@ llvm::ArrayRef<std::unique_ptr<CallEdge>> Function::GetCallEdges() { Block &block = GetBlock(/*can_create*/true); SymbolFile *sym_file = block.GetSymbolFile(); if (!sym_file) - return llvm::None; + return std::nullopt; // Lazily read call site information from the SymbolFile. m_call_edges = sym_file->ParseCallEdgesInFunction(GetID()); diff --git a/contrib/llvm-project/lldb/source/Symbol/LocateSymbolFile.cpp b/contrib/llvm-project/lldb/source/Symbol/LocateSymbolFile.cpp index 1ff532fe3e6c..66ee7589ac60 100644 --- a/contrib/llvm-project/lldb/source/Symbol/LocateSymbolFile.cpp +++ b/contrib/llvm-project/lldb/source/Symbol/LocateSymbolFile.cpp @@ -8,6 +8,8 @@ #include "lldb/Symbol/LocateSymbolFile.h" +#include "lldb/Core/Debugger.h" +#include "lldb/Core/Module.h" #include "lldb/Core/ModuleList.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/Progress.h" @@ -18,12 +20,13 @@ #include "lldb/Utility/DataExtractor.h" #include "lldb/Utility/LLDBLog.h" #include "lldb/Utility/Log.h" -#include "lldb/Utility/Reproducer.h" #include "lldb/Utility/StreamString.h" #include "lldb/Utility/Timer.h" #include "lldb/Utility/UUID.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/ThreadPool.h" // From MacOSX system header "mach/machine.h" typedef int cpu_type_t; @@ -397,6 +400,35 @@ Symbols::LocateExecutableSymbolFile(const ModuleSpec &module_spec, return LocateExecutableSymbolFileDsym(module_spec); } +void Symbols::DownloadSymbolFileAsync(const UUID &uuid) { + if (!ModuleList::GetGlobalModuleListProperties().GetEnableBackgroundLookup()) + return; + + static llvm::SmallSet<UUID, 8> g_seen_uuids; + static std::mutex g_mutex; + Debugger::GetThreadPool().async([=]() { + { + std::lock_guard<std::mutex> guard(g_mutex); + if (g_seen_uuids.count(uuid)) + return; + g_seen_uuids.insert(uuid); + } + + Status error; + ModuleSpec module_spec; + module_spec.GetUUID() = uuid; + if (!Symbols::DownloadObjectAndSymbolFile(module_spec, error, + /*force_lookup=*/true, + /*copy_executable=*/false)) + return; + + if (error.Fail()) + return; + + Debugger::ReportSymbolChange(module_spec); + }); +} + #if !defined(__APPLE__) FileSpec Symbols::FindSymbolFileInBundle(const FileSpec &symfile_bundle, @@ -407,7 +439,8 @@ FileSpec Symbols::FindSymbolFileInBundle(const FileSpec &symfile_bundle, } bool Symbols::DownloadObjectAndSymbolFile(ModuleSpec &module_spec, - Status &error, bool force_lookup) { + Status &error, bool force_lookup, + bool copy_executable) { // Fill in the module_spec.GetFileSpec() for the object file and/or the // module_spec.GetSymbolFileSpec() for the debug symbols file. return false; diff --git a/contrib/llvm-project/lldb/source/Symbol/LocateSymbolFileMacOSX.cpp b/contrib/llvm-project/lldb/source/Symbol/LocateSymbolFileMacOSX.cpp index 4dc42cf01716..7d24905be350 100644 --- a/contrib/llvm-project/lldb/source/Symbol/LocateSymbolFileMacOSX.cpp +++ b/contrib/llvm-project/lldb/source/Symbol/LocateSymbolFileMacOSX.cpp @@ -491,190 +491,188 @@ static bool GetModuleSpecInfoFromUUIDDictionary(CFDictionaryRef uuid_dict, return success; } -bool Symbols::DownloadObjectAndSymbolFile(ModuleSpec &module_spec, - Status &error, bool force_lookup) { - bool success = false; - const UUID *uuid_ptr = module_spec.GetUUIDPtr(); - const FileSpec *file_spec_ptr = module_spec.GetFileSpecPtr(); - - // It's expensive to check for the DBGShellCommands defaults setting, only do - // it once per lldb run and cache the result. - static bool g_have_checked_for_dbgshell_command = false; - static const char *g_dbgshell_command = NULL; - if (!g_have_checked_for_dbgshell_command) { - g_have_checked_for_dbgshell_command = true; +/// It's expensive to check for the DBGShellCommands defaults setting. Only do +/// it once per lldb run and cache the result. +static llvm::StringRef GetDbgShellCommand() { + static std::once_flag g_once_flag; + static std::string g_dbgshell_command; + std::call_once(g_once_flag, [&]() { CFTypeRef defaults_setting = CFPreferencesCopyAppValue( CFSTR("DBGShellCommands"), CFSTR("com.apple.DebugSymbols")); if (defaults_setting && CFGetTypeID(defaults_setting) == CFStringGetTypeID()) { - char cstr_buf[PATH_MAX]; - if (CFStringGetCString((CFStringRef)defaults_setting, cstr_buf, - sizeof(cstr_buf), kCFStringEncodingUTF8)) { - g_dbgshell_command = - strdup(cstr_buf); // this malloc'ed memory will never be freed + char buffer[PATH_MAX]; + if (CFStringGetCString((CFStringRef)defaults_setting, buffer, + sizeof(buffer), kCFStringEncodingUTF8)) { + g_dbgshell_command = buffer; } } if (defaults_setting) { CFRelease(defaults_setting); } + }); + return g_dbgshell_command; +} + +/// Get the dsymForUUID executable and cache the result so we don't end up +/// stat'ing the binary over and over. +static FileSpec GetDsymForUUIDExecutable() { + // The LLDB_APPLE_DSYMFORUUID_EXECUTABLE environment variable is used by the + // test suite to override the dsymForUUID location. Because we must be able + // to change the value within a single test, don't bother caching it. + if (const char *dsymForUUID_env = + getenv("LLDB_APPLE_DSYMFORUUID_EXECUTABLE")) { + FileSpec dsymForUUID_executable(dsymForUUID_env); + FileSystem::Instance().Resolve(dsymForUUID_executable); + if (FileSystem::Instance().Exists(dsymForUUID_executable)) + return dsymForUUID_executable; } - // When g_dbgshell_command is NULL, the user has not enabled the use of an + static std::once_flag g_once_flag; + static FileSpec g_dsymForUUID_executable; + std::call_once(g_once_flag, [&]() { + // Try the DBGShellCommand. + llvm::StringRef dbgshell_command = GetDbgShellCommand(); + if (!dbgshell_command.empty()) { + g_dsymForUUID_executable = FileSpec(dbgshell_command); + FileSystem::Instance().Resolve(g_dsymForUUID_executable); + if (FileSystem::Instance().Exists(g_dsymForUUID_executable)) + return; + } + + // Try dsymForUUID in /usr/local/bin + { + g_dsymForUUID_executable = FileSpec("/usr/local/bin/dsymForUUID"); + if (FileSystem::Instance().Exists(g_dsymForUUID_executable)) + return; + } + + // We couldn't find the dsymForUUID binary. + g_dsymForUUID_executable = {}; + }); + return g_dsymForUUID_executable; +} + +bool Symbols::DownloadObjectAndSymbolFile(ModuleSpec &module_spec, + Status &error, bool force_lookup, + bool copy_executable) { + const UUID *uuid_ptr = module_spec.GetUUIDPtr(); + const FileSpec *file_spec_ptr = module_spec.GetFileSpecPtr(); + + llvm::StringRef dbgshell_command = GetDbgShellCommand(); + + // When dbgshell_command is empty, the user has not enabled the use of an // external program to find the symbols, don't run it for them. - if (!force_lookup && g_dbgshell_command == NULL) { + if (!force_lookup && dbgshell_command.empty()) + return false; + + // We need a UUID or valid (existing FileSpec. + if (!uuid_ptr && + (!file_spec_ptr || !FileSystem::Instance().Exists(*file_spec_ptr))) + return false; + + // We need a dsymForUUID binary or an equivalent executable/script. + FileSpec dsymForUUID_exe_spec = GetDsymForUUIDExecutable(); + if (!dsymForUUID_exe_spec) + return false; + + const std::string dsymForUUID_exe_path = dsymForUUID_exe_spec.GetPath(); + const std::string uuid_str = uuid_ptr ? uuid_ptr->GetAsString() : ""; + const std::string file_path_str = + file_spec_ptr ? file_spec_ptr->GetPath() : ""; + + Log *log = GetLog(LLDBLog::Host); + + // Create the dsymForUUID command. + StreamString command; + const char *copy_executable_arg = copy_executable ? "--copyExecutable " : ""; + if (!uuid_str.empty()) { + command.Printf("%s --ignoreNegativeCache %s%s", + dsymForUUID_exe_path.c_str(), copy_executable_arg, + uuid_str.c_str()); + LLDB_LOGF(log, "Calling %s with UUID %s to find dSYM: %s", + dsymForUUID_exe_path.c_str(), uuid_str.c_str(), + command.GetString().data()); + } else if (!file_path_str.empty()) { + command.Printf("%s --ignoreNegativeCache %s%s", + dsymForUUID_exe_path.c_str(), copy_executable_arg, + file_path_str.c_str()); + LLDB_LOGF(log, "Calling %s with file %s to find dSYM: %s", + dsymForUUID_exe_path.c_str(), file_path_str.c_str(), + command.GetString().data()); + } else { return false; } - if (uuid_ptr || - (file_spec_ptr && FileSystem::Instance().Exists(*file_spec_ptr))) { - static bool g_located_dsym_for_uuid_exe = false; - static bool g_dsym_for_uuid_exe_exists = false; - static char g_dsym_for_uuid_exe_path[PATH_MAX]; - if (!g_located_dsym_for_uuid_exe) { - g_located_dsym_for_uuid_exe = true; - const char *dsym_for_uuid_exe_path_cstr = - getenv("LLDB_APPLE_DSYMFORUUID_EXECUTABLE"); - FileSpec dsym_for_uuid_exe_spec; - if (dsym_for_uuid_exe_path_cstr) { - dsym_for_uuid_exe_spec.SetFile(dsym_for_uuid_exe_path_cstr, - FileSpec::Style::native); - FileSystem::Instance().Resolve(dsym_for_uuid_exe_spec); - g_dsym_for_uuid_exe_exists = - FileSystem::Instance().Exists(dsym_for_uuid_exe_spec); - } + // Invoke dsymForUUID. + int exit_status = -1; + int signo = -1; + std::string command_output; + error = Host::RunShellCommand( + command.GetData(), + FileSpec(), // current working directory + &exit_status, // Exit status + &signo, // Signal int * + &command_output, // Command output + std::chrono::seconds( + 640), // Large timeout to allow for long dsym download times + false); // Don't run in a shell (we don't need shell expansion) + + if (error.Fail() || exit_status != 0 || command_output.empty()) { + LLDB_LOGF(log, "'%s' failed (exit status: %d, error: '%s', output: '%s')", + command.GetData(), exit_status, error.AsCString(), + command_output.c_str()); + return false; + } - if (!g_dsym_for_uuid_exe_exists) { - dsym_for_uuid_exe_spec.SetFile("/usr/local/bin/dsymForUUID", - FileSpec::Style::native); - g_dsym_for_uuid_exe_exists = - FileSystem::Instance().Exists(dsym_for_uuid_exe_spec); - if (!g_dsym_for_uuid_exe_exists) { - long bufsize; - if ((bufsize = sysconf(_SC_GETPW_R_SIZE_MAX)) != -1) { - char buffer[bufsize]; - struct passwd pwd; - struct passwd *tilde_rc = NULL; - // we are a library so we need to use the reentrant version of - // getpwnam() - if (getpwnam_r("rc", &pwd, buffer, bufsize, &tilde_rc) == 0 && - tilde_rc && tilde_rc->pw_dir) { - std::string dsymforuuid_path(tilde_rc->pw_dir); - dsymforuuid_path += "/bin/dsymForUUID"; - dsym_for_uuid_exe_spec.SetFile(dsymforuuid_path.c_str(), - FileSpec::Style::native); - g_dsym_for_uuid_exe_exists = - FileSystem::Instance().Exists(dsym_for_uuid_exe_spec); - } - } - } - } - if (!g_dsym_for_uuid_exe_exists && g_dbgshell_command != NULL) { - dsym_for_uuid_exe_spec.SetFile(g_dbgshell_command, - FileSpec::Style::native); - FileSystem::Instance().Resolve(dsym_for_uuid_exe_spec); - g_dsym_for_uuid_exe_exists = - FileSystem::Instance().Exists(dsym_for_uuid_exe_spec); - } + CFCData data( + CFDataCreateWithBytesNoCopy(NULL, (const UInt8 *)command_output.data(), + command_output.size(), kCFAllocatorNull)); + + CFCReleaser<CFDictionaryRef> plist( + (CFDictionaryRef)::CFPropertyListCreateWithData( + NULL, data.get(), kCFPropertyListImmutable, NULL, NULL)); + + if (!plist.get()) { + LLDB_LOGF(log, "'%s' failed: output is not a valid plist", + command.GetData()); + return false; + } + + if (CFGetTypeID(plist.get()) != CFDictionaryGetTypeID()) { + LLDB_LOGF(log, "'%s' failed: output plist is not a valid CFDictionary", + command.GetData()); + return false; + } - if (g_dsym_for_uuid_exe_exists) - dsym_for_uuid_exe_spec.GetPath(g_dsym_for_uuid_exe_path, - sizeof(g_dsym_for_uuid_exe_path)); + if (!uuid_str.empty()) { + CFCString uuid_cfstr(uuid_str.c_str()); + CFDictionaryRef uuid_dict = + (CFDictionaryRef)CFDictionaryGetValue(plist.get(), uuid_cfstr.get()); + return GetModuleSpecInfoFromUUIDDictionary(uuid_dict, module_spec, error); + } + + if (const CFIndex num_values = ::CFDictionaryGetCount(plist.get())) { + std::vector<CFStringRef> keys(num_values, NULL); + std::vector<CFDictionaryRef> values(num_values, NULL); + ::CFDictionaryGetKeysAndValues(plist.get(), NULL, + (const void **)&values[0]); + if (num_values == 1) { + return GetModuleSpecInfoFromUUIDDictionary(values[0], module_spec, error); } - if (g_dsym_for_uuid_exe_exists) { - std::string uuid_str; - char file_path[PATH_MAX]; - file_path[0] = '\0'; - - if (uuid_ptr) - uuid_str = uuid_ptr->GetAsString(); - - if (file_spec_ptr) - file_spec_ptr->GetPath(file_path, sizeof(file_path)); - - StreamString command; - if (!uuid_str.empty()) - command.Printf("%s --ignoreNegativeCache --copyExecutable %s", - g_dsym_for_uuid_exe_path, uuid_str.c_str()); - else if (file_path[0] != '\0') - command.Printf("%s --ignoreNegativeCache --copyExecutable %s", - g_dsym_for_uuid_exe_path, file_path); - - if (!command.GetString().empty()) { - Log *log = GetLog(LLDBLog::Host); - int exit_status = -1; - int signo = -1; - std::string command_output; - if (log) { - if (!uuid_str.empty()) - LLDB_LOGF(log, "Calling %s with UUID %s to find dSYM", - g_dsym_for_uuid_exe_path, uuid_str.c_str()); - else if (file_path[0] != '\0') - LLDB_LOGF(log, "Calling %s with file %s to find dSYM", - g_dsym_for_uuid_exe_path, file_path); - } - error = Host::RunShellCommand( - command.GetData(), - FileSpec(), // current working directory - &exit_status, // Exit status - &signo, // Signal int * - &command_output, // Command output - std::chrono::seconds( - 640), // Large timeout to allow for long dsym download times - false); // Don't run in a shell (we don't need shell expansion) - if (error.Success() && exit_status == 0 && !command_output.empty()) { - CFCData data(CFDataCreateWithBytesNoCopy( - NULL, (const UInt8 *)command_output.data(), command_output.size(), - kCFAllocatorNull)); - - CFCReleaser<CFDictionaryRef> plist( - (CFDictionaryRef)::CFPropertyListCreateFromXMLData( - NULL, data.get(), kCFPropertyListImmutable, NULL)); - - if (plist.get() && - CFGetTypeID(plist.get()) == CFDictionaryGetTypeID()) { - if (!uuid_str.empty()) { - CFCString uuid_cfstr(uuid_str.c_str()); - CFDictionaryRef uuid_dict = (CFDictionaryRef)CFDictionaryGetValue( - plist.get(), uuid_cfstr.get()); - success = GetModuleSpecInfoFromUUIDDictionary(uuid_dict, - module_spec, error); - } else { - const CFIndex num_values = ::CFDictionaryGetCount(plist.get()); - if (num_values > 0) { - std::vector<CFStringRef> keys(num_values, NULL); - std::vector<CFDictionaryRef> values(num_values, NULL); - ::CFDictionaryGetKeysAndValues(plist.get(), NULL, - (const void **)&values[0]); - if (num_values == 1) { - success = GetModuleSpecInfoFromUUIDDictionary( - values[0], module_spec, error); - return success; - } else { - for (CFIndex i = 0; i < num_values; ++i) { - ModuleSpec curr_module_spec; - if (GetModuleSpecInfoFromUUIDDictionary( - values[i], curr_module_spec, error)) { - if (module_spec.GetArchitecture().IsCompatibleMatch( - curr_module_spec.GetArchitecture())) { - module_spec = curr_module_spec; - return true; - } - } - } - } - } - } - } - } else { - if (!uuid_str.empty()) - LLDB_LOGF(log, "Called %s on %s, no matches", - g_dsym_for_uuid_exe_path, uuid_str.c_str()); - else if (file_path[0] != '\0') - LLDB_LOGF(log, "Called %s on %s, no matches", - g_dsym_for_uuid_exe_path, file_path); + + for (CFIndex i = 0; i < num_values; ++i) { + ModuleSpec curr_module_spec; + if (GetModuleSpecInfoFromUUIDDictionary(values[i], curr_module_spec, + error)) { + if (module_spec.GetArchitecture().IsCompatibleMatch( + curr_module_spec.GetArchitecture())) { + module_spec = curr_module_spec; + return true; } } } } - return success; + + return false; } diff --git a/contrib/llvm-project/lldb/source/Symbol/ObjectContainer.cpp b/contrib/llvm-project/lldb/source/Symbol/ObjectContainer.cpp new file mode 100644 index 000000000000..f4ac7a909b6c --- /dev/null +++ b/contrib/llvm-project/lldb/source/Symbol/ObjectContainer.cpp @@ -0,0 +1,59 @@ +//===-- ObjectContainer.cpp -----------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lldb/Symbol/ObjectContainer.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Target/Process.h" +#include "lldb/Utility/Timer.h" + +using namespace lldb; +using namespace lldb_private; + +ObjectContainer::ObjectContainer(const lldb::ModuleSP &module_sp, + const FileSpec *file, + lldb::offset_t file_offset, + lldb::offset_t length, + lldb::DataBufferSP data_sp, + lldb::offset_t data_offset) + : ModuleChild(module_sp), + m_file(), // This file can be different than the module's file spec + m_offset(file_offset), m_length(length) { + if (file) + m_file = *file; + if (data_sp) + m_data.SetData(data_sp, data_offset, length); +} + +ObjectContainerSP ObjectContainer::FindPlugin(const lldb::ModuleSP &module_sp, + const ProcessSP &process_sp, + lldb::addr_t header_addr, + WritableDataBufferSP data_sp) { + if (!module_sp) + return {}; + + LLDB_SCOPED_TIMERF("ObjectContainer::FindPlugin (module = " + "%s, process = %p, header_addr = " + "0x%" PRIx64 ")", + module_sp->GetFileSpec().GetPath().c_str(), + static_cast<void *>(process_sp.get()), header_addr); + + ObjectContainerCreateMemoryInstance create_callback; + for (size_t idx = 0; + (create_callback = + PluginManager::GetObjectContainerCreateMemoryCallbackAtIndex( + idx)) != nullptr; + ++idx) { + ObjectContainerSP object_container_sp( + create_callback(module_sp, data_sp, process_sp, header_addr)); + if (object_container_sp) + return object_container_sp; + } + + return {}; +} diff --git a/contrib/llvm-project/lldb/source/Symbol/PostfixExpression.cpp b/contrib/llvm-project/lldb/source/Symbol/PostfixExpression.cpp index e80e134f29bb..82db345b459c 100644 --- a/contrib/llvm-project/lldb/source/Symbol/PostfixExpression.cpp +++ b/contrib/llvm-project/lldb/source/Symbol/PostfixExpression.cpp @@ -15,15 +15,16 @@ #include "lldb/Core/dwarf.h" #include "lldb/Utility/Stream.h" #include "llvm/ADT/StringExtras.h" +#include <optional> using namespace lldb_private; using namespace lldb_private::postfix; using namespace lldb_private::dwarf; -static llvm::Optional<BinaryOpNode::OpType> +static std::optional<BinaryOpNode::OpType> GetBinaryOpType(llvm::StringRef token) { if (token.size() != 1) - return llvm::None; + return std::nullopt; switch (token[0]) { case '@': return BinaryOpNode::Align; @@ -32,14 +33,14 @@ GetBinaryOpType(llvm::StringRef token) { case '+': return BinaryOpNode::Plus; } - return llvm::None; + return std::nullopt; } -static llvm::Optional<UnaryOpNode::OpType> +static std::optional<UnaryOpNode::OpType> GetUnaryOpType(llvm::StringRef token) { if (token == "^") return UnaryOpNode::Deref; - return llvm::None; + return std::nullopt; } Node *postfix::ParseOneExpression(llvm::StringRef expr, diff --git a/contrib/llvm-project/lldb/source/Symbol/Symbol.cpp b/contrib/llvm-project/lldb/source/Symbol/Symbol.cpp index 668276aa2500..067b7b900d89 100644 --- a/contrib/llvm-project/lldb/source/Symbol/Symbol.cpp +++ b/contrib/llvm-project/lldb/source/Symbol/Symbol.cpp @@ -115,8 +115,7 @@ void Symbol::Clear() { } bool Symbol::ValueIsAddress() const { - return m_addr_range.GetBaseAddress().GetSection().get() != nullptr || - m_type == eSymbolTypeAbsolute; + return (bool)m_addr_range.GetBaseAddress().GetSection(); } ConstString Symbol::GetDisplayName() const { @@ -425,7 +424,7 @@ Symbol *Symbol::ResolveReExportedSymbolInModuleSpec( // Next try and find the module by basename in case environment variables // or other runtime trickery causes shared libraries to be loaded from // alternate paths - module_spec.GetFileSpec().GetDirectory().Clear(); + module_spec.GetFileSpec().ClearDirectory(); module_sp = target.GetImages().FindFirstModule(module_spec); } } diff --git a/contrib/llvm-project/lldb/source/Symbol/SymbolContext.cpp b/contrib/llvm-project/lldb/source/Symbol/SymbolContext.cpp index a10db0755d03..2ccc248d839e 100644 --- a/contrib/llvm-project/lldb/source/Symbol/SymbolContext.cpp +++ b/contrib/llvm-project/lldb/source/Symbol/SymbolContext.cpp @@ -812,9 +812,7 @@ const Symbol *SymbolContext::FindBestGlobalDataSymbol(ConstString name, reexport_module_sp = target.GetImages().FindFirstModule(reexport_module_spec); if (!reexport_module_sp) { - reexport_module_spec.GetPlatformFileSpec() - .GetDirectory() - .Clear(); + reexport_module_spec.GetPlatformFileSpec().ClearDirectory(); reexport_module_sp = target.GetImages().FindFirstModule(reexport_module_spec); } diff --git a/contrib/llvm-project/lldb/source/Symbol/SymbolFile.cpp b/contrib/llvm-project/lldb/source/Symbol/SymbolFile.cpp index e69150e9a356..b271efd07bfe 100644 --- a/contrib/llvm-project/lldb/source/Symbol/SymbolFile.cpp +++ b/contrib/llvm-project/lldb/source/Symbol/SymbolFile.cpp @@ -120,9 +120,8 @@ void SymbolFile::FindGlobalVariables(const RegularExpression ®ex, uint32_t max_matches, VariableList &variables) {} -void SymbolFile::FindFunctions(ConstString name, +void SymbolFile::FindFunctions(const Module::LookupInfo &lookup_info, const CompilerDeclContext &parent_decl_ctx, - lldb::FunctionNameType name_type_mask, bool include_inlines, SymbolContextList &sc_list) {} @@ -165,16 +164,15 @@ SymbolFile::RegisterInfoResolver::~RegisterInfoResolver() = default; Symtab *SymbolFileCommon::GetSymtab() { std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); - if (m_symtab) - return m_symtab; - // Fetch the symtab from the main object file. - m_symtab = GetMainObjectFile()->GetSymtab(); - - // Then add our symbols to it. - if (m_symtab) - AddSymbols(*m_symtab); + auto *symtab = GetMainObjectFile()->GetSymtab(); + if (m_symtab != symtab) { + m_symtab = symtab; + // Then add our symbols to it. + if (m_symtab) + AddSymbols(*m_symtab); + } return m_symtab; } @@ -187,8 +185,8 @@ void SymbolFileCommon::SectionFileAddressesChanged() { ObjectFile *symfile_objfile = GetObjectFile(); if (symfile_objfile != module_objfile) symfile_objfile->SectionFileAddressesChanged(); - if (m_symtab) - m_symtab->SectionFileAddressesChanged(); + if (auto *symtab = GetSymtab()) + symtab->SectionFileAddressesChanged(); } uint32_t SymbolFileCommon::GetNumCompileUnits() { @@ -228,12 +226,13 @@ void SymbolFileCommon::SetCompileUnitAtIndex(uint32_t idx, (*m_compile_units)[idx] = cu_sp; } -llvm::Expected<TypeSystem &> +llvm::Expected<TypeSystemSP> SymbolFileCommon::GetTypeSystemForLanguage(lldb::LanguageType language) { auto type_system_or_err = m_objfile_sp->GetModule()->GetTypeSystemForLanguage(language); if (type_system_or_err) { - type_system_or_err->SetSymbolFile(this); + if (auto ts = *type_system_or_err) + ts->SetSymbolFile(this); } return type_system_or_err; } diff --git a/contrib/llvm-project/lldb/source/Symbol/SymbolFileOnDemand.cpp b/contrib/llvm-project/lldb/source/Symbol/SymbolFileOnDemand.cpp index b97bc5460daf..aa3d23ccbf4d 100644 --- a/contrib/llvm-project/lldb/source/Symbol/SymbolFileOnDemand.cpp +++ b/contrib/llvm-project/lldb/source/Symbol/SymbolFileOnDemand.cpp @@ -12,6 +12,7 @@ #include "lldb/Symbol/SymbolFile.h" #include <memory> +#include <optional> using namespace lldb; using namespace lldb_private; @@ -197,13 +198,13 @@ Type *SymbolFileOnDemand::ResolveTypeUID(lldb::user_id_t type_uid) { return m_sym_file_impl->ResolveTypeUID(type_uid); } -llvm::Optional<SymbolFile::ArrayInfo> +std::optional<SymbolFile::ArrayInfo> SymbolFileOnDemand::GetDynamicArrayInfoForUID( lldb::user_id_t type_uid, const lldb_private::ExecutionContext *exe_ctx) { if (!m_debug_info_enabled) { LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(), __FUNCTION__); - return llvm::None; + return std::nullopt; } return m_sym_file_impl->GetDynamicArrayInfoForUID(type_uid, exe_ctx); } @@ -274,6 +275,15 @@ SymbolFileOnDemand::ResolveSymbolContext(const Address &so_addr, return m_sym_file_impl->ResolveSymbolContext(so_addr, resolve_scope, sc); } +Status SymbolFileOnDemand::CalculateFrameVariableError(StackFrame &frame) { + if (!m_debug_info_enabled) { + LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(), + __FUNCTION__); + return Status(); + } + return m_sym_file_impl->CalculateFrameVariableError(frame); +} + uint32_t SymbolFileOnDemand::ResolveSymbolContext( const SourceLocationSpec &src_location_spec, SymbolContextItem resolve_scope, SymbolContextList &sc_list) { @@ -375,9 +385,11 @@ void SymbolFileOnDemand::FindFunctions(const RegularExpression ®ex, } void SymbolFileOnDemand::FindFunctions( - ConstString name, const CompilerDeclContext &parent_decl_ctx, - FunctionNameType name_type_mask, bool include_inlines, + const Module::LookupInfo &lookup_info, + const CompilerDeclContext &parent_decl_ctx, bool include_inlines, SymbolContextList &sc_list) { + ConstString name = lookup_info.GetLookupName(); + FunctionNameType name_type_mask = lookup_info.GetNameTypeMask(); if (!m_debug_info_enabled) { Log *log = GetLog(); @@ -402,7 +414,7 @@ void SymbolFileOnDemand::FindFunctions( // allow the FindFucntions to go through. SetLoadDebugInfoEnabled(); } - return m_sym_file_impl->FindFunctions(name, parent_decl_ctx, name_type_mask, + return m_sym_file_impl->FindFunctions(lookup_info, parent_decl_ctx, include_inlines, sc_list); } @@ -456,7 +468,7 @@ void SymbolFileOnDemand::GetTypes(SymbolContextScope *sc_scope, return m_sym_file_impl->GetTypes(sc_scope, type_mask, type_list); } -llvm::Expected<TypeSystem &> +llvm::Expected<lldb::TypeSystemSP> SymbolFileOnDemand::GetTypeSystemForLanguage(LanguageType language) { if (!m_debug_info_enabled) { Log *log = GetLog(); diff --git a/contrib/llvm-project/lldb/source/Symbol/Symtab.cpp b/contrib/llvm-project/lldb/source/Symbol/Symtab.cpp index 936ee04ed492..40777e03be78 100644 --- a/contrib/llvm-project/lldb/source/Symbol/Symtab.cpp +++ b/contrib/llvm-project/lldb/source/Symbol/Symtab.cpp @@ -744,7 +744,7 @@ uint32_t Symtab::AppendSymbolIndexesWithNameAndType( uint32_t Symtab::AppendSymbolIndexesMatchingRegExAndType( const RegularExpression ®exp, SymbolType symbol_type, - std::vector<uint32_t> &indexes) { + std::vector<uint32_t> &indexes, Mangled::NamePreference name_preference) { std::lock_guard<std::recursive_mutex> guard(m_mutex); uint32_t prev_size = indexes.size(); @@ -753,7 +753,8 @@ uint32_t Symtab::AppendSymbolIndexesMatchingRegExAndType( for (uint32_t i = 0; i < sym_end; i++) { if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type) { - const char *name = m_symbols[i].GetName().AsCString(); + const char *name = + m_symbols[i].GetMangled().GetName(name_preference).AsCString(); if (name) { if (regexp.Execute(name)) indexes.push_back(i); @@ -766,7 +767,7 @@ uint32_t Symtab::AppendSymbolIndexesMatchingRegExAndType( uint32_t Symtab::AppendSymbolIndexesMatchingRegExAndType( const RegularExpression ®exp, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, - std::vector<uint32_t> &indexes) { + std::vector<uint32_t> &indexes, Mangled::NamePreference name_preference) { std::lock_guard<std::recursive_mutex> guard(m_mutex); uint32_t prev_size = indexes.size(); @@ -778,7 +779,8 @@ uint32_t Symtab::AppendSymbolIndexesMatchingRegExAndType( if (!CheckSymbolAtIndex(i, symbol_debug_type, symbol_visibility)) continue; - const char *name = m_symbols[i].GetName().AsCString(); + const char *name = + m_symbols[i].GetMangled().GetName(name_preference).AsCString(); if (name) { if (regexp.Execute(name)) indexes.push_back(i); @@ -847,11 +849,13 @@ void Symtab::FindAllSymbolsWithNameAndType( void Symtab::FindAllSymbolsMatchingRexExAndType( const RegularExpression ®ex, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, - std::vector<uint32_t> &symbol_indexes) { + std::vector<uint32_t> &symbol_indexes, + Mangled::NamePreference name_preference) { std::lock_guard<std::recursive_mutex> guard(m_mutex); AppendSymbolIndexesMatchingRegExAndType(regex, symbol_type, symbol_debug_type, - symbol_visibility, symbol_indexes); + symbol_visibility, symbol_indexes, + name_preference); } Symbol *Symtab::FindFirstSymbolWithNameAndType(ConstString name, diff --git a/contrib/llvm-project/lldb/source/Symbol/Type.cpp b/contrib/llvm-project/lldb/source/Symbol/Type.cpp index f83bdcdc1c74..f901c24298a3 100644 --- a/contrib/llvm-project/lldb/source/Symbol/Type.cpp +++ b/contrib/llvm-project/lldb/source/Symbol/Type.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include <cstdio> +#include <optional> #include "lldb/Core/Module.h" #include "lldb/Utility/DataBufferHeap.h" @@ -141,7 +142,7 @@ Type *SymbolFileType::GetType() { } Type::Type(lldb::user_id_t uid, SymbolFile *symbol_file, ConstString name, - llvm::Optional<uint64_t> byte_size, SymbolContextScope *context, + std::optional<uint64_t> byte_size, SymbolContextScope *context, user_id_t encoding_uid, EncodingDataType encoding_uid_type, const Declaration &decl, const CompilerType &compiler_type, ResolveState compiler_type_resolve_state, uint32_t opaque_payload) @@ -184,7 +185,7 @@ void Type::GetDescription(Stream *s, lldb::DescriptionLevel level, } } - // Call the get byte size accesor so we resolve our byte size + // Call the get byte size accessor so we resolve our byte size if (GetByteSize(exe_scope)) s->Printf(", byte-size = %" PRIu64, m_byte_size); bool show_fullpaths = (level == lldb::eDescriptionLevelVerbose); @@ -305,6 +306,10 @@ ConstString Type::GetName() { return m_name; } +ConstString Type::GetBaseName() { + return GetForwardCompilerType().GetTypeName(/*BaseOnly*/ true); +} + void Type::DumpTypeName(Stream *s) { GetName().Dump(s, "<invalid-type-name>"); } void Type::DumpValue(ExecutionContext *exe_ctx, Stream *s, @@ -337,9 +342,9 @@ Type *Type::GetEncodingType() { return m_encoding_type; } -llvm::Optional<uint64_t> Type::GetByteSize(ExecutionContextScope *exe_scope) { +std::optional<uint64_t> Type::GetByteSize(ExecutionContextScope *exe_scope) { if (m_byte_size_has_value) - return m_byte_size; + return static_cast<uint64_t>(m_byte_size); switch (m_encoding_uid_type) { case eEncodingInvalid: @@ -353,17 +358,18 @@ llvm::Optional<uint64_t> Type::GetByteSize(ExecutionContextScope *exe_scope) { case eEncodingIsTypedefUID: { Type *encoding_type = GetEncodingType(); if (encoding_type) - if (llvm::Optional<uint64_t> size = encoding_type->GetByteSize(exe_scope)) { + if (std::optional<uint64_t> size = + encoding_type->GetByteSize(exe_scope)) { m_byte_size = *size; m_byte_size_has_value = true; - return m_byte_size; + return static_cast<uint64_t>(m_byte_size); } - if (llvm::Optional<uint64_t> size = + if (std::optional<uint64_t> size = GetLayoutCompilerType().GetByteSize(exe_scope)) { m_byte_size = *size; m_byte_size_has_value = true; - return m_byte_size; + return static_cast<uint64_t>(m_byte_size); } } break; @@ -374,7 +380,7 @@ llvm::Optional<uint64_t> Type::GetByteSize(ExecutionContextScope *exe_scope) { if (ArchSpec arch = m_symbol_file->GetObjectFile()->GetArchitecture()) { m_byte_size = arch.GetAddressByteSize(); m_byte_size_has_value = true; - return m_byte_size; + return static_cast<uint64_t>(m_byte_size); } } break; } @@ -389,6 +395,10 @@ bool Type::IsAggregateType() { return GetForwardCompilerType().IsAggregateType(); } +bool Type::IsTemplateType() { + return GetForwardCompilerType().IsTemplateType(); +} + lldb::TypeSP Type::GetTypedefType() { lldb::TypeSP type_sp; if (IsTypedef()) { @@ -539,8 +549,10 @@ bool Type::ResolveCompilerType(ResolveState compiler_type_resolve_state) { LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err), "Unable to construct void type from TypeSystemClang"); } else { - CompilerType void_compiler_type = - type_system_or_err->GetBasicTypeFromAST(eBasicTypeVoid); + CompilerType void_compiler_type; + auto ts = *type_system_or_err; + if (ts) + void_compiler_type = ts->GetBasicTypeFromAST(eBasicTypeVoid); switch (m_encoding_uid_type) { case eEncodingIsUID: m_compiler_type = void_compiler_type; @@ -726,11 +738,14 @@ ModuleSP Type::GetModule() { ModuleSP Type::GetExeModule() { if (m_compiler_type) { - SymbolFile *symbol_file = m_compiler_type.GetTypeSystem()->GetSymbolFile(); + auto ts = m_compiler_type.GetTypeSystem(); + if (!ts) + return {}; + SymbolFile *symbol_file = ts->GetSymbolFile(); if (symbol_file) return symbol_file->GetObjectFile()->GetModule(); } - return ModuleSP(); + return {}; } TypeAndOrName::TypeAndOrName(TypeSP &in_type_sp) { @@ -1038,7 +1053,7 @@ CompilerType TypeImpl::GetCompilerType(bool prefer_dynamic) { return CompilerType(); } -TypeSystem *TypeImpl::GetTypeSystem(bool prefer_dynamic) { +CompilerType::TypeSystemSPWrapper TypeImpl::GetTypeSystem(bool prefer_dynamic) { ModuleSP module_sp; if (CheckModule(module_sp)) { if (prefer_dynamic) { @@ -1047,7 +1062,7 @@ TypeSystem *TypeImpl::GetTypeSystem(bool prefer_dynamic) { } return m_static_type.GetTypeSystem(); } - return nullptr; + return {}; } bool TypeImpl::GetDescription(lldb_private::Stream &strm, diff --git a/contrib/llvm-project/lldb/source/Symbol/TypeList.cpp b/contrib/llvm-project/lldb/source/Symbol/TypeList.cpp index 494e59e3a0fc..2e101e0a8f57 100644 --- a/contrib/llvm-project/lldb/source/Symbol/TypeList.cpp +++ b/contrib/llvm-project/lldb/source/Symbol/TypeList.cpp @@ -92,9 +92,9 @@ void TypeList::ForEach( } void TypeList::Dump(Stream *s, bool show_context) { - for (iterator pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) { - pos->get()->Dump(s, show_context); - } + for (iterator pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) + if (Type *t = pos->get()) + t->Dump(s, show_context); } void TypeList::RemoveMismatchedTypes(llvm::StringRef qualified_typename, diff --git a/contrib/llvm-project/lldb/source/Symbol/TypeSystem.cpp b/contrib/llvm-project/lldb/source/Symbol/TypeSystem.cpp index 412373533aab..4eae2c98b12e 100644 --- a/contrib/llvm-project/lldb/source/Symbol/TypeSystem.cpp +++ b/contrib/llvm-project/lldb/source/Symbol/TypeSystem.cpp @@ -12,7 +12,8 @@ #include "lldb/Symbol/CompilerType.h" #include "lldb/Target/Language.h" -#include <set> +#include "llvm/ADT/DenseSet.h" +#include <optional> using namespace lldb_private; using namespace lldb; @@ -24,7 +25,7 @@ static_assert(eNumLanguageTypes < g_num_small_bitvector_bits, "Languages bit vector is no longer small on 64 bit systems"); LanguageSet::LanguageSet() : bitvector(eNumLanguageTypes, false) {} -llvm::Optional<LanguageType> LanguageSet::GetSingularLanguage() { +std::optional<LanguageType> LanguageSet::GetSingularLanguage() { if (bitvector.count() == 1) return (LanguageType)bitvector.find_first(); return {}; @@ -37,19 +38,17 @@ bool LanguageSet::operator[](unsigned i) const { return bitvector[i]; } TypeSystem::~TypeSystem() = default; -static lldb::TypeSystemSP CreateInstanceHelper(lldb::LanguageType language, - Module *module, Target *target) { +static TypeSystemSP CreateInstanceHelper(lldb::LanguageType language, + Module *module, Target *target) { uint32_t i = 0; TypeSystemCreateInstance create_callback; while ((create_callback = PluginManager::GetTypeSystemCreateCallbackAtIndex( i++)) != nullptr) { - lldb::TypeSystemSP type_system_sp = - create_callback(language, module, target); - if (type_system_sp) + if (auto type_system_sp = create_callback(language, module, target)) return type_system_sp; } - return lldb::TypeSystemSP(); + return {}; } lldb::TypeSystemSP TypeSystem::CreateInstance(lldb::LanguageType language, @@ -115,7 +114,11 @@ CompilerType TypeSystem::GetBuiltinTypeByName(ConstString name) { } CompilerType TypeSystem::GetTypeForFormatters(void *type) { - return CompilerType(this, type); + return CompilerType(weak_from_this(), type); +} + +bool TypeSystem::IsTemplateType(lldb::opaque_compiler_type_t type) { + return false; } size_t TypeSystem::GetNumTemplateArguments(lldb::opaque_compiler_type_t type, @@ -134,10 +137,10 @@ CompilerType TypeSystem::GetTypeTemplateArgument(opaque_compiler_type_t type, return CompilerType(); } -llvm::Optional<CompilerType::IntegralTemplateArgument> +std::optional<CompilerType::IntegralTemplateArgument> TypeSystem::GetIntegralTemplateArgument(opaque_compiler_type_t type, size_t idx, bool expand_pack) { - return llvm::None; + return std::nullopt; } LazyBool TypeSystem::ShouldPrintAsOneLiner(void *type, ValueObject *valobj) { @@ -178,6 +181,10 @@ TypeSystem::CreateUtilityFunction(std::string text, std::string name) { return {}; } +std::optional<llvm::json::Value> TypeSystem::ReportStatistics() { + return std::nullopt; +} + #pragma mark TypeSystemMap TypeSystemMap::TypeSystemMap() : m_mutex(), m_map() {} @@ -191,13 +198,13 @@ void TypeSystemMap::Clear() { map = m_map; m_clear_in_progress = true; } - std::set<TypeSystem *> visited; - for (auto pair : map) { - TypeSystem *type_system = pair.second.get(); - if (type_system && !visited.count(type_system)) { - visited.insert(type_system); + llvm::DenseSet<TypeSystem *> visited; + for (auto &pair : map) { + if (visited.count(pair.second.get())) + continue; + visited.insert(pair.second.get()); + if (lldb::TypeSystemSP type_system = pair.second) type_system->Finalize(); - } } map.clear(); { @@ -207,24 +214,26 @@ void TypeSystemMap::Clear() { } } -void TypeSystemMap::ForEach(std::function<bool(TypeSystem *)> const &callback) { +void TypeSystemMap::ForEach( + std::function<bool(lldb::TypeSystemSP)> const &callback) { std::lock_guard<std::mutex> guard(m_mutex); // Use a std::set so we only call the callback once for each unique - // TypeSystem instance - std::set<TypeSystem *> visited; - for (auto pair : m_map) { + // TypeSystem instance. + llvm::DenseSet<TypeSystem *> visited; + for (auto &pair : m_map) { TypeSystem *type_system = pair.second.get(); - if (type_system && !visited.count(type_system)) { - visited.insert(type_system); - if (!callback(type_system)) - break; - } + if (!type_system || visited.count(type_system)) + continue; + visited.insert(type_system); + assert(type_system); + if (!callback(pair.second)) + break; } } -llvm::Expected<TypeSystem &> TypeSystemMap::GetTypeSystemForLanguage( +llvm::Expected<lldb::TypeSystemSP> TypeSystemMap::GetTypeSystemForLanguage( lldb::LanguageType language, - llvm::Optional<CreateCallback> create_callback) { + std::optional<CreateCallback> create_callback) { std::lock_guard<std::mutex> guard(m_mutex); if (m_clear_in_progress) return llvm::make_error<llvm::StringError>( @@ -233,9 +242,10 @@ llvm::Expected<TypeSystem &> TypeSystemMap::GetTypeSystemForLanguage( collection::iterator pos = m_map.find(language); if (pos != m_map.end()) { - auto *type_system = pos->second.get(); - if (type_system) - return *type_system; + if (pos->second) { + assert(!pos->second->weak_from_this().expired()); + return pos->second; + } return llvm::make_error<llvm::StringError>( "TypeSystem for language " + llvm::StringRef(Language::GetNameForLanguageType(language)) + @@ -248,8 +258,8 @@ llvm::Expected<TypeSystem &> TypeSystemMap::GetTypeSystemForLanguage( // Add a new mapping for "language" to point to an already existing // TypeSystem that supports this language m_map[language] = pair.second; - if (pair.second.get()) - return *pair.second.get(); + if (pair.second) + return pair.second; return llvm::make_error<llvm::StringError>( "TypeSystem for language " + llvm::StringRef(Language::GetNameForLanguageType(language)) + @@ -265,11 +275,11 @@ llvm::Expected<TypeSystem &> TypeSystemMap::GetTypeSystemForLanguage( llvm::inconvertibleErrorCode()); // Cache even if we get a shared pointer that contains a null type system - // back + // back. TypeSystemSP type_system_sp = (*create_callback)(); m_map[language] = type_system_sp; - if (type_system_sp.get()) - return *type_system_sp.get(); + if (type_system_sp) + return type_system_sp; return llvm::make_error<llvm::StringError>( "TypeSystem for language " + llvm::StringRef(Language::GetNameForLanguageType(language)) + @@ -277,24 +287,24 @@ llvm::Expected<TypeSystem &> TypeSystemMap::GetTypeSystemForLanguage( llvm::inconvertibleErrorCode()); } -llvm::Expected<TypeSystem &> +llvm::Expected<lldb::TypeSystemSP> TypeSystemMap::GetTypeSystemForLanguage(lldb::LanguageType language, Module *module, bool can_create) { if (can_create) { return GetTypeSystemForLanguage( - language, llvm::Optional<CreateCallback>([language, module]() { + language, std::optional<CreateCallback>([language, module]() { return TypeSystem::CreateInstance(language, module); })); } return GetTypeSystemForLanguage(language); } -llvm::Expected<TypeSystem &> +llvm::Expected<lldb::TypeSystemSP> TypeSystemMap::GetTypeSystemForLanguage(lldb::LanguageType language, Target *target, bool can_create) { if (can_create) { return GetTypeSystemForLanguage( - language, llvm::Optional<CreateCallback>([language, target]() { + language, std::optional<CreateCallback>([language, target]() { return TypeSystem::CreateInstance(language, target); })); } diff --git a/contrib/llvm-project/lldb/source/Symbol/UnwindPlan.cpp b/contrib/llvm-project/lldb/source/Symbol/UnwindPlan.cpp index bd4690547c6b..e258a4e3d82f 100644 --- a/contrib/llvm-project/lldb/source/Symbol/UnwindPlan.cpp +++ b/contrib/llvm-project/lldb/source/Symbol/UnwindPlan.cpp @@ -17,6 +17,7 @@ #include "lldb/Utility/Log.h" #include "llvm/DebugInfo/DIContext.h" #include "llvm/DebugInfo/DWARF/DWARFExpression.h" +#include <optional> using namespace lldb; using namespace lldb_private; @@ -68,13 +69,13 @@ void UnwindPlan::Row::RegisterLocation::SetIsDWARFExpression( m_location.expr.length = len; } -static llvm::Optional<std::pair<lldb::ByteOrder, uint32_t>> +static std::optional<std::pair<lldb::ByteOrder, uint32_t>> GetByteOrderAndAddrSize(Thread *thread) { if (!thread) - return llvm::None; + return std::nullopt; ProcessSP process_sp = thread->GetProcess(); if (!process_sp) - return llvm::None; + return std::nullopt; ArchSpec arch = process_sp->GetTarget().GetArchitecture(); return std::make_pair(arch.GetByteOrder(), arch.GetAddressByteSize()); } @@ -84,7 +85,7 @@ static void DumpDWARFExpr(Stream &s, llvm::ArrayRef<uint8_t> expr, Thread *threa llvm::DataExtractor data(expr, order_and_width->first == eByteOrderLittle, order_and_width->second); llvm::DWARFExpression(data, order_and_width->second, llvm::dwarf::DWARF32) - .print(s.AsRawOstream(), llvm::DIDumpOptions(), nullptr, nullptr); + .print(s.AsRawOstream(), llvm::DIDumpOptions(), nullptr); } else s.PutCString("dwarf-expr"); } @@ -147,7 +148,7 @@ void UnwindPlan::Row::RegisterLocation::Dump(Stream &s, if (m_type == atDWARFExpression) s.PutChar('['); DumpDWARFExpr( - s, llvm::makeArrayRef(m_location.expr.opcodes, m_location.expr.length), + s, llvm::ArrayRef(m_location.expr.opcodes, m_location.expr.length), thread); if (m_type == atDWARFExpression) s.PutChar(']'); @@ -201,8 +202,7 @@ void UnwindPlan::Row::FAValue::Dump(Stream &s, const UnwindPlan *unwind_plan, s.PutChar(']'); break; case isDWARFExpression: - DumpDWARFExpr(s, - llvm::makeArrayRef(m_value.expr.opcodes, m_value.expr.length), + DumpDWARFExpr(s, llvm::ArrayRef(m_value.expr.opcodes, m_value.expr.length), thread); break; case unspecified: diff --git a/contrib/llvm-project/lldb/source/Symbol/UnwindTable.cpp b/contrib/llvm-project/lldb/source/Symbol/UnwindTable.cpp index fe69e41b3638..268f95f71eb4 100644 --- a/contrib/llvm-project/lldb/source/Symbol/UnwindTable.cpp +++ b/contrib/llvm-project/lldb/source/Symbol/UnwindTable.cpp @@ -9,6 +9,7 @@ #include "lldb/Symbol/UnwindTable.h" #include <cstdio> +#include <optional> #include "lldb/Core/Module.h" #include "lldb/Core/Section.h" @@ -85,8 +86,8 @@ void UnwindTable::Initialize() { UnwindTable::~UnwindTable() = default; -llvm::Optional<AddressRange> UnwindTable::GetAddressRange(const Address &addr, - SymbolContext &sc) { +std::optional<AddressRange> UnwindTable::GetAddressRange(const Address &addr, + SymbolContext &sc) { AddressRange range; // First check the unwind info from the object file plugin @@ -108,7 +109,7 @@ llvm::Optional<AddressRange> UnwindTable::GetAddressRange(const Address &addr, if (m_debug_frame_up && m_debug_frame_up->GetAddressRange(addr, range)) return range; - return llvm::None; + return std::nullopt; } FuncUnwindersSP diff --git a/contrib/llvm-project/lldb/source/Symbol/Variable.cpp b/contrib/llvm-project/lldb/source/Symbol/Variable.cpp index f65e73e5d049..5e1996b13bcc 100644 --- a/contrib/llvm-project/lldb/source/Symbol/Variable.cpp +++ b/contrib/llvm-project/lldb/source/Symbol/Variable.cpp @@ -578,7 +578,8 @@ static void PrivateAutoComplete( if (frame) { const bool get_file_globals = true; - VariableList *variable_list = frame->GetVariableList(get_file_globals); + VariableList *variable_list = frame->GetVariableList(get_file_globals, + nullptr); if (variable_list) { for (const VariableSP &var_sp : *variable_list) @@ -674,7 +675,7 @@ static void PrivateAutoComplete( const bool get_file_globals = true; VariableList *variable_list = - frame->GetVariableList(get_file_globals); + frame->GetVariableList(get_file_globals, nullptr); if (!variable_list) break; diff --git a/contrib/llvm-project/lldb/source/Target/JITLoaderList.cpp b/contrib/llvm-project/lldb/source/Target/JITLoaderList.cpp index 92e841b5c94d..9158d0a5e546 100644 --- a/contrib/llvm-project/lldb/source/Target/JITLoaderList.cpp +++ b/contrib/llvm-project/lldb/source/Target/JITLoaderList.cpp @@ -24,9 +24,7 @@ void JITLoaderList::Append(const JITLoaderSP &jit_loader_sp) { void JITLoaderList::Remove(const JITLoaderSP &jit_loader_sp) { std::lock_guard<std::recursive_mutex> guard(m_jit_loaders_mutex); - m_jit_loaders_vec.erase(std::remove(m_jit_loaders_vec.begin(), - m_jit_loaders_vec.end(), jit_loader_sp), - m_jit_loaders_vec.end()); + llvm::erase_value(m_jit_loaders_vec, jit_loader_sp); } size_t JITLoaderList::GetSize() const { return m_jit_loaders_vec.size(); } diff --git a/contrib/llvm-project/lldb/source/Target/Language.cpp b/contrib/llvm-project/lldb/source/Target/Language.cpp index 6df36aeeb7b7..892d2a86437e 100644 --- a/contrib/llvm-project/lldb/source/Target/Language.cpp +++ b/contrib/llvm-project/lldb/source/Target/Language.cpp @@ -144,7 +144,7 @@ Language::GetHardcodedSynthetics() { return {}; } -std::vector<ConstString> +std::vector<FormattersMatchCandidate> Language::GetPossibleFormattersMatches(ValueObject &valobj, lldb::DynamicValueType use_dynamic) { return {}; @@ -221,6 +221,17 @@ const char *Language::GetNameForLanguageType(LanguageType language) { return language_names[eLanguageTypeUnknown].name; } +void Language::PrintSupportedLanguagesForExpressions(Stream &s, + llvm::StringRef prefix, + llvm::StringRef suffix) { + auto supported = Language::GetLanguagesSupportingTypeSystemsForExpressions(); + for (size_t idx = 0; idx < num_languages; ++idx) { + auto const &lang = language_names[idx]; + if (supported[lang.type]) + s << prefix << lang.name << suffix; + } +} + void Language::PrintAllLanguages(Stream &s, const char *prefix, const char *suffix) { for (uint32_t i = 1; i < num_languages; i++) { diff --git a/contrib/llvm-project/lldb/source/Target/Memory.cpp b/contrib/llvm-project/lldb/source/Target/Memory.cpp index a07a72f31922..d4dedeea7c2c 100644 --- a/contrib/llvm-project/lldb/source/Target/Memory.cpp +++ b/contrib/llvm-project/lldb/source/Target/Memory.cpp @@ -332,9 +332,9 @@ AllocatedMemoryCache::AllocatedMemoryCache(Process &process) AllocatedMemoryCache::~AllocatedMemoryCache() = default; -void AllocatedMemoryCache::Clear() { +void AllocatedMemoryCache::Clear(bool deallocate_memory) { std::lock_guard<std::recursive_mutex> guard(m_mutex); - if (m_process.IsAlive()) { + if (m_process.IsAlive() && deallocate_memory) { PermissionsToBlockMap::iterator pos, end = m_memory_map.end(); for (pos = m_memory_map.begin(); pos != end; ++pos) m_process.DoDeallocateMemory(pos->second->GetBaseAddress()); diff --git a/contrib/llvm-project/lldb/source/Target/MemoryTagMap.cpp b/contrib/llvm-project/lldb/source/Target/MemoryTagMap.cpp index 846eef9209da..c5a7c85ac09e 100644 --- a/contrib/llvm-project/lldb/source/Target/MemoryTagMap.cpp +++ b/contrib/llvm-project/lldb/source/Target/MemoryTagMap.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "lldb/Target/MemoryTagMap.h" +#include <optional> using namespace lldb_private; @@ -27,38 +28,38 @@ void MemoryTagMap::InsertTags(lldb::addr_t addr, bool MemoryTagMap::Empty() const { return m_addr_to_tag.empty(); } -std::vector<llvm::Optional<lldb::addr_t>> +std::vector<std::optional<lldb::addr_t>> MemoryTagMap::GetTags(lldb::addr_t addr, size_t len) const { // Addr and len might be unaligned addr = m_manager->RemoveTagBits(addr); MemoryTagManager::TagRange range(addr, len); range = m_manager->ExpandToGranule(range); - std::vector<llvm::Optional<lldb::addr_t>> tags; + std::vector<std::optional<lldb::addr_t>> tags; lldb::addr_t end_addr = range.GetRangeEnd(); addr = range.GetRangeBase(); bool got_valid_tags = false; size_t granule_size = m_manager->GetGranuleSize(); for (; addr < end_addr; addr += granule_size) { - llvm::Optional<lldb::addr_t> tag = GetTag(addr); + std::optional<lldb::addr_t> tag = GetTag(addr); tags.push_back(tag); if (tag) got_valid_tags = true; } - // To save the caller checking if every item is llvm::None, + // To save the caller checking if every item is std::nullopt, // we return an empty vector if we got no tags at all. if (got_valid_tags) return tags; return {}; } -llvm::Optional<lldb::addr_t> MemoryTagMap::GetTag(lldb::addr_t addr) const { +std::optional<lldb::addr_t> MemoryTagMap::GetTag(lldb::addr_t addr) const { // Here we assume that addr is granule aligned, just like when the tags // were inserted. auto found = m_addr_to_tag.find(addr); if (found == m_addr_to_tag.end()) - return llvm::None; + return std::nullopt; return found->second; } diff --git a/contrib/llvm-project/lldb/source/Target/PathMappingList.cpp b/contrib/llvm-project/lldb/source/Target/PathMappingList.cpp index 4ebb175fcd85..13bb50b362c6 100644 --- a/contrib/llvm-project/lldb/source/Target/PathMappingList.cpp +++ b/contrib/llvm-project/lldb/source/Target/PathMappingList.cpp @@ -8,6 +8,7 @@ #include <climits> #include <cstring> +#include <optional> #include "lldb/Host/FileSystem.h" #include "lldb/Host/PosixApi.h" @@ -76,6 +77,19 @@ void PathMappingList::Append(const PathMappingList &rhs, bool notify) { } } +bool PathMappingList::AppendUnique(llvm::StringRef path, + llvm::StringRef replacement, bool notify) { + auto normalized_path = NormalizePath(path); + auto normalized_replacement = NormalizePath(replacement); + for (const auto &pair : m_pairs) { + if (pair.first.GetStringRef().equals(normalized_path) && + pair.second.GetStringRef().equals(normalized_replacement)) + return false; + } + Append(path, replacement, notify); + return true; +} + void PathMappingList::Insert(llvm::StringRef path, llvm::StringRef replacement, uint32_t index, bool notify) { ++m_mod_id; @@ -131,6 +145,16 @@ void PathMappingList::Dump(Stream *s, int pair_index) { } } +llvm::json::Value PathMappingList::ToJSON() { + llvm::json::Array entries; + for (const auto &pair : m_pairs) { + llvm::json::Array entry{pair.first.GetStringRef().str(), + pair.second.GetStringRef().str()}; + entries.emplace_back(std::move(entry)); + } + return entries; +} + void PathMappingList::Clear(bool notify) { if (!m_pairs.empty()) ++m_mod_id; @@ -141,7 +165,7 @@ void PathMappingList::Clear(bool notify) { bool PathMappingList::RemapPath(ConstString path, ConstString &new_path) const { - if (llvm::Optional<FileSpec> remapped = RemapPath(path.GetStringRef())) { + if (std::optional<FileSpec> remapped = RemapPath(path.GetStringRef())) { new_path.SetString(remapped->GetPath()); return true; } @@ -151,18 +175,17 @@ bool PathMappingList::RemapPath(ConstString path, /// Append components to path, applying style. static void AppendPathComponents(FileSpec &path, llvm::StringRef components, llvm::sys::path::Style style) { - auto component = llvm::sys::path::begin(components, style); - auto e = llvm::sys::path::end(components); - while (component != e && - llvm::sys::path::is_separator(*component->data(), style)) - ++component; - for (; component != e; ++component) - path.AppendPathComponent(*component); + auto component = llvm::sys::path::begin(components, style); + auto e = llvm::sys::path::end(components); + while (component != e && + llvm::sys::path::is_separator(*component->data(), style)) + ++component; + for (; component != e; ++component) + path.AppendPathComponent(*component); } -llvm::Optional<FileSpec> -PathMappingList::RemapPath(llvm::StringRef mapping_path, - bool only_if_exists) const { +std::optional<FileSpec> PathMappingList::RemapPath(llvm::StringRef mapping_path, + bool only_if_exists) const { if (m_pairs.empty() || mapping_path.empty()) return {}; LazyBool path_is_relative = eLazyBoolCalculate; @@ -197,10 +220,12 @@ PathMappingList::RemapPath(llvm::StringRef mapping_path, return {}; } -bool PathMappingList::ReverseRemapPath(const FileSpec &file, FileSpec &fixed) const { +std::optional<llvm::StringRef> +PathMappingList::ReverseRemapPath(const FileSpec &file, FileSpec &fixed) const { std::string path = file.GetPath(); llvm::StringRef path_ref(path); for (const auto &it : m_pairs) { + llvm::StringRef removed_prefix = it.second.GetStringRef(); if (!path_ref.consume_front(it.second.GetStringRef())) continue; auto orig_file = it.first.GetStringRef(); @@ -208,12 +233,13 @@ bool PathMappingList::ReverseRemapPath(const FileSpec &file, FileSpec &fixed) co llvm::sys::path::Style::native); fixed.SetFile(orig_file, orig_style); AppendPathComponents(fixed, path_ref, orig_style); - return true; + return removed_prefix; } - return false; + return std::nullopt; } -llvm::Optional<FileSpec> PathMappingList::FindFile(const FileSpec &orig_spec) const { +std::optional<FileSpec> +PathMappingList::FindFile(const FileSpec &orig_spec) const { // We must normalize the orig_spec again using the host's path style, // otherwise there will be mismatch between the host and remote platform // if they use different path styles. diff --git a/contrib/llvm-project/lldb/source/Target/Platform.cpp b/contrib/llvm-project/lldb/source/Target/Platform.cpp index 559f7664c72e..1ddd7596280e 100644 --- a/contrib/llvm-project/lldb/source/Target/Platform.cpp +++ b/contrib/llvm-project/lldb/source/Target/Platform.cpp @@ -10,6 +10,7 @@ #include <csignal> #include <fstream> #include <memory> +#include <optional> #include <vector> #include "lldb/Breakpoint/BreakpointIDList.h" @@ -298,7 +299,7 @@ void Platform::GetStatus(Stream &strm) { if (!os_version.empty()) { strm.Format("OS Version: {0}", os_version.getAsString()); - if (llvm::Optional<std::string> s = GetOSBuildString()) + if (std::optional<std::string> s = GetOSBuildString()) strm.Format(" ({0})", *s); strm.EOL(); @@ -317,7 +318,7 @@ void Platform::GetStatus(Stream &strm) { strm.Format(" Sysroot: {0}\n", GetSDKRootDirectory()); } if (GetWorkingDirectory()) { - strm.Printf("WorkingDir: %s\n", GetWorkingDirectory().GetCString()); + strm.Printf("WorkingDir: %s\n", GetWorkingDirectory().GetPath().c_str()); } if (!IsConnected()) return; @@ -327,7 +328,7 @@ void Platform::GetStatus(Stream &strm) { if (!specific_info.empty()) strm.Printf("Platform-specific connection: %s\n", specific_info.c_str()); - if (llvm::Optional<std::string> s = GetOSKernelDescription()) + if (std::optional<std::string> s = GetOSKernelDescription()) strm.Format(" Kernel: {0}\n", *s); } @@ -373,13 +374,13 @@ llvm::VersionTuple Platform::GetOSVersion(Process *process) { return llvm::VersionTuple(); } -llvm::Optional<std::string> Platform::GetOSBuildString() { +std::optional<std::string> Platform::GetOSBuildString() { if (IsHost()) return HostInfo::GetOSBuildString(); return GetRemoteOSBuildString(); } -llvm::Optional<std::string> Platform::GetOSKernelDescription() { +std::optional<std::string> Platform::GetOSKernelDescription() { if (IsHost()) return HostInfo::GetOSKernelDescription(); return GetRemoteOSKernelDescription(); @@ -434,12 +435,13 @@ RecurseCopy_Callback(void *baton, llvm::sys::fs::file_type ft, // make the new directory and get in there FileSpec dst_dir = rc_baton->dst; if (!dst_dir.GetFilename()) - dst_dir.GetFilename() = src.GetLastPathComponent(); + dst_dir.SetFilename(src.GetLastPathComponent()); Status error = rc_baton->platform_ptr->MakeDirectory( dst_dir, lldb::eFilePermissionsDirectoryDefault); if (error.Fail()) { rc_baton->error.SetErrorStringWithFormat( - "unable to setup directory %s on remote end", dst_dir.GetCString()); + "unable to setup directory %s on remote end", + dst_dir.GetPath().c_str()); return FileSystem::eEnumerateDirectoryResultQuit; // got an error, bail out } @@ -449,7 +451,7 @@ RecurseCopy_Callback(void *baton, llvm::sys::fs::file_type ft, // Make a filespec that only fills in the directory of a FileSpec so when // we enumerate we can quickly fill in the filename for dst copies FileSpec recurse_dst; - recurse_dst.GetDirectory().SetCString(dst_dir.GetPath().c_str()); + recurse_dst.SetDirectory(dst_dir.GetPathAsConstString()); RecurseCopyBaton rc_baton2 = {recurse_dst, rc_baton->platform_ptr, Status()}; FileSystem::Instance().EnumerateDirectory(src_dir_path, true, true, true, @@ -465,7 +467,7 @@ RecurseCopy_Callback(void *baton, llvm::sys::fs::file_type ft, // copy the file and keep going FileSpec dst_file = rc_baton->dst; if (!dst_file.GetFilename()) - dst_file.GetFilename() = src.GetFilename(); + dst_file.SetFilename(src.GetFilename()); FileSpec src_resolved; @@ -487,7 +489,7 @@ RecurseCopy_Callback(void *baton, llvm::sys::fs::file_type ft, // copy the file and keep going FileSpec dst_file = rc_baton->dst; if (!dst_file.GetFilename()) - dst_file.GetFilename() = src.GetFilename(); + dst_file.SetFilename(src.GetFilename()); Status err = rc_baton->platform_ptr->PutFile(src, dst_file); if (err.Fail()) { rc_baton->error.SetErrorString(err.AsCString()); @@ -514,7 +516,7 @@ Status Platform::Install(const FileSpec &src, const FileSpec &dst) { FileSpec fixed_dst(dst); if (!fixed_dst.GetFilename()) - fixed_dst.GetFilename() = src.GetFilename(); + fixed_dst.SetFilename(src.GetFilename()); FileSpec working_dir = GetWorkingDirectory(); @@ -522,7 +524,7 @@ Status Platform::Install(const FileSpec &src, const FileSpec &dst) { if (dst.GetDirectory()) { const char first_dst_dir_char = dst.GetDirectory().GetCString()[0]; if (first_dst_dir_char == '/' || first_dst_dir_char == '\\') { - fixed_dst.GetDirectory() = dst.GetDirectory(); + fixed_dst.SetDirectory(dst.GetDirectory()); } // If the fixed destination file doesn't have a directory yet, then we // must have a relative path. We will resolve this relative path against @@ -533,7 +535,7 @@ Status Platform::Install(const FileSpec &src, const FileSpec &dst) { if (working_dir) { relative_spec = working_dir; relative_spec.AppendPathComponent(dst.GetPath()); - fixed_dst.GetDirectory() = relative_spec.GetDirectory(); + fixed_dst.SetDirectory(relative_spec.GetDirectory()); } else { error.SetErrorStringWithFormat( "platform working directory must be valid for relative path '%s'", @@ -543,7 +545,7 @@ Status Platform::Install(const FileSpec &src, const FileSpec &dst) { } } else { if (working_dir) { - fixed_dst.GetDirectory().SetCString(working_dir.GetCString()); + fixed_dst.SetDirectory(working_dir.GetPathAsConstString()); } else { error.SetErrorStringWithFormat( "platform working directory must be valid for relative path '%s'", @@ -553,7 +555,7 @@ Status Platform::Install(const FileSpec &src, const FileSpec &dst) { } } else { if (working_dir) { - fixed_dst.GetDirectory().SetCString(working_dir.GetCString()); + fixed_dst.SetDirectory(working_dir.GetPathAsConstString()); } else { error.SetErrorStringWithFormat("platform working directory must be valid " "when destination directory is empty"); @@ -580,7 +582,7 @@ Status Platform::Install(const FileSpec &src, const FileSpec &dst) { // Make a filespec that only fills in the directory of a FileSpec so // when we enumerate we can quickly fill in the filename for dst copies FileSpec recurse_dst; - recurse_dst.GetDirectory().SetCString(fixed_dst.GetCString()); + recurse_dst.SetDirectory(fixed_dst.GetPathAsConstString()); std::string src_dir_path(src.GetPath()); RecurseCopyBaton baton = {recurse_dst, this, Status()}; FileSystem::Instance().EnumerateDirectory( @@ -737,7 +739,7 @@ ConstString Platform::GetFullNameForDylib(ConstString basename) { bool Platform::SetRemoteWorkingDirectory(const FileSpec &working_dir) { Log *log = GetLog(LLDBLog::Platform); LLDB_LOGF(log, "Platform::SetRemoteWorkingDirectory('%s')", - working_dir.GetCString()); + working_dir.GetPath().c_str()); m_working_dir = working_dir; return true; } @@ -928,7 +930,8 @@ ArchSpec Platform::GetAugmentedArchSpec(llvm::StringRef triple) { ArchSpec compatible_arch; ArchSpec raw_arch(triple); - if (!IsCompatibleArchitecture(raw_arch, {}, false, &compatible_arch)) + if (!IsCompatibleArchitecture(raw_arch, {}, ArchSpec::CompatibleMatch, + &compatible_arch)) return raw_arch; if (!compatible_arch.IsValid()) @@ -1155,16 +1158,14 @@ Platform::CreateArchList(llvm::ArrayRef<llvm::Triple::ArchType> archs, /// architecture and the target triple contained within. bool Platform::IsCompatibleArchitecture(const ArchSpec &arch, const ArchSpec &process_host_arch, - bool exact_arch_match, + ArchSpec::MatchType match, ArchSpec *compatible_arch_ptr) { // If the architecture is invalid, we must answer true... if (arch.IsValid()) { ArchSpec platform_arch; - auto match = exact_arch_match ? &ArchSpec::IsExactMatch - : &ArchSpec::IsCompatibleMatch; for (const ArchSpec &platform_arch : GetSupportedArchitectures(process_host_arch)) { - if ((arch.*match)(platform_arch)) { + if (arch.IsMatch(platform_arch, match)) { if (compatible_arch_ptr) *compatible_arch_ptr = platform_arch; return true; @@ -1357,7 +1358,7 @@ static constexpr OptionDefinition g_caching_option_table[] = { }; llvm::ArrayRef<OptionDefinition> OptionGroupPlatformRSync::GetDefinitions() { - return llvm::makeArrayRef(g_rsync_option_table); + return llvm::ArrayRef(g_rsync_option_table); } void OptionGroupPlatformRSync::OptionParsingStarting( @@ -1405,7 +1406,7 @@ Platform::SetThreadCreationBreakpoint(lldb_private::Target &target) { } llvm::ArrayRef<OptionDefinition> OptionGroupPlatformSSH::GetDefinitions() { - return llvm::makeArrayRef(g_ssh_option_table); + return llvm::ArrayRef(g_ssh_option_table); } void OptionGroupPlatformSSH::OptionParsingStarting( @@ -1438,7 +1439,7 @@ OptionGroupPlatformSSH::SetOptionValue(uint32_t option_idx, } llvm::ArrayRef<OptionDefinition> OptionGroupPlatformCaching::GetDefinitions() { - return llvm::makeArrayRef(g_caching_option_table); + return llvm::ArrayRef(g_caching_option_table); } void OptionGroupPlatformCaching::OptionParsingStarting( @@ -1772,25 +1773,21 @@ lldb::ProcessSP Platform::DoConnectProcess(llvm::StringRef connect_url, error.Clear(); if (!target) { - ArchSpec arch; - if (target && target->GetArchitecture().IsValid()) - arch = target->GetArchitecture(); - else - arch = Target::GetDefaultArchitecture(); + ArchSpec arch = Target::GetDefaultArchitecture(); - const char *triple = ""; - if (arch.IsValid()) - triple = arch.GetTriple().getTriple().c_str(); + const char *triple = + arch.IsValid() ? arch.GetTriple().getTriple().c_str() : ""; TargetSP new_target_sp; error = debugger.GetTargetList().CreateTarget( debugger, "", triple, eLoadDependentsNo, nullptr, new_target_sp); + target = new_target_sp.get(); + if (!target || error.Fail()) { + return nullptr; + } } - if (!target || error.Fail()) - return nullptr; - lldb::ProcessSP process_sp = target->CreateProcess(debugger.GetListener(), plugin_name, nullptr, true); @@ -1814,7 +1811,7 @@ lldb::ProcessSP Platform::DoConnectProcess(llvm::StringRef connect_url, if (synchronous) { EventSP event_sp; - process_sp->WaitForProcessToStop(llvm::None, &event_sp, true, listener_sp, + process_sp->WaitForProcessToStop(std::nullopt, &event_sp, true, listener_sp, nullptr); process_sp->RestoreProcessEvents(); bool pop_process_io_handler = false; @@ -1930,6 +1927,27 @@ size_t Platform::GetSoftwareBreakpointTrapOpcode(Target &target, trap_opcode_size = sizeof(g_i386_opcode); } break; + case llvm::Triple::riscv32: + case llvm::Triple::riscv64: { + static const uint8_t g_riscv_opcode[] = {0x73, 0x00, 0x10, 0x00}; // ebreak + static const uint8_t g_riscv_opcode_c[] = {0x02, 0x90}; // c.ebreak + if (arch.GetFlags() & ArchSpec::eRISCV_rvc) { + trap_opcode = g_riscv_opcode_c; + trap_opcode_size = sizeof(g_riscv_opcode_c); + } else { + trap_opcode = g_riscv_opcode; + trap_opcode_size = sizeof(g_riscv_opcode); + } + } break; + + case llvm::Triple::loongarch32: + case llvm::Triple::loongarch64: { + static const uint8_t g_loongarch_opcode[] = {0x05, 0x00, 0x2a, + 0x00}; // break 0x5 + trap_opcode = g_loongarch_opcode; + trap_opcode_size = sizeof(g_loongarch_opcode); + } break; + default: return 0; } @@ -1965,14 +1983,15 @@ PlatformSP PlatformList::GetOrCreate(const ArchSpec &arch, std::lock_guard<std::recursive_mutex> guard(m_mutex); // First try exact arch matches across all platforms already created for (const auto &platform_sp : m_platforms) { - if (platform_sp->IsCompatibleArchitecture(arch, process_host_arch, true, - platform_arch_ptr)) + if (platform_sp->IsCompatibleArchitecture( + arch, process_host_arch, ArchSpec::ExactMatch, platform_arch_ptr)) return platform_sp; } // Next try compatible arch matches across all platforms already created for (const auto &platform_sp : m_platforms) { - if (platform_sp->IsCompatibleArchitecture(arch, process_host_arch, false, + if (platform_sp->IsCompatibleArchitecture(arch, process_host_arch, + ArchSpec::CompatibleMatch, platform_arch_ptr)) return platform_sp; } @@ -1984,8 +2003,9 @@ PlatformSP PlatformList::GetOrCreate(const ArchSpec &arch, (create_callback = PluginManager::GetPlatformCreateCallbackAtIndex(idx)); ++idx) { PlatformSP platform_sp = create_callback(false, &arch); - if (platform_sp && platform_sp->IsCompatibleArchitecture( - arch, process_host_arch, true, platform_arch_ptr)) { + if (platform_sp && + platform_sp->IsCompatibleArchitecture( + arch, process_host_arch, ArchSpec::ExactMatch, platform_arch_ptr)) { m_platforms.push_back(platform_sp); return platform_sp; } @@ -1996,7 +2016,8 @@ PlatformSP PlatformList::GetOrCreate(const ArchSpec &arch, ++idx) { PlatformSP platform_sp = create_callback(false, &arch); if (platform_sp && platform_sp->IsCompatibleArchitecture( - arch, process_host_arch, false, platform_arch_ptr)) { + arch, process_host_arch, ArchSpec::CompatibleMatch, + platform_arch_ptr)) { m_platforms.push_back(platform_sp); return platform_sp; } @@ -2030,7 +2051,7 @@ PlatformSP PlatformList::GetOrCreate(llvm::ArrayRef<ArchSpec> archs, if (m_selected_platform_sp) { for (const ArchSpec &arch : archs) { if (m_selected_platform_sp->IsCompatibleArchitecture( - arch, process_host_arch, false, nullptr)) + arch, process_host_arch, ArchSpec::CompatibleMatch, nullptr)) return m_selected_platform_sp; } } @@ -2038,8 +2059,8 @@ PlatformSP PlatformList::GetOrCreate(llvm::ArrayRef<ArchSpec> archs, // Prefer the host platform if it matches at least one architecture. if (host_platform_sp) { for (const ArchSpec &arch : archs) { - if (host_platform_sp->IsCompatibleArchitecture(arch, process_host_arch, - false, nullptr)) + if (host_platform_sp->IsCompatibleArchitecture( + arch, process_host_arch, ArchSpec::CompatibleMatch, nullptr)) return host_platform_sp; } } @@ -2054,10 +2075,9 @@ PlatformSP PlatformList::GetOrCreate(llvm::ArrayRef<ArchSpec> archs, // the same platform supports all architectures then that's the obvious next // best thing. if (candidates.size() == archs.size()) { - if (std::all_of(candidates.begin(), candidates.end(), - [&](const PlatformSP &p) -> bool { - return p->GetName() == candidates.front()->GetName(); - })) { + if (llvm::all_of(candidates, [&](const PlatformSP &p) -> bool { + return p->GetName() == candidates.front()->GetName(); + })) { return candidates.front(); } } @@ -2074,3 +2094,21 @@ PlatformSP PlatformList::Create(llvm::StringRef name) { m_platforms.push_back(platform_sp); return platform_sp; } + +bool PlatformList::LoadPlatformBinaryAndSetup(Process *process, + lldb::addr_t addr, bool notify) { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + + PlatformCreateInstance create_callback; + for (int idx = 0; + (create_callback = PluginManager::GetPlatformCreateCallbackAtIndex(idx)); + ++idx) { + ArchSpec arch; + PlatformSP platform_sp = create_callback(true, &arch); + if (platform_sp) { + if (platform_sp->LoadPlatformBinaryAndSetup(process, addr, notify)) + return true; + } + } + return false; +} diff --git a/contrib/llvm-project/lldb/source/Target/Process.cpp b/contrib/llvm-project/lldb/source/Target/Process.cpp index b2f1318ca91d..e0cca0595ee3 100644 --- a/contrib/llvm-project/lldb/source/Target/Process.cpp +++ b/contrib/llvm-project/lldb/source/Target/Process.cpp @@ -9,6 +9,7 @@ #include <atomic> #include <memory> #include <mutex> +#include <optional> #include "llvm/ADT/ScopeExit.h" #include "llvm/Support/ScopedPrinter.h" @@ -542,7 +543,7 @@ void Process::Finalize() { m_notifications.swap(empty_notifications); m_image_tokens.clear(); m_memory_cache.Clear(); - m_allocated_memory_cache.Clear(); + m_allocated_memory_cache.Clear(/*deallocate_memory=*/true); { std::lock_guard<std::recursive_mutex> guard(m_language_runtimes_mutex); m_language_runtimes.clear(); @@ -1293,7 +1294,10 @@ uint32_t Process::AssignIndexIDToThread(uint64_t thread_id) { } StateType Process::GetState() { - return m_public_state.GetValue(); + if (CurrentThreadIsPrivateStateThread()) + return m_private_state.GetValue(); + else + return m_public_state.GetValue(); } void Process::SetPublicState(StateType new_state, bool restarted) { @@ -1369,8 +1373,8 @@ Status Process::ResumeSynchronous(Stream *stream) { Status error = PrivateResume(); if (error.Success()) { - StateType state = WaitForProcessToStop(llvm::None, nullptr, true, - listener_sp, stream); + StateType state = + WaitForProcessToStop(std::nullopt, nullptr, true, listener_sp, stream); const bool must_be_alive = false; // eStateExited is ok, so this must be false if (!StateIsStoppedState(state, must_be_alive)) @@ -2633,7 +2637,7 @@ Status Process::LoadCore() { // Wait for a stopped event since we just posted one above... lldb::EventSP event_sp; StateType state = - WaitForProcessToStop(llvm::None, &event_sp, true, listener_sp); + WaitForProcessToStop(std::nullopt, &event_sp, true, listener_sp); if (!StateIsStoppedState(state, false)) { Log *log = GetLog(LLDBLog::Process); @@ -2653,6 +2657,10 @@ DynamicLoader *Process::GetDynamicLoader() { return m_dyld_up.get(); } +void Process::SetDynamicLoader(DynamicLoaderUP dyld_up) { + m_dyld_up = std::move(dyld_up); +} + DataExtractor Process::GetAuxvData() { return DataExtractor(); } llvm::Expected<bool> Process::SaveCore(llvm::StringRef outfile) { @@ -2756,6 +2764,19 @@ ListenerSP ProcessAttachInfo::GetListenerForProcess(Debugger &debugger) { return debugger.GetListener(); } +Status Process::WillLaunch(Module *module) { + return DoWillLaunch(module); +} + +Status Process::WillAttachToProcessWithID(lldb::pid_t pid) { + return DoWillAttachToProcessWithID(pid); +} + +Status Process::WillAttachToProcessWithName(const char *process_name, + bool wait_for_launch) { + return DoWillAttachToProcessWithName(process_name, wait_for_launch); +} + Status Process::Attach(ProcessAttachInfo &attach_info) { m_abi_sp.reset(); m_process_input_reader.reset(); @@ -2905,9 +2926,9 @@ void Process::CompleteAttach() { ArchSpec process_host_arch = GetSystemArchitecture(); if (platform_sp) { const ArchSpec &target_arch = GetTarget().GetArchitecture(); - if (target_arch.IsValid() && - !platform_sp->IsCompatibleArchitecture(target_arch, process_host_arch, - false, nullptr)) { + if (target_arch.IsValid() && !platform_sp->IsCompatibleArchitecture( + target_arch, process_host_arch, + ArchSpec::CompatibleMatch, nullptr)) { ArchSpec platform_arch; platform_sp = GetTarget().GetDebugger().GetPlatformList().GetOrCreate( target_arch, process_host_arch, &platform_arch); @@ -3018,7 +3039,7 @@ Status Process::ConnectRemote(llvm::StringRef remote_url) { if (error.Success()) { if (GetID() != LLDB_INVALID_PROCESS_ID) { EventSP event_sp; - StateType state = WaitForProcessStopPrivate(event_sp, llvm::None); + StateType state = WaitForProcessStopPrivate(event_sp, std::nullopt); if (state == eStateStopped || state == eStateCrashed) { // If we attached and actually have a process on the other end, then @@ -3362,7 +3383,7 @@ bool Process::ShouldBroadcastEvent(Event *event_ptr) { m_stdio_communication.Disconnect(); m_stdin_forward = false; - LLVM_FALLTHROUGH; + [[fallthrough]]; case eStateConnected: case eStateAttaching: case eStateLaunching: @@ -3765,7 +3786,7 @@ thread_result_t Process::RunPrivateStateThread(bool is_secondary_thread) { bool interrupt_requested = false; while (!exit_now) { EventSP event_sp; - GetEventsPrivate(event_sp, llvm::None, control_only); + GetEventsPrivate(event_sp, std::nullopt, control_only); if (event_sp->BroadcasterIs(&m_private_state_control_broadcaster)) { LLDB_LOGF(log, "Process::%s (arg = %p, pid = %" PRIu64 @@ -4589,12 +4610,12 @@ GetExpressionTimeout(const EvaluateExpressionOptions &options, return GetOneThreadExpressionTimeout(options); if (!options.GetTimeout()) - return llvm::None; + return std::nullopt; else return *options.GetTimeout() - GetOneThreadExpressionTimeout(options); } -static llvm::Optional<ExpressionResults> +static std::optional<ExpressionResults> HandleStoppedEvent(lldb::tid_t thread_id, const ThreadPlanSP &thread_plan_sp, RestorePlanState &restorer, const EventSP &event_sp, EventSP &event_to_broadcast_sp, @@ -4643,7 +4664,7 @@ HandleStoppedEvent(lldb::tid_t thread_id, const ThreadPlanSP &thread_plan_sp, if (!handle_interrupts && Process::ProcessEventData::GetInterruptedFromEvent(event_sp.get())) - return llvm::None; + return std::nullopt; LLDB_LOG(log, "thread plan did not successfully complete"); if (!options.DoesUnwindOnError()) @@ -5636,7 +5657,9 @@ void Process::DidExec() { m_dyld_up.reset(); m_jit_loaders_up.reset(); m_image_tokens.clear(); - m_allocated_memory_cache.Clear(); + // After an exec, the inferior is a new process and these memory regions are + // no longer allocated. + m_allocated_memory_cache.Clear(/*deallocte_memory=*/false); { std::lock_guard<std::recursive_mutex> guard(m_language_runtimes_mutex); m_language_runtimes.clear(); @@ -6052,8 +6075,11 @@ bool Process::CallVoidArgVoidPtrReturn(const Address *address, llvm::consumeError(type_system_or_err.takeError()); return false; } + auto ts = *type_system_or_err; + if (!ts) + return false; CompilerType void_ptr_type = - type_system_or_err->GetBasicTypeFromAST(eBasicTypeVoid).GetPointerType(); + ts->GetBasicTypeFromAST(eBasicTypeVoid).GetPointerType(); lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallFunction( *thread, *address, void_ptr_type, llvm::ArrayRef<addr_t>(), options)); if (call_plan_sp) { diff --git a/contrib/llvm-project/lldb/source/Target/ProcessTrace.cpp b/contrib/llvm-project/lldb/source/Target/ProcessTrace.cpp index 6b147cb285a7..061af9e0e520 100644 --- a/contrib/llvm-project/lldb/source/Target/ProcessTrace.cpp +++ b/contrib/llvm-project/lldb/source/Target/ProcessTrace.cpp @@ -63,7 +63,7 @@ void ProcessTrace::DidAttach(ArchSpec &process_arch) { SetPrivateState(eStateStopped); EventSP event_sp; - WaitForProcessToStop(llvm::None, &event_sp, true, listener_sp); + WaitForProcessToStop(std::nullopt, &event_sp, true, listener_sp); RestoreProcessEvents(); diff --git a/contrib/llvm-project/lldb/source/Target/RegisterContext.cpp b/contrib/llvm-project/lldb/source/Target/RegisterContext.cpp index 7364660650e8..ee344b01c6b8 100644 --- a/contrib/llvm-project/lldb/source/Target/RegisterContext.cpp +++ b/contrib/llvm-project/lldb/source/Target/RegisterContext.cpp @@ -357,7 +357,7 @@ Status RegisterContext::ReadRegisterValueFromMemory( // TODO: we might need to add a parameter to this function in case the byte // order of the memory data doesn't match the process. For now we are // assuming they are the same. - reg_value.SetFromMemoryData(reg_info, src, src_len, + reg_value.SetFromMemoryData(*reg_info, src, src_len, process_sp->GetByteOrder(), error); } else error.SetErrorString("invalid process"); @@ -368,37 +368,41 @@ Status RegisterContext::ReadRegisterValueFromMemory( Status RegisterContext::WriteRegisterValueToMemory( const RegisterInfo *reg_info, lldb::addr_t dst_addr, uint32_t dst_len, const RegisterValue ®_value) { - uint8_t dst[RegisterValue::kMaxRegisterByteSize]; - Status error; - ProcessSP process_sp(m_thread.GetProcess()); - if (process_sp) { - // TODO: we might need to add a parameter to this function in case the byte - // order of the memory data doesn't match the process. For now we are - // assuming they are the same. + if (!process_sp) { + error.SetErrorString("invalid process"); + return error; + } + + if (reg_info == nullptr) { + error.SetErrorString("Invalid register info argument."); + return error; + } - const uint32_t bytes_copied = reg_value.GetAsMemoryData( - reg_info, dst, dst_len, process_sp->GetByteOrder(), error); - - if (error.Success()) { - if (bytes_copied == 0) { - error.SetErrorString("byte copy failed."); - } else { - const uint32_t bytes_written = - process_sp->WriteMemory(dst_addr, dst, bytes_copied, error); - if (bytes_written != bytes_copied) { - if (error.Success()) { - // This might happen if we read _some_ bytes but not all - error.SetErrorStringWithFormat("only wrote %u of %u bytes", - bytes_written, bytes_copied); - } + // TODO: we might need to add a parameter to this function in case the byte + // order of the memory data doesn't match the process. For now we are + // assuming they are the same. + uint8_t dst[RegisterValue::kMaxRegisterByteSize]; + const uint32_t bytes_copied = reg_value.GetAsMemoryData( + *reg_info, dst, dst_len, process_sp->GetByteOrder(), error); + + if (error.Success()) { + if (bytes_copied == 0) { + error.SetErrorString("byte copy failed."); + } else { + const uint32_t bytes_written = + process_sp->WriteMemory(dst_addr, dst, bytes_copied, error); + if (bytes_written != bytes_copied) { + if (error.Success()) { + // This might happen if we read _some_ bytes but not all + error.SetErrorStringWithFormat("only wrote %u of %u bytes", + bytes_written, bytes_copied); } } } - } else - error.SetErrorString("invalid process"); + } return error; } diff --git a/contrib/llvm-project/lldb/source/Target/RemoteAwarePlatform.cpp b/contrib/llvm-project/lldb/source/Target/RemoteAwarePlatform.cpp index c7b0ade845cf..0bd6c9251c85 100644 --- a/contrib/llvm-project/lldb/source/Target/RemoteAwarePlatform.cpp +++ b/contrib/llvm-project/lldb/source/Target/RemoteAwarePlatform.cpp @@ -14,6 +14,7 @@ #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.h" #include "lldb/Utility/StreamString.h" +#include <optional> using namespace lldb_private; using namespace lldb; @@ -305,16 +306,16 @@ bool RemoteAwarePlatform::GetRemoteOSVersion() { return false; } -llvm::Optional<std::string> RemoteAwarePlatform::GetRemoteOSBuildString() { +std::optional<std::string> RemoteAwarePlatform::GetRemoteOSBuildString() { if (m_remote_platform_sp) return m_remote_platform_sp->GetRemoteOSBuildString(); - return llvm::None; + return std::nullopt; } -llvm::Optional<std::string> RemoteAwarePlatform::GetRemoteOSKernelDescription() { +std::optional<std::string> RemoteAwarePlatform::GetRemoteOSKernelDescription() { if (m_remote_platform_sp) return m_remote_platform_sp->GetRemoteOSKernelDescription(); - return llvm::None; + return std::nullopt; } ArchSpec RemoteAwarePlatform::GetRemoteSystemArchitecture() { diff --git a/contrib/llvm-project/lldb/source/Target/SectionLoadList.cpp b/contrib/llvm-project/lldb/source/Target/SectionLoadList.cpp index 03160ee10dd8..d4bf0573b229 100644 --- a/contrib/llvm-project/lldb/source/Target/SectionLoadList.cpp +++ b/contrib/llvm-project/lldb/source/Target/SectionLoadList.cpp @@ -106,8 +106,8 @@ bool SectionLoadList::SetSectionLoadAddress(const lldb::SectionSP §ion, ModuleSP curr_module_sp(ats_pos->second->GetModule()); if (curr_module_sp) { module_sp->ReportWarning( - "address 0x%16.16" PRIx64 - " maps to more than one section: %s.%s and %s.%s", + "address {0:x16} maps to more than one section: {1}.{2} and " + "{3}.{4}", load_addr, module_sp->GetFileSpec().GetFilename().GetCString(), section->GetName().GetCString(), curr_module_sp->GetFileSpec().GetFilename().GetCString(), @@ -116,8 +116,18 @@ bool SectionLoadList::SetSectionLoadAddress(const lldb::SectionSP §ion, } } ats_pos->second = section; - } else + } else { + // Remove the old address->section entry, if + // there is one. + for (const auto &entry : m_addr_to_sect) { + if (entry.second == section) { + const auto &it_pos = m_addr_to_sect.find(entry.first); + m_addr_to_sect.erase(it_pos); + break; + } + } m_addr_to_sect[load_addr] = section; + } return true; // Changed } else { diff --git a/contrib/llvm-project/lldb/source/Target/StackFrame.cpp b/contrib/llvm-project/lldb/source/Target/StackFrame.cpp index 4fb5ba0b735e..c04b58e80523 100644 --- a/contrib/llvm-project/lldb/source/Target/StackFrame.cpp +++ b/contrib/llvm-project/lldb/source/Target/StackFrame.cpp @@ -20,6 +20,7 @@ #include "lldb/Symbol/Function.h" #include "lldb/Symbol/Symbol.h" #include "lldb/Symbol/SymbolContextScope.h" +#include "lldb/Symbol/SymbolFile.h" #include "lldb/Symbol/Type.h" #include "lldb/Symbol/VariableList.h" #include "lldb/Target/ABI.h" @@ -43,7 +44,7 @@ using namespace lldb_private; // The first bits in the flags are reserved for the SymbolContext::Scope bits // so we know if we have tried to look up information in our internal symbol // context (m_sc) already. -#define RESOLVED_FRAME_CODE_ADDR (uint32_t(eSymbolContextEverything + 1)) +#define RESOLVED_FRAME_CODE_ADDR (uint32_t(eSymbolContextLastItem) << 1) #define RESOLVED_FRAME_ID_SYMBOL_SCOPE (RESOLVED_FRAME_CODE_ADDR << 1) #define GOT_FRAME_BASE (RESOLVED_FRAME_ID_SYMBOL_SCOPE << 1) #define RESOLVED_VARIABLES (GOT_FRAME_BASE << 1) @@ -420,10 +421,12 @@ StackFrame::GetSymbolContext(SymbolContextItem resolve_scope) { return m_sc; } -VariableList *StackFrame::GetVariableList(bool get_file_globals) { +VariableList *StackFrame::GetVariableList(bool get_file_globals, + Status *error_ptr) { std::lock_guard<std::recursive_mutex> guard(m_mutex); if (m_flags.IsClear(RESOLVED_VARIABLES)) { m_flags.Set(RESOLVED_VARIABLES); + m_variable_list_sp = std::make_shared<VariableList>(); Block *frame_block = GetFrameBlock(); @@ -431,7 +434,6 @@ VariableList *StackFrame::GetVariableList(bool get_file_globals) { const bool get_child_variables = true; const bool can_create = true; const bool stop_if_child_block_is_inlined_function = true; - m_variable_list_sp = std::make_shared<VariableList>(); frame_block->AppendBlockVariables(can_create, get_child_variables, stop_if_child_block_is_inlined_function, [](Variable *v) { return true; }, @@ -455,6 +457,17 @@ VariableList *StackFrame::GetVariableList(bool get_file_globals) { } } + if (error_ptr && m_variable_list_sp->GetSize() == 0) { + // Check with the symbol file to check if there is an error for why we + // don't have variables that the user might need to know about. + GetSymbolContext(eSymbolContextEverything); + if (m_sc.module_sp) { + SymbolFile *sym_file = m_sc.module_sp->GetSymbolFile(); + if (sym_file) + *error_ptr = sym_file->GetFrameVariableError(*this); + } + } + return m_variable_list_sp.get(); } @@ -666,7 +679,7 @@ ValueObjectSP StackFrame::GetValueForVariableExpressionPath( } var_expr = var_expr.drop_front(); // Remove the '-' - LLVM_FALLTHROUGH; + [[fallthrough]]; case '.': { var_expr = var_expr.drop_front(); // Remove the '.' or '>' separator_idx = var_expr.find_first_of(".-["); @@ -1147,16 +1160,16 @@ StackFrame::GetValueObjectForFrameVariable(const VariableSP &variable_sp, DynamicValueType use_dynamic) { ValueObjectSP valobj_sp; { // Scope for stack frame mutex. We need to drop this mutex before we figure - // out the dynamic value. That will require converting the StackID in the - // VO back to a StackFrame, which will in turn require locking the - // StackFrameList. If we still hold the StackFrame mutex, we could suffer - // lock inversion against the pattern of getting the StackFrameList and + // out the dynamic value. That will require converting the StackID in the + // VO back to a StackFrame, which will in turn require locking the + // StackFrameList. If we still hold the StackFrame mutex, we could suffer + // lock inversion against the pattern of getting the StackFrameList and // then the stack frame, which is fairly common. std::lock_guard<std::recursive_mutex> guard(m_mutex); if (IsHistorical()) { return valobj_sp; } - VariableList *var_list = GetVariableList(true); + VariableList *var_list = GetVariableList(true, nullptr); if (var_list) { // Make sure the variable is a frame variable const uint32_t var_idx = var_list->FindIndexForVariable(variable_sp.get()); @@ -1355,9 +1368,11 @@ lldb::ValueObjectSP StackFrame::GuessValueForAddress(lldb::addr_t addr) { "Unable to guess value for given address"); return ValueObjectSP(); } else { + auto ts = *c_type_system_or_err; + if (!ts) + return {}; CompilerType void_ptr_type = - c_type_system_or_err - ->GetBasicTypeFromAST(lldb::BasicType::eBasicTypeChar) + ts->GetBasicTypeFromAST(lldb::BasicType::eBasicTypeChar) .GetPointerType(); return ValueObjectMemory::Create(this, "", addr, void_ptr_type); } @@ -1698,7 +1713,7 @@ lldb::ValueObjectSP StackFrame::GuessValueForRegisterAndOffset(ConstString reg, } const bool get_file_globals = false; - VariableList *variables = GetVariableList(get_file_globals); + VariableList *variables = GetVariableList(get_file_globals, nullptr); if (!variables) { return ValueObjectSP(); @@ -1932,12 +1947,12 @@ bool StackFrame::GetStatus(Stream &strm, bool show_frame_info, bool show_source, case Debugger::eStopDisassemblyTypeNoDebugInfo: if (have_debuginfo) break; - LLVM_FALLTHROUGH; + [[fallthrough]]; case Debugger::eStopDisassemblyTypeNoSource: if (have_source) break; - LLVM_FALLTHROUGH; + [[fallthrough]]; case Debugger::eStopDisassemblyTypeAlways: if (target) { diff --git a/contrib/llvm-project/lldb/source/Target/StackFrameList.cpp b/contrib/llvm-project/lldb/source/Target/StackFrameList.cpp index 14663e4b7c7b..c782b506a9cb 100644 --- a/contrib/llvm-project/lldb/source/Target/StackFrameList.cpp +++ b/contrib/llvm-project/lldb/source/Target/StackFrameList.cpp @@ -168,7 +168,7 @@ void StackFrameList::ResetCurrentInlinedDepth() { break; } } - LLVM_FALLTHROUGH; + [[fallthrough]]; default: { // Otherwise, we should set ourselves at the container of the inlining, so // that the user can descend into them. So first we check whether we have diff --git a/contrib/llvm-project/lldb/source/Target/StackFrameRecognizer.cpp b/contrib/llvm-project/lldb/source/Target/StackFrameRecognizer.cpp index 73d22d5bb4e6..0ccb1ae9c031 100644 --- a/contrib/llvm-project/lldb/source/Target/StackFrameRecognizer.cpp +++ b/contrib/llvm-project/lldb/source/Target/StackFrameRecognizer.cpp @@ -77,7 +77,7 @@ void StackFrameRecognizerManager::ForEach( symbol_name = entry.symbol_regexp->GetText().str(); callback(entry.recognizer_id, entry.recognizer->GetName(), module_name, - llvm::makeArrayRef(ConstString(symbol_name)), true); + llvm::ArrayRef(ConstString(symbol_name)), true); } else { callback(entry.recognizer_id, entry.recognizer->GetName(), diff --git a/contrib/llvm-project/lldb/source/Target/Statistics.cpp b/contrib/llvm-project/lldb/source/Target/Statistics.cpp index b8ad25e71f06..c739ac7058ca 100644 --- a/contrib/llvm-project/lldb/source/Target/Statistics.cpp +++ b/contrib/llvm-project/lldb/source/Target/Statistics.cpp @@ -63,6 +63,10 @@ json::Value ModuleStats::ToJSON() const { module.try_emplace("debugInfoIndexSavedToCache", debug_info_index_saved_to_cache); module.try_emplace("debugInfoEnabled", debug_info_enabled); + module.try_emplace("debugInfoHadVariableErrors", + debug_info_had_variable_errors); + module.try_emplace("debugInfoHadIncompleteTypes", + debug_info_had_incomplete_types); module.try_emplace("symbolTableStripped", symtab_stripped); if (!symfile_path.empty()) module.try_emplace("symbolFilePath", symfile_path); @@ -73,6 +77,17 @@ json::Value ModuleStats::ToJSON() const { symfile_ids.emplace_back(symfile_id); module.try_emplace("symbolFileModuleIdentifiers", std::move(symfile_ids)); } + + if (!type_system_stats.empty()) { + json::Array type_systems; + for (const auto &entry : type_system_stats) { + json::Object obj; + obj.try_emplace(entry.first().str(), entry.second); + type_systems.emplace_back(std::move(obj)); + } + module.try_emplace("typeSystemInfo", std::move(type_systems)); + } + return module; } @@ -136,13 +151,14 @@ json::Value TargetStats::ToJSON(Target &target) { target_metrics_json.try_emplace("breakpoints", std::move(breakpoints_array)); target_metrics_json.try_emplace("totalBreakpointResolveTime", totalBreakpointResolveTime); + target_metrics_json.try_emplace("sourceMapDeduceCount", m_source_map_deduce_count); return target_metrics_json; } void TargetStats::SetLaunchOrAttachTime() { m_launch_or_attach_time = StatsClock::now(); - m_first_private_stop_time = llvm::None; + m_first_private_stop_time = std::nullopt; } void TargetStats::SetFirstPrivateStopTime() { @@ -161,6 +177,10 @@ void TargetStats::SetFirstPublicStopTime() { m_first_public_stop_time = StatsClock::now(); } +void TargetStats::IncreaseSourceMapDeduceCount() { + ++m_source_map_deduce_count; +} + bool DebuggerStats::g_collecting_stats = false; llvm::json::Value DebuggerStats::ReportStatistics(Debugger &debugger, @@ -188,6 +208,8 @@ llvm::json::Value DebuggerStats::ReportStatistics(Debugger &debugger, const uint64_t num_modules = Module::GetNumberAllocatedModules(); uint32_t num_debug_info_enabled_modules = 0; uint32_t num_modules_has_debug_info = 0; + uint32_t num_modules_with_variable_errors = 0; + uint32_t num_modules_with_incomplete_types = 0; uint32_t num_stripped_modules = 0; for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) { Module *module = Module::GetAllocatedModuleAtIndex(image_idx); @@ -237,16 +259,30 @@ llvm::json::Value DebuggerStats::ReportStatistics(Debugger &debugger, ++num_stripped_modules; module_stat.debug_info_enabled = sym_file->GetLoadDebugInfoEnabled() && module_stat.debug_info_size > 0; + module_stat.debug_info_had_variable_errors = + sym_file->GetDebugInfoHadFrameVariableErrors(); if (module_stat.debug_info_enabled) ++num_debug_info_enabled_modules; if (module_stat.debug_info_size > 0) ++num_modules_has_debug_info; + if (module_stat.debug_info_had_variable_errors) + ++num_modules_with_variable_errors; } symtab_parse_time += module_stat.symtab_parse_time; symtab_index_time += module_stat.symtab_index_time; debug_parse_time += module_stat.debug_parse_time; debug_index_time += module_stat.debug_index_time; debug_info_size += module_stat.debug_info_size; + module->ForEachTypeSystem([&](lldb::TypeSystemSP ts) { + if (auto stats = ts->ReportStatistics()) + module_stat.type_system_stats.insert({ts->GetPluginName(), *stats}); + if (ts->GetHasForcefullyCompletedTypes()) + module_stat.debug_info_had_incomplete_types = true; + return true; + }); + if (module_stat.debug_info_had_incomplete_types) + ++num_modules_with_incomplete_types; + json_modules.emplace_back(module_stat.ToJSON()); } @@ -270,6 +306,8 @@ llvm::json::Value DebuggerStats::ReportStatistics(Debugger &debugger, {"totalDebugInfoByteSize", debug_info_size}, {"totalModuleCount", num_modules}, {"totalModuleCountHasDebugInfo", num_modules_has_debug_info}, + {"totalModuleCountWithVariableErrors", num_modules_with_variable_errors}, + {"totalModuleCountWithIncompleteTypes", num_modules_with_incomplete_types}, {"totalDebugInfoEnabled", num_debug_info_enabled_modules}, {"totalSymbolTableStripped", num_stripped_modules}, }; diff --git a/contrib/llvm-project/lldb/source/Target/StopInfo.cpp b/contrib/llvm-project/lldb/source/Target/StopInfo.cpp index 00d30070c8c9..225234c0ffba 100644 --- a/contrib/llvm-project/lldb/source/Target/StopInfo.cpp +++ b/contrib/llvm-project/lldb/source/Target/StopInfo.cpp @@ -20,6 +20,7 @@ #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" #include "lldb/Target/ThreadPlan.h" +#include "lldb/Target/ThreadPlanStepInstruction.h" #include "lldb/Target/UnixSignals.h" #include "lldb/Utility/LLDBLog.h" #include "lldb/Utility/Log.h" @@ -361,29 +362,21 @@ protected: " not running commands to avoid recursion."); bool ignoring_breakpoints = process->GetIgnoreBreakpointsInExpressions(); - if (ignoring_breakpoints) { - m_should_stop = false; - // Internal breakpoints will always stop. - for (size_t j = 0; j < num_owners; j++) { - lldb::BreakpointLocationSP bp_loc_sp = - bp_site_sp->GetOwnerAtIndex(j); - if (bp_loc_sp->GetBreakpoint().IsInternal()) { - m_should_stop = true; - break; - } - } - } else { - m_should_stop = true; + // Internal breakpoints should be allowed to do their job, we + // can make sure they don't do anything that would cause recursive + // command execution: + if (!m_was_all_internal) { + m_should_stop = !ignoring_breakpoints; + LLDB_LOGF(log, + "StopInfoBreakpoint::PerformAction - in expression, " + "continuing: %s.", + m_should_stop ? "true" : "false"); + Debugger::ReportWarning( + "hit breakpoint while running function, skipping commands " + "and conditions to prevent recursion", + process->GetTarget().GetDebugger().GetID()); + return; } - LLDB_LOGF(log, - "StopInfoBreakpoint::PerformAction - in expression, " - "continuing: %s.", - m_should_stop ? "true" : "false"); - Debugger::ReportWarning( - "hit breakpoint while running function, skipping commands and " - "conditions to prevent recursion", - process->GetTarget().GetDebugger().GetID()); - return; } StoppointCallbackContext context(event_ptr, exe_ctx, false); @@ -690,39 +683,184 @@ public: } protected: + using StopInfoWatchpointSP = std::shared_ptr<StopInfoWatchpoint>; + // This plan is used to orchestrate stepping over the watchpoint for + // architectures (e.g. ARM) that report the watch before running the watched + // access. This is the sort of job you have to defer to the thread plans, + // if you try to do it directly in the stop info and there are other threads + // that needed to process this stop you will have yanked control away from + // them and they won't behave correctly. + class ThreadPlanStepOverWatchpoint : public ThreadPlanStepInstruction { + public: + ThreadPlanStepOverWatchpoint(Thread &thread, + StopInfoWatchpointSP stop_info_sp, + WatchpointSP watch_sp) + : ThreadPlanStepInstruction(thread, false, true, eVoteNoOpinion, + eVoteNoOpinion), + m_stop_info_sp(stop_info_sp), m_watch_sp(watch_sp) { + assert(watch_sp); + m_watch_index = watch_sp->GetHardwareIndex(); + } + + bool DoWillResume(lldb::StateType resume_state, + bool current_plan) override { + if (resume_state == eStateSuspended) + return true; + + if (!m_did_disable_wp) { + GetThread().GetProcess()->DisableWatchpoint(m_watch_sp.get(), false); + m_did_disable_wp = true; + } + return true; + } + + bool DoPlanExplainsStop(Event *event_ptr) override { + if (ThreadPlanStepInstruction::DoPlanExplainsStop(event_ptr)) + return true; + StopInfoSP stop_info_sp = GetThread().GetPrivateStopInfo(); + // lldb-server resets the stop info for threads that didn't get to run, + // so we might have not gotten to run, but still have a watchpoint stop + // reason, in which case this will indeed be for us. + if (stop_info_sp + && stop_info_sp->GetStopReason() == eStopReasonWatchpoint) + return true; + return false; + } + + void DidPop() override { + // Don't artifically keep the watchpoint alive. + m_watch_sp.reset(); + } + + bool ShouldStop(Event *event_ptr) override { + bool should_stop = ThreadPlanStepInstruction::ShouldStop(event_ptr); + bool plan_done = MischiefManaged(); + if (plan_done) { + m_stop_info_sp->SetStepOverPlanComplete(); + GetThread().SetStopInfo(m_stop_info_sp); + ResetWatchpoint(); + } + return should_stop; + } + + bool ShouldRunBeforePublicStop() override { + return true; + } + + protected: + void ResetWatchpoint() { + if (!m_did_disable_wp) + return; + m_did_disable_wp = true; + GetThread().GetProcess()->EnableWatchpoint(m_watch_sp.get(), true); + m_watch_sp->SetHardwareIndex(m_watch_index); + } + + private: + StopInfoWatchpointSP m_stop_info_sp; + WatchpointSP m_watch_sp; + uint32_t m_watch_index = LLDB_INVALID_INDEX32; + bool m_did_disable_wp = false; + }; + bool ShouldStopSynchronous(Event *event_ptr) override { - // ShouldStop() method is idempotent and should not affect hit count. See - // Process::RunPrivateStateThread()->Process()->HandlePrivateEvent() - // -->Process()::ShouldBroadcastEvent()->ThreadList::ShouldStop()-> - // Thread::ShouldStop()->ThreadPlanBase::ShouldStop()-> - // StopInfoWatchpoint::ShouldStop() and - // Event::DoOnRemoval()->Process::ProcessEventData::DoOnRemoval()-> - // StopInfoWatchpoint::PerformAction(). + // If we are running our step-over the watchpoint plan, stop if it's done + // and continue if it's not: if (m_should_stop_is_valid) return m_should_stop; + // If we are running our step over plan, then stop here and let the regular + // ShouldStop figure out what we should do: Otherwise, give our plan + // more time to get run: + if (m_using_step_over_plan) + return m_step_over_plan_complete; + + Log *log = GetLog(LLDBLog::Process); ThreadSP thread_sp(m_thread_wp.lock()); - if (thread_sp) { - WatchpointSP wp_sp( - thread_sp->CalculateTarget()->GetWatchpointList().FindByID( - GetValue())); - if (wp_sp) { - // Check if we should stop at a watchpoint. - ExecutionContext exe_ctx(thread_sp->GetStackFrameAtIndex(0)); - StoppointCallbackContext context(event_ptr, exe_ctx, true); - m_should_stop = wp_sp->ShouldStop(&context); - } else { - Log *log = GetLog(LLDBLog::Process); + assert(thread_sp); + + if (thread_sp->GetTemporaryResumeState() == eStateSuspended) { + // This is the second firing of a watchpoint so don't process it again. + LLDB_LOG(log, "We didn't run but stopped with a StopInfoWatchpoint, we " + "have already handled this one, don't do it again."); + m_should_stop = false; + m_should_stop_is_valid = true; + return m_should_stop; + } + + WatchpointSP wp_sp( + thread_sp->CalculateTarget()->GetWatchpointList().FindByID(GetValue())); + // If we can no longer find the watchpoint, we just have to stop: + if (!wp_sp) { - LLDB_LOGF(log, - "Process::%s could not find watchpoint location id: %" PRId64 - "...", - __FUNCTION__, GetValue()); + LLDB_LOGF(log, + "Process::%s could not find watchpoint location id: %" PRId64 + "...", + __FUNCTION__, GetValue()); + + m_should_stop = true; + m_should_stop_is_valid = true; + return true; + } + + ExecutionContext exe_ctx(thread_sp->GetStackFrameAtIndex(0)); + StoppointCallbackContext context(event_ptr, exe_ctx, true); + m_should_stop = wp_sp->ShouldStop(&context); + if (!m_should_stop) { + // This won't happen at present because we only allow one watchpoint per + // watched range. So we won't stop at a watched address with a disabled + // watchpoint. If we start allowing overlapping watchpoints, then we + // will have to make watchpoints be real "WatchpointSite" and delegate to + // all the watchpoints sharing the site. In that case, the code below + // would be the right thing to do. + m_should_stop_is_valid = true; + return m_should_stop; + } + // If this is a system where we need to execute the watchpoint by hand + // after the hit, queue a thread plan to do that, and then say not to stop. + // Otherwise, let the async action figure out whether the watchpoint should + // stop + + ProcessSP process_sp = exe_ctx.GetProcessSP(); + uint32_t num; + bool wp_triggers_after; + + if (!process_sp->GetWatchpointSupportInfo(num, wp_triggers_after) + .Success()) { + m_should_stop_is_valid = true; + m_should_stop = true; + return m_should_stop; + } + + if (!wp_triggers_after) { + // We have to step over the watchpoint before we know what to do: + StopInfoWatchpointSP me_as_siwp_sp + = std::static_pointer_cast<StopInfoWatchpoint>(shared_from_this()); + ThreadPlanSP step_over_wp_sp(new ThreadPlanStepOverWatchpoint( + *(thread_sp.get()), me_as_siwp_sp, wp_sp)); + Status error; + error = thread_sp->QueueThreadPlan(step_over_wp_sp, false); + // If we couldn't push the thread plan, just stop here: + if (!error.Success()) { + LLDB_LOGF(log, "Could not push our step over watchpoint plan: %s", + error.AsCString()); m_should_stop = true; + m_should_stop_is_valid = true; + return true; + } else { + // Otherwise, don't set m_should_stop, we don't know that yet. Just + // say we should continue, and tell the thread we really should do so: + thread_sp->SetShouldRunBeforePublicStop(true); + m_using_step_over_plan = true; + return false; } + } else { + // We didn't have to do anything special + m_should_stop_is_valid = true; + return m_should_stop; } - m_should_stop_is_valid = true; + return m_should_stop; } @@ -749,57 +887,12 @@ protected: thread_sp->CalculateTarget()->GetWatchpointList().FindByID( GetValue())); if (wp_sp) { - ExecutionContext exe_ctx(thread_sp->GetStackFrameAtIndex(0)); - ProcessSP process_sp = exe_ctx.GetProcessSP(); - - { - // check if this process is running on an architecture where - // watchpoints trigger before the associated instruction runs. if so, - // disable the WP, single-step and then re-enable the watchpoint - if (process_sp) { - uint32_t num; - bool wp_triggers_after; - - if (process_sp->GetWatchpointSupportInfo(num, wp_triggers_after) - .Success()) { - if (!wp_triggers_after) { - // We need to preserve the watch_index before watchpoint is - // disable. Since Watchpoint::SetEnabled will clear the watch - // index. This will fix TestWatchpointIter failure - Watchpoint *wp = wp_sp.get(); - uint32_t watch_index = wp->GetHardwareIndex(); - process_sp->DisableWatchpoint(wp, false); - StopInfoSP stored_stop_info_sp = thread_sp->GetStopInfo(); - assert(stored_stop_info_sp.get() == this); - - Status new_plan_status; - ThreadPlanSP new_plan_sp( - thread_sp->QueueThreadPlanForStepSingleInstruction( - false, // step-over - false, // abort_other_plans - true, // stop_other_threads - new_plan_status)); - if (new_plan_sp && new_plan_status.Success()) { - new_plan_sp->SetIsControllingPlan(true); - new_plan_sp->SetOkayToDiscard(false); - new_plan_sp->SetPrivate(true); - } - process_sp->GetThreadList().SetSelectedThreadByID( - thread_sp->GetID()); - process_sp->ResumeSynchronous(nullptr); - process_sp->GetThreadList().SetSelectedThreadByID( - thread_sp->GetID()); - thread_sp->SetStopInfo(stored_stop_info_sp); - process_sp->EnableWatchpoint(wp, false); - wp->SetHardwareIndex(watch_index); - } - } - } - } - // This sentry object makes sure the current watchpoint is disabled // while performing watchpoint actions, and it is then enabled after we // are finished. + ExecutionContext exe_ctx(thread_sp->GetStackFrameAtIndex(0)); + ProcessSP process_sp = exe_ctx.GetProcessSP(); + WatchpointSentry sentry(process_sp, wp_sp); /* @@ -825,18 +918,10 @@ protected: } } - // TODO: This condition should be checked in the synchronous part of the - // watchpoint code - // (Watchpoint::ShouldStop), so that we avoid pulling an event even if - // the watchpoint fails the ignore count condition. It is moved here - // temporarily, because for archs with - // watchpoint_exceptions_received=before, the code in the previous - // lines takes care of moving the inferior to next PC. We have to check - // the ignore count condition after this is done, otherwise we will hit - // same watchpoint multiple times until we pass ignore condition, but - // we won't actually be ignoring them. - if (wp_sp->GetHitCount() <= wp_sp->GetIgnoreCount()) + if (wp_sp->GetHitCount() <= wp_sp->GetIgnoreCount()) { m_should_stop = false; + m_should_stop_is_valid = true; + } Debugger &debugger = exe_ctx.GetTargetRef().GetDebugger(); @@ -859,10 +944,9 @@ protected: Scalar scalar_value; if (result_value_sp->ResolveValue(scalar_value)) { if (scalar_value.ULongLong(1) == 0) { - // We have been vetoed. This takes precedence over querying - // the watchpoint whether it should stop (aka ignore count - // and friends). See also StopInfoWatchpoint::ShouldStop() - // as well as Process::ProcessEventData::DoOnRemoval(). + // The condition failed, which we consider "not having hit + // the watchpoint" so undo the hit count here. + wp_sp->UndoHitCount(); m_should_stop = false; } else m_should_stop = true; @@ -946,9 +1030,16 @@ protected: } private: + void SetStepOverPlanComplete() { + assert(m_using_step_over_plan); + m_step_over_plan_complete = true; + } + bool m_should_stop = false; bool m_should_stop_is_valid = false; lldb::addr_t m_watch_hit_addr; + bool m_step_over_plan_complete = false; + bool m_using_step_over_plan = false; }; // StopInfoUnixSignal diff --git a/contrib/llvm-project/lldb/source/Target/Target.cpp b/contrib/llvm-project/lldb/source/Target/Target.cpp index f16fc6b5da85..fd0cf0a5361d 100644 --- a/contrib/llvm-project/lldb/source/Target/Target.cpp +++ b/contrib/llvm-project/lldb/source/Target/Target.cpp @@ -26,6 +26,7 @@ #include "lldb/Core/StreamFile.h" #include "lldb/Core/StructuredDataImpl.h" #include "lldb/Core/ValueObject.h" +#include "lldb/Core/ValueObjectConstResult.h" #include "lldb/Expression/DiagnosticManager.h" #include "lldb/Expression/ExpressionVariable.h" #include "lldb/Expression/REPL.h" @@ -66,6 +67,7 @@ #include <memory> #include <mutex> +#include <optional> using namespace lldb; using namespace lldb_private; @@ -107,7 +109,7 @@ Target::Target(Debugger &debugger, const ArchSpec &target_arch, SetEventName(eBroadcastBitModulesUnloaded, "modules-unloaded"); SetEventName(eBroadcastBitWatchpointChanged, "watchpoint-changed"); SetEventName(eBroadcastBitSymbolsLoaded, "symbols-loaded"); - + CheckInWithManager(); LLDB_LOG(GetLog(LLDBLog::Object), "{0} Target::Target()", @@ -140,10 +142,8 @@ void Target::PrimeFromDummyTarget(Target &target) { AddBreakpoint(std::move(new_bp), false); } - for (auto bp_name_entry : target.m_breakpoint_names) { - - BreakpointName *new_bp_name = new BreakpointName(*bp_name_entry.second); - AddBreakpointName(new_bp_name); + for (const auto &bp_name_entry : target.m_breakpoint_names) { + AddBreakpointName(std::make_unique<BreakpointName>(*bp_name_entry.second)); } m_frame_recognizer_manager_up = std::make_unique<StackFrameRecognizerManager>( @@ -177,6 +177,7 @@ void Target::CleanupProcess() { // clean up needs some help from the process. m_breakpoint_list.ClearAllBreakpointSites(); m_internal_breakpoint_list.ClearAllBreakpointSites(); + ResetBreakpointHitCounts(); // Disable watchpoints just on the debugger side. std::unique_lock<std::recursive_mutex> lock; this->GetWatchpointList().GetListMutex(lock); @@ -284,6 +285,7 @@ void Target::Destroy() { m_breakpoint_list.RemoveAll(notify); m_internal_breakpoint_list.RemoveAll(notify); m_last_created_breakpoint.reset(); + m_watchpoint_list.RemoveAll(notify); m_last_created_watchpoint.reset(); m_search_filter_sp.reset(); m_image_search_paths.Clear(notify); @@ -355,7 +357,9 @@ BreakpointSP Target::CreateBreakpoint(const FileSpecList *containingModules, bool hardware, LazyBool move_to_nearest_code) { FileSpec remapped_file; - if (!GetSourcePathMap().ReverseRemapPath(file, remapped_file)) + std::optional<llvm::StringRef> removed_prefix_opt = + GetSourcePathMap().ReverseRemapPath(file, remapped_file); + if (!removed_prefix_opt) remapped_file = file; if (check_inlines == eLazyBoolCalculate) { @@ -399,7 +403,7 @@ BreakpointSP Target::CreateBreakpoint(const FileSpecList *containingModules, return nullptr; BreakpointResolverSP resolver_sp(new BreakpointResolverFileLine( - nullptr, offset, skip_prologue, location_spec)); + nullptr, offset, skip_prologue, location_spec, removed_prefix_opt)); return CreateBreakpoint(filter_sp, resolver_sp, internal, hardware, true); } @@ -707,8 +711,9 @@ void Target::AddNameToBreakpoint(BreakpointSP &bp_sp, const char *name, bp_sp->AddName(name); } -void Target::AddBreakpointName(BreakpointName *bp_name) { - m_breakpoint_names.insert(std::make_pair(bp_name->GetName(), bp_name)); +void Target::AddBreakpointName(std::unique_ptr<BreakpointName> bp_name) { + m_breakpoint_names.insert( + std::make_pair(bp_name->GetName(), std::move(bp_name))); } BreakpointName *Target::FindBreakpointName(ConstString name, bool can_create, @@ -718,19 +723,20 @@ BreakpointName *Target::FindBreakpointName(ConstString name, bool can_create, return nullptr; BreakpointNameList::iterator iter = m_breakpoint_names.find(name); - if (iter == m_breakpoint_names.end()) { - if (!can_create) { - error.SetErrorStringWithFormat("Breakpoint name \"%s\" doesn't exist and " - "can_create is false.", - name.AsCString()); - return nullptr; - } + if (iter != m_breakpoint_names.end()) { + return iter->second.get(); + } - iter = m_breakpoint_names - .insert(std::make_pair(name, new BreakpointName(name))) - .first; + if (!can_create) { + error.SetErrorStringWithFormat("Breakpoint name \"%s\" doesn't exist and " + "can_create is false.", + name.AsCString()); + return nullptr; } - return (iter->second); + + return m_breakpoint_names + .insert(std::make_pair(name, std::make_unique<BreakpointName>(name))) + .first->second.get(); } void Target::DeleteBreakpointName(ConstString name) { @@ -773,8 +779,8 @@ void Target::ApplyNameToBreakpoints(BreakpointName &bp_name) { void Target::GetBreakpointNames(std::vector<std::string> &names) { names.clear(); - for (auto bp_name : m_breakpoint_names) { - names.push_back(bp_name.first.AsCString()); + for (const auto& bp_name_entry : m_breakpoint_names) { + names.push_back(bp_name_entry.first.AsCString()); } llvm::sort(names); } @@ -1002,6 +1008,10 @@ bool Target::EnableBreakpointByID(break_id_t break_id) { return false; } +void Target::ResetBreakpointHitCounts() { + GetBreakpointList().ResetHitCounts(); +} + Status Target::SerializeBreakpointsToFile(const FileSpec &file, const BreakpointIDList &bp_ids, bool append) { @@ -1427,7 +1437,8 @@ void Target::SetExecutableModule(ModuleSP &executable_sp, if (!m_arch.GetSpec().IsValid()) { m_arch = executable_sp->GetArchitecture(); LLDB_LOG(log, - "setting architecture to {0} ({1}) based on executable file", + "Target::SetExecutableModule setting architecture to {0} ({1}) " + "based on executable file", m_arch.GetSpec().GetArchitectureName(), m_arch.GetSpec().GetTriple().getTriple()); } @@ -1474,7 +1485,8 @@ void Target::SetExecutableModule(ModuleSP &executable_sp, } } -bool Target::SetArchitecture(const ArchSpec &arch_spec, bool set_platform) { +bool Target::SetArchitecture(const ArchSpec &arch_spec, bool set_platform, + bool merge) { Log *log = GetLog(LLDBLog::Target); bool missing_local_arch = !m_arch.GetSpec().IsValid(); bool replace_local_arch = true; @@ -1487,8 +1499,8 @@ bool Target::SetArchitecture(const ArchSpec &arch_spec, bool set_platform) { if (set_platform) { if (other.IsValid()) { auto platform_sp = GetPlatform(); - if (!platform_sp || - !platform_sp->IsCompatibleArchitecture(other, {}, false, nullptr)) { + if (!platform_sp || !platform_sp->IsCompatibleArchitecture( + other, {}, ArchSpec::CompatibleMatch, nullptr)) { ArchSpec platform_arch; if (PlatformSP arch_platform_sp = GetDebugger().GetPlatformList().GetOrCreate(other, {}, @@ -1502,7 +1514,7 @@ bool Target::SetArchitecture(const ArchSpec &arch_spec, bool set_platform) { } if (!missing_local_arch) { - if (m_arch.GetSpec().IsCompatibleMatch(arch_spec)) { + if (merge && m_arch.GetSpec().IsCompatibleMatch(arch_spec)) { other.MergeFrom(m_arch.GetSpec()); if (m_arch.GetSpec().IsCompatibleMatch(other)) { @@ -1526,7 +1538,9 @@ bool Target::SetArchitecture(const ArchSpec &arch_spec, bool set_platform) { // specified if (replace_local_arch) m_arch = other; - LLDB_LOG(log, "set architecture to {0} ({1})", + LLDB_LOG(log, + "Target::SetArchitecture merging compatible arch; arch " + "is now {0} ({1})", m_arch.GetSpec().GetArchitectureName(), m_arch.GetSpec().GetTriple().getTriple()); return true; @@ -1534,9 +1548,13 @@ bool Target::SetArchitecture(const ArchSpec &arch_spec, bool set_platform) { // If we have an executable file, try to reset the executable to the desired // architecture - LLDB_LOGF(log, "Target::SetArchitecture changing architecture to %s (%s)", - arch_spec.GetArchitectureName(), - arch_spec.GetTriple().getTriple().c_str()); + LLDB_LOGF( + log, + "Target::SetArchitecture changing architecture to %s (%s) from %s (%s)", + arch_spec.GetArchitectureName(), + arch_spec.GetTriple().getTriple().c_str(), + m_arch.GetSpec().GetArchitectureName(), + m_arch.GetSpec().GetTriple().getTriple().c_str()); m_arch = other; ModuleSP executable_sp = GetExecutableModule(); @@ -1665,6 +1683,34 @@ void Target::ModulesDidUnload(ModuleList &module_list, bool delete_locations) { m_breakpoint_list.UpdateBreakpoints(module_list, false, delete_locations); m_internal_breakpoint_list.UpdateBreakpoints(module_list, false, delete_locations); + + // If a module was torn down it will have torn down the 'TypeSystemClang's + // that we used as source 'ASTContext's for the persistent variables in + // the current target. Those would now be unsafe to access because the + // 'DeclOrigin' are now possibly stale. Thus clear all persistent + // variables. We only want to flush 'TypeSystem's if the module being + // unloaded was capable of describing a source type. JITted module unloads + // happen frequently for Objective-C utility functions or the REPL and rely + // on the persistent variables to stick around. + const bool should_flush_type_systems = + module_list.AnyOf([](lldb_private::Module &module) { + auto *object_file = module.GetObjectFile(); + + if (!object_file) + return false; + + auto type = object_file->GetType(); + + // eTypeExecutable: when debugged binary was rebuilt + // eTypeSharedLibrary: if dylib was re-loaded + return module.FileHasChanged() && + (type == ObjectFile::eTypeObjectFile || + type == ObjectFile::eTypeExecutable || + type == ObjectFile::eTypeSharedLibrary); + }); + + if (should_flush_type_systems) + m_scratch_type_system_map.Clear(); } } @@ -2085,11 +2131,12 @@ ModuleSP Target::GetOrCreateModule(const ModuleSpec &module_spec, bool notify, // a suitable image. if (m_image_search_paths.GetSize()) { ModuleSpec transformed_spec(module_spec); + ConstString transformed_dir; if (m_image_search_paths.RemapPath( - module_spec.GetFileSpec().GetDirectory(), - transformed_spec.GetFileSpec().GetDirectory())) { - transformed_spec.GetFileSpec().GetFilename() = - module_spec.GetFileSpec().GetFilename(); + module_spec.GetFileSpec().GetDirectory(), transformed_dir)) { + transformed_spec.GetFileSpec().SetDirectory(transformed_dir); + transformed_spec.GetFileSpec().SetFilename( + module_spec.GetFileSpec().GetFilename()); error = ModuleList::GetSharedModule(transformed_spec, module_sp, &search_paths, &old_modules, &did_create_module); @@ -2283,7 +2330,7 @@ void Target::ImageSearchPathsChanged(const PathMappingList &path_list, target->SetExecutableModule(exe_module_sp, eLoadDependentsYes); } -llvm::Expected<TypeSystem &> +llvm::Expected<lldb::TypeSystemSP> Target::GetScratchTypeSystemForLanguage(lldb::LanguageType language, bool create_on_demand) { if (!m_valid) @@ -2312,14 +2359,15 @@ Target::GetScratchTypeSystemForLanguage(lldb::LanguageType language, create_on_demand); } -std::vector<TypeSystem *> Target::GetScratchTypeSystems(bool create_on_demand) { +std::vector<lldb::TypeSystemSP> +Target::GetScratchTypeSystems(bool create_on_demand) { if (!m_valid) return {}; // Some TypeSystem instances are associated with several LanguageTypes so // they will show up several times in the loop below. The SetVector filters // out all duplicates as they serve no use for the caller. - llvm::SetVector<TypeSystem *> scratch_type_systems; + std::vector<lldb::TypeSystemSP> scratch_type_systems; LanguageSet languages_for_expressions = Language::GetLanguagesSupportingTypeSystemsForExpressions(); @@ -2334,10 +2382,17 @@ std::vector<TypeSystem *> Target::GetScratchTypeSystems(bool create_on_demand) { "system available", Language::GetNameForLanguageType(language)); else - scratch_type_systems.insert(&type_system_or_err.get()); + if (auto ts = *type_system_or_err) + scratch_type_systems.push_back(ts); } - - return scratch_type_systems.takeVector(); + std::sort(scratch_type_systems.begin(), scratch_type_systems.end(), + [](lldb::TypeSystemSP a, lldb::TypeSystemSP b) { + return a.get() <= b.get(); + }); + scratch_type_systems.erase( + std::unique(scratch_type_systems.begin(), scratch_type_systems.end()), + scratch_type_systems.end()); + return scratch_type_systems; } PersistentExpressionState * @@ -2351,7 +2406,13 @@ Target::GetPersistentExpressionStateForLanguage(lldb::LanguageType language) { return nullptr; } - return type_system_or_err->GetPersistentExpressionState(); + if (auto ts = *type_system_or_err) + return ts->GetPersistentExpressionState(); + + LLDB_LOG(GetLog(LLDBLog::Target), + "Unable to get persistent expression state for language {}", + Language::GetNameForLanguageType(language)); + return nullptr; } UserExpression *Target::GetUserExpressionForLanguage( @@ -2368,8 +2429,16 @@ UserExpression *Target::GetUserExpressionForLanguage( return nullptr; } - auto *user_expr = type_system_or_err->GetUserExpression( - expr, prefix, language, desired_type, options, ctx_obj); + auto ts = *type_system_or_err; + if (!ts) { + error.SetErrorStringWithFormat( + "Type system for language %s is no longer live", + Language::GetNameForLanguageType(language)); + return nullptr; + } + + auto *user_expr = ts->GetUserExpression(expr, prefix, language, desired_type, + options, ctx_obj); if (!user_expr) error.SetErrorStringWithFormat( "Could not create an expression for language %s", @@ -2390,9 +2459,15 @@ FunctionCaller *Target::GetFunctionCallerForLanguage( llvm::toString(std::move(err)).c_str()); return nullptr; } - - auto *persistent_fn = type_system_or_err->GetFunctionCaller( - return_type, function_address, arg_value_list, name); + auto ts = *type_system_or_err; + if (!ts) { + error.SetErrorStringWithFormat( + "Type system for language %s is no longer live", + Language::GetNameForLanguageType(language)); + return nullptr; + } + auto *persistent_fn = ts->GetFunctionCaller(return_type, function_address, + arg_value_list, name); if (!persistent_fn) error.SetErrorStringWithFormat( "Could not create an expression for language %s", @@ -2408,10 +2483,15 @@ Target::CreateUtilityFunction(std::string expression, std::string name, auto type_system_or_err = GetScratchTypeSystemForLanguage(language); if (!type_system_or_err) return type_system_or_err.takeError(); - + auto ts = *type_system_or_err; + if (!ts) + return llvm::make_error<llvm::StringError>( + llvm::StringRef("Type system for language ") + + Language::GetNameForLanguageType(language) + + llvm::StringRef(" is no longer live"), + llvm::inconvertibleErrorCode()); std::unique_ptr<UtilityFunction> utility_fn = - type_system_or_err->CreateUtilityFunction(std::move(expression), - std::move(name)); + ts->CreateUtilityFunction(std::move(expression), std::move(name)); if (!utility_fn) return llvm::make_error<llvm::StringError>( llvm::StringRef("Could not create an expression for language") + @@ -2505,8 +2585,13 @@ ExpressionResults Target::EvaluateExpression( LLDB_LOG_ERROR(GetLog(LLDBLog::Target), std::move(err), "Unable to get scratch type system"); } else { - persistent_var_sp = - type_system_or_err->GetPersistentExpressionState()->GetVariable(expr); + auto ts = *type_system_or_err; + if (!ts) + LLDB_LOG_ERROR(GetLog(LLDBLog::Target), std::move(err), + "Scratch type system is no longer live"); + else + persistent_var_sp = + ts->GetPersistentExpressionState()->GetVariable(expr); } } if (persistent_var_sp) { @@ -2518,6 +2603,10 @@ ExpressionResults Target::EvaluateExpression( execution_results = UserExpression::Evaluate(exe_ctx, options, expr, prefix, result_valobj_sp, error, fixed_expression, ctx_obj); + // Pass up the error by wrapping it inside an error result. + if (error.Fail() && !result_valobj_sp) + result_valobj_sp = ValueObjectConstResult::Create( + exe_ctx.GetBestExecutionContextScope(), error); } if (execution_results == eExpressionCompleted) @@ -2530,9 +2619,12 @@ ExpressionResults Target::EvaluateExpression( lldb::ExpressionVariableSP Target::GetPersistentVariable(ConstString name) { lldb::ExpressionVariableSP variable_sp; m_scratch_type_system_map.ForEach( - [name, &variable_sp](TypeSystem *type_system) -> bool { + [name, &variable_sp](TypeSystemSP type_system) -> bool { + auto ts = type_system.get(); + if (!ts) + return true; if (PersistentExpressionState *persistent_state = - type_system->GetPersistentExpressionState()) { + ts->GetPersistentExpressionState()) { variable_sp = persistent_state->GetVariable(name); if (variable_sp) @@ -2547,9 +2639,13 @@ lldb::addr_t Target::GetPersistentSymbol(ConstString name) { lldb::addr_t address = LLDB_INVALID_ADDRESS; m_scratch_type_system_map.ForEach( - [name, &address](TypeSystem *type_system) -> bool { + [name, &address](lldb::TypeSystemSP type_system) -> bool { + auto ts = type_system.get(); + if (!ts) + return true; + if (PersistentExpressionState *persistent_state = - type_system->GetPersistentExpressionState()) { + ts->GetPersistentExpressionState()) { address = persistent_state->LookupSymbol(name); if (address != LLDB_INVALID_ADDRESS) return false; // Stop iterating the ForEach @@ -3109,7 +3205,7 @@ Status Target::Launch(ProcessLaunchInfo &launch_info, Stream *stream) { assert(launch_info.GetHijackListener()); EventSP first_stop_event_sp; - state = m_process_sp->WaitForProcessToStop(llvm::None, &first_stop_event_sp, + state = m_process_sp->WaitForProcessToStop(std::nullopt, &first_stop_event_sp, rebroadcast_first_stop, launch_info.GetHijackListener()); m_process_sp->RestoreProcessEvents(); @@ -3219,8 +3315,8 @@ Status Target::Attach(ProcessAttachInfo &attach_info, Stream *stream) { // the process to attach to by default if (!attach_info.ProcessInfoSpecified()) { if (old_exec_module_sp) - attach_info.GetExecutableFile().GetFilename() = - old_exec_module_sp->GetPlatformFileSpec().GetFilename(); + attach_info.GetExecutableFile().SetFilename( + old_exec_module_sp->GetPlatformFileSpec().GetFilename()); if (!attach_info.ProcessInfoSpecified()) { return Status("no process specified, create a target with a file, or " @@ -3265,8 +3361,9 @@ Status Target::Attach(ProcessAttachInfo &attach_info, Stream *stream) { if (async) { process_sp->RestoreProcessEvents(); } else { - state = process_sp->WaitForProcessToStop( - llvm::None, nullptr, false, attach_info.GetHijackListener(), stream); + state = process_sp->WaitForProcessToStop(std::nullopt, nullptr, false, + attach_info.GetHijackListener(), + stream); process_sp->RestoreProcessEvents(); if (state != eStateStopped) { @@ -3362,7 +3459,7 @@ void Target::FinalizeFileActions(ProcessLaunchInfo &info) { } } -void Target::AddDummySignal(llvm::StringRef name, LazyBool pass, LazyBool notify, +void Target::AddDummySignal(llvm::StringRef name, LazyBool pass, LazyBool notify, LazyBool stop) { if (name.empty()) return; @@ -3377,38 +3474,38 @@ void Target::AddDummySignal(llvm::StringRef name, LazyBool pass, LazyBool notify elem.stop = stop; } -bool Target::UpdateSignalFromDummy(UnixSignalsSP signals_sp, +bool Target::UpdateSignalFromDummy(UnixSignalsSP signals_sp, const DummySignalElement &elem) { if (!signals_sp) return false; - int32_t signo + int32_t signo = signals_sp->GetSignalNumberFromName(elem.first().str().c_str()); if (signo == LLDB_INVALID_SIGNAL_NUMBER) return false; - + if (elem.second.pass == eLazyBoolYes) signals_sp->SetShouldSuppress(signo, false); else if (elem.second.pass == eLazyBoolNo) signals_sp->SetShouldSuppress(signo, true); - + if (elem.second.notify == eLazyBoolYes) signals_sp->SetShouldNotify(signo, true); else if (elem.second.notify == eLazyBoolNo) signals_sp->SetShouldNotify(signo, false); - + if (elem.second.stop == eLazyBoolYes) signals_sp->SetShouldStop(signo, true); else if (elem.second.stop == eLazyBoolNo) signals_sp->SetShouldStop(signo, false); - return true; + return true; } -bool Target::ResetSignalFromDummy(UnixSignalsSP signals_sp, +bool Target::ResetSignalFromDummy(UnixSignalsSP signals_sp, const DummySignalElement &elem) { if (!signals_sp) return false; - int32_t signo + int32_t signo = signals_sp->GetSignalNumberFromName(elem.first().str().c_str()); if (signo == LLDB_INVALID_SIGNAL_NUMBER) return false; @@ -3419,14 +3516,14 @@ bool Target::ResetSignalFromDummy(UnixSignalsSP signals_sp, return true; } -void Target::UpdateSignalsFromDummy(UnixSignalsSP signals_sp, +void Target::UpdateSignalsFromDummy(UnixSignalsSP signals_sp, StreamSP warning_stream_sp) { if (!signals_sp) return; for (const auto &elem : m_dummy_signals) { if (!UpdateSignalFromDummy(signals_sp, elem)) - warning_stream_sp->Printf("Target signal '%s' not found in process\n", + warning_stream_sp->Printf("Target signal '%s' not found in process\n", elem.first().str().c_str()); } } @@ -3459,7 +3556,7 @@ void Target::ClearDummySignals(Args &signal_names) { void Target::PrintDummySignals(Stream &strm, Args &signal_args) { strm.Printf("NAME PASS STOP NOTIFY\n"); strm.Printf("=========== ======= ======= =======\n"); - + auto str_for_lazy = [] (LazyBool lazy) -> const char * { switch (lazy) { case eLazyBoolCalculate: return "not set"; @@ -4267,6 +4364,12 @@ PathMappingList &TargetProperties::GetSourcePathMap() const { return option_value->GetCurrentValue(); } +bool TargetProperties::GetAutoSourceMapRelative() const { + const uint32_t idx = ePropertyAutoSourceMapRelative; + return m_collection_sp->GetPropertyAtIndexAsBoolean( + nullptr, idx, g_target_properties[idx].default_uint_value != 0); +} + void TargetProperties::AppendExecutableSearchPaths(const FileSpec &dir) { const uint32_t idx = ePropertyExecutableSearchPaths; OptionValueFileSpecList *option_value = @@ -4372,7 +4475,7 @@ void TargetProperties::CheckJITObjectsDir() { else if (!writable) os << "is not writable"; - llvm::Optional<lldb::user_id_t> debugger_id = llvm::None; + std::optional<lldb::user_id_t> debugger_id; if (m_target) debugger_id = m_target->GetDebugger().GetID(); Debugger::ReportError(os.str(), debugger_id); diff --git a/contrib/llvm-project/lldb/source/Target/TargetList.cpp b/contrib/llvm-project/lldb/source/Target/TargetList.cpp index 829036976a21..8ce2ae8c2898 100644 --- a/contrib/llvm-project/lldb/source/Target/TargetList.cpp +++ b/contrib/llvm-project/lldb/source/Target/TargetList.cpp @@ -216,7 +216,8 @@ Status TargetList::CreateTargetInternal( // If we have a valid architecture, make sure the current platform is // compatible with that architecture. if (!prefer_platform_arch && arch.IsValid()) { - if (!platform_sp->IsCompatibleArchitecture(arch, {}, false, nullptr)) { + if (!platform_sp->IsCompatibleArchitecture( + arch, {}, ArchSpec::CompatibleMatch, nullptr)) { platform_sp = platform_list.GetOrCreate(arch, {}, &platform_arch); if (platform_sp) platform_list.SetSelectedPlatform(platform_sp); @@ -225,7 +226,8 @@ Status TargetList::CreateTargetInternal( // If "arch" isn't valid, yet "platform_arch" is, it means we have an // executable file with a single architecture which should be used. ArchSpec fixed_platform_arch; - if (!platform_sp->IsCompatibleArchitecture(platform_arch, {}, false, nullptr)) { + if (!platform_sp->IsCompatibleArchitecture( + platform_arch, {}, ArchSpec::CompatibleMatch, nullptr)) { platform_sp = platform_list.GetOrCreate(platform_arch, {}, &fixed_platform_arch); if (platform_sp) @@ -256,8 +258,8 @@ Status TargetList::CreateTargetInternal(Debugger &debugger, ArchSpec arch(specified_arch); if (arch.IsValid()) { - if (!platform_sp || - !platform_sp->IsCompatibleArchitecture(arch, {}, false, nullptr)) + if (!platform_sp || !platform_sp->IsCompatibleArchitecture( + arch, {}, ArchSpec::CompatibleMatch, nullptr)) platform_sp = debugger.GetPlatformList().GetOrCreate(specified_arch, {}, &arch); } @@ -354,7 +356,7 @@ Status TargetList::CreateTargetInternal(Debugger &debugger, } if (file.GetDirectory()) { FileSpec file_dir; - file_dir.GetDirectory() = file.GetDirectory(); + file_dir.SetDirectory(file.GetDirectory()); target_sp->AppendExecutableSearchPaths(file_dir); } diff --git a/contrib/llvm-project/lldb/source/Target/TargetProperties.td b/contrib/llvm-project/lldb/source/Target/TargetProperties.td index acee09ca0469..202304174bc1 100644 --- a/contrib/llvm-project/lldb/source/Target/TargetProperties.td +++ b/contrib/llvm-project/lldb/source/Target/TargetProperties.td @@ -37,6 +37,9 @@ let Definition = "target" in { def SourceMap: Property<"source-map", "PathMap">, DefaultStringValue<"">, Desc<"Source path remappings apply substitutions to the paths of source files, typically needed to debug from a different host than the one that built the target. The source-map property consists of an array of pairs, the first element is a path prefix, and the second is its replacement. The syntax is `prefix1 replacement1 prefix2 replacement2...`. The pairs are checked in order, the first prefix that matches is used, and that prefix is substituted with the replacement. A common pattern is to use source-map in conjunction with the clang -fdebug-prefix-map flag. In the build, use `-fdebug-prefix-map=/path/to/build_dir=.` to rewrite the host specific build directory to `.`. Then for debugging, use `settings set target.source-map . /path/to/local_dir` to convert `.` to a valid local path.">; + def AutoSourceMapRelative: Property<"auto-source-map-relative", "Boolean">, + DefaultTrue, + Desc<"Automatically deduce source path mappings based on source file breakpoint resolution. It only deduces source mapping if source file breakpoint request is using full path and if the debug info contains relative paths.">; def ExecutableSearchPaths: Property<"exec-search-paths", "FileSpecList">, DefaultStringValue<"">, Desc<"Executable search paths to use when locating executable files whose paths don't match the local file system.">; diff --git a/contrib/llvm-project/lldb/source/Target/Thread.cpp b/contrib/llvm-project/lldb/source/Target/Thread.cpp index f63b57fd4e62..d620f746339e 100644 --- a/contrib/llvm-project/lldb/source/Target/Thread.cpp +++ b/contrib/llvm-project/lldb/source/Target/Thread.cpp @@ -53,6 +53,7 @@ #include "lldb/lldb-enumerations.h" #include <memory> +#include <optional> using namespace lldb; using namespace lldb_private; @@ -221,6 +222,7 @@ Thread::Thread(Process &process, lldb::tid_t tid, bool use_invalid_index_id) Thread::GetStaticBroadcasterClass().AsCString()), m_process_wp(process.shared_from_this()), m_stop_info_sp(), m_stop_info_stop_id(0), m_stop_info_override_stop_id(0), + m_should_run_before_public_stop(false), m_index_id(use_invalid_index_id ? LLDB_INVALID_INDEX32 : process.GetNextThreadIndexID(tid)), m_reg_context_sp(), m_state(eStateUnloaded), m_state_mutex(), @@ -369,7 +371,10 @@ void Thread::CalculatePublicStopInfo() { SetStopInfo(GetStopInfo()); } -lldb::StopInfoSP Thread::GetPrivateStopInfo() { +lldb::StopInfoSP Thread::GetPrivateStopInfo(bool calculate) { + if (!calculate) + return m_stop_info_sp; + if (m_destroy_called) return m_stop_info_sp; @@ -377,9 +382,15 @@ lldb::StopInfoSP Thread::GetPrivateStopInfo() { if (process_sp) { const uint32_t process_stop_id = process_sp->GetStopID(); if (m_stop_info_stop_id != process_stop_id) { + // We preserve the old stop info for a variety of reasons: + // 1) Someone has already updated it by the time we get here + // 2) We didn't get to execute the breakpoint instruction we stopped at + // 3) This is a virtual step so we didn't actually run + // 4) If this thread wasn't allowed to run the last time round. if (m_stop_info_sp) { if (m_stop_info_sp->IsValid() || IsStillAtLastBreakpointHit() || - GetCurrentPlan()->IsVirtualStep()) + GetCurrentPlan()->IsVirtualStep() + || GetTemporaryResumeState() == eStateSuspended) SetStopInfo(m_stop_info_sp); else m_stop_info_sp.reset(); @@ -723,7 +734,11 @@ bool Thread::ShouldResume(StateType resume_state) { return need_to_resume; } -void Thread::DidResume() { SetResumeSignal(LLDB_INVALID_SIGNAL_NUMBER); } +void Thread::DidResume() { + SetResumeSignal(LLDB_INVALID_SIGNAL_NUMBER); + // This will get recomputed each time when we stop. + SetShouldRunBeforePublicStop(false); +} void Thread::DidStop() { SetState(eStateStopped); } @@ -763,6 +778,9 @@ bool Thread::ShouldStop(Event *event_ptr) { : LLDB_INVALID_ADDRESS); return false; } + + // Clear the "must run me before stop" if it was set: + SetShouldRunBeforePublicStop(false); if (log) { LLDB_LOGF(log, @@ -845,9 +863,14 @@ bool Thread::ShouldStop(Event *event_ptr) { // stack below. done_processing_current_plan = (plan_ptr->IsControllingPlan() && !plan_ptr->OkayToDiscard()); - } else + } else { + bool should_force_run = plan_ptr->ShouldRunBeforePublicStop(); + if (should_force_run) { + SetShouldRunBeforePublicStop(true); + should_stop = false; + } done_processing_current_plan = true; - + } break; } } @@ -1062,7 +1085,7 @@ ThreadPlanStack &Thread::GetPlans() const { // queries GetDescription makes, and only assert if you try to run the thread. if (!m_null_plan_stack_up) m_null_plan_stack_up = std::make_unique<ThreadPlanStack>(*this, true); - return *(m_null_plan_stack_up.get()); + return *m_null_plan_stack_up; } void Thread::PushPlan(ThreadPlanSP thread_plan_sp) { @@ -1641,6 +1664,10 @@ addr_t Thread::GetThreadLocalData(const ModuleSP module, bool Thread::SafeToCallFunctions() { Process *process = GetProcess().get(); if (process) { + DynamicLoader *loader = GetProcess()->GetDynamicLoader(); + if (loader && loader->IsFullyInitialized() == false) + return false; + SystemRuntime *runtime = process->GetSystemRuntime(); if (runtime) { return runtime->SafeToCallFunctionsOnThisThread(shared_from_this()); @@ -2020,10 +2047,10 @@ lldb::ValueObjectSP Thread::GetSiginfoValue() { if (!type.IsValid()) return ValueObjectConstResult::Create(&target, Status("no siginfo_t for the platform")); - llvm::Optional<uint64_t> type_size = type.GetByteSize(nullptr); + std::optional<uint64_t> type_size = type.GetByteSize(nullptr); assert(type_size); llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>> data = - GetSiginfo(type_size.value()); + GetSiginfo(*type_size); if (!data) return ValueObjectConstResult::Create(&target, Status(data.takeError())); diff --git a/contrib/llvm-project/lldb/source/Target/ThreadCollection.cpp b/contrib/llvm-project/lldb/source/Target/ThreadCollection.cpp index 8c2309795a4c..45ce2fd318b7 100644 --- a/contrib/llvm-project/lldb/source/Target/ThreadCollection.cpp +++ b/contrib/llvm-project/lldb/source/Target/ThreadCollection.cpp @@ -34,10 +34,10 @@ void ThreadCollection::AddThreadSortedByIndexID(const ThreadSP &thread_sp) { m_threads.push_back(thread_sp); else { m_threads.insert( - std::upper_bound(m_threads.begin(), m_threads.end(), thread_sp, - [](const ThreadSP &lhs, const ThreadSP &rhs) -> bool { - return lhs->GetIndexID() < rhs->GetIndexID(); - }), + llvm::upper_bound(m_threads, thread_sp, + [](const ThreadSP &lhs, const ThreadSP &rhs) -> bool { + return lhs->GetIndexID() < rhs->GetIndexID(); + }), thread_sp); } } diff --git a/contrib/llvm-project/lldb/source/Target/ThreadList.cpp b/contrib/llvm-project/lldb/source/Target/ThreadList.cpp index 7359bfcd3cfc..006c8648be52 100644 --- a/contrib/llvm-project/lldb/source/Target/ThreadList.cpp +++ b/contrib/llvm-project/lldb/source/Target/ThreadList.cpp @@ -245,14 +245,17 @@ bool ThreadList::ShouldStop(Event *event_ptr) { for (lldb::ThreadSP thread_sp : m_threads) { // This is an optimization... If we didn't let a thread run in between // the previous stop and this one, we shouldn't have to consult it for - // ShouldStop. So just leave it off the list we are going to inspect. On - // Linux, if a thread-specific conditional breakpoint was hit, it won't + // ShouldStop. So just leave it off the list we are going to inspect. + // If the thread didn't run but had work to do before declaring a public + // stop, then also include it. + // On Linux, if a thread-specific conditional breakpoint was hit, it won't // necessarily be the thread that hit the breakpoint itself that // evaluates the conditional expression, so the thread that hit the // breakpoint could still be asked to stop, even though it hasn't been // allowed to run since the previous stop. if (thread_sp->GetTemporaryResumeState() != eStateSuspended || - thread_sp->IsStillAtLastBreakpointHit()) + thread_sp->IsStillAtLastBreakpointHit() + || thread_sp->ShouldRunBeforePublicStop()) threads_copy.push_back(thread_sp); } @@ -300,6 +303,10 @@ bool ThreadList::ShouldStop(Event *event_ptr) { thread_sp->GetStopInfo(); } + // If a thread needs to finish some job that can be done just on this thread + // before broadcastion the stop, it will signal that by returning true for + // ShouldRunBeforePublicStop. This variable gathers the results from that. + bool a_thread_needs_to_run = false; for (pos = threads_copy.begin(); pos != end; ++pos) { ThreadSP thread_sp(*pos); @@ -329,11 +336,23 @@ bool ThreadList::ShouldStop(Event *event_ptr) { did_anybody_stop_for_a_reason |= thread_sp->ThreadStoppedForAReason(); const bool thread_should_stop = thread_sp->ShouldStop(event_ptr); + if (thread_should_stop) should_stop |= true; + else { + bool this_thread_forces_run = thread_sp->ShouldRunBeforePublicStop(); + a_thread_needs_to_run |= this_thread_forces_run; + if (this_thread_forces_run) + LLDB_LOG(log, + "ThreadList::{0} thread: {1:x}, " + "says it needs to run before public stop.", + __FUNCTION__, thread_sp->GetID()); + } } - if (!should_stop && !did_anybody_stop_for_a_reason) { + if (a_thread_needs_to_run) { + should_stop = false; + } else if (!should_stop && !did_anybody_stop_for_a_reason) { should_stop = true; LLDB_LOGF(log, "ThreadList::%s we stopped but no threads had a stop reason, " @@ -368,9 +387,17 @@ Vote ThreadList::ShouldReportStop(Event *event_ptr) { // Run through the threads and ask whether we should report this event. For // stopping, a YES vote wins over everything. A NO vote wins over NO - // opinion. + // opinion. The exception is if a thread has work it needs to force before + // a public stop, which overrides everyone else's opinion: for (pos = m_threads.begin(); pos != end; ++pos) { ThreadSP thread_sp(*pos); + if (thread_sp->ShouldRunBeforePublicStop()) { + LLDB_LOG(log, "Thread {0:x} has private business to complete, overrode " + "the should report stop.", thread_sp->GetID()); + result = eVoteNo; + break; + } + const Vote vote = thread_sp->ShouldReportStop(event_ptr); switch (vote) { case eVoteNoOpinion: @@ -550,7 +577,13 @@ bool ThreadList::WillResume() { run_me_only_list.SetStopID(m_process->GetStopID()); - bool run_only_current_thread = false; + // One or more threads might want to "Stop Others". We want to handle all + // those requests first. And if there is a thread that wanted to "resume + // before a public stop", let it get the first crack: + // There are two special kinds of thread that have priority for "StopOthers": + // a "ShouldRunBeforePublicStop thread, or the currently selected thread. If + // we find one satisfying that critereon, put it here. + ThreadSP stop_others_thread_sp; for (pos = m_threads.begin(); pos != end; ++pos) { ThreadSP thread_sp(*pos); @@ -562,17 +595,16 @@ bool ThreadList::WillResume() { // You can't say "stop others" and also want yourself to be suspended. assert(thread_sp->GetCurrentPlan()->RunState() != eStateSuspended); + run_me_only_list.AddThread(thread_sp); - if (thread_sp == GetSelectedThread()) { - // If the currently selected thread wants to run on its own, always let - // it. - run_only_current_thread = true; - run_me_only_list.Clear(); - run_me_only_list.AddThread(thread_sp); + if (thread_sp == GetSelectedThread()) + stop_others_thread_sp = thread_sp; + + if (thread_sp->ShouldRunBeforePublicStop()) { + // This takes precedence, so if we find one of these, service it: + stop_others_thread_sp = thread_sp; break; } - - run_me_only_list.AddThread(thread_sp); } } @@ -593,8 +625,8 @@ bool ThreadList::WillResume() { } else { ThreadSP thread_to_run; - if (run_only_current_thread) { - thread_to_run = GetSelectedThread(); + if (stop_others_thread_sp) { + thread_to_run = stop_others_thread_sp; } else if (run_me_only_list.GetSize(false) == 1) { thread_to_run = run_me_only_list.GetThreadAtIndex(0); } else { @@ -607,6 +639,9 @@ bool ThreadList::WillResume() { for (pos = m_threads.begin(); pos != end; ++pos) { ThreadSP thread_sp(*pos); if (thread_sp == thread_to_run) { + // Note, a thread might be able to fulfil it's plan w/o actually + // resuming. An example of this is a step that changes the current + // inlined function depth w/o moving the PC. Check that here: if (!thread_sp->ShouldResume(thread_sp->GetCurrentPlan()->RunState())) need_to_resume = false; } else @@ -624,7 +659,7 @@ void ThreadList::DidResume() { // Don't clear out threads that aren't going to get a chance to run, rather // leave their state for the next time around. ThreadSP thread_sp(*pos); - if (thread_sp->GetResumeState() != eStateSuspended) + if (thread_sp->GetTemporaryResumeState() != eStateSuspended) thread_sp->DidResume(); } } diff --git a/contrib/llvm-project/lldb/source/Target/ThreadPlanStack.cpp b/contrib/llvm-project/lldb/source/Target/ThreadPlanStack.cpp index ac7b44cef37d..157293142907 100644 --- a/contrib/llvm-project/lldb/source/Target/ThreadPlanStack.cpp +++ b/contrib/llvm-project/lldb/source/Target/ThreadPlanStack.cpp @@ -406,7 +406,7 @@ void ThreadPlanStackMap::Update(ThreadList ¤t_threads, for (auto thread : current_threads.Threads()) { lldb::tid_t cur_tid = thread->GetID(); if (!Find(cur_tid)) { - AddThread(*thread.get()); + AddThread(*thread); thread->QueueBasePlan(true); } } diff --git a/contrib/llvm-project/lldb/source/Target/ThreadPlanTracer.cpp b/contrib/llvm-project/lldb/source/Target/ThreadPlanTracer.cpp index 7e0925307644..82927ef64877 100644 --- a/contrib/llvm-project/lldb/source/Target/ThreadPlanTracer.cpp +++ b/contrib/llvm-project/lldb/source/Target/ThreadPlanTracer.cpp @@ -110,10 +110,10 @@ TypeFromUser ThreadPlanAssemblyTracer::GetIntPointerType() { LLDB_LOG_ERROR(GetLog(LLDBLog::Types), std::move(err), "Unable to get integer pointer type from TypeSystem"); } else { - m_intptr_type = TypeFromUser( - type_system_or_err->GetBuiltinTypeForEncodingAndBitSize( - eEncodingUint, - target_sp->GetArchitecture().GetAddressByteSize() * 8)); + if (auto ts = *type_system_or_err) + m_intptr_type = TypeFromUser(ts->GetBuiltinTypeForEncodingAndBitSize( + eEncodingUint, + target_sp->GetArchitecture().GetAddressByteSize() * 8)); } } } diff --git a/contrib/llvm-project/lldb/source/Target/Trace.cpp b/contrib/llvm-project/lldb/source/Target/Trace.cpp index ac832734b8d0..1ffd617a80fc 100644 --- a/contrib/llvm-project/lldb/source/Target/Trace.cpp +++ b/contrib/llvm-project/lldb/source/Target/Trace.cpp @@ -19,6 +19,7 @@ #include "lldb/Target/Thread.h" #include "lldb/Utility/LLDBLog.h" #include "lldb/Utility/Stream.h" +#include <optional> using namespace lldb; using namespace lldb_private; @@ -49,10 +50,10 @@ bool fromJSON(const Value &value, JSONSimpleTraceBundleDescription &bundle, /// limitations in move constructors. /// \{ template <typename K, typename V> -static Optional<V> Lookup(DenseMap<K, V> &map, K k) { +static std::optional<V> Lookup(DenseMap<K, V> &map, K k) { auto it = map.find(k); if (it == map.end()) - return None; + return std::nullopt; return it->second; } @@ -66,10 +67,11 @@ static V *LookupAsPtr(DenseMap<K, V> &map, K k) { /// Similar to the methods above but it looks for an item in a map of maps. template <typename K1, typename K2, typename V> -static Optional<V> Lookup(DenseMap<K1, DenseMap<K2, V>> &map, K1 k1, K2 k2) { +static std::optional<V> Lookup(DenseMap<K1, DenseMap<K2, V>> &map, K1 k1, + K2 k2) { auto it = map.find(k1); if (it == map.end()) - return None; + return std::nullopt; return Lookup(it->second, k2); } @@ -182,19 +184,20 @@ Expected<std::string> Trace::GetLiveProcessState() { return m_live_process->TraceGetState(GetPluginName()); } -Optional<uint64_t> Trace::GetLiveThreadBinaryDataSize(lldb::tid_t tid, - llvm::StringRef kind) { +std::optional<uint64_t> +Trace::GetLiveThreadBinaryDataSize(lldb::tid_t tid, llvm::StringRef kind) { Storage &storage = GetUpdatedStorage(); return Lookup(storage.live_thread_data, tid, ConstString(kind)); } -Optional<uint64_t> Trace::GetLiveCpuBinaryDataSize(lldb::cpu_id_t cpu_id, - llvm::StringRef kind) { +std::optional<uint64_t> Trace::GetLiveCpuBinaryDataSize(lldb::cpu_id_t cpu_id, + llvm::StringRef kind) { Storage &storage = GetUpdatedStorage(); return Lookup(storage.live_cpu_data_sizes, cpu_id, ConstString(kind)); } -Optional<uint64_t> Trace::GetLiveProcessBinaryDataSize(llvm::StringRef kind) { +std::optional<uint64_t> +Trace::GetLiveProcessBinaryDataSize(llvm::StringRef kind) { Storage &storage = GetUpdatedStorage(); return Lookup(storage.live_process_data, ConstString(kind)); } @@ -228,7 +231,7 @@ Trace::GetLiveTraceBinaryData(const TraceGetBinaryDataRequest &request, Expected<std::vector<uint8_t>> Trace::GetLiveThreadBinaryData(lldb::tid_t tid, llvm::StringRef kind) { - llvm::Optional<uint64_t> size = GetLiveThreadBinaryDataSize(tid, kind); + std::optional<uint64_t> size = GetLiveThreadBinaryDataSize(tid, kind); if (!size) return createStringError( inconvertibleErrorCode(), @@ -236,7 +239,7 @@ Trace::GetLiveThreadBinaryData(lldb::tid_t tid, llvm::StringRef kind) { kind.data(), tid); TraceGetBinaryDataRequest request{GetPluginName().str(), kind.str(), tid, - /*cpu_id=*/None}; + /*cpu_id=*/std::nullopt}; return GetLiveTraceBinaryData(request, *size); } @@ -246,7 +249,7 @@ Trace::GetLiveCpuBinaryData(lldb::cpu_id_t cpu_id, llvm::StringRef kind) { return createStringError( inconvertibleErrorCode(), "Attempted to fetch live cpu data without a live process."); - llvm::Optional<uint64_t> size = GetLiveCpuBinaryDataSize(cpu_id, kind); + std::optional<uint64_t> size = GetLiveCpuBinaryDataSize(cpu_id, kind); if (!size) return createStringError( inconvertibleErrorCode(), @@ -254,20 +257,21 @@ Trace::GetLiveCpuBinaryData(lldb::cpu_id_t cpu_id, llvm::StringRef kind) { kind.data(), cpu_id); TraceGetBinaryDataRequest request{GetPluginName().str(), kind.str(), - /*tid=*/None, cpu_id}; + /*tid=*/std::nullopt, cpu_id}; return m_live_process->TraceGetBinaryData(request); } Expected<std::vector<uint8_t>> Trace::GetLiveProcessBinaryData(llvm::StringRef kind) { - llvm::Optional<uint64_t> size = GetLiveProcessBinaryDataSize(kind); + std::optional<uint64_t> size = GetLiveProcessBinaryDataSize(kind); if (!size) return createStringError( inconvertibleErrorCode(), "Tracing data \"%s\" is not available for the process.", kind.data()); TraceGetBinaryDataRequest request{GetPluginName().str(), kind.str(), - /*tid=*/None, /*cpu_id*/ None}; + /*tid=*/std::nullopt, + /*cpu_id*/ std::nullopt}; return GetLiveTraceBinaryData(request, *size); } @@ -344,7 +348,7 @@ const char *Trace::RefreshLiveProcessState() { } Trace::Trace(ArrayRef<ProcessSP> postmortem_processes, - Optional<std::vector<lldb::cpu_id_t>> postmortem_cpus) { + std::optional<std::vector<lldb::cpu_id_t>> postmortem_cpus) { for (ProcessSP process_sp : postmortem_processes) m_storage.postmortem_processes.push_back(process_sp.get()); m_storage.cpus = postmortem_cpus; @@ -370,7 +374,7 @@ uint32_t Trace::GetStopID() { llvm::Expected<FileSpec> Trace::GetPostMortemThreadDataFile(lldb::tid_t tid, llvm::StringRef kind) { Storage &storage = GetUpdatedStorage(); - if (Optional<FileSpec> file = + if (std::optional<FileSpec> file = Lookup(storage.postmortem_thread_data, tid, ConstString(kind))) return *file; else @@ -383,7 +387,7 @@ Trace::GetPostMortemThreadDataFile(lldb::tid_t tid, llvm::StringRef kind) { llvm::Expected<FileSpec> Trace::GetPostMortemCpuDataFile(lldb::cpu_id_t cpu_id, llvm::StringRef kind) { Storage &storage = GetUpdatedStorage(); - if (Optional<FileSpec> file = + if (std::optional<FileSpec> file = Lookup(storage.postmortem_cpu_data, cpu_id, ConstString(kind))) return *file; else @@ -437,7 +441,7 @@ llvm::Error Trace::OnDataFileRead(FileSpec file, if (std::error_code err = trace_or_error.getError()) return createStringError( inconvertibleErrorCode(), "Failed fetching trace-related file %s. %s", - file.GetCString(), toString(errorCodeToError(err)).c_str()); + file.GetPath().c_str(), toString(errorCodeToError(err)).c_str()); MemoryBuffer &data = **trace_or_error; ArrayRef<uint8_t> array_ref( diff --git a/contrib/llvm-project/lldb/source/Target/TraceCursor.cpp b/contrib/llvm-project/lldb/source/Target/TraceCursor.cpp index de3f9bf1b33d..b85cc750a8a4 100644 --- a/contrib/llvm-project/lldb/source/Target/TraceCursor.cpp +++ b/contrib/llvm-project/lldb/source/Target/TraceCursor.cpp @@ -52,6 +52,8 @@ const char *TraceCursor::EventKindToString(lldb::TraceEvent event_kind) { return "CPU core changed"; case lldb::eTraceEventHWClockTick: return "HW clock tick"; + case lldb::eTraceEventSyncPoint: + return "trace synchronization point"; } llvm_unreachable("Fully covered switch above"); } diff --git a/contrib/llvm-project/lldb/source/Target/TraceDumper.cpp b/contrib/llvm-project/lldb/source/Target/TraceDumper.cpp index 5b71e9e4e97a..d059d443805c 100644 --- a/contrib/llvm-project/lldb/source/Target/TraceDumper.cpp +++ b/contrib/llvm-project/lldb/source/Target/TraceDumper.cpp @@ -7,34 +7,39 @@ //===----------------------------------------------------------------------===// #include "lldb/Target/TraceDumper.h" - #include "lldb/Core/Module.h" #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/Function.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Process.h" #include "lldb/Target/SectionLoadList.h" +#include <optional> using namespace lldb; using namespace lldb_private; using namespace llvm; /// \return -/// The given string or \b None if it's empty. -static Optional<const char *> ToOptionalString(const char *s) { +/// The given string or \b std::nullopt if it's empty. +static std::optional<const char *> ToOptionalString(const char *s) { if (!s) - return None; + return std::nullopt; return s; } + +static const char *GetModuleName(const SymbolContext &sc) { + if (!sc.module_sp) + return nullptr; + return sc.module_sp->GetFileSpec().GetFilename().AsCString(); +} + /// \return /// The module name (basename if the module is a file, or the actual name if /// it's a virtual module), or \b nullptr if no name nor module was found. static const char *GetModuleName(const TraceDumper::TraceItem &item) { - if (!item.symbol_info || !item.symbol_info->sc.module_sp) + if (!item.symbol_info) return nullptr; - return item.symbol_info->sc.module_sp->GetFileSpec() - .GetFilename() - .AsCString(); + return GetModuleName(item.symbol_info->sc); } // This custom LineEntry validator is neded because some line_entries have @@ -64,10 +69,12 @@ static bool FileLineAndColumnMatches(const LineEntry &a, const LineEntry &b) { /// - module /// - symbol /// - function -/// - line +/// - inlined function +/// - source line info static bool IsSameInstructionSymbolContext(const TraceDumper::SymbolInfo &prev_insn, - const TraceDumper::SymbolInfo &insn) { + const TraceDumper::SymbolInfo &insn, + bool check_source_line_info = true) { // module checks if (insn.sc.module_sp != prev_insn.sc.module_sp) return false; @@ -78,11 +85,23 @@ IsSameInstructionSymbolContext(const TraceDumper::SymbolInfo &prev_insn, // function checks if (!insn.sc.function && !prev_insn.sc.function) - return true; + return true; // This means two dangling instruction in the same module. We + // can assume they are part of the same unnamed symbol else if (insn.sc.function != prev_insn.sc.function) return false; + Block *inline_block_a = + insn.sc.block ? insn.sc.block->GetContainingInlinedBlock() : nullptr; + Block *inline_block_b = prev_insn.sc.block + ? prev_insn.sc.block->GetContainingInlinedBlock() + : nullptr; + if (inline_block_a != inline_block_b) + return false; + // line entry checks + if (!check_source_line_info) + return true; + const bool curr_line_valid = IsLineEntryValid(insn.sc.line_entry); const bool prev_line_valid = IsLineEntryValid(prev_insn.sc.line_entry); if (curr_line_valid && prev_line_valid) @@ -100,6 +119,14 @@ public: void NoMoreData() override { m_s << " no more data\n"; } + void FunctionCallForest( + const std::vector<TraceDumper::FunctionCallUP> &forest) override { + for (size_t i = 0; i < forest.size(); i++) { + m_s.Format("\n[call tree #{0}]\n", i); + DumpFunctionCallTree(*forest[i]); + } + } + void TraceItem(const TraceDumper::TraceItem &item) override { if (item.symbol_info) { if (!item.prev_symbol_info || @@ -148,6 +175,9 @@ public: case eTraceEventDisabledHW: case eTraceEventDisabledSW: break; + case eTraceEventSyncPoint: + m_s.Format(" [{0}]", item.sync_point_metadata); + break; } } else if (item.error) { m_s << "(error) " << *item.error; @@ -171,6 +201,78 @@ public: } private: + void + DumpSegmentContext(const TraceDumper::FunctionCall::TracedSegment &segment) { + if (segment.GetOwningCall().IsError()) { + m_s << "<tracing errors>"; + return; + } + + const SymbolContext &first_sc = segment.GetFirstInstructionSymbolInfo().sc; + first_sc.DumpStopContext( + &m_s, segment.GetFirstInstructionSymbolInfo().exe_ctx.GetTargetPtr(), + segment.GetFirstInstructionSymbolInfo().address, + /*show_fullpaths=*/false, + /*show_module=*/true, /*show_inlined_frames=*/false, + /*show_function_arguments=*/true, + /*show_function_name=*/true); + m_s << " to "; + const SymbolContext &last_sc = segment.GetLastInstructionSymbolInfo().sc; + if (IsLineEntryValid(first_sc.line_entry) && + IsLineEntryValid(last_sc.line_entry)) { + m_s.Format("{0}:{1}", last_sc.line_entry.line, last_sc.line_entry.column); + } else { + last_sc.DumpStopContext( + &m_s, segment.GetFirstInstructionSymbolInfo().exe_ctx.GetTargetPtr(), + segment.GetLastInstructionSymbolInfo().address, + /*show_fullpaths=*/false, + /*show_module=*/false, /*show_inlined_frames=*/false, + /*show_function_arguments=*/false, + /*show_function_name=*/false); + } + } + + void DumpUntracedContext(const TraceDumper::FunctionCall &function_call) { + if (function_call.IsError()) { + m_s << "tracing error"; + } + const SymbolContext &sc = function_call.GetSymbolInfo().sc; + + const char *module_name = GetModuleName(sc); + if (!module_name) + m_s << "(none)"; + else if (!sc.function && !sc.symbol) + m_s << module_name << "`(none)"; + else + m_s << module_name << "`" << sc.GetFunctionName().AsCString(); + } + + void DumpFunctionCallTree(const TraceDumper::FunctionCall &function_call) { + if (function_call.GetUntracedPrefixSegment()) { + m_s.Indent(); + DumpUntracedContext(function_call); + m_s << "\n"; + + m_s.IndentMore(); + DumpFunctionCallTree(function_call.GetUntracedPrefixSegment()->GetNestedCall()); + m_s.IndentLess(); + } + + for (const TraceDumper::FunctionCall::TracedSegment &segment : + function_call.GetTracedSegments()) { + m_s.Indent(); + DumpSegmentContext(segment); + m_s.Format(" [{0}, {1}]\n", segment.GetFirstInstructionID(), + segment.GetLastInstructionID()); + + segment.IfNestedCall([&](const TraceDumper::FunctionCall &nested_call) { + m_s.IndentMore(); + DumpFunctionCallTree(nested_call); + m_s.IndentLess(); + }); + } + } + Stream &m_s; TraceDumperOptions m_options; bool m_was_prev_instruction_an_error = false; @@ -192,6 +294,7 @@ class OutputWriterJSON : public TraceDumper::OutputWriter { "loadAddress": string decimal, "id": decimal, "hwClock"?: string decimal, + "syncPointMetadata"?: string, "timestamp_ns"?: string decimal, "module"?: string, "symbol"?: string, @@ -199,6 +302,7 @@ class OutputWriterJSON : public TraceDumper::OutputWriter { "column"?: decimal, "source"?: string, "mnemonic"?: string, + "controlFlowKind"?: string, } */ public: @@ -211,6 +315,43 @@ public: ~OutputWriterJSON() { m_j.arrayEnd(); } + void FunctionCallForest( + const std::vector<TraceDumper::FunctionCallUP> &forest) override { + for (size_t i = 0; i < forest.size(); i++) { + m_j.object([&] { DumpFunctionCallTree(*forest[i]); }); + } + } + + void DumpFunctionCallTree(const TraceDumper::FunctionCall &function_call) { + if (function_call.GetUntracedPrefixSegment()) { + m_j.attributeObject("untracedPrefixSegment", [&] { + m_j.attributeObject("nestedCall", [&] { + DumpFunctionCallTree( + function_call.GetUntracedPrefixSegment()->GetNestedCall()); + }); + }); + } + + if (!function_call.GetTracedSegments().empty()) { + m_j.attributeArray("tracedSegments", [&] { + for (const TraceDumper::FunctionCall::TracedSegment &segment : + function_call.GetTracedSegments()) { + m_j.object([&] { + m_j.attribute("firstInstructionId", + std::to_string(segment.GetFirstInstructionID())); + m_j.attribute("lastInstructionId", + std::to_string(segment.GetLastInstructionID())); + segment.IfNestedCall( + [&](const TraceDumper::FunctionCall &nested_call) { + m_j.attributeObject( + "nestedCall", [&] { DumpFunctionCallTree(nested_call); }); + }); + }); + } + }); + } + } + void DumpEvent(const TraceDumper::TraceItem &item) { m_j.attribute("event", TraceCursor::EventKindToString(*item.event)); switch (*item.event) { @@ -223,6 +364,9 @@ public: case eTraceEventDisabledHW: case eTraceEventDisabledSW: break; + case eTraceEventSyncPoint: + m_j.attribute("syncPointMetadata", item.sync_point_metadata); + break; } } @@ -234,10 +378,18 @@ public: "symbol", ToOptionalString(item.symbol_info->sc.GetFunctionName().AsCString())); - if (item.symbol_info->instruction) { + if (lldb::InstructionSP instruction = item.symbol_info->instruction) { + ExecutionContext exe_ctx = item.symbol_info->exe_ctx; m_j.attribute("mnemonic", - ToOptionalString(item.symbol_info->instruction->GetMnemonic( - &item.symbol_info->exe_ctx))); + ToOptionalString(instruction->GetMnemonic(&exe_ctx))); + if (m_options.show_control_flow_kind) { + lldb::InstructionControlFlowKind instruction_control_flow_kind = + instruction->GetControlFlowKind(&exe_ctx); + m_j.attribute("controlFlowKind", + ToOptionalString( + Instruction::GetNameForInstructionControlFlowKind( + instruction_control_flow_kind))); + } } if (IsLineEntryValid(item.symbol_info->sc.line_entry)) { @@ -256,9 +408,9 @@ public: m_j.attribute("id", item.id); if (m_options.show_timestamps) m_j.attribute("timestamp_ns", item.timestamp - ? Optional<std::string>( + ? std::optional<std::string>( std::to_string(*item.timestamp)) - : None); + : std::nullopt); if (item.event) { DumpEvent(item); @@ -286,32 +438,32 @@ CreateWriter(Stream &s, const TraceDumperOptions &options, Thread &thread) { new OutputWriterCLI(s, options, thread)); } -TraceDumper::TraceDumper(lldb::TraceCursorUP &&cursor_up, Stream &s, +TraceDumper::TraceDumper(lldb::TraceCursorSP cursor_sp, Stream &s, const TraceDumperOptions &options) - : m_cursor_up(std::move(cursor_up)), m_options(options), + : m_cursor_sp(std::move(cursor_sp)), m_options(options), m_writer_up(CreateWriter( - s, m_options, *m_cursor_up->GetExecutionContextRef().GetThreadSP())) { + s, m_options, *m_cursor_sp->GetExecutionContextRef().GetThreadSP())) { if (m_options.id) - m_cursor_up->GoToId(*m_options.id); + m_cursor_sp->GoToId(*m_options.id); else if (m_options.forwards) - m_cursor_up->Seek(0, TraceCursor::SeekType::Beginning); + m_cursor_sp->Seek(0, lldb::eTraceCursorSeekTypeBeginning); else - m_cursor_up->Seek(0, TraceCursor::SeekType::End); + m_cursor_sp->Seek(0, lldb::eTraceCursorSeekTypeEnd); - m_cursor_up->SetForwards(m_options.forwards); + m_cursor_sp->SetForwards(m_options.forwards); if (m_options.skip) { - m_cursor_up->Seek((m_options.forwards ? 1 : -1) * *m_options.skip, - TraceCursor::SeekType::Current); + m_cursor_sp->Seek((m_options.forwards ? 1 : -1) * *m_options.skip, + lldb::eTraceCursorSeekTypeCurrent); } } TraceDumper::TraceItem TraceDumper::CreatRawTraceItem() { TraceItem item = {}; - item.id = m_cursor_up->GetId(); + item.id = m_cursor_sp->GetId(); if (m_options.show_timestamps) - item.timestamp = m_cursor_up->GetWallClockTime(); + item.timestamp = m_cursor_sp->GetWallClockTime(); return item; } @@ -319,13 +471,12 @@ TraceDumper::TraceItem TraceDumper::CreatRawTraceItem() { /// instruction's symbol context when possible. static SymbolContext CalculateSymbolContext(const Address &address, - const TraceDumper::SymbolInfo &prev_symbol_info) { + const SymbolContext &prev_symbol_context) { AddressRange range; - if (prev_symbol_info.sc.GetAddressRange(eSymbolContextEverything, 0, - /*inline_block_range*/ false, - range) && + if (prev_symbol_context.GetAddressRange(eSymbolContextEverything, 0, + /*inline_block_range*/ true, range) && range.Contains(address)) - return prev_symbol_info.sc; + return prev_symbol_context; SymbolContext sc; address.CalculateSymbolContext(&sc, eSymbolContextEverything); @@ -368,59 +519,395 @@ CalculateDisass(const TraceDumper::SymbolInfo &symbol_info, : InstructionSP()); } -Optional<lldb::user_id_t> TraceDumper::DumpInstructions(size_t count) { - ThreadSP thread_sp = m_cursor_up->GetExecutionContextRef().GetThreadSP(); +static TraceDumper::SymbolInfo +CalculateSymbolInfo(const ExecutionContext &exe_ctx, lldb::addr_t load_address, + const TraceDumper::SymbolInfo &prev_symbol_info) { + TraceDumper::SymbolInfo symbol_info; + symbol_info.exe_ctx = exe_ctx; + symbol_info.address.SetLoadAddress(load_address, exe_ctx.GetTargetPtr()); + symbol_info.sc = + CalculateSymbolContext(symbol_info.address, prev_symbol_info.sc); + std::tie(symbol_info.disassembler, symbol_info.instruction) = + CalculateDisass(symbol_info, prev_symbol_info, exe_ctx); + return symbol_info; +} + +std::optional<lldb::user_id_t> TraceDumper::DumpInstructions(size_t count) { + ThreadSP thread_sp = m_cursor_sp->GetExecutionContextRef().GetThreadSP(); SymbolInfo prev_symbol_info; - Optional<lldb::user_id_t> last_id; + std::optional<lldb::user_id_t> last_id; ExecutionContext exe_ctx; thread_sp->GetProcess()->GetTarget().CalculateExecutionContext(exe_ctx); - for (size_t insn_seen = 0; insn_seen < count && m_cursor_up->HasValue(); - m_cursor_up->Next()) { + for (size_t insn_seen = 0; insn_seen < count && m_cursor_sp->HasValue(); + m_cursor_sp->Next()) { - last_id = m_cursor_up->GetId(); + last_id = m_cursor_sp->GetId(); TraceItem item = CreatRawTraceItem(); - if (m_cursor_up->IsEvent()) { - if (!m_options.show_events) - continue; - item.event = m_cursor_up->GetEventType(); + if (m_cursor_sp->IsEvent() && m_options.show_events) { + item.event = m_cursor_sp->GetEventType(); switch (*item.event) { case eTraceEventCPUChanged: - item.cpu_id = m_cursor_up->GetCPU(); + item.cpu_id = m_cursor_sp->GetCPU(); break; case eTraceEventHWClockTick: - item.hw_clock = m_cursor_up->GetHWClock(); + item.hw_clock = m_cursor_sp->GetHWClock(); break; case eTraceEventDisabledHW: case eTraceEventDisabledSW: break; + case eTraceEventSyncPoint: + item.sync_point_metadata = m_cursor_sp->GetSyncPointMetadata(); + break; } - } else if (m_cursor_up->IsError()) { - item.error = m_cursor_up->GetError(); - } else { + m_writer_up->TraceItem(item); + } else if (m_cursor_sp->IsError()) { + item.error = m_cursor_sp->GetError(); + m_writer_up->TraceItem(item); + } else if (m_cursor_sp->IsInstruction() && !m_options.only_events) { insn_seen++; - item.load_address = m_cursor_up->GetLoadAddress(); + item.load_address = m_cursor_sp->GetLoadAddress(); if (!m_options.raw) { - SymbolInfo symbol_info; - symbol_info.exe_ctx = exe_ctx; - symbol_info.address.SetLoadAddress(item.load_address, - exe_ctx.GetTargetPtr()); - symbol_info.sc = - CalculateSymbolContext(symbol_info.address, prev_symbol_info); - std::tie(symbol_info.disassembler, symbol_info.instruction) = - CalculateDisass(symbol_info, prev_symbol_info, exe_ctx); + SymbolInfo symbol_info = + CalculateSymbolInfo(exe_ctx, item.load_address, prev_symbol_info); item.prev_symbol_info = prev_symbol_info; item.symbol_info = symbol_info; prev_symbol_info = symbol_info; } + m_writer_up->TraceItem(item); } - m_writer_up->TraceItem(item); } - if (!m_cursor_up->HasValue()) + if (!m_cursor_sp->HasValue()) m_writer_up->NoMoreData(); return last_id; } + +void TraceDumper::FunctionCall::TracedSegment::AppendInsn( + const TraceCursorSP &cursor_sp, + const TraceDumper::SymbolInfo &symbol_info) { + m_last_insn_id = cursor_sp->GetId(); + m_last_symbol_info = symbol_info; +} + +lldb::user_id_t +TraceDumper::FunctionCall::TracedSegment::GetFirstInstructionID() const { + return m_first_insn_id; +} + +lldb::user_id_t +TraceDumper::FunctionCall::TracedSegment::GetLastInstructionID() const { + return m_last_insn_id; +} + +void TraceDumper::FunctionCall::TracedSegment::IfNestedCall( + std::function<void(const FunctionCall &function_call)> callback) const { + if (m_nested_call) + callback(*m_nested_call); +} + +const TraceDumper::FunctionCall & +TraceDumper::FunctionCall::TracedSegment::GetOwningCall() const { + return m_owning_call; +} + +TraceDumper::FunctionCall & +TraceDumper::FunctionCall::TracedSegment::CreateNestedCall( + const TraceCursorSP &cursor_sp, + const TraceDumper::SymbolInfo &symbol_info) { + m_nested_call = std::make_unique<FunctionCall>(cursor_sp, symbol_info); + m_nested_call->SetParentCall(m_owning_call); + return *m_nested_call; +} + +const TraceDumper::SymbolInfo & +TraceDumper::FunctionCall::TracedSegment::GetFirstInstructionSymbolInfo() + const { + return m_first_symbol_info; +} + +const TraceDumper::SymbolInfo & +TraceDumper::FunctionCall::TracedSegment::GetLastInstructionSymbolInfo() const { + return m_last_symbol_info; +} + +const TraceDumper::FunctionCall & +TraceDumper::FunctionCall::UntracedPrefixSegment::GetNestedCall() const { + return *m_nested_call; +} + +TraceDumper::FunctionCall::FunctionCall( + const TraceCursorSP &cursor_sp, + const TraceDumper::SymbolInfo &symbol_info) { + m_is_error = cursor_sp->IsError(); + AppendSegment(cursor_sp, symbol_info); +} + +void TraceDumper::FunctionCall::AppendSegment( + const TraceCursorSP &cursor_sp, + const TraceDumper::SymbolInfo &symbol_info) { + m_traced_segments.emplace_back(cursor_sp, symbol_info, *this); +} + +const TraceDumper::SymbolInfo & +TraceDumper::FunctionCall::GetSymbolInfo() const { + return m_traced_segments.back().GetLastInstructionSymbolInfo(); +} + +bool TraceDumper::FunctionCall::IsError() const { return m_is_error; } + +const std::deque<TraceDumper::FunctionCall::TracedSegment> & +TraceDumper::FunctionCall::GetTracedSegments() const { + return m_traced_segments; +} + +TraceDumper::FunctionCall::TracedSegment & +TraceDumper::FunctionCall::GetLastTracedSegment() { + return m_traced_segments.back(); +} + +const std::optional<TraceDumper::FunctionCall::UntracedPrefixSegment> & +TraceDumper::FunctionCall::GetUntracedPrefixSegment() const { + return m_untraced_prefix_segment; +} + +void TraceDumper::FunctionCall::SetUntracedPrefixSegment( + TraceDumper::FunctionCallUP &&nested_call) { + m_untraced_prefix_segment.emplace(std::move(nested_call)); +} + +TraceDumper::FunctionCall *TraceDumper::FunctionCall::GetParentCall() const { + return m_parent_call; +} + +void TraceDumper::FunctionCall::SetParentCall( + TraceDumper::FunctionCall &parent_call) { + m_parent_call = &parent_call; +} + +/// Given an instruction that happens after a return, find the ancestor function +/// call that owns it. If this ancestor doesn't exist, create a new ancestor and +/// make it the root of the tree. +/// +/// \param[in] last_function_call +/// The function call that performs the return. +/// +/// \param[in] symbol_info +/// The symbol information of the instruction after the return. +/// +/// \param[in] cursor_sp +/// The cursor pointing to the instruction after the return. +/// +/// \param[in,out] roots +/// The object owning the roots. It might be modified if a new root needs to +/// be created. +/// +/// \return +/// A reference to the function call that owns the new instruction +static TraceDumper::FunctionCall &AppendReturnedInstructionToFunctionCallForest( + TraceDumper::FunctionCall &last_function_call, + const TraceDumper::SymbolInfo &symbol_info, const TraceCursorSP &cursor_sp, + std::vector<TraceDumper::FunctionCallUP> &roots) { + + // We omit the current node because we can't return to itself. + TraceDumper::FunctionCall *ancestor = last_function_call.GetParentCall(); + + for (; ancestor; ancestor = ancestor->GetParentCall()) { + // This loop traverses the tree until it finds a call that we can return to. + if (IsSameInstructionSymbolContext(ancestor->GetSymbolInfo(), symbol_info, + /*check_source_line_info=*/false)) { + // We returned to this symbol, so we are assuming we are returning there + // Note: If this is not robust enough, we should actually check if we + // returning to the instruction that follows the last instruction from + // that call, as that's the behavior of CALL instructions. + ancestor->AppendSegment(cursor_sp, symbol_info); + return *ancestor; + } + } + + // We didn't find the call we were looking for, so we now create a synthetic + // one that will contain the new instruction in its first traced segment. + TraceDumper::FunctionCallUP new_root = + std::make_unique<TraceDumper::FunctionCall>(cursor_sp, symbol_info); + // This new root will own the previous root through an untraced prefix segment. + new_root->SetUntracedPrefixSegment(std::move(roots.back())); + roots.pop_back(); + // We update the roots container to point to the new root + roots.emplace_back(std::move(new_root)); + return *roots.back(); +} + +/// Append an instruction to a function call forest. The new instruction might +/// be appended to the current segment, to a new nest call, or return to an +/// ancestor call. +/// +/// \param[in] exe_ctx +/// The exeuction context of the traced thread. +/// +/// \param[in] last_function_call +/// The chronologically most recent function call before the new instruction. +/// +/// \param[in] prev_symbol_info +/// The symbol information of the previous instruction in the trace. +/// +/// \param[in] symbol_info +/// The symbol information of the new instruction. +/// +/// \param[in] cursor_sp +/// The cursor pointing to the new instruction. +/// +/// \param[in,out] roots +/// The object owning the roots. It might be modified if a new root needs to +/// be created. +/// +/// \return +/// A reference to the function call that owns the new instruction. +static TraceDumper::FunctionCall &AppendInstructionToFunctionCallForest( + const ExecutionContext &exe_ctx, + TraceDumper::FunctionCall *last_function_call, + const TraceDumper::SymbolInfo &prev_symbol_info, + const TraceDumper::SymbolInfo &symbol_info, const TraceCursorSP &cursor_sp, + std::vector<TraceDumper::FunctionCallUP> &roots) { + if (!last_function_call || last_function_call->IsError()) { + // We create a brand new root + roots.emplace_back( + std::make_unique<TraceDumper::FunctionCall>(cursor_sp, symbol_info)); + return *roots.back(); + } + + AddressRange range; + if (symbol_info.sc.GetAddressRange( + eSymbolContextBlock | eSymbolContextFunction | eSymbolContextSymbol, + 0, /*inline_block_range*/ true, range)) { + if (range.GetBaseAddress() == symbol_info.address) { + // Our instruction is the first instruction of a function. This has + // to be a call. This should also identify if a trampoline or the linker + // is making a call using a non-CALL instruction. + return last_function_call->GetLastTracedSegment().CreateNestedCall( + cursor_sp, symbol_info); + } + } + if (IsSameInstructionSymbolContext(prev_symbol_info, symbol_info, + /*check_source_line_info=*/false)) { + // We are still in the same function. This can't be a call because otherwise + // we would be in the first instruction of the symbol. + last_function_call->GetLastTracedSegment().AppendInsn(cursor_sp, + symbol_info); + return *last_function_call; + } + // Now we are in a different symbol. Let's see if this is a return or a + // call + const InstructionSP &insn = last_function_call->GetLastTracedSegment() + .GetLastInstructionSymbolInfo() + .instruction; + InstructionControlFlowKind insn_kind = + insn ? insn->GetControlFlowKind(&exe_ctx) + : eInstructionControlFlowKindOther; + + switch (insn_kind) { + case lldb::eInstructionControlFlowKindCall: + case lldb::eInstructionControlFlowKindFarCall: { + // This is a regular call + return last_function_call->GetLastTracedSegment().CreateNestedCall( + cursor_sp, symbol_info); + } + case lldb::eInstructionControlFlowKindFarReturn: + case lldb::eInstructionControlFlowKindReturn: { + // We should have caught most trampolines and linker functions earlier, so + // let's assume this is a regular return. + return AppendReturnedInstructionToFunctionCallForest( + *last_function_call, symbol_info, cursor_sp, roots); + } + default: + // we changed symbols not using a call or return and we are not in the + // beginning of a symbol, so this should be something very artificial + // or maybe a jump to some label in the middle of it section. + + // We first check if it's a return from an inline method + if (prev_symbol_info.sc.block && + prev_symbol_info.sc.block->GetContainingInlinedBlock()) { + return AppendReturnedInstructionToFunctionCallForest( + *last_function_call, symbol_info, cursor_sp, roots); + } + // Now We assume it's a call. We should revisit this in the future. + // Ideally we should be able to decide whether to create a new tree, + // or go deeper or higher in the stack. + return last_function_call->GetLastTracedSegment().CreateNestedCall( + cursor_sp, symbol_info); + } +} + +/// Append an error to a function call forest. The new error might be appended +/// to the current segment if it contains errors or will create a new root. +/// +/// \param[in] last_function_call +/// The chronologically most recent function call before the new error. +/// +/// \param[in] cursor_sp +/// The cursor pointing to the new error. +/// +/// \param[in,out] roots +/// The object owning the roots. It might be modified if a new root needs to +/// be created. +/// +/// \return +/// A reference to the function call that owns the new error. +TraceDumper::FunctionCall &AppendErrorToFunctionCallForest( + TraceDumper::FunctionCall *last_function_call, TraceCursorSP &cursor_sp, + std::vector<TraceDumper::FunctionCallUP> &roots) { + if (last_function_call && last_function_call->IsError()) { + last_function_call->GetLastTracedSegment().AppendInsn( + cursor_sp, TraceDumper::SymbolInfo{}); + return *last_function_call; + } else { + roots.emplace_back(std::make_unique<TraceDumper::FunctionCall>( + cursor_sp, TraceDumper::SymbolInfo{})); + return *roots.back(); + } +} + +static std::vector<TraceDumper::FunctionCallUP> +CreateFunctionCallForest(TraceCursorSP &cursor_sp, + const ExecutionContext &exe_ctx) { + + std::vector<TraceDumper::FunctionCallUP> roots; + TraceDumper::SymbolInfo prev_symbol_info; + + TraceDumper::FunctionCall *last_function_call = nullptr; + + for (; cursor_sp->HasValue(); cursor_sp->Next()) { + if (cursor_sp->IsError()) { + last_function_call = &AppendErrorToFunctionCallForest(last_function_call, + cursor_sp, roots); + prev_symbol_info = {}; + } else if (cursor_sp->IsInstruction()) { + TraceDumper::SymbolInfo symbol_info = CalculateSymbolInfo( + exe_ctx, cursor_sp->GetLoadAddress(), prev_symbol_info); + + last_function_call = &AppendInstructionToFunctionCallForest( + exe_ctx, last_function_call, prev_symbol_info, symbol_info, cursor_sp, + roots); + prev_symbol_info = symbol_info; + } else if (cursor_sp->GetEventType() == eTraceEventCPUChanged) { + // TODO: In case of a CPU change, we create a new root because we haven't + // investigated yet if a call tree can safely continue or if interrupts + // could have polluted the original call tree. + last_function_call = nullptr; + prev_symbol_info = {}; + } + } + + return roots; +} + +void TraceDumper::DumpFunctionCalls() { + ThreadSP thread_sp = m_cursor_sp->GetExecutionContextRef().GetThreadSP(); + ExecutionContext exe_ctx; + thread_sp->GetProcess()->GetTarget().CalculateExecutionContext(exe_ctx); + + m_writer_up->FunctionCallForest( + CreateFunctionCallForest(m_cursor_sp, exe_ctx)); +} diff --git a/contrib/llvm-project/lldb/source/Target/UnixSignals.cpp b/contrib/llvm-project/lldb/source/Target/UnixSignals.cpp index 3ece3ee24cbe..858b1691f318 100644 --- a/contrib/llvm-project/lldb/source/Target/UnixSignals.cpp +++ b/contrib/llvm-project/lldb/source/Target/UnixSignals.cpp @@ -13,6 +13,7 @@ #include "Plugins/Process/Utility/NetBSDSignals.h" #include "lldb/Host/HostInfo.h" #include "lldb/Utility/ArchSpec.h" +#include <optional> using namespace lldb_private; using namespace llvm; @@ -285,9 +286,9 @@ int32_t UnixSignals::GetSignalAtIndex(int32_t index) const { uint64_t UnixSignals::GetVersion() const { return m_version; } std::vector<int32_t> -UnixSignals::GetFilteredSignals(llvm::Optional<bool> should_suppress, - llvm::Optional<bool> should_stop, - llvm::Optional<bool> should_notify) { +UnixSignals::GetFilteredSignals(std::optional<bool> should_suppress, + std::optional<bool> should_stop, + std::optional<bool> should_notify) { std::vector<int32_t> result; for (int32_t signo = GetFirstSignalNumber(); signo != LLDB_INVALID_SIGNAL_NUMBER; @@ -300,13 +301,13 @@ UnixSignals::GetFilteredSignals(llvm::Optional<bool> should_suppress, // If any of filtering conditions are not met, we move on to the next // signal. - if (should_suppress && signal_suppress != should_suppress.value()) + if (should_suppress && signal_suppress != *should_suppress) continue; - if (should_stop && signal_stop != should_stop.value()) + if (should_stop && signal_stop != *should_stop) continue; - if (should_notify && signal_notify != should_notify.value()) + if (should_notify && signal_notify != *should_notify) continue; result.push_back(signo); diff --git a/contrib/llvm-project/lldb/source/Utility/ArchSpec.cpp b/contrib/llvm-project/lldb/source/Utility/ArchSpec.cpp index a99aed82bc88..e1d7ee3ee276 100644 --- a/contrib/llvm-project/lldb/source/Utility/ArchSpec.cpp +++ b/contrib/llvm-project/lldb/source/Utility/ArchSpec.cpp @@ -16,6 +16,7 @@ #include "llvm/BinaryFormat/COFF.h" #include "llvm/BinaryFormat/ELF.h" #include "llvm/BinaryFormat/MachO.h" +#include "llvm/Support/ARMTargetParser.h" #include "llvm/Support/Compiler.h" using namespace lldb; @@ -220,6 +221,11 @@ static const CoreDefinition g_core_definitions[] = { {eByteOrderLittle, 8, 2, 4, llvm::Triple::riscv64, ArchSpec::eCore_riscv64, "riscv64"}, + {eByteOrderLittle, 4, 4, 4, llvm::Triple::loongarch32, + ArchSpec::eCore_loongarch32, "loongarch32"}, + {eByteOrderLittle, 8, 4, 4, llvm::Triple::loongarch64, + ArchSpec::eCore_loongarch64, "loongarch64"}, + {eByteOrderLittle, 4, 4, 4, llvm::Triple::UnknownArch, ArchSpec::eCore_uknownMach32, "unknown-mach-32"}, {eByteOrderLittle, 8, 4, 4, llvm::Triple::UnknownArch, @@ -255,13 +261,13 @@ struct ArchDefinition { }; void ArchSpec::ListSupportedArchNames(StringList &list) { - for (uint32_t i = 0; i < llvm::array_lengthof(g_core_definitions); ++i) - list.AppendString(g_core_definitions[i].name); + for (const auto &def : g_core_definitions) + list.AppendString(def.name); } void ArchSpec::AutoComplete(CompletionRequest &request) { - for (uint32_t i = 0; i < llvm::array_lengthof(g_core_definitions); ++i) - request.TryCompleteCurrentArg(g_core_definitions[i].name); + for (const auto &def : g_core_definitions) + request.TryCompleteCurrentArg(def.name); } #define CPU_ANY (UINT32_MAX) @@ -340,9 +346,9 @@ static const ArchDefinitionEntry g_macho_arch_entries[] = { {ArchSpec::eCore_uknownMach64, llvm::MachO::CPU_ARCH_ABI64, 0, 0xFF000000u, 0x00000000u}}; // clang-format on -static const ArchDefinition g_macho_arch_def = { - eArchTypeMachO, llvm::array_lengthof(g_macho_arch_entries), - g_macho_arch_entries, "mach-o"}; +static const ArchDefinition g_macho_arch_def = {eArchTypeMachO, + std::size(g_macho_arch_entries), + g_macho_arch_entries, "mach-o"}; //===----------------------------------------------------------------------===// // A table that gets searched linearly for matches. This table is used to @@ -406,11 +412,17 @@ static const ArchDefinitionEntry g_elf_arch_entries[] = { ArchSpec::eRISCVSubType_riscv32, 0xFFFFFFFFu, 0xFFFFFFFFu}, // riscv32 {ArchSpec::eCore_riscv64, llvm::ELF::EM_RISCV, ArchSpec::eRISCVSubType_riscv64, 0xFFFFFFFFu, 0xFFFFFFFFu}, // riscv64 + {ArchSpec::eCore_loongarch32, llvm::ELF::EM_LOONGARCH, + ArchSpec::eLoongArchSubType_loongarch32, 0xFFFFFFFFu, + 0xFFFFFFFFu}, // loongarch32 + {ArchSpec::eCore_loongarch64, llvm::ELF::EM_LOONGARCH, + ArchSpec::eLoongArchSubType_loongarch64, 0xFFFFFFFFu, + 0xFFFFFFFFu}, // loongarch64 }; static const ArchDefinition g_elf_arch_def = { eArchTypeELF, - llvm::array_lengthof(g_elf_arch_entries), + std::size(g_elf_arch_entries), g_elf_arch_entries, "elf", }; @@ -436,7 +448,7 @@ static const ArchDefinitionEntry g_coff_arch_entries[] = { static const ArchDefinition g_coff_arch_def = { eArchTypeCOFF, - llvm::array_lengthof(g_coff_arch_entries), + std::size(g_coff_arch_entries), g_coff_arch_entries, "pe-coff", }; @@ -446,16 +458,12 @@ static const ArchDefinition g_coff_arch_def = { static const ArchDefinition *g_arch_definitions[] = { &g_macho_arch_def, &g_elf_arch_def, &g_coff_arch_def}; -static const size_t k_num_arch_definitions = - llvm::array_lengthof(g_arch_definitions); - //===----------------------------------------------------------------------===// // Static helper functions. // Get the architecture definition for a given object type. static const ArchDefinition *FindArchDefinition(ArchitectureType arch_type) { - for (unsigned int i = 0; i < k_num_arch_definitions; ++i) { - const ArchDefinition *def = g_arch_definitions[i]; + for (const ArchDefinition *def : g_arch_definitions) { if (def->type == arch_type) return def; } @@ -464,15 +472,15 @@ static const ArchDefinition *FindArchDefinition(ArchitectureType arch_type) { // Get an architecture definition by name. static const CoreDefinition *FindCoreDefinition(llvm::StringRef name) { - for (unsigned int i = 0; i < llvm::array_lengthof(g_core_definitions); ++i) { - if (name.equals_insensitive(g_core_definitions[i].name)) - return &g_core_definitions[i]; + for (const auto &def : g_core_definitions) { + if (name.equals_insensitive(def.name)) + return &def; } return nullptr; } static inline const CoreDefinition *FindCoreDefinition(ArchSpec::Core core) { - if (core < llvm::array_lengthof(g_core_definitions)) + if (core < std::size(g_core_definitions)) return &g_core_definitions[core]; return nullptr; } @@ -583,7 +591,6 @@ void ArchSpec::SetFlags(const std::string &elf_abi) { std::string ArchSpec::GetClangTargetCPU() const { std::string cpu; - if (IsMIPS()) { switch (m_core) { case ArchSpec::eCore_mips32: @@ -630,6 +637,9 @@ std::string ArchSpec::GetClangTargetCPU() const { break; } } + + if (GetTriple().isARM()) + cpu = llvm::ARM::getARMCPUForArch(GetTriple(), "").str(); return cpu; } @@ -928,14 +938,6 @@ uint32_t ArchSpec::GetMaximumOpcodeByteSize() const { return 0; } -bool ArchSpec::IsExactMatch(const ArchSpec &rhs) const { - return IsEqualTo(rhs, true); -} - -bool ArchSpec::IsCompatibleMatch(const ArchSpec &rhs) const { - return IsEqualTo(rhs, false); -} - static bool IsCompatibleEnvironment(llvm::Triple::EnvironmentType lhs, llvm::Triple::EnvironmentType rhs) { if (lhs == rhs) @@ -967,11 +969,11 @@ static bool IsCompatibleEnvironment(llvm::Triple::EnvironmentType lhs, return false; } -bool ArchSpec::IsEqualTo(const ArchSpec &rhs, bool exact_match) const { +bool ArchSpec::IsMatch(const ArchSpec &rhs, MatchType match) const { // explicitly ignoring m_distribution_id in this method. if (GetByteOrder() != rhs.GetByteOrder() || - !cores_match(GetCore(), rhs.GetCore(), true, exact_match)) + !cores_match(GetCore(), rhs.GetCore(), true, match == ExactMatch)) return false; const llvm::Triple &lhs_triple = GetTriple(); @@ -988,7 +990,7 @@ bool ArchSpec::IsEqualTo(const ArchSpec &rhs, bool exact_match) const { // On Windows, the vendor field doesn't have any practical effect, but // it is often set to either "pc" or "w64". if ((lhs_triple_vendor != rhs_triple_vendor) && - (exact_match || !both_windows)) { + (match == ExactMatch || !both_windows)) { const bool rhs_vendor_specified = rhs.TripleVendorWasSpecified(); const bool lhs_vendor_specified = TripleVendorWasSpecified(); // Both architectures had the vendor specified, so if they aren't equal @@ -1007,7 +1009,7 @@ bool ArchSpec::IsEqualTo(const ArchSpec &rhs, bool exact_match) const { const llvm::Triple::EnvironmentType rhs_triple_env = rhs_triple.getEnvironment(); - if (!exact_match) { + if (match == CompatibleMatch) { // x86_64-apple-ios-macabi, x86_64-apple-macosx are compatible, no match. if ((lhs_triple_os == llvm::Triple::IOS && lhs_triple_env == llvm::Triple::MacABI && @@ -1034,12 +1036,13 @@ bool ArchSpec::IsEqualTo(const ArchSpec &rhs, bool exact_match) const { return false; // If the pair of os+env is both unspecified, match any other os+env combo. - if (!exact_match && ((!lhs_os_specified && !lhs_triple.hasEnvironment()) || - (!rhs_os_specified && !rhs_triple.hasEnvironment()))) + if (match == CompatibleMatch && + ((!lhs_os_specified && !lhs_triple.hasEnvironment()) || + (!rhs_os_specified && !rhs_triple.hasEnvironment()))) return true; } - if (!exact_match && both_windows) + if (match == CompatibleMatch && both_windows) return true; // The Windows environments (MSVC vs GNU) are compatible return IsCompatibleEnvironment(lhs_triple_env, rhs_triple_env); @@ -1090,7 +1093,7 @@ static bool cores_match(const ArchSpec::Core core1, const ArchSpec::Core core2, case ArchSpec::eCore_arm_generic: if (enforce_exact_match) break; - LLVM_FALLTHROUGH; + [[fallthrough]]; case ArchSpec::kCore_arm_any: if (core2 >= ArchSpec::kCore_arm_first && core2 <= ArchSpec::kCore_arm_last) return true; @@ -1478,15 +1481,3 @@ void ArchSpec::DumpTriple(llvm::raw_ostream &s) const { if (!environ_str.empty()) s << "-" << environ_str; } - -void llvm::yaml::ScalarTraits<ArchSpec>::output(const ArchSpec &Val, void *, - raw_ostream &Out) { - Val.DumpTriple(Out); -} - -llvm::StringRef -llvm::yaml::ScalarTraits<ArchSpec>::input(llvm::StringRef Scalar, void *, - ArchSpec &Val) { - Val = ArchSpec(Scalar); - return {}; -} diff --git a/contrib/llvm-project/lldb/source/Utility/Args.cpp b/contrib/llvm-project/lldb/source/Utility/Args.cpp index daccb91d8436..2d50b43bc241 100644 --- a/contrib/llvm-project/lldb/source/Utility/Args.cpp +++ b/contrib/llvm-project/lldb/source/Utility/Args.cpp @@ -215,7 +215,12 @@ bool Args::GetCommandString(std::string &command) const { for (size_t i = 0; i < m_entries.size(); ++i) { if (i > 0) command += ' '; + char quote = m_entries[i].quote; + if (quote != '\0') + command += quote; command += m_entries[i].ref(); + if (quote != '\0') + command += quote; } return !m_entries.empty(); @@ -307,7 +312,7 @@ void Args::AppendArguments(const char **argv) { assert(m_argv.size() == m_entries.size() + 1); assert(m_argv.back() == nullptr); m_argv.pop_back(); - for (auto arg : llvm::makeArrayRef(argv, argc)) { + for (auto arg : llvm::ArrayRef(argv, argc)) { m_entries.emplace_back(arg, '\0'); m_argv.push_back(m_entries.back().data()); } @@ -353,7 +358,7 @@ void Args::DeleteArgumentAtIndex(size_t idx) { void Args::SetArguments(size_t argc, const char **argv) { Clear(); - auto args = llvm::makeArrayRef(argv, argc); + auto args = llvm::ArrayRef(argv, argc); m_entries.resize(argc); m_argv.resize(argc + 1); for (size_t i = 0; i < args.size(); ++i) { @@ -682,20 +687,3 @@ void OptionsWithRaw::SetFromString(llvm::StringRef arg_string) { if (!found_suffix) m_suffix = std::string(original_args); } - -void llvm::yaml::MappingTraits<Args::ArgEntry>::mapping(IO &io, - Args::ArgEntry &v) { - MappingNormalization<NormalizedArgEntry, Args::ArgEntry> keys(io, v); - io.mapRequired("value", keys->value); - io.mapRequired("quote", keys->quote); -} - -void llvm::yaml::MappingTraits<Args>::mapping(IO &io, Args &v) { - io.mapRequired("entries", v.m_entries); - - // Recompute m_argv vector. - v.m_argv.clear(); - for (auto &entry : v.m_entries) - v.m_argv.push_back(entry.data()); - v.m_argv.push_back(nullptr); -} diff --git a/contrib/llvm-project/lldb/source/Utility/ConstString.cpp b/contrib/llvm-project/lldb/source/Utility/ConstString.cpp index 142c335ddbbe..7b084769e1ff 100644 --- a/contrib/llvm-project/lldb/source/Utility/ConstString.cpp +++ b/contrib/llvm-project/lldb/source/Utility/ConstString.cpp @@ -335,15 +335,3 @@ void llvm::format_provider<ConstString>::format(const ConstString &CS, llvm::StringRef Options) { format_provider<StringRef>::format(CS.GetStringRef(), OS, Options); } - -void llvm::yaml::ScalarTraits<ConstString>::output(const ConstString &Val, - void *, raw_ostream &Out) { - Out << Val.GetStringRef(); -} - -llvm::StringRef -llvm::yaml::ScalarTraits<ConstString>::input(llvm::StringRef Scalar, void *, - ConstString &Val) { - Val = ConstString(Scalar); - return {}; -} diff --git a/contrib/llvm-project/lldb/source/Utility/Diagnostics.cpp b/contrib/llvm-project/lldb/source/Utility/Diagnostics.cpp new file mode 100644 index 000000000000..a59750167cf7 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Utility/Diagnostics.cpp @@ -0,0 +1,107 @@ +//===-- Diagnostics.cpp ---------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lldb/Utility/Diagnostics.h" +#include "lldb/Utility/LLDBAssert.h" + +#include "llvm/Support/Error.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/raw_ostream.h" +#include <optional> + +using namespace lldb_private; +using namespace lldb; +using namespace llvm; + +static constexpr size_t g_num_log_messages = 100; + +void Diagnostics::Initialize() { + lldbassert(!InstanceImpl() && "Already initialized."); + InstanceImpl().emplace(); +} + +void Diagnostics::Terminate() { + lldbassert(InstanceImpl() && "Already terminated."); + InstanceImpl().reset(); +} + +bool Diagnostics::Enabled() { return InstanceImpl().operator bool(); } + +std::optional<Diagnostics> &Diagnostics::InstanceImpl() { + static std::optional<Diagnostics> g_diagnostics; + return g_diagnostics; +} + +Diagnostics &Diagnostics::Instance() { return *InstanceImpl(); } + +Diagnostics::Diagnostics() : m_log_handler(g_num_log_messages) {} + +Diagnostics::~Diagnostics() {} + +void Diagnostics::AddCallback(Callback callback) { + std::lock_guard<std::mutex> guard(m_callbacks_mutex); + m_callbacks.push_back(callback); +} + +bool Diagnostics::Dump(raw_ostream &stream) { + Expected<FileSpec> diagnostics_dir = CreateUniqueDirectory(); + if (!diagnostics_dir) { + stream << "unable to create diagnostic dir: " + << toString(diagnostics_dir.takeError()) << '\n'; + return false; + } + + return Dump(stream, *diagnostics_dir); +} + +bool Diagnostics::Dump(raw_ostream &stream, const FileSpec &dir) { + stream << "LLDB diagnostics will be written to " << dir.GetPath() << "\n"; + stream << "Please include the directory content when filing a bug report\n"; + + if (Error error = Create(dir)) { + stream << toString(std::move(error)) << '\n'; + return false; + } + + return true; +} + +llvm::Expected<FileSpec> Diagnostics::CreateUniqueDirectory() { + SmallString<128> diagnostics_dir; + std::error_code ec = + sys::fs::createUniqueDirectory("diagnostics", diagnostics_dir); + if (ec) + return errorCodeToError(ec); + return FileSpec(diagnostics_dir.str()); +} + +Error Diagnostics::Create(const FileSpec &dir) { + if (Error err = DumpDiangosticsLog(dir)) + return err; + + for (Callback c : m_callbacks) { + if (Error err = c(dir)) + return err; + } + + return Error::success(); +} + +llvm::Error Diagnostics::DumpDiangosticsLog(const FileSpec &dir) const { + FileSpec log_file = dir.CopyByAppendingPathComponent("diagnostics.log"); + std::error_code ec; + llvm::raw_fd_ostream stream(log_file.GetPath(), ec, llvm::sys::fs::OF_None); + if (ec) + return errorCodeToError(ec); + m_log_handler.Dump(stream); + return Error::success(); +} + +void Diagnostics::Report(llvm::StringRef message) { + m_log_handler.Emit(message); +} diff --git a/contrib/llvm-project/lldb/source/Utility/Event.cpp b/contrib/llvm-project/lldb/source/Utility/Event.cpp index 4c07293c92df..5fca61b16df8 100644 --- a/contrib/llvm-project/lldb/source/Utility/Event.cpp +++ b/contrib/llvm-project/lldb/source/Utility/Event.cpp @@ -124,9 +124,7 @@ ConstString EventDataBytes::GetFlavor() const { } void EventDataBytes::Dump(Stream *s) const { - size_t num_printable_chars = - std::count_if(m_bytes.begin(), m_bytes.end(), llvm::isPrint); - if (num_printable_chars == m_bytes.size()) + if (llvm::all_of(m_bytes, llvm::isPrint)) s->Format("\"{0}\"", m_bytes); else s->Format("{0:$[ ]@[x-2]}", llvm::make_range( diff --git a/contrib/llvm-project/lldb/source/Utility/FileSpec.cpp b/contrib/llvm-project/lldb/source/Utility/FileSpec.cpp index c0dbc29bcd1f..7ff57307dec5 100644 --- a/contrib/llvm-project/lldb/source/Utility/FileSpec.cpp +++ b/contrib/llvm-project/lldb/source/Utility/FileSpec.cpp @@ -21,6 +21,7 @@ #include "llvm/Support/raw_ostream.h" #include <algorithm> +#include <optional> #include <system_error> #include <vector> @@ -170,9 +171,7 @@ void FileSpec::SetFile(llvm::StringRef pathname) { SetFile(pathname, m_style); } // up into a directory and filename and stored as uniqued string values for // quick comparison and efficient memory usage. void FileSpec::SetFile(llvm::StringRef pathname, Style style) { - m_filename.Clear(); - m_directory.Clear(); - m_is_resolved = false; + Clear(); m_style = (style == Style::native) ? GetNativeStyle() : style; if (pathname.empty()) @@ -259,6 +258,7 @@ Stream &lldb_private::operator<<(Stream &s, const FileSpec &f) { void FileSpec::Clear() { m_directory.Clear(); m_filename.Clear(); + PathWasModified(); } // Compare two FileSpec objects. If "full" is true, then both the directory and @@ -305,7 +305,8 @@ bool FileSpec::Match(const FileSpec &pattern, const FileSpec &file) { return true; } -llvm::Optional<FileSpec::Style> FileSpec::GuessPathStyle(llvm::StringRef absolute_path) { +std::optional<FileSpec::Style> +FileSpec::GuessPathStyle(llvm::StringRef absolute_path) { if (absolute_path.startswith("/")) return Style::posix; if (absolute_path.startswith(R"(\\)")) @@ -314,7 +315,7 @@ llvm::Optional<FileSpec::Style> FileSpec::GuessPathStyle(llvm::StringRef absolut (absolute_path.substr(1, 2) == R"(:\)" || absolute_path.substr(1, 2) == R"(:/)")) return Style::windows; - return llvm::None; + return std::nullopt; } // Dump the object to the supplied stream. If the object contains a valid @@ -330,17 +331,35 @@ void FileSpec::Dump(llvm::raw_ostream &s) const { FileSpec::Style FileSpec::GetPathStyle() const { return m_style; } -// Directory string get accessor. -ConstString &FileSpec::GetDirectory() { return m_directory; } +void FileSpec::SetDirectory(ConstString directory) { + m_directory = directory; + PathWasModified(); +} -// Directory string const get accessor. -ConstString FileSpec::GetDirectory() const { return m_directory; } +void FileSpec::SetDirectory(llvm::StringRef directory) { + m_directory = ConstString(directory); + PathWasModified(); +} -// Filename string get accessor. -ConstString &FileSpec::GetFilename() { return m_filename; } +void FileSpec::SetFilename(ConstString filename) { + m_filename = filename; + PathWasModified(); +} -// Filename string const get accessor. -ConstString FileSpec::GetFilename() const { return m_filename; } +void FileSpec::SetFilename(llvm::StringRef filename) { + m_filename = ConstString(filename); + PathWasModified(); +} + +void FileSpec::ClearFilename() { + m_filename.Clear(); + PathWasModified(); +} + +void FileSpec::ClearDirectory() { + m_directory.Clear(); + PathWasModified(); +} // Extract the directory and path into a fixed buffer. This is needed as the // directory and path are stored in separate string values. @@ -360,8 +379,8 @@ std::string FileSpec::GetPath(bool denormalize) const { return static_cast<std::string>(result); } -const char *FileSpec::GetCString(bool denormalize) const { - return ConstString{GetPath(denormalize)}.AsCString(nullptr); +ConstString FileSpec::GetPathAsConstString(bool denormalize) const { + return ConstString{GetPath(denormalize)}; } void FileSpec::GetPath(llvm::SmallVectorImpl<char> &path, @@ -476,18 +495,22 @@ bool FileSpec::IsRelative() const { } bool FileSpec::IsAbsolute() const { - llvm::SmallString<64> current_path; - GetPath(current_path, false); + // Check if we have cached if this path is absolute to avoid recalculating. + if (m_absolute != Absolute::Calculate) + return m_absolute == Absolute::Yes; - // Early return if the path is empty. - if (current_path.empty()) - return false; + m_absolute = Absolute::No; - // We consider paths starting with ~ to be absolute. - if (current_path[0] == '~') - return true; + llvm::SmallString<64> path; + GetPath(path, false); - return llvm::sys::path::is_absolute(current_path, m_style); + if (!path.empty()) { + // We consider paths starting with ~ to be absolute. + if (path[0] == '~' || llvm::sys::path::is_absolute(path, m_style)) + m_absolute = Absolute::Yes; + } + + return m_absolute == Absolute::Yes; } void FileSpec::MakeAbsolute(const FileSpec &dir) { @@ -536,19 +559,3 @@ void llvm::format_provider<FileSpec>::format(const FileSpec &F, if (!file.empty()) Stream << file; } - -void llvm::yaml::ScalarEnumerationTraits<FileSpecStyle>::enumeration( - IO &io, FileSpecStyle &value) { - io.enumCase(value, "windows", FileSpecStyle(FileSpec::Style::windows)); - io.enumCase(value, "posix", FileSpecStyle(FileSpec::Style::posix)); - io.enumCase(value, "native", FileSpecStyle(FileSpec::Style::native)); -} - -void llvm::yaml::MappingTraits<FileSpec>::mapping(IO &io, FileSpec &f) { - io.mapRequired("directory", f.m_directory); - io.mapRequired("file", f.m_filename); - io.mapRequired("resolved", f.m_is_resolved); - FileSpecStyle style = f.m_style; - io.mapRequired("style", style); - f.m_style = style; -} diff --git a/contrib/llvm-project/lldb/source/Utility/GDBRemote.cpp b/contrib/llvm-project/lldb/source/Utility/GDBRemote.cpp index 91f94de4dc0d..276b1276f4e6 100644 --- a/contrib/llvm-project/lldb/source/Utility/GDBRemote.cpp +++ b/contrib/llvm-project/lldb/source/Utility/GDBRemote.cpp @@ -14,7 +14,6 @@ #include <cstdio> using namespace lldb; -using namespace lldb_private::repro; using namespace lldb_private; using namespace llvm; @@ -62,99 +61,3 @@ void GDBRemotePacket::Dump(Stream &strm) const { strm.Printf("tid=0x%4.4" PRIx64 " <%4u> %s packet: %s\n", tid, bytes_transmitted, GetTypeStr().data(), packet.data.c_str()); } - -void yaml::ScalarEnumerationTraits<GDBRemotePacket::Type>::enumeration( - IO &io, GDBRemotePacket::Type &value) { - io.enumCase(value, "Invalid", GDBRemotePacket::ePacketTypeInvalid); - io.enumCase(value, "Send", GDBRemotePacket::ePacketTypeSend); - io.enumCase(value, "Recv", GDBRemotePacket::ePacketTypeRecv); -} - -void yaml::ScalarTraits<GDBRemotePacket::BinaryData>::output( - const GDBRemotePacket::BinaryData &Val, void *, raw_ostream &Out) { - Out << toHex(Val.data); -} - -StringRef yaml::ScalarTraits<GDBRemotePacket::BinaryData>::input( - StringRef Scalar, void *, GDBRemotePacket::BinaryData &Val) { - Val.data = fromHex(Scalar); - return {}; -} - -void yaml::MappingTraits<GDBRemotePacket>::mapping(IO &io, - GDBRemotePacket &Packet) { - io.mapRequired("packet", Packet.packet); - io.mapRequired("type", Packet.type); - io.mapRequired("bytes", Packet.bytes_transmitted); - io.mapRequired("index", Packet.packet_idx); - io.mapRequired("tid", Packet.tid); -} - -StringRef -yaml::MappingTraits<GDBRemotePacket>::validate(IO &io, - GDBRemotePacket &Packet) { - return {}; -} - -void GDBRemoteProvider::Keep() { - std::vector<std::string> files; - for (auto &recorder : m_packet_recorders) { - files.push_back(recorder->GetFilename().GetPath()); - } - - FileSpec file = GetRoot().CopyByAppendingPathComponent(Info::file); - std::error_code ec; - llvm::raw_fd_ostream os(file.GetPath(), ec, llvm::sys::fs::OF_TextWithCRLF); - if (ec) - return; - yaml::Output yout(os); - yout << files; -} - -void GDBRemoteProvider::Discard() { m_packet_recorders.clear(); } - -llvm::Expected<std::unique_ptr<PacketRecorder>> -PacketRecorder::Create(const FileSpec &filename) { - std::error_code ec; - auto recorder = std::make_unique<PacketRecorder>(std::move(filename), ec); - if (ec) - return llvm::errorCodeToError(ec); - return std::move(recorder); -} - -PacketRecorder *GDBRemoteProvider::GetNewPacketRecorder() { - std::size_t i = m_packet_recorders.size() + 1; - std::string filename = (llvm::Twine(Info::name) + llvm::Twine("-") + - llvm::Twine(i) + llvm::Twine(".yaml")) - .str(); - auto recorder_or_error = - PacketRecorder::Create(GetRoot().CopyByAppendingPathComponent(filename)); - if (!recorder_or_error) { - llvm::consumeError(recorder_or_error.takeError()); - return nullptr; - } - - m_packet_recorders.push_back(std::move(*recorder_or_error)); - return m_packet_recorders.back().get(); -} - -void PacketRecorder::Record(const GDBRemotePacket &packet) { - if (!m_record) - return; - yaml::Output yout(m_os); - yout << const_cast<GDBRemotePacket &>(packet); - m_os.flush(); -} - -llvm::raw_ostream *GDBRemoteProvider::GetHistoryStream() { - FileSpec history_file = GetRoot().CopyByAppendingPathComponent(Info::file); - - std::error_code EC; - m_stream_up = std::make_unique<raw_fd_ostream>( - history_file.GetPath(), EC, sys::fs::OpenFlags::OF_TextWithCRLF); - return m_stream_up.get(); -} - -char GDBRemoteProvider::ID = 0; -const char *GDBRemoteProvider::Info::file = "gdb-remote.yaml"; -const char *GDBRemoteProvider::Info::name = "gdb-remote"; diff --git a/contrib/llvm-project/lldb/source/Utility/Listener.cpp b/contrib/llvm-project/lldb/source/Utility/Listener.cpp index d756e70deda4..8bb55f93bbf8 100644 --- a/contrib/llvm-project/lldb/source/Utility/Listener.cpp +++ b/contrib/llvm-project/lldb/source/Utility/Listener.cpp @@ -11,7 +11,6 @@ #include "lldb/Utility/ConstString.h" #include "lldb/Utility/Event.h" #include "lldb/Utility/LLDBLog.h" -#include "llvm/ADT/Optional.h" #include <algorithm> #include <memory> diff --git a/contrib/llvm-project/lldb/source/Utility/Log.cpp b/contrib/llvm-project/lldb/source/Utility/Log.cpp index 67edb15ba684..045e0f2cb68a 100644 --- a/contrib/llvm-project/lldb/source/Utility/Log.cpp +++ b/contrib/llvm-project/lldb/source/Utility/Log.cpp @@ -60,13 +60,14 @@ void Log::ListCategories(llvm::raw_ostream &stream, }); } -uint32_t Log::GetFlags(llvm::raw_ostream &stream, const ChannelMap::value_type &entry, - llvm::ArrayRef<const char *> categories) { +Log::MaskType Log::GetFlags(llvm::raw_ostream &stream, + const ChannelMap::value_type &entry, + llvm::ArrayRef<const char *> categories) { bool list_categories = false; - uint32_t flags = 0; + Log::MaskType flags = 0; for (const char *category : categories) { if (llvm::StringRef("all").equals_insensitive(category)) { - flags |= UINT32_MAX; + flags |= std::numeric_limits<Log::MaskType>::max(); continue; } if (llvm::StringRef("default").equals_insensitive(category)) { @@ -91,7 +92,7 @@ uint32_t Log::GetFlags(llvm::raw_ostream &stream, const ChannelMap::value_type & } void Log::Enable(const std::shared_ptr<LogHandler> &handler_sp, - uint32_t options, uint32_t flags) { + uint32_t options, Log::MaskType flags) { llvm::sys::ScopedWriter lock(m_mutex); MaskType mask = m_mask.fetch_or(flags, std::memory_order_relaxed); @@ -102,7 +103,7 @@ void Log::Enable(const std::shared_ptr<LogHandler> &handler_sp, } } -void Log::Disable(uint32_t flags) { +void Log::Disable(Log::MaskType flags) { llvm::sys::ScopedWriter lock(m_mutex); MaskType mask = m_mask.fetch_and(~flags, std::memory_order_relaxed); @@ -126,7 +127,7 @@ const Flags Log::GetOptions() const { return m_options.load(std::memory_order_relaxed); } -const Flags Log::GetMask() const { +Log::MaskType Log::GetMask() const { return m_mask.load(std::memory_order_relaxed); } @@ -203,7 +204,7 @@ void Log::Register(llvm::StringRef name, Channel &channel) { void Log::Unregister(llvm::StringRef name) { auto iter = g_channel_map->find(name); assert(iter != g_channel_map->end()); - iter->second.Disable(UINT32_MAX); + iter->second.Disable(std::numeric_limits<MaskType>::max()); g_channel_map->erase(iter); } @@ -216,7 +217,7 @@ bool Log::EnableLogChannel(const std::shared_ptr<LogHandler> &log_handler_sp, error_stream << llvm::formatv("Invalid log channel '{0}'.\n", channel); return false; } - uint32_t flags = categories.empty() + MaskType flags = categories.empty() ? iter->second.m_channel.default_flags : GetFlags(error_stream, *iter, categories); iter->second.Enable(log_handler_sp, log_options, flags); @@ -231,8 +232,8 @@ bool Log::DisableLogChannel(llvm::StringRef channel, error_stream << llvm::formatv("Invalid log channel '{0}'.\n", channel); return false; } - uint32_t flags = categories.empty() - ? UINT32_MAX + MaskType flags = categories.empty() + ? std::numeric_limits<MaskType>::max() : GetFlags(error_stream, *iter, categories); iter->second.Disable(flags); return true; @@ -267,7 +268,7 @@ bool Log::ListChannelCategories(llvm::StringRef channel, void Log::DisableAllLogChannels() { for (auto &entry : *g_channel_map) - entry.second.Disable(UINT32_MAX); + entry.second.Disable(std::numeric_limits<MaskType>::max()); } void Log::ForEachChannelCategory( diff --git a/contrib/llvm-project/lldb/source/Utility/LoongArch_DWARF_Registers.h b/contrib/llvm-project/lldb/source/Utility/LoongArch_DWARF_Registers.h new file mode 100644 index 000000000000..34e40a066051 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Utility/LoongArch_DWARF_Registers.h @@ -0,0 +1,177 @@ +//===-- LoongArch_DWARF_Registers.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_SOURCE_UTILITY_LOONGARCH_DWARF_REGISTERS_H +#define LLDB_SOURCE_UTILITY_LOONGARCH_DWARF_REGISTERS_H + +#include "lldb/lldb-private.h" + +namespace loongarch_dwarf { + +enum { + dwarf_gpr_r0 = 0, + dwarf_gpr_r1, + dwarf_gpr_r2, + dwarf_gpr_r3, + dwarf_gpr_r4, + dwarf_gpr_r5, + dwarf_gpr_r6, + dwarf_gpr_r7, + dwarf_gpr_r8, + dwarf_gpr_r9, + dwarf_gpr_r10, + dwarf_gpr_r11, + dwarf_gpr_r12, + dwarf_gpr_r13, + dwarf_gpr_r14, + dwarf_gpr_r15, + dwarf_gpr_r16, + dwarf_gpr_r17, + dwarf_gpr_r18, + dwarf_gpr_r19, + dwarf_gpr_r20, + dwarf_gpr_r21, + dwarf_gpr_r22, + dwarf_gpr_r23, + dwarf_gpr_r24, + dwarf_gpr_r25, + dwarf_gpr_r26, + dwarf_gpr_r27, + dwarf_gpr_r28, + dwarf_gpr_r29, + dwarf_gpr_r30, + dwarf_gpr_r31 = 31, + + dwarf_gpr_orig_a0, + dwarf_gpr_pc, + dwarf_gpr_badv, + + dwarf_gpr_reserved0 = 35, + dwarf_gpr_reserved1, + dwarf_gpr_reserved2, + dwarf_gpr_reserved3, + dwarf_gpr_reserved4, + dwarf_gpr_reserved5, + dwarf_gpr_reserved6, + dwarf_gpr_reserved7, + dwarf_gpr_reserved8, + dwarf_gpr_reserved9, + + dwarf_fpr_f0 = 45, + dwarf_fpr_f1, + dwarf_fpr_f2, + dwarf_fpr_f3, + dwarf_fpr_f4, + dwarf_fpr_f5, + dwarf_fpr_f6, + dwarf_fpr_f7, + dwarf_fpr_f8, + dwarf_fpr_f9, + dwarf_fpr_f10, + dwarf_fpr_f11, + dwarf_fpr_f12, + dwarf_fpr_f13, + dwarf_fpr_f14, + dwarf_fpr_f15, + dwarf_fpr_f16, + dwarf_fpr_f17, + dwarf_fpr_f18, + dwarf_fpr_f19, + dwarf_fpr_f20, + dwarf_fpr_f21, + dwarf_fpr_f22, + dwarf_fpr_f23, + dwarf_fpr_f24, + dwarf_fpr_f25, + dwarf_fpr_f26, + dwarf_fpr_f27, + dwarf_fpr_f28, + dwarf_fpr_f29, + dwarf_fpr_f30, + dwarf_fpr_f31 = 76, + + dwarf_fpr_fcc0, + dwarf_fpr_fcc1, + dwarf_fpr_fcc2, + dwarf_fpr_fcc3, + dwarf_fpr_fcc4, + dwarf_fpr_fcc5, + dwarf_fpr_fcc6, + dwarf_fpr_fcc7, + dwarf_fpr_fcsr, + + // register name alias + dwarf_gpr_zero = dwarf_gpr_r0, + dwarf_gpr_ra = dwarf_gpr_r1, + dwarf_gpr_tp = dwarf_gpr_r2, + dwarf_gpr_sp = dwarf_gpr_r3, + dwarf_gpr_a0 = dwarf_gpr_r4, + dwarf_gpr_a1 = dwarf_gpr_r5, + dwarf_gpr_a2 = dwarf_gpr_r6, + dwarf_gpr_a3 = dwarf_gpr_r7, + dwarf_gpr_a4 = dwarf_gpr_r8, + dwarf_gpr_a5 = dwarf_gpr_r9, + dwarf_gpr_a6 = dwarf_gpr_r10, + dwarf_gpr_a7 = dwarf_gpr_r11, + dwarf_gpr_t0 = dwarf_gpr_r12, + dwarf_gpr_t1 = dwarf_gpr_r13, + dwarf_gpr_t2 = dwarf_gpr_r14, + dwarf_gpr_t3 = dwarf_gpr_r15, + dwarf_gpr_t4 = dwarf_gpr_r16, + dwarf_gpr_t5 = dwarf_gpr_r17, + dwarf_gpr_t6 = dwarf_gpr_r18, + dwarf_gpr_t7 = dwarf_gpr_r19, + dwarf_gpr_t8 = dwarf_gpr_r20, + dwarf_gpr_fp = dwarf_gpr_r22, + dwarf_gpr_s0 = dwarf_gpr_r23, + dwarf_gpr_s1 = dwarf_gpr_r24, + dwarf_gpr_s2 = dwarf_gpr_r25, + dwarf_gpr_s3 = dwarf_gpr_r26, + dwarf_gpr_s4 = dwarf_gpr_r27, + dwarf_gpr_s5 = dwarf_gpr_r28, + dwarf_gpr_s6 = dwarf_gpr_r29, + dwarf_gpr_s7 = dwarf_gpr_r30, + dwarf_gpr_s8 = dwarf_gpr_r31, + + dwarf_fpr_fa0 = dwarf_fpr_f0, + dwarf_fpr_fa1 = dwarf_fpr_f1, + dwarf_fpr_fa2 = dwarf_fpr_f2, + dwarf_fpr_fa3 = dwarf_fpr_f3, + dwarf_fpr_fa4 = dwarf_fpr_f4, + dwarf_fpr_fa5 = dwarf_fpr_f5, + dwarf_fpr_fa6 = dwarf_fpr_f6, + dwarf_fpr_fa7 = dwarf_fpr_f7, + dwarf_fpr_ft0 = dwarf_fpr_f8, + dwarf_fpr_ft1 = dwarf_fpr_f9, + dwarf_fpr_ft2 = dwarf_fpr_f10, + dwarf_fpr_ft3 = dwarf_fpr_f11, + dwarf_fpr_ft4 = dwarf_fpr_f12, + dwarf_fpr_ft5 = dwarf_fpr_f13, + dwarf_fpr_ft6 = dwarf_fpr_f14, + dwarf_fpr_ft7 = dwarf_fpr_f15, + dwarf_fpr_ft8 = dwarf_fpr_f16, + dwarf_fpr_ft9 = dwarf_fpr_f17, + dwarf_fpr_ft10 = dwarf_fpr_f18, + dwarf_fpr_ft11 = dwarf_fpr_f19, + dwarf_fpr_ft12 = dwarf_fpr_f20, + dwarf_fpr_ft13 = dwarf_fpr_f21, + dwarf_fpr_ft14 = dwarf_fpr_f22, + dwarf_fpr_ft15 = dwarf_fpr_f23, + dwarf_fpr_fs0 = dwarf_fpr_f24, + dwarf_fpr_fs1 = dwarf_fpr_f25, + dwarf_fpr_fs2 = dwarf_fpr_f26, + dwarf_fpr_fs3 = dwarf_fpr_f27, + dwarf_fpr_fs4 = dwarf_fpr_f28, + dwarf_fpr_fs5 = dwarf_fpr_f29, + dwarf_fpr_fs6 = dwarf_fpr_f30, + dwarf_fpr_fs7 = dwarf_fpr_f31, +}; + +} // namespace loongarch_dwarf + +#endif // LLDB_SOURCE_UTILITY_LOONGARCH_DWARF_REGISTERS_H diff --git a/contrib/llvm-project/lldb/source/Utility/ProcessInfo.cpp b/contrib/llvm-project/lldb/source/Utility/ProcessInfo.cpp index 3b094294ffaa..8e27a17d8337 100644 --- a/contrib/llvm-project/lldb/source/Utility/ProcessInfo.cpp +++ b/contrib/llvm-project/lldb/source/Utility/ProcessInfo.cpp @@ -9,17 +9,16 @@ #include "lldb/Utility/ProcessInfo.h" #include "lldb/Utility/ArchSpec.h" -#include "lldb/Utility/ReproducerProvider.h" #include "lldb/Utility/Stream.h" #include "lldb/Utility/StreamString.h" #include "lldb/Utility/UserIDResolver.h" #include "llvm/ADT/SmallString.h" #include <climits> +#include <optional> using namespace lldb; using namespace lldb_private; -using namespace lldb_private::repro; ProcessInfo::ProcessInfo() : m_executable(), m_arguments(), m_environment(), m_arch() {} @@ -194,7 +193,7 @@ void ProcessInstanceInfo::DumpAsTableRow(Stream &s, UserIDResolver &resolver, auto print = [&](bool (ProcessInstanceInfo::*isValid)() const, uint32_t (ProcessInstanceInfo::*getID)() const, - llvm::Optional<llvm::StringRef> (UserIDResolver::*getName)( + std::optional<llvm::StringRef> (UserIDResolver::*getName)( UserIDResolver::id_t id)) { const char *format = "{0,-10} "; if (!(this->*isValid)()) { @@ -332,45 +331,3 @@ void ProcessInstanceInfoMatch::Clear() { m_name_match_type = NameMatch::Ignore; m_match_all_users = false; } - -void llvm::yaml::MappingTraits<ProcessInstanceInfo>::mapping( - IO &io, ProcessInstanceInfo &Info) { - io.mapRequired("executable", Info.m_executable); - io.mapRequired("arg0", Info.m_arg0); - io.mapRequired("args", Info.m_arguments); - io.mapRequired("arch", Info.m_arch); - io.mapRequired("uid", Info.m_uid); - io.mapRequired("gid", Info.m_gid); - io.mapRequired("pid", Info.m_pid); - io.mapRequired("effective-uid", Info.m_euid); - io.mapRequired("effective-gid", Info.m_egid); - io.mapRequired("parent-pid", Info.m_parent_pid); -} - - -llvm::Optional<ProcessInstanceInfoList> -repro::GetReplayProcessInstanceInfoList() { - static std::unique_ptr<repro::MultiLoader<repro::ProcessInfoProvider>> - loader = repro::MultiLoader<repro::ProcessInfoProvider>::Create( - repro::Reproducer::Instance().GetLoader()); - - if (!loader) - return {}; - - llvm::Optional<std::string> nextfile = loader->GetNextFile(); - if (!nextfile) - return {}; - - auto error_or_file = llvm::MemoryBuffer::getFile(*nextfile); - if (std::error_code err = error_or_file.getError()) - return {}; - - ProcessInstanceInfoList infos; - llvm::yaml::Input yin((*error_or_file)->getBuffer()); - yin >> infos; - - if (auto err = yin.error()) - return {}; - - return infos; -} diff --git a/contrib/llvm-project/lldb/source/Utility/RISCV_DWARF_Registers.h b/contrib/llvm-project/lldb/source/Utility/RISCV_DWARF_Registers.h new file mode 100644 index 000000000000..b7fc9d913e33 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Utility/RISCV_DWARF_Registers.h @@ -0,0 +1,195 @@ +//===-- RISCV_DWARF_Registers.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_SOURCE_UTILITY_RISCV_DWARF_REGISTERS_H +#define LLDB_SOURCE_UTILITY_RISCV_DWARF_REGISTERS_H + +#include "lldb/lldb-private.h" + +namespace riscv_dwarf { + +enum { + dwarf_gpr_x0 = 0, + dwarf_gpr_x1, + dwarf_gpr_x2, + dwarf_gpr_x3, + dwarf_gpr_x4, + dwarf_gpr_x5, + dwarf_gpr_x6, + dwarf_gpr_x7, + dwarf_gpr_x8, + dwarf_gpr_x9, + dwarf_gpr_x10, + dwarf_gpr_x11, + dwarf_gpr_x12, + dwarf_gpr_x13, + dwarf_gpr_x14, + dwarf_gpr_x15, + dwarf_gpr_x16, + dwarf_gpr_x17, + dwarf_gpr_x18, + dwarf_gpr_x19, + dwarf_gpr_x20, + dwarf_gpr_x21, + dwarf_gpr_x22, + dwarf_gpr_x23, + dwarf_gpr_x24, + dwarf_gpr_x25, + dwarf_gpr_x26, + dwarf_gpr_x27, + dwarf_gpr_x28, + dwarf_gpr_x29, + dwarf_gpr_x30, + dwarf_gpr_x31 = 31, + + dwarf_fpr_f0 = 32, + dwarf_fpr_f1, + dwarf_fpr_f2, + dwarf_fpr_f3, + dwarf_fpr_f4, + dwarf_fpr_f5, + dwarf_fpr_f6, + dwarf_fpr_f7, + dwarf_fpr_f8, + dwarf_fpr_f9, + dwarf_fpr_f10, + dwarf_fpr_f11, + dwarf_fpr_f12, + dwarf_fpr_f13, + dwarf_fpr_f14, + dwarf_fpr_f15, + dwarf_fpr_f16, + dwarf_fpr_f17, + dwarf_fpr_f18, + dwarf_fpr_f19, + dwarf_fpr_f20, + dwarf_fpr_f21, + dwarf_fpr_f22, + dwarf_fpr_f23, + dwarf_fpr_f24, + dwarf_fpr_f25, + dwarf_fpr_f26, + dwarf_fpr_f27, + dwarf_fpr_f28, + dwarf_fpr_f29, + dwarf_fpr_f30, + dwarf_fpr_f31 = 63, + + // alternate frame return column + dwarf_alt_fr_col = 64, + + dwarf_v0 = 96, + dwarf_v1, + dwarf_v2, + dwarf_v3, + dwarf_v4, + dwarf_v5, + dwarf_v6, + dwarf_v7, + dwarf_v8, + dwarf_v9, + dwarf_v10, + dwarf_v11, + dwarf_v12, + dwarf_v13, + dwarf_v14, + dwarf_v15, + dwarf_v16, + dwarf_v17, + dwarf_v18, + dwarf_v19, + dwarf_v20, + dwarf_v21, + dwarf_v22, + dwarf_v23, + dwarf_v24, + dwarf_v25, + dwarf_v26, + dwarf_v27, + dwarf_v28, + dwarf_v29, + dwarf_v30, + dwarf_v31 = 127, + dwarf_first_csr = 4096, + dwarf_fpr_fcsr = dwarf_first_csr + 0x003, + dwarf_last_csr = 8191, + + // register ABI name + dwarf_gpr_zero = dwarf_gpr_x0, + dwarf_gpr_ra = dwarf_gpr_x1, + dwarf_gpr_sp = dwarf_gpr_x2, + dwarf_gpr_gp = dwarf_gpr_x3, + dwarf_gpr_tp = dwarf_gpr_x4, + dwarf_gpr_t0 = dwarf_gpr_x5, + dwarf_gpr_t1 = dwarf_gpr_x6, + dwarf_gpr_t2 = dwarf_gpr_x7, + dwarf_gpr_fp = dwarf_gpr_x8, + dwarf_gpr_s1 = dwarf_gpr_x9, + dwarf_gpr_a0 = dwarf_gpr_x10, + dwarf_gpr_a1 = dwarf_gpr_x11, + dwarf_gpr_a2 = dwarf_gpr_x12, + dwarf_gpr_a3 = dwarf_gpr_x13, + dwarf_gpr_a4 = dwarf_gpr_x14, + dwarf_gpr_a5 = dwarf_gpr_x15, + dwarf_gpr_a6 = dwarf_gpr_x16, + dwarf_gpr_a7 = dwarf_gpr_x17, + dwarf_gpr_s2 = dwarf_gpr_x18, + dwarf_gpr_s3 = dwarf_gpr_x19, + dwarf_gpr_s4 = dwarf_gpr_x20, + dwarf_gpr_s5 = dwarf_gpr_x21, + dwarf_gpr_s6 = dwarf_gpr_x22, + dwarf_gpr_s7 = dwarf_gpr_x23, + dwarf_gpr_s8 = dwarf_gpr_x24, + dwarf_gpr_s9 = dwarf_gpr_x25, + dwarf_gpr_s10 = dwarf_gpr_x26, + dwarf_gpr_s11 = dwarf_gpr_x27, + dwarf_gpr_t3 = dwarf_gpr_x28, + dwarf_gpr_t4 = dwarf_gpr_x29, + dwarf_gpr_t5 = dwarf_gpr_x30, + dwarf_gpr_t6 = dwarf_gpr_x31, + + dwarf_fpr_ft0 = dwarf_fpr_f0, + dwarf_fpr_ft1 = dwarf_fpr_f1, + dwarf_fpr_ft2 = dwarf_fpr_f2, + dwarf_fpr_ft3 = dwarf_fpr_f3, + dwarf_fpr_ft4 = dwarf_fpr_f4, + dwarf_fpr_ft5 = dwarf_fpr_f5, + dwarf_fpr_ft6 = dwarf_fpr_f6, + dwarf_fpr_ft7 = dwarf_fpr_f7, + dwarf_fpr_fs0 = dwarf_fpr_f8, + dwarf_fpr_fs1 = dwarf_fpr_f9, + dwarf_fpr_fa0 = dwarf_fpr_f10, + dwarf_fpr_fa1 = dwarf_fpr_f11, + dwarf_fpr_fa2 = dwarf_fpr_f12, + dwarf_fpr_fa3 = dwarf_fpr_f13, + dwarf_fpr_fa4 = dwarf_fpr_f14, + dwarf_fpr_fa5 = dwarf_fpr_f15, + dwarf_fpr_fa6 = dwarf_fpr_f16, + dwarf_fpr_fa7 = dwarf_fpr_f17, + dwarf_fpr_fs2 = dwarf_fpr_f18, + dwarf_fpr_fs3 = dwarf_fpr_f19, + dwarf_fpr_fs4 = dwarf_fpr_f20, + dwarf_fpr_fs5 = dwarf_fpr_f21, + dwarf_fpr_fs6 = dwarf_fpr_f22, + dwarf_fpr_fs7 = dwarf_fpr_f23, + dwarf_fpr_fs8 = dwarf_fpr_f24, + dwarf_fpr_fs9 = dwarf_fpr_f25, + dwarf_fpr_fs10 = dwarf_fpr_f26, + dwarf_fpr_fs11 = dwarf_fpr_f27, + dwarf_fpr_ft8 = dwarf_fpr_f28, + dwarf_fpr_ft9 = dwarf_fpr_f29, + dwarf_fpr_ft10 = dwarf_fpr_f30, + dwarf_fpr_ft11 = dwarf_fpr_f31, + + // mock pc regnum + dwarf_gpr_pc = 11451, +}; + +} // namespace riscv_dwarf + +#endif // LLDB_SOURCE_UTILITY_RISCV_DWARF_REGISTERS_H diff --git a/contrib/llvm-project/lldb/source/Utility/RegisterValue.cpp b/contrib/llvm-project/lldb/source/Utility/RegisterValue.cpp index a298c70d370b..b9ce9fd18ac4 100644 --- a/contrib/llvm-project/lldb/source/Utility/RegisterValue.cpp +++ b/contrib/llvm-project/lldb/source/Utility/RegisterValue.cpp @@ -35,21 +35,16 @@ bool RegisterValue::GetData(DataExtractor &data) const { return data.SetData(GetBytes(), GetByteSize(), GetByteOrder()) > 0; } -uint32_t RegisterValue::GetAsMemoryData(const RegisterInfo *reg_info, void *dst, +uint32_t RegisterValue::GetAsMemoryData(const RegisterInfo ®_info, void *dst, uint32_t dst_len, lldb::ByteOrder dst_byte_order, Status &error) const { - if (reg_info == nullptr) { - error.SetErrorString("invalid register info argument."); - return 0; - } - // ReadRegister should have already been called on this object prior to // calling this. if (GetType() == eTypeInvalid) { // No value has been read into this object... error.SetErrorStringWithFormat( - "invalid register value type for register %s", reg_info->name); + "invalid register value type for register %s", reg_info.name); return 0; } @@ -58,7 +53,7 @@ uint32_t RegisterValue::GetAsMemoryData(const RegisterInfo *reg_info, void *dst, return 0; } - const uint32_t src_len = reg_info->byte_size; + const uint32_t src_len = reg_info.byte_size; // Extract the register data into a data extractor DataExtractor reg_data; @@ -76,20 +71,15 @@ uint32_t RegisterValue::GetAsMemoryData(const RegisterInfo *reg_info, void *dst, dst_byte_order); // dst byte order if (bytes_copied == 0) error.SetErrorStringWithFormat( - "failed to copy data for register write of %s", reg_info->name); + "failed to copy data for register write of %s", reg_info.name); return bytes_copied; } -uint32_t RegisterValue::SetFromMemoryData(const RegisterInfo *reg_info, +uint32_t RegisterValue::SetFromMemoryData(const RegisterInfo ®_info, const void *src, uint32_t src_len, lldb::ByteOrder src_byte_order, Status &error) { - if (reg_info == nullptr) { - error.SetErrorString("invalid register info argument."); - return 0; - } - // Moving from addr into a register // // Case 1: src_len == dst_len @@ -112,12 +102,12 @@ uint32_t RegisterValue::SetFromMemoryData(const RegisterInfo *reg_info, return 0; } - const uint32_t dst_len = reg_info->byte_size; + const uint32_t dst_len = reg_info.byte_size; if (src_len > dst_len) { error.SetErrorStringWithFormat( "%u bytes is too big to store in register %s (%u bytes)", src_len, - reg_info->name, dst_len); + reg_info.name, dst_len); return 0; } @@ -159,17 +149,20 @@ bool RegisterValue::GetScalarValue(Scalar &scalar) const { void RegisterValue::Clear() { m_type = eTypeInvalid; } -RegisterValue::Type RegisterValue::SetType(const RegisterInfo *reg_info) { +RegisterValue::Type RegisterValue::SetType(const RegisterInfo ®_info) { // To change the type, we simply copy the data in again, using the new format RegisterValue copy; DataExtractor copy_data; - if (copy.CopyValue(*this) && copy.GetData(copy_data)) - SetValueFromData(reg_info, copy_data, 0, true); + if (copy.CopyValue(*this) && copy.GetData(copy_data)) { + Status error = SetValueFromData(reg_info, copy_data, 0, true); + assert(error.Success() && "Expected SetValueFromData to succeed."); + UNUSED_IF_ASSERT_DISABLED(error); + } return m_type; } -Status RegisterValue::SetValueFromData(const RegisterInfo *reg_info, +Status RegisterValue::SetValueFromData(const RegisterInfo ®_info, DataExtractor &src, lldb::offset_t src_offset, bool partial_data_ok) { @@ -180,22 +173,22 @@ Status RegisterValue::SetValueFromData(const RegisterInfo *reg_info, return error; } - if (reg_info->byte_size == 0) { + if (reg_info.byte_size == 0) { error.SetErrorString("invalid register info."); return error; } uint32_t src_len = src.GetByteSize() - src_offset; - if (!partial_data_ok && (src_len < reg_info->byte_size)) { + if (!partial_data_ok && (src_len < reg_info.byte_size)) { error.SetErrorString("not enough data."); return error; } // Cap the data length if there is more than enough bytes for this register // value - if (src_len > reg_info->byte_size) - src_len = reg_info->byte_size; + if (src_len > reg_info.byte_size) + src_len = reg_info.byte_size; // Zero out the value in case we get partial data... memset(buffer.bytes, 0, sizeof(buffer.bytes)); @@ -203,20 +196,20 @@ Status RegisterValue::SetValueFromData(const RegisterInfo *reg_info, type128 int128; m_type = eTypeInvalid; - switch (reg_info->encoding) { + switch (reg_info.encoding) { case eEncodingInvalid: break; case eEncodingUint: case eEncodingSint: - if (reg_info->byte_size == 1) + if (reg_info.byte_size == 1) SetUInt8(src.GetMaxU32(&src_offset, src_len)); - else if (reg_info->byte_size <= 2) + else if (reg_info.byte_size <= 2) SetUInt16(src.GetMaxU32(&src_offset, src_len)); - else if (reg_info->byte_size <= 4) + else if (reg_info.byte_size <= 4) SetUInt32(src.GetMaxU32(&src_offset, src_len)); - else if (reg_info->byte_size <= 8) + else if (reg_info.byte_size <= 8) SetUInt64(src.GetMaxU64(&src_offset, src_len)); - else if (reg_info->byte_size <= 16) { + else if (reg_info.byte_size <= 16) { uint64_t data1 = src.GetU64(&src_offset); uint64_t data2 = src.GetU64(&src_offset); if (src.GetByteSize() == eByteOrderBig) { @@ -230,16 +223,16 @@ Status RegisterValue::SetValueFromData(const RegisterInfo *reg_info, } break; case eEncodingIEEE754: - if (reg_info->byte_size == sizeof(float)) + if (reg_info.byte_size == sizeof(float)) SetFloat(src.GetFloat(&src_offset)); - else if (reg_info->byte_size == sizeof(double)) + else if (reg_info.byte_size == sizeof(double)) SetDouble(src.GetDouble(&src_offset)); - else if (reg_info->byte_size == sizeof(long double)) + else if (reg_info.byte_size == sizeof(long double)) SetLongDouble(src.GetLongDouble(&src_offset)); break; case eEncodingVector: { m_type = eTypeBytes; - buffer.length = reg_info->byte_size; + buffer.length = reg_info.byte_size; buffer.byte_order = src.GetByteOrder(); assert(buffer.length <= kMaxRegisterByteSize); if (buffer.length > kMaxRegisterByteSize) @@ -252,7 +245,7 @@ Status RegisterValue::SetValueFromData(const RegisterInfo *reg_info, buffer.byte_order) == 0) // dst byte order { error.SetErrorStringWithFormat( - "failed to copy data for register write of %s", reg_info->name); + "failed to copy data for register write of %s", reg_info.name); return error; } } @@ -260,7 +253,7 @@ Status RegisterValue::SetValueFromData(const RegisterInfo *reg_info, if (m_type == eTypeInvalid) error.SetErrorStringWithFormat( - "invalid register value type for register %s", reg_info->name); + "invalid register value type for register %s", reg_info.name); return error; } diff --git a/contrib/llvm-project/lldb/source/Utility/Reproducer.cpp b/contrib/llvm-project/lldb/source/Utility/Reproducer.cpp deleted file mode 100644 index 3641c933c38a..000000000000 --- a/contrib/llvm-project/lldb/source/Utility/Reproducer.cpp +++ /dev/null @@ -1,230 +0,0 @@ -//===-- Reproducer.cpp ----------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "lldb/Utility/Reproducer.h" -#include "lldb/Utility/LLDBAssert.h" -#include "lldb/Utility/ReproducerProvider.h" -#include "lldb/Utility/Timer.h" - -#include "llvm/Support/FileSystem.h" -#include "llvm/Support/Threading.h" -#include "llvm/Support/raw_ostream.h" - -using namespace lldb_private; -using namespace lldb_private::repro; -using namespace llvm; -using namespace llvm::yaml; - -Reproducer &Reproducer::Instance() { return *InstanceImpl(); } - -llvm::Error Reproducer::Initialize(ReproducerMode mode, - llvm::Optional<FileSpec> root) { - lldbassert(!InstanceImpl() && "Already initialized."); - InstanceImpl().emplace(); - - switch (mode) { - case ReproducerMode::Capture: { - if (!root) { - SmallString<128> repro_dir; - auto ec = sys::fs::createUniqueDirectory("reproducer", repro_dir); - if (ec) - return make_error<StringError>( - "unable to create unique reproducer directory", ec); - root.emplace(repro_dir); - } else { - auto ec = sys::fs::create_directory(root->GetPath()); - if (ec) - return make_error<StringError>("unable to create reproducer directory", - ec); - } - return Instance().SetCapture(root); - } break; - case ReproducerMode::Off: - break; - }; - - return Error::success(); -} - -void Reproducer::Initialize() { - llvm::cantFail(Initialize(repro::ReproducerMode::Off, llvm::None)); -} - -bool Reproducer::Initialized() { return InstanceImpl().operator bool(); } - -void Reproducer::Terminate() { - lldbassert(InstanceImpl() && "Already terminated."); - InstanceImpl().reset(); -} - -Optional<Reproducer> &Reproducer::InstanceImpl() { - static Optional<Reproducer> g_reproducer; - return g_reproducer; -} - -const Generator *Reproducer::GetGenerator() const { - std::lock_guard<std::mutex> guard(m_mutex); - if (m_generator) - return &(*m_generator); - return nullptr; -} - -const Loader *Reproducer::GetLoader() const { - std::lock_guard<std::mutex> guard(m_mutex); - if (m_loader) - return &(*m_loader); - return nullptr; -} - -Generator *Reproducer::GetGenerator() { - std::lock_guard<std::mutex> guard(m_mutex); - if (m_generator) - return &(*m_generator); - return nullptr; -} - -Loader *Reproducer::GetLoader() { - std::lock_guard<std::mutex> guard(m_mutex); - if (m_loader) - return &(*m_loader); - return nullptr; -} - -llvm::Error Reproducer::SetCapture(llvm::Optional<FileSpec> root) { - std::lock_guard<std::mutex> guard(m_mutex); - - if (root && m_loader) - return make_error<StringError>( - "cannot generate a reproducer when replay one", - inconvertibleErrorCode()); - - if (!root) { - m_generator.reset(); - return Error::success(); - } - - m_generator.emplace(*root); - return Error::success(); -} - -FileSpec Reproducer::GetReproducerPath() const { - if (auto g = GetGenerator()) - return g->GetRoot(); - if (auto l = GetLoader()) - return l->GetRoot(); - return {}; -} - -static FileSpec MakeAbsolute(const FileSpec &file_spec) { - SmallString<128> path; - file_spec.GetPath(path, false); - llvm::sys::fs::make_absolute(path); - return FileSpec(path, file_spec.GetPathStyle()); -} - -Generator::Generator(FileSpec root) : m_root(MakeAbsolute(std::move(root))) { - GetOrCreate<repro::WorkingDirectoryProvider>(); - GetOrCreate<repro::HomeDirectoryProvider>(); -} - -Generator::~Generator() { - if (!m_done) { - if (m_auto_generate) { - Keep(); - } else { - Discard(); - } - } -} - -ProviderBase *Generator::Register(std::unique_ptr<ProviderBase> provider) { - std::lock_guard<std::mutex> lock(m_providers_mutex); - std::pair<const void *, std::unique_ptr<ProviderBase>> key_value( - provider->DynamicClassID(), std::move(provider)); - auto e = m_providers.insert(std::move(key_value)); - return e.first->getSecond().get(); -} - -void Generator::Keep() { - LLDB_SCOPED_TIMER(); - assert(!m_done); - m_done = true; - - for (auto &provider : m_providers) - provider.second->Keep(); - - AddProvidersToIndex(); -} - -void Generator::Discard() { - LLDB_SCOPED_TIMER(); - assert(!m_done); - m_done = true; - - for (auto &provider : m_providers) - provider.second->Discard(); - - llvm::sys::fs::remove_directories(m_root.GetPath()); -} - -void Generator::SetAutoGenerate(bool b) { m_auto_generate = b; } - -bool Generator::IsAutoGenerate() const { return m_auto_generate; } - -const FileSpec &Generator::GetRoot() const { return m_root; } - -void Generator::AddProvidersToIndex() { - FileSpec index = m_root; - index.AppendPathComponent("index.yaml"); - - std::error_code EC; - auto strm = std::make_unique<raw_fd_ostream>(index.GetPath(), EC, - sys::fs::OpenFlags::OF_None); - yaml::Output yout(*strm); - - std::vector<std::string> files; - files.reserve(m_providers.size()); - for (auto &provider : m_providers) { - files.emplace_back(provider.second->GetFile()); - } - - yout << files; -} - -Loader::Loader(FileSpec root, bool passive) - : m_root(MakeAbsolute(std::move(root))), m_loaded(false) {} - -llvm::Error Loader::LoadIndex() { - if (m_loaded) - return llvm::Error::success(); - - FileSpec index = m_root.CopyByAppendingPathComponent("index.yaml"); - - auto error_or_file = MemoryBuffer::getFile(index.GetPath()); - if (auto err = error_or_file.getError()) - return make_error<StringError>("unable to load reproducer index", err); - - yaml::Input yin((*error_or_file)->getBuffer()); - yin >> m_files; - if (auto err = yin.error()) - return make_error<StringError>("unable to read reproducer index", err); - - // Sort files to speed up search. - llvm::sort(m_files); - - // Remember that we've loaded the index. - m_loaded = true; - - return llvm::Error::success(); -} - -bool Loader::HasFile(StringRef file) { - assert(m_loaded); - auto it = std::lower_bound(m_files.begin(), m_files.end(), file.str()); - return (it != m_files.end()) && (*it == file); -} diff --git a/contrib/llvm-project/lldb/source/Utility/ReproducerProvider.cpp b/contrib/llvm-project/lldb/source/Utility/ReproducerProvider.cpp deleted file mode 100644 index 44f24e44f38d..000000000000 --- a/contrib/llvm-project/lldb/source/Utility/ReproducerProvider.cpp +++ /dev/null @@ -1,194 +0,0 @@ -//===-- Reproducer.cpp ----------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "lldb/Utility/ReproducerProvider.h" -#include "lldb/Utility/ProcessInfo.h" -#include "llvm/ADT/ScopeExit.h" -#include "llvm/Support/FileSystem.h" -#include "llvm/Support/WithColor.h" -#include "llvm/Support/raw_ostream.h" - -using namespace lldb_private; -using namespace lldb_private::repro; -using namespace llvm; -using namespace llvm::yaml; - -llvm::Expected<std::unique_ptr<DataRecorder>> -DataRecorder::Create(const FileSpec &filename) { - std::error_code ec; - auto recorder = std::make_unique<DataRecorder>(std::move(filename), ec); - if (ec) - return llvm::errorCodeToError(ec); - return std::move(recorder); -} - -llvm::Expected<std::unique_ptr<YamlRecorder>> -YamlRecorder::Create(const FileSpec &filename) { - std::error_code ec; - auto recorder = std::make_unique<YamlRecorder>(std::move(filename), ec); - if (ec) - return llvm::errorCodeToError(ec); - return std::move(recorder); -} - -void VersionProvider::Keep() { - FileSpec file = GetRoot().CopyByAppendingPathComponent(Info::file); - std::error_code ec; - llvm::raw_fd_ostream os(file.GetPath(), ec, llvm::sys::fs::OF_TextWithCRLF); - if (ec) - return; - os << m_version << "\n"; -} - -void FileProvider::RecordInterestingDirectory(const llvm::Twine &dir) { - if (m_collector) - m_collector->addFile(dir); -} - -void FileProvider::RecordInterestingDirectoryRecursive(const llvm::Twine &dir) { - if (m_collector) - m_collector->addDirectory(dir); -} - -void FileProvider::Keep() { - if (m_collector) { - FileSpec file = GetRoot().CopyByAppendingPathComponent(Info::file); - m_collector->writeMapping(file.GetPath()); - } -} - -llvm::Expected<std::unique_ptr<ProcessInfoRecorder>> -ProcessInfoRecorder::Create(const FileSpec &filename) { - std::error_code ec; - auto recorder = - std::make_unique<ProcessInfoRecorder>(std::move(filename), ec); - if (ec) - return llvm::errorCodeToError(ec); - return std::move(recorder); -} - -void ProcessInfoProvider::Keep() { - std::vector<std::string> files; - for (auto &recorder : m_process_info_recorders) { - recorder->Stop(); - files.push_back(recorder->GetFilename().GetPath()); - } - - FileSpec file = GetRoot().CopyByAppendingPathComponent(Info::file); - std::error_code ec; - llvm::raw_fd_ostream os(file.GetPath(), ec, llvm::sys::fs::OF_TextWithCRLF); - if (ec) - return; - llvm::yaml::Output yout(os); - yout << files; -} - -void ProcessInfoProvider::Discard() { m_process_info_recorders.clear(); } - -ProcessInfoRecorder *ProcessInfoProvider::GetNewProcessInfoRecorder() { - std::size_t i = m_process_info_recorders.size() + 1; - std::string filename = (llvm::Twine(Info::name) + llvm::Twine("-") + - llvm::Twine(i) + llvm::Twine(".yaml")) - .str(); - auto recorder_or_error = ProcessInfoRecorder::Create( - GetRoot().CopyByAppendingPathComponent(filename)); - if (!recorder_or_error) { - llvm::consumeError(recorder_or_error.takeError()); - return nullptr; - } - - m_process_info_recorders.push_back(std::move(*recorder_or_error)); - return m_process_info_recorders.back().get(); -} - -void ProcessInfoRecorder::Record(const ProcessInstanceInfoList &process_infos) { - if (!m_record) - return; - llvm::yaml::Output yout(m_os); - yout << const_cast<ProcessInstanceInfoList &>(process_infos); - m_os.flush(); -} - -void SymbolFileProvider::AddSymbolFile(const UUID *uuid, - const FileSpec &module_file, - const FileSpec &symbol_file) { - if (!uuid || (!module_file && !symbol_file)) - return; - m_symbol_files.emplace_back(uuid->GetAsString(), module_file.GetPath(), - symbol_file.GetPath()); -} - -void SymbolFileProvider::Keep() { - FileSpec file = this->GetRoot().CopyByAppendingPathComponent(Info::file); - std::error_code ec; - llvm::raw_fd_ostream os(file.GetPath(), ec, llvm::sys::fs::OF_TextWithCRLF); - if (ec) - return; - - // Remove duplicates. - llvm::sort(m_symbol_files); - m_symbol_files.erase( - std::unique(m_symbol_files.begin(), m_symbol_files.end()), - m_symbol_files.end()); - - llvm::yaml::Output yout(os); - yout << m_symbol_files; -} - -SymbolFileLoader::SymbolFileLoader(Loader *loader) { - if (!loader) - return; - - FileSpec file = loader->GetFile<SymbolFileProvider::Info>(); - if (!file) - return; - - auto error_or_file = llvm::MemoryBuffer::getFile(file.GetPath()); - if (auto err = error_or_file.getError()) - return; - - llvm::yaml::Input yin((*error_or_file)->getBuffer()); - yin >> m_symbol_files; -} - -std::pair<FileSpec, FileSpec> -SymbolFileLoader::GetPaths(const UUID *uuid) const { - if (!uuid) - return {}; - - auto it = std::lower_bound(m_symbol_files.begin(), m_symbol_files.end(), - SymbolFileProvider::Entry(uuid->GetAsString())); - if (it == m_symbol_files.end()) - return {}; - return std::make_pair<FileSpec, FileSpec>(FileSpec(it->module_path), - FileSpec(it->symbol_path)); -} - -void ProviderBase::anchor() {} -char CommandProvider::ID = 0; -char FileProvider::ID = 0; -char ProviderBase::ID = 0; -char VersionProvider::ID = 0; -char WorkingDirectoryProvider::ID = 0; -char HomeDirectoryProvider::ID = 0; -char ProcessInfoProvider::ID = 0; -char SymbolFileProvider::ID = 0; -const char *CommandProvider::Info::file = "command-interpreter.yaml"; -const char *CommandProvider::Info::name = "command-interpreter"; -const char *FileProvider::Info::file = "files.yaml"; -const char *FileProvider::Info::name = "files"; -const char *VersionProvider::Info::file = "version.txt"; -const char *VersionProvider::Info::name = "version"; -const char *WorkingDirectoryProvider::Info::file = "cwd.txt"; -const char *WorkingDirectoryProvider::Info::name = "cwd"; -const char *HomeDirectoryProvider::Info::file = "home.txt"; -const char *HomeDirectoryProvider::Info::name = "home"; -const char *ProcessInfoProvider::Info::file = "process-info.yaml"; -const char *ProcessInfoProvider::Info::name = "process-info"; -const char *SymbolFileProvider::Info::file = "symbol-files.yaml"; -const char *SymbolFileProvider::Info::name = "symbol-files"; diff --git a/contrib/llvm-project/lldb/source/Utility/SelectHelper.cpp b/contrib/llvm-project/lldb/source/Utility/SelectHelper.cpp index 05dbd1cce09d..b7d9e19bc7cb 100644 --- a/contrib/llvm-project/lldb/source/Utility/SelectHelper.cpp +++ b/contrib/llvm-project/lldb/source/Utility/SelectHelper.cpp @@ -20,10 +20,10 @@ #include "lldb/lldb-types.h" #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/Optional.h" #include <algorithm> #include <chrono> +#include <optional> #include <cerrno> #if defined(_WIN32) @@ -82,7 +82,7 @@ bool SelectHelper::FDIsSetError(lldb::socket_t fd) const { return false; } -static void updateMaxFd(llvm::Optional<lldb::socket_t> &vold, +static void updateMaxFd(std::optional<lldb::socket_t> &vold, lldb::socket_t vnew) { if (!vold) vold = vnew; @@ -100,10 +100,10 @@ lldb_private::Status SelectHelper::Select() { return lldb_private::Status("Too many file descriptors for select()"); #endif - llvm::Optional<lldb::socket_t> max_read_fd; - llvm::Optional<lldb::socket_t> max_write_fd; - llvm::Optional<lldb::socket_t> max_error_fd; - llvm::Optional<lldb::socket_t> max_fd; + std::optional<lldb::socket_t> max_read_fd; + std::optional<lldb::socket_t> max_write_fd; + std::optional<lldb::socket_t> max_error_fd; + std::optional<lldb::socket_t> max_fd; for (auto &pair : m_fd_map) { pair.second.PrepareForSelect(); const lldb::socket_t fd = pair.first; @@ -138,15 +138,15 @@ lldb_private::Status SelectHelper::Select() { llvm::SmallVector<fd_set, 1> write_fdset; llvm::SmallVector<fd_set, 1> error_fdset; - if (max_read_fd.hasValue()) { + if (max_read_fd.has_value()) { read_fdset.resize((nfds / FD_SETSIZE) + 1); read_fdset_ptr = read_fdset.data(); } - if (max_write_fd.hasValue()) { + if (max_write_fd.has_value()) { write_fdset.resize((nfds / FD_SETSIZE) + 1); write_fdset_ptr = write_fdset.data(); } - if (max_error_fd.hasValue()) { + if (max_error_fd.has_value()) { error_fdset.resize((nfds / FD_SETSIZE) + 1); error_fdset_ptr = error_fdset.data(); } @@ -198,7 +198,7 @@ lldb_private::Status SelectHelper::Select() { if (m_end_time) { tv_ptr = &tv; const auto remaining_dur = - duration_cast<microseconds>(m_end_time.value() - steady_clock::now()); + duration_cast<microseconds>(*m_end_time - steady_clock::now()); if (remaining_dur.count() > 0) { // Wait for a specific amount of time const auto dur_secs = duration_cast<seconds>(remaining_dur); diff --git a/contrib/llvm-project/lldb/source/Utility/StringExtractorGDBRemote.cpp b/contrib/llvm-project/lldb/source/Utility/StringExtractorGDBRemote.cpp index fc740615dd05..9f79d2271b1e 100644 --- a/contrib/llvm-project/lldb/source/Utility/StringExtractorGDBRemote.cpp +++ b/contrib/llvm-project/lldb/source/Utility/StringExtractorGDBRemote.cpp @@ -10,6 +10,7 @@ #include <cctype> #include <cstring> +#include <optional> constexpr lldb::pid_t StringExtractorGDBRemote::AllProcesses; constexpr lldb::tid_t StringExtractorGDBRemote::AllThreads; @@ -637,7 +638,7 @@ bool StringExtractorGDBRemote::ValidateResponse() const { return true; // No validator, so response is valid } -llvm::Optional<std::pair<lldb::pid_t, lldb::tid_t>> +std::optional<std::pair<lldb::pid_t, lldb::tid_t>> StringExtractorGDBRemote::GetPidTid(lldb::pid_t default_pid) { llvm::StringRef view = llvm::StringRef(m_packet).substr(m_index); size_t initial_length = view.size(); @@ -652,7 +653,7 @@ StringExtractorGDBRemote::GetPidTid(lldb::pid_t default_pid) { } else if (view.consumeInteger(16, pid) || pid == 0) { // not a valid hex integer OR unsupported pid 0 m_index = UINT64_MAX; - return llvm::None; + return std::nullopt; } // "." must follow if we expect TID too; otherwise, we assume -1 @@ -671,7 +672,7 @@ StringExtractorGDBRemote::GetPidTid(lldb::pid_t default_pid) { } else if (view.consumeInteger(16, tid) || tid == 0 || pid == AllProcesses) { // not a valid hex integer OR tid 0 OR pid -1 + a specific tid m_index = UINT64_MAX; - return llvm::None; + return std::nullopt; } // update m_index diff --git a/contrib/llvm-project/lldb/source/Utility/StringList.cpp b/contrib/llvm-project/lldb/source/Utility/StringList.cpp index ee1f157f16f1..98923a07db70 100644 --- a/contrib/llvm-project/lldb/source/Utility/StringList.cpp +++ b/contrib/llvm-project/lldb/source/Utility/StringList.cpp @@ -108,7 +108,7 @@ std::string StringList::LongestCommonPrefix() { if (m_strings.empty()) return {}; - auto args = llvm::makeArrayRef(m_strings); + auto args = llvm::ArrayRef(m_strings); llvm::StringRef prefix = args.front(); for (auto arg : args.drop_front()) { size_t count = 0; diff --git a/contrib/llvm-project/lldb/source/Utility/StructuredData.cpp b/contrib/llvm-project/lldb/source/Utility/StructuredData.cpp index fc10fa539e9e..acc09289e6b9 100644 --- a/contrib/llvm-project/lldb/source/Utility/StructuredData.cpp +++ b/contrib/llvm-project/lldb/source/Utility/StructuredData.cpp @@ -50,6 +50,11 @@ StructuredData::ParseJSONFromFile(const FileSpec &input_spec, Status &error) { return StructuredData::ObjectSP(); } +bool StructuredData::IsRecordType(const ObjectSP object_sp) { + return object_sp->GetType() == lldb::eStructuredDataTypeArray || + object_sp->GetType() == lldb::eStructuredDataTypeDictionary; +} + static StructuredData::ObjectSP ParseJSONValue(json::Value &value) { if (json::Object *O = value.getAsObject()) return ParseJSONObject(O); @@ -69,6 +74,9 @@ static StructuredData::ObjectSP ParseJSONValue(json::Value &value) { if (auto d = value.getAsNumber()) return std::make_shared<StructuredData::Float>(*d); + if (auto n = value.getAsNull()) + return std::make_shared<StructuredData::Null>(); + return StructuredData::ObjectSP(); } @@ -172,3 +180,98 @@ void StructuredData::Null::Serialize(json::OStream &s) const { void StructuredData::Generic::Serialize(json::OStream &s) const { s.value(llvm::formatv("{0:X}", m_object)); } + +void StructuredData::Integer::GetDescription(lldb_private::Stream &s) const { + s.Printf("%" PRId64, static_cast<int64_t>(m_value)); +} + +void StructuredData::Float::GetDescription(lldb_private::Stream &s) const { + s.Printf("%f", m_value); +} + +void StructuredData::Boolean::GetDescription(lldb_private::Stream &s) const { + s.Printf(m_value ? "True" : "False"); +} + +void StructuredData::String::GetDescription(lldb_private::Stream &s) const { + s.Printf("%s", m_value.empty() ? "\"\"" : m_value.c_str()); +} + +void StructuredData::Array::GetDescription(lldb_private::Stream &s) const { + size_t index = 0; + size_t indentation_level = s.GetIndentLevel(); + for (const auto &item_sp : m_items) { + // Sanitize. + if (!item_sp) + continue; + + // Reset original indentation level. + s.SetIndentLevel(indentation_level); + s.Indent(); + + // Print key + s.Printf("[%zu]:", index++); + + // Return to new line and increase indentation if value is record type. + // Otherwise add spacing. + bool should_indent = IsRecordType(item_sp); + if (should_indent) { + s.EOL(); + s.IndentMore(); + } else { + s.PutChar(' '); + } + + // Print value and new line if now last pair. + item_sp->GetDescription(s); + if (item_sp != *(--m_items.end())) + s.EOL(); + + // Reset indentation level if it was incremented previously. + if (should_indent) + s.IndentLess(); + } +} + +void StructuredData::Dictionary::GetDescription(lldb_private::Stream &s) const { + size_t indentation_level = s.GetIndentLevel(); + for (const auto &pair : m_dict) { + // Sanitize. + if (pair.first.IsNull() || pair.first.IsEmpty() || !pair.second) + continue; + + // Reset original indentation level. + s.SetIndentLevel(indentation_level); + s.Indent(); + + // Print key. + s.Printf("%s:", pair.first.AsCString()); + + // Return to new line and increase indentation if value is record type. + // Otherwise add spacing. + bool should_indent = IsRecordType(pair.second); + if (should_indent) { + s.EOL(); + s.IndentMore(); + } else { + s.PutChar(' '); + } + + // Print value and new line if now last pair. + pair.second->GetDescription(s); + if (pair != *(--m_dict.end())) + s.EOL(); + + // Reset indentation level if it was incremented previously. + if (should_indent) + s.IndentLess(); + } +} + +void StructuredData::Null::GetDescription(lldb_private::Stream &s) const { + s.Printf("NULL"); +} + +void StructuredData::Generic::GetDescription(lldb_private::Stream &s) const { + s.Printf("%p", m_object); +} diff --git a/contrib/llvm-project/lldb/source/Utility/TraceGDBRemotePackets.cpp b/contrib/llvm-project/lldb/source/Utility/TraceGDBRemotePackets.cpp index 9879b7b2cb79..387c7ef9f876 100644 --- a/contrib/llvm-project/lldb/source/Utility/TraceGDBRemotePackets.cpp +++ b/contrib/llvm-project/lldb/source/Utility/TraceGDBRemotePackets.cpp @@ -144,7 +144,7 @@ json::Value toJSON(const TraceGetBinaryDataRequest &packet) { bool fromJSON(const json::Value &value, TraceGetBinaryDataRequest &packet, Path path) { ObjectMapper o(value, path); - Optional<uint64_t> cpu_id; + std::optional<uint64_t> cpu_id; if (!(o && o.map("type", packet.type) && o.map("kind", packet.kind) && o.map("tid", packet.tid) && o.map("cpuId", cpu_id))) return false; diff --git a/contrib/llvm-project/lldb/source/Utility/TraceIntelPTGDBRemotePackets.cpp b/contrib/llvm-project/lldb/source/Utility/TraceIntelPTGDBRemotePackets.cpp index 7a0ed9c53c65..20e16b8ed3a6 100644 --- a/contrib/llvm-project/lldb/source/Utility/TraceIntelPTGDBRemotePackets.cpp +++ b/contrib/llvm-project/lldb/source/Utility/TraceIntelPTGDBRemotePackets.cpp @@ -30,10 +30,10 @@ json::Value toJSON(const JSONUINT64 &uint64, bool hex) { } bool fromJSON(const json::Value &value, JSONUINT64 &uint64, Path path) { - if (Optional<uint64_t> val = value.getAsUINT64()) { + if (std::optional<uint64_t> val = value.getAsUINT64()) { uint64.value = *val; return true; - } else if (Optional<StringRef> val = value.getAsString()) { + } else if (std::optional<StringRef> val = value.getAsString()) { if (!val->getAsInteger(/*radix=*/0, uint64.value)) return true; path.report("invalid string number"); diff --git a/contrib/llvm-project/lldb/source/Utility/UUID.cpp b/contrib/llvm-project/lldb/source/Utility/UUID.cpp index 0adeb06e4c04..62a75ecf47c2 100644 --- a/contrib/llvm-project/lldb/source/Utility/UUID.cpp +++ b/contrib/llvm-project/lldb/source/Utility/UUID.cpp @@ -35,14 +35,15 @@ static inline bool separate(size_t count) { } } -UUID UUID::fromCvRecord(UUID::CvRecordPdb70 debug_info) { +UUID::UUID(UUID::CvRecordPdb70 debug_info) { llvm::sys::swapByteOrder(debug_info.Uuid.Data1); llvm::sys::swapByteOrder(debug_info.Uuid.Data2); llvm::sys::swapByteOrder(debug_info.Uuid.Data3); llvm::sys::swapByteOrder(debug_info.Age); if (debug_info.Age) - return UUID::fromOptionalData(&debug_info, sizeof(debug_info)); - return UUID::fromOptionalData(&debug_info.Uuid, sizeof(debug_info.Uuid)); + *this = UUID(&debug_info, sizeof(debug_info)); + else + *this = UUID(&debug_info.Uuid, sizeof(debug_info.Uuid)); } std::string UUID::GetAsString(llvm::StringRef separator) const { @@ -107,16 +108,6 @@ bool UUID::SetFromStringRef(llvm::StringRef str) { if (!rest.empty() || bytes.empty()) return false; - *this = fromData(bytes); + *this = UUID(bytes); return true; } - -bool UUID::SetFromOptionalStringRef(llvm::StringRef str) { - bool result = SetFromStringRef(str); - if (result) { - if (llvm::all_of(m_bytes, [](uint8_t b) { return b == 0; })) - Clear(); - } - - return result; -} diff --git a/contrib/llvm-project/lldb/source/Utility/UriParser.cpp b/contrib/llvm-project/lldb/source/Utility/UriParser.cpp index b7771d57aefd..432b046d008b 100644 --- a/contrib/llvm-project/lldb/source/Utility/UriParser.cpp +++ b/contrib/llvm-project/lldb/source/Utility/UriParser.cpp @@ -12,6 +12,7 @@ #include <string> #include <cstdint> +#include <optional> #include <tuple> using namespace lldb_private; @@ -24,13 +25,13 @@ llvm::raw_ostream &lldb_private::operator<<(llvm::raw_ostream &OS, return OS << U.path; } -llvm::Optional<URI> URI::Parse(llvm::StringRef uri) { +std::optional<URI> URI::Parse(llvm::StringRef uri) { URI ret; const llvm::StringRef kSchemeSep("://"); auto pos = uri.find(kSchemeSep); if (pos == std::string::npos) - return llvm::None; + return std::nullopt; // Extract path. ret.scheme = uri.substr(0, pos); @@ -50,12 +51,12 @@ llvm::Optional<URI> URI::Parse(llvm::StringRef uri) { // hostname is enclosed with square brackets. pos = host_port.rfind(']'); if (pos == std::string::npos) - return llvm::None; + return std::nullopt; ret.hostname = host_port.substr(1, pos - 1); host_port = host_port.drop_front(pos + 1); if (!host_port.empty() && !host_port.consume_front(":")) - return llvm::None; + return std::nullopt; } else { std::tie(ret.hostname, host_port) = host_port.split(':'); } @@ -64,10 +65,10 @@ llvm::Optional<URI> URI::Parse(llvm::StringRef uri) { if (!host_port.empty()) { uint16_t port_value = 0; if (host_port.getAsInteger(0, port_value)) - return llvm::None; + return std::nullopt; ret.port = port_value; } else - ret.port = llvm::None; + ret.port = std::nullopt; return ret; } diff --git a/contrib/llvm-project/lldb/source/Utility/UserIDResolver.cpp b/contrib/llvm-project/lldb/source/Utility/UserIDResolver.cpp index 73bdde77cc0f..83e033f32310 100644 --- a/contrib/llvm-project/lldb/source/Utility/UserIDResolver.cpp +++ b/contrib/llvm-project/lldb/source/Utility/UserIDResolver.cpp @@ -8,33 +8,34 @@ #include "lldb/Utility/UserIDResolver.h" #include "llvm/Support/ManagedStatic.h" +#include <optional> using namespace lldb_private; UserIDResolver::~UserIDResolver() = default; -llvm::Optional<llvm::StringRef> UserIDResolver::Get( +std::optional<llvm::StringRef> UserIDResolver::Get( id_t id, Map &cache, - llvm::Optional<std::string> (UserIDResolver::*do_get)(id_t)) { + std::optional<std::string> (UserIDResolver::*do_get)(id_t)) { std::lock_guard<std::mutex> guard(m_mutex); - auto iter_bool = cache.try_emplace(id, llvm::None); + auto iter_bool = cache.try_emplace(id, std::nullopt); if (iter_bool.second) iter_bool.first->second = (this->*do_get)(id); if (iter_bool.first->second) return llvm::StringRef(*iter_bool.first->second); - return llvm::None; + return std::nullopt; } namespace { class NoopResolver : public UserIDResolver { protected: - llvm::Optional<std::string> DoGetUserName(id_t uid) override { - return llvm::None; + std::optional<std::string> DoGetUserName(id_t uid) override { + return std::nullopt; } - llvm::Optional<std::string> DoGetGroupName(id_t gid) override { - return llvm::None; + std::optional<std::string> DoGetGroupName(id_t gid) override { + return std::nullopt; } }; } // namespace diff --git a/contrib/llvm-project/lldb/source/Utility/UuidCompatibility.h b/contrib/llvm-project/lldb/source/Utility/UuidCompatibility.h index e992c0c79a1f..40ebc1de24e4 100644 --- a/contrib/llvm-project/lldb/source/Utility/UuidCompatibility.h +++ b/contrib/llvm-project/lldb/source/Utility/UuidCompatibility.h @@ -14,4 +14,12 @@ // uuid_t is guaranteed to always be a 16-byte array typedef unsigned char uuid_t[16]; +// Return 1 if uuid is null, that is, all zeroes. +inline __attribute__((always_inline)) int uuid_is_null(uuid_t uuid) { + for (int i = 0; i < 16; i++) + if (uuid[i]) + return 0; + return 1; +} + #endif // utility_UUID_COMPATIBILITY_H diff --git a/contrib/llvm-project/lldb/tools/driver/Driver.cpp b/contrib/llvm-project/lldb/tools/driver/Driver.cpp index 16fa2f1393d5..d463267aeef3 100644 --- a/contrib/llvm-project/lldb/tools/driver/Driver.cpp +++ b/contrib/llvm-project/lldb/tools/driver/Driver.cpp @@ -15,7 +15,6 @@ #include "lldb/API/SBFile.h" #include "lldb/API/SBHostOS.h" #include "lldb/API/SBLanguageRuntime.h" -#include "lldb/API/SBReproducer.h" #include "lldb/API/SBStream.h" #include "lldb/API/SBStringList.h" #include "lldb/API/SBStructuredData.h" @@ -60,11 +59,14 @@ enum ID { #undef OPTION }; -#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE; +#define PREFIX(NAME, VALUE) \ + static constexpr StringLiteral NAME##_init[] = VALUE; \ + static constexpr ArrayRef<StringLiteral> NAME(NAME##_init, \ + std::size(NAME##_init) - 1); #include "Options.inc" #undef PREFIX -const opt::OptTable::Info InfoTable[] = { +static constexpr opt::OptTable::Info InfoTable[] = { #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ HELPTEXT, METAVAR, VALUES) \ { \ @@ -76,9 +78,9 @@ const opt::OptTable::Info InfoTable[] = { #undef OPTION }; -class LLDBOptTable : public opt::OptTable { +class LLDBOptTable : public opt::GenericOptTable { public: - LLDBOptTable() : OptTable(InfoTable) {} + LLDBOptTable() : opt::GenericOptTable(InfoTable) {} }; } // namespace @@ -742,39 +744,6 @@ EXAMPLES: llvm::outs() << examples << '\n'; } -static llvm::Optional<int> InitializeReproducer(llvm::StringRef argv0, - opt::InputArgList &input_args) { - bool capture = input_args.hasArg(OPT_capture); - bool generate_on_exit = input_args.hasArg(OPT_generate_on_exit); - auto *capture_path = input_args.getLastArg(OPT_capture_path); - - if (generate_on_exit && !capture) { - WithColor::warning() - << "-reproducer-generate-on-exit specified without -capture\n"; - } - - if (capture || capture_path) { - if (capture_path) { - if (!capture) - WithColor::warning() << "-capture-path specified without -capture\n"; - if (const char *error = SBReproducer::Capture(capture_path->getValue())) { - WithColor::error() << "reproducer capture failed: " << error << '\n'; - return 1; - } - } else { - const char *error = SBReproducer::Capture(); - if (error) { - WithColor::error() << "reproducer capture failed: " << error << '\n'; - return 1; - } - } - if (generate_on_exit) - SBReproducer::SetAutoGenerate(true); - } - - return llvm::None; -} - int main(int argc, char const *argv[]) { // Editline uses for example iswprint which is dependent on LC_CTYPE. std::setlocale(LC_ALL, ""); @@ -788,7 +757,7 @@ int main(int argc, char const *argv[]) { LLDBOptTable T; unsigned MissingArgIndex; unsigned MissingArgCount; - ArrayRef<const char *> arg_arr = makeArrayRef(argv + 1, argc - 1); + ArrayRef<const char *> arg_arr = ArrayRef(argv + 1, argc - 1); opt::InputArgList input_args = T.ParseArgs(arg_arr, MissingArgIndex, MissingArgCount); llvm::StringRef argv0 = llvm::sys::path::filename(argv[0]); @@ -816,16 +785,16 @@ int main(int argc, char const *argv[]) { return 1; } - if (auto exit_code = InitializeReproducer(argv[0], input_args)) { - return *exit_code; - } - SBError error = SBDebugger::InitializeWithErrorHandling(); if (error.Fail()) { WithColor::error() << "initialization failed: " << error.GetCString() << '\n'; return 1; } + + // Setup LLDB signal handlers once the debugger has been initialized. + SBDebugger::PrintDiagnosticsOnError(); + SBHostOS::ThreadCreated("<lldb.driver.main-thread>"); signal(SIGINT, sigint_handler); diff --git a/contrib/llvm-project/lldb/tools/driver/Options.td b/contrib/llvm-project/lldb/tools/driver/Options.td index 9e6ee390eead..a24fb3826b90 100644 --- a/contrib/llvm-project/lldb/tools/driver/Options.td +++ b/contrib/llvm-project/lldb/tools/driver/Options.td @@ -228,12 +228,4 @@ def: Flag<["-"], "d">, Alias<debug>, HelpText<"Alias for --debug">; -def capture: F<"capture">, - HelpText<"Tells the debugger to capture a reproducer.">; -def capture_path: Separate<["--", "-"], "capture-path">, - MetaVarName<"<filename>">, - HelpText<"Tells the debugger to use the given filename for the reproducer.">; -def generate_on_exit: F<"reproducer-generate-on-exit">, - HelpText<"Generate reproducer on exit.">; - def REM : R<["--"], "">; diff --git a/contrib/llvm-project/lldb/tools/lldb-server/Acceptor.cpp b/contrib/llvm-project/lldb/tools/lldb-server/Acceptor.cpp index 4714252011aa..2037f1e0f62b 100644 --- a/contrib/llvm-project/lldb/tools/lldb-server/Acceptor.cpp +++ b/contrib/llvm-project/lldb/tools/lldb-server/Acceptor.cpp @@ -15,6 +15,7 @@ #include "lldb/Host/common/TCPSocket.h" #include "lldb/Utility/StreamString.h" #include "lldb/Utility/UriParser.h" +#include <optional> using namespace lldb; using namespace lldb_private; @@ -85,7 +86,7 @@ std::unique_ptr<Acceptor> Acceptor::Create(StringRef name, Socket::SocketProtocol socket_protocol = Socket::ProtocolUnixDomain; // Try to match socket name as URL - e.g., tcp://localhost:5555 - if (llvm::Optional<URI> res = URI::Parse(name)) { + if (std::optional<URI> res = URI::Parse(name)) { if (!FindProtocolByScheme(res->scheme.str().c_str(), socket_protocol)) error.SetErrorStringWithFormat("Unknown protocol scheme \"%s\"", res->scheme.str().c_str()); diff --git a/contrib/llvm-project/lldb/tools/lldb-server/SystemInitializerLLGS.cpp b/contrib/llvm-project/lldb/tools/lldb-server/SystemInitializerLLGS.cpp index b93e6b40dcd9..4233252a84df 100644 --- a/contrib/llvm-project/lldb/tools/lldb-server/SystemInitializerLLGS.cpp +++ b/contrib/llvm-project/lldb/tools/lldb-server/SystemInitializerLLGS.cpp @@ -29,6 +29,11 @@ using HostObjectFile = ObjectFileELF; #include "Plugins/Instruction/ARM/EmulateInstructionARM.h" #endif +#if defined(__loongarch__) +#define LLDB_TARGET_LoongArch +#include "Plugins/Instruction/LoongArch/EmulateInstructionLoongArch.h" +#endif + #if defined(__mips64__) || defined(mips64) || defined(__mips64) || \ defined(__MIPS64__) || defined(_M_MIPS64) #define LLDB_TARGET_MIPS64 @@ -41,6 +46,11 @@ using HostObjectFile = ObjectFileELF; #include "Plugins/Instruction/MIPS/EmulateInstructionMIPS.h" #endif +#if defined(__riscv) +#define LLDB_TARGET_RISCV +#include "Plugins/Instruction/RISCV/EmulateInstructionRISCV.h" +#endif + using namespace lldb_private; llvm::Error SystemInitializerLLGS::Initialize() { @@ -52,12 +62,18 @@ llvm::Error SystemInitializerLLGS::Initialize() { #if defined(LLDB_TARGET_ARM) || defined(LLDB_TARGET_ARM64) EmulateInstructionARM::Initialize(); #endif +#if defined(LLDB_TARGET_LoongArch) + EmulateInstructionLoongArch::Initialize(); +#endif #if defined(LLDB_TARGET_MIPS) || defined(LLDB_TARGET_MIPS64) EmulateInstructionMIPS::Initialize(); #endif #if defined(LLDB_TARGET_MIPS64) EmulateInstructionMIPS64::Initialize(); #endif +#if defined(LLDB_TARGET_RISCV) + EmulateInstructionRISCV::Initialize(); +#endif return llvm::Error::success(); } @@ -68,12 +84,18 @@ void SystemInitializerLLGS::Terminate() { #if defined(LLDB_TARGET_ARM) || defined(LLDB_TARGET_ARM64) EmulateInstructionARM::Terminate(); #endif +#if defined(LLDB_TARGET_LoongArch) + EmulateInstructionLoongArch::Terminate(); +#endif #if defined(LLDB_TARGET_MIPS) || defined(LLDB_TARGET_MIPS64) EmulateInstructionMIPS::Terminate(); #endif #if defined(LLDB_TARGET_MIPS64) EmulateInstructionMIPS64::Terminate(); #endif +#if defined(LLDB_TARGET_RISCV) + EmulateInstructionRISCV::Terminate(); +#endif SystemInitializerCommon::Terminate(); } diff --git a/contrib/llvm-project/lldb/tools/lldb-server/lldb-gdbserver.cpp b/contrib/llvm-project/lldb/tools/lldb-server/lldb-gdbserver.cpp index eca66cfc4967..2533be6fd647 100644 --- a/contrib/llvm-project/lldb/tools/lldb-server/lldb-gdbserver.cpp +++ b/contrib/llvm-project/lldb/tools/lldb-server/lldb-gdbserver.cpp @@ -278,11 +278,14 @@ enum ID { #undef OPTION }; -#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE; +#define PREFIX(NAME, VALUE) \ + constexpr llvm::StringLiteral NAME##_init[] = VALUE; \ + constexpr llvm::ArrayRef<llvm::StringLiteral> NAME( \ + NAME##_init, std::size(NAME##_init) - 1); #include "LLGSOptions.inc" #undef PREFIX -const opt::OptTable::Info InfoTable[] = { +static constexpr opt::OptTable::Info InfoTable[] = { #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ HELPTEXT, METAVAR, VALUES) \ { \ @@ -294,9 +297,9 @@ const opt::OptTable::Info InfoTable[] = { #undef OPTION }; -class LLGSOptTable : public opt::OptTable { +class LLGSOptTable : public opt::GenericOptTable { public: - LLGSOptTable() : OptTable(InfoTable) {} + LLGSOptTable() : opt::GenericOptTable(InfoTable) {} void PrintHelp(llvm::StringRef Name) { std::string Usage = diff --git a/contrib/llvm-project/lldb/tools/lldb-server/lldb-platform.cpp b/contrib/llvm-project/lldb/tools/lldb-server/lldb-platform.cpp index 1a969eec8db8..21b433511c56 100644 --- a/contrib/llvm-project/lldb/tools/lldb-server/lldb-platform.cpp +++ b/contrib/llvm-project/lldb/tools/lldb-server/lldb-platform.cpp @@ -19,6 +19,7 @@ #include <sys/wait.h> #endif #include <fstream> +#include <optional> #include "llvm/Support/FileSystem.h" #include "llvm/Support/FileUtilities.h" @@ -100,7 +101,7 @@ static Status save_socket_id_to_file(const std::string &socket_id, Status error(llvm::sys::fs::create_directory(temp_file_spec.GetPath())); if (error.Fail()) return Status("Failed to create directory %s: %s", - temp_file_spec.GetCString(), error.AsCString()); + temp_file_spec.GetPath().c_str(), error.AsCString()); llvm::SmallString<64> temp_file_path; temp_file_spec.AppendPathComponent("port-file.%%%%%%"); @@ -352,7 +353,7 @@ int main_platform(int argc, char *argv[]) { if (platform.IsConnected()) { if (inferior_arguments.GetArgumentCount() > 0) { lldb::pid_t pid = LLDB_INVALID_PROCESS_ID; - llvm::Optional<uint16_t> port = 0; + std::optional<uint16_t> port = 0; std::string socket_name; Status error = platform.LaunchGDBServer(inferior_arguments, "", // hostname @@ -366,7 +367,7 @@ int main_platform(int argc, char *argv[]) { bool interrupt = false; bool done = false; while (!interrupt && !done) { - if (platform.GetPacketAndSendResponse(llvm::None, error, interrupt, + if (platform.GetPacketAndSendResponse(std::nullopt, error, interrupt, done) != GDBRemoteCommunication::PacketResult::Success) break; |