diff options
author | David Spickett <david.spickett@linaro.org> | 2021-04-12 15:40:32 +0100 |
---|---|---|
committer | David Spickett <david.spickett@linaro.org> | 2021-07-29 10:26:37 +0100 |
commit | d510b5f199d6e7a3062b5a6ea43181c4cc00a605 (patch) | |
tree | 6bb4eae3fa35275514d4a7c3418f27dccfde1e67 /lldb/source/Plugins/Process/Linux/NativeThreadLinux.cpp | |
parent | 971f4173f82da6e13ee4c5b1a0301ba0fde0d696 (diff) | |
download | llvm-d510b5f199d6e7a3062b5a6ea43181c4cc00a605.zip llvm-d510b5f199d6e7a3062b5a6ea43181c4cc00a605.tar.gz llvm-d510b5f199d6e7a3062b5a6ea43181c4cc00a605.tar.bz2 |
[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
Diffstat (limited to 'lldb/source/Plugins/Process/Linux/NativeThreadLinux.cpp')
-rw-r--r-- | lldb/source/Plugins/Process/Linux/NativeThreadLinux.cpp | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/lldb/source/Plugins/Process/Linux/NativeThreadLinux.cpp b/lldb/source/Plugins/Process/Linux/NativeThreadLinux.cpp index d8ba541..a7e4e9b 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 <sys/syscall.h> // 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: <addr>) + // Remove the closing ) + m_stop_description.pop_back(); + + std::stringstream ss; + lldb::addr_t fault_addr = reinterpret_cast<uintptr_t>(info->si_addr); + std::unique_ptr<MemoryTagManager> manager(std::move(details->manager)); + + ss << " logical tag: 0x" << std::hex << manager->GetLogicalTag(fault_addr); + + std::vector<uint8_t> 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<std::vector<lldb::addr_t>> 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; |