[llvm] [llvm-exegesis] Add explicit error message with segfault address (PR #74210)

Aiden Grossman via llvm-commits llvm-commits at lists.llvm.org
Mon Dec 11 00:40:57 PST 2023


https://github.com/boomanaiden154 updated https://github.com/llvm/llvm-project/pull/74210

>From 313e7d3f6bb5cafc9c3cfb7878a4c566e1cbbeb0 Mon Sep 17 00:00:00 2001
From: Aiden Grossman <agrossman154 at yahoo.com>
Date: Mon, 11 Dec 2023 00:38:50 -0800
Subject: [PATCH] [llvm-exegesis] Use explicit error classes for different
 snippet crashes

This patch switches to using explicit snippet crashes that contain more
information about the specific type of error (like the address for a
segmentation fault) that occurred. All these new error classes inherit
from SnippetExecutionFailure to allow for easily grabbing all of them in
addition to filtering for specific types using the standard LLVM error
primitives.
---
 .../latency/subprocess-abnormal-exit-code.s   |  4 +-
 .../X86/latency/subprocess-segfault.s         |  4 +-
 .../llvm-exegesis/lib/BenchmarkRunner.cpp     | 21 ++++-------
 llvm/tools/llvm-exegesis/lib/Error.cpp        | 26 +++++++++++--
 llvm/tools/llvm-exegesis/lib/Error.h          | 37 ++++++++++++++++---
 5 files changed, 65 insertions(+), 27 deletions(-)

diff --git a/llvm/test/tools/llvm-exegesis/X86/latency/subprocess-abnormal-exit-code.s b/llvm/test/tools/llvm-exegesis/X86/latency/subprocess-abnormal-exit-code.s
index 849f1a2e552f1..1edb263455f95 100644
--- a/llvm/test/tools/llvm-exegesis/X86/latency/subprocess-abnormal-exit-code.s
+++ b/llvm/test/tools/llvm-exegesis/X86/latency/subprocess-abnormal-exit-code.s
@@ -1,8 +1,8 @@
 # REQUIRES: exegesis-can-measure-latency, x86_64-linux
 
-# RUN: llvm-exegesis -mtriple=x86_64-unknown-unknown -mode=latency -snippets-file=%s -execution-mode=subprocess | FileCheck %s
+# RUN: not llvm-exegesis -mtriple=x86_64-unknown-unknown -mode=latency -snippets-file=%s -execution-mode=subprocess 2>&1 | FileCheck %s
 
-# CHECK: error: 'Child benchmarking process exited with non-zero exit code: Child process returned with unknown exit code'
+# CHECK: llvm-exegesis error: Child benchmarking process exited with non-zero exit code: Child process returned with unknown exit code
 
 movl $60, %eax
 movl $127, %edi
diff --git a/llvm/test/tools/llvm-exegesis/X86/latency/subprocess-segfault.s b/llvm/test/tools/llvm-exegesis/X86/latency/subprocess-segfault.s
index 92b08e1c18c62..c72ac287d7170 100644
--- a/llvm/test/tools/llvm-exegesis/X86/latency/subprocess-segfault.s
+++ b/llvm/test/tools/llvm-exegesis/X86/latency/subprocess-segfault.s
@@ -2,7 +2,7 @@
 
 # RUN: llvm-exegesis -mtriple=x86_64-unknown-unknown -mode=latency -snippets-file=%s -execution-mode=subprocess | FileCheck %s
 
-# CHECK: error:           'The benchmarking subprocess sent unexpected signal: Segmentation fault'
+# CHECK: error: The snippet encountered a segmentation fault at address 10
 
-# LLVM-EXEGESIS-DEFREG RBX 0
+# LLVM-EXEGESIS-DEFREG RBX 10
 movq (%rbx), %rax
diff --git a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
index 85375dec2a44c..e7e9d5050abc8 100644
--- a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
+++ b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
@@ -141,17 +141,10 @@ class InProcessFunctionExecutorImpl : public BenchmarkRunner::FunctionExecutor {
       CrashRecoveryContext::Disable();
       PS.reset();
       if (Crashed) {
-        std::string Msg = "snippet crashed while running";
-#ifdef LLVM_ON_UNIX
         // See "Exit Status for Commands":
         // https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xcu_chap02.html
         constexpr const int kSigOffset = 128;
-        if (const char *const SigName = strsignal(CRC.RetCode - kSigOffset)) {
-          Msg += ": ";
-          Msg += SigName;
-        }
-#endif
-        return make_error<SnippetCrash>(std::move(Msg));
+        return make_error<SnippetSignal>(CRC.RetCode - kSigOffset);
       }
     }
 
@@ -360,7 +353,7 @@ class SubProcessFunctionExecutorImpl
         return Error::success();
       }
       // The child exited, but not successfully
-      return make_error<SnippetCrash>(
+      return make_error<Failure>(
           "Child benchmarking process exited with non-zero exit code: " +
           childProcessExitCodeToString(ChildExitCode));
     }
