[lldb][AArch64] Add memory-tagging qSupported feature

This feature "memory-tagging+" indicates that lldb-server
supports memory tagging packets. (added in a later patch)

We check HWCAP2_MTE to decide whether to enable this
feature for Linux.

Reviewed By: omjavaid

Differential Revision: https://reviews.llvm.org/D97282
This commit is contained in:
David Spickett 2021-02-19 15:32:09 +00:00
parent d57a5879ab
commit 8d58fbd09e
10 changed files with 59 additions and 3 deletions

View File

@ -243,8 +243,9 @@ public:
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 {

View File

@ -2721,6 +2721,13 @@ protected:
/// 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<lldb::LanguageType, lldb::LanguageRuntimeSP>
LanguageRuntimeCollection;

View File

@ -858,6 +858,7 @@ class GdbRemoteTestCaseBase(Base):
"multiprocess",
"fork-events",
"vfork-events",
"memory-tagging",
]
def parse_qSupported_response(self, context):

View File

@ -53,11 +53,20 @@
#include <sys/user.h>
#include <sys/wait.h>
#ifdef __aarch64__
#include <asm/hwcap.h>
#include <sys/auxv.h>
#endif
// Support hardware breakpoints in case it has not been defined
#ifndef TRAP_HWBKPT
#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 +292,17 @@ NativeProcessLinux::Factory::Attach(
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;
#ifdef __aarch64__
// At this point we do not have a process so read auxv directly.
if ((getauxval(AT_HWCAP2) & HWCAP2_MTE))
supported |= Extension::memory_tagging;
#endif
return supported;
}
// Public Instance Methods

View File

@ -311,6 +311,7 @@ void GDBRemoteCommunicationClient::GetRemoteQSupported() {
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
@ -356,6 +357,8 @@ void GDBRemoteCommunicationClient::GetRemoteQSupported() {
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
@ -576,6 +579,13 @@ bool GDBRemoteCommunicationClient::GetSharedCacheInfoSupported() {
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;

View File

@ -451,6 +451,8 @@ public:
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 @@ protected:
LazyBool m_supports_QPassSignals = eLazyBoolCalculate;
LazyBool m_supports_error_string_reply = eLazyBoolCalculate;
LazyBool m_supports_multiprocess = eLazyBoolCalculate;
LazyBool m_supports_memory_tagging = eLazyBoolCalculate;
bool m_supports_qProcessInfoPID : 1, m_supports_qfProcessInfo : 1,
m_supports_qUserName : 1, m_supports_qGroupName : 1,

View File

@ -3608,6 +3608,8 @@ std::vector<std::string> GDBRemoteCommunicationServerLLGS::HandleFeatures(
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 = {};

View File

@ -2767,6 +2767,10 @@ size_t ProcessGDBRemote::DoReadMemory(addr_t addr, void *buf, size_t size,
return 0;
}
bool ProcessGDBRemote::SupportsMemoryTagging() {
return m_gdb_comm.GetMemoryTaggingSupported();
}
Status ProcessGDBRemote::WriteObjectFile(
std::vector<ObjectFile::LoadableData> entries) {
Status error;

View File

@ -235,6 +235,8 @@ protected:
friend class GDBRemoteCommunicationClient;
friend class GDBRemoteRegisterContext;
bool SupportsMemoryTagging() override;
/// Broadcaster event bits definitions.
enum {
eBroadcastBitAsyncContinue = (1 << 0),

View File

@ -1025,6 +1025,14 @@ class LldbGdbServerTestCase(gdbremote_testcase.GdbRemoteTestCaseBase, DwarfOpcod
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()