https://github.com/Jlalond created https://github.com/llvm/llvm-project/pull/110065
This fixes a functionality gap with GDB, where GDB will properly decode the stop reason and give the address for SIGSEGV. I also added descriptions to all stop reasons, following the same code path that the Native Linux Thread uses. >From 0e31c0ad2b9db1ba9055bb4b984557100c0a9feb Mon Sep 17 00:00:00 2001 From: Jacob Lalonde <jalalo...@fb.com> Date: Tue, 24 Sep 2024 17:42:49 -0700 Subject: [PATCH 1/3] Add the addr info when appropriate for NIX' crash signals --- .../Process/elf-core/ProcessElfCore.cpp | 1 + .../Process/elf-core/ThreadElfCore.cpp | 44 ++++++++++++++++--- .../Plugins/Process/elf-core/ThreadElfCore.h | 18 ++++++-- .../postmortem/elf-core/TestLinuxCore.py | 17 +++++++ .../elf-core/linux-x86_64-sigsev.yaml | 8 ++++ 5 files changed, 80 insertions(+), 8 deletions(-) create mode 100644 lldb/test/API/functionalities/postmortem/elf-core/linux-x86_64-sigsev.yaml diff --git a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp index 7955594bf5d94c..468a3b8934e741 100644 --- a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp +++ b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp @@ -931,6 +931,7 @@ llvm::Error ProcessElfCore::parseLinuxNotes(llvm::ArrayRef<CoreNote> notes) { return status.ToError(); thread_data.signo = siginfo.si_signo; thread_data.code = siginfo.si_code; + thread_data.description = siginfo.GetDescription(); break; } case ELF::NT_FILE: { diff --git a/lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp b/lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp index 52b96052bdbeca..3260caabd70ac6 100644 --- a/lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp +++ b/lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp @@ -6,9 +6,11 @@ // //===----------------------------------------------------------------------===// +#include "Plugins/Process/POSIX/CrashReason.h" #include "lldb/Target/RegisterContext.h" #include "lldb/Target/StopInfo.h" #include "lldb/Target/Target.h" +#include "lldb/Target/UnixSignals.h" #include "lldb/Target/Unwind.h" #include "lldb/Utility/DataExtractor.h" #include "lldb/Utility/LLDBLog.h" @@ -41,6 +43,7 @@ #include "RegisterContextPOSIXCore_x86_64.h" #include "ThreadElfCore.h" +#include "bits/types/siginfo_t.h" #include <memory> using namespace lldb; @@ -49,8 +52,8 @@ using namespace lldb_private; // 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_code(td.code), m_gpregset_data(td.gpregset), - m_notes(td.notes) {} + m_signo(td.signo), m_code(td.code), m_sig_description(td.description), + m_gpregset_data(td.gpregset), m_notes(td.notes) {} ThreadElfCore::~ThreadElfCore() { DestroyThread(); } @@ -241,7 +244,7 @@ bool ThreadElfCore::CalculateStopInfo() { return false; SetStopInfo(StopInfo::CreateStopReasonWithSignal( - *this, m_signo, /*description=*/nullptr, m_code)); + *this, m_signo, m_sig_description.c_str(), m_code)); return true; } @@ -543,7 +546,8 @@ size_t ELFLinuxSigInfo::GetSize(const lldb_private::ArchSpec &arch) { Status ELFLinuxSigInfo::Parse(const DataExtractor &data, const ArchSpec &arch) { Status error; - if (GetSize(arch) > data.GetByteSize()) { + uint64_t size = GetSize(arch); + if (size > data.GetByteSize()) { error = Status::FromErrorStringWithFormat( "NT_SIGINFO size should be %zu, but the remaining bytes are: %" PRIu64, GetSize(arch), data.GetByteSize()); @@ -556,6 +560,36 @@ Status ELFLinuxSigInfo::Parse(const DataExtractor &data, const ArchSpec &arch) { si_signo = data.GetU32(&offset); si_errno = data.GetU32(&offset); si_code = data.GetU32(&offset); + // 64b ELF have a 4 byte pad. + if (data.GetAddressByteSize() == 8) + offset += 4; + switch (si_signo) { + case SIGFPE: + case SIGILL: + case SIGSEGV: + case SIGBUS: + case SIGTRAP: + addr = (void*)data.GetAddress(&offset); + addr_lsb = data.GetU16(&offset); + return error; + default: + return error; + } +} - return error; +std::string ELFLinuxSigInfo::GetDescription() { + switch (si_signo) { + case SIGFPE: + case SIGILL: + case SIGSEGV: + case SIGBUS: + case SIGTRAP: + return lldb_private::UnixSignals::CreateForHost()->GetSignalDescription( + si_signo, si_code, + reinterpret_cast<uintptr_t>(addr)); + default: + return lldb_private::UnixSignals::CreateForHost()->GetSignalDescription( + si_signo, si_code + ); + } } diff --git a/lldb/source/Plugins/Process/elf-core/ThreadElfCore.h b/lldb/source/Plugins/Process/elf-core/ThreadElfCore.h index 3fa0b8b0eedb0b..0dc21a10ded5e5 100644 --- a/lldb/source/Plugins/Process/elf-core/ThreadElfCore.h +++ b/lldb/source/Plugins/Process/elf-core/ThreadElfCore.h @@ -75,16 +75,25 @@ struct ELFLinuxPrStatus { static_assert(sizeof(ELFLinuxPrStatus) == 112, "sizeof ELFLinuxPrStatus is not correct!"); +union ELFSigval { + int sival_int; + void *sival_ptr; +}; + struct ELFLinuxSigInfo { - int32_t si_signo; - int32_t si_code; + int32_t si_signo; // Order matters for the first 3. int32_t si_errno; + int32_t si_code; + void *addr; /* faulting insn/memory ref. */ + int32_t addr_lsb; /* Valid LSB of the reported address. */ ELFLinuxSigInfo(); lldb_private::Status Parse(const lldb_private::DataExtractor &data, const lldb_private::ArchSpec &arch); + std::string GetDescription(); + // Return the bytesize of the structure // 64 bit - just sizeof // 32 bit - hardcoded because we are reusing the struct, but some of the @@ -93,7 +102,7 @@ struct ELFLinuxSigInfo { static size_t GetSize(const lldb_private::ArchSpec &arch); }; -static_assert(sizeof(ELFLinuxSigInfo) == 12, +static_assert(sizeof(ELFLinuxSigInfo) == 32, "sizeof ELFLinuxSigInfo is not correct!"); // PRPSINFO structure's size differs based on architecture. @@ -144,7 +153,9 @@ struct ThreadData { lldb::tid_t tid; int signo = 0; int code = 0; + void* sigaddr = nullptr; int prstatus_sig = 0; + std::string description; std::string name; }; @@ -183,6 +194,7 @@ class ThreadElfCore : public lldb_private::Thread { int m_signo; int m_code; + std::string m_sig_description; lldb_private::DataExtractor m_gpregset_data; std::vector<lldb_private::CoreNote> m_notes; diff --git a/lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py b/lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py index 7e8531c88bf34c..1f0dee1e86b682 100644 --- a/lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py +++ b/lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py @@ -10,6 +10,7 @@ from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * from lldbsuite.test import lldbutil +from fblldb import fbvscode class LinuxCoreTestCase(TestBase): @@ -833,6 +834,22 @@ def test_riscv64_regs_gpr_only(self): substrs=["registers were unavailable"], ) + def test_sigsev_stopreason(self): + """ + Test that the address is included in the stop reason for a SIGSEV + """ + src = self.getSourcePath("linux-x64-sigsev.yaml") + obj_file = self.getBuildArtifact("sigsev.out") + fbvscode.set_trace() + self.yaml2obj(src, obj_file) + target = self.dbg.CreateTarget(None) + process = target.LoadCore(obj_file) + self.assertTrue(process, PROCESS_IS_VALID) + stop_reason = process.GetThreadAtIndex(0).GetStopDescription(128) + self.assertEqual(process.GetNumThreads(), 1) + self.assertIn("SIGSEGV: address not mapped to object (fault address: 0x1000)", stop_reason) + + def test_get_core_file_api(self): """ Test SBProcess::GetCoreFile() API can successfully get the core file. diff --git a/lldb/test/API/functionalities/postmortem/elf-core/linux-x86_64-sigsev.yaml b/lldb/test/API/functionalities/postmortem/elf-core/linux-x86_64-sigsev.yaml new file mode 100644 index 00000000000000..2adf30a36918a2 --- /dev/null +++ b/lldb/test/API/functionalities/postmortem/elf-core/linux-x86_64-sigsev.yaml @@ -0,0 +1,8 @@ +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + OSABI: ELFOSABI_FREEBSD + Type: ET_EXEC + Machine: EM_X86_64 + Entry: 0xFFFFFFFF8037C000 >From 0bc394ca58248b595a832dd1567b1389d3e07824 Mon Sep 17 00:00:00 2001 From: Jacob Lalonde <jalalo...@fb.com> Date: Wed, 25 Sep 2024 17:41:57 -0700 Subject: [PATCH 2/3] Drop test as we can't yamilize the pt_note content --- .../postmortem/elf-core/TestLinuxCore.py | 17 ----------------- .../elf-core/linux-x86_64-sigsev.yaml | 8 -------- 2 files changed, 25 deletions(-) delete mode 100644 lldb/test/API/functionalities/postmortem/elf-core/linux-x86_64-sigsev.yaml diff --git a/lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py b/lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py index 1f0dee1e86b682..7e8531c88bf34c 100644 --- a/lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py +++ b/lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py @@ -10,7 +10,6 @@ from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * from lldbsuite.test import lldbutil -from fblldb import fbvscode class LinuxCoreTestCase(TestBase): @@ -834,22 +833,6 @@ def test_riscv64_regs_gpr_only(self): substrs=["registers were unavailable"], ) - def test_sigsev_stopreason(self): - """ - Test that the address is included in the stop reason for a SIGSEV - """ - src = self.getSourcePath("linux-x64-sigsev.yaml") - obj_file = self.getBuildArtifact("sigsev.out") - fbvscode.set_trace() - self.yaml2obj(src, obj_file) - target = self.dbg.CreateTarget(None) - process = target.LoadCore(obj_file) - self.assertTrue(process, PROCESS_IS_VALID) - stop_reason = process.GetThreadAtIndex(0).GetStopDescription(128) - self.assertEqual(process.GetNumThreads(), 1) - self.assertIn("SIGSEGV: address not mapped to object (fault address: 0x1000)", stop_reason) - - def test_get_core_file_api(self): """ Test SBProcess::GetCoreFile() API can successfully get the core file. diff --git a/lldb/test/API/functionalities/postmortem/elf-core/linux-x86_64-sigsev.yaml b/lldb/test/API/functionalities/postmortem/elf-core/linux-x86_64-sigsev.yaml deleted file mode 100644 index 2adf30a36918a2..00000000000000 --- a/lldb/test/API/functionalities/postmortem/elf-core/linux-x86_64-sigsev.yaml +++ /dev/null @@ -1,8 +0,0 @@ ---- !ELF -FileHeader: - Class: ELFCLASS64 - Data: ELFDATA2LSB - OSABI: ELFOSABI_FREEBSD - Type: ET_EXEC - Machine: EM_X86_64 - Entry: 0xFFFFFFFF8037C000 >From 8f6eab35a41fb91b75f9046cec8f7d0773be9001 Mon Sep 17 00:00:00 2001 From: Jacob Lalonde <jalalo...@fb.com> Date: Wed, 25 Sep 2024 17:42:38 -0700 Subject: [PATCH 3/3] Run GCF --- .../Process/elf-core/ThreadElfCore.cpp | 44 +++++++++---------- .../Plugins/Process/elf-core/ThreadElfCore.h | 10 ++--- 2 files changed, 25 insertions(+), 29 deletions(-) diff --git a/lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp b/lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp index 3260caabd70ac6..e9ae5211c28a53 100644 --- a/lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp +++ b/lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp @@ -6,7 +6,6 @@ // //===----------------------------------------------------------------------===// -#include "Plugins/Process/POSIX/CrashReason.h" #include "lldb/Target/RegisterContext.h" #include "lldb/Target/StopInfo.h" #include "lldb/Target/Target.h" @@ -43,7 +42,6 @@ #include "RegisterContextPOSIXCore_x86_64.h" #include "ThreadElfCore.h" -#include "bits/types/siginfo_t.h" #include <memory> using namespace lldb; @@ -564,32 +562,30 @@ Status ELFLinuxSigInfo::Parse(const DataExtractor &data, const ArchSpec &arch) { if (data.GetAddressByteSize() == 8) offset += 4; switch (si_signo) { - case SIGFPE: - case SIGILL: - case SIGSEGV: - case SIGBUS: - case SIGTRAP: - addr = (void*)data.GetAddress(&offset); - addr_lsb = data.GetU16(&offset); - return error; - default: - return error; + case SIGFPE: + case SIGILL: + case SIGSEGV: + case SIGBUS: + case SIGTRAP: + addr = (void *)data.GetAddress(&offset); + addr_lsb = data.GetU16(&offset); + return error; + default: + return error; } } std::string ELFLinuxSigInfo::GetDescription() { switch (si_signo) { - case SIGFPE: - case SIGILL: - case SIGSEGV: - case SIGBUS: - case SIGTRAP: - return lldb_private::UnixSignals::CreateForHost()->GetSignalDescription( - si_signo, si_code, - reinterpret_cast<uintptr_t>(addr)); - default: - return lldb_private::UnixSignals::CreateForHost()->GetSignalDescription( - si_signo, si_code - ); + case SIGFPE: + case SIGILL: + case SIGSEGV: + case SIGBUS: + case SIGTRAP: + return lldb_private::UnixSignals::CreateForHost()->GetSignalDescription( + si_signo, si_code, reinterpret_cast<uintptr_t>(addr)); + default: + return lldb_private::UnixSignals::CreateForHost()->GetSignalDescription( + si_signo, si_code); } } diff --git a/lldb/source/Plugins/Process/elf-core/ThreadElfCore.h b/lldb/source/Plugins/Process/elf-core/ThreadElfCore.h index 0dc21a10ded5e5..3c6c02f73efae8 100644 --- a/lldb/source/Plugins/Process/elf-core/ThreadElfCore.h +++ b/lldb/source/Plugins/Process/elf-core/ThreadElfCore.h @@ -75,16 +75,16 @@ struct ELFLinuxPrStatus { static_assert(sizeof(ELFLinuxPrStatus) == 112, "sizeof ELFLinuxPrStatus is not correct!"); -union ELFSigval { - int sival_int; - void *sival_ptr; +union ELFSigval { + int sival_int; + void *sival_ptr; }; struct ELFLinuxSigInfo { int32_t si_signo; // Order matters for the first 3. int32_t si_errno; int32_t si_code; - void *addr; /* faulting insn/memory ref. */ + void *addr; /* faulting insn/memory ref. */ int32_t addr_lsb; /* Valid LSB of the reported address. */ ELFLinuxSigInfo(); @@ -153,7 +153,7 @@ struct ThreadData { lldb::tid_t tid; int signo = 0; int code = 0; - void* sigaddr = nullptr; + void *sigaddr = nullptr; int prstatus_sig = 0; std::string description; std::string name; _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits