aboutsummaryrefslogtreecommitdiff
path: root/lldb/source/Plugins/Process/Linux/NativeThreadLinux.cpp
diff options
context:
space:
mode:
authorDavid Spickett <david.spickett@linaro.org>2021-04-12 15:40:32 +0100
committerDavid Spickett <david.spickett@linaro.org>2021-07-29 10:26:37 +0100
commitd510b5f199d6e7a3062b5a6ea43181c4cc00a605 (patch)
tree6bb4eae3fa35275514d4a7c3418f27dccfde1e67 /lldb/source/Plugins/Process/Linux/NativeThreadLinux.cpp
parent971f4173f82da6e13ee4c5b1a0301ba0fde0d696 (diff)
downloadllvm-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.cpp59
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;