Skip to content

Commit 85bc498

Browse files
committed
[LLDB] Show sub type of signals when debugging a core file
Previously we only looked at the si_signo field, so you got: ``` (lldb) bt * thread #1, name = 'a.out.mte', stop reason = signal SIGSEGV * frame #0: 0x00000000004007f4 ``` This patch adds si_code so we can show: ``` (lldb) bt * thread #1, name = 'a.out.mte', stop reason = signal SIGSEGV: sync tag check fault * frame #0: 0x00000000004007f4 ``` The order of errno and code was incorrect in ElfLinuxSigInfo::Parse. It was the order that a "swapped" siginfo arch would use, which for Linux, is only MIPS. We removed MIPS Linux support some time ago. See: https://github.com/torvalds/linux/blob/fe15c26ee26efa11741a7b632e9f23b01aca4cc6/include/uapi/asm-generic/siginfo.h#L121 A test is added using memory tagging faults. Which were the original motivation for the changes. Reviewed By: JDevlieghere Differential Revision: https://reviews.llvm.org/D146045
1 parent d0de2c5 commit 85bc498

File tree

7 files changed

+47
-18
lines changed

7 files changed

+47
-18
lines changed

lldb/include/lldb/Target/StopInfo.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,8 @@ class StopInfo : public std::enable_shared_from_this<StopInfo> {
115115

116116
static lldb::StopInfoSP
117117
CreateStopReasonWithSignal(Thread &thread, int signo,
118-
const char *description = nullptr);
118+
const char *description = nullptr,
119+
std::optional<int> code = std::nullopt);
119120

