[llvm] a78cfd5 - [GCOV] Set !kcfi_type metadata for indirectly called functions

Sami Tolvanen via llvm-commits llvm-commits at lists.llvm.org
Wed Jan 11 15:05:16 PST 2023


Author: Sami Tolvanen
Date: 2023-01-11T22:53:22Z
New Revision: a78cfd5909024f9daa9a5175e9d411b0fac0e9a1

URL: https://github.com/llvm/llvm-project/commit/a78cfd5909024f9daa9a5175e9d411b0fac0e9a1
DIFF: https://github.com/llvm/llvm-project/commit/a78cfd5909024f9daa9a5175e9d411b0fac0e9a1.diff

LOG: [GCOV] Set !kcfi_type metadata for indirectly called functions

With CONFIG_GCOV_KERNEL, the Linux kernel indirectly calls the
__llvm_gcov_* functions generated by LLVM. With -fsanitize=kcfi,
these calls are made from instrumented code and fail indirect
call checks as they don't have !kcfi_type metadata. Similarly
to D138945, set type metadata for these functions to allow GCOV
and KCFI to be both enabled.

Link: https://github.com/ClangBuiltLinux/linux/issues/1778

Reviewed By: MaskRay

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

Added: 
    llvm/test/Transforms/GCOVProfiling/kcfi.ll

Modified: 
    llvm/include/llvm/Transforms/Utils/ModuleUtils.h
    llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp
    llvm/lib/Transforms/Utils/ModuleUtils.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/Transforms/Utils/ModuleUtils.h b/llvm/include/llvm/Transforms/Utils/ModuleUtils.h
