Skip to content

Commit ce87c9d

Browse files
committed
Add the addr info when appropriate for NIX' crash signals
1 parent 35684fa commit ce87c9d

File tree

5 files changed

+80
-8
lines changed

5 files changed

+80
-8
lines changed

lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -931,6 +931,7 @@ llvm::Error ProcessElfCore::parseLinuxNotes(llvm::ArrayRef<CoreNote> notes) {
931931
return status.ToError();
932932
thread_data.signo = siginfo.si_signo;
933933
thread_data.code = siginfo.si_code;
934+
thread_data.description = siginfo.GetDescription();
934935
break;
935936
}
936937
case ELF::NT_FILE: {

lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9+
#include "Plugins/Process/POSIX/CrashReason.h"
910
#include "lldb/Target/RegisterContext.h"
1011
#include "lldb/Target/StopInfo.h"
1112
#include "lldb/Target/Target.h"
13+
#include "lldb/Target/UnixSignals.h"
1214
#include "lldb/Target/Unwind.h"
1315
#include "lldb/Utility/DataExtractor.h"
1416
#include "lldb/Utility/LLDBLog.h"
@@ -41,6 +43,7 @@
4143
#include "RegisterContextPOSIXCore_x86_64.h"
4244
#include "ThreadElfCore.h"
4345

46+
#include "bits/types/siginfo_t.h"
4447
#include <memory>
4548

4649
using namespace lldb;
@@ -49,8 +52,8 @@ using namespace lldb_private;
4952
// Construct a Thread object with given data
5053
ThreadElfCore::ThreadElfCore(Process &process, const ThreadData &td)
5154
: Thread(process, td.tid), m_thread_name(td.name), m_thread_reg_ctx_sp(),
52-
m_signo(td.signo), m_code(td.code), m_gpregset_data(td.gpregset),
53-
m_notes(td.notes) {}
55+
m_signo(td.signo), m_code(td.code), m_sig_description(td.description),
56+
m_gpregset_data(td.gpregset), m_notes(td.notes) {}
5457

5558
ThreadElfCore::~ThreadElfCore() { DestroyThread(); }
5659

@@ -241,7 +244,7 @@ bool ThreadElfCore::CalculateStopInfo() {
241244
return false;
242245

243246
SetStopInfo(StopInfo::CreateStopReasonWithSignal(
244-
*this, m_signo, /*description=*/nullptr, m_code));
247+
*this, m_signo, m_sig_description.c_str(), m_code));
245248
return true;
246249
}
247250