120121
static lldb::StopInfoSP CreateStopReasonToTrace(Thread &thread);
121122

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -922,6 +922,7 @@ llvm::Error ProcessElfCore::parseLinuxNotes(llvm::ArrayRef<CoreNote> notes) {
922922
if (status.Fail())
923923
return status.ToError();
924924
thread_data.signo = siginfo.si_signo;
925+
thread_data.code = siginfo.si_code;
925926
break;
926927
}
927928
case ELF::NT_FILE: {

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

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ using namespace lldb_private;
4646
// Construct a Thread object with given data
4747
ThreadElfCore::ThreadElfCore(Process &process, const ThreadData &td)
4848
: Thread(process, td.tid), m_thread_name(td.name), m_thread_reg_ctx_sp(),
49-
m_signo(td.signo), m_gpregset_data(td.gpregset), m_notes(td.notes) {}
49+
m_signo(td.signo), m_code(td.code), m_gpregset_data(td.gpregset),
50+
m_notes(td.notes) {}
5051

5152
ThreadElfCore::~ThreadElfCore() { DestroyThread(); }
5253

@@ -221,11 +222,12 @@ ThreadElfCore::CreateRegisterContextForFrame(StackFrame *frame) {
221222

222223
bool ThreadElfCore::CalculateStopInfo() {
223224
ProcessSP process_sp(GetProcess());
224-
if (process_sp) {
225-
SetStopInfo(StopInfo::CreateStopReasonWithSignal(*this, m_signo));
226-
return true;
227-
}
228-
return false;
225+
if (!process_sp)
226+
return false;
227+
228+
SetStopInfo(StopInfo::CreateStopReasonWithSignal(
229+
*this, m_signo, /*description=*/nullptr, m_code));
230+
return true;
229231
}
230232

231233
// Parse PRSTATUS from NOTE entry
@@ -409,8 +411,8 @@ Status ELFLinuxSigInfo::Parse(const DataExtractor &data, const ArchSpec &arch) {
409411
// properly, because the struct is for the 64 bit version
410412
offset_t offset = 0;
411413
si_signo = data.GetU32(&offset);
412-
si_code = data.GetU32(&offset);
413414
si_errno = data.GetU32(&offset);
415+
si_code = data.GetU32(&offset);
414416

415417
return error;
416418
}

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ struct ThreadData {
128128
std::vector<lldb_private::CoreNote> notes;
129129
lldb::tid_t tid;
130130
int signo = 0;
131+
int code = 0;
131132
int prstatus_sig = 0;
132133
std::string name;
133134
};
@@ -166,6 +167,7 @@ class ThreadElfCore : public lldb_private::Thread {
166167
lldb::RegisterContextSP m_thread_reg_ctx_sp;
167168

168169
int m_signo;
170+
int m_code;
169171

170172
lldb_private::DataExtractor m_gpregset_data;
171173
std::vector<lldb_private::CoreNote> m_notes;

lldb/source/Target/StopInfo.cpp

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1044,8 +1044,9 @@ class StopInfoWatchpoint : public StopInfo {
10441044

10451045
class StopInfoUnixSignal : public StopInfo {
10461046
public:
1047-
StopInfoUnixSignal(Thread &thread, int signo, const char *description)
1048-
: StopInfo(thread, signo) {
1047+
StopInfoUnixSignal(Thread &thread, int signo, const char *description,
1048+
std::optional<int> code)
1049+
: StopInfo(thread, signo), m_code(code) {
10491050
SetDescription(description);
10501051
}
10511052

@@ -1100,19 +1101,26 @@ class StopInfoUnixSignal : public StopInfo {
11001101
if (m_description.empty()) {
11011102
ThreadSP thread_sp(m_thread_wp.lock());
11021103
if (thread_sp) {
1104+
UnixSignalsSP unix_signals = thread_sp->GetProcess()->GetUnixSignals();
11031105
StreamString strm;
1104-
const char *signal_name =
1105-
thread_sp->GetProcess()->GetUnixSignals()->GetSignalAsCString(
1106-
m_value);
1107-
if (signal_name)
1108-
strm.Printf("signal %s", signal_name);
1106+
strm << "signal ";
1107+
1108+
std::string signal_name =
1109+
unix_signals->GetSignalDescription(m_value, m_code);
1110+
if (signal_name.size())
1111+
strm << signal_name;
11091112
else
1110-
strm.Printf("signal %" PRIi64, m_value);
1113+
strm.Printf("%" PRIi64, m_value);
1114+
11111115
m_description = std::string(strm.GetString());
11121116
}
11131117
}
11141118
return m_description.c_str();
11151119
}
1120+
1121+
private:
1122+
// In siginfo_t terms, if m_value is si_signo, m_code is si_code.
1123+
std::optional<int> m_code;
11161124
};
11171125

11181126
// StopInfoTrace
@@ -1371,9 +1379,10 @@ StopInfo::CreateStopReasonWithWatchpointID(Thread &thread, break_id_t watch_id,
13711379
}
13721380

13731381
StopInfoSP StopInfo::CreateStopReasonWithSignal(Thread &thread, int signo,
1374-
const char *description) {
1382+
const char *description,
1383+
std::optional<int> code) {
13751384
thread.GetProcess()->GetUnixSignals()->IncrementSignalHitCount(signo);
1376-
return StopInfoSP(new StopInfoUnixSignal(thread, signo, description));
1385+
return StopInfoSP(new StopInfoUnixSignal(thread, signo, description, code));
13771386
}
13781387

13791388
StopInfoSP StopInfo::CreateStopReasonToTrace(Thread &thread) {

lldb/test/API/linux/aarch64/mte_core_file/TestAArch64LinuxMTEMemoryTagCoreFile.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,3 +166,14 @@ def test_mte_commands_no_mte(self):
166166
# the MTE core file which does support it but does not allow writing tags.
167167
self.expect("memory tag write 0 1",
168168
substrs=["error: Process does not support memory tagging"], error=True)
169+
170+
@skipIfLLVMTargetMissing("AArch64")
171+
def test_mte_tag_fault_reason(self):
172+
""" Test that we correctly report the fault reason. """
173+
self.runCmd("target create --core core.mte")
174+
175+
# There is no fault address shown here because core files do not include
176+
# si_addr.
177+
self.expect("bt", substrs=[
178+
"* thread #1, name = 'a.out.mte', stop reason = signal SIGSEGV: "
179+
"sync tag check fault"])

llvm/docs/ReleaseNotes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,9 @@ Changes to LLDB
221221
omit defaulted template parameters. The full template parameter list can still be
222222
viewed with ``expr --raw-output``/``frame var --raw-output``. (`D141828 <https://reviews.llvm.org/D141828>`_)
223223

224+
* LLDB is now able to show the subtype of signals found in a core file. For example
225+
memory tagging specific segfaults such as ``SIGSEGV: sync tag check fault``.
226+
224227
Changes to Sanitizers
225228
---------------------
226229

0 commit comments

Comments
 (0)