Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions clang/lib/CodeGen/CGExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6496,11 +6496,8 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType,
SanitizerDebugLocation SanScope(this, {CheckOrdinal}, CheckHandler);
EmitSanitizerStatReport(llvm::SanStat_CFI_ICall);

llvm::Metadata *MD;
if (CGM.getCodeGenOpts().SanitizeCfiICallGeneralizePointers)
MD = CGM.CreateMetadataIdentifierGeneralized(QualType(FnType, 0));
else
MD = CGM.CreateMetadataIdentifierForType(QualType(FnType, 0));
llvm::Metadata *MD =
CGM.CreateMetadataIdentifierForFnType(QualType(FnType, 0));

llvm::Value *TypeId = llvm::MetadataAsValue::get(getLLVMContext(), MD);

Expand Down
46 changes: 33 additions & 13 deletions clang/lib/CodeGen/CodeGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2343,8 +2343,11 @@ llvm::ConstantInt *CodeGenModule::CreateCrossDsoCfiTypeId(llvm::Metadata *MD) {
// originally pointed-to type, e.g. 'const char *' and 'char * const *'
// generalize to 'const void *' while 'char *' and 'const char **' generalize to
// 'void *'.
static QualType GeneralizeType(ASTContext &Ctx, QualType Ty) {
if (!Ty->isPointerType())
static QualType GeneralizeType(ASTContext &Ctx, QualType Ty,
bool GeneralizePointers) {
// TODO: Add other generalizations.

if (!GeneralizePointers || !Ty->isPointerType())
return Ty;

return Ctx.getPointerType(
Expand All @@ -2353,26 +2356,29 @@ static QualType GeneralizeType(ASTContext &Ctx, QualType Ty) {
}

// Apply type generalization to a FunctionType's return and argument types
static QualType GeneralizeFunctionType(ASTContext &Ctx, QualType Ty) {
static QualType GeneralizeFunctionType(ASTContext &Ctx, QualType Ty,
bool GeneralizePointers) {
if (auto *FnType = Ty->getAs<FunctionProtoType>()) {
SmallVector<QualType, 8> GeneralizedParams;
for (auto &Param : FnType->param_types())
GeneralizedParams.push_back(GeneralizeType(Ctx, Param));
GeneralizedParams.push_back(
GeneralizeType(Ctx, Param, GeneralizePointers));

return Ctx.getFunctionType(GeneralizeType(Ctx, FnType->getReturnType()),
GeneralizedParams, FnType->getExtProtoInfo());
return Ctx.getFunctionType(
GeneralizeType(Ctx, FnType->getReturnType(), GeneralizePointers),
GeneralizedParams, FnType->getExtProtoInfo());
}

if (auto *FnType = Ty->getAs<FunctionNoProtoType>())
return Ctx.getFunctionNoProtoType(
GeneralizeType(Ctx, FnType->getReturnType()));
GeneralizeType(Ctx, FnType->getReturnType(), GeneralizePointers));

llvm_unreachable("Encountered unknown FunctionType");
}

llvm::ConstantInt *CodeGenModule::CreateKCFITypeId(QualType T, StringRef Salt) {
if (getCodeGenOpts().SanitizeCfiICallGeneralizePointers)
T = GeneralizeFunctionType(getContext(), T);
T = GeneralizeFunctionType(
getContext(), T, getCodeGenOpts().SanitizeCfiICallGeneralizePointers);
if (auto *FnType = T->getAs<FunctionProtoType>())
T = getContext().getFunctionType(
FnType->getReturnType(), FnType->getParamTypes(),
Expand Down Expand Up @@ -3041,9 +3047,14 @@ void CodeGenModule::createFunctionTypeMetadataForIcall(const FunctionDecl *FD,
if (isa<CXXMethodDecl>(FD) && !cast<CXXMethodDecl>(FD)->isStatic())
return;

llvm::Metadata *MD = CreateMetadataIdentifierForType(FD->getType());
QualType FnType = GeneralizeFunctionType(getContext(), FD->getType(),
/*GeneralizePointers=*/false);
llvm::Metadata *MD = CreateMetadataIdentifierForType(FnType);
F->addTypeMetadata(0, MD);
F->addTypeMetadata(0, CreateMetadataIdentifierGeneralized(FD->getType()));

QualType GenPtrFnType = GeneralizeFunctionType(getContext(), FD->getType(),
/*GeneralizePointers=*/true);
F->addTypeMetadata(0, CreateMetadataIdentifierGeneralized(GenPtrFnType));

// Emit a hash-based bit set entry for cross-DSO calls.
if (CodeGenOpts.SanitizeCfiCrossDso)
Expand Down Expand Up @@ -7934,6 +7945,15 @@ CodeGenModule::CreateMetadataIdentifierImpl(QualType T, MetadataTypeMap &Map,
return InternalId;
}

llvm::Metadata *CodeGenModule::CreateMetadataIdentifierForFnType(QualType T) {
assert(isa<FunctionType>(T));
T = GeneralizeFunctionType(
getContext(), T, getCodeGenOpts().SanitizeCfiICallGeneralizePointers);
if (getCodeGenOpts().SanitizeCfiICallGeneralizePointers)
return CreateMetadataIdentifierGeneralized(T);
return CreateMetadataIdentifierForType(T);
}

llvm::Metadata *CodeGenModule::CreateMetadataIdentifierForType(QualType T) {
return CreateMetadataIdentifierImpl(T, MetadataIdMap, "");
}
Expand All @@ -7944,8 +7964,8 @@ CodeGenModule::CreateMetadataIdentifierForVirtualMemPtrType(QualType T) {
}

llvm::Metadata *CodeGenModule::CreateMetadataIdentifierGeneralized(QualType T) {
return CreateMetadataIdentifierImpl(GeneralizeFunctionType(getContext(), T),
GeneralizedMetadataIdMap, ".generalized");
return CreateMetadataIdentifierImpl(T, GeneralizedMetadataIdMap,
".generalized");
}

/// Returns whether this module needs the "all-vtables" type identifier.
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/CodeGen/CodeGenModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -1623,6 +1623,9 @@ class CodeGenModule : public CodeGenTypeCache {
/// Generate a KCFI type identifier for T.
llvm::ConstantInt *CreateKCFITypeId(QualType T, StringRef Salt);

/// Create a metadata identifier for the given function type.
llvm::Metadata *CreateMetadataIdentifierForFnType(QualType T);

/// Create a metadata identifier for the given type. This may either be an
/// MDString (for external identifiers) or a distinct unnamed MDNode (for
/// internal identifiers).
Expand Down
16 changes: 16 additions & 0 deletions clang/test/CodeGen/cfi-icall-generalize.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,21 @@ void g(int** (*fp)(const char *, const char **)) {
fp(0, 0);
}

union Union {
char *c;
long* n;
} __attribute__((transparent_union));

// CHECK: define{{.*}} void @uni({{.*}} !type [[TYPE2:![0-9]+]] !type [[TYPE2_GENERALIZED:![0-9]+]]
void uni(void (*fn)(union Union), union Union arg1) {
// UNGENERALIZED: call i1 @llvm.type.test(ptr {{.*}}, metadata !"_ZTSFv5UnionE")
// GENERALIZED: call i1 @llvm.type.test(ptr {{.*}}, metadata !"_ZTSFv5UnionE.generalized")
fn(arg1);
}

// CHECK: [[TYPE]] = !{i64 0, !"_ZTSFPPiPKcPS2_E"}
// CHECK: [[TYPE_GENERALIZED]] = !{i64 0, !"_ZTSFPvPKvS_E.generalized"}

// CHECK: [[TYPE2]] = !{i64 0, !"_ZTSFvPFv5UnionES_E"}
// CHECK: [[TYPE2_GENERALIZED]] = !{i64 0, !"_ZTSFvPv5UnionE.generalized"}

14 changes: 14 additions & 0 deletions clang/test/CodeGen/cfi-icall-normalize2.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,20 @@ void baz(void (*fn)(int, int, int), int arg1, int arg2, int arg3) {
fn(arg1, arg2, arg3);
}

union Union {
char *c;
long* n;
} __attribute__((transparent_union));

void uni(void (*fn)(union Union), union Union arg1) {
// CHECK-LABEL: define{{.*}}uni
// CHECK-SAME: {{.*}}!type ![[TYPE4:[0-9]+]] !type !{{[0-9]+}}
// CHECK: call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%0}}, metadata !"_ZTSFv5UnionE.normalized")
fn(arg1);
}

// CHECK: ![[TYPE1]] = !{i64 0, !"_ZTSFvPFvu3i32ES_E.normalized"}
// CHECK: ![[TYPE2]] = !{i64 0, !"_ZTSFvPFvu3i32S_ES_S_E.normalized"}
// CHECK: ![[TYPE3]] = !{i64 0, !"_ZTSFvPFvu3i32S_S_ES_S_S_E.normalized"}
// CHECK: ![[TYPE4]] = !{i64 0, !"_ZTSFvPFv5UnionES_E.normalized"}

16 changes: 16 additions & 0 deletions clang/test/CodeGen/kcfi-generalize.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,24 @@ void g(int** (*fp)(const char *, const char **)) {
fp(0, 0);
}

union Union {
char *c;
long* n;
} __attribute__((transparent_union));

// CHECK: define{{.*}} void @uni({{.*}} !kcfi_type [[TYPE2:![0-9]+]]
void uni(void (*fn)(union Union), union Union arg1) {
// UNGENERALIZED: call {{.*}} [ "kcfi"(i32 -1037059548) ]
// GENERALIZED: call {{.*}} [ "kcfi"(i32 422130955) ]
fn(arg1);
}

// UNGENERALIZED: [[TYPE]] = !{i32 1296635908}
// GENERALIZED: [[TYPE]] = !{i32 -49168686}

// UNGENERALIZED: [[TYPE3]] = !{i32 874141567}
// GENERALIZED: [[TYPE3]] = !{i32 954385378}

// UNGENERALIZED: [[TYPE2]] = !{i32 981319178}
// GENERALIZED: [[TYPE2]] = !{i32 -1599950473}

14 changes: 14 additions & 0 deletions clang/test/CodeGen/kcfi-normalize.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,21 @@ void baz(void (*fn)(int, int, int), int arg1, int arg2, int arg3) {
fn(arg1, arg2, arg3);
}

union Union {
char *c;
long* n;
} __attribute__((transparent_union));

void uni(void (*fn)(union Union), union Union arg1) {
// CHECK-LABEL: define{{.*}}uni
// CHECK-SAME: {{.*}}!kcfi_type ![[TYPE4:[0-9]+]]
// CHECK: call void %0(ptr %1) [ "kcfi"(i32 -1430221633) ]
fn(arg1);
}

// CHECK: ![[#]] = !{i32 4, !"cfi-normalize-integers", i32 1}
// CHECK: ![[TYPE1]] = !{i32 -1143117868}
// CHECK: ![[TYPE2]] = !{i32 -460921415}
// CHECK: ![[TYPE3]] = !{i32 -333839615}
// CHECK: ![[TYPE4]] = !{i32 1766237188}

Loading