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);
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);
}
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;
}
// 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);
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);
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);
--- /dev/null
+;; 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