[PATCH] D115317: [dfsan] Add a flag to ignore personality routines.

Taewook Oh via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Tue Dec 7 21:37:12 PST 2021


twoh created this revision.
Herald added a subscriber: hiraditya.
twoh requested review of this revision.
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

This diff adds "dfsan-ignore-personality-routine" flag, which makes
the dfsan pass to not to generate wrappers for the personality functions if the
function is marked uninstrumented.

This flag is to support dfsan with the cases where the exception handling
routines cannot be instrumented (e.g. use the prebuilt version of c++ standard
library). When the personality function cannot be instrumented it is supposed
to be marked "uninstrumented" from the abi list file. While DFSan generates a
wrapper function for uninstrumented functions, it cannot cannot generate a
valid wrapper for vararg functions, and indirect invocation of vararg function
wrapper terminates the execution of dfsan-instrumented programs. This makes
invocation of personality routine to crash the program, because 1) clang adds a
declaration of personality functions as a vararg function with no fixed
argument, and 2) personality routines are always called indirectly.

To address this issue, the flag introduced in this diff makes dfsan to not to
instrument the personality function. This is not the "correct" solution in the
sense that return value label from the personality function will be undefined.
However, in practice, if the exception handling routines are uninstrumented we
wouldn't expect precise label propagation around them, and it would be more
beneficial to make the rest of the program run without termination.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D115317

Files:
  llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp
  llvm/test/Instrumentation/DataFlowSanitizer/Inputs/personality-routine-abilist.txt
  llvm/test/Instrumentation/DataFlowSanitizer/ignore_persnality_routine.ll


Index: llvm/test/Instrumentation/DataFlowSanitizer/ignore_persnality_routine.ll
===================================================================
--- /dev/null
+++ llvm/test/Instrumentation/DataFlowSanitizer/ignore_persnality_routine.ll
@@ -0,0 +1,39 @@
+; RUN: opt < %s -dfsan -S --dfsan-abilist=%S/Inputs/personality-routine-abilist.txt | FileCheck %s
+; RUN: opt < %s -dfsan -S --dfsan-abilist=%S/Inputs/personality-routine-abilist.txt -dfsan-ignore-personality-routine | FileCheck %s --check-prefix=CHECK-IGNORE
+; RUN: opt < %s -passes=dfsan -S --dfsan-abilist=%S/Inputs/personality-routine-abilist.txt | FileCheck %s
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+declare i32 @__gxx_personality_v0(...)
+
+declare i8* @__cxa_begin_catch(i8*)
+
+declare void @__cxa_end_catch()
+
+declare void @g(...)
+
+; CHECK-LABEL: @h.dfsan
+; CHECK-SAME: personality {{.*}}@"dfsw$__gxx_personality_v0"{{.*}}
+; CHECK-IGNORE-LABEL: @h.dfsan
+; CHECK-IGNORE-SAME: personality {{.*}}__gxx_personality_v0{{.*}}
+define i32 @h() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
+  invoke void (...) @g(i32 42)
+          to label %try.cont unwind label %lpad
+
+lpad:
+  %1 = landingpad { i8*, i32 }
+          catch i8* null
+  %2 = extractvalue { i8*, i32 } %1, 0
+  %3 = tail call i8* @__cxa_begin_catch(i8* %2)
+  tail call void @__cxa_end_catch()
+  br label %try.cont
+
+try.cont:
+  ret i32 0
+}
+
+; CHECK: @"dfsw$__gxx_personality_v0"
+; CHECK: call void @__dfsan_vararg_wrapper
+; CHECK-IGNORE-NOT: @"dfsw$__gxx_personality_v0"
+; CHECK-IGNORE-NOT: call void @__dfsan_vararg_wrapper
Index: llvm/test/Instrumentation/DataFlowSanitizer/Inputs/personality-routine-abilist.txt
===================================================================
--- /dev/null
+++ llvm/test/Instrumentation/DataFlowSanitizer/Inputs/personality-routine-abilist.txt
@@ -0,0 +1 @@
+fun:__gxx_personality_v0=uninstrumented
Index: llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp
===================================================================
--- llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp
+++ llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp
@@ -232,6 +232,12 @@
                                    cl::desc("Track origins of labels"),
                                    cl::Hidden, cl::init(0));
 
+static cl::opt<bool> ClIgnorePersonalityRoutine(
+    "dfsan-ignore-personality-routine",
+    cl::desc("If a personality routine is marked uninstrumented from the ABI "
+             "list, do not create a wrapper for it."),
+    cl::Hidden, cl::init(false));
+
 static StringRef getGlobalTypeString(const GlobalValue &G) {
   // Types of GlobalVariables are always pointer types.
   Type *GType = G.getValueType();
@@ -1357,9 +1363,24 @@
   std::vector<Function *> FnsToInstrument;
   SmallPtrSet<Function *, 2> FnsWithNativeABI;
   SmallPtrSet<Function *, 2> FnsWithForceZeroLabel;
+  SmallPtrSet<Constant *, 1> PersonalityFns;
   for (Function &F : M)
-    if (!F.isIntrinsic() && !DFSanRuntimeFunctions.contains(&F))
+    if (!F.isIntrinsic() && !DFSanRuntimeFunctions.contains(&F)) {
       FnsToInstrument.push_back(&F);
+      if (F.hasPersonalityFn())
+        PersonalityFns.insert(F.getPersonalityFn()->stripPointerCasts());
+    }
+
+  if (ClIgnorePersonalityRoutine) {
+    for (auto *C : PersonalityFns) {
+      assert(isa<Function>(C) && "Personality routine is not a function!");
+      Function *F = cast<Function>(C);
+      if (!isInstrumented(F))
+        FnsToInstrument.erase(
+            std::remove(FnsToInstrument.begin(), FnsToInstrument.end(), F),
+            FnsToInstrument.end());
+    }
+  }
 
   // Give function aliases prefixes when necessary, and build wrappers where the
   // instrumentedness is inconsistent.


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D115317.392642.patch
Type: text/x-patch
Size: 3954 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20211208/2b3bddc3/attachment.bin>


More information about the llvm-commits mailing list