[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:
fe15c26ee2/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
This commit is contained in:
parent
d0de2c51c9
commit
85bc498826
|
@ -115,7 +115,8 @@ public:
|
|||
|
||||
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);
|
||||
|
||||
|
|
|
@ -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: {
|
||||
|
|
|
@ -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(); }
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
@ -166,6 +167,7 @@ protected:
|
|||
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;
|
||||
|
|
|
@ -1044,8 +1044,9 @@ private:
|
|||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -1100,19 +1101,26 @@ public:
|
|||
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
|
||||
|
@ -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) {
|
||||
|
|
|
@ -166,3 +166,14 @@ class AArch64LinuxMTEMemoryTagCoreFileTestCase(TestBase):
|
|||
# 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"])
|
||||
|
|
|
@ -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
|
||||
---------------------
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user