diff --git a/lldb/source/Plugins/Process/POSIX/CrashReason.h b/lldb/source/Plugins/Process/POSIX/CrashReason.h --- a/lldb/source/Plugins/Process/POSIX/CrashReason.h +++ b/lldb/source/Plugins/Process/POSIX/CrashReason.h @@ -13,6 +13,7 @@ #include +#include #include enum class CrashReason { @@ -51,7 +52,10 @@ eFloatSubscriptRange }; -std::string GetCrashReasonString(CrashReason reason, lldb::addr_t fault_addr); +// fault_addr will be empty when used from a core file which does not record the +// fault address. +std::string GetCrashReasonString(CrashReason reason, + std::optional fault_addr); std::string GetCrashReasonString(CrashReason reason, const siginfo_t &info); const char *CrashReasonAsString(CrashReason reason); diff --git a/lldb/source/Plugins/Process/POSIX/CrashReason.cpp b/lldb/source/Plugins/Process/POSIX/CrashReason.cpp --- a/lldb/source/Plugins/Process/POSIX/CrashReason.cpp +++ b/lldb/source/Plugins/Process/POSIX/CrashReason.cpp @@ -159,7 +159,8 @@ reinterpret_cast(info.si_addr)); } -std::string GetCrashReasonString(CrashReason reason, lldb::addr_t fault_addr) { +std::string GetCrashReasonString(CrashReason reason, + std::optional fault_addr) { std::string str; switch (reason) { @@ -169,11 +170,13 @@ case CrashReason::eInvalidAddress: str = "signal SIGSEGV: invalid address"; - AppendFaultAddr(str, fault_addr); + if (fault_addr) + AppendFaultAddr(str, *fault_addr); break; case CrashReason::ePrivilegedAddress: str = "signal SIGSEGV: address access protected"; - AppendFaultAddr(str, fault_addr); + if (fault_addr) + AppendFaultAddr(str, *fault_addr); break; case CrashReason::eBoundViolation: str = "signal SIGSEGV: bound violation"; @@ -183,7 +186,8 @@ break; case CrashReason::eSyncTagCheckFault: str = "signal SIGSEGV: sync tag check fault"; - AppendFaultAddr(str, fault_addr); + if (fault_addr) + AppendFaultAddr(str, *fault_addr); break; case CrashReason::eIllegalOpcode: str = "signal SIGILL: illegal instruction"; @@ -350,6 +354,5 @@ return GetCrashReasonForSIGILL(info); } - assert(false && "unexpected signal"); return CrashReason::eInvalidCrashReason; } diff --git a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp --- a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp +++ b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp @@ -920,6 +920,7 @@ if (status.Fail()) return status.ToError(); thread_data.signo = siginfo.si_signo; + thread_data.code = siginfo.si_code; break; } case ELF::NT_FILE: { diff --git a/lldb/source/Plugins/Process/elf-core/ThreadElfCore.h b/lldb/source/Plugins/Process/elf-core/ThreadElfCore.h --- a/lldb/source/Plugins/Process/elf-core/ThreadElfCore.h +++ b/lldb/source/Plugins/Process/elf-core/ThreadElfCore.h @@ -128,6 +128,7 @@ std::vector notes; lldb::tid_t tid; int signo = 0; + int code = 0; int prstatus_sig = 0; std::string name; }; @@ -166,6 +167,7 @@ lldb::RegisterContextSP m_thread_reg_ctx_sp; int m_signo; + int m_code; lldb_private::DataExtractor m_gpregset_data; std::vector m_notes; diff --git a/lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp b/lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp --- a/lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp +++ b/lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp @@ -14,6 +14,7 @@ #include "lldb/Utility/LLDBLog.h" #include "lldb/Utility/Log.h" +#include "Plugins/Process/POSIX/CrashReason.h" #include "Plugins/Process/Utility/RegisterContextFreeBSD_i386.h" #include "Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h" #include "Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h" @@ -39,6 +40,7 @@ #include "ThreadElfCore.h" #include +#include using namespace lldb; using namespace lldb_private; @@ -46,7 +48,8 @@ // Construct a Thread object with given data ThreadElfCore::ThreadElfCore(Process &process, const ThreadData &td) : Thread(process, td.tid), m_thread_name(td.name), m_thread_reg_ctx_sp(), - m_signo(td.signo), m_gpregset_data(td.gpregset), m_notes(td.notes) {} + m_signo(td.signo), m_code(td.code), m_gpregset_data(td.gpregset), + m_notes(td.notes) {} ThreadElfCore::~ThreadElfCore() { DestroyThread(); } @@ -221,11 +224,20 @@ bool ThreadElfCore::CalculateStopInfo() { ProcessSP process_sp(GetProcess()); - if (process_sp) { - SetStopInfo(StopInfo::CreateStopReasonWithSignal(*this, m_signo)); - return true; + if (!process_sp) + return false; + + siginfo_t info; + info.si_signo = m_signo; + info.si_code = m_code; + std::string description; + CrashReason reason = GetCrashReason(info); + if (reason != CrashReason::eInvalidCrashReason) { + description = GetCrashReasonString(reason, /*fault_addr=*/std::nullopt); } - return false; + SetStopInfo(StopInfo::CreateStopReasonWithSignal( + *this, m_signo, description.size() ? description.c_str() : nullptr)); + return true; } // Parse PRSTATUS from NOTE entry @@ -409,8 +421,8 @@ // properly, because the struct is for the 64 bit version offset_t offset = 0; si_signo = data.GetU32(&offset); - si_code = data.GetU32(&offset); si_errno = data.GetU32(&offset); + si_code = data.GetU32(&offset); return error; } diff --git a/lldb/test/API/linux/aarch64/mte_core_file/TestAArch64LinuxMTEMemoryTagCoreFile.py b/lldb/test/API/linux/aarch64/mte_core_file/TestAArch64LinuxMTEMemoryTagCoreFile.py --- a/lldb/test/API/linux/aarch64/mte_core_file/TestAArch64LinuxMTEMemoryTagCoreFile.py +++ b/lldb/test/API/linux/aarch64/mte_core_file/TestAArch64LinuxMTEMemoryTagCoreFile.py @@ -166,3 +166,14 @@ # the MTE core file which does support it but does not allow writing tags. self.expect("memory tag write 0 1", substrs=["error: Process does not support memory tagging"], error=True) + + @skipIfLLVMTargetMissing("AArch64") + def test_mte_tag_fault_reason(self): + """ Test that we correctly report the fault reason. """ + self.runCmd("target create --core core.mte") + + # There is no fault address shown here because core files do not include + # si_addr. + self.expect("bt", substrs=[ + "* thread #1, name = 'a.out.mte', stop reason = signal SIGSEGV: " + "sync tag check fault"]) diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst --- a/llvm/docs/ReleaseNotes.rst +++ b/llvm/docs/ReleaseNotes.rst @@ -188,6 +188,10 @@ omit defaulted template parameters. The full template parameter list can still be viewed with `expr --raw-output`/`frame var --raw-output`. (`D141828 `_) +* LLDB will now use the value of the ``siginfo`` ``si_code`` field to report + more specific signal types when debugging an ELF core file. For example + "sync tag check fault", which is a specific type of SIGSEGV. + Changes to Sanitizers ---------------------