DavidSpickett updated this revision to Diff 503274.
DavidSpickett added a comment.

Add code functionality to UnixSignals instead.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D145377/new/

https://reviews.llvm.org/D145377

Files:
  lldb/include/lldb/Target/StopInfo.h
  lldb/include/lldb/Target/UnixSignals.h
  lldb/source/Plugins/Process/Utility/LinuxSignals.cpp
  lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
  lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp
  lldb/source/Plugins/Process/elf-core/ThreadElfCore.h
  lldb/source/Target/StopInfo.cpp
  lldb/source/Target/UnixSignals.cpp
  
lldb/test/API/linux/aarch64/mte_core_file/TestAArch64LinuxMTEMemoryTagCoreFile.py
  lldb/unittests/Signals/UnixSignalsTest.cpp
  llvm/docs/ReleaseNotes.rst

Index: llvm/docs/ReleaseNotes.rst
===================================================================
--- llvm/docs/ReleaseNotes.rst
+++ llvm/docs/ReleaseNotes.rst
@@ -188,6 +188,9 @@
   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>`_)
 
+* When debugging a Linux core file containing a segfault related to memory tagging,
+  LLDB now reports the specific type of that fault. For example ``SIGSEGV: sync tag check fault``.
+
 Changes to Sanitizers
 ---------------------
 
Index: lldb/unittests/Signals/UnixSignalsTest.cpp
===================================================================
--- lldb/unittests/Signals/UnixSignalsTest.cpp
+++ lldb/unittests/Signals/UnixSignalsTest.cpp
@@ -23,6 +23,7 @@
     AddSignal(4, "SIG4", true, false, true, "DESC4");
     AddSignal(8, "SIG8", true, true, true, "DESC8");
     AddSignal(16, "SIG16", true, false, false, "DESC16");
+    AddSignalCode(16, 1, "a specific type of SIG16");
   }
 };
 
@@ -93,6 +94,25 @@
   EXPECT_EQ(name, signals.GetSignalAsCString(signo));
 }
 
+TEST(UnixSignalsTest, GetAsCString) {
+  TestSignals signals;
+
+  EXPECT_EQ(nullptr, signals.GetSignalAsCString(100));
+  std::string name = signals.GetSignalAsCString(16);
+  EXPECT_EQ("SIG16", name);
+}
+
+TEST(UnixSignalsTest, GetAsString) {
+  TestSignals signals;
+
+  EXPECT_EQ("", signals.GetSignalAsString(100, std::nullopt));
+  EXPECT_EQ("SIG16", signals.GetSignalAsString(16, std::nullopt));
+  EXPECT_EQ("", signals.GetSignalAsString(100, 100));
+  EXPECT_EQ("SIG16", signals.GetSignalAsString(16, 100));
+  EXPECT_EQ("SIG16: a specific type of SIG16",
+            signals.GetSignalAsString(16, 1));
+}
+
 TEST(UnixSignalsTest, VersionChange) {
   TestSignals signals;
 
Index: lldb/test/API/linux/aarch64/mte_core_file/TestAArch64LinuxMTEMemoryTagCoreFile.py
===================================================================
--- lldb/test/API/linux/aarch64/mte_core_file/TestAArch64LinuxMTEMemoryTagCoreFile.py
+++ lldb/test/API/linux/aarch64/mte_core_file/TestAArch64LinuxMTEMemoryTagCoreFile.py
@@ -166,3 +166,14 @@
         # 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"])
Index: lldb/source/Target/UnixSignals.cpp
===================================================================
--- lldb/source/Target/UnixSignals.cpp
+++ lldb/source/Target/UnixSignals.cpp
@@ -122,6 +122,14 @@
   ++m_version;
 }
 
+void UnixSignals::AddSignalCode(int signo, int code, const char *description) {
+  collection::iterator signal = m_signals.find(signo);
+  if (signal == m_signals.end())
+    return;
+  signal->second.m_codes.insert(std::pair{code, description});
+  ++m_version;
+}
+
 void UnixSignals::RemoveSignal(int signo) {
   collection::iterator pos = m_signals.find(signo);
   if (pos != m_signals.end())
@@ -137,6 +145,27 @@
     return pos->second.m_name.GetCString();
 }
 
+std::string UnixSignals::GetSignalAsString(int32_t signo,
+                                           std::optional<int32_t> code) const {
+  std::string str;
+
+  collection::const_iterator pos = m_signals.find(signo);
+  if (pos != m_signals.end()) {
+    str = pos->second.m_name.GetCString();
+
+    if (code) {
+      std::map<int, ConstString>::const_iterator cpos =
+          pos->second.m_codes.find(*code);
+      if (cpos != pos->second.m_codes.end()) {
+        str += ": ";
+        str += cpos->second.GetCString();
+      }
+    }
+  }
+
+  return str;
+}
+
 bool UnixSignals::SignalIsValid(int32_t signo) const {
   return m_signals.find(signo) != m_signals.end();
 }
Index: lldb/source/Target/StopInfo.cpp
===================================================================
--- lldb/source/Target/StopInfo.cpp
+++ lldb/source/Target/StopInfo.cpp
@@ -1039,8 +1039,9 @@
 
 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);
   }
 
@@ -1095,19 +1096,26 @@
     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->GetSignalAsString(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
@@ -1366,9 +1374,10 @@
 }
 
 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) {
Index: lldb/source/Plugins/Process/elf-core/ThreadElfCore.h
===================================================================
--- lldb/source/Plugins/Process/elf-core/ThreadElfCore.h
+++ lldb/source/Plugins/Process/elf-core/ThreadElfCore.h
@@ -128,6 +128,7 @@
   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 @@
   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;
Index: lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp
===================================================================
--- lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp
+++ lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp
@@ -46,7 +46,8 @@
 // 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 @@
 
 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 @@
   // 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;
 }
Index: lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
===================================================================
--- lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
+++ lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
@@ -920,6 +920,7 @@
       if (status.Fail())
         return status.ToError();
       thread_data.signo = siginfo.si_signo;
+      thread_data.code = siginfo.si_code;
       break;
     }
     case ELF::NT_FILE: {
Index: lldb/source/Plugins/Process/Utility/LinuxSignals.cpp
===================================================================
--- lldb/source/Plugins/Process/Utility/LinuxSignals.cpp
+++ lldb/source/Plugins/Process/Utility/LinuxSignals.cpp
@@ -28,6 +28,8 @@
   AddSignal(9,      "SIGKILL",      false,    true,   true,   "kill");
   AddSignal(10,     "SIGUSR1",      false,    true,   true,   "user defined signal 1");
   AddSignal(11,     "SIGSEGV",      false,    true,   true,   "segmentation violation");
+  AddSignalCode(11, 8 /*SEGV_MTEAERR*/, "async tag check fault");
+  AddSignalCode(11, 9 /*SEGV_MTESERR*/, "sync tag check fault");
   AddSignal(12,     "SIGUSR2",      false,    true,   true,   "user defined signal 2");
   AddSignal(13,     "SIGPIPE",      false,    true,   true,   "write to pipe with reading end closed");
   AddSignal(14,     "SIGALRM",      false,    false,  false,  "alarm");
Index: lldb/include/lldb/Target/UnixSignals.h
===================================================================
--- lldb/include/lldb/Target/UnixSignals.h
+++ lldb/include/lldb/Target/UnixSignals.h
@@ -32,6 +32,9 @@
 
   const char *GetSignalAsCString(int32_t signo) const;
 
+  std::string GetSignalAsString(int32_t signo,
+                                std::optional<int32_t> code) const;
+
   bool SignalIsValid(int32_t signo) const;
 
   int32_t GetSignalNumberFromName(const char *name) const;
@@ -82,6 +85,8 @@
                  bool default_stop, bool default_notify,
                  const char *description, const char *alias = nullptr);
 
+  void AddSignalCode(int signo, int code, const char *description);
+
   void RemoveSignal(int signo);
 
   /// Track how many times signals are hit as stop reasons.
@@ -115,6 +120,7 @@
     ConstString m_name;
     ConstString m_alias;
     std::string m_description;
+    std::map<int32_t, ConstString> m_codes;
     uint32_t m_hit_count = 0;
     bool m_suppress : 1, m_stop : 1, m_notify : 1;
     bool m_default_suppress : 1, m_default_stop : 1, m_default_notify : 1;
Index: lldb/include/lldb/Target/StopInfo.h
===================================================================
--- lldb/include/lldb/Target/StopInfo.h
+++ lldb/include/lldb/Target/StopInfo.h
@@ -115,7 +115,8 @@
 
   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);
 
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to