r278050 - [Attr] Add support for the `ms_hook_prologue` attribute.

Charles Davis via cfe-commits cfe-commits at lists.llvm.org
Mon Aug 8 14:03:40 PDT 2016


Author: cdavis
Date: Mon Aug  8 16:03:39 2016
New Revision: 278050

URL: http://llvm.org/viewvc/llvm-project?rev=278050&view=rev
Log:
[Attr] Add support for the `ms_hook_prologue` attribute.

Summary:
Based on a patch by Michael Mueller.

This attribute specifies that a function can be hooked or patched. This
mechanism was originally devised by Microsoft for hotpatching their
binaries (which they're constantly updating to stay ahead of crackers,
script kiddies, and other ne'er-do-wells on the Internet), but it's now
commonly abused by Windows programs that want to hook API functions. It
is for this reason that this attribute was added to GCC--hence the name,
`ms_hook_prologue`.

Depends on D19908.

Reviewers: rnk, aaron.ballman

Subscribers: cfe-commits

Differential Revision: https://reviews.llvm.org/D19909

Added:
    cfe/trunk/test/Sema/attr-ms-hook-prologue-wrong-arch.c
    cfe/trunk/test/Sema/attr-ms-hook-prologue.c
Modified:
    cfe/trunk/include/clang/Basic/Attr.td
    cfe/trunk/include/clang/Basic/AttrDocs.td
    cfe/trunk/lib/CodeGen/TargetInfo.cpp
    cfe/trunk/lib/Sema/SemaDeclAttr.cpp
    cfe/trunk/test/CodeGen/function-attributes.c

Modified: cfe/trunk/include/clang/Basic/Attr.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=278050&r1=278049&r2=278050&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Attr.td (original)
+++ cfe/trunk/include/clang/Basic/Attr.td Mon Aug  8 16:03:39 2016
@@ -257,6 +257,7 @@ def TargetMips : TargetArch<["mips", "mi
 def TargetMSP430 : TargetArch<["msp430"]>;
 def TargetX86 : TargetArch<["x86"]>;
 def TargetAnyX86 : TargetArch<["x86", "x86_64"]>;
+def TargetWindowsArches : TargetArch<["x86", "x86_64", "arm", "thumb"]>;
 def TargetWindows : TargetArch<["x86", "x86_64", "arm", "thumb"]> {
   let OSes = ["Win32"];
 }
@@ -2069,6 +2070,12 @@ def TypeTagForDatatype : InheritableAttr
 
 // Microsoft-related attributes
 
+def MSHookPrologue : InheritableAttr, TargetSpecificAttr<TargetWindowsArches> {
+  let Spellings = [GCC<"ms_hook_prologue">];
+  let Subjects = SubjectList<[Function]>;
+  let Documentation = [MSHookPrologueDocs];
+}
+
 def MSNoVTable : InheritableAttr, TargetSpecificAttr<TargetMicrosoftCXXABI> {
   let Spellings = [Declspec<"novtable">];
   let Subjects = SubjectList<[CXXRecord]>;

Modified: cfe/trunk/include/clang/Basic/AttrDocs.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/AttrDocs.td?rev=278050&r1=278049&r2=278050&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/AttrDocs.td (original)
+++ cfe/trunk/include/clang/Basic/AttrDocs.td Mon Aug  8 16:03:39 2016
@@ -548,6 +548,22 @@ Query for this feature with ``__has_attr
   }];
 }
 
