vsk updated this revision to Diff 116453.
vsk added a comment.

- Remove some noisy changes.


https://reviews.llvm.org/D38210

Files:
  docs/UndefinedBehaviorSanitizer.rst
  lib/CodeGen/CGExpr.cpp
  lib/CodeGen/CodeGenFunction.cpp
  lib/CodeGen/CodeGenModule.cpp
  lib/CodeGen/CodeGenModule.h
  test/CodeGen/sanitize-function-calls.c

Index: test/CodeGen/sanitize-function-calls.c
===================================================================
--- /dev/null
+++ test/CodeGen/sanitize-function-calls.c
@@ -0,0 +1,86 @@
+// RUN: %clang_cc1 -w -triple i386-linux-gnu -fsanitize=function -emit-llvm -o - %s | FileCheck %s --check-prefixes=X32
+// RUN: %clang_cc1 -w -triple x86_64-linux-gnu -fsanitize=function -emit-llvm -o - %s | FileCheck %s --check-prefixes=X64
+
+struct S {};
+
+// X32: [[no_proto_ti:@.*]] = private constant i8* inttoptr (i32 4 to i8*)
+// X64: [[no_proto_ti:@.*]] = private constant i8* inttoptr (i64 4 to i8*)
+
+// X32: prologue <{ i32, i32 }> <{ i32 846595819, i32 sub (i32 ptrtoint (i8** [[no_proto_ti]] to i32), i32 ptrtoint (void ()* @no_proto to i32)) }>
+// X64: prologue <{ i32, i32 }> <{ i32 846595819, i32 trunc (i64 sub (i64 ptrtoint (i8** [[no_proto_ti]] to i64), i64 ptrtoint (void ()* @no_proto to i64)) to i32) }>
+void no_proto() {}
+
+void proto(void) {}
+
+typedef struct S (*vfunc0)(void);
+typedef void (*vfunc1)(void);
+typedef char (*vfunc2)(void);
+typedef short (*vfunc3)(void);
+typedef int (*vfunc4)(void);
+typedef long long (*vfunc5)(void);
+typedef float (*vfunc6)(void);
+typedef double (*vfunc7)(void);
+typedef void (*vfunc8)(int, int, int, int, int, int, int, int, int, int, int);
+
+// X64-LABEL: @call_proto
+void call_proto(void) {
+  // X64: [[ICMP:%.*]] = icmp eq i8* {{.*}}, null, !nosanitize
+  // X64-NEXT: br i1 [[ICMP]], {{.*}} !nosanitize
+  vfunc0 f0 = &proto;
+  f0();
+
+  // X64: [[ICMP:%.*]] = icmp eq i8* {{.*}}, inttoptr (i64 4 to i8*), !nosanitize
+  // X64-NEXT: br i1 [[ICMP]], {{.*}} !nosanitize
+  vfunc1 f1 = &proto;
+  f1();
+
+  // X64: [[ICMP:%.*]] = icmp eq i8* {{.*}}, inttoptr (i64 16 to i8*), !nosanitize
+  // X64-NEXT: br i1 [[ICMP]], {{.*}} !nosanitize
+  vfunc2 f2 = &proto;
+  f2();
+
+  // X64: [[ICMP:%.*]] = icmp eq i8* {{.*}}, inttoptr (i64 20 to i8*), !nosanitize
+  // X64-NEXT: br i1 [[ICMP]], {{.*}} !nosanitize
+  vfunc3 f3 = &proto;
+  f3();
+
+  // X64: [[ICMP:%.*]] = icmp eq i8* {{.*}}, inttoptr (i64 24 to i8*), !nosanitize
+  // X64-NEXT: br i1 [[ICMP]], {{.*}} !nosanitize
+  vfunc4 f4 = &proto;
+  f4();
+
+  // X64: [[ICMP:%.*]] = icmp eq i8* {{.*}}, inttoptr (i64 28 to i8*), !nosanitize
+  // X64-NEXT: br i1 [[ICMP]], {{.*}} !nosanitize
+  vfunc5 f5 = &proto;
+  f5();
+
+  // X64: [[ICMP:%.*]] = icmp eq i8* {{.*}}, inttoptr (i64 8 to i8*), !nosanitize
+  // X64-NEXT: br i1 [[ICMP]], {{.*}} !nosanitize
+  vfunc6 f6 = &proto;
+  f6();
+
+  // X64: [[ICMP:%.*]] = icmp eq i8* {{.*}}, inttoptr (i64 12 to i8*), !nosanitize
+  // X64-NEXT: br i1 [[ICMP]], {{.*}} !nosanitize
+  vfunc7 f7 = &proto;
+  f7();
+
+  // X64: [[ICMP:%.*]] = icmp eq i8* {{.*}}, inttoptr (i64 3681400516 to i8*), !nosanitize
+  // X64-NEXT: br i1 [[ICMP]], {{.*}} !nosanitize
+  vfunc8 f8 = &proto;
+  f8(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1);
+}
+
+// X64-LABEL: @call_no_proto
+void call_no_proto(void) {
+  // X64: [[ICMP:%.*]] = icmp eq i8* {{.*}}, null, !nosanitize
+  // X64-NEXT: br i1 [[ICMP]], {{.*}} !nosanitize
+  vfunc0 f0 = &no_proto;
+  f0();
+}
+
+// X64-LABEL: @main
+int main() {
+  call_proto();
+  call_no_proto();
+  return 0;
+}
Index: lib/CodeGen/CodeGenModule.h
===================================================================
--- lib/CodeGen/CodeGenModule.h
+++ lib/CodeGen/CodeGenModule.h
@@ -745,6 +745,9 @@
   /// Get the address of the RTTI descriptor for the given type.
   llvm::Constant *GetAddrOfRTTIDescriptor(QualType Ty, bool ForEH = false);
 
