hhellyer updated this revision to Diff 78163.
hhellyer added a comment.

Update with fixes from review comments.
I've run clang-format, fixed the use of iterators and added const qualifiers.
I removed the use of the SIGSTOP constant and use GetUnixSignals instead.
I've also moved that block down a few lines until after SetUnixSignals has been 
called.

I will update the patch with the test cases shortly.


https://reviews.llvm.org/D26676

Files:
  source/Plugins/Process/elf-core/ProcessElfCore.cpp
  source/Plugins/Process/elf-core/ThreadElfCore.cpp
  source/Plugins/Process/elf-core/ThreadElfCore.h

Index: source/Plugins/Process/elf-core/ThreadElfCore.h
===================================================================
--- source/Plugins/Process/elf-core/ThreadElfCore.h
+++ source/Plugins/Process/elf-core/ThreadElfCore.h
@@ -82,6 +82,38 @@
 static_assert(sizeof(ELFLinuxPrStatus) == 112,
               "sizeof ELFLinuxPrStatus is not correct!");
 
+struct ELFLinuxSigInfo {
+  int32_t si_signo;
+  int32_t si_code;
+  int32_t si_errno;
+
+  ELFLinuxSigInfo();
+
+  lldb_private::Error Parse(lldb_private::DataExtractor &data,
+                            const lldb_private::ArchSpec &arch);
+
+  // Return the bytesize of the structure
+  // 64 bit - just sizeof
+  // 32 bit - hardcoded because we are reusing the struct, but some of the
+  // members are smaller -
+  // so the layout is not the same
+  static size_t GetSize(const lldb_private::ArchSpec &arch) {
+    switch (arch.GetCore()) {
+    case lldb_private::ArchSpec::eCore_x86_64_x86_64:
+      return sizeof(ELFLinuxSigInfo);
+    case lldb_private::ArchSpec::eCore_s390x_generic:
+    case lldb_private::ArchSpec::eCore_x86_32_i386:
+    case lldb_private::ArchSpec::eCore_x86_32_i486:
+      return 12;
+    default:
+      return 0;
+    }
+  }
+};
+
+static_assert(sizeof(ELFLinuxSigInfo) == 12,
+              "sizeof ELFLinuxSigInfo is not correct!");
+
 // PRPSINFO structure's size differs based on architecture.
 // This is the layout in the x86-64 arch case.
 // In the i386 case we parse it manually and fill it again
@@ -133,7 +165,8 @@
   lldb_private::DataExtractor fpregset;
   lldb_private::DataExtractor vregset;
   lldb::tid_t tid;
-  int signo;
+  int signo = 0;
+  int prstatus_sig = 0;
   std::string name;
 };
 
Index: source/Plugins/Process/elf-core/ThreadElfCore.cpp
===================================================================
--- source/Plugins/Process/elf-core/ThreadElfCore.cpp
+++ source/Plugins/Process/elf-core/ThreadElfCore.cpp
@@ -320,3 +320,45 @@
 
   return error;
 }
+
+//----------------------------------------------------------------
+// Parse SIGINFO from NOTE entry
+//----------------------------------------------------------------
+ELFLinuxSigInfo::ELFLinuxSigInfo() {
+  memset(this, 0, sizeof(ELFLinuxSigInfo));
+}
+
+Error ELFLinuxSigInfo::Parse(DataExtractor &data, const ArchSpec &arch) {
+  Error error;
+  ByteOrder byteorder = data.GetByteOrder();
+  if (GetSize(arch) > data.GetByteSize()) {
+    error.SetErrorStringWithFormat(
+        "NT_SIGINFO size should be %zu, but the remaining bytes are: %" PRIu64,
+        GetSize(arch), data.GetByteSize());
+    return error;
+  }
+
+  switch (arch.GetCore()) {
+  case ArchSpec::eCore_x86_64_x86_64:
+    data.ExtractBytes(0, sizeof(ELFLinuxPrStatus), byteorder, this);
+    break;
+  case ArchSpec::eCore_s390x_generic:
+  case ArchSpec::eCore_x86_32_i386:
+  case ArchSpec::eCore_x86_32_i486: {
+    // Parsing from a 32 bit ELF core file, and populating/reusing the structure
+    // 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);
+
+    break;
+  }
+  default:
+    error.SetErrorStringWithFormat("ELFLinuxSigInfo::%s Unknown architecture",
+                                   __FUNCTION__);
+    break;
+  }
+
+  return error;
+}
Index: source/Plugins/Process/elf-core/ProcessElfCore.cpp
===================================================================
--- source/Plugins/Process/elf-core/ProcessElfCore.cpp
+++ source/Plugins/Process/elf-core/ProcessElfCore.cpp
@@ -214,6 +214,29 @@
 
   SetUnixSignals(UnixSignals::Create(GetArchitecture()));
 
+  // Ensure we found at least one thread that was stopped on a signal.
+  bool siginfo_signal_found = false;
+  bool prstatus_signal_found = false;
+  // Check we found a signal in a SIGINFO note.
+  for (const auto &thread_data: m_thread_data) {
+    if (thread_data.signo != 0)
+      siginfo_signal_found = true;
+    if (thread_data.prstatus_sig != 0)
+      prstatus_signal_found = true;
+  }
+  if (siginfo_signal_found == false) {
+    // If we don't have signal from SIGINFO use the signal from each threads
+    // PRSTATUS note.
+    if (prstatus_signal_found == true) {
+      for (const auto &thread_data: m_thread_data)
+        thread_data.signo = thread_data.prstatus_sig;
+    } else if (m_thread_data.size() > 0) {
+      // If all else fails force the first thread to be SIGSTOP
+      m_thread_data.begin()->signo =
+          GetUnixSignals()->GetSignalNumberFromName("SIGSTOP");
+    }
+  }
+
   // Core files are useless without the main executable. See if we can locate
   // the main
   // executable using data we found in the core file notes.
@@ -400,7 +423,8 @@
   NT_TASKSTRUCT,
   NT_PLATFORM,
   NT_AUXV,
-  NT_FILE = 0x46494c45
+  NT_FILE = 0x46494c45,
+  NT_SIGINFO = 0x53494749
 };
 
 namespace FREEBSD {
@@ -484,6 +508,7 @@
   ArchSpec arch = GetArchitecture();
   ELFLinuxPrPsInfo prpsinfo;
   ELFLinuxPrStatus prstatus;
+  ELFLinuxSigInfo siginfo;
   size_t header_size;
   size_t len;
   Error error;
@@ -545,7 +570,7 @@
         error = prstatus.Parse(note_data, arch);
         if (error.Fail())
           return error;
-        thread_data->signo = prstatus.pr_cursig;
+        thread_data->prstatus_sig = prstatus.pr_cursig;
         thread_data->tid = prstatus.pr_pid;
         header_size = ELFLinuxPrStatus::GetSize(arch);
         len = note_data.GetByteSize() - header_size;
@@ -583,6 +608,12 @@
             m_nt_file_entries[i].path.SetCString(path);
         }
       } break;
+      case NT_SIGINFO: {
+        error = siginfo.Parse(note_data, arch);
+        if (error.Fail())
+          return error;
+        thread_data->signo = siginfo.si_signo;
+      } break;
       default:
         break;
       }
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to