+def MSHookPrologueDocs : Documentation {
+  let Category = DocCatFunction;
+  let Content = [{
+The ``ms_hook_prologue`` attribute marks a function as "hotpatchable" according
+to conventions used on Windows. Specifically, enough space will be ensured
+in the prologue for a short jump, and an architecturally dependently sized
+patch space will be reserved prior to the entry point. See the documentation
+for the `/HOTPATCH`_ switch on MSDN.
+
+This attribute cannot be used in conjunction with the ``naked``,
+``always_inline``, or ``__forceinline`` attributes.
+
+.. _`/HOTPATCH`: https://msdn.microsoft.com/en-us/library/ms173507.aspx
+  }];
+}
+
 def NoDebugDocs : Documentation {
   let Category = DocCatVariable;
   let Content = [{

Modified: cfe/trunk/lib/CodeGen/TargetInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/TargetInfo.cpp?rev=278050&r1=278049&r2=278050&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/TargetInfo.cpp (original)
+++ cfe/trunk/lib/CodeGen/TargetInfo.cpp Mon Aug  8 16:03:39 2016
@@ -1779,6 +1779,10 @@ void X86_32TargetCodeGenInfo::setTargetA
       llvm::Function *Fn = cast<llvm::Function>(GV);
       Fn->setCallingConv(llvm::CallingConv::X86_INTR);
     }
+    if (FD->hasAttr<MSHookPrologueAttr>()) {
+      llvm::Function *Fn = cast<llvm::Function>(GV);
+      Fn->addFnAttr("patchable-function", "ms-hotpatch");
+    }
   }
 }
 
@@ -2109,6 +2113,10 @@ public:
         llvm::Function *Fn = cast<llvm::Function>(GV);
         Fn->setCallingConv(llvm::CallingConv::X86_INTR);
       }
+      if (FD->hasAttr<MSHookPrologueAttr>()) {
+        llvm::Function *Fn = cast<llvm::Function>(GV);
+        Fn->addFnAttr("patchable-function", "ms-hotpatch");
+      }
     }
   }
 };

Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=278050&r1=278049&r2=278050&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Mon Aug  8 16:03:39 2016
@@ -1664,15 +1664,6 @@ static void handleCommonAttr(Sema &S, De
     D->addAttr(CA);
 }
 
