48
48
#include "clang/CodeGen/ConstantInitBuilder.h"
49
49
#include "clang/Frontend/FrontendDiagnostic.h"
50
50
#include "llvm/ADT/STLExtras.h"
51
+
#include "llvm/ADT/StringExtras.h"
51
52
#include "llvm/ADT/StringSwitch.h"
52
53
#include "llvm/ADT/Triple.h"
53
54
#include "llvm/Analysis/TargetLibraryInfo.h"
67
68
#include "llvm/Support/MD5.h"
68
69
#include "llvm/Support/TimeProfiler.h"
69
70
#include "llvm/Support/X86TargetParser.h"
71
+
#include "llvm/Support/xxhash.h"
70
72
71
73
using namespace clang;
72
74
using namespace CodeGen;
@@ -577,6 +579,8 @@ void CodeGenModule::Release() {
577
579
CodeGenFunction(*this).EmitCfiCheckFail();
578
580
CodeGenFunction(*this).EmitCfiCheckStub();
579
581
}
582
+
if (LangOpts.Sanitize.has(SanitizerKind::KCFI))
583
+
finalizeKCFITypes();
580
584
emitAtAvailableLinkGuard();
581
585
if (Context.getTargetInfo().getTriple().isWasm())
582
586
EmitMainVoidAlias();
@@ -759,6 +763,9 @@ void CodeGenModule::Release() {
759
763
CodeGenOpts.SanitizeCfiCanonicalJumpTables);
760
764
}
761
765
766
+
if (LangOpts.Sanitize.has(SanitizerKind::KCFI))
767
+
getModule().addModuleFlag(llvm::Module::Override, "kcfi", 1);
768
+
762
769
if (CodeGenOpts.CFProtectionReturn &&
763
770
Target.checkCFProtectionReturnSupported(getDiags())) {
764
771
// Indicate that we want to instrument return control flow protection.
@@ -1669,6 +1676,20 @@ llvm::ConstantInt *CodeGenModule::CreateCrossDsoCfiTypeId(llvm::Metadata *MD) {
1669
1676
return llvm::ConstantInt::get(Int64Ty, llvm::MD5Hash(MDS->getString()));
1670
1677
}
1671
1678
1679
+
llvm::ConstantInt *CodeGenModule::CreateKCFITypeId(QualType T) {
1680
+
if (auto *FnType = T->getAs<FunctionProtoType>())
1681
+
T = getContext().getFunctionType(
1682
+
FnType->getReturnType(), FnType->getParamTypes(),
1683
+
FnType->getExtProtoInfo().withExceptionSpec(EST_None));
1684
+
1685
+
std::string OutName;
1686
+
llvm::raw_string_ostream Out(OutName);
1687
+
getCXXABI().getMangleContext().mangleTypeName(T, Out);
1688
+
1689
+
return llvm::ConstantInt::get(Int32Ty,
1690
+
static_cast<uint32_t>(llvm::xxHash64(OutName)));
1691
+
}
1692
+
1672
1693
void CodeGenModule::SetLLVMFunctionAttributes(GlobalDecl GD,
1673
1694
const CGFunctionInfo &Info,
1674
1695
llvm::Function *F, bool IsThunk) {
@@ -2287,6 +2308,57 @@ void CodeGenModule::CreateFunctionTypeMetadataForIcall(const FunctionDecl *FD,
2287
2308
F->addTypeMetadata(0, llvm::ConstantAsMetadata::get(CrossDsoTypeId));
2288
2309
}
2289
2310
2311
+
void CodeGenModule::setKCFIType(const FunctionDecl *FD, llvm::Function *F) {
2312
+
if (isa<CXXMethodDecl>(FD) && !cast<CXXMethodDecl>(FD)->isStatic())
2313
+
return;
2314
+
2315
+
llvm::LLVMContext &Ctx = F->getContext();
2316
+
llvm::MDBuilder MDB(Ctx);
2317
+
F->setMetadata(llvm::LLVMContext::MD_kcfi_type,
2318
+
llvm::MDNode::get(
2319
+
Ctx, MDB.createConstant(CreateKCFITypeId(FD->getType()))));
2320
+
}
2321
+
2322
+
static bool allowKCFIIdentifier(StringRef Name) {
2323
+
// KCFI type identifier constants are only necessary for external assembly
2324
+
// functions, which means it's safe to skip unusual names. Subset of
2325
+
// MCAsmInfo::isAcceptableChar() and MCAsmInfoXCOFF::isAcceptableChar().
2326
+
return llvm::all_of(Name, [](const char &C) {
2327
+
return llvm::isAlnum(C) || C == '_' || C == '.';
2328
+
});
2329
+
}
2330
+
2331
+
void CodeGenModule::finalizeKCFITypes() {
2332
+
llvm::Module &M = getModule();
2333
+
for (auto &F : M.functions()) {
2334
+
// Remove KCFI type metadata from non-address-taken local functions.
2335
+
bool AddressTaken = F.hasAddressTaken();
2336
+
if (!AddressTaken && F.hasLocalLinkage())
2337
+
F.eraseMetadata(llvm::LLVMContext::MD_kcfi_type);
2338
+
2339
+
// Generate a constant with the expected KCFI type identifier for all
2340
+
// address-taken function declarations to support annotating indirectly
2341
+
// called assembly functions.
2342
+
if (!AddressTaken || !F.isDeclaration())
2343
+
continue;
2344
+
2345
+
const llvm::ConstantInt *Type;
2346
+
if (const llvm::MDNode *MD = F.getMetadata(llvm::LLVMContext::MD_kcfi_type))
2347
+
Type = llvm::mdconst::extract<llvm::ConstantInt>(MD->getOperand(0));
2348
+
else
2349
+
continue;
2350
+
2351
+
StringRef Name = F.getName();
2352
+
if (!allowKCFIIdentifier(Name))
2353
+
continue;
2354
+
2355
+
std::string Asm = (".weak __kcfi_typeid_" + Name + "\n.set __kcfi_typeid_" +
2356
+
Name + ", " + Twine(Type->getZExtValue()) + "\n")
2357
+
.str();
2358
+
M.appendModuleInlineAsm(Asm);
2359
+
}
2360
+
}
2361
+
2290
2362
void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, llvm::Function *F,
2291
2363
bool IsIncompleteFunction,
2292
2364
bool IsThunk) {
@@ -2369,6 +2441,9 @@ void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, llvm::Function *F,
2369
2441
!CodeGenOpts.SanitizeCfiCanonicalJumpTables)
2370
2442
CreateFunctionTypeMetadataForIcall(FD, F);
2371
2443
2444
+
if (LangOpts.Sanitize.has(SanitizerKind::KCFI))
2445
+
setKCFIType(FD, F);
2446
+
2372
2447
if (getLangOpts().OpenMP && FD->hasAttr<OMPDeclareSimdDeclAttr>())
2373
2448
getOpenMPRuntime().emitDeclareSimdFunction(FD, F);
2374
2449
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4