From d510b5f199d6e7a3062b5a6ea43181c4cc00a605 Mon Sep 17 00:00:00 2001 From: David Spickett Date: Mon, 12 Apr 2021 15:40:32 +0100 Subject: [lldb][AArch64] Annotate synchronous tag faults In the latest Linux kernels synchronous tag faults include the tag bits in their address. This change adds logical and allocation tags to the description of synchronous tag faults. (asynchronous faults have no address) Process 1626 stopped * thread #1, name = 'a.out', stop reason = signal SIGSEGV: sync tag check fault (fault address: 0x900fffff7ff9010 logical tag: 0x9 allocation tag: 0x0) This extends the existing description and will show as much as it can on the rare occasion something fails. This change supports AArch64 MTE only but other architectures could be added by extending the switch at the start of AnnotateSyncTagCheckFault. The rest of the function is generic code. Tests have been added for synchronous and asynchronous MTE faults. Reviewed By: omjavaid Differential Revision: https://reviews.llvm.org/D105178 --- .../Plugins/Process/Linux/NativeThreadLinux.cpp | 59 ++++++++++++++++++++++ 1 file changed, 59 insertions(+) (limited to 'lldb/source/Plugins/Process/Linux/NativeThreadLinux.cpp') diff --git a/lldb/source/Plugins/Process/Linux/NativeThreadLinux.cpp b/lldb/source/Plugins/Process/Linux/NativeThreadLinux.cpp index d8ba5415a983..a7e4e9b13ff0 100644 --- a/lldb/source/Plugins/Process/Linux/NativeThreadLinux.cpp +++ b/lldb/source/Plugins/Process/Linux/NativeThreadLinux.cpp @@ -26,6 +26,7 @@ #include "llvm/ADT/SmallString.h" #include "Plugins/Process/POSIX/CrashReason.h" +#include "Plugins/Process/Utility/MemoryTagManagerAArch64MTE.h" #include // Try to define a macro to encapsulate the tgkill syscall @@ -299,11 +300,69 @@ void NativeThreadLinux::SetStoppedBySignal(uint32_t signo, ? CrashReason::eInvalidAddress : GetCrashReason(*info); m_stop_description = GetCrashReasonString(reason, *info); + + if (reason == CrashReason::eSyncTagCheckFault) { + AnnotateSyncTagCheckFault(info); + } + break; } } } +void NativeThreadLinux::AnnotateSyncTagCheckFault(const siginfo_t *info) { + int32_t allocation_tag_type = 0; + switch (GetProcess().GetArchitecture().GetMachine()) { + // aarch64_32 deliberately not here because there's no 32 bit MTE + case llvm::Triple::aarch64: + case llvm::Triple::aarch64_be: + allocation_tag_type = MemoryTagManagerAArch64MTE::eMTE_allocation; + break; + default: + return; + } + + auto details = + GetRegisterContext().GetMemoryTaggingDetails(allocation_tag_type); + if (!details) { + llvm::consumeError(details.takeError()); + return; + } + + // We assume that the stop description is currently: + // signal SIGSEGV: sync tag check fault (fault address: ) + // Remove the closing ) + m_stop_description.pop_back(); + + std::stringstream ss; + lldb::addr_t fault_addr = reinterpret_cast(info->si_addr); + std::unique_ptr manager(std::move(details->manager)); + + ss << " logical tag: 0x" << std::hex << manager->GetLogicalTag(fault_addr); + + std::vector allocation_tag_data; + // The fault address may not be granule aligned. ReadMemoryTags will granule + // align any range you give it, potentially making it larger. + // To prevent this set len to 1. This always results in a range that is at + // most 1 granule in size and includes fault_addr. + Status status = GetProcess().ReadMemoryTags(allocation_tag_type, fault_addr, + 1, allocation_tag_data); + + if (status.Success()) { + llvm::Expected> allocation_tag = + manager->UnpackTagsData(allocation_tag_data, 1); + if (allocation_tag) { + ss << " allocation tag: 0x" << std::hex << allocation_tag->front() << ")"; + } else { + llvm::consumeError(allocation_tag.takeError()); + ss << ")"; + } + } else + ss << ")"; + + m_stop_description += ss.str(); +} + bool NativeThreadLinux::IsStopped(int *signo) { if (!StateIsStoppedState(m_state, false)) return false; -- cgit v1.2.3