From 753fcd644e903d6da3b27c2ae2159c3711b4618e Mon Sep 17 00:00:00 2001 From: Nick Desaulniers Date: Fri, 21 May 2021 15:53:21 -0700 Subject: [PATCH] [IR] make stack-protector-guard-* flags into module attrs D88631 added initial support for: - -mstack-protector-guard= - -mstack-protector-guard-reg= - -mstack-protector-guard-offset= flags, and D100919 extended these to AArch64. Unfortunately, these flags aren't retained for LTO. Make them module attributes rather than TargetOptions. Link: https://github.com/ClangBuiltLinux/linux/issues/1378 Reviewed By: tejohnson Differential Revision: https://reviews.llvm.org/D102742 --- include/llvm/CodeGen/CommandFlags.h | 7 -- include/llvm/IR/Module.h | 14 ++++ include/llvm/Target/TargetOptions.h | 12 --- lib/CodeGen/CommandFlags.cpp | 41 ---------- lib/CodeGen/StackProtector.cpp | 5 +- lib/IR/Module.cpp | 35 ++++++++ lib/Target/AArch64/AArch64InstrInfo.cpp | 8 +- lib/Target/X86/X86ISelLowering.cpp | 12 +-- test/CodeGen/AArch64/stack-guard-sysreg.ll | 82 +++++++++++-------- test/CodeGen/X86/stack-protector-3.ll | 44 ++++++++-- .../stack-protector-guard-module-attrs.ll | 77 +++++++++++++++++ 11 files changed, 225 insertions(+), 112 deletions(-) create mode 100644 test/Linker/stack-protector-guard-module-attrs.ll diff --git a/include/llvm/CodeGen/CommandFlags.h b/include/llvm/CodeGen/CommandFlags.h index f4555c34585..5a435175629 100644 --- a/include/llvm/CodeGen/CommandFlags.h +++ b/include/llvm/CodeGen/CommandFlags.h @@ -106,10 +106,6 @@ bool getXCOFFTracebackTable(); std::string getBBSections(); -std::string getStackProtectorGuard(); -int getStackProtectorGuardOffset(); -std::string getStackProtectorGuardReg(); - unsigned getTLSSize(); bool getEmulatedTLS(); @@ -150,9 +146,6 @@ struct RegisterCodeGenFlags { llvm::BasicBlockSection getBBSectionsMode(llvm::TargetOptions &Options); -llvm::StackProtectorGuards -getStackProtectorGuardMode(llvm::TargetOptions &Options); - /// Common utility function tightly tied to the options listed here. Initializes /// a TargetOptions object with CodeGen flags and returns it. /// \p TheTriple is used to determine the default value for options if diff --git a/include/llvm/IR/Module.h b/include/llvm/IR/Module.h index a71a4c06914..68e26c06453 100644 --- a/include/llvm/IR/Module.h +++ b/include/llvm/IR/Module.h @@ -895,6 +895,20 @@ public: FramePointerKind getFramePointer() const; void setFramePointer(FramePointerKind Kind); + /// Get/set what kind of stack protector guard to use. + StringRef getStackProtectorGuard() const; + void setStackProtectorGuard(StringRef Kind); + + /// Get/set which register to use as the stack protector guard register. The + /// empty string is equivalent to "global". Other values may be "tls" or + /// "sysreg". + StringRef getStackProtectorGuardReg() const; + void setStackProtectorGuardReg(StringRef Reg); + + /// Get/set what offset from the stack protector to use. + int getStackProtectorGuardOffset() const; + void setStackProtectorGuardOffset(int Offset); + /// @name Utility functions for querying and setting the build SDK version /// @{ diff --git a/include/llvm/Target/TargetOptions.h b/include/llvm/Target/TargetOptions.h index 61781b5a208..3b2290ab9ec 100644 --- a/include/llvm/Target/TargetOptions.h +++ b/include/llvm/Target/TargetOptions.h @@ -73,8 +73,6 @@ namespace llvm { None // Do not use Basic Block Sections. }; - enum class StackProtectorGuards { None, TLS, Global, SysReg }; - enum class EABI { Unknown, Default, // Default means not specified @@ -328,16 +326,6 @@ namespace llvm { /// By default, it is set to false. unsigned DebugStrictDwarf : 1; - /// Stack protector guard offset to use. - int StackProtectorGuardOffset = INT_MAX; - - /// Stack protector guard mode to use, e.g. tls, global, sysreg. - StackProtectorGuards StackProtectorGuard = - StackProtectorGuards::None; - - /// Stack protector guard reg to use, e.g. usually fs or gs in X86. - std::string StackProtectorGuardReg = "None"; - /// Name of the stack usage file (i.e., .su file) if user passes /// -fstack-usage. If empty, it can be implied that -fstack-usage is not /// passed on the command line. diff --git a/lib/CodeGen/CommandFlags.cpp b/lib/CodeGen/CommandFlags.cpp index 593a3303e10..a7f6ca4c69f 100644 --- a/lib/CodeGen/CommandFlags.cpp +++ b/lib/CodeGen/CommandFlags.cpp @@ -79,9 +79,6 @@ CGOPT_EXP(bool, FunctionSections) CGOPT(bool, IgnoreXCOFFVisibility) CGOPT(bool, XCOFFTracebackTable) CGOPT(std::string, BBSections) -CGOPT(std::string, StackProtectorGuard) -CGOPT(int, StackProtectorGuardOffset) -CGOPT(std::string, StackProtectorGuardReg) CGOPT(unsigned, TLSSize) CGOPT(bool, EmulatedTLS) CGOPT(bool, UniqueSectionNames) @@ -366,21 +363,6 @@ codegen::RegisterCodeGenFlags::RegisterCodeGenFlags() { cl::init("none")); CGBINDOPT(BBSections); - static cl::opt StackProtectorGuard( - "stack-protector-guard", cl::desc("Stack protector guard mode"), - cl::init("none")); - CGBINDOPT(StackProtectorGuard); - - static cl::opt StackProtectorGuardReg( - "stack-protector-guard-reg", cl::desc("Stack protector guard register"), - cl::init("none")); - CGBINDOPT(StackProtectorGuardReg); - - static cl::opt StackProtectorGuardOffset( - "stack-protector-guard-offset", cl::desc("Stack protector guard offset"), - cl::init(INT_MAX)); - CGBINDOPT(StackProtectorGuardOffset); - static cl::opt TLSSize( "tls-size", cl::desc("Bit size of immediate TLS offsets"), cl::init(0)); CGBINDOPT(TLSSize); @@ -502,26 +484,6 @@ codegen::getBBSectionsMode(llvm::TargetOptions &Options) { } } -llvm::StackProtectorGuards -codegen::getStackProtectorGuardMode(llvm::TargetOptions &Options) { - if (getStackProtectorGuard() == "tls") - return StackProtectorGuards::TLS; - if (getStackProtectorGuard() == "global") - return StackProtectorGuards::Global; - if (getStackProtectorGuard() == "sysreg") - return StackProtectorGuards::SysReg; - if (getStackProtectorGuard() != "none") { - ErrorOr> MBOrErr = - MemoryBuffer::getFile(getStackProtectorGuard()); - if (!MBOrErr) - errs() << "error illegal stack protector guard mode: " - << MBOrErr.getError().message() << "\n"; - else - Options.BBSectionsFuncListBuf = std::move(*MBOrErr); - } - return StackProtectorGuards::None; -} - // Common utility function tightly tied to the options listed here. Initializes // a TargetOptions object with CodeGen flags and returns it. TargetOptions @@ -558,9 +520,6 @@ codegen::InitTargetOptionsFromCodeGenFlags(const Triple &TheTriple) { Options.BBSections = getBBSectionsMode(Options); Options.UniqueSectionNames = getUniqueSectionNames(); Options.UniqueBasicBlockSectionNames = getUniqueBasicBlockSectionNames(); - Options.StackProtectorGuard = getStackProtectorGuardMode(Options); - Options.StackProtectorGuardOffset = getStackProtectorGuardOffset(); - Options.StackProtectorGuardReg = getStackProtectorGuardReg(); Options.TLSSize = getTLSSize(); Options.EmulatedTLS = getEmulatedTLS(); Options.ExplicitEmulatedTLS = EmulatedTLSView->getNumOccurrences() > 0; diff --git a/lib/CodeGen/StackProtector.cpp b/lib/CodeGen/StackProtector.cpp index ff6ff6dfe03..9f229d51b98 100644 --- a/lib/CodeGen/StackProtector.cpp +++ b/lib/CodeGen/StackProtector.cpp @@ -380,9 +380,8 @@ static Value *getStackGuard(const TargetLoweringBase *TLI, Module *M, IRBuilder<> &B, bool *SupportsSelectionDAGSP = nullptr) { Value *Guard = TLI->getIRStackGuard(B); - auto GuardMode = TLI->getTargetMachine().Options.StackProtectorGuard; - if ((GuardMode == llvm::StackProtectorGuards::TLS || - GuardMode == llvm::StackProtectorGuards::None) && Guard) + StringRef GuardMode = M->getStackProtectorGuard(); + if ((GuardMode == "tls" || GuardMode.empty()) && Guard) return B.CreateLoad(B.getInt8PtrTy(), Guard, true, "StackGuard"); // Use SelectionDAG SSP handling, since there isn't an IR guard. diff --git a/lib/IR/Module.cpp b/lib/IR/Module.cpp index 726ac6ab825..d38b2d1de24 100644 --- a/lib/IR/Module.cpp +++ b/lib/IR/Module.cpp @@ -686,6 +686,41 @@ void Module::setFramePointer(FramePointerKind Kind) { addModuleFlag(ModFlagBehavior::Max, "frame-pointer", static_cast(Kind)); } +StringRef Module::getStackProtectorGuard() const { + Metadata *MD = getModuleFlag("stack-protector-guard"); + if (auto *MDS = dyn_cast_or_null(MD)) + return MDS->getString(); + return {}; +} + +void Module::setStackProtectorGuard(StringRef Kind) { + MDString *ID = MDString::get(getContext(), Kind); + addModuleFlag(ModFlagBehavior::Error, "stack-protector-guard", ID); +} + +StringRef Module::getStackProtectorGuardReg() const { + Metadata *MD = getModuleFlag("stack-protector-guard-reg"); + if (auto *MDS = dyn_cast_or_null(MD)) + return MDS->getString(); + return {}; +} + +void Module::setStackProtectorGuardReg(StringRef Reg) { + MDString *ID = MDString::get(getContext(), Reg); + addModuleFlag(ModFlagBehavior::Error, "stack-protector-guard-reg", ID); +} + +int Module::getStackProtectorGuardOffset() const { + Metadata *MD = getModuleFlag("stack-protector-guard-offset"); + if (auto *CI = mdconst::dyn_extract_or_null(MD)) + return CI->getSExtValue(); + return INT_MAX; +} + +void Module::setStackProtectorGuardOffset(int Offset) { + addModuleFlag(ModFlagBehavior::Error, "stack-protector-guard-offset", Offset); +} + void Module::setSDKVersion(const VersionTuple &V) { SmallVector Entries; Entries.push_back(V.getMajor()); diff --git a/lib/Target/AArch64/AArch64InstrInfo.cpp b/lib/Target/AArch64/AArch64InstrInfo.cpp index 6fc4775200a..a8a0b6d375d 100644 --- a/lib/Target/AArch64/AArch64InstrInfo.cpp +++ b/lib/Target/AArch64/AArch64InstrInfo.cpp @@ -1904,10 +1904,10 @@ bool AArch64InstrInfo::expandPostRAPseudo(MachineInstr &MI) const { } Register Reg = MI.getOperand(0).getReg(); - TargetOptions Options = MI.getParent()->getParent()->getTarget().Options; - if (Options.StackProtectorGuard == StackProtectorGuards::SysReg) { + Module &M = *MBB.getParent()->getFunction().getParent(); + if (M.getStackProtectorGuard() == "sysreg") { const AArch64SysReg::SysReg *SrcReg = - AArch64SysReg::lookupSysRegByName(Options.StackProtectorGuardReg); + AArch64SysReg::lookupSysRegByName(M.getStackProtectorGuardReg()); if (!SrcReg) report_fatal_error("Unknown SysReg for Stack Protector Guard Register"); @@ -1915,7 +1915,7 @@ bool AArch64InstrInfo::expandPostRAPseudo(MachineInstr &MI) const { BuildMI(MBB, MI, DL, get(AArch64::MRS)) .addDef(Reg, RegState::Renamable) .addImm(SrcReg->Encoding); - int Offset = Options.StackProtectorGuardOffset; + int Offset = M.getStackProtectorGuardOffset(); if (Offset >= 0 && Offset <= 32760 && Offset % 8 == 0) { // ldr xN, [xN, #offset] BuildMI(MBB, MI, DL, get(AArch64::LDRXui)) diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index dbafc56e034..70bf79c1de6 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -2510,15 +2510,16 @@ Value *X86TargetLowering::getIRStackGuard(IRBuilder<> &IRB) const { return SegmentOffset(IRB, 0x10, getAddressSpace()); } else { unsigned AddressSpace = getAddressSpace(); + Module *M = IRB.GetInsertBlock()->getParent()->getParent(); // Specially, some users may customize the base reg and offset. - int Offset = getTargetMachine().Options.StackProtectorGuardOffset; + int Offset = M->getStackProtectorGuardOffset(); // If we don't set -stack-protector-guard-offset value: // %fs:0x28, unless we're using a Kernel code model, in which case // it's %gs:0x28. gs:0x14 on i386. if (Offset == INT_MAX) Offset = (Subtarget.is64Bit()) ? 0x28 : 0x14; - const auto &GuardReg = getTargetMachine().Options.StackProtectorGuardReg; + StringRef GuardReg = M->getStackProtectorGuardReg(); if (GuardReg == "fs") AddressSpace = X86AS::FS; else if (GuardReg == "gs") @@ -2548,12 +2549,11 @@ void X86TargetLowering::insertSSPDeclarations(Module &M) const { return; } - auto GuardMode = getTargetMachine().Options.StackProtectorGuard; + StringRef GuardMode = M.getStackProtectorGuard(); // glibc, bionic, and Fuchsia have a special slot for the stack guard. - if ((GuardMode == llvm::StackProtectorGuards::TLS || - GuardMode == llvm::StackProtectorGuards::None) - && hasStackGuardSlotTLS(Subtarget.getTargetTriple())) + if ((GuardMode == "tls" || GuardMode.empty()) && + hasStackGuardSlotTLS(Subtarget.getTargetTriple())) return; TargetLowering::insertSSPDeclarations(M); } diff --git a/test/CodeGen/AArch64/stack-guard-sysreg.ll b/test/CodeGen/AArch64/stack-guard-sysreg.ll index 4e5d1425a70..60b39282b15 100644 --- a/test/CodeGen/AArch64/stack-guard-sysreg.ll +++ b/test/CodeGen/AArch64/stack-guard-sysreg.ll @@ -1,46 +1,39 @@ -; RUN: llc %s --stack-protector-guard=sysreg \ -; RUN: --stack-protector-guard-reg=sp_el0 \ -; RUN: --stack-protector-guard-offset=0 -verify-machineinstrs -o - | \ +; RUN: split-file %s %t +; RUN: cat %t/main.ll %t/a.ll > %t/a2.ll +; RUN: cat %t/main.ll %t/b.ll > %t/b2.ll +; RUN: cat %t/main.ll %t/c.ll > %t/c2.ll +; RUN: cat %t/main.ll %t/d.ll > %t/d2.ll +; RUN: cat %t/main.ll %t/e.ll > %t/e2.ll +; RUN: cat %t/main.ll %t/f.ll > %t/f2.ll +; RUN: cat %t/main.ll %t/g.ll > %t/g2.ll +; RUN: cat %t/main.ll %t/h.ll > %t/h2.ll +; RUN: cat %t/main.ll %t/i.ll > %t/i2.ll +; RUN: cat %t/main.ll %t/j.ll > %t/j2.ll +; RUN: llc %t/a2.ll -verify-machineinstrs -o - | \ ; RUN: FileCheck --check-prefix=CHECK --check-prefix=CHECK-NO-OFFSET %s -; RUN: llc %s --stack-protector-guard=sysreg \ -; RUN: --stack-protector-guard-reg=sp_el0 \ -; RUN: --stack-protector-guard-offset=8 -verify-machineinstrs -o - | \ +; RUN: llc %t/b2.ll -verify-machineinstrs -o - | \ ; RUN: FileCheck --check-prefix=CHECK --check-prefix=CHECK-POSITIVE-OFFSET %s -; RUN: llc %s --stack-protector-guard=sysreg \ -; RUN: --stack-protector-guard-reg=sp_el0 \ -; RUN: --stack-protector-guard-offset=-8 -verify-machineinstrs -o - | \ +; RUN: llc %t/c2.ll -verify-machineinstrs -o - | \ ; RUN: FileCheck --check-prefix=CHECK --check-prefix=CHECK-NEGATIVE-OFFSET %s -; RUN: llc %s --stack-protector-guard=sysreg \ -; RUN: --stack-protector-guard-reg=sp_el0 \ -; RUN: --stack-protector-guard-offset=1 -verify-machineinstrs -o - | \ +; RUN: llc %t/d2.ll -verify-machineinstrs -o - | \ ; RUN: FileCheck --check-prefix=CHECK --check-prefix=CHECK-NPOT-OFFSET %s -; RUN: llc %s --stack-protector-guard=sysreg \ -; RUN: --stack-protector-guard-reg=sp_el0 \ -; RUN: --stack-protector-guard-offset=-1 -verify-machineinstrs -o - | \ +; RUN: llc %t/e2.ll -verify-machineinstrs -o - | \ ; RUN: FileCheck --check-prefix=CHECK --check-prefix=CHECK-NPOT-NEG-OFFSET %s -; RUN: llc %s --stack-protector-guard=sysreg \ -; RUN: --stack-protector-guard-reg=sp_el0 \ -; RUN: --stack-protector-guard-offset=257 -verify-machineinstrs -o - | \ +; RUN: llc %t/f2.ll -verify-machineinstrs -o - | \ ; RUN: FileCheck --check-prefix=CHECK --check-prefix=CHECK-257-OFFSET %s -; RUN: llc %s --stack-protector-guard=sysreg \ -; RUN: --stack-protector-guard-reg=sp_el0 \ -; RUN: --stack-protector-guard-offset=-257 -verify-machineinstrs -o - | \ +; RUN: llc %t/g2.ll -verify-machineinstrs -o - | \ ; RUN: FileCheck --check-prefix=CHECK --check-prefix=CHECK-MINUS-257-OFFSET %s ; XFAIL -; RUN: not --crash llc %s --stack-protector-guard=sysreg \ -; RUN: --stack-protector-guard-reg=sp_el0 \ -; RUN: --stack-protector-guard-offset=32761 -o - 2>&1 | \ +; RUN: not --crash llc %t/h2.ll -o - 2>&1 | \ ; RUN: FileCheck --check-prefix=CHECK-BAD-OFFSET %s -; RUN: not --crash llc %s --stack-protector-guard=sysreg \ -; RUN: --stack-protector-guard-reg=sp_el0 \ -; RUN: --stack-protector-guard-offset=-4096 -o - 2>&1 | \ +; RUN: not --crash llc %t/i2.ll -o - 2>&1 | \ ; RUN: FileCheck --check-prefix=CHECK-BAD-OFFSET %s -; RUN: not --crash llc %s --stack-protector-guard=sysreg \ -; RUN: --stack-protector-guard-reg=sp_el0 \ -; RUN: --stack-protector-guard-offset=4097 -o - 2>&1 | \ +; RUN: not --crash llc %t/j2.ll -o - 2>&1 | \ ; RUN: FileCheck --check-prefix=CHECK-BAD-OFFSET %s +;--- main.ll + target triple = "aarch64-unknown-linux-gnu" ; Verify that we `mrs` from `SP_EL0` twice, rather than load from @@ -100,6 +93,31 @@ entry: declare void @baz(i32*) -attributes #0 = { sspstrong } - ; CHECK-BAD-OFFSET: LLVM ERROR: Unable to encode Stack Protector Guard Offset + +attributes #0 = { sspstrong } +!llvm.module.flags = !{!1, !2, !3} + +!1 = !{i32 2, !"stack-protector-guard", !"sysreg"} +!2 = !{i32 2, !"stack-protector-guard-reg", !"sp_el0"} + +;--- a.ll +!3 = !{i32 2, !"stack-protector-guard-offset", i32 0} +;--- b.ll +!3 = !{i32 2, !"stack-protector-guard-offset", i32 8} +;--- c.ll +!3 = !{i32 2, !"stack-protector-guard-offset", i32 -8} +;--- d.ll +!3 = !{i32 2, !"stack-protector-guard-offset", i32 1} +;--- e.ll +!3 = !{i32 2, !"stack-protector-guard-offset", i32 -1} +;--- f.ll +!3 = !{i32 2, !"stack-protector-guard-offset", i32 257} +;--- g.ll +!3 = !{i32 2, !"stack-protector-guard-offset", i32 -257} +;--- h.ll +!3 = !{i32 2, !"stack-protector-guard-offset", i32 32761} +;--- i.ll +!3 = !{i32 2, !"stack-protector-guard-offset", i32 -4096} +;--- j.ll +!3 = !{i32 2, !"stack-protector-guard-offset", i32 4097} diff --git a/test/CodeGen/X86/stack-protector-3.ll b/test/CodeGen/X86/stack-protector-3.ll index 5cae90e24e6..69ff8126831 100644 --- a/test/CodeGen/X86/stack-protector-3.ll +++ b/test/CodeGen/X86/stack-protector-3.ll @@ -1,10 +1,18 @@ -; RUN: llc -mtriple=x86_64-pc-linux-gnu -o - < %s | FileCheck --check-prefix=CHECK-TLS-FS-40 %s -; RUN: llc -mtriple=x86_64-pc-linux-gnu -stack-protector-guard=tls -o - < %s | FileCheck --check-prefix=CHECK-TLS-FS-40 %s -; RUN: llc -mtriple=x86_64-pc-linux-gnu -stack-protector-guard=global -o - < %s | FileCheck --check-prefix=CHECK-GLOBAL %s -; RUN: llc -mtriple=x86_64-pc-linux-gnu -stack-protector-guard-reg=fs -o - < %s | FileCheck --check-prefix=CHECK-TLS-FS-40 %s -; RUN: llc -mtriple=x86_64-pc-linux-gnu -stack-protector-guard-reg=gs -o - < %s | FileCheck --check-prefix=CHECK-GS %s -; RUN: llc -mtriple=x86_64-pc-linux-gnu -stack-protector-guard-offset=20 -o - < %s | FileCheck --check-prefix=CHECK-OFFSET %s -; RUN: llc -mtriple=x86_64-pc-linux-gnu -stack-protector-guard-offset=-20 -o - < %s | FileCheck --check-prefix=CHECK-NEGATIVE-OFFSET %s +; RUN: split-file %s %t +; RUN: cat %t/main.ll %t/a.ll > %t/a2.ll +; RUN: cat %t/main.ll %t/b.ll > %t/b2.ll +; RUN: cat %t/main.ll %t/c.ll > %t/c2.ll +; RUN: cat %t/main.ll %t/d.ll > %t/d2.ll +; RUN: cat %t/main.ll %t/e.ll > %t/e2.ll +; RUN: cat %t/main.ll %t/f.ll > %t/f2.ll +; RUN: cat %t/main.ll %t/g.ll > %t/g2.ll +; RUN: llc -mtriple=x86_64-pc-linux-gnu -o - < %t/a2.ll | FileCheck --check-prefix=CHECK-TLS-FS-40 %s +; RUN: llc -mtriple=x86_64-pc-linux-gnu -o - < %t/b2.ll | FileCheck --check-prefix=CHECK-TLS-FS-40 %s +; RUN: llc -mtriple=x86_64-pc-linux-gnu -o - < %t/c2.ll | FileCheck --check-prefix=CHECK-GLOBAL %s +; RUN: llc -mtriple=x86_64-pc-linux-gnu -o - < %t/d2.ll | FileCheck --check-prefix=CHECK-TLS-FS-40 %s +; RUN: llc -mtriple=x86_64-pc-linux-gnu -o - < %t/e2.ll | FileCheck --check-prefix=CHECK-GS %s +; RUN: llc -mtriple=x86_64-pc-linux-gnu -o - < %t/f2.ll | FileCheck --check-prefix=CHECK-OFFSET %s +; RUN: llc -mtriple=x86_64-pc-linux-gnu -o - < %t/g2.ll | FileCheck --check-prefix=CHECK-NEGATIVE-OFFSET %s ; CHECK-TLS-FS-40: movq %fs:40, %rax ; CHECK-TLS-FS-40: movq %fs:40, %rax @@ -47,6 +55,8 @@ ; CHECK-GLOBAL-NEXT: .cfi_def_cfa_offset 32 ; CHECK-GLOBAL-NEXT: callq __stack_chk_fail +;--- main.ll + ; ModuleID = 't.c' @.str = private unnamed_addr constant [14 x i8] c"stackoverflow\00", align 1 @a = dso_local local_unnamed_addr global i8* null, align 8 @@ -75,3 +85,23 @@ declare void @llvm.memcpy.p0i8.p0i8.i64(i8* noalias nocapture writeonly, i8* noa attributes #0 = { nounwind sspreq uwtable writeonly "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="none" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" "unsafe-fp-math"="false" "use-soft-float"="false" } attributes #1 = { argmemonly nounwind willreturn } attributes #2 = { nounwind } + +;--- a.ll +;--- b.ll +!llvm.module.flags = !{!1} +!1 = !{i32 2, !"stack-protector-guard", !"tls"} +;--- c.ll +!llvm.module.flags = !{!1} +!1 = !{i32 2, !"stack-protector-guard", !"global"} +;--- d.ll +!llvm.module.flags = !{!1} +!1 = !{i32 2, !"stack-protector-guard-reg", !"fs"} +;--- e.ll +!llvm.module.flags = !{!1} +!1 = !{i32 2, !"stack-protector-guard-reg", !"gs"} +;--- f.ll +!llvm.module.flags = !{!1} +!1 = !{i32 2, !"stack-protector-guard-offset", i32 20} +;--- g.ll +!llvm.module.flags = !{!1} +!1 = !{i32 2, !"stack-protector-guard-offset", i32 -20} diff --git a/test/Linker/stack-protector-guard-module-attrs.ll b/test/Linker/stack-protector-guard-module-attrs.ll new file mode 100644 index 00000000000..f022f5b86b7 --- /dev/null +++ b/test/Linker/stack-protector-guard-module-attrs.ll @@ -0,0 +1,77 @@ +; RUN: split-file %s %t +; RUN: not llvm-link %t/a.ll %t/b.ll 2>&1 | FileCheck --check-prefix=CHECK-KIND %s +; RUN: not llvm-link %t/c.ll %t/d.ll 2>&1 | FileCheck --check-prefix=CHECK-REG %s +; RUN: not llvm-link %t/e.ll %t/f.ll 2>&1 | FileCheck --check-prefix=CHECK-OFFSET %s +; RUN: llvm-link %t/g.ll %t/h.ll + +; CHECK-KIND: error: linking module flags 'stack-protector-guard': IDs have conflicting values +; CHECK-REG: error: linking module flags 'stack-protector-guard-reg': IDs have conflicting values +; CHECK-OFFSET: error: linking module flags 'stack-protector-guard-offset': IDs have conflicting values + +;--- a.ll +; Test that different values of stack-protector-guard fail. +define void @foo() sspstrong { + ret void +} +!llvm.module.flags = !{!0} +!0 = !{i32 1, !"stack-protector-guard", !"sysreg"} +;--- b.ll +declare void @foo() sspstrong +define void @bar() sspstrong { + call void @foo() + ret void +} +!llvm.module.flags = !{!0} +!0 = !{i32 1, !"stack-protector-guard", !"global"} + +;--- c.ll +; Test that different values of stack-protector-guard-reg fail. +define void @foo() sspstrong { + ret void +} +!llvm.module.flags = !{!0} +!0 = !{i32 1, !"stack-protector-guard-reg", !"sp_el0"} +;--- d.ll +declare void @foo() sspstrong +define void @bar() sspstrong { + call void @foo() + ret void +} +!llvm.module.flags = !{!0} +!0 = !{i32 1, !"stack-protector-guard-reg", !"sp_el1"} + +;--- e.ll +; Test that different values of stack-protector-guard-offset fail. +define void @foo() sspstrong { + ret void +} +!llvm.module.flags = !{!0} +!0 = !{i32 1, !"stack-protector-guard-offset", i32 257} +;--- f.ll +declare void @foo() sspstrong +define void @bar() sspstrong { + call void @foo() + ret void +} +!llvm.module.flags = !{!0} +!0 = !{i32 1, !"stack-protector-guard-offset", i32 256} + +;--- g.ll +; Test that the same values for the three module attributes succeed. +define void @foo() sspstrong { + ret void +} +!llvm.module.flags = !{!0, !1, !2} +!0 = !{i32 1, !"stack-protector-guard", !"sysreg"} +!1 = !{i32 1, !"stack-protector-guard-reg", !"sp_el0"} +!2 = !{i32 1, !"stack-protector-guard-offset", i32 257} +;--- h.ll +declare void @foo() sspstrong +define void @bar() sspstrong { + call void @foo() + ret void +} +!llvm.module.flags = !{!0, !1, !2} +!0 = !{i32 1, !"stack-protector-guard", !"sysreg"} +!1 = !{i32 1, !"stack-protector-guard-reg", !"sp_el0"} +!2 = !{i32 1, !"stack-protector-guard-offset", i32 257}