Skip to content

Commit e2d37a0

Browse files
samitolvanencjdb
authored andcommitted
Fix KCFI types for generated functions with integer normalization (llvm#104826)
With -fsanitize-cfi-icall-experimental-normalize-integers, Clang appends ".normalized" to KCFI types in CodeGenModule::CreateKCFITypeId, which changes type hashes also for functions that don't have integer types in their signatures. However, llvm::setKCFIType does not take integer normalization into account, which means LLVM generated functions with KCFI types, e.g. sanitizer constructors, will fail KCFI checks when integer normalization is enabled in Clang. Add a cfi-normalize-integers module flag to indicate integer normalization is used, and append ".normalized" to KCFI types also in llvm::setKCFIType to fix the type mismatch.
1 parent ac484ac commit e2d37a0

File tree

5 files changed

+53
-8
lines changed

5 files changed

+53
-8
lines changed

Diff for: clang/lib/CodeGen/CodeGenModule.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -1134,6 +1134,11 @@ void CodeGenModule::Release() {
11341134
CodeGenOpts.SanitizeCfiCanonicalJumpTables);
11351135
}
11361136

1137+
if (CodeGenOpts.SanitizeCfiICallNormalizeIntegers) {
1138+
getModule().addModuleFlag(llvm::Module::Override, "cfi-normalize-integers",
1139+
1);
1140+
}
1141+
11371142
if (LangOpts.Sanitize.has(SanitizerKind::KCFI)) {
11381143
getModule().addModuleFlag(llvm::Module::Override, "kcfi", 1);
11391144
// KCFI assumes patchable-function-prefix is the same for all indirectly

Diff for: clang/test/CodeGen/kcfi-normalize.c

+1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ void baz(void (*fn)(int, int, int), int arg1, int arg2, int arg3) {
2828
fn(arg1, arg2, arg3);
2929
}
3030

31+
// CHECK: ![[#]] = !{i32 4, !"cfi-normalize-integers", i32 1}
3132
// CHECK: ![[TYPE1]] = !{i32 -1143117868}
3233
// CHECK: ![[TYPE2]] = !{i32 -460921415}
3334
// CHECK: ![[TYPE3]] = !{i32 -333839615}

Diff for: llvm/lib/Transforms/Utils/ModuleUtils.cpp

+7-5
Original file line numberDiff line numberDiff line change
@@ -205,11 +205,13 @@ void llvm::setKCFIType(Module &M, Function &F, StringRef MangledType) {
205205
// Matches CodeGenModule::CreateKCFITypeId in Clang.
206206
LLVMContext &Ctx = M.getContext();
207207
MDBuilder MDB(Ctx);
208-
F.setMetadata(
209-
LLVMContext::MD_kcfi_type,
210-
MDNode::get(Ctx, MDB.createConstant(ConstantInt::get(
211-
Type::getInt32Ty(Ctx),
212-
static_cast<uint32_t>(xxHash64(MangledType))))));
208+
std::string Type = MangledType.str();
209+
if (M.getModuleFlag("cfi-normalize-integers"))
210+
Type += ".normalized";
211+
F.setMetadata(LLVMContext::MD_kcfi_type,
212+
MDNode::get(Ctx, MDB.createConstant(ConstantInt::get(
213+
Type::getInt32Ty(Ctx),
214+
static_cast<uint32_t>(xxHash64(Type))))));
213215
// If the module was compiled with -fpatchable-function-entry, ensure
214216
// we use the same patchable-function-prefix.
215217
if (auto *MD = mdconst::extract_or_null<ConstantInt>(

Diff for: llvm/test/Transforms/GCOVProfiling/kcfi-normalize.ll

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
;; Ensure __llvm_gcov_(writeout|reset|init) have the correct !kcfi_type
2+
;; with integer normalization.
3+
; RUN: mkdir -p %t && cd %t
4+
; RUN: opt < %s -S -passes=insert-gcov-profiling | FileCheck %s
5+
6+
target triple = "x86_64-unknown-linux-gnu"
7+
8+
define dso_local void @empty() !dbg !5 {
9+
entry:
10+
ret void, !dbg !8
11+
}
12+
13+
!llvm.dbg.cu = !{!0}
14+
!llvm.module.flags = !{!3, !4, !9, !10}
15+
16+
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, emissionKind: FullDebug, enums: !2)
17+
!1 = !DIFile(filename: "a.c", directory: "")
18+
!2 = !{}
19+
!3 = !{i32 7, !"Dwarf Version", i32 5}
20+
!4 = !{i32 2, !"Debug Info Version", i32 3}
21+
!5 = distinct !DISubprogram(name: "empty", scope: !1, file: !1, line: 1, type: !6, scopeLine: 1, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !2)
22+
!6 = !DISubroutineType(types: !7)
23+
!7 = !{null}
24+
!8 = !DILocation(line: 2, column: 1, scope: !5)
25+
!9 = !{i32 4, !"kcfi", i32 1}
26+
!10 = !{i32 4, !"cfi-normalize-integers", i32 1}
27+
28+
; CHECK: define internal void @__llvm_gcov_writeout()
29+
; CHECK-SAME: !kcfi_type ![[#TYPE:]]
30+
; CHECK: define internal void @__llvm_gcov_reset()
31+
; CHECK-SAME: !kcfi_type ![[#TYPE]]
32+
; CHECK: define internal void @__llvm_gcov_init()
33+
; CHECK-SAME: !kcfi_type ![[#TYPE]]
34+
35+
; CHECK: ![[#TYPE]] = !{i32 -440107680}

Diff for: llvm/test/Transforms/GCOVProfiling/kcfi.ll

+5-3
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,10 @@ entry:
2424
!9 = !{i32 4, !"kcfi", i32 1}
2525

2626
; CHECK: define internal void @__llvm_gcov_writeout()
27-
; CHECK-SAME: !kcfi_type
27+
; CHECK-SAME: !kcfi_type ![[#TYPE:]]
2828
; CHECK: define internal void @__llvm_gcov_reset()
29-
; CHECK-SAME: !kcfi_type
29+
; CHECK-SAME: !kcfi_type ![[#TYPE]]
3030
; CHECK: define internal void @__llvm_gcov_init()
31-
; CHECK-SAME: !kcfi_type
31+
; CHECK-SAME: !kcfi_type ![[#TYPE]]
32+
33+
; CHECK: ![[#TYPE]] = !{i32 -1522505972}

0 commit comments

Comments
 (0)