From f7a0c7bf8bc8318ed28d889c9a56437ab3e91385 Mon Sep 17 00:00:00 2001 From: Eric Christopher Date: Tue, 6 Jul 2010 05:18:56 +0000 Subject: [PATCH] Fix up -fstack-protector on linux to use the segment registers. Split out testcases per architecture and os now. Patch from Nelson Elhage. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@107640 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Target/TargetLowering.h | 8 ++++++ lib/CodeGen/StackProtector.cpp | 17 +++++++++-- lib/Target/X86/X86ISelLowering.cpp | 21 ++++++++++++++ lib/Target/X86/X86ISelLowering.h | 6 ++++ test/CodeGen/PowerPC/stack-protector.ll | 25 +++++++++++++++++ test/CodeGen/X86/stack-protector-linux.ll | 28 +++++++++++++++++++ .../{Generic => X86}/stack-protector.ll | 8 +++--- 7 files changed, 107 insertions(+), 6 deletions(-) create mode 100644 test/CodeGen/PowerPC/stack-protector.ll create mode 100644 test/CodeGen/X86/stack-protector-linux.ll rename test/CodeGen/{Generic => X86}/stack-protector.ll (74%) diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h index eb048f6d9fa..497a025d534 100644 --- a/include/llvm/Target/TargetLowering.h +++ b/include/llvm/Target/TargetLowering.h @@ -749,6 +749,14 @@ public: /// getFunctionAlignment - Return the Log2 alignment of this function. virtual unsigned getFunctionAlignment(const Function *) const = 0; + /// getStackCookieLocation - Return true if the target stores stack + /// protector cookies at a fixed offset in some non-standard address + /// space, and populates the address space and offset as + /// appropriate. + virtual bool getStackCookieLocation(unsigned &AddressSpace, unsigned &Offset) const { + return false; + } + //===--------------------------------------------------------------------===// // TargetLowering Optimization Methods // diff --git a/lib/CodeGen/StackProtector.cpp b/lib/CodeGen/StackProtector.cpp index 8a6a727a1f9..e318afe2b55 100644 --- a/lib/CodeGen/StackProtector.cpp +++ b/lib/CodeGen/StackProtector.cpp @@ -136,7 +136,7 @@ bool StackProtector::RequiresStackProtector() const { bool StackProtector::InsertStackProtectors() { BasicBlock *FailBB = 0; // The basic block to jump to if check fails. AllocaInst *AI = 0; // Place on stack that stores the stack guard. - Constant *StackGuardVar = 0; // The stack guard variable. + Value *StackGuardVar = 0; // The stack guard variable. for (Function::iterator I = F->begin(), E = F->end(); I != E; ) { BasicBlock *BB = I++; @@ -155,7 +155,20 @@ bool StackProtector::InsertStackProtectors() { // PointerType *PtrTy = PointerType::getUnqual( Type::getInt8Ty(RI->getContext())); - StackGuardVar = M->getOrInsertGlobal("__stack_chk_guard", PtrTy); + + unsigned AddressSpace, Offset; + if (TLI->getStackCookieLocation(AddressSpace, Offset)) { + Constant *ASPtr = Constant::getNullValue( + PointerType::get(Type::getInt8Ty(RI->getContext()), AddressSpace)); + APInt OffsetInt(32, Offset); + Constant *OffsetVal = Constant::getIntegerValue( + Type::getInt32Ty(RI->getContext()), OffsetInt); + StackGuardVar = ConstantExpr::getPointerCast( + ConstantExpr::getGetElementPtr(ASPtr, &OffsetVal, 1), + PointerType::get(PtrTy, AddressSpace)); + } else { + StackGuardVar = M->getOrInsertGlobal("__stack_chk_guard", PtrTy); + } BasicBlock &Entry = F->getEntryBlock(); Instruction *InsPt = &Entry.front(); diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 423a076e7d0..8a0a04ee22e 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -1189,6 +1189,27 @@ unsigned X86TargetLowering::getFunctionAlignment(const Function *F) const { return F->hasFnAttr(Attribute::OptimizeForSize) ? 0 : 4; } +bool X86TargetLowering::getStackCookieLocation(unsigned &AddressSpace, + unsigned &Offset) const { + if (!Subtarget->isTargetLinux()) + return false; + + if (Subtarget->is64Bit()) { + // %fs:0x28, unless we're using a Kernel code model, in which case it's %gs: + Offset = 0x28; + if (getTargetMachine().getCodeModel() == CodeModel::Kernel) + AddressSpace = 256; + else + AddressSpace = 257; + } else { + // %gs:0x14 on i386 + Offset = 0x14; + AddressSpace = 256; + } + return true; +} + + //===----------------------------------------------------------------------===// // Return Value Calling Convention Implementation //===----------------------------------------------------------------------===// diff --git a/lib/Target/X86/X86ISelLowering.h b/lib/Target/X86/X86ISelLowering.h index a7de0b1166c..82cef27a63d 100644 --- a/lib/Target/X86/X86ISelLowering.h +++ b/lib/Target/X86/X86ISelLowering.h @@ -593,6 +593,12 @@ namespace llvm { /// getFunctionAlignment - Return the Log2 alignment of this function. virtual unsigned getFunctionAlignment(const Function *F) const; + /// getStackCookieLocation - Return true if the target stores stack + /// protector cookies at a fixed offset in some non-standard address + /// space, and populates the address space and offset as + /// appropriate. + virtual bool getStackCookieLocation(unsigned &AddressSpace, unsigned &Offset) const; + private: /// Subtarget - Keep a pointer to the X86Subtarget around so that we can /// make the right decision when generating code for different targets. diff --git a/test/CodeGen/PowerPC/stack-protector.ll b/test/CodeGen/PowerPC/stack-protector.ll new file mode 100644 index 00000000000..20203612502 --- /dev/null +++ b/test/CodeGen/PowerPC/stack-protector.ll @@ -0,0 +1,25 @@ +; RUN: llc -march=ppc32 < %s -o - | grep {__stack_chk_guard} +; RUN: llc -march=ppc32 < %s -o - | grep {__stack_chk_fail} + +@"\01LC" = internal constant [11 x i8] c"buf == %s\0A\00" ; <[11 x i8]*> [#uses=1] + +define void @test(i8* %a) nounwind ssp { +entry: + %a_addr = alloca i8* ; [#uses=2] + %buf = alloca [8 x i8] ; <[8 x i8]*> [#uses=2] + %"alloca point" = bitcast i32 0 to i32 ; [#uses=0] + store i8* %a, i8** %a_addr + %buf1 = bitcast [8 x i8]* %buf to i8* ; [#uses=1] + %0 = load i8** %a_addr, align 4 ; [#uses=1] + %1 = call i8* @strcpy(i8* %buf1, i8* %0) nounwind ; [#uses=0] + %buf2 = bitcast [8 x i8]* %buf to i8* ; [#uses=1] + %2 = call i32 (i8*, ...)* @printf(i8* getelementptr ([11 x i8]* @"\01LC", i32 0, i32 0), i8* %buf2) nounwind ; [#uses=0] + br label %return + +return: ; preds = %entry + ret void +} + +declare i8* @strcpy(i8*, i8*) nounwind + +declare i32 @printf(i8*, ...) nounwind diff --git a/test/CodeGen/X86/stack-protector-linux.ll b/test/CodeGen/X86/stack-protector-linux.ll new file mode 100644 index 00000000000..fe2a9c5d57a --- /dev/null +++ b/test/CodeGen/X86/stack-protector-linux.ll @@ -0,0 +1,28 @@ +; RUN: llc -mtriple=i386-pc-linux-gnu < %s -o - | grep %gs: +; RUN: llc -mtriple=x86_64-pc-linux-gnu < %s -o - | grep %fs: +; RUN: llc -code-model=kernel -mtriple=x86_64-pc-linux-gnu < %s -o - | grep %gs: +; RUN: llc -mtriple=x86_64-apple-darwin < %s -o - | grep {__stack_chk_guard} +; RUN: llc -mtriple=x86_64-apple-darwin < %s -o - | grep {__stack_chk_fail} + +@"\01LC" = internal constant [11 x i8] c"buf == %s\0A\00" ; <[11 x i8]*> [#uses=1] + +define void @test(i8* %a) nounwind ssp { +entry: + %a_addr = alloca i8* ; [#uses=2] + %buf = alloca [8 x i8] ; <[8 x i8]*> [#uses=2] + %"alloca point" = bitcast i32 0 to i32 ; [#uses=0] + store i8* %a, i8** %a_addr + %buf1 = bitcast [8 x i8]* %buf to i8* ; [#uses=1] + %0 = load i8** %a_addr, align 4 ; [#uses=1] + %1 = call i8* @strcpy(i8* %buf1, i8* %0) nounwind ; [#uses=0] + %buf2 = bitcast [8 x i8]* %buf to i8* ; [#uses=1] + %2 = call i32 (i8*, ...)* @printf(i8* getelementptr ([11 x i8]* @"\01LC", i32 0, i32 0), i8* %buf2) nounwind ; [#uses=0] + br label %return + +return: ; preds = %entry + ret void +} + +declare i8* @strcpy(i8*, i8*) nounwind + +declare i32 @printf(i8*, ...) nounwind diff --git a/test/CodeGen/Generic/stack-protector.ll b/test/CodeGen/X86/stack-protector.ll similarity index 74% rename from test/CodeGen/Generic/stack-protector.ll rename to test/CodeGen/X86/stack-protector.ll index a59c649781d..f0fc4ddbd65 100644 --- a/test/CodeGen/Generic/stack-protector.ll +++ b/test/CodeGen/X86/stack-protector.ll @@ -1,5 +1,5 @@ -; RUN: llc < %s -o - | grep {__stack_chk_guard} -; RUN: llc < %s -o - | grep {__stack_chk_fail} +; RUN: llc -march=x86 < %s -o - | grep {__stack_chk_guard} +; RUN: llc -march=x86 < %s -o - | grep {__stack_chk_fail} @"\01LC" = internal constant [11 x i8] c"buf == %s\0A\00" ; <[11 x i8]*> [#uses=1] @@ -7,12 +7,12 @@ define void @test(i8* %a) nounwind ssp { entry: %a_addr = alloca i8* ; [#uses=2] %buf = alloca [8 x i8] ; <[8 x i8]*> [#uses=2] - %"alloca point" = bitcast i32 0 to i32 ; [#uses=0] + %"alloca point" = bitcast i32 0 to i32 ; [#uses=0] store i8* %a, i8** %a_addr %buf1 = bitcast [8 x i8]* %buf to i8* ; [#uses=1] %0 = load i8** %a_addr, align 4 ; [#uses=1] %1 = call i8* @strcpy(i8* %buf1, i8* %0) nounwind ; [#uses=0] - %buf2 = bitcast [8 x i8]* %buf to i8* ; [#uses=1] + %buf2 = bitcast [8 x i8]* %buf to i8* ; [#uses=1] %2 = call i32 (i8*, ...)* @printf(i8* getelementptr ([11 x i8]* @"\01LC", i32 0, i32 0), i8* %buf2) nounwind ; [#uses=0] br label %return