+  /// Get the type descriptor for a function for use with UBSan.
+  llvm::Constant *GetUBSanFunctionTypeDescriptor(QualType Ty);
+
   /// Get the address of a uuid descriptor .
   ConstantAddress GetAddrOfUuidDescriptor(const CXXUuidofExpr* E);
 
Index: lib/CodeGen/CodeGenModule.cpp
===================================================================
--- lib/CodeGen/CodeGenModule.cpp
+++ lib/CodeGen/CodeGenModule.cpp
@@ -4495,6 +4495,62 @@
   return getCXXABI().getAddrOfRTTIDescriptor(Ty);
 }
 
+llvm::Constant *CodeGenModule::GetUBSanFunctionTypeDescriptor(QualType Ty) {
+  if (getLangOpts().CPlusPlus)
+    return GetAddrOfRTTIDescriptor(Ty, /*ForEH=*/true);
+
+  // Bits:
+  //  0    : unused
+  //  1    : unused
+  //  2-4  : encode(returnType)
+  //  5-6  : encode(param1)
+  //  ...  : encode(paramK)
+  //  30-32: encode(param9)
+
+  auto encode = [this](QualType EncodeTy) {
+    // Encode one of: ?, void, f32, f64, i8, i16, i32, i64 (in 3 bits)
+    const auto *T = EncodeTy.getTypePtr();
+    if (T->isVoidType())
+      return 1;
+
+    uint64_t Size = getContext().getTypeSize(EncodeTy);
+    if (T->hasFloatingRepresentation()) {
+      switch (Size) {
+      case 32:
+        return 2;
+      case 64:
+        return 3;
+      default:
+        return 0;
+      }
+    }
+
+    switch (Size) {
+    case 8:
+      return 4;
+    case 16:
+      return 5;
+    case 32:
+      return 6;
+    case 64:
+      return 7;
+    default:
+      return 0;
+    }
+  };
+
+  const auto *FuncTy = Ty->getAs<FunctionType>();
+  unsigned Encoding = encode(FuncTy->getReturnType()) << 2;
+  if (auto *ProtoTy = dyn_cast<FunctionProtoType>(FuncTy)) {
+    auto Types = ProtoTy->getParamTypes();
+    for (unsigned I = 0, E = Types.size(); I < E && I < 9; ++I)
+      Encoding |= encode(Types[I]) << (5 + (3 * I));
+  }
+
+  return llvm::ConstantExpr::getIntToPtr(
+      llvm::ConstantInt::get(IntPtrTy, Encoding), Int8PtrTy);
+}
+
 void CodeGenModule::EmitOMPThreadPrivateDecl(const OMPThreadPrivateDecl *D) {
   for (auto RefExpr : D->varlists()) {
     auto *VD = cast<VarDecl>(cast<DeclRefExpr>(RefExpr)->getDecl());
Index: lib/CodeGen/CodeGenFunction.cpp
===================================================================
--- lib/CodeGen/CodeGenFunction.cpp
+++ lib/CodeGen/CodeGenFunction.cpp
@@ -887,12 +887,12 @@
 
   // If we are checking function types, emit a function type signature as
   // prologue data.
-  if (getLangOpts().CPlusPlus && SanOpts.has(SanitizerKind::Function)) {
+  if (SanOpts.has(SanitizerKind::Function)) {
     if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) {
       if (llvm::Constant *PrologueSig =
               CGM.getTargetCodeGenInfo().getUBSanFunctionSignature(CGM)) {
         llvm::Constant *FTRTTIConst =
-            CGM.GetAddrOfRTTIDescriptor(FD->getType(), /*ForEH=*/true);
+            CGM.GetUBSanFunctionTypeDescriptor(FD->getType());
         llvm::Constant *FTRTTIConstEncoded =
             EncodeAddrForUseInPrologue(Fn, FTRTTIConst);
         llvm::Constant *PrologueStructElems[] = {PrologueSig,
Index: lib/CodeGen/CGExpr.cpp
===================================================================
--- lib/CodeGen/CGExpr.cpp
+++ lib/CodeGen/CGExpr.cpp
@@ -4402,13 +4402,13 @@
 
   CGCallee Callee = OrigCallee;
 
-  if (getLangOpts().CPlusPlus && SanOpts.has(SanitizerKind::Function) &&
+  if (SanOpts.has(SanitizerKind::Function) &&
       (!TargetDecl || !isa<FunctionDecl>(TargetDecl))) {
     if (llvm::Constant *PrefixSig =
             CGM.getTargetCodeGenInfo().getUBSanFunctionSignature(CGM)) {
       SanitizerScope SanScope(this);
       llvm::Constant *FTRTTIConst =
-          CGM.GetAddrOfRTTIDescriptor(QualType(FnType, 0), /*ForEH=*/true);
+          CGM.GetUBSanFunctionTypeDescriptor(QualType(FnType, 0));
       llvm::Type *PrefixStructTyElems[] = {PrefixSig->getType(), Int32Ty};
       llvm::StructType *PrefixStructTy = llvm::StructType::get(
           CGM.getLLVMContext(), PrefixStructTyElems, /*isPacked=*/true);
@@ -4436,10 +4436,8 @@
           DecodeAddrUsedInPrologue(CalleePtr, CalleeRTTIEncoded);
       llvm::Value *CalleeRTTIMatch =
           Builder.CreateICmpEQ(CalleeRTTI, FTRTTIConst);
-      llvm::Constant *StaticData[] = {
-        EmitCheckSourceLocation(E->getLocStart()),
-        EmitCheckTypeDescriptor(CalleeType)
-      };
+      llvm::Constant *StaticData[] = {EmitCheckSourceLocation(E->getLocStart()),
+                                      EmitCheckTypeDescriptor(CalleeType)};
       EmitCheck(std::make_pair(CalleeRTTIMatch, SanitizerKind::Function),
                 SanitizerHandler::FunctionTypeMismatch, StaticData, CalleePtr);
 
Index: docs/UndefinedBehaviorSanitizer.rst
===================================================================
--- docs/UndefinedBehaviorSanitizer.rst
+++ docs/UndefinedBehaviorSanitizer.rst
@@ -87,7 +87,7 @@
   -  ``-fsanitize=float-divide-by-zero``: Floating point division by
      zero.
   -  ``-fsanitize=function``: Indirect call of a function through a
-     function pointer of the wrong type (Darwin/Linux, C++ and x86/x86_64
+     function pointer of the wrong type (Darwin/Linux and x86/x86_64
      only).
   -  ``-fsanitize=integer-divide-by-zero``: Integer division by zero.
   -  ``-fsanitize=nonnull-attribute``: Passing null pointer as a function
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to