diff --git a/llvm/lib/Transforms/Utils/ModuleUtils.cpp b/llvm/lib/Transforms/Utils/ModuleUtils.cpp --- a/llvm/lib/Transforms/Utils/ModuleUtils.cpp +++ b/llvm/lib/Transforms/Utils/ModuleUtils.cpp @@ -15,8 +15,10 @@ #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Function.h" #include "llvm/IR/IRBuilder.h" +#include "llvm/IR/MDBuilder.h" #include "llvm/IR/Module.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Support/xxhash.h" using namespace llvm; #define DEBUG_TYPE "moduleutils" @@ -112,6 +114,19 @@ appendToUsedList(M, "llvm.compiler.used", Values); } +static void setKCFIType(Module &M, Function &F, StringRef MangledType) { + if (!M.getModuleFlag("kcfi")) + return; + // Matches CodeGenModule::CreateKCFITypeId in Clang. + LLVMContext &Ctx = M.getContext(); + MDBuilder MDB(Ctx); + F.setMetadata( + LLVMContext::MD_kcfi_type, + MDNode::get(Ctx, MDB.createConstant(ConstantInt::get( + Type::getInt32Ty(Ctx), + static_cast(xxHash64(MangledType)))))); +} + FunctionCallee llvm::declareSanitizerInitFunction(Module &M, StringRef InitName, ArrayRef InitArgTypes) { @@ -128,6 +143,7 @@ GlobalValue::InternalLinkage, M.getDataLayout().getProgramAddressSpace(), CtorName, &M); Ctor->addFnAttr(Attribute::NoUnwind); + setKCFIType(M, *Ctor, "_ZTSFvvE"); // void (*)(void) BasicBlock *CtorBB = BasicBlock::Create(M.getContext(), "", Ctor); ReturnInst::Create(M.getContext(), CtorBB); // Ensure Ctor cannot be discarded, even if in a comdat. diff --git a/llvm/test/Instrumentation/AddressSanitizer/kcfi.ll b/llvm/test/Instrumentation/AddressSanitizer/kcfi.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Instrumentation/AddressSanitizer/kcfi.ll @@ -0,0 +1,11 @@ +;; Test that we emit kcfi_type metadata for asan.module_ctor with KCFI. + +; RUN: opt < %s -passes=asan -S | FileCheck %s + +; CHECK: @llvm.global_ctors = {{.*}}{ i32 1, ptr @asan.module_ctor, ptr @asan.module_ctor } + +; CHECK: define internal void @asan.module_ctor() +; CHECK-SAME: !kcfi_type + +!llvm.module.flags = !{!0} +!0 = !{i32 4, !"kcfi", i32 1}