diff --git a/lldb/include/lldb/Target/StopInfo.h b/lldb/include/lldb/Target/StopInfo.h --- a/lldb/include/lldb/Target/StopInfo.h +++ b/lldb/include/lldb/Target/StopInfo.h @@ -115,7 +115,8 @@ static lldb::StopInfoSP CreateStopReasonWithSignal(Thread &thread, int signo, - const char *description = nullptr); + const char *description = nullptr, + std::optional code = std::nullopt); static lldb::StopInfoSP CreateStopReasonToTrace(Thread &thread); 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 @@ -922,6 +922,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 @@ -46,7 +46,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 +222,12 @@ bool ThreadElfCore::CalculateStopInfo() { ProcessSP process_sp(GetProcess()); - if (process_sp) { - SetStopInfo(StopInfo::CreateStopReasonWithSignal(*this, m_signo)); - return true; - } - return false; + if (!process_sp) + return false; + + SetStopInfo(StopInfo::CreateStopReasonWithSignal( + *this, m_signo, /*description=*/nullptr, m_code)); + return true; } // Parse PRSTATUS from NOTE entry @@ -409,8 +411,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/source/Target/StopInfo.cpp b/lldb/source/Target/StopInfo.cpp --- a/lldb/source/Target/StopInfo.cpp +++ b/lldb/source/Target/StopInfo.cpp @@ -1044,8 +1044,9 @@ class StopInfoUnixSignal : public StopInfo { public: - StopInfoUnixSignal(Thread &thread, int signo, const char *description) - : StopInfo(thread, signo) { + StopInfoUnixSignal(Thread &thread, int signo, const char *description, + std::optional code) + : StopInfo(thread, signo), m_code(code) { SetDescription(description); } @@ -1100,19 +1101,26 @@ if (m_description.empty()) { ThreadSP thread_sp(m_thread_wp.lock()); if (thread_sp) { + UnixSignalsSP unix_signals = thread_sp->GetProcess()->GetUnixSignals(); StreamString strm; - const char *signal_name = - thread_sp->GetProcess()->GetUnixSignals()->GetSignalAsCString( - m_value); - if (signal_name) - strm.Printf("signal %s", signal_name); + strm << "signal "; + + std::string signal_name = + unix_signals->GetSignalDescription(m_value, m_code); + if (signal_name.size()) + strm << signal_name; else - strm.Printf("signal %" PRIi64, m_value); + strm.Printf("%" PRIi64, m_value); + m_description = std::string(strm.GetString()); } } return m_description.c_str(); } + +private: + // In siginfo_t terms, if m_value is si_signo, m_code is si_code. + std::optional m_code; }; // StopInfoTrace @@ -1371,9 +1379,10 @@ } StopInfoSP StopInfo::CreateStopReasonWithSignal(Thread &thread, int signo, - const char *description) { + const char *description, + std::optional code) { thread.GetProcess()->GetUnixSignals()->IncrementSignalHitCount(signo); - return StopInfoSP(new StopInfoUnixSignal(thread, signo, description)); + return StopInfoSP(new StopInfoUnixSignal(thread, signo, description, code)); } StopInfoSP StopInfo::CreateStopReasonToTrace(Thread &thread) { 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 @@ -221,6 +221,9 @@ omit defaulted template parameters. The full template parameter list can still be viewed with ``expr --raw-output``/``frame var --raw-output``. (`D141828 `_) +* LLDB is now able to show the subtype of signals found in a core file. For example + memory tagging specific segfaults such as ``SIGSEGV: sync tag check fault``. + Changes to Sanitizers ---------------------