@@ -543,7 +546,8 @@ size_t ELFLinuxSigInfo::GetSize(const lldb_private::ArchSpec &arch) {
543546

544547
Status ELFLinuxSigInfo::Parse(const DataExtractor &data, const ArchSpec &arch) {
545548
Status error;
546-
if (GetSize(arch) > data.GetByteSize()) {
549+
uint64_t size = GetSize(arch);
550+
if (size > data.GetByteSize()) {
547551
error = Status::FromErrorStringWithFormat(
548552
"NT_SIGINFO size should be %zu, but the remaining bytes are: %" PRIu64,
549553
GetSize(arch), data.GetByteSize());
@@ -556,6 +560,36 @@ Status ELFLinuxSigInfo::Parse(const DataExtractor &data, const ArchSpec &arch) {
556560
si_signo = data.GetU32(&offset);
557561
si_errno = data.GetU32(&offset);
558562
si_code = data.GetU32(&offset);
563+
// 64b ELF have a 4 byte pad.
564+
if (data.GetAddressByteSize() == 8)
565+
offset += 4;
566+
switch (si_signo) {
567+
case SIGFPE:
568+
case SIGILL:
569+
case SIGSEGV:
570+
case SIGBUS:
571+
case SIGTRAP:
572+
addr = (void*)data.GetAddress(&offset);
573+
addr_lsb = data.GetU16(&offset);
574+
return error;
575+
default:
576+
return error;
577+
}
578+
}
559579

560-
return error;
580+
std::string ELFLinuxSigInfo::GetDescription() {
581+
switch (si_signo) {
582+
case SIGFPE:
583+
case SIGILL:
584+
case SIGSEGV:
585+
case SIGBUS:
586+
case SIGTRAP:
587+
return lldb_private::UnixSignals::CreateForHost()->GetSignalDescription(
588+
si_signo, si_code,
589+
reinterpret_cast<uintptr_t>(addr));
590+
default:
591+
return lldb_private::UnixSignals::CreateForHost()->GetSignalDescription(
592+
si_signo, si_code
593+
);
594+
}
561595
}

lldb/source/Plugins/Process/elf-core/ThreadElfCore.h

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,16 +75,25 @@ struct ELFLinuxPrStatus {
7575
static_assert(sizeof(ELFLinuxPrStatus) == 112,
7676
"sizeof ELFLinuxPrStatus is not correct!");
7777

78+
union ELFSigval {
79+
int sival_int;
80+
void *sival_ptr;
81+
};
82+
7883
struct ELFLinuxSigInfo {
79-
int32_t si_signo;
80-
int32_t si_code;
84+
int32_t si_signo; // Order matters for the first 3.
8185
int32_t si_errno;
86+
int32_t si_code;
87+
void *addr; /* faulting insn/memory ref. */
88+
int32_t addr_lsb; /* Valid LSB of the reported address. */
8289

8390
ELFLinuxSigInfo();
8491

8592
lldb_private::Status Parse(const lldb_private::DataExtractor &data,
8693
const lldb_private::ArchSpec &arch);
8794

95+
std::string GetDescription();
96+
8897
// Return the bytesize of the structure
8998
// 64 bit - just sizeof
9099
// 32 bit - hardcoded because we are reusing the struct, but some of the
@@ -93,7 +102,7 @@ struct ELFLinuxSigInfo {
93102
static size_t GetSize(const lldb_private::ArchSpec &arch);
94103
};
95104

96-
static_assert(sizeof(ELFLinuxSigInfo) == 12,
105+
static_assert(sizeof(ELFLinuxSigInfo) == 32,
97106
"sizeof ELFLinuxSigInfo is not correct!");
98107

99108
// PRPSINFO structure's size differs based on architecture.
@@ -144,7 +153,9 @@ struct ThreadData {
144153
lldb::tid_t tid;
145154
int signo = 0;
146155
int code = 0;
156+
void* sigaddr = nullptr;
147157
int prstatus_sig = 0;
158+
std::string description;
148159
std::string name;
149160
};
150161

@@ -183,6 +194,7 @@ class ThreadElfCore : public lldb_private::Thread {
183194

184195
int m_signo;
185196
int m_code;
197+
std::string m_sig_description;
186198

187199
lldb_private::DataExtractor m_gpregset_data;
188200
std::vector<lldb_private::CoreNote> m_notes;

lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from lldbsuite.test.decorators import *
1111
from lldbsuite.test.lldbtest import *
1212
from lldbsuite.test import lldbutil
13+
from fblldb import fbvscode
1314

1415

1516
class LinuxCoreTestCase(TestBase):
@@ -833,6 +834,22 @@ def test_riscv64_regs_gpr_only(self):
833834
substrs=["registers were unavailable"],
834835
)
835836

837+
def test_sigsev_stopreason(self):
838+
"""
839+
Test that the address is included in the stop reason for a SIGSEV
840+
"""
841+
src = self.getSourcePath("linux-x64-sigsev.yaml")
842+
obj_file = self.getBuildArtifact("sigsev.out")
843+
fbvscode.set_trace()
844+
self.yaml2obj(src, obj_file)
845+
target = self.dbg.CreateTarget(None)
846+
process = target.LoadCore(obj_file)
847+
self.assertTrue(process, PROCESS_IS_VALID)
848+
stop_reason = process.GetThreadAtIndex(0).GetStopDescription(128)
849+
self.assertEqual(process.GetNumThreads(), 1)
850+
self.assertIn("SIGSEGV: address not mapped to object (fault address: 0x1000)", stop_reason)
851+
852+
836853
def test_get_core_file_api(self):
837854
"""
838855
Test SBProcess::GetCoreFile() API can successfully get the core file.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
--- !ELF
2+
FileHeader:
3+
Class: ELFCLASS64
4+
Data: ELFDATA2LSB
5+
OSABI: ELFOSABI_FREEBSD
6+
Type: ET_EXEC
7+
Machine: EM_X86_64
8+
Entry: 0xFFFFFFFF8037C000

0 commit comments

Comments
 (0)