aboutsummaryrefslogtreecommitdiff
path: root/lldb
diff options
context:
space:
mode:
Diffstat (limited to 'lldb')
-rw-r--r--lldb/bindings/interface/SBThreadExtensions.i4
-rw-r--r--lldb/bindings/python/python-extensions.swig1
-rw-r--r--lldb/docs/python_api_enums.rst2
-rw-r--r--lldb/docs/resources/lldbgdbremote.md83
-rw-r--r--lldb/docs/use/formatting.rst6
-rw-r--r--lldb/include/lldb/Core/Module.h3
-rw-r--r--lldb/include/lldb/Core/ModuleList.h8
-rw-r--r--lldb/include/lldb/Expression/Expression.h57
-rw-r--r--lldb/include/lldb/Symbol/SymbolFile.h13
-rw-r--r--lldb/include/lldb/Symbol/TypeSystem.h3
-rw-r--r--lldb/include/lldb/Target/Process.h1
-rw-r--r--lldb/include/lldb/lldb-enumerations.h15
-rw-r--r--lldb/packages/Python/lldbsuite/support/temp_file.py23
-rw-r--r--lldb/packages/Python/lldbsuite/test/builders/builder.py5
-rw-r--r--lldb/packages/Python/lldbsuite/test/configuration.py4
-rw-r--r--lldb/packages/Python/lldbsuite/test/decorators.py143
-rw-r--r--lldb/packages/Python/lldbsuite/test/dotest.py14
-rw-r--r--lldb/packages/Python/lldbsuite/test/dotest_args.py8
-rw-r--r--lldb/packages/Python/lldbsuite/test/make/Makefile.rules10
-rwxr-xr-xlldb/scripts/framework-header-fix.py2
-rw-r--r--lldb/source/Commands/CommandObjectDWIMPrint.cpp47
-rw-r--r--lldb/source/Commands/CommandObjectMemory.cpp2
-rw-r--r--lldb/source/Core/DumpDataExtractor.cpp16
-rw-r--r--lldb/source/Core/Module.cpp9
-rw-r--r--lldb/source/Core/ModuleList.cpp14
-rw-r--r--lldb/source/DataFormatters/FormatManager.cpp1
-rw-r--r--lldb/source/DataFormatters/VectorType.cpp2
-rw-r--r--lldb/source/Expression/Expression.cpp49
-rw-r--r--lldb/source/Expression/IRExecutionUnit.cpp65
-rw-r--r--lldb/source/Expression/IRInterpreter.cpp4
-rw-r--r--lldb/source/Host/common/Host.cpp9
-rw-r--r--lldb/source/Host/windows/Host.cpp63
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp2
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp2
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp3
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp2
-rw-r--r--lldb/source/Plugins/Instruction/RISCV/EmulateInstructionRISCV.cpp6
-rw-r--r--lldb/source/Plugins/Language/ClangCommon/ClangHighlighter.cpp3
-rw-r--r--lldb/source/Plugins/Process/wasm/CMakeLists.txt1
-rw-r--r--lldb/source/Plugins/Process/wasm/ProcessWasm.cpp33
-rw-r--r--lldb/source/Plugins/Process/wasm/ProcessWasm.h8
-rw-r--r--lldb/source/Plugins/Process/wasm/RegisterContextWasm.cpp109
-rw-r--r--lldb/source/Plugins/Process/wasm/RegisterContextWasm.h69
-rw-r--r--lldb/source/Plugins/Process/wasm/ThreadWasm.cpp17
-rw-r--r--lldb/source/Plugins/Process/wasm/ThreadWasm.h3
-rw-r--r--lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp29
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp10
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.h13
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp62
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp13
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.h31
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp19
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h13
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp51
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h13
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp56
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h3
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp11
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h3
-rw-r--r--lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp6
-rw-r--r--lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp5
-rw-r--r--lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp5
-rw-r--r--lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp78
-rw-r--r--lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h7
-rw-r--r--lldb/source/Target/Process.cpp12
-rw-r--r--lldb/source/ValueObject/ValueObject.cpp5
-rw-r--r--lldb/test/API/commands/watchpoints/step_over_watchpoint/TestStepOverWatchpoint.py10
-rw-r--r--lldb/test/API/commands/watchpoints/watchpoint_count/TestWatchpointCount.py4
-rw-r--r--lldb/test/API/functionalities/gdb_remote_client/TestGDBRemoteClient.py6
-rw-r--r--lldb/test/API/functionalities/gdb_remote_client/TestWasm.py225
-rw-r--r--lldb/test/API/functionalities/gdb_remote_client/simple.c10
-rw-r--r--lldb/test/API/functionalities/gdb_remote_client/simple.yaml228
-rw-r--r--lldb/test/API/functionalities/plugins/python_os_plugin/stepping_plugin_threads/TestOSPluginStepping.py2
-rw-r--r--lldb/test/API/functionalities/postmortem/minidump-new/TestMiniDumpNew.py14
-rw-r--r--lldb/test/API/functionalities/postmortem/minidump/TestMiniDump.py2
-rw-r--r--lldb/test/API/functionalities/scripted_process/stack_core_scripted_process.py4
-rw-r--r--lldb/test/API/functionalities/step_scripted/TestStepScripted.py4
-rw-r--r--lldb/test/API/functionalities/tail_call_frames/cross_dso/TestCrossDSOTailCalls.py1
-rw-r--r--lldb/test/API/functionalities/tail_call_frames/cross_object/TestCrossObjectTailCalls.py1
-rw-r--r--lldb/test/API/functionalities/tsan/multiple/TestTsanMultiple.py2
-rw-r--r--lldb/test/API/lang/cpp/expr-definition-in-dylib/Makefile6
-rw-r--r--lldb/test/API/lang/cpp/expr-definition-in-dylib/TestExprDefinitionInDylib.py33
-rw-r--r--lldb/test/API/lang/cpp/expr-definition-in-dylib/lib.cpp3
-rw-r--r--lldb/test/API/lang/cpp/expr-definition-in-dylib/lib.h8
-rw-r--r--lldb/test/API/lang/cpp/expr-definition-in-dylib/main.cpp6
-rw-r--r--lldb/test/API/macosx/abort_with_payload/TestAbortWithPayload.py2
-rw-r--r--lldb/test/API/macosx/corefile-exception-reason/TestCorefileExceptionReason.py2
-rw-r--r--lldb/test/API/riscv/break-undecoded/TestBreakpointIllegal.py4
-rw-r--r--lldb/test/Shell/Recognizer/Inputs/ubsan_add_overflow.c3
-rw-r--r--lldb/test/Shell/Recognizer/ubsan_add_overflow.test22
-rw-r--r--lldb/test/Shell/Scripts/TestFrameworkFixScript.test2
-rw-r--r--lldb/test/Shell/Scripts/TestFrameworkFixUnifdef.test2
-rw-r--r--lldb/test/Shell/Scripts/TestRPCFrameworkFixScript.test2
-rw-r--r--lldb/tools/lldb-rpc/LLDBRPCHeaders.cmake2
-rw-r--r--lldb/unittests/Core/DumpDataExtractorTest.cpp6
-rw-r--r--lldb/unittests/Expression/CMakeLists.txt1
-rw-r--r--lldb/unittests/Expression/ExpressionTest.cpp122
-rw-r--r--lldb/unittests/Host/FileSystemTest.cpp2
-rw-r--r--lldb/unittests/Symbol/TestTypeSystemClang.cpp142
99 files changed, 1905 insertions, 367 deletions
diff --git a/lldb/bindings/interface/SBThreadExtensions.i b/lldb/bindings/interface/SBThreadExtensions.i
index 267faad..4ec9f10 100644
--- a/lldb/bindings/interface/SBThreadExtensions.i
+++ b/lldb/bindings/interface/SBThreadExtensions.i
@@ -45,6 +45,9 @@ STRING_EXTENSION_OUTSIDE(SBThread)
frames.append(frame)
return frames
+ def get_stop_description(self):
+ return self.GetStopDescription(1024)
+
def get_stop_reason_data(self):
return [
self.GetStopReasonDataAtIndex(idx)
@@ -69,6 +72,7 @@ STRING_EXTENSION_OUTSIDE(SBThread)
name = property(GetName, None, doc='''A read only property that returns the name of this thread as a string.''')
queue = property(GetQueueName, None, doc='''A read only property that returns the dispatch queue name of this thread as a string.''')
queue_id = property(GetQueueID, None, doc='''A read only property that returns the dispatch queue id of this thread as an integer.''')
+ stop_description = property(get_stop_description, None, doc='''A read only property that returns a string describing the reason this thread stopped.''')
stop_reason = property(GetStopReason, None, doc='''A read only property that returns an lldb enumeration value (see enumerations that start with "lldb.eStopReason") that represents the reason this thread stopped.''')
stop_reason_data = property(get_stop_reason_data, None, doc='''A read only property that returns the stop reason data as a list.''')
is_suspended = property(IsSuspended, None, doc='''A read only property that returns a boolean value that indicates if this thread is suspended.''')
diff --git a/lldb/bindings/python/python-extensions.swig b/lldb/bindings/python/python-extensions.swig
index 4ba1607..40fa768 100644
--- a/lldb/bindings/python/python-extensions.swig
+++ b/lldb/bindings/python/python-extensions.swig
@@ -594,6 +594,7 @@ def is_numeric_type(basic_type):
if basic_type == eBasicTypeFloat: return (True,True)
if basic_type == eBasicTypeDouble: return (True,True)
if basic_type == eBasicTypeLongDouble: return (True,True)
+ if basic_type == eBasicTypeFloat128: return (True,True)
if basic_type == eBasicTypeFloatComplex: return (True,True)
if basic_type == eBasicTypeDoubleComplex: return (True,True)
if basic_type == eBasicTypeLongDoubleComplex: return (True,True)
diff --git a/lldb/docs/python_api_enums.rst b/lldb/docs/python_api_enums.rst
index b6a2497..a43a47b 100644
--- a/lldb/docs/python_api_enums.rst
+++ b/lldb/docs/python_api_enums.rst
@@ -321,6 +321,7 @@ Format
.. py:data:: eFormatInstruction
.. py:data:: eFormatVoid
.. py:data:: eFormatUnicode8
+.. py:data:: eFormatFloat128
.. _DescriptionLevel:
@@ -1045,6 +1046,7 @@ BasicType
.. py:data:: eBasicTypeObjCSel
.. py:data:: eBasicTypeNullPtr
.. py:data:: eBasicTypeOther
+.. py:data:: eBasicTypeFloat128
.. _TraceType:
diff --git a/lldb/docs/resources/lldbgdbremote.md b/lldb/docs/resources/lldbgdbremote.md
index 41628cf..36b95f1 100644
--- a/lldb/docs/resources/lldbgdbremote.md
+++ b/lldb/docs/resources/lldbgdbremote.md
@@ -1998,22 +1998,6 @@ threads (live system debug) / cores (JTAG) in your program have
stopped and allows LLDB to display and control your program
correctly.
-## qWasmCallStack
-
-Get the Wasm call stack for the given thread id. This returns a hex-encoded
-list of PC values, one for each frame of the call stack. To match the Wasm
-specification, the addresses are encoded in little endian byte order, even if
-the endian of the Wasm runtime's host is not little endian.
-
-```
-send packet: $qWasmCallStack:202dbe040#08
-read packet: $9c01000000000040e501000000000040fe01000000000040#
-```
-
-**Priority to Implement:** Only required for Wasm support. This packed is
-supported by the [WAMR](https://github.com/bytecodealliance/wasm-micro-runtime)
-and [V8](https://v8.dev) Wasm runtimes.
-
## qWatchpointSupportInfo
Get the number of hardware watchpoints available on the remote target.
@@ -2479,3 +2463,70 @@ omitting them will work fine; these numbers are always base 16.
The length of the payload is not provided. A reliable, 8-bit clean,
transport layer is assumed.
+
+## Wasm Packets
+
+The packet below are supported by the
+[WAMR](https://github.com/bytecodealliance/wasm-micro-runtime) and
+[V8](https://v8.dev) Wasm runtimes.
+
+
+### qWasmCallStack
+
+Get the Wasm call stack for the given thread id. This returns a hex-encoded
+list of PC values, one for each frame of the call stack. To match the Wasm
+specification, the addresses are encoded in little endian byte order, even if
+the endian of the Wasm runtime's host is not little endian.
+
+```
+send packet: $qWasmCallStack:202dbe040#08
+read packet: $9c01000000000040e501000000000040fe01000000000040#
+```
+
+**Priority to Implement:** Only required for Wasm support. Necessary to show
+stack traces.
+
+### qWasmGlobal
+
+Get the value of a Wasm global variable for the given frame index at the given
+variable index. The indexes are encoded as base 10. The result is a hex-encoded
+address from where to read the value.
+
+```
+send packet: $qWasmGlobal:0;2#cb
+read packet: $e0030100#b9
+```
+
+**Priority to Implement:** Only required for Wasm support. Necessary to show
+variables.
+
+
+### qWasmLocal
+
+Get the value of a Wasm function argument or local variable for the given frame
+index at the given variable index. The indexes are encoded as base 10. The
+result is a hex-encoded address from where to read the value.
+
+
+```
+send packet: $qWasmLocal:0;2#cb
+read packet: $e0030100#b9
+```
+
+**Priority to Implement:** Only required for Wasm support. Necessary to show
+variables.
+
+
+### qWasmStackValue
+
+Get the value of a Wasm local variable from the Wasm operand stack, for the
+given frame index at the given variable index. The indexes are encoded as base
+10. The result is a hex-encoded address from where to read value.
+
+```
+send packet: $qWasmStackValue:0;2#cb
+read packet: $e0030100#b9
+```
+
+**Priority to Implement:** Only required for Wasm support. Necessary to show
+variables.
diff --git a/lldb/docs/use/formatting.rst b/lldb/docs/use/formatting.rst
index 39ccfed..c5a880c 100644
--- a/lldb/docs/use/formatting.rst
+++ b/lldb/docs/use/formatting.rst
@@ -344,19 +344,19 @@ E.g., the following setting would reconstruct the entire function name (and is L
::
- (lldb) settings set plugin.cplusplus.dislpay.function-name-format "${function.return-left}${function.scope}${function.basename}${function.template-arguments}${function.formatted-arguments}${function.qualifiers}${function.return-right}${function.suffix}"
+ (lldb) settings set plugin.cplusplus.display.function-name-format "${function.return-left}${function.scope}${function.basename}${function.template-arguments}${function.formatted-arguments}${function.qualifiers}${function.return-right}${function.suffix}"
If a user wanted to only print the name and arguments of a C++ function one could do:
::
- (lldb) settings set plugin.cplusplus.dislpay.function-name-format "${function.scope}${function.basename}${function.formatted-arguments}"
+ (lldb) settings set plugin.cplusplus.display.function-name-format "${function.scope}${function.basename}${function.formatted-arguments}"
Then the following would highlight just the basename in green:
::
- (lldb) settings set plugin.cplusplus.dislpay.function-name-format "${function.scope}${ansi.fg.yellow}${function.basename}${ansi.normal}${function.formatted-arguments}"
+ (lldb) settings set plugin.cplusplus.display.function-name-format "${function.scope}${ansi.fg.yellow}${function.basename}${ansi.normal}${function.formatted-arguments}"
The ``${function.name-with-args}`` by default asks the language plugin whether it supports a language-specific ``function-name-format`` (e.g., the ``plugin.cplusplus.display.function-name-format`` for C++), and if it does, uses it. Otherwise it will display the demangled function name.
diff --git a/lldb/include/lldb/Core/Module.h b/lldb/include/lldb/Core/Module.h
index 8bb55c9..8513e14 100644
--- a/lldb/include/lldb/Core/Module.h
+++ b/lldb/include/lldb/Core/Module.h
@@ -86,7 +86,8 @@ struct ModuleFunctionSearchOptions {
///
/// The module will parse more detailed information as more queries are made.
class Module : public std::enable_shared_from_this<Module>,
- public SymbolContextScope {
+ public SymbolContextScope,
+ public UserID {
public:
class LookupInfo;
// Static functions that can track the lifetime of module objects. This is
diff --git a/lldb/include/lldb/Core/ModuleList.h b/lldb/include/lldb/Core/ModuleList.h
index d5e291f3..6ecdcf1 100644
--- a/lldb/include/lldb/Core/ModuleList.h
+++ b/lldb/include/lldb/Core/ModuleList.h
@@ -352,6 +352,14 @@ public:
// UUID values is very efficient and accurate.
lldb::ModuleSP FindModule(const UUID &uuid) const;
+ /// Find a module by LLDB-specific unique identifier.
+ ///
+ /// \param[in] uid The UID of the module assigned to it on construction.
+ ///
+ /// \returns ModuleSP of module with \c uid. Returns nullptr if no such
+ /// module could be found.
+ lldb::ModuleSP FindModule(lldb::user_id_t uid) const;
+
/// Finds the first module whose file specification matches \a module_spec.
lldb::ModuleSP FindFirstModule(const ModuleSpec &module_spec) const;
diff --git a/lldb/include/lldb/Expression/Expression.h b/lldb/include/lldb/Expression/Expression.h
index 8de9364..20067f4 100644
--- a/lldb/include/lldb/Expression/Expression.h
+++ b/lldb/include/lldb/Expression/Expression.h
@@ -13,6 +13,7 @@
#include <string>
#include <vector>
+#include "llvm/Support/FormatProviders.h"
#include "lldb/Expression/ExpressionTypeSystemHelper.h"
#include "lldb/lldb-forward.h"
@@ -96,6 +97,62 @@ protected:
///invalid.
};
+/// Holds parsed information about a function call label that
+/// LLDB attaches as an AsmLabel to function AST nodes it parses
+/// from debug-info.
+///
+/// The format being:
+///
+/// <prefix>:<module uid>:<symbol uid>:<name>
+///
+/// The label string needs to stay valid for the entire lifetime
+/// of this object.
+struct FunctionCallLabel {
+ /// Unique identifier of the lldb_private::Module
+ /// which contains the symbol identified by \c symbol_id.
+ lldb::user_id_t module_id;
+
+ /// Unique identifier of the function symbol on which to
+ /// perform the function call. For example, for DWARF this would
+ /// be the DIE UID.
+ lldb::user_id_t symbol_id;
+
+ /// Name to use when searching for the function symbol in
+ /// \c module_id. For most function calls this will be a
+ /// mangled name. In cases where a mangled name can't be used,
+ /// this will be the function name.
+ ///
+ /// NOTE: kept as last element so we don't have to worry about
+ /// ':' in the mangled name when parsing the label.
+ llvm::StringRef lookup_name;
+
+ /// Decodes the specified function \c label into a \c FunctionCallLabel.
+ static llvm::Expected<FunctionCallLabel> fromString(llvm::StringRef label);
+
+ /// Encode this FunctionCallLabel into its string representation.
+ ///
+ /// The representation roundtrips through \c fromString:
+ /// \code{.cpp}
+ /// llvm::StringRef encoded = "$__lldb_func:0x0:0x0:_Z3foov";
+ /// FunctionCallLabel label = *fromString(label);
+ ///
+ /// assert (label.toString() == encoded);
+ /// assert (*fromString(label.toString()) == label);
+ /// \endcode
+ std::string toString() const;
+};
+
+/// LLDB attaches this prefix to mangled names of functions that get called
+/// from JITted expressions.
+inline constexpr llvm::StringRef FunctionCallLabelPrefix = "$__lldb_func";
+
} // namespace lldb_private
+namespace llvm {
+template <> struct format_provider<lldb_private::FunctionCallLabel> {
+ static void format(const lldb_private::FunctionCallLabel &label,
+ raw_ostream &OS, StringRef Style);
+};
+} // namespace llvm
+
#endif // LLDB_EXPRESSION_EXPRESSION_H
diff --git a/lldb/include/lldb/Symbol/SymbolFile.h b/lldb/include/lldb/Symbol/SymbolFile.h
index e95f955..bbc615d 100644
--- a/lldb/include/lldb/Symbol/SymbolFile.h
+++ b/lldb/include/lldb/Symbol/SymbolFile.h
@@ -18,6 +18,7 @@
#include "lldb/Symbol/CompilerType.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/SourceModule.h"
+#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/Type.h"
#include "lldb/Symbol/TypeList.h"
#include "lldb/Symbol/TypeSystem.h"
@@ -328,6 +329,18 @@ public:
GetMangledNamesForFunction(const std::string &scope_qualified_name,
std::vector<ConstString> &mangled_names);
+ /// Resolves the function corresponding to the specified LLDB function
+ /// call \c label.
+ ///
+ /// \param[in] label The FunctionCallLabel to be resolved.
+ ///
+ /// \returns An llvm::Error if the specified \c label couldn't be resolved.
+ /// Returns the resolved function (as a SymbolContext) otherwise.
+ virtual llvm::Expected<SymbolContext>
+ ResolveFunctionCallLabel(const FunctionCallLabel &label) {
+ return llvm::createStringError("Not implemented");
+ }
+
virtual void GetTypes(lldb_private::SymbolContextScope *sc_scope,
lldb::TypeClass type_mask,
lldb_private::TypeList &type_list) = 0;
diff --git a/lldb/include/lldb/Symbol/TypeSystem.h b/lldb/include/lldb/Symbol/TypeSystem.h
index cb1f013..16a2e0b 100644
--- a/lldb/include/lldb/Symbol/TypeSystem.h
+++ b/lldb/include/lldb/Symbol/TypeSystem.h
@@ -310,7 +310,8 @@ public:
// Exploring the type
- virtual const llvm::fltSemantics &GetFloatTypeSemantics(size_t byte_size) = 0;
+ virtual const llvm::fltSemantics &
+ GetFloatTypeSemantics(size_t byte_size, lldb::Format format) = 0;
virtual llvm::Expected<uint64_t>
GetBitSize(lldb::opaque_compiler_type_t type,
diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h
index 7e66e31..dc75d98 100644
--- a/lldb/include/lldb/Target/Process.h
+++ b/lldb/include/lldb/Target/Process.h
@@ -100,6 +100,7 @@ public:
void SetStopOnSharedLibraryEvents(bool stop);
bool GetDisableLangRuntimeUnwindPlans() const;
void SetDisableLangRuntimeUnwindPlans(bool disable);
+ void DisableLanguageRuntimeUnwindPlansCallback();
bool GetDetachKeepsStopped() const;
void SetDetachKeepsStopped(bool keep_stopped);
bool GetWarningsOptimization() const;
diff --git a/lldb/include/lldb/lldb-enumerations.h b/lldb/include/lldb/lldb-enumerations.h
index 171a650..c63c1f0 100644
--- a/lldb/include/lldb/lldb-enumerations.h
+++ b/lldb/include/lldb/lldb-enumerations.h
@@ -198,11 +198,15 @@ enum Format {
///< character arrays that can contain non printable
///< characters
eFormatAddressInfo, ///< Describe what an address points to (func + offset
- ///< with file/line, symbol + offset, data, etc)
- eFormatHexFloat, ///< ISO C99 hex float string
- eFormatInstruction, ///< Disassemble an opcode
- eFormatVoid, ///< Do not print this
+ ///< with file/line, symbol + offset, data, etc)
+ eFormatHexFloat, ///< ISO C99 hex float string
+ eFormatInstruction, ///< Disassemble an opcode
+ eFormatVoid, ///< Do not print this
eFormatUnicode8,
+ eFormatFloat128, ///< Disambiguate between 128-bit `long double` (which uses
+ ///< `eFormatFloat`) and `__float128` (which uses
+ ///< `eFormatFloat128`). If the value being formatted is not
+ ///< 128 bits, then this is identical to `eFormatFloat`.
kNumFormats
};
@@ -838,7 +842,8 @@ enum BasicType {
eBasicTypeObjCClass,
eBasicTypeObjCSel,
eBasicTypeNullPtr,
- eBasicTypeOther
+ eBasicTypeOther,
+ eBasicTypeFloat128
};
/// Deprecated
diff --git a/lldb/packages/Python/lldbsuite/support/temp_file.py b/lldb/packages/Python/lldbsuite/support/temp_file.py
new file mode 100644
index 0000000..a21e212
--- /dev/null
+++ b/lldb/packages/Python/lldbsuite/support/temp_file.py
@@ -0,0 +1,23 @@
+"""
+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
+"""
+
+import os
+import tempfile
+
+
+class OnDiskTempFile:
+ def __init__(self, delete=True):
+ self.path = None
+
+ def __enter__(self):
+ fd, path = tempfile.mkstemp()
+ os.close(fd)
+ self.path = path
+ return self
+
+ def __exit__(self, exc_type, exc_val, exc_tb):
+ if os.path.exists(self.path):
+ os.remove(self.path)
diff --git a/lldb/packages/Python/lldbsuite/test/builders/builder.py b/lldb/packages/Python/lldbsuite/test/builders/builder.py
index ada6f9f..96c7b39 100644
--- a/lldb/packages/Python/lldbsuite/test/builders/builder.py
+++ b/lldb/packages/Python/lldbsuite/test/builders/builder.py
@@ -26,7 +26,7 @@ class Builder:
def getTriple(self, arch):
"""Returns the triple for the given architecture or None."""
- return None
+ return configuration.triple
def getExtraMakeArgs(self):
"""
@@ -37,6 +37,9 @@ class Builder:
def getArchCFlags(self, architecture):
"""Returns the ARCH_CFLAGS for the make system."""
+ triple = self.getTriple(architecture)
+ if triple:
+ return ["ARCH_CFLAGS=-target {}".format(triple)]
return []
def getMake(self, test_subdir, test_name):
diff --git a/lldb/packages/Python/lldbsuite/test/configuration.py b/lldb/packages/Python/lldbsuite/test/configuration.py
index b2d91fd2..5e38109 100644
--- a/lldb/packages/Python/lldbsuite/test/configuration.py
+++ b/lldb/packages/Python/lldbsuite/test/configuration.py
@@ -45,6 +45,9 @@ dsymutil = None
sdkroot = None
make_path = None
+# Allow specifying a triple for cross compilation.
+triple = None
+
# The overriden dwarf verison.
# Don't use this to test the current compiler's
# DWARF version, as this won't be set if the
@@ -141,6 +144,7 @@ enabled_plugins = []
# Typical values include Debug, Release, RelWithDebInfo and MinSizeRel
cmake_build_type = None
+
def shouldSkipBecauseOfCategories(test_categories):
if use_categories:
if (
diff --git a/lldb/packages/Python/lldbsuite/test/decorators.py b/lldb/packages/Python/lldbsuite/test/decorators.py
index a5f5837..bd10bcc 100644
--- a/lldb/packages/Python/lldbsuite/test/decorators.py
+++ b/lldb/packages/Python/lldbsuite/test/decorators.py
@@ -20,6 +20,7 @@ from . import configuration
from . import test_categories
from . import lldbtest_config
from lldbsuite.support import funcutils
+from lldbsuite.support import temp_file
from lldbsuite.test import lldbplatform
from lldbsuite.test import lldbplatformutil
@@ -94,22 +95,23 @@ def _match_decorator_property(expected, actual):
def _compiler_supports(
- compiler, flag, source="int main() {}", output_file=tempfile.NamedTemporaryFile()
+ compiler, flag, source="int main() {}", output_file=temp_file.OnDiskTempFile()
):
"""Test whether the compiler supports the given flag."""
- if platform.system() == "Darwin":
- compiler = "xcrun " + compiler
- try:
- cmd = "echo '%s' | %s %s -x c -o %s -" % (
- source,
- compiler,
- flag,
- output_file.name,
- )
- subprocess.check_call(cmd, shell=True)
- except subprocess.CalledProcessError:
- return False
- return True
+ with output_file:
+ if platform.system() == "Darwin":
+ compiler = "xcrun " + compiler
+ try:
+ cmd = "echo '%s' | %s %s -x c -o %s -" % (
+ source,
+ compiler,
+ flag,
+ output_file.path,
+ )
+ subprocess.check_call(cmd, shell=True)
+ except subprocess.CalledProcessError:
+ return False
+ return True
def expectedFailureIf(condition, bugnumber=None):
@@ -876,19 +878,19 @@ def skipUnlessSupportedTypeAttribute(attr):
def compiler_doesnt_support_struct_attribute():
compiler_path = lldbplatformutil.getCompiler()
- f = tempfile.NamedTemporaryFile()
- cmd = [lldbplatformutil.getCompiler(), "-x", "c++", "-c", "-o", f.name, "-"]
- p = subprocess.Popen(
- cmd,
- stdin=subprocess.PIPE,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE,
- universal_newlines=True,
- )
- stdout, stderr = p.communicate("struct __attribute__((%s)) Test {};" % attr)
- if attr in stderr:
- return "Compiler does not support attribute %s" % (attr)
- return None
+ with temp_file.OnDiskTempFile() as f:
+ cmd = [lldbplatformutil.getCompiler(), "-x", "c++", "-c", "-o", f.path, "-"]
+ p = subprocess.Popen(
+ cmd,
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ universal_newlines=True,
+ )
+ stdout, stderr = p.communicate("struct __attribute__((%s)) Test {};" % attr)
+ if attr in stderr:
+ return "Compiler does not support attribute %s" % (attr)
+ return None
return skipTestIfFn(compiler_doesnt_support_struct_attribute)
@@ -902,21 +904,21 @@ def skipUnlessHasCallSiteInfo(func):
if not compiler.startswith("clang"):
return "Test requires clang as compiler"
- f = tempfile.NamedTemporaryFile()
- cmd = (
- "echo 'int main() {}' | "
- "%s -g -glldb -O1 -S -emit-llvm -x c -o %s -" % (compiler_path, f.name)
- )
- if os.popen(cmd).close() is not None:
- return "Compiler can't compile with call site info enabled"
+ with temp_file.OnDiskTempFile() as f:
+ cmd = (
+ "echo 'int main() {}' | "
+ "%s -g -glldb -O1 -S -emit-llvm -x c -o %s -" % (compiler_path, f.path)
+ )
+ if os.popen(cmd).close() is not None:
+ return "Compiler can't compile with call site info enabled"
- with open(f.name, "r") as ir_output_file:
- buf = ir_output_file.read()
+ with open(f.path, "r") as ir_output_file:
+ buf = ir_output_file.read()
- if "DIFlagAllCallsDescribed" not in buf:
- return "Compiler did not introduce DIFlagAllCallsDescribed IR flag"
+ if "DIFlagAllCallsDescribed" not in buf:
+ return "Compiler did not introduce DIFlagAllCallsDescribed IR flag"
- return None
+ return None
return skipTestIfFn(is_compiler_clang_with_call_site_info)(func)
@@ -957,7 +959,7 @@ def skipUnlessUndefinedBehaviorSanitizer(func):
)
# We need to write out the object into a named temp file for inspection.
- outputf = tempfile.NamedTemporaryFile()
+ outputf = temp_file.OnDiskTempFile()
# Try to compile with ubsan turned on.
if not _compiler_supports(
@@ -969,7 +971,7 @@ def skipUnlessUndefinedBehaviorSanitizer(func):
return "Compiler cannot compile with -fsanitize=undefined"
# Check that we actually see ubsan instrumentation in the binary.
- cmd = "nm %s" % outputf.name
+ cmd = "nm %s" % outputf.path
with os.popen(cmd) as nm_output:
if "___ubsan_handle_divrem_overflow" not in nm_output.read():
return "Division by zero instrumentation is missing"
@@ -1037,40 +1039,37 @@ def skipUnlessAArch64MTELinuxCompiler(func):
def is_toolchain_with_mte():
compiler_path = lldbplatformutil.getCompiler()
- f = tempfile.NamedTemporaryFile(delete=False)
- if lldbplatformutil.getPlatform() == "windows":
- return "MTE tests are not compatible with 'windows'"
-
- # Note hostos may be Windows.
- f.close()
+ with temp_file.OnDiskTempFile() as f:
+ if lldbplatformutil.getPlatform() == "windows":
+ return "MTE tests are not compatible with 'windows'"
+
+ cmd = f"{compiler_path} -x c -o {f.path} -"
+ if (
+ subprocess.run(
+ cmd, shell=True, input="int main() {}".encode()
+ ).returncode
+ != 0
+ ):
+ # Cannot compile at all, don't skip the test
+ # so that we report the broken compiler normally.
+ return None
- cmd = f"{compiler_path} -x c -o {f.name} -"
- if (
- subprocess.run(cmd, shell=True, input="int main() {}".encode()).returncode
- != 0
- ):
- os.remove(f.name)
- # Cannot compile at all, don't skip the test
- # so that we report the broken compiler normally.
+ # We need the Linux headers and ACLE MTE intrinsics
+ test_src = """
+ #include <asm/hwcap.h>
+ #include <arm_acle.h>
+ #ifndef HWCAP2_MTE
+ #error
+ #endif
+ int main() {
+ void* ptr = __arm_mte_create_random_tag((void*)(0), 0);
+ }"""
+ cmd = f"{compiler_path} -march=armv8.5-a+memtag -x c -o {f.path} -"
+ res = subprocess.run(cmd, shell=True, input=test_src.encode())
+ if res.returncode != 0:
+ return "Toolchain does not support MTE"
return None
- # We need the Linux headers and ACLE MTE intrinsics
- test_src = """
- #include <asm/hwcap.h>
- #include <arm_acle.h>
- #ifndef HWCAP2_MTE
- #error
- #endif
- int main() {
- void* ptr = __arm_mte_create_random_tag((void*)(0), 0);
- }"""
- cmd = f"{compiler_path} -march=armv8.5-a+memtag -x c -o {f.name} -"
- res = subprocess.run(cmd, shell=True, input=test_src.encode())
- os.remove(f.name)
- if res.returncode != 0:
- return "Toolchain does not support MTE"
- return None
-
return skipTestIfFn(is_toolchain_with_mte)(func)
diff --git a/lldb/packages/Python/lldbsuite/test/dotest.py b/lldb/packages/Python/lldbsuite/test/dotest.py
index 24236e7..47a3c2e 100644
--- a/lldb/packages/Python/lldbsuite/test/dotest.py
+++ b/lldb/packages/Python/lldbsuite/test/dotest.py
@@ -43,6 +43,7 @@ from . import lldbtest_config
from . import test_categories
from . import test_result
from ..support import seven
+from ..support import temp_file
def is_exe(fpath):
@@ -321,8 +322,13 @@ def parseOptionsAndInitTestdirs():
logging.error("No SDK found with the name %s; aborting...", args.apple_sdk)
sys.exit(-1)
+ if args.triple:
+ configuration.triple = args.triple
+
if args.arch:
configuration.arch = args.arch
+ elif args.triple:
+ configuration.arch = args.triple.split("-")[0]
else:
configuration.arch = platform_machine
@@ -780,8 +786,8 @@ def canRunLibcxxTests():
return True, "libc++ always present"
if platform == "linux":
- with tempfile.NamedTemporaryFile() as f:
- cmd = [configuration.compiler, "-xc++", "-stdlib=libc++", "-o", f.name, "-"]
+ with temp_file.OnDiskTempFile() as f:
+ cmd = [configuration.compiler, "-xc++", "-stdlib=libc++", "-o", f.path, "-"]
p = subprocess.Popen(
cmd,
stdin=subprocess.PIPE,
@@ -840,8 +846,8 @@ def canRunMsvcStlTests():
if platform != "windows":
return False, f"Don't know how to build with MSVC's STL on {platform}"
- with tempfile.NamedTemporaryFile() as f:
- cmd = [configuration.compiler, "-xc++", "-o", f.name, "-E", "-"]
+ with temp_file.OnDiskTempFile() as f:
+ cmd = [configuration.compiler, "-xc++", "-o", f.path, "-E", "-"]
p = subprocess.Popen(
cmd,
stdin=subprocess.PIPE,
diff --git a/lldb/packages/Python/lldbsuite/test/dotest_args.py b/lldb/packages/Python/lldbsuite/test/dotest_args.py
index e9c2138..fce9e41 100644
--- a/lldb/packages/Python/lldbsuite/test/dotest_args.py
+++ b/lldb/packages/Python/lldbsuite/test/dotest_args.py
@@ -58,6 +58,14 @@ def create_parser():
"""Specify the path to sysroot. This overrides apple_sdk sysroot."""
),
)
+ group.add_argument(
+ "--triple",
+ metavar="triple",
+ dest="triple",
+ help=textwrap.dedent(
+ """Specify the target triple. Used for cross compilation."""
+ ),
+ )
if sys.platform == "darwin":
group.add_argument(
"--apple-sdk",
diff --git a/lldb/packages/Python/lldbsuite/test/make/Makefile.rules b/lldb/packages/Python/lldbsuite/test/make/Makefile.rules
index 8521ca5..e72ffd1 100644
--- a/lldb/packages/Python/lldbsuite/test/make/Makefile.rules
+++ b/lldb/packages/Python/lldbsuite/test/make/Makefile.rules
@@ -149,6 +149,16 @@ else
endif
#----------------------------------------------------------------------
+# Use LLD when cross compiling on Darwin.
+#----------------------------------------------------------------------
+ifeq "$(HOST_OS)" "Darwin"
+ ifneq (,$(filter $(OS), Android FreeBSD Linux NetBSD Windows_NT))
+ LDFLAGS += -fuse-ld=lld
+ endif
+endif
+
+
+#----------------------------------------------------------------------
# ARCHFLAG is the flag used to tell the compiler which architecture
# to compile for. The default is the flag that clang accepts.
#----------------------------------------------------------------------
diff --git a/lldb/scripts/framework-header-fix.py b/lldb/scripts/framework-header-fix.py
index aa034db..36c5c67 100755
--- a/lldb/scripts/framework-header-fix.py
+++ b/lldb/scripts/framework-header-fix.py
@@ -112,7 +112,7 @@ def main():
# but passing them in with dashes for this script causes argparse to think that they're
# arguments in and of themself, so they need to passed in without dashes.
if args.unifdef_guards:
- unifdef_guards = ["-" + guard for guard in args.unifdef_guards]
+ unifdef_guards = ["-U" + guard for guard in args.unifdef_guards]
# Create the framework's header dir if it doesn't already exist
if not os.path.exists(os.path.dirname(output_file_path)):
diff --git a/lldb/source/Commands/CommandObjectDWIMPrint.cpp b/lldb/source/Commands/CommandObjectDWIMPrint.cpp
index a2c004d..d7589cc 100644
--- a/lldb/source/Commands/CommandObjectDWIMPrint.cpp
+++ b/lldb/source/Commands/CommandObjectDWIMPrint.cpp
@@ -18,11 +18,14 @@
#include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Utility/ConstString.h"
+#include "lldb/Utility/LLDBLog.h"
+#include "lldb/Utility/Log.h"
#include "lldb/ValueObject/ValueObject.h"
#include "lldb/lldb-defines.h"
#include "lldb/lldb-enumerations.h"
#include "lldb/lldb-forward.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Error.h"
#include <regex>
@@ -132,27 +135,22 @@ void CommandObjectDWIMPrint::DoExecute(StringRef command,
};
// Dump `valobj` according to whether `po` was requested or not.
- auto dump_val_object = [&](ValueObject &valobj) {
+ auto dump_val_object = [&](ValueObject &valobj) -> Error {
if (is_po) {
StreamString temp_result_stream;
- if (llvm::Error error = valobj.Dump(temp_result_stream, dump_options)) {
- result.AppendError(toString(std::move(error)));
- return;
- }
+ if (Error err = valobj.Dump(temp_result_stream, dump_options))
+ return err;
llvm::StringRef output = temp_result_stream.GetString();
maybe_add_hint(output);
result.GetOutputStream() << output;
} else {
- llvm::Error error =
- valobj.Dump(result.GetOutputStream(), dump_options);
- if (error) {
- result.AppendError(toString(std::move(error)));
- return;
- }
+ if (Error err = valobj.Dump(result.GetOutputStream(), dump_options))
+ return err;
}
m_interpreter.PrintWarningsIfNecessary(result.GetOutputStream(),
m_cmd_name);
result.SetStatus(eReturnStatusSuccessFinishResult);
+ return Error::success();
};
// First, try `expr` as a _limited_ frame variable expression path: only the
@@ -186,8 +184,13 @@ void CommandObjectDWIMPrint::DoExecute(StringRef command,
expr);
}
- dump_val_object(*valobj_sp);
- return;
+ Error err = dump_val_object(*valobj_sp);
+ if (!err)
+ return;
+
+ // Dump failed, continue on to expression evaluation.
+ LLDB_LOG_ERROR(GetLog(LLDBLog::Expressions), std::move(err),
+ "could not print frame variable '{1}': {0}", expr);
}
}
@@ -196,8 +199,14 @@ void CommandObjectDWIMPrint::DoExecute(StringRef command,
if (auto *state = target.GetPersistentExpressionStateForLanguage(language))
if (auto var_sp = state->GetVariable(expr))
if (auto valobj_sp = var_sp->GetValueObject()) {
- dump_val_object(*valobj_sp);
- return;
+ Error err = dump_val_object(*valobj_sp);
+ if (!err)
+ return;
+
+ // Dump failed, continue on to expression evaluation.
+ LLDB_LOG_ERROR(GetLog(LLDBLog::Expressions), std::move(err),
+ "could not print persistent variable '{1}': {0}",
+ expr);
}
// Third, and lastly, try `expr` as a source expression to evaluate.
@@ -248,10 +257,12 @@ void CommandObjectDWIMPrint::DoExecute(StringRef command,
result.AppendNoteWithFormatv("ran `expression {0}{1}`", flags, expr);
}
- if (valobj_sp->GetError().GetError() != UserExpression::kNoResult)
- dump_val_object(*valobj_sp);
- else
+ if (valobj_sp->GetError().GetError() != UserExpression::kNoResult) {
+ if (Error err = dump_val_object(*valobj_sp))
+ result.SetError(std::move(err));
+ } else {
result.SetStatus(eReturnStatusSuccessFinishNoResult);
+ }
if (suppress_result)
if (auto result_var_sp =
diff --git a/lldb/source/Commands/CommandObjectMemory.cpp b/lldb/source/Commands/CommandObjectMemory.cpp
index 5792c13..af1ff3e 100644
--- a/lldb/source/Commands/CommandObjectMemory.cpp
+++ b/lldb/source/Commands/CommandObjectMemory.cpp
@@ -156,6 +156,7 @@ public:
case eFormatBinary:
case eFormatFloat:
+ case eFormatFloat128:
case eFormatOctal:
case eFormatDecimal:
case eFormatEnum:
@@ -1356,6 +1357,7 @@ protected:
switch (m_format_options.GetFormat()) {
case kNumFormats:
case eFormatFloat: // TODO: add support for floats soon
+ case eFormatFloat128:
case eFormatCharPrintable:
case eFormatBytesWithASCII:
case eFormatComplex:
diff --git a/lldb/source/Core/DumpDataExtractor.cpp b/lldb/source/Core/DumpDataExtractor.cpp
index 7214073..37dffc7 100644
--- a/lldb/source/Core/DumpDataExtractor.cpp
+++ b/lldb/source/Core/DumpDataExtractor.cpp
@@ -318,14 +318,15 @@ static void printMemoryTags(const DataExtractor &DE, Stream *s,
}
static const llvm::fltSemantics &GetFloatSemantics(const TargetSP &target_sp,
- size_t byte_size) {
+ size_t byte_size,
+ lldb::Format format) {
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);
+ return ts->GetFloatTypeSemantics(byte_size, format);
}
// No target, just make a reasonable guess
switch(byte_size) {
@@ -335,7 +336,13 @@ static const llvm::fltSemantics &GetFloatSemantics(const TargetSP &target_sp,
return llvm::APFloat::IEEEsingle();
case 8:
return llvm::APFloat::IEEEdouble();
- }
+ case 16:
+ if (format == eFormatFloat128) {
+ return llvm::APFloat::IEEEquad();
+ }
+ // Otherwise it's ambigious whether a 16-byte float is a float128 or a
+ // target-specific long double.
+ }
return llvm::APFloat::Bogus();
}
@@ -653,6 +660,7 @@ lldb::offset_t lldb_private::DumpDataExtractor(
}
} break;
+ case eFormatFloat128:
case eFormatFloat: {
TargetSP target_sp;
if (exe_scope)
@@ -666,7 +674,7 @@ lldb::offset_t lldb_private::DumpDataExtractor(
const unsigned format_precision = 0;
const llvm::fltSemantics &semantics =
- GetFloatSemantics(target_sp, item_byte_size);
+ GetFloatSemantics(target_sp, item_byte_size, item_format);
// 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
diff --git a/lldb/source/Core/Module.cpp b/lldb/source/Core/Module.cpp
index 90997da..f27a95d 100644
--- a/lldb/source/Core/Module.cpp
+++ b/lldb/source/Core/Module.cpp
@@ -130,8 +130,10 @@ Module *Module::GetAllocatedModuleAtIndex(size_t idx) {
return nullptr;
}
+static std::atomic<lldb::user_id_t> g_unique_id = 1;
+
Module::Module(const ModuleSpec &module_spec)
- : m_unwind_table(*this), m_file_has_changed(false),
+ : UserID(g_unique_id++), m_unwind_table(*this), m_file_has_changed(false),
m_first_file_changed_log(false) {
// Scope for locker below...
{
@@ -236,7 +238,8 @@ Module::Module(const ModuleSpec &module_spec)
Module::Module(const FileSpec &file_spec, const ArchSpec &arch,
ConstString object_name, lldb::offset_t object_offset,
const llvm::sys::TimePoint<> &object_mod_time)
- : m_mod_time(FileSystem::Instance().GetModificationTime(file_spec)),
+ : UserID(g_unique_id++),
+ m_mod_time(FileSystem::Instance().GetModificationTime(file_spec)),
m_arch(arch), m_file(file_spec), m_object_name(object_name),
m_object_offset(object_offset), m_object_mod_time(object_mod_time),
m_unwind_table(*this), m_file_has_changed(false),
@@ -257,7 +260,7 @@ Module::Module(const FileSpec &file_spec, const ArchSpec &arch,
}
Module::Module()
- : m_unwind_table(*this), m_file_has_changed(false),
+ : UserID(g_unique_id++), m_unwind_table(*this), m_file_has_changed(false),
m_first_file_changed_log(false) {
std::lock_guard<std::recursive_mutex> guard(
GetAllocationModuleCollectionMutex());
diff --git a/lldb/source/Core/ModuleList.cpp b/lldb/source/Core/ModuleList.cpp
index d2e5be8..01f46b6 100644
--- a/lldb/source/Core/ModuleList.cpp
+++ b/lldb/source/Core/ModuleList.cpp
@@ -584,6 +584,20 @@ ModuleSP ModuleList::FindModule(const UUID &uuid) const {
return module_sp;
}
+ModuleSP ModuleList::FindModule(lldb::user_id_t uid) const {
+ ModuleSP module_sp;
+ ForEach([&](const ModuleSP &m) {
+ if (m->GetID() == uid) {
+ module_sp = m;
+ return IterationAction::Stop;
+ }
+
+ return IterationAction::Continue;
+ });
+
+ return module_sp;
+}
+
void ModuleList::FindTypes(Module *search_first, const TypeQuery &query,
TypeResults &results) const {
std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
diff --git a/lldb/source/DataFormatters/FormatManager.cpp b/lldb/source/DataFormatters/FormatManager.cpp
index 7862fb8..8595f81 100644
--- a/lldb/source/DataFormatters/FormatManager.cpp
+++ b/lldb/source/DataFormatters/FormatManager.cpp
@@ -72,6 +72,7 @@ static constexpr FormatInfo g_format_infos[] = {
{eFormatInstruction, 'i', "instruction"},
{eFormatVoid, 'v', "void"},
{eFormatUnicode8, 'u', "unicode8"},
+ {eFormatFloat128, '\0', "float128"},
};
static_assert((sizeof(g_format_infos) / sizeof(g_format_infos[0])) ==
diff --git a/lldb/source/DataFormatters/VectorType.cpp b/lldb/source/DataFormatters/VectorType.cpp
index 8a842b8..c2355fb 100644
--- a/lldb/source/DataFormatters/VectorType.cpp
+++ b/lldb/source/DataFormatters/VectorType.cpp
@@ -55,6 +55,8 @@ static CompilerType GetCompilerTypeForFormat(lldb::Format format,
case lldb::eFormatFloat:
return type_system->GetBasicTypeFromAST(lldb::eBasicTypeFloat);
+ case lldb::eFormatFloat128:
+ return type_system->GetBasicTypeFromAST(lldb::eBasicTypeFloat128);
case lldb::eFormatHex:
case lldb::eFormatHexUppercase:
diff --git a/lldb/source/Expression/Expression.cpp b/lldb/source/Expression/Expression.cpp
index 93f585e..796851f 100644
--- a/lldb/source/Expression/Expression.cpp
+++ b/lldb/source/Expression/Expression.cpp
@@ -10,6 +10,11 @@
#include "lldb/Target/ExecutionContextScope.h"
#include "lldb/Target/Target.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Error.h"
+
using namespace lldb_private;
Expression::Expression(Target &target)
@@ -26,3 +31,47 @@ Expression::Expression(ExecutionContextScope &exe_scope)
m_jit_end_addr(LLDB_INVALID_ADDRESS) {
assert(m_target_wp.lock());
}
+
+llvm::Expected<FunctionCallLabel>
+lldb_private::FunctionCallLabel::fromString(llvm::StringRef label) {
+ llvm::SmallVector<llvm::StringRef, 4> components;
+ label.split(components, ":", /*MaxSplit=*/3);
+
+ if (components.size() != 4)
+ return llvm::createStringError("malformed function call label.");
+
+ if (components[0] != FunctionCallLabelPrefix)
+ return llvm::createStringError(llvm::formatv(
+ "expected function call label prefix '{0}' but found '{1}' instead.",
+ FunctionCallLabelPrefix, components[0]));
+
+ llvm::StringRef module_label = components[1];
+ llvm::StringRef die_label = components[2];
+
+ lldb::user_id_t module_id = 0;
+ if (!llvm::to_integer(module_label, module_id))
+ return llvm::createStringError(
+ llvm::formatv("failed to parse module ID from '{0}'.", module_label));
+
+ lldb::user_id_t die_id;
+ if (!llvm::to_integer(die_label, die_id))
+ return llvm::createStringError(
+ llvm::formatv("failed to parse symbol ID from '{0}'.", die_label));
+
+ return FunctionCallLabel{/*.module_id=*/module_id,
+ /*.symbol_id=*/die_id,
+ /*.lookup_name=*/components[3]};
+}
+
+std::string lldb_private::FunctionCallLabel::toString() const {
+ return llvm::formatv("{0}:{1:x}:{2:x}:{3}", FunctionCallLabelPrefix,
+ module_id, symbol_id, lookup_name)
+ .str();
+}
+
+void llvm::format_provider<FunctionCallLabel>::format(
+ const FunctionCallLabel &label, raw_ostream &OS, StringRef Style) {
+ OS << llvm::formatv("FunctionCallLabel{ module_id: {0:x}, symbol_id: {1:x}, "
+ "lookup_name: {2} }",
+ label.module_id, label.symbol_id, label.lookup_name);
+}
diff --git a/lldb/source/Expression/IRExecutionUnit.cpp b/lldb/source/Expression/IRExecutionUnit.cpp
index 6f812b9..5e40df2 100644
--- a/lldb/source/Expression/IRExecutionUnit.cpp
+++ b/lldb/source/Expression/IRExecutionUnit.cpp
@@ -13,6 +13,7 @@
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
+#include "llvm/Support/Error.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/raw_ostream.h"
@@ -20,6 +21,7 @@
#include "lldb/Core/Disassembler.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/Section.h"
+#include "lldb/Expression/Expression.h"
#include "lldb/Expression/IRExecutionUnit.h"
#include "lldb/Expression/ObjectFileJIT.h"
#include "lldb/Host/HostInfo.h"
@@ -36,6 +38,7 @@
#include "lldb/Utility/LLDBAssert.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
+#include "lldb/lldb-defines.h"
#include <optional>
@@ -771,6 +774,40 @@ private:
lldb::addr_t m_best_internal_load_address = LLDB_INVALID_ADDRESS;
};
+/// Returns address of the function referred to by the special function call
+/// label \c label.
+static llvm::Expected<lldb::addr_t>
+ResolveFunctionCallLabel(const FunctionCallLabel &label,
+ const lldb_private::SymbolContext &sc,
+ bool &symbol_was_missing_weak) {
+ symbol_was_missing_weak = false;
+
+ if (!sc.target_sp)
+ return llvm::createStringError("target not available.");
+
+ auto module_sp = sc.target_sp->GetImages().FindModule(label.module_id);
+ if (!module_sp)
+ return llvm::createStringError(
+ llvm::formatv("failed to find module by UID {0}", label.module_id));
+
+ auto *symbol_file = module_sp->GetSymbolFile();
+ if (!symbol_file)
+ return llvm::createStringError(
+ llvm::formatv("no SymbolFile found on module {0:x}.", module_sp.get()));
+
+ auto sc_or_err = symbol_file->ResolveFunctionCallLabel(label);
+ if (!sc_or_err)
+ return llvm::joinErrors(
+ llvm::createStringError("failed to resolve function by UID"),
+ sc_or_err.takeError());
+
+ SymbolContextList sc_list;
+ sc_list.Append(*sc_or_err);
+
+ LoadAddressResolver resolver(*sc.target_sp, symbol_was_missing_weak);
+ return resolver.Resolve(sc_list).value_or(LLDB_INVALID_ADDRESS);
+}
+
lldb::addr_t
IRExecutionUnit::FindInSymbols(const std::vector<ConstString> &names,
const lldb_private::SymbolContext &sc,
@@ -906,6 +943,34 @@ lldb::addr_t IRExecutionUnit::FindInUserDefinedSymbols(
lldb::addr_t IRExecutionUnit::FindSymbol(lldb_private::ConstString name,
bool &missing_weak) {
+ if (name.GetStringRef().starts_with(FunctionCallLabelPrefix)) {
+ auto label_or_err = FunctionCallLabel::fromString(name);
+ if (!label_or_err) {
+ LLDB_LOG_ERROR(GetLog(LLDBLog::Expressions), label_or_err.takeError(),
+ "failed to create FunctionCallLabel from '{1}': {0}",
+ name.GetStringRef());
+ return LLDB_INVALID_ADDRESS;
+ }
+
+ if (auto addr_or_err =
+ ResolveFunctionCallLabel(*label_or_err, m_sym_ctx, missing_weak)) {
+ return *addr_or_err;
+ } else {
+ LLDB_LOG_ERROR(GetLog(LLDBLog::Expressions), addr_or_err.takeError(),
+ "Failed to resolve function call label '{1}': {0}",
+ name.GetStringRef());
+
+ // Fall back to lookup by name despite error in resolving the label.
+ // May happen in practice if the definition of a function lives in
+ // a different lldb_private::Module than it's declaration. Meaning
+ // we couldn't pin-point it using the information encoded in the label.
+ name.SetString(label_or_err->lookup_name);
+ }
+ }
+
+ // TODO: now with function call labels, do we still need to
+ // generate alternate manglings?
+
std::vector<ConstString> candidate_C_names;
std::vector<ConstString> candidate_CPlusPlus_names;
diff --git a/lldb/source/Expression/IRInterpreter.cpp b/lldb/source/Expression/IRInterpreter.cpp
index fa74e88..9140483 100644
--- a/lldb/source/Expression/IRInterpreter.cpp
+++ b/lldb/source/Expression/IRInterpreter.cpp
@@ -259,7 +259,9 @@ public:
break;
case Value::FunctionVal:
if (const Function *constant_func = dyn_cast<Function>(constant)) {
- lldb_private::ConstString name(constant_func->getName());
+ lldb_private::ConstString name(
+ llvm::GlobalValue::dropLLVMManglingEscape(
+ constant_func->getName()));
bool missing_weak = false;
lldb::addr_t addr = m_execution_unit.FindSymbol(name, missing_weak);
if (addr == LLDB_INVALID_ADDRESS)
diff --git a/lldb/source/Host/common/Host.cpp b/lldb/source/Host/common/Host.cpp
index 5992b54..510f9c7 100644
--- a/lldb/source/Host/common/Host.cpp
+++ b/lldb/source/Host/common/Host.cpp
@@ -82,10 +82,11 @@ int __pthread_fchdir(int fildes);
using namespace lldb;
using namespace lldb_private;
-#if !defined(__APPLE__)
-// The system log is currently only meaningful on Darwin, where this means
-// os_log. The meaning of a "system log" isn't as clear on other platforms, and
-// therefore we don't providate a default implementation. Vendors are free to
+#if !defined(__APPLE__) && !defined(_WIN32)
+// The system log is currently only meaningful on Darwin and Windows.
+// On Darwin, this means os_log. On Windows this means Events Viewer.
+// The meaning of a "system log" isn't as clear on other platforms, and
+// therefore we don't providate a default implementation. Vendors are free
// to implement this function if they have a use for it.
void Host::SystemLog(Severity severity, llvm::StringRef message) {}
#endif
diff --git a/lldb/source/Host/windows/Host.cpp b/lldb/source/Host/windows/Host.cpp
index a7369e7..4e747f7 100644
--- a/lldb/source/Host/windows/Host.cpp
+++ b/lldb/source/Host/windows/Host.cpp
@@ -22,7 +22,9 @@
#include "lldb/Utility/StreamString.h"
#include "lldb/Utility/StructuredData.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/ConvertUTF.h"
+#include "llvm/Support/ManagedStatic.h"
// Windows includes
#include <tlhelp32.h>
@@ -302,3 +304,64 @@ Environment Host::GetEnvironment() {
}
return env;
}
+
+/// Manages the lifecycle of a Windows Event's Source.
+/// The destructor will call DeregisterEventSource.
+/// This class is meant to be used with \ref llvm::ManagedStatic.
+class WindowsEventLog {
+public:
+ WindowsEventLog() : handle(RegisterEventSource(nullptr, L"lldb")) {}
+
+ ~WindowsEventLog() {
+ if (handle)
+ DeregisterEventSource(handle);
+ }
+
+ HANDLE GetHandle() const { return handle; }
+
+private:
+ HANDLE handle;
+};
+
+static llvm::ManagedStatic<WindowsEventLog> event_log;
+
+static std::wstring AnsiToUtf16(const std::string &ansi) {
+ if (ansi.empty())
+ return {};
+
+ const int unicode_length =
+ MultiByteToWideChar(CP_ACP, 0, ansi.c_str(), -1, nullptr, 0);
+ if (unicode_length == 0)
+ return {};
+
+ std::wstring unicode(unicode_length, L'\0');
+ MultiByteToWideChar(CP_ACP, 0, ansi.c_str(), -1, &unicode[0], unicode_length);
+ return unicode;
+}
+
+void Host::SystemLog(Severity severity, llvm::StringRef message) {
+ HANDLE h = event_log->GetHandle();
+ if (!h)
+ return;
+
+ std::wstring wide_message = AnsiToUtf16(message.str());
+ if (wide_message.empty())
+ return;
+
+ LPCWSTR msg_ptr = wide_message.c_str();
+
+ WORD event_type;
+ switch (severity) {
+ case lldb::eSeverityWarning:
+ event_type = EVENTLOG_WARNING_TYPE;
+ break;
+ case lldb::eSeverityError:
+ event_type = EVENTLOG_ERROR_TYPE;
+ break;
+ case lldb::eSeverityInfo:
+ default:
+ event_type = EVENTLOG_INFORMATION_TYPE;
+ }
+
+ ReportEventW(h, event_type, 0, 0, nullptr, 1, 0, &msg_ptr, nullptr);
+}
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
index 9f77fbc..214e260 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
@@ -1991,7 +1991,7 @@ void ClangExpressionDeclMap::AddContextClassType(NameSearchContext &context,
const bool is_artificial = false;
CXXMethodDecl *method_decl = m_clang_ast_context->AddMethodToCXXRecordType(
- copied_clang_type.GetOpaqueQualType(), "$__lldb_expr", nullptr,
+ copied_clang_type.GetOpaqueQualType(), "$__lldb_expr", /*asm_label=*/{},
method_type, lldb::eAccessPublic, is_virtual, is_static, is_inline,
is_explicit, is_attr_used, is_artificial);
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
index 3995bc0..e5a1d2d 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
@@ -894,7 +894,7 @@ ClangExpressionParser::ClangExpressionParser(
m_llvm_context = std::make_unique<LLVMContext>();
m_code_generator.reset(CreateLLVMCodeGen(
m_compiler->getDiagnostics(), module_name,
- &m_compiler->getVirtualFileSystem(), m_compiler->getHeaderSearchOpts(),
+ m_compiler->getVirtualFileSystemPtr(), m_compiler->getHeaderSearchOpts(),
m_compiler->getPreprocessorOpts(), m_compiler->getCodeGenOpts(),
*m_llvm_context));
}
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp
index 06f3a7e..ff9ed9c 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp
@@ -260,9 +260,8 @@ TokenVerifier::TokenVerifier(std::string body) {
// Let's build the actual source code Clang needs and setup some utility
// objects.
- llvm::IntrusiveRefCntPtr<DiagnosticIDs> diag_ids(new DiagnosticIDs());
DiagnosticOptions diags_opts;
- DiagnosticsEngine diags(diag_ids, diags_opts);
+ DiagnosticsEngine diags(DiagnosticIDs::create(), diags_opts);
clang::SourceManager SM(diags, file_mgr);
auto buf = llvm::MemoryBuffer::getMemBuffer(body);
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp
index 2f838b3..d54f072 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp
@@ -747,7 +747,7 @@ ClangModulesDeclVendor::Create(Target &target) {
// Make sure clang uses the same VFS as LLDB.
instance->createFileManager(FileSystem::Instance().GetVirtualFileSystem());
- instance->setDiagnostics(diagnostics_engine.get());
+ instance->setDiagnostics(diagnostics_engine);
std::unique_ptr<clang::FrontendAction> action(new clang::SyntaxOnlyAction);
diff --git a/lldb/source/Plugins/Instruction/RISCV/EmulateInstructionRISCV.cpp b/lldb/source/Plugins/Instruction/RISCV/EmulateInstructionRISCV.cpp
index 2adde02..5e429a9 100644
--- a/lldb/source/Plugins/Instruction/RISCV/EmulateInstructionRISCV.cpp
+++ b/lldb/source/Plugins/Instruction/RISCV/EmulateInstructionRISCV.cpp
@@ -1807,7 +1807,7 @@ RISCVSingleStepBreakpointLocationsPredictor::GetBreakpointLocations(
Log *log = GetLog(LLDBLog::Unwind);
LLDB_LOGF(log,
"RISCVSingleStepBreakpointLocationsPredictor::%s: can't find "
- "corresponding load reserve insturuction",
+ "corresponding load reserve instruction",
__FUNCTION__);
return {*pc + (inst->is_rvc ? 2u : 4u)};
}
@@ -1839,7 +1839,7 @@ RISCVSingleStepBreakpointLocationsPredictor::HandleAtomicSequence(
EmulateInstructionRISCV *riscv_emulator =
static_cast<EmulateInstructionRISCV *>(m_emulator_up.get());
- // Handle instructions between LR and SC. According to unprivilleged
+ // Handle instructions between LR and SC. According to unprivileged
// RISC-V ISA there can be at most 16 instructions in the sequence.
lldb::addr_t entry_pc = pc; // LR instruction address
@@ -1872,7 +1872,7 @@ RISCVSingleStepBreakpointLocationsPredictor::HandleAtomicSequence(
Log *log = GetLog(LLDBLog::Unwind);
LLDB_LOGF(log,
"RISCVSingleStepBreakpointLocationsPredictor::%s: can't find "
- "corresponding store conditional insturuction",
+ "corresponding store conditional instruction",
__FUNCTION__);
return {entry_pc + (lr_inst->is_rvc ? 2u : 4u)};
}
diff --git a/lldb/source/Plugins/Language/ClangCommon/ClangHighlighter.cpp b/lldb/source/Plugins/Language/ClangCommon/ClangHighlighter.cpp
index 8cc5714..9cb5ea3 100644
--- a/lldb/source/Plugins/Language/ClangCommon/ClangHighlighter.cpp
+++ b/lldb/source/Plugins/Language/ClangCommon/ClangHighlighter.cpp
@@ -162,9 +162,8 @@ void ClangHighlighter::Highlight(const HighlightStyle &options,
// Let's build the actual source code Clang needs and setup some utility
// objects.
std::string full_source = previous_lines.str() + line.str();
- llvm::IntrusiveRefCntPtr<DiagnosticIDs> diag_ids(new DiagnosticIDs());
DiagnosticOptions diags_opts;
- DiagnosticsEngine diags(diag_ids, diags_opts);
+ DiagnosticsEngine diags(DiagnosticIDs::create(), diags_opts);
clang::SourceManager SM(diags, file_mgr);
auto buf = llvm::MemoryBuffer::getMemBuffer(full_source);
diff --git a/lldb/source/Plugins/Process/wasm/CMakeLists.txt b/lldb/source/Plugins/Process/wasm/CMakeLists.txt
index ff8a3c7..779b97e 100644
--- a/lldb/source/Plugins/Process/wasm/CMakeLists.txt
+++ b/lldb/source/Plugins/Process/wasm/CMakeLists.txt
@@ -1,5 +1,6 @@
add_lldb_library(lldbPluginProcessWasm PLUGIN
ProcessWasm.cpp
+ RegisterContextWasm.cpp
ThreadWasm.cpp
UnwindWasm.cpp
diff --git a/lldb/source/Plugins/Process/wasm/ProcessWasm.cpp b/lldb/source/Plugins/Process/wasm/ProcessWasm.cpp
index 5eeabec..580e8c1 100644
--- a/lldb/source/Plugins/Process/wasm/ProcessWasm.cpp
+++ b/lldb/source/Plugins/Process/wasm/ProcessWasm.cpp
@@ -131,3 +131,36 @@ ProcessWasm::GetWasmCallStack(lldb::tid_t tid) {
return call_stack_pcs;
}
+
+llvm::Expected<lldb::DataBufferSP>
+ProcessWasm::GetWasmVariable(WasmVirtualRegisterKinds kind, int frame_index,
+ int index) {
+ StreamString packet;
+ switch (kind) {
+ case eWasmTagLocal:
+ packet.Printf("qWasmLocal:");
+ break;
+ case eWasmTagGlobal:
+ packet.Printf("qWasmGlobal:");
+ break;
+ case eWasmTagOperandStack:
+ packet.PutCString("qWasmStackValue:");
+ break;
+ case eWasmTagNotAWasmLocation:
+ return llvm::createStringError("not a Wasm location");
+ }
+ packet.Printf("%d;%d", frame_index, index);
+
+ StringExtractorGDBRemote response;
+ if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response) !=
+ GDBRemoteCommunication::PacketResult::Success)
+ return llvm::createStringError("failed to send Wasm variable");
+
+ if (!response.IsNormalResponse())
+ return llvm::createStringError("failed to get response for Wasm variable");
+
+ WritableDataBufferSP buffer_sp(
+ new DataBufferHeap(response.GetStringRef().size() / 2, 0));
+ response.GetHexBytes(buffer_sp->GetData(), '\xcc');
+ return buffer_sp;
+}
diff --git a/lldb/source/Plugins/Process/wasm/ProcessWasm.h b/lldb/source/Plugins/Process/wasm/ProcessWasm.h
index bab14a8..22effe7 100644
--- a/lldb/source/Plugins/Process/wasm/ProcessWasm.h
+++ b/lldb/source/Plugins/Process/wasm/ProcessWasm.h
@@ -10,6 +10,7 @@
#define LLDB_SOURCE_PLUGINS_PROCESS_WASM_PROCESSWASM_H
#include "Plugins/Process/gdb-remote/ProcessGDBRemote.h"
+#include "Utility/WasmVirtualRegisters.h"
namespace lldb_private {
namespace wasm {
@@ -71,12 +72,19 @@ public:
/// Retrieve the current call stack from the WebAssembly remote process.
llvm::Expected<std::vector<lldb::addr_t>> GetWasmCallStack(lldb::tid_t tid);
+ /// Query the value of a WebAssembly variable from the WebAssembly
+ /// remote process.
+ llvm::Expected<lldb::DataBufferSP>
+ GetWasmVariable(WasmVirtualRegisterKinds kind, int frame_index, int index);
+
protected:
std::shared_ptr<process_gdb_remote::ThreadGDBRemote>
CreateThread(lldb::tid_t tid) override;
private:
friend class UnwindWasm;
+ friend class ThreadWasm;
+
process_gdb_remote::GDBRemoteDynamicRegisterInfoSP &GetRegisterInfo() {
return m_register_info_sp;
}
diff --git a/lldb/source/Plugins/Process/wasm/RegisterContextWasm.cpp b/lldb/source/Plugins/Process/wasm/RegisterContextWasm.cpp
new file mode 100644
index 0000000..b468171
--- /dev/null
+++ b/lldb/source/Plugins/Process/wasm/RegisterContextWasm.cpp
@@ -0,0 +1,109 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "RegisterContextWasm.h"
+#include "Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h"
+#include "ProcessWasm.h"
+#include "ThreadWasm.h"
+#include "lldb/Utility/LLDBLog.h"
+#include "lldb/Utility/Log.h"
+#include "lldb/Utility/RegisterValue.h"
+#include "llvm/Support/Error.h"
+#include <memory>
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::process_gdb_remote;
+using namespace lldb_private::wasm;
+
+RegisterContextWasm::RegisterContextWasm(
+ wasm::ThreadWasm &thread, uint32_t concrete_frame_idx,
+ GDBRemoteDynamicRegisterInfoSP reg_info_sp)
+ : GDBRemoteRegisterContext(thread, concrete_frame_idx, reg_info_sp, false,
+ false) {}
+
+RegisterContextWasm::~RegisterContextWasm() = default;
+
+uint32_t RegisterContextWasm::ConvertRegisterKindToRegisterNumber(
+ lldb::RegisterKind kind, uint32_t num) {
+ return num;
+}
+
+size_t RegisterContextWasm::GetRegisterCount() {
+ // Wasm has no registers.
+ return 0;
+}
+
+const RegisterInfo *RegisterContextWasm::GetRegisterInfoAtIndex(size_t reg) {
+ uint32_t tag = GetWasmVirtualRegisterTag(reg);
+ if (tag == eWasmTagNotAWasmLocation)
+ return m_reg_info_sp->GetRegisterInfoAtIndex(
+ GetWasmVirtualRegisterIndex(reg));
+
+ auto it = m_register_map.find(reg);
+ if (it == m_register_map.end()) {
+ WasmVirtualRegisterKinds kind = static_cast<WasmVirtualRegisterKinds>(tag);
+ std::tie(it, std::ignore) = m_register_map.insert(
+ {reg, std::make_unique<WasmVirtualRegisterInfo>(
+ kind, GetWasmVirtualRegisterIndex(reg))});
+ }
+ return it->second.get();
+}
+
+size_t RegisterContextWasm::GetRegisterSetCount() { return 0; }
+
+const RegisterSet *RegisterContextWasm::GetRegisterSet(size_t reg_set) {
+ // Wasm has no registers.
+ return nullptr;
+}
+
+bool RegisterContextWasm::ReadRegister(const RegisterInfo *reg_info,
+ RegisterValue &value) {
+ // The only real registers is the PC.
+ if (reg_info->name)
+ return GDBRemoteRegisterContext::ReadRegister(reg_info, value);
+
+ // Read the virtual registers.
+ ThreadWasm *thread = static_cast<ThreadWasm *>(&GetThread());
+ ProcessWasm *process = static_cast<ProcessWasm *>(thread->GetProcess().get());
+ if (!thread)
+ return false;
+
+ uint32_t frame_index = m_concrete_frame_idx;
+ WasmVirtualRegisterInfo *wasm_reg_info =
+ static_cast<WasmVirtualRegisterInfo *>(
+ const_cast<RegisterInfo *>(reg_info));
+
+ llvm::Expected<DataBufferSP> maybe_buffer = process->GetWasmVariable(
+ wasm_reg_info->kind, frame_index, wasm_reg_info->index);
+ if (!maybe_buffer) {
+ LLDB_LOG_ERROR(GetLog(LLDBLog::Process), maybe_buffer.takeError(),
+ "Failed to read Wasm local: {0}");
+ return false;
+ }
+
+ DataBufferSP buffer_sp = *maybe_buffer;
+ DataExtractor reg_data(buffer_sp, process->GetByteOrder(),
+ process->GetAddressByteSize());
+ wasm_reg_info->byte_size = buffer_sp->GetByteSize();
+ wasm_reg_info->encoding = lldb::eEncodingUint;
+
+ Status error = value.SetValueFromData(
+ *reg_info, reg_data, reg_info->byte_offset, /*partial_data_ok=*/false);
+ return error.Success();
+}
+
+void RegisterContextWasm::InvalidateAllRegisters() {}
+
+bool RegisterContextWasm::WriteRegister(const RegisterInfo *reg_info,
+ const RegisterValue &value) {
+ // The only real registers is the PC.
+ if (reg_info->name)
+ return GDBRemoteRegisterContext::WriteRegister(reg_info, value);
+ return false;
+}
diff --git a/lldb/source/Plugins/Process/wasm/RegisterContextWasm.h b/lldb/source/Plugins/Process/wasm/RegisterContextWasm.h
new file mode 100644
index 0000000..7e63eb8
--- /dev/null
+++ b/lldb/source/Plugins/Process/wasm/RegisterContextWasm.h
@@ -0,0 +1,69 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_SOURCE_PLUGINS_PROCESS_WASM_REGISTERCONTEXTWASM_H
+#define LLDB_SOURCE_PLUGINS_PROCESS_WASM_REGISTERCONTEXTWASM_H
+
+#include "Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h"
+#include "ThreadWasm.h"
+#include "Utility/WasmVirtualRegisters.h"
+#include "lldb/lldb-private-types.h"
+#include <unordered_map>
+
+namespace lldb_private {
+namespace wasm {
+
+class RegisterContextWasm;
+
+typedef std::shared_ptr<RegisterContextWasm> RegisterContextWasmSP;
+
+struct WasmVirtualRegisterInfo : public RegisterInfo {
+ WasmVirtualRegisterKinds kind;
+ uint32_t index;
+
+ WasmVirtualRegisterInfo(WasmVirtualRegisterKinds kind, uint32_t index)
+ : RegisterInfo(), kind(kind), index(index) {}
+};
+
+class RegisterContextWasm
+ : public process_gdb_remote::GDBRemoteRegisterContext {
+public:
+ RegisterContextWasm(
+ wasm::ThreadWasm &thread, uint32_t concrete_frame_idx,
+ process_gdb_remote::GDBRemoteDynamicRegisterInfoSP reg_info_sp);
+
+ ~RegisterContextWasm() override;
+
+ uint32_t ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind,
+ uint32_t num) override;
+
+ void InvalidateAllRegisters() override;
+
+ size_t GetRegisterCount() override;
+
+ const RegisterInfo *GetRegisterInfoAtIndex(size_t reg) override;
+
+ size_t GetRegisterSetCount() override;
+
+ const RegisterSet *GetRegisterSet(size_t reg_set) override;
+
+ bool ReadRegister(const RegisterInfo *reg_info,
+ RegisterValue &value) override;
+
+ bool WriteRegister(const RegisterInfo *reg_info,
+ const RegisterValue &value) override;
+
+private:
+ std::unordered_map<size_t, std::unique_ptr<WasmVirtualRegisterInfo>>
+ m_register_map;
+};
+
+} // namespace wasm
+} // namespace lldb_private
+
+#endif
diff --git a/lldb/source/Plugins/Process/wasm/ThreadWasm.cpp b/lldb/source/Plugins/Process/wasm/ThreadWasm.cpp
index a6553ff..0666b75 100644
--- a/lldb/source/Plugins/Process/wasm/ThreadWasm.cpp
+++ b/lldb/source/Plugins/Process/wasm/ThreadWasm.cpp
@@ -9,6 +9,7 @@
#include "ThreadWasm.h"
#include "ProcessWasm.h"
+#include "RegisterContextWasm.h"
#include "UnwindWasm.h"
#include "lldb/Target/Target.h"
@@ -32,3 +33,19 @@ llvm::Expected<std::vector<lldb::addr_t>> ThreadWasm::GetWasmCallStack() {
}
return llvm::createStringError("no process");
}
+
+lldb::RegisterContextSP
+ThreadWasm::CreateRegisterContextForFrame(StackFrame *frame) {
+ uint32_t concrete_frame_idx = 0;
+ ProcessSP process_sp(GetProcess());
+ ProcessWasm *wasm_process = static_cast<ProcessWasm *>(process_sp.get());
+
+ if (frame)
+ concrete_frame_idx = frame->GetConcreteFrameIndex();
+
+ if (concrete_frame_idx == 0)
+ return std::make_shared<RegisterContextWasm>(
+ *this, concrete_frame_idx, wasm_process->GetRegisterInfo());
+
+ return GetUnwinder().CreateRegisterContextForFrame(frame);
+}
diff --git a/lldb/source/Plugins/Process/wasm/ThreadWasm.h b/lldb/source/Plugins/Process/wasm/ThreadWasm.h
index 1c90f58..c2f5762 100644
--- a/lldb/source/Plugins/Process/wasm/ThreadWasm.h
+++ b/lldb/source/Plugins/Process/wasm/ThreadWasm.h
@@ -25,6 +25,9 @@ public:
/// Retrieve the current call stack from the WebAssembly remote process.
llvm::Expected<std::vector<lldb::addr_t>> GetWasmCallStack();
+ lldb::RegisterContextSP
+ CreateRegisterContextForFrame(StackFrame *frame) override;
+
protected:
Unwind &GetUnwinder() override;
diff --git a/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp b/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp
index 81c6731..591fded 100644
--- a/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp
+++ b/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp
@@ -738,9 +738,29 @@ size_t SymbolFileCTF::ParseTypes(CompileUnit &cu) {
LLDB_LOG(log, "Parsed {0} CTF types", m_ctf_types.size());
- for (lldb::user_id_t uid = 1; uid < type_uid; ++uid)
+ for (lldb::user_id_t uid = 1; uid < type_uid; ++uid) {
ResolveTypeUID(uid);
+ // Remove the CTF type because we don't need it anymore, except for record
+ // types which we may need to complete later.
+ auto ctf_type_it = m_ctf_types.find(uid);
+ if (ctf_type_it != m_ctf_types.end()) {
+ CTFType *ctf_type = ctf_type_it->second.get();
+ if (!llvm::isa<CTFRecord>(ctf_type))
+ m_ctf_types.erase(uid);
+ }
+ }
+
+#ifndef NDEBUG
+ // Verify that the only CTF types left at this point are record types.
+ for (auto &t : m_ctf_types) {
+ CTFType *ctf_type = t.second.get();
+ assert(ctf_type && "invalid type in m_ctf_types");
+ assert(llvm::isa<CTFRecord>(ctf_type) && "leaking non record type");
+ }
+
+#endif
+
LLDB_LOG(log, "Created {0} CTF types", m_types.size());
return m_types.size();
@@ -994,6 +1014,8 @@ lldb_private::Type *SymbolFileCTF::ResolveTypeUID(lldb::user_id_t type_uid) {
CTFType *ctf_type = ctf_type_it->second.get();
assert(ctf_type && "m_ctf_types should only contain valid CTF types");
+ assert(ctf_type->uid == type_uid &&
+ "CTF type UID doesn't match UID in m_ctf_types");
Log *log = GetLog(LLDBLog::Symbols);
@@ -1015,11 +1037,6 @@ lldb_private::Type *SymbolFileCTF::ResolveTypeUID(lldb::user_id_t type_uid) {
m_types[type_uid] = type_sp;
- // Except for record types which we'll need to complete later, we don't need
- // the CTF type anymore.
- if (!isa<CTFRecord>(ctf_type))
- m_ctf_types.erase(type_uid);
-
return type_sp.get();
}
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp b/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp
index 4bfbb4d..9762ead 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp
@@ -13,6 +13,7 @@
#include "lldb/Core/Module.h"
#include "lldb/Symbol/Function.h"
+#include "lldb/lldb-private-enumerations.h"
#include "llvm/Support/DJB.h"
using namespace lldb;
@@ -275,7 +276,7 @@ void AppleDWARFIndex::GetNamespaces(
void AppleDWARFIndex::GetFunctions(
const Module::LookupInfo &lookup_info, SymbolFileDWARF &dwarf,
const CompilerDeclContext &parent_decl_ctx,
- llvm::function_ref<bool(DWARFDIE die)> callback) {
+ llvm::function_ref<IterationAction(DWARFDIE die)> callback) {
if (!m_apple_names_up)
return;
@@ -288,15 +289,16 @@ void AppleDWARFIndex::GetFunctions(
ReportInvalidDIERef(die_ref, name);
continue;
}
- if (!ProcessFunctionDIE(lookup_info, die, parent_decl_ctx, callback))
+ if (ProcessFunctionDIE(lookup_info, die, parent_decl_ctx, callback) ==
+ IterationAction::Stop)
return;
}
}
void AppleDWARFIndex::GetFunctions(
const RegularExpression &regex,
- llvm::function_ref<bool(DWARFDIE die)> callback) {
- return GetGlobalVariables(regex, callback);
+ llvm::function_ref<IterationAction(DWARFDIE die)> callback) {
+ return GetGlobalVariables(regex, IterationActionAdaptor(callback));
}
void AppleDWARFIndex::Dump(Stream &s) {
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.h b/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.h
index 73de75b..c0f0eb6 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.h
@@ -61,12 +61,13 @@ public:
llvm::function_ref<bool(DWARFDIE die)> callback) override;
void GetNamespaces(ConstString name,
llvm::function_ref<bool(DWARFDIE die)> callback) override;
- void GetFunctions(const Module::LookupInfo &lookup_info,
- SymbolFileDWARF &dwarf,
- const CompilerDeclContext &parent_decl_ctx,
- llvm::function_ref<bool(DWARFDIE die)> callback) override;
- void GetFunctions(const RegularExpression &regex,
- llvm::function_ref<bool(DWARFDIE die)> callback) override;
+ void GetFunctions(
+ const Module::LookupInfo &lookup_info, SymbolFileDWARF &dwarf,
+ const CompilerDeclContext &parent_decl_ctx,
+ llvm::function_ref<IterationAction(DWARFDIE die)> callback) override;
+ void GetFunctions(
+ const RegularExpression &regex,
+ llvm::function_ref<IterationAction(DWARFDIE die)> callback) override;
void Dump(Stream &s) override;
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index ba65f50..781c1c6c 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -24,6 +24,7 @@
#include "Plugins/Language/ObjC/ObjCLanguage.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/Value.h"
+#include "lldb/Expression/Expression.h"
#include "lldb/Host/Host.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/Function.h"
@@ -249,6 +250,47 @@ static unsigned GetCXXMethodCVQuals(const DWARFDIE &subprogram,
return cv_quals;
}
+static std::string MakeLLDBFuncAsmLabel(const DWARFDIE &die) {
+ char const *name = die.GetMangledName(/*substitute_name_allowed*/ false);
+ if (!name)
+ return {};
+
+ SymbolFileDWARF *dwarf = die.GetDWARF();
+ if (!dwarf)
+ return {};
+
+ auto get_module_id = [&](SymbolFile *sym) {
+ if (!sym)
+ return LLDB_INVALID_UID;
+
+ auto *obj = sym->GetMainObjectFile();
+ if (!obj)
+ return LLDB_INVALID_UID;
+
+ auto module_sp = obj->GetModule();
+ if (!module_sp)
+ return LLDB_INVALID_UID;
+
+ return module_sp->GetID();
+ };
+
+ lldb::user_id_t module_id = get_module_id(dwarf->GetDebugMapSymfile());
+ if (module_id == LLDB_INVALID_UID)
+ module_id = get_module_id(dwarf);
+
+ if (module_id == LLDB_INVALID_UID)
+ return {};
+
+ const auto die_id = die.GetID();
+ if (die_id == LLDB_INVALID_UID)
+ return {};
+
+ return FunctionCallLabel{/*module_id=*/module_id,
+ /*symbol_id=*/die_id,
+ /*.lookup_name=*/name}
+ .toString();
+}
+
TypeSP DWARFASTParserClang::ParseTypeFromClangModule(const SymbolContext &sc,
const DWARFDIE &die,
Log *log) {
@@ -1231,7 +1273,7 @@ std::pair<bool, TypeSP> DWARFASTParserClang::ParseCXXMethod(
clang::CXXMethodDecl *cxx_method_decl = m_ast.AddMethodToCXXRecordType(
class_opaque_type.GetOpaqueQualType(), attrs.name.GetCString(),
- attrs.mangled_name, clang_type, accessibility, attrs.is_virtual,
+ MakeLLDBFuncAsmLabel(die), clang_type, accessibility, attrs.is_virtual,
is_static, attrs.is_inline, attrs.is_explicit, is_attr_used,
attrs.is_artificial);
@@ -1384,7 +1426,7 @@ DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die,
ignore_containing_context ? m_ast.GetTranslationUnitDecl()
: containing_decl_ctx,
GetOwningClangModule(die), name, clang_type, attrs.storage,
- attrs.is_inline);
+ attrs.is_inline, MakeLLDBFuncAsmLabel(die));
std::free(name_buf);
if (has_template_params) {
@@ -1394,7 +1436,7 @@ DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die,
ignore_containing_context ? m_ast.GetTranslationUnitDecl()
: containing_decl_ctx,
GetOwningClangModule(die), attrs.name.GetStringRef(), clang_type,
- attrs.storage, attrs.is_inline);
+ attrs.storage, attrs.is_inline, /*asm_label=*/{});
clang::FunctionTemplateDecl *func_template_decl =
m_ast.CreateFunctionTemplateDecl(
containing_decl_ctx, GetOwningClangModule(die),
@@ -1406,20 +1448,6 @@ DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die,
lldbassert(function_decl);
if (function_decl) {
- // Attach an asm(<mangled_name>) label to the FunctionDecl.
- // This ensures that clang::CodeGen emits function calls
- // using symbols that are mangled according to the DW_AT_linkage_name.
- // If we didn't do this, the external symbols wouldn't exactly
- // match the mangled name LLDB knows about and the IRExecutionUnit
- // would have to fall back to searching object files for
- // approximately matching function names. The motivating
- // example is generating calls to ABI-tagged template functions.
- // This is done separately for member functions in
- // AddMethodToCXXRecordType.
- if (attrs.mangled_name)
- function_decl->addAttr(clang::AsmLabelAttr::CreateImplicit(
- m_ast.getASTContext(), attrs.mangled_name, /*literal=*/false));
-
LinkDeclContextToDIE(function_decl, die);
const clang::FunctionProtoType *function_prototype(
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp
index 30c890d..a806506 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp
@@ -16,6 +16,7 @@
#include "lldb/Core/Mangled.h"
#include "lldb/Core/Module.h"
#include "lldb/Target/Language.h"
+#include "lldb/lldb-private-enumerations.h"
using namespace lldb_private;
using namespace lldb;
@@ -23,10 +24,10 @@ using namespace lldb_private::plugin::dwarf;
DWARFIndex::~DWARFIndex() = default;
-bool DWARFIndex::ProcessFunctionDIE(
+IterationAction DWARFIndex::ProcessFunctionDIE(
const Module::LookupInfo &lookup_info, DWARFDIE die,
const CompilerDeclContext &parent_decl_ctx,
- llvm::function_ref<bool(DWARFDIE die)> callback) {
+ llvm::function_ref<IterationAction(DWARFDIE die)> callback) {
llvm::StringRef name = lookup_info.GetLookupName().GetStringRef();
FunctionNameType name_type_mask = lookup_info.GetNameTypeMask();
@@ -43,7 +44,7 @@ bool DWARFIndex::ProcessFunctionDIE(
if (!lookup_info.NameMatchesLookupInfo(name_to_match_against,
lookup_info.GetLanguageType()))
- return true;
+ return IterationAction::Continue;
}
// Exit early if we're searching exclusively for methods or selectors and
@@ -51,12 +52,12 @@ bool DWARFIndex::ProcessFunctionDIE(
uint32_t looking_for_nonmethods =
name_type_mask & ~(eFunctionNameTypeMethod | eFunctionNameTypeSelector);
if (!looking_for_nonmethods && parent_decl_ctx.IsValid())
- return true;
+ return IterationAction::Continue;
// Otherwise, we need to also check that the context matches. If it does not
// match, we do nothing.
if (!SymbolFileDWARF::DIEInDeclContext(parent_decl_ctx, die))
- return true;
+ return IterationAction::Continue;
// In case of a full match, we just insert everything we find.
if (name_type_mask & eFunctionNameTypeFull && die.GetMangledName() == name)
@@ -79,7 +80,7 @@ bool DWARFIndex::ProcessFunctionDIE(
return callback(die);
}
- return true;
+ return IterationAction::Continue;
}
DWARFIndex::DIERefCallbackImpl::DIERefCallbackImpl(
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.h
index 15d8503..3578824 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.h
@@ -16,6 +16,7 @@
#include "lldb/Core/Module.h"
#include "lldb/Target/Statistics.h"
+#include "lldb/lldb-private-enumerations.h"
namespace lldb_private::plugin {
namespace dwarf {
@@ -82,10 +83,10 @@ public:
virtual void
GetFunctions(const Module::LookupInfo &lookup_info, SymbolFileDWARF &dwarf,
const CompilerDeclContext &parent_decl_ctx,
- llvm::function_ref<bool(DWARFDIE die)> callback) = 0;
+ llvm::function_ref<IterationAction(DWARFDIE die)> callback) = 0;
virtual void
GetFunctions(const RegularExpression &regex,
- llvm::function_ref<bool(DWARFDIE die)> callback) = 0;
+ llvm::function_ref<IterationAction(DWARFDIE die)> callback) = 0;
virtual void Dump(Stream &s) = 0;
@@ -101,9 +102,10 @@ protected:
/// the function given by "die" matches search criteria given by
/// "parent_decl_ctx" and "name_type_mask", it calls the callback with the
/// given die.
- bool ProcessFunctionDIE(const Module::LookupInfo &lookup_info, DWARFDIE die,
- const CompilerDeclContext &parent_decl_ctx,
- llvm::function_ref<bool(DWARFDIE die)> callback);
+ IterationAction ProcessFunctionDIE(
+ const Module::LookupInfo &lookup_info, DWARFDIE die,
+ const CompilerDeclContext &parent_decl_ctx,
+ llvm::function_ref<IterationAction(DWARFDIE die)> callback);
class DIERefCallbackImpl {
public:
@@ -140,6 +142,25 @@ protected:
bool ProcessNamespaceDieMatchParents(
const CompilerDeclContext &parent_decl_ctx, DWARFDIE die,
llvm::function_ref<bool(DWARFDIE die)> callback);
+
+ /// Helper to convert callbacks that return an \c IterationAction
+ /// to a callback that returns a \c bool, where \c true indicates
+ /// we should continue iterating. This will be used to incrementally
+ /// migrate the callbacks to return an \c IterationAction.
+ ///
+ /// FIXME: remove once all callbacks in the DWARFIndex APIs return
+ /// IterationAction.
+ struct IterationActionAdaptor {
+ IterationActionAdaptor(
+ llvm::function_ref<IterationAction(DWARFDIE die)> callback)
+ : m_callback_ref(callback) {}
+
+ bool operator()(DWARFDIE die) {
+ return m_callback_ref(std::move(die)) == IterationAction::Continue;
+ }
+
+ llvm::function_ref<IterationAction(DWARFDIE die)> m_callback_ref;
+ };
};
} // namespace dwarf
} // namespace lldb_private::plugin
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp
index ff1a76b..3ae9fcc 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp
@@ -14,6 +14,7 @@
#include "lldb/Core/Module.h"
#include "lldb/Utility/RegularExpression.h"
#include "lldb/Utility/Stream.h"
+#include "lldb/lldb-private-enumerations.h"
#include "llvm/ADT/Sequence.h"
#include <optional>
@@ -607,7 +608,7 @@ void DebugNamesDWARFIndex::GetNamespacesWithParents(
void DebugNamesDWARFIndex::GetFunctions(
const Module::LookupInfo &lookup_info, SymbolFileDWARF &dwarf,
const CompilerDeclContext &parent_decl_ctx,
- llvm::function_ref<bool(DWARFDIE die)> callback) {
+ llvm::function_ref<IterationAction(DWARFDIE die)> callback) {
ConstString name = lookup_info.GetLookupName();
std::set<DWARFDebugInfoEntry *> seen;
for (const DebugNames::Entry &entry :
@@ -617,12 +618,12 @@ void DebugNamesDWARFIndex::GetFunctions(
continue;
if (DWARFDIE die = GetDIE(entry)) {
- if (!ProcessFunctionDIE(lookup_info, die, parent_decl_ctx,
- [&](DWARFDIE die) {
- if (!seen.insert(die.GetDIE()).second)
- return true;
- return callback(die);
- }))
+ if (ProcessFunctionDIE(lookup_info, die, parent_decl_ctx,
+ [&](DWARFDIE die) {
+ if (!seen.insert(die.GetDIE()).second)
+ return IterationAction::Continue;
+ return callback(die);
+ }) == IterationAction::Stop)
return;
}
}
@@ -632,7 +633,7 @@ void DebugNamesDWARFIndex::GetFunctions(
void DebugNamesDWARFIndex::GetFunctions(
const RegularExpression &regex,
- llvm::function_ref<bool(DWARFDIE die)> callback) {
+ llvm::function_ref<IterationAction(DWARFDIE die)> callback) {
for (const DebugNames::NameIndex &ni: *m_debug_names_up) {
for (DebugNames::NameTableEntry nte: ni) {
if (!regex.Execute(nte.getString()))
@@ -645,7 +646,7 @@ void DebugNamesDWARFIndex::GetFunctions(
if (tag != DW_TAG_subprogram && tag != DW_TAG_inlined_subroutine)
continue;
- if (!ProcessEntry(*entry_or, callback))
+ if (!ProcessEntry(*entry_or, IterationActionAdaptor(callback)))
return;
}
MaybeLogLookupError(entry_or.takeError(), ni, nte.getString());
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h b/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h
index ab6cde1..2105919 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h
@@ -58,12 +58,13 @@ public:
void GetNamespacesWithParents(
ConstString name, const CompilerDeclContext &parent_decl_ctx,
llvm::function_ref<bool(DWARFDIE die)> callback) override;
- void GetFunctions(const Module::LookupInfo &lookup_info,
- SymbolFileDWARF &dwarf,
- const CompilerDeclContext &parent_decl_ctx,
- llvm::function_ref<bool(DWARFDIE die)> callback) override;
- void GetFunctions(const RegularExpression &regex,
- llvm::function_ref<bool(DWARFDIE die)> callback) override;
+ void GetFunctions(
+ const Module::LookupInfo &lookup_info, SymbolFileDWARF &dwarf,
+ const CompilerDeclContext &parent_decl_ctx,
+ llvm::function_ref<IterationAction(DWARFDIE die)> callback) override;
+ void GetFunctions(
+ const RegularExpression &regex,
+ llvm::function_ref<IterationAction(DWARFDIE die)> callback) override;
void Dump(Stream &s) override;
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp b/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
index c858ce2..f96ac7e 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
@@ -21,6 +21,7 @@
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/Timer.h"
+#include "lldb/lldb-private-enumerations.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/ThreadPool.h"
#include <atomic>
@@ -471,60 +472,62 @@ void ManualDWARFIndex::GetNamespaces(
void ManualDWARFIndex::GetFunctions(
const Module::LookupInfo &lookup_info, SymbolFileDWARF &dwarf,
const CompilerDeclContext &parent_decl_ctx,
- llvm::function_ref<bool(DWARFDIE die)> callback) {
+ llvm::function_ref<IterationAction(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(
- name, DIERefCallback(
- [&](DWARFDIE die) {
- if (!SymbolFileDWARF::DIEInDeclContext(parent_decl_ctx,
- die))
- return true;
- return callback(die);
- },
- name.GetStringRef())))
+ name, DIERefCallback(IterationActionAdaptor([&](DWARFDIE die) {
+ if (!SymbolFileDWARF::DIEInDeclContext(
+ parent_decl_ctx, die))
+ return IterationAction::Continue;
+ return callback(die);
+ }),
+ name.GetStringRef())))
return;
}
if (name_type_mask & eFunctionNameTypeBase) {
if (!m_set.function_basenames.Find(
- name, DIERefCallback(
- [&](DWARFDIE die) {
- if (!SymbolFileDWARF::DIEInDeclContext(parent_decl_ctx,
- die))
- return true;
- return callback(die);
- },
- name.GetStringRef())))
+ name, DIERefCallback(IterationActionAdaptor([&](DWARFDIE die) {
+ if (!SymbolFileDWARF::DIEInDeclContext(
+ parent_decl_ctx, die))
+ return IterationAction::Continue;
+ return callback(die);
+ }),
+ name.GetStringRef())))
return;
}
if (name_type_mask & eFunctionNameTypeMethod && !parent_decl_ctx.IsValid()) {
if (!m_set.function_methods.Find(
- name, DIERefCallback(callback, name.GetStringRef())))
+ name, DIERefCallback(IterationActionAdaptor(callback),
+ name.GetStringRef())))
return;
}
if (name_type_mask & eFunctionNameTypeSelector &&
!parent_decl_ctx.IsValid()) {
if (!m_set.function_selectors.Find(
- name, DIERefCallback(callback, name.GetStringRef())))
+ name, DIERefCallback(IterationActionAdaptor(callback),
+ name.GetStringRef())))
return;
}
}
void ManualDWARFIndex::GetFunctions(
const RegularExpression &regex,
- llvm::function_ref<bool(DWARFDIE die)> callback) {
+ llvm::function_ref<IterationAction(DWARFDIE die)> callback) {
Index();
- if (!m_set.function_basenames.Find(regex,
- DIERefCallback(callback, regex.GetText())))
+ if (!m_set.function_basenames.Find(
+ regex,
+ DIERefCallback(IterationActionAdaptor(callback), regex.GetText())))
return;
- if (!m_set.function_fullnames.Find(regex,
- DIERefCallback(callback, regex.GetText())))
+ if (!m_set.function_fullnames.Find(
+ regex,
+ DIERefCallback(IterationActionAdaptor(callback), regex.GetText())))
return;
}
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h b/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h
index 04627b0..5685ba4 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h
@@ -50,12 +50,13 @@ public:
llvm::function_ref<bool(DWARFDIE die)> callback) override;
void GetNamespaces(ConstString name,
llvm::function_ref<bool(DWARFDIE die)> callback) override;
- void GetFunctions(const Module::LookupInfo &lookup_info,
- SymbolFileDWARF &dwarf,
- const CompilerDeclContext &parent_decl_ctx,
- llvm::function_ref<bool(DWARFDIE die)> callback) override;
- void GetFunctions(const RegularExpression &regex,
- llvm::function_ref<bool(DWARFDIE die)> callback) override;
+ void GetFunctions(
+ const Module::LookupInfo &lookup_info, SymbolFileDWARF &dwarf,
+ const CompilerDeclContext &parent_decl_ctx,
+ llvm::function_ref<IterationAction(DWARFDIE die)> callback) override;
+ void GetFunctions(
+ const RegularExpression &regex,
+ llvm::function_ref<IterationAction(DWARFDIE die)> callback) override;
void Dump(Stream &s) override;
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index 41ab8d1..a3ba061 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -74,6 +74,7 @@
#include "ManualDWARFIndex.h"
#include "SymbolFileDWARFDebugMap.h"
#include "SymbolFileDWARFDwo.h"
+#include "lldb/lldb-private-enumerations.h"
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
@@ -2475,6 +2476,55 @@ bool SymbolFileDWARF::ResolveFunction(const DWARFDIE &orig_die,
return false;
}
+llvm::Expected<SymbolContext>
+SymbolFileDWARF::ResolveFunctionCallLabel(const FunctionCallLabel &label) {
+ std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
+
+ DWARFDIE die = GetDIE(label.symbol_id);
+ if (!die.IsValid())
+ return llvm::createStringError(
+ llvm::formatv("invalid DIE ID in {0}", label));
+
+ // Label was created using a declaration DIE. Need to fetch the definition
+ // to resolve the function call.
+ if (die.GetAttributeValueAsUnsigned(llvm::dwarf::DW_AT_declaration, 0)) {
+ Module::LookupInfo info(ConstString(label.lookup_name),
+ lldb::eFunctionNameTypeFull,
+ lldb::eLanguageTypeUnknown);
+
+ m_index->GetFunctions(info, *this, {}, [&](DWARFDIE entry) {
+ if (entry.GetAttributeValueAsUnsigned(llvm::dwarf::DW_AT_declaration, 0))
+ return IterationAction::Continue;
+
+ // We don't check whether the specification DIE for this function
+ // corresponds to the declaration DIE because the declaration might be in
+ // a type-unit but the definition in the compile-unit (and it's
+ // specifcation would point to the declaration in the compile-unit). We
+ // rely on the mangled name within the module to be enough to find us the
+ // unique definition.
+ die = entry;
+ return IterationAction::Stop;
+ });
+
+ if (die.GetAttributeValueAsUnsigned(llvm::dwarf::DW_AT_declaration, 0))
+ return llvm::createStringError(
+ llvm::formatv("failed to find definition DIE for {0}", label));
+ }
+
+ SymbolContextList sc_list;
+ if (!ResolveFunction(die, /*include_inlines=*/false, sc_list))
+ return llvm::createStringError(
+ llvm::formatv("failed to resolve function for {0}", label));
+
+ if (sc_list.IsEmpty())
+ return llvm::createStringError(
+ llvm::formatv("failed to find function for {0}", label));
+
+ assert(sc_list.GetSize() == 1);
+
+ return sc_list[0];
+}
+
bool SymbolFileDWARF::DIEInDeclContext(const CompilerDeclContext &decl_ctx,
const DWARFDIE &die,
bool only_root_namespaces) {
@@ -2539,7 +2589,7 @@ void SymbolFileDWARF::FindFunctions(const Module::LookupInfo &lookup_info,
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;
+ return IterationAction::Continue;
});
// With -gsimple-template-names, a templated type's DW_AT_name will not
// contain the template parameters. Try again stripping '<' and anything
@@ -2556,7 +2606,7 @@ void SymbolFileDWARF::FindFunctions(const Module::LookupInfo &lookup_info,
[&](DWARFDIE die) {
if (resolved_dies.insert(die.GetDIE()).second)
ResolveFunction(die, include_inlines, sc_list);
- return true;
+ return IterationAction::Continue;
});
}
}
@@ -2592,7 +2642,7 @@ void SymbolFileDWARF::FindFunctions(const RegularExpression &regex,
m_index->GetFunctions(regex, [&](DWARFDIE die) {
if (resolved_dies.insert(die.GetDIE()).second)
ResolveFunction(die, include_inlines, sc_list);
- return true;
+ return IterationAction::Continue;
});
}
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
index 56d8ccb..3ec538d 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
@@ -436,6 +436,9 @@ protected:
DIEArray MergeBlockAbstractParameters(const DWARFDIE &block_die,
DIEArray &&variable_dies);
+ llvm::Expected<SymbolContext>
+ ResolveFunctionCallLabel(const FunctionCallLabel &label) override;
+
// Given a die_offset, figure out the symbol context representing that die.
bool ResolveFunction(const DWARFDIE &die, bool include_inlines,
SymbolContextList &sc_list);
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
index dd94f0b..9d7452a 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
@@ -1602,3 +1602,14 @@ void SymbolFileDWARFDebugMap::GetCompileOptions(
return IterationAction::Continue;
});
}
+
+llvm::Expected<SymbolContext> SymbolFileDWARFDebugMap::ResolveFunctionCallLabel(
+ const FunctionCallLabel &label) {
+ const uint64_t oso_idx = GetOSOIndexFromUserID(label.symbol_id);
+ SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(oso_idx);
+ if (!oso_dwarf)
+ return llvm::createStringError(llvm::formatv(
+ "couldn't find symbol file for {0} in debug-map.", label));
+
+ return oso_dwarf->ResolveFunctionCallLabel(label);
+}
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
index f074b17..e1f1df23 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
@@ -144,6 +144,9 @@ public:
void
GetCompileOptions(std::unordered_map<lldb::CompUnitSP, Args> &args) override;
+ llvm::Expected<SymbolContext>
+ ResolveFunctionCallLabel(const FunctionCallLabel &label) override;
+
protected:
enum { kHaveInitializedOSOs = (1 << 0), kNumFlags };
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
index 702ec5e..8137622 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
@@ -88,7 +88,7 @@ struct CreateMethodDecl : public TypeVisitorCallbacks {
MethodOptions::CompilerGenerated;
function_decl = m_clang.AddMethodToCXXRecordType(
parent_ty, proc_name,
- /*mangled_name=*/nullptr, func_ct, /*access=*/access_type,
+ /*asm_label=*/{}, func_ct, /*access=*/access_type,
/*is_virtual=*/is_virtual, /*is_static=*/is_static,
/*is_inline=*/false, /*is_explicit=*/false,
/*is_attr_used=*/false, /*is_artificial=*/is_artificial);
@@ -903,7 +903,7 @@ PdbAstBuilder::CreateFunctionDecl(PdbCompilandSymId func_id,
if (!function_decl) {
function_decl = m_clang.AddMethodToCXXRecordType(
parent_opaque_ty, func_name,
- /*mangled_name=*/nullptr, func_ct,
+ /*asm_label=*/{}, func_ct,
/*access=*/lldb::AccessType::eAccessPublic,
/*is_virtual=*/false, /*is_static=*/false,
/*is_inline=*/false, /*is_explicit=*/false,
@@ -913,7 +913,7 @@ PdbAstBuilder::CreateFunctionDecl(PdbCompilandSymId func_id,
} else {
function_decl = m_clang.CreateFunctionDeclaration(
parent, OptionalClangModuleID(), func_name, func_ct, func_storage,
- is_inline);
+ is_inline, /*asm_label=*/{});
CreateFunctionParameters(func_id, *function_decl, param_count);
}
return function_decl;
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp
index 807ee5b..1c575e9 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp
@@ -111,9 +111,8 @@ void UdtRecordCompleter::AddMethod(llvm::StringRef name, TypeIndex type_idx,
bool is_artificial = (options & MethodOptions::CompilerGenerated) ==
MethodOptions::CompilerGenerated;
m_ast_builder.clang().AddMethodToCXXRecordType(
- derived_opaque_ty, name.data(), nullptr, method_ct,
- access_type, attrs.isVirtual(), attrs.isStatic(), false, false, false,
- is_artificial);
+ derived_opaque_ty, name.data(), /*asm_label=*/{}, method_ct, access_type,
+ attrs.isVirtual(), attrs.isStatic(), false, false, false, is_artificial);
m_cxx_record_map[derived_opaque_ty].insert({name, method_ct});
}
diff --git a/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp b/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp
index 0090d8f..8b8eac6e 100644
--- a/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp
+++ b/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp
@@ -954,7 +954,8 @@ PDBASTParser::GetDeclForSymbol(const llvm::pdb::PDBSymbol &symbol) {
auto decl = m_ast.CreateFunctionDeclaration(
decl_context, OptionalClangModuleID(), name,
- type->GetForwardCompilerType(), storage, func->hasInlineAttribute());
+ type->GetForwardCompilerType(), storage, func->hasInlineAttribute(),
+ /*asm_label=*/{});
std::vector<clang::ParmVarDecl *> params;
if (std::unique_ptr<PDBSymbolTypeFunctionSig> sig = func->getSignature()) {
@@ -1446,7 +1447,7 @@ PDBASTParser::AddRecordMethod(lldb_private::SymbolFile &symbol_file,
// TODO: get mangled name for the method.
return m_ast.AddMethodToCXXRecordType(
record_type.GetOpaqueQualType(), name.c_str(),
- /*mangled_name*/ nullptr, method_comp_type, access, method.isVirtual(),
+ /*asm_label=*/{}, method_comp_type, access, method.isVirtual(),
method.isStatic(), method.hasInlineAttribute(),
/*is_explicit*/ false, // FIXME: Need this field in CodeView.
/*is_attr_used*/ false,
diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
index 256952dc..9301f92 100644
--- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
+++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
@@ -60,6 +60,7 @@
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/UniqueCStringMap.h"
+#include "lldb/Expression/Expression.h"
#include "lldb/Host/StreamFile.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/SymbolFile.h"
@@ -665,10 +666,9 @@ void TypeSystemClang::CreateASTContext() {
m_file_manager_up = std::make_unique<clang::FileManager>(
file_system_options, FileSystem::Instance().GetVirtualFileSystem());
- llvm::IntrusiveRefCntPtr<DiagnosticIDs> diag_id_sp(new DiagnosticIDs());
m_diagnostic_options_up = std::make_unique<DiagnosticOptions>();
- m_diagnostics_engine_up =
- std::make_unique<DiagnosticsEngine>(diag_id_sp, *m_diagnostic_options_up);
+ m_diagnostics_engine_up = std::make_unique<DiagnosticsEngine>(
+ DiagnosticIDs::create(), *m_diagnostic_options_up);
m_source_manager_up = std::make_unique<clang::SourceManager>(
*m_diagnostics_engine_up, *m_file_manager_up);
@@ -796,6 +796,8 @@ TypeSystemClang::GetBuiltinTypeForEncodingAndBitSize(Encoding encoding,
return GetType(ast.LongDoubleTy);
if (QualTypeMatchesBitSize(bit_size, ast, ast.HalfTy))
return GetType(ast.HalfTy);
+ if (QualTypeMatchesBitSize(bit_size, ast, ast.Float128Ty))
+ return GetType(ast.Float128Ty);
break;
case eEncodingVector:
@@ -957,6 +959,13 @@ CompilerType TypeSystemClang::GetBuiltinTypeForDWARFEncodingAndBitSize(
if (type_name == "long double" &&
QualTypeMatchesBitSize(bit_size, ast, ast.LongDoubleTy))
return GetType(ast.LongDoubleTy);
+ // As Rust currently uses `TypeSystemClang`, match `f128` here as well so it
+ // doesn't get misinterpreted as `long double` on targets where they are
+ // the same size but different formats.
+ if ((type_name == "__float128" || type_name == "_Float128" ||
+ type_name == "f128") &&
+ QualTypeMatchesBitSize(bit_size, ast, ast.Float128Ty))
+ return GetType(ast.Float128Ty);
// Fall back to not requiring a name match
if (QualTypeMatchesBitSize(bit_size, ast, ast.FloatTy))
return GetType(ast.FloatTy);
@@ -966,6 +975,8 @@ CompilerType TypeSystemClang::GetBuiltinTypeForDWARFEncodingAndBitSize(
return GetType(ast.LongDoubleTy);
if (QualTypeMatchesBitSize(bit_size, ast, ast.HalfTy))
return GetType(ast.HalfTy);
+ if (QualTypeMatchesBitSize(bit_size, ast, ast.Float128Ty))
+ return GetType(ast.Float128Ty);
break;
case DW_ATE_signed:
@@ -2055,6 +2066,8 @@ TypeSystemClang::GetOpaqueCompilerType(clang::ASTContext *ast,
return ast->DoubleTy.getAsOpaquePtr();
case eBasicTypeLongDouble:
return ast->LongDoubleTy.getAsOpaquePtr();
+ case eBasicTypeFloat128:
+ return ast->Float128Ty.getAsOpaquePtr();
case eBasicTypeFloatComplex:
return ast->getComplexType(ast->FloatTy).getAsOpaquePtr();
case eBasicTypeDoubleComplex:
@@ -2137,7 +2150,7 @@ std::string TypeSystemClang::GetTypeNameForDecl(const NamedDecl *named_decl,
FunctionDecl *TypeSystemClang::CreateFunctionDeclaration(
clang::DeclContext *decl_ctx, OptionalClangModuleID owning_module,
llvm::StringRef name, const CompilerType &function_clang_type,
- clang::StorageClass storage, bool is_inline) {
+ clang::StorageClass storage, bool is_inline, llvm::StringRef asm_label) {
FunctionDecl *func_decl = nullptr;
ASTContext &ast = getASTContext();
if (!decl_ctx)
@@ -2158,6 +2171,21 @@ FunctionDecl *TypeSystemClang::CreateFunctionDeclaration(
func_decl->setConstexprKind(isConstexprSpecified
? ConstexprSpecKind::Constexpr
: ConstexprSpecKind::Unspecified);
+
+ // Attach an asm(<mangled_name>) label to the FunctionDecl.
+ // This ensures that clang::CodeGen emits function calls
+ // using symbols that are mangled according to the DW_AT_linkage_name.
+ // If we didn't do this, the external symbols wouldn't exactly
+ // match the mangled name LLDB knows about and the IRExecutionUnit
+ // would have to fall back to searching object files for
+ // approximately matching function names. The motivating
+ // example is generating calls to ABI-tagged template functions.
+ // This is done separately for member functions in
+ // AddMethodToCXXRecordType.
+ if (!asm_label.empty())
+ func_decl->addAttr(clang::AsmLabelAttr::CreateImplicit(ast, asm_label,
+ /*literal=*/true));
+
SetOwningModule(func_decl, owning_module);
decl_ctx->addDecl(func_decl);
@@ -4728,19 +4756,24 @@ CompilerType TypeSystemClang::CreateGenericFunctionPrototype() {
// Exploring the type
const llvm::fltSemantics &
-TypeSystemClang::GetFloatTypeSemantics(size_t byte_size) {
+TypeSystemClang::GetFloatTypeSemantics(size_t byte_size, lldb::Format format) {
clang::ASTContext &ast = getASTContext();
const size_t bit_size = byte_size * 8;
if (bit_size == ast.getTypeSize(ast.FloatTy))
return ast.getFloatTypeSemantics(ast.FloatTy);
else if (bit_size == ast.getTypeSize(ast.DoubleTy))
return ast.getFloatTypeSemantics(ast.DoubleTy);
+ else if (format == eFormatFloat128 &&
+ bit_size == ast.getTypeSize(ast.Float128Ty))
+ return ast.getFloatTypeSemantics(ast.Float128Ty);
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);
+ else if (bit_size == ast.getTypeSize(ast.Float128Ty))
+ return ast.getFloatTypeSemantics(ast.Float128Ty);
return llvm::APFloatBase::Bogus();
}
@@ -5218,6 +5251,8 @@ lldb::Format TypeSystemClang::GetFormat(lldb::opaque_compiler_type_t type) {
case clang::BuiltinType::Double:
case clang::BuiltinType::LongDouble:
return lldb::eFormatFloat;
+ case clang::BuiltinType::Float128:
+ return lldb::eFormatFloat128;
default:
return lldb::eFormatHex;
}
@@ -5515,6 +5550,8 @@ TypeSystemClang::GetBasicTypeEnumeration(lldb::opaque_compiler_type_t type) {
return eBasicTypeDouble;
case clang::BuiltinType::LongDouble:
return eBasicTypeLongDouble;
+ case clang::BuiltinType::Float128:
+ return eBasicTypeFloat128;
case clang::BuiltinType::NullPtr:
return eBasicTypeNullPtr;
@@ -6076,6 +6113,7 @@ uint32_t TypeSystemClang::GetNumPointeeChildren(clang::QualType type) {
case clang::BuiltinType::Float:
case clang::BuiltinType::Double:
case clang::BuiltinType::LongDouble:
+ case clang::BuiltinType::Float128:
case clang::BuiltinType::Dependent:
case clang::BuiltinType::Overload:
case clang::BuiltinType::ObjCId:
@@ -7651,7 +7689,7 @@ TypeSystemClang::CreateParameterDeclarations(
clang::CXXMethodDecl *TypeSystemClang::AddMethodToCXXRecordType(
lldb::opaque_compiler_type_t type, llvm::StringRef name,
- const char *mangled_name, const CompilerType &method_clang_type,
+ llvm::StringRef asm_label, const CompilerType &method_clang_type,
lldb::AccessType access, bool is_virtual, bool is_static, bool is_inline,
bool is_explicit, bool is_attr_used, bool is_artificial) {
if (!type || !method_clang_type.IsValid() || name.empty())
@@ -7784,10 +7822,9 @@ clang::CXXMethodDecl *TypeSystemClang::AddMethodToCXXRecordType(
if (is_attr_used)
cxx_method_decl->addAttr(clang::UsedAttr::CreateImplicit(getASTContext()));
- if (mangled_name != nullptr) {
+ if (!asm_label.empty())
cxx_method_decl->addAttr(clang::AsmLabelAttr::CreateImplicit(
- getASTContext(), mangled_name, /*literal=*/false));
- }
+ getASTContext(), asm_label, /*literal=*/true));
// Parameters on member function declarations in DWARF generally don't
// have names, so we omit them when creating the ParmVarDecls.
@@ -8720,6 +8757,7 @@ bool TypeSystemClang::DumpTypeValue(
case eFormatHex:
case eFormatHexUppercase:
case eFormatFloat:
+ case eFormatFloat128:
case eFormatOctal:
case eFormatOSType:
case eFormatUnsigned:
@@ -9030,6 +9068,21 @@ ConstString TypeSystemClang::DeclGetName(void *opaque_decl) {
return ConstString();
}
+static ConstString
+ExtractMangledNameFromFunctionCallLabel(llvm::StringRef label) {
+ auto label_or_err = FunctionCallLabel::fromString(label);
+ if (!label_or_err) {
+ llvm::consumeError(label_or_err.takeError());
+ return {};
+ }
+
+ llvm::StringRef mangled = label_or_err->lookup_name;
+ if (Mangled::IsMangledName(mangled))
+ return ConstString(mangled);
+
+ return {};
+}
+
ConstString TypeSystemClang::DeclGetMangledName(void *opaque_decl) {
clang::NamedDecl *nd = llvm::dyn_cast_or_null<clang::NamedDecl>(
static_cast<clang::Decl *>(opaque_decl));
@@ -9041,6 +9094,13 @@ ConstString TypeSystemClang::DeclGetMangledName(void *opaque_decl) {
if (!mc || !mc->shouldMangleCXXName(nd))
return {};
+ // We have an LLDB FunctionCallLabel instead of an ordinary mangled name.
+ // Extract the mangled name out of this label.
+ if (const auto *label = nd->getAttr<AsmLabelAttr>())
+ if (ConstString mangled =
+ ExtractMangledNameFromFunctionCallLabel(label->getLabel()))
+ return mangled;
+
llvm::SmallVector<char, 1024> buf;
llvm::raw_svector_ostream llvm_ostrm(buf);
if (llvm::isa<clang::CXXConstructorDecl>(nd)) {
diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
index 63dee9d..5431d12 100644
--- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
+++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
@@ -477,7 +477,7 @@ public:
clang::FunctionDecl *CreateFunctionDeclaration(
clang::DeclContext *decl_ctx, OptionalClangModuleID owning_module,
llvm::StringRef name, const CompilerType &function_Type,
- clang::StorageClass storage, bool is_inline);
+ clang::StorageClass storage, bool is_inline, llvm::StringRef asm_label);
CompilerType
CreateFunctionType(const CompilerType &result_type,
@@ -823,7 +823,8 @@ public:
// Exploring the type
- const llvm::fltSemantics &GetFloatTypeSemantics(size_t byte_size) override;
+ const llvm::fltSemantics &GetFloatTypeSemantics(size_t byte_size,
+ lldb::Format format) override;
llvm::Expected<uint64_t> GetByteSize(lldb::opaque_compiler_type_t type,
ExecutionContextScope *exe_scope) {
@@ -1001,7 +1002,7 @@ public:
clang::CXXMethodDecl *AddMethodToCXXRecordType(
lldb::opaque_compiler_type_t type, llvm::StringRef name,
- const char *mangled_name, const CompilerType &method_type,
+ llvm::StringRef asm_label, const CompilerType &method_type,
lldb::AccessType access, bool is_virtual, bool is_static, bool is_inline,
bool is_explicit, bool is_attr_used, bool is_artificial);
diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp
index 2aa02fd..ff9e5fc 100644
--- a/lldb/source/Target/Process.cpp
+++ b/lldb/source/Target/Process.cpp
@@ -166,6 +166,9 @@ ProcessProperties::ProcessProperties(lldb_private::Process *process)
m_collection_sp->SetValueChangedCallback(
ePropertyPythonOSPluginPath,
[this] { m_process->LoadOperatingSystemPlugin(true); });
+ m_collection_sp->SetValueChangedCallback(
+ ePropertyDisableLangRuntimeUnwindPlans,
+ [this] { DisableLanguageRuntimeUnwindPlansCallback(); });
}
m_experimental_properties_up =
@@ -280,6 +283,15 @@ void ProcessProperties::SetDisableLangRuntimeUnwindPlans(bool disable) {
m_process->Flush();
}
+void ProcessProperties::DisableLanguageRuntimeUnwindPlansCallback() {
+ if (!m_process)
+ return;
+ for (auto thread_sp : m_process->Threads()) {
+ thread_sp->ClearStackFrames();
+ thread_sp->DiscardThreadPlans(/*force*/ true);
+ }
+}
+
bool ProcessProperties::GetDetachKeepsStopped() const {
const uint32_t idx = ePropertyDetachKeepsStopped;
return GetPropertyAtIndexAs<bool>(
diff --git a/lldb/source/ValueObject/ValueObject.cpp b/lldb/source/ValueObject/ValueObject.cpp
index 84ad130..3878442 100644
--- a/lldb/source/ValueObject/ValueObject.cpp
+++ b/lldb/source/ValueObject/ValueObject.cpp
@@ -1466,8 +1466,9 @@ bool ValueObject::DumpPrintableRepresentation(
(custom_format == eFormatComplexFloat) ||
(custom_format == eFormatDecimal) || (custom_format == eFormatHex) ||
(custom_format == eFormatHexUppercase) ||
- (custom_format == eFormatFloat) || (custom_format == eFormatOctal) ||
- (custom_format == eFormatOSType) ||
+ (custom_format == eFormatFloat) ||
+ (custom_format == eFormatFloat128) ||
+ (custom_format == eFormatOctal) || (custom_format == eFormatOSType) ||
(custom_format == eFormatUnicode16) ||
(custom_format == eFormatUnicode32) ||
(custom_format == eFormatUnsigned) ||
diff --git a/lldb/test/API/commands/watchpoints/step_over_watchpoint/TestStepOverWatchpoint.py b/lldb/test/API/commands/watchpoints/step_over_watchpoint/TestStepOverWatchpoint.py
index 8179d52..67dfbea 100644
--- a/lldb/test/API/commands/watchpoints/step_over_watchpoint/TestStepOverWatchpoint.py
+++ b/lldb/test/API/commands/watchpoints/step_over_watchpoint/TestStepOverWatchpoint.py
@@ -50,11 +50,11 @@ class TestStepOverWatchpoint(TestBase):
lldb.eStopReasonWatchpoint,
STOPPED_DUE_TO_WATCHPOINT,
)
- self.assertEqual(thread.GetStopDescription(20), "watchpoint 1")
+ self.assertEqual(thread.stop_description, "watchpoint 1")
process.Continue()
self.assertState(process.GetState(), lldb.eStateStopped, PROCESS_STOPPED)
- self.assertEqual(thread.GetStopDescription(20), "step over")
+ self.assertEqual(thread.stop_description, "step over")
self.step_inst_for_watchpoint(1)
@@ -89,11 +89,11 @@ class TestStepOverWatchpoint(TestBase):
lldb.eStopReasonWatchpoint,
STOPPED_DUE_TO_WATCHPOINT,
)
- self.assertEqual(thread.GetStopDescription(20), "watchpoint 1")
+ self.assertEqual(thread.stop_description, "watchpoint 1")
process.Continue()
self.assertState(process.GetState(), lldb.eStateStopped, PROCESS_STOPPED)
- self.assertEqual(thread.GetStopDescription(20), "step over")
+ self.assertEqual(thread.stop_description, "step over")
self.step_inst_for_watchpoint(1)
@@ -106,7 +106,7 @@ class TestStepOverWatchpoint(TestBase):
if stop_reason == lldb.eStopReasonWatchpoint:
self.assertFalse(watchpoint_hit, "Watchpoint already hit.")
expected_stop_desc = "watchpoint %d" % wp_id
- actual_stop_desc = self.thread().GetStopDescription(20)
+ actual_stop_desc = self.thread().stop_description
self.assertEqual(
actual_stop_desc, expected_stop_desc, "Watchpoint ID didn't match."
)
diff --git a/lldb/test/API/commands/watchpoints/watchpoint_count/TestWatchpointCount.py b/lldb/test/API/commands/watchpoints/watchpoint_count/TestWatchpointCount.py
index ff834b5..a0251d4 100644
--- a/lldb/test/API/commands/watchpoints/watchpoint_count/TestWatchpointCount.py
+++ b/lldb/test/API/commands/watchpoints/watchpoint_count/TestWatchpointCount.py
@@ -35,7 +35,7 @@ class TestWatchpointCount(TestBase):
self.assertStopReason(
stop_reason, lldb.eStopReasonWatchpoint, "watchpoint for x1 not hit"
)
- stop_reason_descr = thread.GetStopDescription(256)
+ stop_reason_descr = thread.stop_description
self.assertEqual(stop_reason_descr, "watchpoint 1")
process.Continue()
@@ -43,5 +43,5 @@ class TestWatchpointCount(TestBase):
self.assertStopReason(
stop_reason, lldb.eStopReasonWatchpoint, "watchpoint for x2 not hit"
)
- stop_reason_descr = thread.GetStopDescription(256)
+ stop_reason_descr = thread.stop_description
self.assertEqual(stop_reason_descr, "watchpoint 2")
diff --git a/lldb/test/API/functionalities/gdb_remote_client/TestGDBRemoteClient.py b/lldb/test/API/functionalities/gdb_remote_client/TestGDBRemoteClient.py
index 12b464d..67c5d7d 100644
--- a/lldb/test/API/functionalities/gdb_remote_client/TestGDBRemoteClient.py
+++ b/lldb/test/API/functionalities/gdb_remote_client/TestGDBRemoteClient.py
@@ -594,7 +594,7 @@ class TestGDBRemoteClient(GDBRemoteTestBase):
process = self.connect(target)
self.assertEqual(process.threads[0].GetStopReason(), lldb.eStopReasonSignal)
- self.assertEqual(process.threads[0].GetStopDescription(100), "signal SIGBUS")
+ self.assertEqual(process.threads[0].stop_description, "signal SIGBUS")
def test_signal_lldb_old(self):
class MyResponder(MockGDBServerResponder):
@@ -620,7 +620,7 @@ class TestGDBRemoteClient(GDBRemoteTestBase):
process = self.connect(target)
self.assertEqual(process.threads[0].GetStopReason(), lldb.eStopReasonSignal)
- self.assertEqual(process.threads[0].GetStopDescription(100), "signal SIGUSR1")
+ self.assertEqual(process.threads[0].stop_description, "signal SIGUSR1")
def test_signal_lldb(self):
class MyResponder(MockGDBServerResponder):
@@ -643,7 +643,7 @@ class TestGDBRemoteClient(GDBRemoteTestBase):
process = self.connect(target)
self.assertEqual(process.threads[0].GetStopReason(), lldb.eStopReasonSignal)
- self.assertEqual(process.threads[0].GetStopDescription(100), "signal SIGUSR1")
+ self.assertEqual(process.threads[0].stop_description, "signal SIGUSR1")
def do_siginfo_test(self, platform, target_yaml, raw_data, expected):
class MyResponder(MockGDBServerResponder):
diff --git a/lldb/test/API/functionalities/gdb_remote_client/TestWasm.py b/lldb/test/API/functionalities/gdb_remote_client/TestWasm.py
index 445f422..73c81ef 100644
--- a/lldb/test/API/functionalities/gdb_remote_client/TestWasm.py
+++ b/lldb/test/API/functionalities/gdb_remote_client/TestWasm.py
@@ -1,12 +1,15 @@
import lldb
+import os
import binascii
from lldbsuite.test.lldbtest import *
from lldbsuite.test.decorators import *
from lldbsuite.test.gdbclientutils import *
from lldbsuite.test.lldbgdbclient import GDBRemoteTestBase
-LLDB_INVALID_ADDRESS = lldb.LLDB_INVALID_ADDRESS
-load_address = 0x400000000
+MODULE_ID = 4
+LOAD_ADDRESS = MODULE_ID << 32
+WASM_LOCAL_ADDR = 0x103E0
+
def format_register_value(val):
"""
@@ -23,12 +26,59 @@ def format_register_value(val):
return result
+class WasmStackFrame:
+ def __init__(self, address):
+ self._address = address
+
+ def __str__(self):
+ return format_register_value(LOAD_ADDRESS | self._address)
+
+
+class WasmCallStack:
+ def __init__(self, wasm_stack_frames):
+ self._wasm_stack_frames = wasm_stack_frames
+
+ def __str__(self):
+ result = ""
+ for frame in self._wasm_stack_frames:
+ result += str(frame)
+ return result
+
+
+class FakeMemory:
+ def __init__(self, start_addr, end_addr):
+ self._base_addr = start_addr
+ self._memory = bytearray(end_addr - start_addr)
+ self._memoryview = memoryview(self._memory)
+
+ def store_bytes(self, addr, bytes_obj):
+ assert addr > self._base_addr
+ assert addr < self._base_addr + len(self._memoryview)
+ offset = addr - self._base_addr
+ chunk = self._memoryview[offset : offset + len(bytes_obj)]
+ for i in range(len(bytes_obj)):
+ chunk[i] = bytes_obj[i]
+
+ def get_bytes(self, addr, length):
+ assert addr > self._base_addr
+ assert addr < self._base_addr + len(self._memoryview)
+
+ offset = addr - self._base_addr
+ return self._memoryview[offset : offset + length]
+
+ def contains(self, addr):
+ return addr - self._base_addr < len(self._memoryview)
+
+
class MyResponder(MockGDBServerResponder):
- current_pc = load_address + 0x0A
+ current_pc = LOAD_ADDRESS | 0x01AD
- def __init__(self, obj_path, module_name=""):
+ def __init__(self, obj_path, module_name="", wasm_call_stacks=[], memory=None):
self._obj_path = obj_path
self._module_name = module_name or obj_path
+ self._wasm_call_stacks = wasm_call_stacks
+ self._call_stack_request_count = 0
+ self._memory = memory
MockGDBServerResponder.__init__(self)
def respond(self, packet):
@@ -36,6 +86,8 @@ class MyResponder(MockGDBServerResponder):
return self.qRegisterInfo(packet[13:])
if packet.startswith("qWasmCallStack"):
return self.qWasmCallStack()
+ if packet.startswith("qWasmLocal"):
+ return self.qWasmLocal(packet)
return MockGDBServerResponder.respond(self, packet)
def qSupported(self, client_supported):
@@ -71,28 +123,61 @@ class MyResponder(MockGDBServerResponder):
if obj == "libraries":
xml = (
'<library-list><library name="%s"><section address="%d"/></library></library-list>'
- % (self._module_name, load_address)
+ % (self._module_name, LOAD_ADDRESS)
)
return xml, False
else:
return None, False
def readMemory(self, addr, length):
- if addr < load_address:
+ if self._memory and self._memory.contains(addr):
+ chunk = self._memory.get_bytes(addr, length)
+ return chunk.hex()
+ if addr < LOAD_ADDRESS:
return "E02"
result = ""
with open(self._obj_path, mode="rb") as file:
file_content = bytearray(file.read())
- addr_from = addr - load_address
+ if addr >= LOAD_ADDRESS + len(file_content):
+ return "E03"
+ addr_from = addr - LOAD_ADDRESS
addr_to = addr_from + min(length, len(file_content) - addr_from)
for i in range(addr_from, addr_to):
result += format(file_content[i], "02x")
file.close()
return result
+ def setBreakpoint(self, packet):
+ bp_data = packet[1:].split(",")
+ self._bp_address = bp_data[1]
+ return "OK"
+
+ def qfThreadInfo(self):
+ return "m1"
+
+ def cont(self):
+ # Continue execution. Simulates running the Wasm engine until a breakpoint is hit.
+ return (
+ "T05thread-pcs:"
+ + format(int(self._bp_address, 16) & 0x3FFFFFFFFFFFFFFF, "x")
+ + ";thread:1"
+ )
+
def qWasmCallStack(self):
- # Return two 64-bit addresses: 0x40000000000001B3, 0x40000000000001FE
- return "b301000000000040fe01000000000040"
+ if len(self._wasm_call_stacks) == 0:
+ return ""
+ result = str(self._wasm_call_stacks[self._call_stack_request_count])
+ self._call_stack_request_count += 1
+ return result
+
+ def qWasmLocal(self, packet):
+ # Format: qWasmLocal:frame_index;index
+ data = packet.split(":")
+ data = data[1].split(";")
+ frame_index, local_index = data
+ if frame_index == "0" and local_index == "2":
+ return format_register_value(WASM_LOCAL_ADDR)
+ return "E03"
class TestWasm(GDBRemoteTestBase):
@@ -124,35 +209,35 @@ class TestWasm(GDBRemoteTestBase):
code_section = module.GetSectionAtIndex(0)
self.assertEqual("code", code_section.GetName())
self.assertEqual(
- load_address | code_section.GetFileOffset(),
+ LOAD_ADDRESS | code_section.GetFileOffset(),
code_section.GetLoadAddress(target),
)
debug_info_section = module.GetSectionAtIndex(1)
self.assertEqual(".debug_info", debug_info_section.GetName())
self.assertEqual(
- load_address | debug_info_section.GetFileOffset(),
+ LOAD_ADDRESS | debug_info_section.GetFileOffset(),
debug_info_section.GetLoadAddress(target),
)
debug_abbrev_section = module.GetSectionAtIndex(2)
self.assertEqual(".debug_abbrev", debug_abbrev_section.GetName())
self.assertEqual(
- load_address | debug_abbrev_section.GetFileOffset(),
+ LOAD_ADDRESS | debug_abbrev_section.GetFileOffset(),
debug_abbrev_section.GetLoadAddress(target),
)
debug_line_section = module.GetSectionAtIndex(3)
self.assertEqual(".debug_line", debug_line_section.GetName())
self.assertEqual(
- load_address | debug_line_section.GetFileOffset(),
+ LOAD_ADDRESS | debug_line_section.GetFileOffset(),
debug_line_section.GetLoadAddress(target),
)
debug_str_section = module.GetSectionAtIndex(4)
self.assertEqual(".debug_str", debug_str_section.GetName())
self.assertEqual(
- load_address | debug_line_section.GetFileOffset(),
+ LOAD_ADDRESS | debug_line_section.GetFileOffset(),
debug_line_section.GetLoadAddress(target),
)
@@ -194,97 +279,103 @@ class TestWasm(GDBRemoteTestBase):
code_section = module.GetSectionAtIndex(0)
self.assertEqual("code", code_section.GetName())
self.assertEqual(
- load_address | code_section.GetFileOffset(),
+ LOAD_ADDRESS | code_section.GetFileOffset(),
code_section.GetLoadAddress(target),
)
debug_info_section = module.GetSectionAtIndex(1)
self.assertEqual(".debug_info", debug_info_section.GetName())
self.assertEqual(
- LLDB_INVALID_ADDRESS, debug_info_section.GetLoadAddress(target)
+ lldb.LLDB_INVALID_ADDRESS, debug_info_section.GetLoadAddress(target)
)
debug_abbrev_section = module.GetSectionAtIndex(2)
self.assertEqual(".debug_abbrev", debug_abbrev_section.GetName())
self.assertEqual(
- LLDB_INVALID_ADDRESS, debug_abbrev_section.GetLoadAddress(target)
+ lldb.LLDB_INVALID_ADDRESS, debug_abbrev_section.GetLoadAddress(target)
)
debug_line_section = module.GetSectionAtIndex(3)
self.assertEqual(".debug_line", debug_line_section.GetName())
self.assertEqual(
- LLDB_INVALID_ADDRESS, debug_line_section.GetLoadAddress(target)
+ lldb.LLDB_INVALID_ADDRESS, debug_line_section.GetLoadAddress(target)
)
debug_str_section = module.GetSectionAtIndex(4)
self.assertEqual(".debug_str", debug_str_section.GetName())
self.assertEqual(
- LLDB_INVALID_ADDRESS, debug_line_section.GetLoadAddress(target)
+ lldb.LLDB_INVALID_ADDRESS, debug_line_section.GetLoadAddress(target)
)
@skipIfAsan
@skipIfXmlSupportMissing
- def test_load_module_from_file(self):
- """Test connecting to a WebAssembly engine via GDB-remote and loading a Wasm module from a file"""
-
- yaml_path = "test_wasm_embedded_debug_sections.yaml"
- yaml_base, ext = os.path.splitext(yaml_path)
+ def test_simple_wasm_debugging_session(self):
+ """Test connecting to a WebAssembly engine via GDB-remote, loading a
+ Wasm module with embedded DWARF symbols, setting a breakpoint and
+ checking the debuggee state"""
+
+ # simple.yaml was created by compiling simple.c to wasm and using
+ # obj2yaml on the output.
+ #
+ # $ clang -target wasm32 -nostdlib -Wl,--no-entry -Wl,--export-all -O0 -g -o simple.wasm simple.c
+ # $ obj2yaml simple.wasm -o simple.yaml
+ yaml_path = "simple.yaml"
+ yaml_base, _ = os.path.splitext(yaml_path)
obj_path = self.getBuildArtifact(yaml_base)
self.yaml2obj(yaml_path, obj_path)
- self.server.responder = MyResponder(obj_path)
+ # Create a fake call stack.
+ call_stacks = [
+ WasmCallStack(
+ [WasmStackFrame(0x019C), WasmStackFrame(0x01E5), WasmStackFrame(0x01FE)]
+ ),
+ ]
+
+ # Create fake memory for our wasm locals.
+ self.memory = FakeMemory(0x10000, 0x20000)
+ self.memory.store_bytes(
+ WASM_LOCAL_ADDR,
+ bytes.fromhex(
+ "0000000000000000020000000100000000000000020000000100000000000000"
+ ),
+ )
+
+ self.server.responder = MyResponder(
+ obj_path, "test_wasm", call_stacks, self.memory
+ )
target = self.dbg.CreateTarget("")
+ breakpoint = target.BreakpointCreateByName("add")
process = self.connect(target, "wasm")
lldbutil.expect_state_changes(
self, self.dbg.GetListener(), process, [lldb.eStateStopped]
)
+ location = breakpoint.GetLocationAtIndex(0)
+ self.assertTrue(location and location.IsEnabled(), VALID_BREAKPOINT_LOCATION)
+
num_modules = target.GetNumModules()
self.assertEqual(1, num_modules)
- module = target.GetModuleAtIndex(0)
- num_sections = module.GetNumSections()
- self.assertEqual(5, num_sections)
-
- code_section = module.GetSectionAtIndex(0)
- self.assertEqual("code", code_section.GetName())
- self.assertEqual(
- load_address | code_section.GetFileOffset(),
- code_section.GetLoadAddress(target),
- )
-
- debug_info_section = module.GetSectionAtIndex(1)
- self.assertEqual(".debug_info", debug_info_section.GetName())
- self.assertEqual(
- LLDB_INVALID_ADDRESS, debug_info_section.GetLoadAddress(target)
- )
-
- debug_abbrev_section = module.GetSectionAtIndex(2)
- self.assertEqual(".debug_abbrev", debug_abbrev_section.GetName())
- self.assertEqual(
- LLDB_INVALID_ADDRESS, debug_abbrev_section.GetLoadAddress(target)
- )
-
- debug_line_section = module.GetSectionAtIndex(3)
- self.assertEqual(".debug_line", debug_line_section.GetName())
- self.assertEqual(
- LLDB_INVALID_ADDRESS, debug_line_section.GetLoadAddress(target)
- )
-
- debug_str_section = module.GetSectionAtIndex(4)
- self.assertEqual(".debug_str", debug_str_section.GetName())
- self.assertEqual(
- LLDB_INVALID_ADDRESS, debug_line_section.GetLoadAddress(target)
- )
-
thread = process.GetThreadAtIndex(0)
self.assertTrue(thread.IsValid())
- frame = thread.GetFrameAtIndex(0)
- self.assertTrue(frame.IsValid())
- self.assertEqual(frame.GetPC(), 0x40000000000001B3)
-
- frame = thread.GetFrameAtIndex(1)
- self.assertTrue(frame.IsValid())
- self.assertEqual(frame.GetPC(), 0x40000000000001FE)
+ # Check that our frames match our fake call stack.
+ frame0 = thread.GetFrameAtIndex(0)
+ self.assertTrue(frame0.IsValid())
+ self.assertEqual(frame0.GetPC(), LOAD_ADDRESS | 0x019C)
+ self.assertIn("add", frame0.GetFunctionName())
+
+ frame1 = thread.GetFrameAtIndex(1)
+ self.assertTrue(frame1.IsValid())
+ self.assertEqual(frame1.GetPC(), LOAD_ADDRESS | 0x01E5)
+ self.assertIn("main", frame1.GetFunctionName())
+
+ # Check that we can resolve local variables.
+ a = frame0.FindVariable("a")
+ self.assertTrue(a.IsValid())
+ self.assertEqual(a.GetValueAsUnsigned(), 1)
+
+ b = frame0.FindVariable("b")
+ self.assertTrue(b.IsValid())
+ self.assertEqual(b.GetValueAsUnsigned(), 2)
diff --git a/lldb/test/API/functionalities/gdb_remote_client/simple.c b/lldb/test/API/functionalities/gdb_remote_client/simple.c
new file mode 100644
index 0000000..62ca1fe
--- /dev/null
+++ b/lldb/test/API/functionalities/gdb_remote_client/simple.c
@@ -0,0 +1,10 @@
+int add(int a, int b) {
+ // Break here
+ return a + b;
+}
+
+int main() {
+ int i = 1;
+ int j = 2;
+ return add(i, j);
+}
diff --git a/lldb/test/API/functionalities/gdb_remote_client/simple.yaml b/lldb/test/API/functionalities/gdb_remote_client/simple.yaml
new file mode 100644
index 0000000..cf1b7d8
--- /dev/null
+++ b/lldb/test/API/functionalities/gdb_remote_client/simple.yaml
@@ -0,0 +1,228 @@
+--- !WASM
+FileHeader:
+ Version: 0x1
+Sections:
+ - Type: TYPE
+ Signatures:
+ - Index: 0
+ ParamTypes: []
+ ReturnTypes: []
+ - Index: 1
+ ParamTypes:
+ - I32
+ - I32
+ ReturnTypes:
+ - I32
+ - Index: 2
+ ParamTypes: []
+ ReturnTypes:
+ - I32
+ - Type: FUNCTION
+ FunctionTypes: [ 0, 1, 2, 1 ]
+ - Type: TABLE
+ Tables:
+ - Index: 0
+ ElemType: FUNCREF
+ Limits:
+ Flags: [ HAS_MAX ]
+ Minimum: 0x1
+ Maximum: 0x1
+ - Type: MEMORY
+ Memories:
+ - Minimum: 0x2
+ - Type: GLOBAL
+ Globals:
+ - Index: 0
+ Type: I32
+ Mutable: true
+ InitExpr:
+ Opcode: I32_CONST
+ Value: 66560
+ - Index: 1
+ Type: I32
+ Mutable: false
+ InitExpr:
+ Opcode: I32_CONST
+ Value: 1024
+ - Index: 2
+ Type: I32
+ Mutable: false
+ InitExpr:
+ Opcode: I32_CONST
+ Value: 1024
+ - Index: 3
+ Type: I32
+ Mutable: false
+ InitExpr:
+ Opcode: I32_CONST
+ Value: 1024
+ - Index: 4
+ Type: I32
+ Mutable: false
+ InitExpr:
+ Opcode: I32_CONST
+ Value: 66560
+ - Index: 5
+ Type: I32
+ Mutable: false
+ InitExpr:
+ Opcode: I32_CONST
+ Value: 1024
+ - Index: 6
+ Type: I32
+ Mutable: false
+ InitExpr:
+ Opcode: I32_CONST
+ Value: 66560
+ - Index: 7
+ Type: I32
+ Mutable: false
+ InitExpr:
+ Opcode: I32_CONST
+ Value: 131072
+ - Index: 8
+ Type: I32
+ Mutable: false
+ InitExpr:
+ Opcode: I32_CONST
+ Value: 0
+ - Index: 9
+ Type: I32
+ Mutable: false
+ InitExpr:
+ Opcode: I32_CONST
+ Value: 1
+ - Index: 10
+ Type: I32
+ Mutable: false
+ InitExpr:
+ Opcode: I32_CONST
+ Value: 65536
+ - Type: EXPORT
+ Exports:
+ - Name: memory
+ Kind: MEMORY
+ Index: 0
+ - Name: __wasm_call_ctors
+ Kind: FUNCTION
+ Index: 0
+ - Name: add
+ Kind: FUNCTION
+ Index: 1
+ - Name: __original_main
+ Kind: FUNCTION
+ Index: 2
+ - Name: main
+ Kind: FUNCTION
+ Index: 3
+ - Name: __main_void
+ Kind: FUNCTION
+ Index: 2
+ - Name: __indirect_function_table
+ Kind: TABLE
+ Index: 0
+ - Name: __dso_handle
+ Kind: GLOBAL
+ Index: 1
+ - Name: __data_end
+ Kind: GLOBAL
+ Index: 2
+ - Name: __stack_low
+ Kind: GLOBAL
+ Index: 3
+ - Name: __stack_high
+ Kind: GLOBAL
+ Index: 4
+ - Name: __global_base
+ Kind: GLOBAL
+ Index: 5
+ - Name: __heap_base
+ Kind: GLOBAL
+ Index: 6
+ - Name: __heap_end
+ Kind: GLOBAL
+ Index: 7
+ - Name: __memory_base
+ Kind: GLOBAL
+ Index: 8
+ - Name: __table_base
+ Kind: GLOBAL
+ Index: 9
+ - Name: __wasm_first_page_end
+ Kind: GLOBAL
+ Index: 10
+ - Type: CODE
+ Functions:
+ - Index: 0
+ Locals: []
+ Body: 0B
+ - Index: 1
+ Locals:
+ - Type: I32
+ Count: 1
+ Body: 23808080800041106B21022002200036020C20022001360208200228020C20022802086A0F0B
+ - Index: 2
+ Locals:
+ - Type: I32
+ Count: 2
+ Body: 23808080800041106B210020002480808080002000410036020C2000410136020820004102360204200028020820002802041081808080002101200041106A24808080800020010F0B
+ - Index: 3
+ Locals: []
+ Body: 1082808080000F0B
+ - Type: CUSTOM
+ Name: .debug_abbrev
+ Payload: 011101250E1305030E10171B0E110155170000022E01110112064018030E3A0B3B0B271949133F1900000305000218030E3A0B3B0B49130000042E01110112064018030E3A0B3B0B49133F1900000534000218030E3A0B3B0B49130000062400030E3E0B0B0B000000
+ - Type: CUSTOM
+ Name: .debug_info
+ Payload: 940000000400000000000401620000001D0055000000000000000D000000000000000000000002050000002900000004ED00029F510000000101900000000302910C60000000010190000000030291085E00000001019000000000042F0000004C00000004ED00009F04000000010690000000050291080B0000000107900000000502910409000000010890000000000600000000050400
+ - Type: CUSTOM
+ Name: .debug_ranges
+ Payload: 050000002E0000002F0000007B0000000000000000000000
+ - Type: CUSTOM
+ Name: .debug_str
+ Payload: 696E74006D61696E006A0069002F55736572732F6A6F6E61732F7761736D2D6D6963726F2D72756E74696D652F70726F647563742D6D696E692F706C6174666F726D732F64617277696E2F6275696C64006164640073696D706C652E630062006100636C616E672076657273696F6E2032322E302E306769742028676974406769746875622E636F6D3A4A4465766C696567686572652F6C6C766D2D70726F6A6563742E67697420343161363839613132323834633834623632383933393461356338306264636534383733656466302900
+ - Type: CUSTOM
+ Name: .debug_line
+ Payload: 62000000040020000000010101FB0E0D0001010101000000010000010073696D706C652E6300000000000005020500000001050A0A08AE050E0658050C5805032002020001010005022F0000001705070A08BB75050E7505110658050A58050382020F000101
+ - Type: CUSTOM
+ Name: name
+ FunctionNames:
+ - Index: 0
+ Name: __wasm_call_ctors
+ - Index: 1
+ Name: add
+ - Index: 2
+ Name: __original_main
+ - Index: 3
+ Name: main
+ GlobalNames:
+ - Index: 0
+ Name: __stack_pointer
+ - Type: CUSTOM
+ Name: producers
+ Languages:
+ - Name: C11
+ Version: ''
+ Tools:
+ - Name: clang
+ Version: '22.0.0git'
+ - Type: CUSTOM
+ Name: target_features
+ Features:
+ - Prefix: USED
+ Name: bulk-memory
+ - Prefix: USED
+ Name: bulk-memory-opt
+ - Prefix: USED
+ Name: call-indirect-overlong
+ - Prefix: USED
+ Name: multivalue
+ - Prefix: USED
+ Name: mutable-globals
+ - Prefix: USED
+ Name: nontrapping-fptoint
+ - Prefix: USED
+ Name: reference-types
+ - Prefix: USED
+ Name: sign-ext
+...
diff --git a/lldb/test/API/functionalities/plugins/python_os_plugin/stepping_plugin_threads/TestOSPluginStepping.py b/lldb/test/API/functionalities/plugins/python_os_plugin/stepping_plugin_threads/TestOSPluginStepping.py
index 0d06a9d..dc555dd 100644
--- a/lldb/test/API/functionalities/plugins/python_os_plugin/stepping_plugin_threads/TestOSPluginStepping.py
+++ b/lldb/test/API/functionalities/plugins/python_os_plugin/stepping_plugin_threads/TestOSPluginStepping.py
@@ -123,5 +123,5 @@ class TestOSPluginStepping(TestBase):
os_thread = self.get_os_thread()
self.assertTrue(os_thread.IsValid(), "The OS thread is back after continue")
self.assertIn(
- "step out", os_thread.GetStopDescription(100), "Completed step out plan"
+ "step out", os_thread.stop_description, "Completed step out plan"
)
diff --git a/lldb/test/API/functionalities/postmortem/minidump-new/TestMiniDumpNew.py b/lldb/test/API/functionalities/postmortem/minidump-new/TestMiniDumpNew.py
index 8776d72..4b7d24e 100644
--- a/lldb/test/API/functionalities/postmortem/minidump-new/TestMiniDumpNew.py
+++ b/lldb/test/API/functionalities/postmortem/minidump-new/TestMiniDumpNew.py
@@ -117,7 +117,7 @@ class MiniDumpNewTestCase(TestBase):
self.assertEqual(self.process.GetNumThreads(), 1)
thread = self.process.GetThreadAtIndex(0)
self.assertStopReason(thread.GetStopReason(), lldb.eStopReasonSignal)
- stop_description = thread.GetStopDescription(256)
+ stop_description = thread.stop_description
self.assertIn("SIGSEGV", stop_description)
@skipIfLLVMTargetMissing("X86")
@@ -153,7 +153,7 @@ class MiniDumpNewTestCase(TestBase):
self.assertEqual(self.process.GetNumThreads(), 1)
thread = self.process.GetThreadAtIndex(0)
self.assertStopReason(thread.GetStopReason(), lldb.eStopReasonNone)
- stop_description = thread.GetStopDescription(256)
+ stop_description = thread.stop_description
self.assertEqual(stop_description, "")
def test_snapshot_minidump_null_exn_code(self):
@@ -164,7 +164,7 @@ class MiniDumpNewTestCase(TestBase):
self.assertEqual(self.process.GetNumThreads(), 1)
thread = self.process.GetThreadAtIndex(0)
self.assertStopReason(thread.GetStopReason(), lldb.eStopReasonNone)
- stop_description = thread.GetStopDescription(256)
+ stop_description = thread.stop_description
self.assertEqual(stop_description, "")
def check_register_unsigned(self, set, name, expected):
@@ -198,7 +198,7 @@ class MiniDumpNewTestCase(TestBase):
self.assertEqual(self.process.GetNumThreads(), 1)
thread = self.process.GetThreadAtIndex(0)
self.assertStopReason(thread.GetStopReason(), lldb.eStopReasonNone)
- stop_description = thread.GetStopDescription(256)
+ stop_description = thread.stop_description
self.assertEqual(stop_description, "")
registers = thread.GetFrameAtIndex(0).GetRegisters()
# Verify the GPR registers are all correct
@@ -261,7 +261,7 @@ class MiniDumpNewTestCase(TestBase):
self.assertEqual(self.process.GetNumThreads(), 1)
thread = self.process.GetThreadAtIndex(0)
self.assertStopReason(thread.GetStopReason(), lldb.eStopReasonNone)
- stop_description = thread.GetStopDescription(256)
+ stop_description = thread.stop_description
self.assertEqual(stop_description, "")
registers = thread.GetFrameAtIndex(0).GetRegisters()
# Verify the GPR registers are all correct
@@ -522,7 +522,7 @@ class MiniDumpNewTestCase(TestBase):
for i in range(2):
thread = self.process.GetThreadAtIndex(i)
self.assertStopReason(thread.GetStopReason(), lldb.eStopReasonSignal)
- stop_description = thread.GetStopDescription(256)
+ stop_description = thread.stop_description
self.assertIn("SIGSEGV", stop_description)
def test_breakpoint_on_minidump(self):
@@ -539,7 +539,7 @@ class MiniDumpNewTestCase(TestBase):
process = target.LoadCore(core)
self.assertTrue(process, VALID_PROCESS)
thread = process.GetThreadAtIndex(0)
- stop_reason = thread.GetStopDescription(256)
+ stop_reason = thread.stop_description
self.assertIn("breakpoint 1.1", stop_reason)
finally:
if os.path.isfile(core):
diff --git a/lldb/test/API/functionalities/postmortem/minidump/TestMiniDump.py b/lldb/test/API/functionalities/postmortem/minidump/TestMiniDump.py
index 8fe5d2a..362b219 100644
--- a/lldb/test/API/functionalities/postmortem/minidump/TestMiniDump.py
+++ b/lldb/test/API/functionalities/postmortem/minidump/TestMiniDump.py
@@ -32,7 +32,7 @@ class MiniDumpTestCase(TestBase):
self.assertEqual(self.process.GetNumThreads(), 1)
thread = self.process.GetThreadAtIndex(0)
self.assertStopReason(thread.GetStopReason(), lldb.eStopReasonException)
- stop_description = thread.GetStopDescription(256)
+ stop_description = thread.stop_description
self.assertIn("0xc0000005", stop_description)
def test_modules_in_mini_dump(self):
diff --git a/lldb/test/API/functionalities/scripted_process/stack_core_scripted_process.py b/lldb/test/API/functionalities/scripted_process/stack_core_scripted_process.py
index 736bb69..ee5ae32 100644
--- a/lldb/test/API/functionalities/scripted_process/stack_core_scripted_process.py
+++ b/lldb/test/API/functionalities/scripted_process/stack_core_scripted_process.py
@@ -204,9 +204,7 @@ class StackCoreScriptedThread(ScriptedThread):
if self.is_stopped:
if "arm64" in self.scripted_process.arch:
stop_reason["type"] = lldb.eStopReasonException
- stop_reason["data"][
- "desc"
- ] = self.corefile_thread.GetStopDescription(100)
+ stop_reason["data"]["desc"] = self.corefile_thread.stop_description
elif self.scripted_process.arch == "x86_64":
stop_reason["type"] = lldb.eStopReasonSignal
stop_reason["data"]["signal"] = signal.SIGTRAP
diff --git a/lldb/test/API/functionalities/step_scripted/TestStepScripted.py b/lldb/test/API/functionalities/step_scripted/TestStepScripted.py
index 5276369..343236a 100644
--- a/lldb/test/API/functionalities/step_scripted/TestStepScripted.py
+++ b/lldb/test/API/functionalities/step_scripted/TestStepScripted.py
@@ -41,7 +41,7 @@ class StepScriptedTestCase(TestBase):
frame = thread.GetFrameAtIndex(0)
self.assertEqual("main", frame.GetFunctionName())
- stop_desc = thread.GetStopDescription(1000)
+ stop_desc = thread.stop_description
self.assertIn("Stepping out from", stop_desc, "Got right description")
def run_until_branch_instruction(self):
@@ -153,7 +153,7 @@ class StepScriptedTestCase(TestBase):
self.assertTrue(foo_val.GetValueDidChange(), "Foo changed")
# And we should have a reasonable stop description:
- desc = thread.GetStopDescription(1000)
+ desc = thread.stop_description
self.assertIn("Stepped until foo changed", desc, "Got right stop description")
def test_stop_others_from_command(self):
diff --git a/lldb/test/API/functionalities/tail_call_frames/cross_dso/TestCrossDSOTailCalls.py b/lldb/test/API/functionalities/tail_call_frames/cross_dso/TestCrossDSOTailCalls.py
index 7c3d09b..0ca2f9e5 100644
--- a/lldb/test/API/functionalities/tail_call_frames/cross_dso/TestCrossDSOTailCalls.py
+++ b/lldb/test/API/functionalities/tail_call_frames/cross_dso/TestCrossDSOTailCalls.py
@@ -11,7 +11,6 @@ class TestCrossDSOTailCalls(TestBase):
@skipIf(compiler="clang", compiler_version=["<", "10.0"])
@skipIf(dwarf_version=["<", "4"])
@expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr26265")
- @expectedFailureAll(archs=["arm$", "arm64", "aarch64"], bugnumber="llvm.org/PR44561")
def test_cross_dso_tail_calls(self):
self.build()
exe = self.getBuildArtifact("a.out")
diff --git a/lldb/test/API/functionalities/tail_call_frames/cross_object/TestCrossObjectTailCalls.py b/lldb/test/API/functionalities/tail_call_frames/cross_object/TestCrossObjectTailCalls.py
index 180f4d3..b5de75e 100644
--- a/lldb/test/API/functionalities/tail_call_frames/cross_object/TestCrossObjectTailCalls.py
+++ b/lldb/test/API/functionalities/tail_call_frames/cross_object/TestCrossObjectTailCalls.py
@@ -11,7 +11,6 @@ class TestCrossObjectTailCalls(TestBase):
@skipIf(compiler="clang", compiler_version=["<", "10.0"])
@skipIf(dwarf_version=["<", "4"])
@expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr26265")
- @expectedFailureAll(archs=["arm$", "arm64", "aarch64"], bugnumber="llvm.org/PR44561")
def test_cross_object_tail_calls(self):
self.build()
exe = self.getBuildArtifact("a.out")
diff --git a/lldb/test/API/functionalities/tsan/multiple/TestTsanMultiple.py b/lldb/test/API/functionalities/tsan/multiple/TestTsanMultiple.py
index 435e180..aa2d1d9 100644
--- a/lldb/test/API/functionalities/tsan/multiple/TestTsanMultiple.py
+++ b/lldb/test/API/functionalities/tsan/multiple/TestTsanMultiple.py
@@ -49,7 +49,7 @@ class TsanMultipleTestCase(TestBase):
stop_description = (
self.dbg.GetSelectedTarget()
.process.GetSelectedThread()
- .GetStopDescription(100)
+ .stop_description
)
self.assertTrue(
diff --git a/lldb/test/API/lang/cpp/expr-definition-in-dylib/Makefile b/lldb/test/API/lang/cpp/expr-definition-in-dylib/Makefile
new file mode 100644
index 0000000..82daeb1
--- /dev/null
+++ b/lldb/test/API/lang/cpp/expr-definition-in-dylib/Makefile
@@ -0,0 +1,6 @@
+CXX_SOURCES := main.cpp
+
+DYLIB_CXX_SOURCES := lib.cpp
+DYLIB_NAME := lib
+
+include Makefile.rules
diff --git a/lldb/test/API/lang/cpp/expr-definition-in-dylib/TestExprDefinitionInDylib.py b/lldb/test/API/lang/cpp/expr-definition-in-dylib/TestExprDefinitionInDylib.py
new file mode 100644
index 0000000..02c34b3
--- /dev/null
+++ b/lldb/test/API/lang/cpp/expr-definition-in-dylib/TestExprDefinitionInDylib.py
@@ -0,0 +1,33 @@
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class ExprDefinitionInDylibTestCase(TestBase):
+ NO_DEBUG_INFO_TESTCASE = True
+
+ @skipIfWindows
+ def test(self):
+ """
+ Tests that we can call functions whose definition
+ is in a different LLDB module than it's declaration.
+ """
+ self.build()
+
+ target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
+ self.assertTrue(target, VALID_TARGET)
+
+ env = self.registerSharedLibrariesWithTarget(target, ["lib"])
+
+ breakpoint = lldbutil.run_break_set_by_file_and_line(
+ self, "main.cpp", line_number("main.cpp", "return")
+ )
+
+ process = target.LaunchSimple(None, env, self.get_process_working_directory())
+
+ self.assertIsNotNone(
+ lldbutil.get_one_thread_stopped_at_breakpoint_id(self.process(), breakpoint)
+ )
+
+ self.expect_expr("f.method()", result_value="-72", result_type="int")
diff --git a/lldb/test/API/lang/cpp/expr-definition-in-dylib/lib.cpp b/lldb/test/API/lang/cpp/expr-definition-in-dylib/lib.cpp
new file mode 100644
index 0000000..ad148ce
--- /dev/null
+++ b/lldb/test/API/lang/cpp/expr-definition-in-dylib/lib.cpp
@@ -0,0 +1,3 @@
+#include "lib.h"
+
+int Foo::method() { return -72; }
diff --git a/lldb/test/API/lang/cpp/expr-definition-in-dylib/lib.h b/lldb/test/API/lang/cpp/expr-definition-in-dylib/lib.h
new file mode 100644
index 0000000..9568db2
--- /dev/null
+++ b/lldb/test/API/lang/cpp/expr-definition-in-dylib/lib.h
@@ -0,0 +1,8 @@
+#ifndef LIB_H_IN
+#define LIB_H_IN
+
+struct Foo {
+ int method();
+};
+
+#endif // LIB_H_IN
diff --git a/lldb/test/API/lang/cpp/expr-definition-in-dylib/main.cpp b/lldb/test/API/lang/cpp/expr-definition-in-dylib/main.cpp
new file mode 100644
index 0000000..2fddb2b
--- /dev/null
+++ b/lldb/test/API/lang/cpp/expr-definition-in-dylib/main.cpp
@@ -0,0 +1,6 @@
+#include "lib.h"
+
+int main() {
+ Foo f;
+ return f.method();
+}
diff --git a/lldb/test/API/macosx/abort_with_payload/TestAbortWithPayload.py b/lldb/test/API/macosx/abort_with_payload/TestAbortWithPayload.py
index c10d958..a850908 100644
--- a/lldb/test/API/macosx/abort_with_payload/TestAbortWithPayload.py
+++ b/lldb/test/API/macosx/abort_with_payload/TestAbortWithPayload.py
@@ -61,7 +61,7 @@ class TestAbortWithPayload(TestBase):
self.assertEqual(thread, sel_thread, "Selected the original thread")
# Make sure the stop reason is right:
self.assertEqual(
- thread.GetStopDescription(100),
+ thread.stop_description,
"abort with payload or reason",
"Description was right",
)
diff --git a/lldb/test/API/macosx/corefile-exception-reason/TestCorefileExceptionReason.py b/lldb/test/API/macosx/corefile-exception-reason/TestCorefileExceptionReason.py
index ada74a1..e452bb5 100644
--- a/lldb/test/API/macosx/corefile-exception-reason/TestCorefileExceptionReason.py
+++ b/lldb/test/API/macosx/corefile-exception-reason/TestCorefileExceptionReason.py
@@ -44,7 +44,7 @@ class TestCorefileExceptionReason(TestBase):
self.runCmd("fr v")
self.assertEqual(
- thread.GetStopDescription(256), "ESR_EC_DABORT_EL0 (fault address: 0x0)"
+ thread.stop_description, "ESR_EC_DABORT_EL0 (fault address: 0x0)"
)
if self.TraceOn():
diff --git a/lldb/test/API/riscv/break-undecoded/TestBreakpointIllegal.py b/lldb/test/API/riscv/break-undecoded/TestBreakpointIllegal.py
index 41e8901..5b00298 100644
--- a/lldb/test/API/riscv/break-undecoded/TestBreakpointIllegal.py
+++ b/lldb/test/API/riscv/break-undecoded/TestBreakpointIllegal.py
@@ -17,7 +17,7 @@ class TestBreakpointIllegal(TestBase):
)
self.runCmd("thread step-inst")
# we need to step more, as some compilers do not set appropriate debug info.
- while cur_thread.GetStopDescription(256) == "instruction step into":
+ while cur_thread.stop_description == "instruction step into":
self.runCmd("thread step-inst")
# The stop reason of the thread should be illegal opcode.
self.expect(
@@ -34,7 +34,7 @@ class TestBreakpointIllegal(TestBase):
)
self.runCmd("thread step-inst")
# we need to step more, as some compilers do not set appropriate debug info.
- while cur_thread.GetStopDescription(256) == "instruction step into":
+ while cur_thread.stop_description == "instruction step into":
self.runCmd("thread step-inst")
# The stop reason of the thread should be illegal opcode.
self.expect(
diff --git a/lldb/test/Shell/Recognizer/Inputs/ubsan_add_overflow.c b/lldb/test/Shell/Recognizer/Inputs/ubsan_add_overflow.c
new file mode 100644
index 0000000..9f12c32
--- /dev/null
+++ b/lldb/test/Shell/Recognizer/Inputs/ubsan_add_overflow.c
@@ -0,0 +1,3 @@
+#include <limits.h>
+
+int main() { return INT_MAX + 1; }
diff --git a/lldb/test/Shell/Recognizer/ubsan_add_overflow.test b/lldb/test/Shell/Recognizer/ubsan_add_overflow.test
new file mode 100644
index 0000000..a5e95cf
--- /dev/null
+++ b/lldb/test/Shell/Recognizer/ubsan_add_overflow.test
@@ -0,0 +1,22 @@
+# UNSUPPORTED: system-windows
+
+# RUN: %clang_host -g -O0 %S/Inputs/ubsan_add_overflow.c -o %t.out \
+# RUN: -fsanitize=signed-integer-overflow -fsanitize-trap=signed-integer-overflow
+
+# RUN: %lldb -b -s %s %t.out | FileCheck %s
+
+run
+# CHECK: thread #{{.*}} stop reason = Undefined Behavior Sanitizer: Integer addition overflowed
+# CHECK-NEXT: frame #1: {{.*}}`main at ubsan_add_overflow.c
+
+bt
+# CHECK: frame #0: {{.*}}`__clang_trap_msg$Undefined Behavior Sanitizer$Integer addition overflowed{{.*}}
+# CHECK: frame #1: {{.*}}`main at ubsan_add_overflow.c
+
+frame info
+# CHECK: frame #{{.*}}`main at ubsan_add_overflow.c
+
+frame recognizer info 0
+# CHECK: frame 0 is recognized by Verbose Trap StackFrame Recognizer
+
+quit
diff --git a/lldb/test/Shell/Scripts/TestFrameworkFixScript.test b/lldb/test/Shell/Scripts/TestFrameworkFixScript.test
index 2b1818e..183ea3a 100644
--- a/lldb/test/Shell/Scripts/TestFrameworkFixScript.test
+++ b/lldb/test/Shell/Scripts/TestFrameworkFixScript.test
@@ -1,6 +1,6 @@
# Create a temp dir for output and run the framework fix script on the truncated version of SBAddress.h in the inputs dir.
RUN: mkdir -p %t/Outputs
-RUN: %python %p/../../../scripts/framework-header-fix.py -f lldb_main -i %p/Inputs/Main/SBAddress.h -o %t/Outputs/SBAddress.h -p /usr/bin/unifdef --unifdef_guards USWIG
+RUN: %python %p/../../../scripts/framework-header-fix.py -f lldb_main -i %p/Inputs/Main/SBAddress.h -o %t/Outputs/SBAddress.h -p /usr/bin/unifdef --unifdef_guards SWIG
# Check the output
RUN: cat %t/Outputs/SBAddress.h | FileCheck %s
diff --git a/lldb/test/Shell/Scripts/TestFrameworkFixUnifdef.test b/lldb/test/Shell/Scripts/TestFrameworkFixUnifdef.test
index ba18b4b..a4fffe4 100644
--- a/lldb/test/Shell/Scripts/TestFrameworkFixUnifdef.test
+++ b/lldb/test/Shell/Scripts/TestFrameworkFixUnifdef.test
@@ -1,7 +1,7 @@
# REQUIRES: system-darwin
# Create a temp dir for output and run the framework fix script on the truncated version of SBAddress.h in the inputs dir.
RUN: mkdir -p %t/Outputs
-RUN: %python %p/../../../scripts/framework-header-fix.py -f lldb_main -i %p/Inputs/Main/SBAddress.h -o %t/Outputs/SBAddress.h -p /usr/bin/unifdef --unifdef_guards USWIG
+RUN: %python %p/../../../scripts/framework-header-fix.py -f lldb_main -i %p/Inputs/Main/SBAddress.h -o %t/Outputs/SBAddress.h -p /usr/bin/unifdef --unifdef_guards SWIG
# Check the output
RUN: cat %t/Outputs/SBAddress.h | FileCheck %s
diff --git a/lldb/test/Shell/Scripts/TestRPCFrameworkFixScript.test b/lldb/test/Shell/Scripts/TestRPCFrameworkFixScript.test
index e2080ca..d7775c2 100644
--- a/lldb/test/Shell/Scripts/TestRPCFrameworkFixScript.test
+++ b/lldb/test/Shell/Scripts/TestRPCFrameworkFixScript.test
@@ -1,6 +1,6 @@
# Create a temp dir for output and run the framework fix script on the truncated version of SBAddress.h in the inputs dir.
RUN: mkdir -p %t/Outputs
-RUN: %python %p/../../../scripts/framework-header-fix.py -f lldb_rpc -i %p/Inputs/RPC/RPCSBAddress.h -o %t/Outputs/RPCSBAddress.h -p /usr/bin/unifdef --unifdef_guards USWIG
+RUN: %python %p/../../../scripts/framework-header-fix.py -f lldb_rpc -i %p/Inputs/RPC/RPCSBAddress.h -o %t/Outputs/RPCSBAddress.h -p /usr/bin/unifdef --unifdef_guards SWIG
# Check the output
RUN: cat %t/Outputs/RPCSBAddress.h | FileCheck %s
diff --git a/lldb/tools/lldb-rpc/LLDBRPCHeaders.cmake b/lldb/tools/lldb-rpc/LLDBRPCHeaders.cmake
index 6c363f4..2376e23 100644
--- a/lldb/tools/lldb-rpc/LLDBRPCHeaders.cmake
+++ b/lldb/tools/lldb-rpc/LLDBRPCHeaders.cmake
@@ -79,7 +79,7 @@ function(FixIncludePaths in subfolder out)
add_custom_command(OUTPUT ${parked_header}
COMMAND ${LLDB_SOURCE_DIR}/scripts/framework-header-fix.py
- -f lldb_rpc -i ${in} -o ${parked_header} -p ${unifdef_EXECUTABLE} --unifdef_guards USWIG
+ -f lldb_rpc -i ${in} -o ${parked_header} -p ${unifdef_EXECUTABLE} --unifdef_guards SWIG
DEPENDS ${in}
COMMENT "Fixing includes in ${in}"
)
diff --git a/lldb/unittests/Core/DumpDataExtractorTest.cpp b/lldb/unittests/Core/DumpDataExtractorTest.cpp
index 3d1e8bc..6302f1e 100644
--- a/lldb/unittests/Core/DumpDataExtractorTest.cpp
+++ b/lldb/unittests/Core/DumpDataExtractorTest.cpp
@@ -163,6 +163,9 @@ TEST_F(DumpDataExtractorTest, Formats) {
TestDump(0xcafef00d, lldb::Format::eFormatHex, "0xcafef00d");
TestDump(0xcafef00d, lldb::Format::eFormatHexUppercase, "0xCAFEF00D");
TestDump(0.456, lldb::Format::eFormatFloat, "0.45600000000000002");
+ TestDump(std::vector<uint64_t>{0x47ae147ae147ae14, 0x40011147ae147ae1},
+ lldb::Format::eFormatFloat128,
+ "4.26999999999999999999999999999999963");
TestDump(9, lldb::Format::eFormatOctal, "011");
// Chars packed into an integer.
TestDump<uint32_t>(0x4C4C4442, lldb::Format::eFormatOSType, "'LLDB'");
@@ -388,6 +391,9 @@ TEST_F(DumpDataExtractorTest, ItemByteSizeErrors) {
TestDumpWithItemByteSize(
18, lldb::Format::eFormatFloat,
"error: unsupported byte size (18) for float format");
+ TestDumpWithItemByteSize(
+ 17, lldb::Format::eFormatFloat128,
+ "error: unsupported byte size (17) for float format");
// We want sizes to exactly match one of float/double.
TestDumpWithItemByteSize(
diff --git a/lldb/unittests/Expression/CMakeLists.txt b/lldb/unittests/Expression/CMakeLists.txt
index 533cdc6..4c58b3c 100644
--- a/lldb/unittests/Expression/CMakeLists.txt
+++ b/lldb/unittests/Expression/CMakeLists.txt
@@ -4,6 +4,7 @@ add_lldb_unittest(ExpressionTests
DiagnosticManagerTest.cpp
DWARFExpressionTest.cpp
CppModuleConfigurationTest.cpp
+ ExpressionTest.cpp
LINK_LIBS
lldbCore
diff --git a/lldb/unittests/Expression/ExpressionTest.cpp b/lldb/unittests/Expression/ExpressionTest.cpp
new file mode 100644
index 0000000..12f6dd5
--- /dev/null
+++ b/lldb/unittests/Expression/ExpressionTest.cpp
@@ -0,0 +1,122 @@
+//===-- ExpressionTest.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 "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+#include "TestingSupport/TestUtilities.h"
+#include "lldb/Expression/Expression.h"
+#include "llvm/Testing/Support/Error.h"
+
+using namespace lldb_private;
+
+struct LabelTestCase {
+ llvm::StringRef encoded;
+ FunctionCallLabel label;
+ llvm::SmallVector<llvm::StringRef> error_pattern;
+};
+
+static LabelTestCase g_label_test_cases[] = {
+ // Failure modes
+ {"bar:0x0:0x0:_Z3foov",
+ {},
+ {"expected function call label prefix '$__lldb_func' but found 'bar' "
+ "instead."}},
+ {"$__lldb_func :0x0:0x0:_Z3foov",
+ {},
+ {"expected function call label prefix '$__lldb_func' but found "
+ "'$__lldb_func ' instead."}},
+ {"$__lldb_funcc:0x0:0x0:_Z3foov",
+ {},
+ {"expected function call label prefix '$__lldb_func' but found "
+ "'$__lldb_funcc' instead."}},
+ {"", {}, {"malformed function call label."}},
+ {"foo", {}, {"malformed function call label."}},
+ {"$__lldb_func", {}, {"malformed function call label."}},
+ {"$__lldb_func:", {}, {"malformed function call label."}},
+ {"$__lldb_func:0x0:0x0", {}, {"malformed function call label."}},
+ {"$__lldb_func:abc:0x0:_Z3foov",
+ {},
+ {"failed to parse module ID from 'abc'."}},
+ {"$__lldb_func:-1:0x0:_Z3foov",
+ {},
+ {"failed to parse module ID from '-1'."}},
+ {"$__lldb_func:0x0invalid:0x0:_Z3foov",
+ {},
+ {"failed to parse module ID from '0x0invalid'."}},
+ {"$__lldb_func:0x0 :0x0:_Z3foov",
+ {},
+ {"failed to parse module ID from '0x0 '."}},
+ {"$__lldb_func:0x0:abc:_Z3foov",
+ {},
+ {"failed to parse symbol ID from 'abc'."}},
+ {"$__lldb_func:0x5:-1:_Z3foov",
+ {},
+ {"failed to parse symbol ID from '-1'."}},
+ {"$__lldb_func:0x5:0x0invalid:_Z3foov",
+ {},
+ {"failed to parse symbol ID from '0x0invalid'."}},
+ {"$__lldb_func:0x5:0x0 :_Z3foov",
+ {},
+ {"failed to parse symbol ID from '0x0 '."}},
+ {"$__lldb_func:0x0:0x0:_Z3foov",
+ {
+ /*.module_id=*/0x0,
+ /*.symbol_id=*/0x0,
+ /*.lookup_name=*/"_Z3foov",
+ },
+ {}},
+ {"$__lldb_func:0x0:0x0:abc:def:::a",
+ {
+ /*.module_id=*/0x0,
+ /*.symbol_id=*/0x0,
+ /*.lookup_name=*/"abc:def:::a",
+ },
+ {}},
+ {"$__lldb_func:0xd2:0xf0:$__lldb_func",
+ {
+ /*.module_id=*/0xd2,
+ /*.symbol_id=*/0xf0,
+ /*.lookup_name=*/"$__lldb_func",
+ },
+ {}},
+};
+
+struct ExpressionTestFixture : public testing::TestWithParam<LabelTestCase> {};
+
+TEST_P(ExpressionTestFixture, FunctionCallLabel) {
+ const auto &[encoded, label, errors] = GetParam();
+
+ auto decoded_or_err = FunctionCallLabel::fromString(encoded);
+ if (!errors.empty()) {
+ EXPECT_THAT_EXPECTED(
+ decoded_or_err,
+ llvm::FailedWithMessageArray(testing::ElementsAreArray(errors)));
+ return;
+ }
+
+ EXPECT_THAT_EXPECTED(decoded_or_err, llvm::Succeeded());
+
+ auto label_str = label.toString();
+ EXPECT_EQ(decoded_or_err->toString(), encoded);
+ EXPECT_EQ(label_str, encoded);
+
+ EXPECT_EQ(decoded_or_err->module_id, label.module_id);
+ EXPECT_EQ(decoded_or_err->symbol_id, label.symbol_id);
+ EXPECT_EQ(decoded_or_err->lookup_name, label.lookup_name);
+
+ auto roundtrip_or_err = FunctionCallLabel::fromString(label_str);
+ EXPECT_THAT_EXPECTED(roundtrip_or_err, llvm::Succeeded());
+
+ EXPECT_EQ(roundtrip_or_err->module_id, label.module_id);
+ EXPECT_EQ(roundtrip_or_err->symbol_id, label.symbol_id);
+ EXPECT_EQ(roundtrip_or_err->lookup_name, label.lookup_name);
+}
+
+INSTANTIATE_TEST_SUITE_P(FunctionCallLabelTest, ExpressionTestFixture,
+ testing::ValuesIn(g_label_test_cases));
diff --git a/lldb/unittests/Host/FileSystemTest.cpp b/lldb/unittests/Host/FileSystemTest.cpp
index 58887f6..e3c2b5a 100644
--- a/lldb/unittests/Host/FileSystemTest.cpp
+++ b/lldb/unittests/Host/FileSystemTest.cpp
@@ -186,7 +186,7 @@ TEST(FileSystemTest, FileAndDirectoryComponents) {
}
static IntrusiveRefCntPtr<DummyFileSystem> GetSimpleDummyFS() {
- IntrusiveRefCntPtr<DummyFileSystem> D(new DummyFileSystem());
+ auto D = makeIntrusiveRefCnt<DummyFileSystem>();
D->addRegularFile("/foo");
D->addDirectory("/bar");
D->addSymlink("/baz");
diff --git a/lldb/unittests/Symbol/TestTypeSystemClang.cpp b/lldb/unittests/Symbol/TestTypeSystemClang.cpp
index 71930ab..b993b82 100644
--- a/lldb/unittests/Symbol/TestTypeSystemClang.cpp
+++ b/lldb/unittests/Symbol/TestTypeSystemClang.cpp
@@ -17,6 +17,7 @@
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/ExprCXX.h"
+#include "llvm/IR/GlobalValue.h"
#include "gtest/gtest.h"
using namespace clang;
@@ -76,6 +77,8 @@ TEST_F(TestTypeSystemClang, TestGetBasicTypeFromEnum) {
context.getComplexType(context.FloatTy)));
EXPECT_TRUE(
context.hasSameType(GetBasicQualType(eBasicTypeHalf), context.HalfTy));
+ EXPECT_TRUE(context.hasSameType(GetBasicQualType(eBasicTypeFloat128),
+ context.Float128Ty));
EXPECT_TRUE(
context.hasSameType(GetBasicQualType(eBasicTypeInt), context.IntTy));
EXPECT_TRUE(context.hasSameType(GetBasicQualType(eBasicTypeInt128),
@@ -869,7 +872,7 @@ TEST_F(TestTypeSystemClang, TestFunctionTemplateConstruction) {
CompilerType clang_type = m_ast->CreateFunctionType(int_type, {}, false, 0U);
FunctionDecl *func = m_ast->CreateFunctionDeclaration(
TU, OptionalClangModuleID(), "foo", clang_type, StorageClass::SC_None,
- false);
+ false, /*asm_label=*/{});
TypeSystemClang::TemplateParameterInfos empty_params;
// Create the actual function template.
@@ -900,7 +903,7 @@ TEST_F(TestTypeSystemClang, TestFunctionTemplateInRecordConstruction) {
// 2. It is mirroring the behavior of DWARFASTParserClang::ParseSubroutine.
FunctionDecl *func = m_ast->CreateFunctionDeclaration(
TU, OptionalClangModuleID(), "foo", clang_type, StorageClass::SC_None,
- false);
+ false, /*asm_label=*/{});
TypeSystemClang::TemplateParameterInfos empty_params;
// Create the actual function template.
@@ -938,7 +941,7 @@ TEST_F(TestTypeSystemClang, TestDeletingImplicitCopyCstrDueToMoveCStr) {
bool is_attr_used = false;
bool is_artificial = false;
m_ast->AddMethodToCXXRecordType(
- t.GetOpaqueQualType(), class_name, nullptr, function_type,
+ t.GetOpaqueQualType(), class_name, /*asm_label=*/{}, function_type,
lldb::AccessType::eAccessPublic, is_virtual, is_static, is_inline,
is_explicit, is_attr_used, is_artificial);
@@ -975,7 +978,7 @@ TEST_F(TestTypeSystemClang, TestNotDeletingUserCopyCstrDueToMoveCStr) {
CompilerType function_type = m_ast->CreateFunctionType(
return_type, args, /*variadic=*/false, /*quals*/ 0U);
m_ast->AddMethodToCXXRecordType(
- t.GetOpaqueQualType(), class_name, nullptr, function_type,
+ t.GetOpaqueQualType(), class_name, /*asm_label=*/{}, function_type,
lldb::AccessType::eAccessPublic, is_virtual, is_static, is_inline,
is_explicit, is_attr_used, is_artificial);
}
@@ -987,7 +990,7 @@ TEST_F(TestTypeSystemClang, TestNotDeletingUserCopyCstrDueToMoveCStr) {
m_ast->CreateFunctionType(return_type, args,
/*variadic=*/false, /*quals*/ 0U);
m_ast->AddMethodToCXXRecordType(
- t.GetOpaqueQualType(), class_name, nullptr, function_type,
+ t.GetOpaqueQualType(), class_name, /*asm_label=*/{}, function_type,
lldb::AccessType::eAccessPublic, is_virtual, is_static, is_inline,
is_explicit, is_attr_used, is_artificial);
}
@@ -1098,7 +1101,7 @@ TEST_F(TestTypeSystemClang, AddMethodToCXXRecordType_ParmVarDecls) {
m_ast->CreateFunctionType(return_type, param_types,
/*variadic=*/false, /*quals*/ 0U);
m_ast->AddMethodToCXXRecordType(
- t.GetOpaqueQualType(), "myFunc", nullptr, function_type,
+ t.GetOpaqueQualType(), "myFunc", /*asm_label=*/{}, function_type,
lldb::AccessType::eAccessPublic, is_virtual, is_static, is_inline,
is_explicit, is_attr_used, is_artificial);
@@ -1116,3 +1119,130 @@ TEST_F(TestTypeSystemClang, AddMethodToCXXRecordType_ParmVarDecls) {
EXPECT_EQ(method_it->getParamDecl(0)->getDeclContext(), *method_it);
EXPECT_EQ(method_it->getParamDecl(1)->getDeclContext(), *method_it);
}
+
+TEST_F(TestTypeSystemClang, AsmLabel_CtorDtor) {
+ // Tests TypeSystemClang::DeclGetMangledName for constructors/destructors
+ // with and without AsmLabels.
+
+ llvm::StringRef class_name = "S";
+ CompilerType t = clang_utils::createRecord(*m_ast, class_name);
+ m_ast->StartTagDeclarationDefinition(t);
+
+ CompilerType return_type = m_ast->GetBasicType(lldb::eBasicTypeVoid);
+ const bool is_virtual = false;
+ const bool is_static = false;
+ const bool is_inline = false;
+ const bool is_explicit = true;
+ const bool is_attr_used = false;
+ const bool is_artificial = false;
+
+ CompilerType function_type =
+ m_ast->CreateFunctionType(return_type, {},
+ /*variadic=*/false, /*quals*/ 0U);
+ auto *ctor_nolabel = m_ast->AddMethodToCXXRecordType(
+ t.GetOpaqueQualType(), "S", /*asm_label=*/{}, function_type,
+ lldb::AccessType::eAccessPublic, is_virtual, is_static, is_inline,
+ is_explicit, is_attr_used, is_artificial);
+
+ auto *dtor_nolabel = m_ast->AddMethodToCXXRecordType(
+ t.GetOpaqueQualType(), "~S", /*asm_label=*/{}, function_type,
+ lldb::AccessType::eAccessPublic, is_virtual, is_static, is_inline,
+ is_explicit, is_attr_used, is_artificial);
+
+ auto *ctor = m_ast->AddMethodToCXXRecordType(
+ t.GetOpaqueQualType(), "S", /*asm_label=*/"$__lldb_func:0x0:0x0:S",
+ function_type, lldb::AccessType::eAccessPublic, is_virtual, is_static,
+ is_inline, is_explicit, is_attr_used, is_artificial);
+
+ auto *dtor = m_ast->AddMethodToCXXRecordType(
+ t.GetOpaqueQualType(), "~S", /*asm_label=*/"$__lldb_func:0x0:0x0:~S",
+ function_type, lldb::AccessType::eAccessPublic, is_virtual, is_static,
+ is_inline, is_explicit, is_attr_used, is_artificial);
+
+ m_ast->CompleteTagDeclarationDefinition(t);
+
+ ASSERT_TRUE(ctor_nolabel);
+ ASSERT_TRUE(dtor_nolabel);
+ ASSERT_TRUE(ctor);
+ ASSERT_TRUE(dtor);
+
+#ifdef _WIN32
+ EXPECT_STREQ(m_ast->DeclGetMangledName(ctor_nolabel).GetCString(),
+ "??0S@@QEAA@XZ");
+ EXPECT_STREQ(m_ast->DeclGetMangledName(dtor_nolabel).GetCString(),
+ "??_DS@@QEAAXXZ");
+#else
+ EXPECT_STREQ(m_ast->DeclGetMangledName(ctor_nolabel).GetCString(),
+ "_ZN1SC1Ev");
+ EXPECT_STREQ(m_ast->DeclGetMangledName(dtor_nolabel).GetCString(),
+ "_ZN1SD1Ev");
+#endif
+
+ EXPECT_STREQ(llvm::GlobalValue::dropLLVMManglingEscape(
+ m_ast->DeclGetMangledName(ctor).GetStringRef())
+ .data(),
+ "$__lldb_func:0x0:0x0:S");
+ EXPECT_STREQ(llvm::GlobalValue::dropLLVMManglingEscape(
+ m_ast->DeclGetMangledName(dtor).GetStringRef())
+ .data(),
+ "$__lldb_func:0x0:0x0:~S");
+}
+
+struct AsmLabelTestCase {
+ llvm::StringRef mangled;
+ llvm::StringRef expected;
+};
+
+class TestTypeSystemClangAsmLabel
+ : public testing::TestWithParam<AsmLabelTestCase> {
+public:
+ SubsystemRAII<FileSystem, HostInfo> subsystems;
+
+ void SetUp() override {
+ m_holder =
+ std::make_unique<clang_utils::TypeSystemClangHolder>("test ASTContext");
+ m_ast = m_holder->GetAST();
+ }
+
+ void TearDown() override {
+ m_ast = nullptr;
+ m_holder.reset();
+ }
+
+protected:
+ TypeSystemClang *m_ast = nullptr;
+ std::unique_ptr<clang_utils::TypeSystemClangHolder> m_holder;
+};
+
+static AsmLabelTestCase g_asm_label_test_cases[] = {
+ {/*mangled=*/"$__lldb_func:0x0:0x0:_Z3foov",
+ /*expected=*/"_Z3foov"},
+ {/*mangled=*/"$__lldb_func:0x0:0x0:foo",
+ /*expected=*/"$__lldb_func:0x0:0x0:foo"},
+ {/*mangled=*/"foo",
+ /*expected=*/"foo"},
+ {/*mangled=*/"_Z3foov",
+ /*expected=*/"_Z3foov"},
+ {/*mangled=*/"$__lldb_func:",
+ /*expected=*/"$__lldb_func:"},
+};
+
+TEST_P(TestTypeSystemClangAsmLabel, DeclGetMangledName) {
+ const auto &[mangled, expected] = GetParam();
+
+ CompilerType int_type = m_ast->GetBasicType(lldb::eBasicTypeInt);
+ clang::TranslationUnitDecl *TU = m_ast->GetTranslationUnitDecl();
+
+ // Prepare the declarations/types we need for the template.
+ CompilerType clang_type = m_ast->CreateFunctionType(int_type, {}, false, 0U);
+ FunctionDecl *func = m_ast->CreateFunctionDeclaration(
+ TU, OptionalClangModuleID(), "foo", clang_type, StorageClass::SC_None,
+ false, /*asm_label=*/mangled);
+
+ ASSERT_EQ(llvm::GlobalValue::dropLLVMManglingEscape(
+ m_ast->DeclGetMangledName(func).GetStringRef()),
+ expected);
+}
+
+INSTANTIATE_TEST_SUITE_P(AsmLabelTests, TestTypeSystemClangAsmLabel,
+ testing::ValuesIn(g_asm_label_test_cases));