index 47a618647f1d9..6f893d8416c6c 100644
--- a/llvm/include/llvm/Transforms/Utils/ModuleUtils.h
+++ b/llvm/include/llvm/Transforms/Utils/ModuleUtils.h
@@ -42,6 +42,10 @@ void appendToGlobalCtors(Module &M, Function *F, int Priority,
 void appendToGlobalDtors(Module &M, Function *F, int Priority,
                          Constant *Data = nullptr);
 
+/// Sets the KCFI type for the function. Used for compiler-generated functions
+/// that are indirectly called in instrumented code.
+void setKCFIType(Module &M, Function &F, StringRef MangledType);
+
 FunctionCallee declareSanitizerInitFunction(Module &M, StringRef InitName,
                                             ArrayRef<Type *> InitArgTypes);
 

diff  --git a/llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp b/llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp
index 85dcca2d47dba..0c2688f7b3f68 100644
--- a/llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp
+++ b/llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp
@@ -119,7 +119,8 @@ class GCOVProfiler {
                    function_ref<BranchProbabilityInfo *(Function &F)> GetBPI,
                    function_ref<const TargetLibraryInfo &(Function &F)> GetTLI);
 
-  Function *createInternalFunction(FunctionType *FTy, StringRef Name);
+  Function *createInternalFunction(FunctionType *FTy, StringRef Name,
+                                   StringRef MangledType = "");
   void emitGlobalConstructor(
       SmallVectorImpl<std::pair<GlobalVariable *, MDNode *>> &CountersBySP);
 
@@ -976,13 +977,16 @@ bool GCOVProfiler::emitProfileNotes(
 }
 
 Function *GCOVProfiler::createInternalFunction(FunctionType *FTy,
-                                               StringRef Name) {
+                                               StringRef Name,
+                                               StringRef MangledType /*=""*/) {
   Function *F = Function::createWithDefaultAttr(
       FTy, GlobalValue::InternalLinkage, 0, Name, M);
   F->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
   F->addFnAttr(Attribute::NoUnwind);
   if (Options.NoRedZone)
     F->addFnAttr(Attribute::NoRedZone);
+  if (!MangledType.empty())
+    setKCFIType(*M, *F, MangledType);
   return F;
 }
 
@@ -995,7 +999,7 @@ void GCOVProfiler::emitGlobalConstructor(
   // be executed at exit and the "__llvm_gcov_reset" function to be executed
   // when "__gcov_flush" is called.
   FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false);
-  Function *F = createInternalFunction(FTy, "__llvm_gcov_init");
+  Function *F = createInternalFunction(FTy, "__llvm_gcov_init", "_ZTSFvvE");
   F->addFnAttr(Attribute::NoInline);
 
   BasicBlock *BB = BasicBlock::Create(*Ctx, "entry", F);
@@ -1071,7 +1075,8 @@ Function *GCOVProfiler::insertCounterWriteout(
   FunctionType *WriteoutFTy = FunctionType::get(Type::getVoidTy(*Ctx), false);
   Function *WriteoutF = M->getFunction("__llvm_gcov_writeout");
   if (!WriteoutF)
-    WriteoutF = createInternalFunction(WriteoutFTy, "__llvm_gcov_writeout");
+    WriteoutF =
+        createInternalFunction(WriteoutFTy, "__llvm_gcov_writeout", "_ZTSFvvE");
   WriteoutF->addFnAttr(Attribute::NoInline);
 
   BasicBlock *BB = BasicBlock::Create(*Ctx, "entry", WriteoutF);
@@ -1317,7 +1322,7 @@ Function *GCOVProfiler::insertReset(
   FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false);
   Function *ResetF = M->getFunction("__llvm_gcov_reset");
   if (!ResetF)
-    ResetF = createInternalFunction(FTy, "__llvm_gcov_reset");
+    ResetF = createInternalFunction(FTy, "__llvm_gcov_reset", "_ZTSFvvE");
   ResetF->addFnAttr(Attribute::NoInline);
 
   BasicBlock *Entry = BasicBlock::Create(*Ctx, "entry", ResetF);

diff  --git a/llvm/lib/Transforms/Utils/ModuleUtils.cpp b/llvm/lib/Transforms/Utils/ModuleUtils.cpp
index 315258d0faaf6..ee5e65fbaa505 100644
--- a/llvm/lib/Transforms/Utils/ModuleUtils.cpp
+++ b/llvm/lib/Transforms/Utils/ModuleUtils.cpp
@@ -150,7 +150,7 @@ void llvm::removeFromUsedLists(Module &M,
   removeFromUsedList(M, "llvm.compiler.used", ShouldRemove);
 }
 
-static void setKCFIType(Module &M, Function &F, StringRef MangledType) {
+void llvm::setKCFIType(Module &M, Function &F, StringRef MangledType) {
   if (!M.getModuleFlag("kcfi"))
     return;
   // Matches CodeGenModule::CreateKCFITypeId in Clang.

diff  --git a/llvm/test/Transforms/GCOVProfiling/kcfi.ll b/llvm/test/Transforms/GCOVProfiling/kcfi.ll
new file mode 100644
index 0000000000000..b25f40f05d5bc
--- /dev/null
+++ b/llvm/test/Transforms/GCOVProfiling/kcfi.ll
@@ -0,0 +1,31 @@
+;; Ensure __llvm_gcov_(writeout|reset|init) have !kcfi_type with KCFI.
+; RUN: mkdir -p %t && cd %t
+; RUN: opt < %s -S -passes=insert-gcov-profiling | FileCheck %s
+
+target triple = "x86_64-unknown-linux-gnu"
+
+define dso_local void @empty() !dbg !5 {
+entry:
+  ret void, !dbg !8
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3, !4, !9}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, emissionKind: FullDebug, enums: !2)
+!1 = !DIFile(filename: "a.c", directory: "")
+!2 = !{}
+!3 = !{i32 7, !"Dwarf Version", i32 5}
+!4 = !{i32 2, !"Debug Info Version", i32 3}
+!5 = distinct !DISubprogram(name: "empty", scope: !1, file: !1, line: 1, type: !6, scopeLine: 1, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !2)
+!6 = !DISubroutineType(types: !7)
+!7 = !{null}
+!8 = !DILocation(line: 2, column: 1, scope: !5)
+!9 = !{i32 4, !"kcfi", i32 1}
+
+; CHECK: define internal void @__llvm_gcov_writeout()
+; CHECK-SAME: !kcfi_type
+; CHECK: define internal void @__llvm_gcov_reset()
+; CHECK-SAME: !kcfi_type
+; CHECK: define internal void @__llvm_gcov_init()
+; CHECK-SAME: !kcfi_type


        


More information about the llvm-commits mailing list