diff --git a/lldb/include/lldb/Host/common/NativeProcessProtocol.h b/lldb/include/lldb/Host/common/NativeProcessProtocol.h --- a/lldb/include/lldb/Host/common/NativeProcessProtocol.h +++ b/lldb/include/lldb/Host/common/NativeProcessProtocol.h @@ -243,8 +243,9 @@ pass_signals = (1u << 3), auxv = (1u << 4), libraries_svr4 = (1u << 5), + memory_tagging = (1u << 6), - LLVM_MARK_AS_BITMASK_ENUM(libraries_svr4) + LLVM_MARK_AS_BITMASK_ENUM(memory_tagging) }; class Factory { diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h --- a/lldb/include/lldb/Target/Process.h +++ b/lldb/include/lldb/Target/Process.h @@ -2772,6 +2772,13 @@ /// false. bool RouteAsyncStructuredData(const StructuredData::ObjectSP object_sp); + /// Check whether the process supports memory tagging. + /// + /// \return + /// true if the process supports memory tagging, + /// false otherwise. + virtual bool SupportsMemoryTagging() { return false; } + // Type definitions typedef std::map LanguageRuntimeCollection; diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py --- a/lldb/packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py +++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py @@ -857,6 +857,7 @@ "multiprocess", "fork-events", "vfork-events", + "memory-tagging", ] def parse_qSupported_response(self, context): diff --git a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp --- a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp +++ b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp @@ -46,7 +46,9 @@ #include "llvm/Support/FileSystem.h" #include "llvm/Support/Threading.h" +#include #include +#include #include #include #include @@ -58,6 +60,10 @@ #define TRAP_HWBKPT 4 #endif +#ifndef HWCAP2_MTE +#define HWCAP2_MTE (1 << 18) +#endif + using namespace lldb; using namespace lldb_private; using namespace lldb_private::process_linux; @@ -283,8 +289,15 @@ NativeProcessLinux::Extension NativeProcessLinux::Factory::GetSupportedExtensions() const { - return Extension::multiprocess | Extension::fork | Extension::vfork | - Extension::pass_signals | Extension::auxv | Extension::libraries_svr4; + NativeProcessLinux::Extension supported = + Extension::multiprocess | Extension::fork | Extension::vfork | + Extension::pass_signals | Extension::auxv | Extension::libraries_svr4; + + // At this point we do not have a process so read auxv directly. + if ((getauxval(AT_HWCAP2) & HWCAP2_MTE)) + supported |= Extension::memory_tagging; + + return supported; } // Public Instance Methods diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h @@ -451,6 +451,8 @@ bool GetSharedCacheInfoSupported(); + bool GetMemoryTaggingSupported(); + /// Use qOffsets to query the offset used when relocating the target /// executable. If successful, the returned structure will contain at least /// one value in the offsets field. @@ -558,6 +560,7 @@ LazyBool m_supports_QPassSignals; LazyBool m_supports_error_string_reply; LazyBool m_supports_multiprocess; + LazyBool m_supports_memory_tagging; bool m_supports_qProcessInfoPID : 1, m_supports_qfProcessInfo : 1, m_supports_qUserName : 1, m_supports_qGroupName : 1, diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -90,6 +90,7 @@ m_supports_QPassSignals(eLazyBoolCalculate), m_supports_error_string_reply(eLazyBoolCalculate), m_supports_multiprocess(eLazyBoolCalculate), + m_supports_memory_tagging(eLazyBoolCalculate), m_supports_qProcessInfoPID(true), m_supports_qfProcessInfo(true), m_supports_qUserName(true), m_supports_qGroupName(true), m_supports_qThreadStopInfo(true), m_supports_z0(true), @@ -347,6 +348,7 @@ m_supports_multiprocess = eLazyBoolNo; m_supports_qEcho = eLazyBoolNo; m_supports_QPassSignals = eLazyBoolNo; + m_supports_memory_tagging = eLazyBoolNo; m_max_packet_size = UINT64_MAX; // It's supposed to always be there, but if // not, we assume no limit @@ -392,6 +394,8 @@ m_supports_QPassSignals = eLazyBoolYes; else if (x == "multiprocess+") m_supports_multiprocess = eLazyBoolYes; + else if (x == "memory-tagging+") + m_supports_memory_tagging = eLazyBoolYes; // Look for a list of compressions in the features list e.g. // qXfer:features:read+;PacketSize=20000;qEcho+;SupportedCompressions=zlib- // deflate,lzma @@ -612,6 +616,13 @@ return m_supports_jGetSharedCacheInfo; } +bool GDBRemoteCommunicationClient::GetMemoryTaggingSupported() { + if (m_supports_memory_tagging == eLazyBoolCalculate) { + GetRemoteQSupported(); + } + return m_supports_memory_tagging == eLazyBoolYes; +} + bool GDBRemoteCommunicationClient::GetxPacketSupported() { if (m_supports_x == eLazyBoolCalculate) { StringExtractorGDBRemote response; diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp @@ -3608,6 +3608,8 @@ ret.push_back("qXfer:auxv:read+"); if (bool(plugin_features & Extension::libraries_svr4)) ret.push_back("qXfer:libraries-svr4:read+"); + if (bool(plugin_features & Extension::memory_tagging)) + ret.push_back("memory-tagging+"); // check for client features m_extensions_supported = {}; diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h @@ -235,6 +235,8 @@ friend class GDBRemoteCommunicationClient; friend class GDBRemoteRegisterContext; + bool SupportsMemoryTagging() override; + /// Broadcaster event bits definitions. enum { eBroadcastBitAsyncContinue = (1 << 0), diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -2768,6 +2768,10 @@ return 0; } +bool ProcessGDBRemote::SupportsMemoryTagging() { + return m_gdb_comm.GetMemoryTaggingSupported(); +} + Status ProcessGDBRemote::WriteObjectFile( std::vector entries) { Status error; diff --git a/lldb/test/API/tools/lldb-server/TestLldbGdbServer.py b/lldb/test/API/tools/lldb-server/TestLldbGdbServer.py --- a/lldb/test/API/tools/lldb-server/TestLldbGdbServer.py +++ b/lldb/test/API/tools/lldb-server/TestLldbGdbServer.py @@ -1025,6 +1025,14 @@ self.assertEqual(supported_dict.get('fork-events', '-'), '-') self.assertEqual(supported_dict.get('vfork-events', '-'), '-') + # We need to be able to self.runCmd to get cpuinfo, + # which is not possible when using a remote platform. + @skipIfRemote + def test_qSupported_memory_tagging(self): + supported_dict = self.get_qSupported_dict() + self.assertEqual(supported_dict.get("memory-tagging", '-'), + '+' if self.isAArch64MTE() else '-') + @skipIfWindows # No pty support to test any inferior output def test_written_M_content_reads_back_correctly(self): self.build()