Skip to content

Commit def7925

Browse files
samitolvanentru
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. (cherry picked from commit e1c36bd)
1 parent 4b322f6 commit def7925

File tree

5 files changed

+53
-8
lines changed

5 files changed

+53
-8
lines changed

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

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}

llvm/lib/Transforms/Utils/ModuleUtils.cpp

+7-5
Original file line numberDiff line numberDiff line change
@@ -161,11 +161,13 @@ void llvm::setKCFIType(Module &M, Function &F, StringRef MangledType) {
161161
// Matches CodeGenModule::CreateKCFITypeId in Clang.
162162
LLVMContext &Ctx = M.getContext();
163163
MDBuilder MDB(Ctx);
164-
F.setMetadata(
165-
LLVMContext::MD_kcfi_type,
166-
MDNode::get(Ctx, MDB.createConstant(ConstantInt::get(
167-
Type::getInt32Ty(Ctx),
168-
static_cast<uint32_t>(xxHash64(MangledType))))));
164+
std::string Type = MangledType.str();
165+
if (M.getModuleFlag("cfi-normalize-integers"))
166+
Type += ".normalized";
167+
F.setMetadata(LLVMContext::MD_kcfi_type,
168+
MDNode::get(Ctx, MDB.createConstant(ConstantInt::get(
169+
Type::getInt32Ty(Ctx),
170+
static_cast<uint32_t>(xxHash64(Type))))));
169171
// If the module was compiled with -fpatchable-function-entry, ensure
170172
// we use the same patchable-function-prefix.
171173
if (auto *MD = mdconst::extract_or_null<ConstantInt>(
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}

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)