summaryrefslogtreecommitdiffstats
path: root/lib/CodeGen/CodeGenModule.cpp
diff options
context:
space:
mode:
authorVlad Tsyrklevich <vlad@tsyrklevich.net>2017-10-31 22:39:44 +0000
committerVlad Tsyrklevich <vlad@tsyrklevich.net>2017-10-31 22:39:44 +0000
commit746fd88cc65883572b7602dc7b1f9e74462fd451 (patch)
tree0df935811a2170ba214956d0d703276504999c5f /lib/CodeGen/CodeGenModule.cpp
parenta934273b7cd28c48745e4c5a122ca3a505ab2028 (diff)
[CFI] Add CFI-icall pointer type generalization
Summary: This change allows generalizing pointers in type signatures used for cfi-icall by enabling the -fsanitize-cfi-icall-generalize-pointers flag. This works by 1) emitting an additional generalized type signature metadata node for functions and 2) llvm.type.test()ing for the generalized type for translation units with the flag specified. This flag is incompatible with -fsanitize-cfi-cross-dso because it would require emitting twice as many type hashes which would increase artifact size. Reviewers: pcc, eugenis Reviewed By: pcc Subscribers: kcc Differential Revision: https://reviews.llvm.org/D39358 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@317044 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CodeGenModule.cpp')
-rw-r--r--lib/CodeGen/CodeGenModule.cpp55
1 files changed, 55 insertions, 0 deletions
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index 2254f3e70d..b2a18a03f2 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -1152,6 +1152,7 @@ void CodeGenModule::CreateFunctionTypeMetadata(const FunctionDecl *FD,
llvm::Metadata *MD = CreateMetadataIdentifierForType(FD->getType());
F->addTypeMetadata(0, MD);
+ F->addTypeMetadata(0, CreateMetadataIdentifierGeneralized(FD->getType()));
// Emit a hash-based bit set entry for cross-DSO calls.
if (CodeGenOpts.SanitizeCfiCrossDso)
@@ -4543,6 +4544,60 @@ llvm::Metadata *CodeGenModule::CreateMetadataIdentifierForType(QualType T) {
return InternalId;
}
+// Generalize pointer types to a void pointer with the qualifiers of the
+// 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())
+ return Ty;
+
+ return Ctx.getPointerType(
+ QualType(Ctx.VoidTy).withCVRQualifiers(
+ Ty->getPointeeType().getCVRQualifiers()));
+}
+
+// Apply type generalization to a FunctionType's return and argument types
+static QualType GeneralizeFunctionType(ASTContext &Ctx, QualType Ty) {
+ if (auto *FnType = Ty->getAs<FunctionProtoType>()) {
+ SmallVector<QualType, 8> GeneralizedParams;
+ for (auto &Param : FnType->param_types())
+ GeneralizedParams.push_back(GeneralizeType(Ctx, Param));
+
+ return Ctx.getFunctionType(
+ GeneralizeType(Ctx, FnType->getReturnType()),
+ GeneralizedParams, FnType->getExtProtoInfo());
+ }
+
+ if (auto *FnType = Ty->getAs<FunctionNoProtoType>())
+ return Ctx.getFunctionNoProtoType(
+ GeneralizeType(Ctx, FnType->getReturnType()));
+
+ llvm_unreachable("Encountered unknown FunctionType");
+}
+
+llvm::Metadata *CodeGenModule::CreateMetadataIdentifierGeneralized(QualType T) {
+ T = GeneralizeFunctionType(getContext(), T);
+
+ llvm::Metadata *&InternalId = GeneralizedMetadataIdMap[T.getCanonicalType()];
+ if (InternalId)
+ return InternalId;
+
+ if (isExternallyVisible(T->getLinkage())) {
+ std::string OutName;
+ llvm::raw_string_ostream Out(OutName);
+ getCXXABI().getMangleContext().mangleTypeName(T, Out);
+ Out << ".generalized";
+
+ InternalId = llvm::MDString::get(getLLVMContext(), Out.str());
+ } else {
+ InternalId = llvm::MDNode::getDistinct(getLLVMContext(),
+ llvm::ArrayRef<llvm::Metadata *>());
+ }
+
+ return InternalId;
+}
+
/// Returns whether this module needs the "all-vtables" type identifier.
bool CodeGenModule::NeedAllVtablesTypeId() const {
// Returns true if at least one of vtable-based CFI checkers is enabled and