-static void handleNakedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
-  if (checkAttrMutualExclusion<DisableTailCallsAttr>(S, D, Attr.getRange(),
-                                                     Attr.getName()))
-    return;
-
-  D->addAttr(::new (S.Context) NakedAttr(Attr.getRange(), S.Context,
-                                         Attr.getAttributeSpellingListIndex()));
-}
-
 static void handleNoReturnAttr(Sema &S, Decl *D, const AttributeList &attr) {
   if (hasDeclarator(D)) return;
 
@@ -3673,7 +3664,9 @@ OptimizeNoneAttr *Sema::mergeOptimizeNon
 static void handleAlwaysInlineAttr(Sema &S, Decl *D,
                                    const AttributeList &Attr) {
   if (checkAttrMutualExclusion<NotTailCalledAttr>(S, D, Attr.getRange(),
-                                                  Attr.getName()))
+                                                  Attr.getName()) ||
+      checkAttrMutualExclusion<MSHookPrologueAttr>(S, D, Attr.getRange(),
+                                                   Attr.getName()))
     return;
 
   if (AlwaysInlineAttr *Inline = S.mergeAlwaysInlineAttr(
@@ -5552,7 +5545,8 @@ static void ProcessDeclAttribute(Sema &S
     handleHotAttr(S, D, Attr);
     break;
   case AttributeList::AT_Naked:
-    handleNakedAttr(S, D, Attr);
+    handleSimpleAttributeWithExclusions<NakedAttr, DisableTailCallsAttr,
+                                        MSHookPrologueAttr>(S, D, Attr);
     break;
   case AttributeList::AT_NoReturn:
     handleNoReturnAttr(S, D, Attr);
@@ -5780,6 +5774,9 @@ static void ProcessDeclAttribute(Sema &S
     break;
   case AttributeList::AT_LayoutVersion:
     handleLayoutVersion(S, D, Attr);
+  case AttributeList::AT_MSHookPrologue:
+    handleSimpleAttributeWithExclusions<MSHookPrologueAttr, NakedAttr,
+      AlwaysInlineAttr>(S, D, Attr);
     break;
   case AttributeList::AT_MSNoVTable:
     handleSimpleAttribute<MSNoVTableAttr>(S, D, Attr);

Modified: cfe/trunk/test/CodeGen/function-attributes.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/function-attributes.c?rev=278050&r1=278049&r2=278050&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/function-attributes.c (original)
+++ cfe/trunk/test/CodeGen/function-attributes.c Mon Aug  8 16:03:39 2016
@@ -108,11 +108,18 @@ void f20(void) {
   _setjmp(0);
 }
 
+// CHECK-LABEL: define void @f21
+// CHECK: [[HOTPATCH:#[0-9]+]]
+// CHECK: {
+void __attribute__((ms_hook_prologue)) f21(void) {
+}
+
 // CHECK: attributes [[NUW]] = { nounwind optsize{{.*}} }
 // CHECK: attributes [[AI]] = { alwaysinline nounwind optsize{{.*}} }
 // CHECK: attributes [[NUW_OS_RN]] = { nounwind optsize readnone{{.*}} }
 // CHECK: attributes [[ALIGN]] = { nounwind optsize alignstack=16{{.*}} }
 // CHECK: attributes [[RT]] = { nounwind optsize returns_twice{{.*}} }
+// CHECK: attributes [[HOTPATCH]] = { nounwind optsize{{.*}}"patchable-function"="ms-hotpatch"{{.*}} }
 // CHECK: attributes [[NR]] = { noreturn optsize }
 // CHECK: attributes [[NUW_RN]] = { nounwind optsize readnone }
 // CHECK: attributes [[RT_CALL]] = { optsize returns_twice }

Added: cfe/trunk/test/Sema/attr-ms-hook-prologue-wrong-arch.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/attr-ms-hook-prologue-wrong-arch.c?rev=278050&view=auto
==============================================================================
--- cfe/trunk/test/Sema/attr-ms-hook-prologue-wrong-arch.c (added)
+++ cfe/trunk/test/Sema/attr-ms-hook-prologue-wrong-arch.c Mon Aug  8 16:03:39 2016
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 -triple s390x-unknown-linux -fms-extensions -fsyntax-only -verify %s
+
+// expected-warning at +1{{unknown attribute 'ms_hook_prologue' ignored}}
+int __attribute__((ms_hook_prologue)) foo(int a, int b) {
+  return a+b;
+}

Added: cfe/trunk/test/Sema/attr-ms-hook-prologue.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/attr-ms-hook-prologue.c?rev=278050&view=auto
==============================================================================
--- cfe/trunk/test/Sema/attr-ms-hook-prologue.c (added)
+++ cfe/trunk/test/Sema/attr-ms-hook-prologue.c Mon Aug  8 16:03:39 2016
@@ -0,0 +1,22 @@
+// RUN: %clang_cc1 -triple i386-pc-linux -fms-extensions -fsyntax-only -verify %s
+
+int __attribute__((ms_hook_prologue)) foo(int a, int b) {
+  return a+b;
+}
+
+// expected-note at +2{{conflicting attribute is here}}
+// expected-error at +1{{'naked' and 'ms_hook_prologue' attributes are not compatible}}
+__declspec(naked) int __attribute__((ms_hook_prologue)) bar(int a, int b) {
+}
+
+// expected-note at +2{{conflicting attribute is here}}
+// expected-error at +1{{'__forceinline' and 'ms_hook_prologue' attributes are not compatible}}
+__forceinline int __attribute__((ms_hook_prologue)) baz(int a, int b) {
+  return a-b;
+}
+
+// expected-warning at +1{{'ms_hook_prologue' attribute only applies to functions}}
+int x __attribute__((ms_hook_prologue));
+
+// expected-error at +1{{'ms_hook_prologue' attribute takes no arguments}}
+int f(int a, int b) __attribute__((ms_hook_prologue(2)));




More information about the cfe-commits mailing list