@@ -373,9 +366,11 @@ class SubProcessFunctionExecutorImpl
                                  Twine(strerror(errno)));
     }
 
-    return make_error<SnippetCrash>(
-        "The benchmarking subprocess sent unexpected signal: " +
-        Twine(strsignal(ChildSignalInfo.si_signo)));
+    if (ChildSignalInfo.si_signo == SIGSEGV)
+      return make_error<SnippetSegmentationFault>(
+          reinterpret_cast<intptr_t>(ChildSignalInfo.si_addr));
+
+    return make_error<SnippetSignal>(ChildSignalInfo.si_signo);
   }
 
   [[noreturn]] void prepareAndRunBenchmark(int Pipe,
@@ -575,7 +570,7 @@ Expected<Benchmark> BenchmarkRunner::runConfiguration(
   auto NewMeasurements = runMeasurements(**Executor);
 
   if (Error E = NewMeasurements.takeError()) {
-    if (!E.isA<SnippetCrash>())
+    if (!E.isA<SnippetExecutionFailure>())
       return std::move(E);
     InstrBenchmark.Error = toString(std::move(E));
     return std::move(InstrBenchmark);
diff --git a/llvm/tools/llvm-exegesis/lib/Error.cpp b/llvm/tools/llvm-exegesis/lib/Error.cpp
index 51ce41bf00bf5..d29c413856704 100644
--- a/llvm/tools/llvm-exegesis/lib/Error.cpp
+++ b/llvm/tools/llvm-exegesis/lib/Error.cpp
@@ -8,6 +8,10 @@
 
 #include "Error.h"
 
+#ifdef LLVM_ON_UNIX
+#include <string.h>
+#endif // LLVM_ON_UNIX
+
 namespace llvm {
 namespace exegesis {
 
@@ -19,13 +23,27 @@ std::error_code ClusteringError::convertToErrorCode() const {
   return inconvertibleErrorCode();
 }
 
-char SnippetCrash::ID;
-
-void SnippetCrash::log(raw_ostream &OS) const { OS << Msg; }
+char SnippetExecutionFailure::ID;
 
-std::error_code SnippetCrash::convertToErrorCode() const {
+std::error_code SnippetExecutionFailure::convertToErrorCode() const {
   return inconvertibleErrorCode();
 }
 
+char SnippetSegmentationFault::ID;
+
+void SnippetSegmentationFault::log(raw_ostream &OS) const {
+  OS << "The snippet encountered a segmentation fault at address "
+     << Twine::utohexstr(Address);
+}
+
+char SnippetSignal::ID;
+
+void SnippetSignal::log(raw_ostream &OS) const {
+  OS << "snippet crashed while running";
+#ifdef LLVM_ON_UNIX
+  OS << ": " << strsignal(SignalNumber);
+#endif // LLVM_ON_UNIX
+}
+
 } // namespace exegesis
 } // namespace llvm
diff --git a/llvm/tools/llvm-exegesis/lib/Error.h b/llvm/tools/llvm-exegesis/lib/Error.h
index e5fa093e6e125..2587c45f55743 100644
--- a/llvm/tools/llvm-exegesis/lib/Error.h
+++ b/llvm/tools/llvm-exegesis/lib/Error.h
@@ -36,19 +36,44 @@ class ClusteringError : public ErrorInfo<ClusteringError> {
   std::string Msg;
 };
 
-// A class representing failures that happened during snippet execution.
-// Instead of terminating the program crashes are logged into the output.
-class SnippetCrash : public ErrorInfo<SnippetCrash> {
+// A class representing a non-descript snippet execution failure. This class
+// is designed to sub-classed into more specific failures that contain
+// additional data about the specific error that they represent. Instead of
+// halting the program, the errors are reported in the output.
+class SnippetExecutionFailure : public ErrorInfo<SnippetExecutionFailure> {
 public:
   static char ID;
-  SnippetCrash(const Twine &S) : Msg(S.str()) {}
+
+  std::error_code convertToErrorCode() const override;
+};
+
+// A class representing specifically segmentation faults that happen during
+// snippet execution.
+class SnippetSegmentationFault : public SnippetExecutionFailure {
+public:
+  static char ID;
+  SnippetSegmentationFault(intptr_t SegFaultAddress)
+      : Address(SegFaultAddress){};
+
+  intptr_t getAddress() { return Address; }
 
   void log(raw_ostream &OS) const override;
 
-  std::error_code convertToErrorCode() const override;
+private:
+  intptr_t Address;
+};
+
+// A class representing all other non-specific failures that happen during
+// snippet execution.
+class SnippetSignal : public SnippetExecutionFailure {
+public:
+  static char ID;
+  SnippetSignal(int Signal) : SignalNumber(Signal){};
+
+  void log(raw_ostream &OS) const override;
 
 private:
-  std::string Msg;
+  int SignalNumber;
 };
 
 } // namespace exegesis



More information about the llvm-commits mailing list