summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/CodeGen/CGExpr.cpp9
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.cpp42
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.h9
-rw-r--r--clang/lib/CodeGen/TargetInfo.cpp19
4 files changed, 60 insertions, 19 deletions
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 2b0086d22a7..193e4f122af 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -4409,10 +4409,7 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType, const CGCallee &OrigCallee
SanitizerScope SanScope(this);
llvm::Constant *FTRTTIConst =
CGM.GetAddrOfRTTIDescriptor(QualType(FnType, 0), /*ForEH=*/true);
- llvm::Type *PrefixStructTyElems[] = {
- PrefixSig->getType(),
- FTRTTIConst->getType()
- };
+ llvm::Type *PrefixStructTyElems[] = {PrefixSig->getType(), Int32Ty};
llvm::StructType *PrefixStructTy = llvm::StructType::get(
CGM.getLLVMContext(), PrefixStructTyElems, /*isPacked=*/true);
@@ -4433,8 +4430,10 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType, const CGCallee &OrigCallee
EmitBlock(TypeCheck);
llvm::Value *CalleeRTTIPtr =
Builder.CreateConstGEP2_32(PrefixStructTy, CalleePrefixStruct, 0, 1);
- llvm::Value *CalleeRTTI =
+ llvm::Value *CalleeRTTIEncoded =
Builder.CreateAlignedLoad(CalleeRTTIPtr, getPointerAlign());
+ llvm::Value *CalleeRTTI =
+ DecodeAddrUsedInPrologue(CalleePtr, CalleeRTTIEncoded);
llvm::Value *CalleeRTTIMatch =
Builder.CreateICmpEQ(CalleeRTTI, FTRTTIConst);
llvm::Constant *StaticData[] = {
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index a9a1a53be20..1c9fc367940 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -429,6 +429,43 @@ bool CodeGenFunction::ShouldXRayInstrumentFunction() const {
return CGM.getCodeGenOpts().XRayInstrumentFunctions;
}
+llvm::Constant *
+CodeGenFunction::EncodeAddrForUseInPrologue(llvm::Function *F,
+ llvm::Constant *Addr) {
+ // Addresses stored in prologue data can't require run-time fixups and must
+ // be PC-relative. Run-time fixups are undesirable because they necessitate
+ // writable text segments, which are unsafe. And absolute addresses are
+ // undesirable because they break PIE mode.
+
+ // Add a layer of indirection through a private global. Taking its address
+ // won't result in a run-time fixup, even if Addr has linkonce_odr linkage.
+ auto *GV = new llvm::GlobalVariable(CGM.getModule(), Addr->getType(),
+ /*isConstant=*/true,
+ llvm::GlobalValue::PrivateLinkage, Addr);
+
+ // Create a PC-relative address.
+ auto *GOTAsInt = llvm::ConstantExpr::getPtrToInt(GV, IntPtrTy);
+ auto *FuncAsInt = llvm::ConstantExpr::getPtrToInt(F, IntPtrTy);
+ auto *PCRelAsInt = llvm::ConstantExpr::getSub(GOTAsInt, FuncAsInt);
+ return (IntPtrTy == Int32Ty)
+ ? PCRelAsInt
+ : llvm::ConstantExpr::getTrunc(PCRelAsInt, Int32Ty);
+}
+
+llvm::Value *
+CodeGenFunction::DecodeAddrUsedInPrologue(llvm::Value *F,
+ llvm::Value *EncodedAddr) {
+ // Reconstruct the address of the global.
+ auto *PCRelAsInt = Builder.CreateSExt(EncodedAddr, IntPtrTy);
+ auto *FuncAsInt = Builder.CreatePtrToInt(F, IntPtrTy, "func_addr.int");
+ auto *GOTAsInt = Builder.CreateAdd(PCRelAsInt, FuncAsInt, "global_addr.int");
+ auto *GOTAddr = Builder.CreateIntToPtr(GOTAsInt, Int8PtrPtrTy, "global_addr");
+
+ // Load the original pointer through the global.
+ return Builder.CreateLoad(Address(GOTAddr, getPointerAlign()),
+ "decoded_addr");
+}
+
/// EmitFunctionInstrumentation - Emit LLVM code to call the specified
/// instrumentation function with the current function and the call site, if
/// function instrumentation is enabled.
@@ -856,7 +893,10 @@ void CodeGenFunction::StartFunction(GlobalDecl GD,
CGM.getTargetCodeGenInfo().getUBSanFunctionSignature(CGM)) {
llvm::Constant *FTRTTIConst =
CGM.GetAddrOfRTTIDescriptor(FD->getType(), /*ForEH=*/true);
- llvm::Constant *PrologueStructElems[] = { PrologueSig, FTRTTIConst };
+ llvm::Constant *FTRTTIConstEncoded =
+ EncodeAddrForUseInPrologue(Fn, FTRTTIConst);
+ llvm::Constant *PrologueStructElems[] = {PrologueSig,
+ FTRTTIConstEncoded};
llvm::Constant *PrologueStructConst =
llvm::ConstantStruct::getAnon(PrologueStructElems, /*Packed=*/true);
Fn->setPrologueData(PrologueStructConst);
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index a3b9beb2988..33bf74b5d39 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -1776,6 +1776,15 @@ public:
/// EmitMCountInstrumentation - Emit call to .mcount.
void EmitMCountInstrumentation();
+ /// Encode an address into a form suitable for use in a function prologue.
+ llvm::Constant *EncodeAddrForUseInPrologue(llvm::Function *F,
+ llvm::Constant *Addr);
+
+ /// Decode an address used in a function prologue, encoded by \c
+ /// EncodeAddrForUseInPrologue.
+ llvm::Value *DecodeAddrUsedInPrologue(llvm::Value *F,
+ llvm::Value *EncodedAddr);
+
/// EmitFunctionProlog - Emit the target specific LLVM code to load the
/// arguments for the given function. This is also responsible for naming the
/// LLVM function arguments.
diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp
index 10fa2ea322c..934e155ccdf 100644
--- a/clang/lib/CodeGen/TargetInfo.cpp
+++ b/clang/lib/CodeGen/TargetInfo.cpp
@@ -1086,8 +1086,8 @@ public:
getUBSanFunctionSignature(CodeGen::CodeGenModule &CGM) const override {
unsigned Sig = (0xeb << 0) | // jmp rel8
(0x06 << 8) | // .+0x08
- ('F' << 16) |
- ('T' << 24);
+ ('v' << 16) |
+ ('2' << 24);
return llvm::ConstantInt::get(CGM.Int32Ty, Sig);
}
@@ -2277,17 +2277,10 @@ public:
llvm::Constant *
getUBSanFunctionSignature(CodeGen::CodeGenModule &CGM) const override {
- unsigned Sig;
- if (getABIInfo().has64BitPointers())
- Sig = (0xeb << 0) | // jmp rel8
- (0x0a << 8) | // .+0x0c
- ('F' << 16) |
- ('T' << 24);
- else
- Sig = (0xeb << 0) | // jmp rel8
- (0x06 << 8) | // .+0x08
- ('F' << 16) |
- ('T' << 24);
+ unsigned Sig = (0xeb << 0) | // jmp rel8
+ (0x06 << 8) | // .+0x08
+ ('v' << 16) |
+ ('2' << 24);
return llvm::ConstantInt::get(CGM.Int32Ty, Sig);
}
OpenPOWER on IntegriCloud