Skip to content

Commit

Permalink
[LLDB] Show sub type of signals when debugging a core file
Browse files Browse the repository at this point in the history
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
  • Loading branch information
DavidSpickett committed Mar 21, 2023
1 parent d0de2c5 commit 85bc498
Show file tree
Hide file tree
Showing 7 changed files with 47 additions and 18 deletions.
3 changes: 2 additions & 1 deletion lldb/include/lldb/Target/StopInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,8 @@ class StopInfo : public std::enable_shared_from_this<StopInfo> {

static lldb::StopInfoSP
CreateStopReasonWithSignal(Thread &thread, int signo,
const char *description = nullptr);
const char *description = nullptr,
std::optional<int> code = std::nullopt);

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

Expand Down
1 change: 1 addition & 0 deletions lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -922,6 +922,7 @@ llvm::Error ProcessElfCore::parseLinuxNotes(llvm::ArrayRef<CoreNote> notes) {
if (status.Fail())
return status.ToError();
thread_data.signo = siginfo.si_signo;
thread_data.code = siginfo.si_code;
break;
}
case ELF::NT_FILE: {
Expand Down
16 changes: 9 additions & 7 deletions lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,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_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(); }

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

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
Expand Down Expand Up @@ -409,8 +411,8 @@ Status ELFLinuxSigInfo::Parse(const DataExtractor &data, const ArchSpec &arch) {
// 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;
}
2 changes: 2 additions & 0 deletions lldb/source/Plugins/Process/elf-core/ThreadElfCore.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ struct ThreadData {
std::vector<lldb_private::CoreNote> notes;
lldb::tid_t tid;
int signo = 0;
int code = 0;
int prstatus_sig = 0;
std::string name;
};
Expand Down Expand Up @@ -166,6 +167,7 @@ class ThreadElfCore : public lldb_private::Thread {
lldb::RegisterContextSP m_thread_reg_ctx_sp;

int m_signo;
int m_code;

lldb_private::DataExtractor m_gpregset_data;
std::vector<lldb_private::CoreNote> m_notes;
Expand Down
29 changes: 19 additions & 10 deletions lldb/source/Target/StopInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1044,8 +1044,9 @@ class StopInfoWatchpoint : public StopInfo {

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<int> code)
: StopInfo(thread, signo), m_code(code) {
SetDescription(description);
}

Expand Down Expand Up @@ -1100,19 +1101,26 @@ class StopInfoUnixSignal : public StopInfo {
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<int> m_code;
};

// StopInfoTrace
Expand Down Expand Up @@ -1371,9 +1379,10 @@ StopInfo::CreateStopReasonWithWatchpointID(Thread &thread, break_id_t watch_id,
}

StopInfoSP StopInfo::CreateStopReasonWithSignal(Thread &thread, int signo,
const char *description) {
const char *description,
std::optional<int> 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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,3 +166,14 @@ def test_mte_commands_no_mte(self):
# 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"])
3 changes: 3 additions & 0 deletions llvm/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,9 @@ Changes to LLDB
omit defaulted template parameters. The full template parameter list can still be
viewed with ``expr --raw-output``/``frame var --raw-output``. (`D141828 <https://reviews.llvm.org/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
---------------------

Expand Down

0 comments on commit 85bc498

Please sign in to comment.