samitolvanen updated this revision to Diff 383518.
samitolvanen marked 2 inline comments as done.
samitolvanen added a comment.

Missed a comment.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D108479

Files:
  clang/docs/LanguageExtensions.rst
  clang/include/clang/AST/APValue.h
  clang/include/clang/Basic/Builtins.def
  clang/lib/AST/APValue.cpp
  clang/lib/AST/ExprConstant.cpp
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/lib/CodeGen/CGExprConstant.cpp
  clang/lib/Sema/SemaChecking.cpp
  clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp
  clang/test/CodeGen/builtin-addressof-nocfi.c
  clang/test/SemaCXX/builtins.cpp

Index: clang/test/SemaCXX/builtins.cpp
===================================================================
--- clang/test/SemaCXX/builtins.cpp
+++ clang/test/SemaCXX/builtins.cpp
@@ -39,6 +39,15 @@
   S *ptmp = __builtin_addressof(S{}); // expected-error {{taking the address of a temporary}}
 }
 
+namespace addressof_nocfi {
+void a(void) {}
+static_assert(__builtin_addressof_nocfi(a) == a, "");
+
+struct S {
+} s;
+static_assert(__builtin_addressof_nocfi(s) == &s, "");
+} // namespace addressof_nocfi
+
 void no_ms_builtins() {
   __assume(1); // expected-error {{use of undeclared}}
   __noop(1); // expected-error {{use of undeclared}}
Index: clang/test/CodeGen/builtin-addressof-nocfi.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/builtin-addressof-nocfi.c
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -fsanitize=cfi-icall -o - %s | FileCheck %s
+
+#if !__has_builtin(__builtin_addressof_nocfi)
+#error "missing __builtin_addressof_nocfi"
+#endif
+
+void a(void) {}
+void b(void) {}
+void c(void (*p)(void)) {
+  p();
+}
+
+// CHECK: @e = constant void ()* no_cfi @a
+void (*const e)(void) = __builtin_addressof_nocfi(a);
+// CHECK: @f = global [2 x void ()*] [void ()* @b, void ()* no_cfi @b]
+void (*f[])(void) = {b, __builtin_addressof_nocfi(b)};
+
+void d(void) {
+  // CHECK: store void ()* no_cfi @b, void ()** %g
+  void (*g)(void) = __builtin_addressof_nocfi(b);
+  // CHECK: call void @c(void ()* no_cfi @a)
+  c(__builtin_addressof_nocfi(a));
+  e();
+  f[1]();
+  g();
+}
Index: clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp
+++ clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp
@@ -66,7 +66,8 @@
   case Builtin::BI__builtin_expect:
   case Builtin::BI__builtin_expect_with_probability:
   case Builtin::BI__builtin_assume_aligned:
-  case Builtin::BI__builtin_addressof: {
+  case Builtin::BI__builtin_addressof:
+  case Builtin::BI__builtin_addressof_nocfi: {
     // For __builtin_unpredictable, __builtin_expect,
     // __builtin_expect_with_probability and __builtin_assume_aligned,
     // just return the value of the subexpression.
Index: clang/lib/Sema/SemaChecking.cpp
===================================================================
--- clang/lib/Sema/SemaChecking.cpp
+++ clang/lib/Sema/SemaChecking.cpp
@@ -1749,6 +1749,7 @@
       return ExprError();
     break;
   case Builtin::BI__builtin_addressof:
+  case Builtin::BI__builtin_addressof_nocfi:
     if (SemaBuiltinAddressof(*this, TheCall))
       return ExprError();
     break;
Index: clang/lib/CodeGen/CGExprConstant.cpp
===================================================================
--- clang/lib/CodeGen/CGExprConstant.cpp
+++ clang/lib/CodeGen/CGExprConstant.cpp
@@ -1889,8 +1889,12 @@
     if (D->hasAttr<WeakRefAttr>())
       return CGM.GetWeakRefReference(D).getPointer();
 
-    if (auto FD = dyn_cast<FunctionDecl>(D))
-      return CGM.GetAddrOfFunction(FD);
+    if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
+      llvm::Constant *C = CGM.GetAddrOfFunction(FD);
+      if (base.isNoCFIValue())
+        return llvm::NoCFIValue::get(cast<llvm::GlobalValue>(C));
+      return C;
+    }
 
     if (auto VD = dyn_cast<VarDecl>(D)) {
       // We can never refer to a variable with local storage.
Index: clang/lib/CodeGen/CGBuiltin.cpp
===================================================================
--- clang/lib/CodeGen/CGBuiltin.cpp
+++ clang/lib/CodeGen/CGBuiltin.cpp
@@ -4439,6 +4439,9 @@
   }
   case Builtin::BI__builtin_addressof:
     return RValue::get(EmitLValue(E->getArg(0)).getPointer(*this));
+  case Builtin::BI__builtin_addressof_nocfi:
+    return RValue::get(llvm::NoCFIValue::get(
+        cast<GlobalValue>(EmitLValue(E->getArg(0)).getPointer(*this))));
   case Builtin::BI__builtin_operator_new:
     return EmitBuiltinNewDeleteCall(
         E->getCallee()->getType()->castAs<FunctionProtoType>(), E, false);
Index: clang/lib/AST/ExprConstant.cpp
===================================================================
--- clang/lib/AST/ExprConstant.cpp
+++ clang/lib/AST/ExprConstant.cpp
@@ -8982,6 +8982,11 @@
   switch (BuiltinOp) {
   case Builtin::BI__builtin_addressof:
     return evaluateLValue(E->getArg(0), Result);
+  case Builtin::BI__builtin_addressof_nocfi:
+    if (!evaluateLValue(E->getArg(0), Result))
+      return false;
+    Result.Base.setNoCFIValue(true);
+    return true;
   case Builtin::BI__builtin_assume_aligned: {
     // We need to be very careful here because: if the pointer does not have the
     // asserted alignment, then the behavior is undefined, and undefined
Index: clang/lib/AST/APValue.cpp
===================================================================
--- clang/lib/AST/APValue.cpp
+++ clang/lib/AST/APValue.cpp
@@ -40,9 +40,11 @@
     "Type is insufficiently aligned");
 
 APValue::LValueBase::LValueBase(const ValueDecl *P, unsigned I, unsigned V)
-    : Ptr(P ? cast<ValueDecl>(P->getCanonicalDecl()) : nullptr), Local{I, V} {}
+    : Ptr(P ? cast<ValueDecl>(P->getCanonicalDecl()) : nullptr),
+      Local{I, V,
+            /*NoCFIValue =*/false} {}
 APValue::LValueBase::LValueBase(const Expr *P, unsigned I, unsigned V)
-    : Ptr(P), Local{I, V} {}
+    : Ptr(P), Local{I, V, /*NoCFIValue=*/false} {}
 
 APValue::LValueBase APValue::LValueBase::getDynamicAlloc(DynamicAllocLValue LV,
                                                          QualType Type) {
@@ -124,6 +126,15 @@
   return QualType::getFromOpaquePtr(DynamicAllocType);
 }
 
+bool APValue::LValueBase::isNoCFIValue() const {
+  return (is<const ValueDecl *>() ? Local.NoCFIValue : false);
+}
+
+void APValue::LValueBase::setNoCFIValue(bool NoCFI) {
+  if (is<const ValueDecl *>())
+    Local.NoCFIValue = NoCFI;
+}
+
 void APValue::LValueBase::Profile(llvm::FoldingSetNodeID &ID) const {
   ID.AddPointer(Ptr.getOpaqueValue());
   if (is<TypeInfoLValue>() || is<DynamicAllocLValue>())
Index: clang/include/clang/Basic/Builtins.def
===================================================================
--- clang/include/clang/Basic/Builtins.def
+++ clang/include/clang/Basic/Builtins.def
@@ -1559,6 +1559,7 @@
 
 // Clang builtins (not available in GCC).
 BUILTIN(__builtin_addressof, "v*v&", "nct")
+BUILTIN(__builtin_addressof_nocfi, "v*v&", "nct")
 BUILTIN(__builtin_operator_new, "v*z", "tc")
 BUILTIN(__builtin_operator_delete, "vv*", "tn")
 BUILTIN(__builtin_char_memchr, "c*cC*iz", "n")
Index: clang/include/clang/AST/APValue.h
===================================================================
--- clang/include/clang/AST/APValue.h
+++ clang/include/clang/AST/APValue.h
@@ -176,6 +176,8 @@
     unsigned getVersion() const;
     QualType getTypeInfoType() const;
     QualType getDynamicAllocType() const;
+    bool isNoCFIValue() const;
+    void setNoCFIValue(bool NoCFI);
 
     QualType getType() const;
 
@@ -190,6 +192,7 @@
     PtrTy Ptr;
     struct LocalState {
       unsigned CallIndex, Version;
+      bool NoCFIValue;
     };
     union {
       LocalState Local;
Index: clang/docs/LanguageExtensions.rst
===================================================================
--- clang/docs/LanguageExtensions.rst
+++ clang/docs/LanguageExtensions.rst
@@ -2517,6 +2517,13 @@
     return __builtin_addressof(value);
   }
 
+``__builtin_addressof_nocfi``
+-----------------------------
+
+``__builtin_addressof_nocfi`` is similar to ``__builtin_addressof``, but
+with ``-fsanitize=cfi``, when passed a function, it returns the address of
+the function body instead of a pointer to the CFI jump table.
+
 ``__builtin_operator_new`` and ``__builtin_operator_delete``
 ------------------------------------------------------------
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to