Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions clang/include/clang/Basic/CodeGenOptions.def
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ CODEGENOPT(InstrumentForProfiling , 1, 0, Benign) ///< Set when -pg is enabled.
CODEGENOPT(CallFEntry , 1, 0, Benign) ///< Set when -mfentry is enabled.
CODEGENOPT(MNopMCount , 1, 0, Benign) ///< Set when -mnop-mcount is enabled.
CODEGENOPT(RecordMCount , 1, 0, Benign) ///< Set when -mrecord-mcount is enabled.
CODEGENOPT(StackProtectorGuardRecord, 1, 0, Benign) ///< Set when -mstack-protector-guard-record is enabled.
CODEGENOPT(PackedStack , 1, 0, Benign) ///< Set when -mpacked-stack is enabled.
CODEGENOPT(LessPreciseFPMAD , 1, 0, Benign) ///< Enable less precise MAD instructions to
///< be generated.
Expand Down
8 changes: 8 additions & 0 deletions clang/include/clang/Options/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -5749,6 +5749,14 @@ def mstack_protector_guard_reg_EQ : Joined<["-"], "mstack-protector-guard-reg=">
Visibility<[ClangOption, CC1Option]>,
HelpText<"Use the given reg for addressing the stack-protector guard">,
MarshallingInfoString<CodeGenOpts<"StackProtectorGuardReg">>;
def mstackprotector_guard_record
: Flag<["-"], "mstack-protector-guard-record">,
HelpText<
"Generate a __stack_protector_loc section entry for each load of "
"the stackguard address.">,
Visibility<[ClangOption, CC1Option]>,
Group<m_Group>,
MarshallingInfoFlag<CodeGenOpts<"StackProtectorGuardRecord">>;
def mfentry : Flag<["-"], "mfentry">, HelpText<"Insert calls to fentry at function entry (x86/SystemZ only)">,
Visibility<[ClangOption, CC1Option]>, Group<m_Group>,
MarshallingInfoFlag<CodeGenOpts<"CallFEntry">>;
Expand Down
8 changes: 8 additions & 0 deletions clang/lib/CodeGen/CodeGenFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1195,6 +1195,14 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
}
}

if (CGM.getCodeGenOpts().StackProtectorGuardRecord) {
if (CGM.getCodeGenOpts().StackProtectorGuard != "global")
CGM.getDiags().Report(diag::err_opt_not_valid_without_opt)
<< "-mstack-protector-guard-record"
<< "-mstack-protector-guard=global";
Fn->addFnAttr("mstackprotector-guard-record");
}

if (CGM.getCodeGenOpts().PackedStack) {
if (getContext().getTargetInfo().getTriple().getArch() !=
llvm::Triple::systemz)
Expand Down
40 changes: 29 additions & 11 deletions clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3438,22 +3438,24 @@ static void RenderSSPOptions(const Driver &D, const ToolChain &TC,
}

const std::string &TripleStr = EffectiveTriple.getTriple();
StringRef GuardValue;
if (Arg *A = Args.getLastArg(options::OPT_mstack_protector_guard_EQ)) {
StringRef Value = A->getValue();
GuardValue = A->getValue();
if (!EffectiveTriple.isX86() && !EffectiveTriple.isAArch64() &&
!EffectiveTriple.isARM() && !EffectiveTriple.isThumb() &&
!EffectiveTriple.isRISCV() && !EffectiveTriple.isPPC())
!EffectiveTriple.isRISCV() && !EffectiveTriple.isPPC() &&
!EffectiveTriple.isSystemZ())
D.Diag(diag::err_drv_unsupported_opt_for_target)
<< A->getAsString(Args) << TripleStr;
if ((EffectiveTriple.isX86() || EffectiveTriple.isARM() ||
EffectiveTriple.isThumb()) &&
Value != "tls" && Value != "global") {
EffectiveTriple.isThumb() || EffectiveTriple.isSystemZ()) &&
GuardValue != "tls" && GuardValue != "global") {
D.Diag(diag::err_drv_invalid_value_with_suggestion)
<< A->getOption().getName() << Value << "tls global";
<< A->getOption().getName() << GuardValue << "tls global";
return;
}
if ((EffectiveTriple.isARM() || EffectiveTriple.isThumb()) &&
Value == "tls") {
GuardValue == "tls") {
if (!Args.hasArg(options::OPT_mstack_protector_guard_offset_EQ)) {
D.Diag(diag::err_drv_ssp_missing_offset_argument)
<< A->getAsString(Args);
Expand All @@ -3477,18 +3479,19 @@ static void RenderSSPOptions(const Driver &D, const ToolChain &TC,
CmdArgs.push_back("-target-feature");
CmdArgs.push_back("+read-tp-tpidruro");
}
if (EffectiveTriple.isAArch64() && Value != "sysreg" && Value != "global") {
if (EffectiveTriple.isAArch64() && GuardValue != "sysreg" &&
GuardValue != "global") {
D.Diag(diag::err_drv_invalid_value_with_suggestion)
<< A->getOption().getName() << Value << "sysreg global";
<< A->getOption().getName() << GuardValue << "sysreg global";
return;
}
if (EffectiveTriple.isRISCV() || EffectiveTriple.isPPC()) {
if (Value != "tls" && Value != "global") {
if (GuardValue != "tls" && GuardValue != "global") {
D.Diag(diag::err_drv_invalid_value_with_suggestion)
<< A->getOption().getName() << Value << "tls global";
<< A->getOption().getName() << GuardValue << "tls global";
return;
}
if (Value == "tls") {
if (GuardValue == "tls") {
if (!Args.hasArg(options::OPT_mstack_protector_guard_offset_EQ)) {
D.Diag(diag::err_drv_ssp_missing_offset_argument)
<< A->getAsString(Args);
Expand Down Expand Up @@ -3562,6 +3565,21 @@ static void RenderSSPOptions(const Driver &D, const ToolChain &TC,
}
A->render(Args, CmdArgs);
}

if (Arg *A = Args.getLastArg(options::OPT_mstackprotector_guard_record)) {
if (!EffectiveTriple.isSystemZ()) {
D.Diag(diag::err_drv_unsupported_opt_for_target)
<< A->getAsString(Args) << TripleStr;
return;
}
if (GuardValue != "global") {
D.Diag(diag::err_drv_argument_only_allowed_with)
<< "-mstack-protector-guard-record"
<< "-mstack-protector-guard=global";
return;
}
A->render(Args, CmdArgs);
}
}

static void RenderSCPOptions(const ToolChain &TC, const ArgList &Args,
Expand Down
16 changes: 16 additions & 0 deletions clang/test/CodeGen/SystemZ/stack-guard-pseudos.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// RUN: %clang_cc1 -S -mllvm -stop-after=systemz-isel -stack-protector 1 -triple=s390x-ibm-linux < %s -o - | FileCheck -check-prefix=CHECK-PSEUDOS %s
// RUN: not %clang_cc1 -S -stack-protector 1 -mstack-protector-guard-record -triple=s390x-ibm-linux < %s -o - 2>&1 | FileCheck -check-prefix=CHECK-OPTS %s
// CHECK-PSEUDOS: bb.0.entry:
// CHECK-PSEUDOS: %3:addr64bit = LOAD_STACK_GUARD_ADDRESS
// CHECK-PSEUDOS: MOVE_STACK_GUARD %stack.0.StackGuardSlot, 0, %3
// CHECK-PSEUDOS: COMPARE_STACK_GUARD %stack.0.StackGuardSlot, 0, %3, implicit-def $cc

extern char *strcpy (char * D, const char * S);
int main(int argc, char *argv[])
{
char Buffer[8] = {0};
strcpy(Buffer, argv[1]);
return 0;
}

// CHECK-OPTS: error: option '-mstack-protector-guard-record' cannot be specified without '-mstack-protector-guard=global'
18 changes: 18 additions & 0 deletions clang/test/Driver/stack-protector-guard.c
Original file line number Diff line number Diff line change
Expand Up @@ -155,3 +155,21 @@

// CHECK-TLS-POWERPC32: "-cc1" {{.*}}"-mstack-protector-guard=tls" "-mstack-protector-guard-offset=24" "-mstack-protector-guard-reg=r2"
// INVALID-REG-POWERPC32: error: invalid value 'r3' in 'mstack-protector-guard-reg=', expected one of: r2

// RUN: %clang -### -target systemz-unknown-elf -mstack-protector-guard=tls %s 2>&1 | \
// RUN: FileCheck -check-prefix=CHECK_TLS_SYSTEMZ %s
// CHECK_TLS_SYSTEMZ: "-cc1" {{.*}}"-mstack-protector-guard=tls"

// RUN: %clang -### -target systemz-unknown-elf -mstack-protector-guard=global %s 2>&1 | \
// RUN: FileCheck -check-prefix=CHECK_GLOBAL_SYSTEMZ %s
// CHECK_GLOBAL_SYSTEMZ: "-cc1" {{.*}}"-mstack-protector-guard=global"

// RUN: %clang -### -target systemz-unknown-elf -mstack-protector-guard=global \
// RUN: -mstack-protector-guard-record %s 2>&1 | \
// RUN: FileCheck -check-prefix=CHECK_GLOBAL_RECORD_SYSTEMZ %s
// CHECK_GLOBAL_RECORD_SYSTEMZ: "-cc1" {{.*}}"-mstack-protector-guard=global" "-mstack-protector-guard-record"

// RUN: not %clang -target systemz-unknown-elf -mstack-protector-guard=tls \
// RUN: -mstack-protector-guard-record %s 2>&1 | \
// RUN: FileCheck -check-prefix=INVALID_TLS_RECORD_SYSTEMZ %s
// INVALID_TLS_RECORD_SYSTEMZ: error: invalid argument '-mstack-protector-guard-record' only allowed with '-mstack-protector-guard=global'
127 changes: 127 additions & 0 deletions llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,11 @@
#include "llvm/BinaryFormat/GOFF.h"
#include "llvm/CodeGen/MachineModuleInfoImpls.h"
#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Mangler.h"
#include "llvm/IR/Module.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCInstBuilder.h"
#include "llvm/MC/MCSectionELF.h"
#include "llvm/MC/MCStreamer.h"
Expand Down Expand Up @@ -213,6 +215,16 @@ SystemZAsmPrinter::AssociatedDataAreaTable::insert(const MachineOperand MO) {
return insert(Sym, ADAslotType);
}

namespace {
unsigned long getStackGuardOffset(const MachineBasicBlock *MBB) {
// In the TLS (default) case, AddrReg will contain the thread pointer, so we
// need to add 40 bytes to get the actual address of the stack guard.
StringRef GuardType =
MBB->getParent()->getFunction().getParent()->getStackProtectorGuard();
return (GuardType == "global") ? 0 : 40;
}
} // namespace

void SystemZAsmPrinter::emitInstruction(const MachineInstr *MI) {
SystemZ_MC::verifyInstructionPredicates(MI->getOpcode(),
getSubtargetInfo().getFeatureBits());
Expand Down Expand Up @@ -740,13 +752,128 @@ void SystemZAsmPrinter::emitInstruction(const MachineInstr *MI) {
case SystemZ::EH_SjLj_Setup:
return;

case SystemZ::LOAD_STACK_GUARD: {
// If requested, record address of stack guard address load
if (MF->getFunction().hasFnAttribute("mstackprotector-guard-record"))
emitStackProtectorLocEntry();
Register AddrReg = emitLoadStackGuardAddress(MI);
LoweredMI = MCInstBuilder(SystemZ::LG)
.addReg(AddrReg)
.addImm(getStackGuardOffset(MI->getParent()))
.addReg(0);
} break;

case SystemZ::LOAD_STACK_GUARD_ADDRESS:
// If requested, record address of stack guard address load
if (MF->getFunction().hasFnAttribute("mstackprotector-guard-record"))
emitStackProtectorLocEntry();
emitLoadStackGuardAddress(MI);
return;

case SystemZ::COMPARE_STACK_GUARD:
LoweredMI = MCInstBuilder(SystemZ::CLC)
.addReg(MI->getOperand(0).getReg())
.addImm(MI->getOperand(1).getImm())
.addImm(8)
.addReg(MI->getOperand(2).getReg())
.addImm(getStackGuardOffset(MI->getParent()));
break;

case SystemZ::MOVE_STACK_GUARD:
LoweredMI = MCInstBuilder(SystemZ::MVC)
.addReg(MI->getOperand(0).getReg())
.addImm(MI->getOperand(1).getImm())
.addImm(8)
.addReg(MI->getOperand(2).getReg())
.addImm(getStackGuardOffset(MI->getParent()));
break;

default:
Lower.lower(MI, LoweredMI);
break;
}
EmitToStreamer(*OutStreamer, LoweredMI);
}

void SystemZAsmPrinter::emitStackProtectorLocEntry() {
MCSymbol *Sym = OutContext.createTempSymbol();
OutStreamer->pushSection();
OutStreamer->switchSection(OutContext.getELFSection(
"__stack_protector_loc", ELF::SHT_PROGBITS, ELF::SHF_ALLOC));
OutStreamer->emitSymbolValue(Sym, getDataLayout().getPointerSize());
OutStreamer->popSection();
OutStreamer->emitLabel(Sym);
}

// Emit the stack guard address load, depending on guard type.
// Return the register the stack guard address was loaded into.
Register SystemZAsmPrinter::emitLoadStackGuardAddress(const MachineInstr *MI) {
const MachineBasicBlock *MBB = MI->getParent();
const MachineFunction &MF = *MBB->getParent();
const Register AddrReg = MI->getOperand(0).getReg();
const MCRegisterInfo &MRI = *TM.getMCRegisterInfo();
const Register Reg32 = MRI.getSubReg(AddrReg, SystemZ::subreg_l32);

const Module *M = MF.getFunction().getParent();
StringRef GuardType = M->getStackProtectorGuard();

if (GuardType.empty() || (GuardType == "tls")) {
// EAR can only load the low subregister so use a shift for %a0 to produce
// the GR containing %a0 and %a1.

// ear <reg>, %a0
MCInst EAR1 = MCInstBuilder(SystemZ::EAR)
.addReg(Reg32)
.addReg(SystemZ::A0)
.addReg(AddrReg);

// sllg <reg>, <reg>, 32
MCInst SLLG = MCInstBuilder(SystemZ::SLLG)
.addReg(AddrReg)
.addReg(AddrReg)
.addReg(0)
.addImm(32);

// ear <reg>, %a1
MCInst EAR2 = MCInstBuilder(SystemZ::EAR)
.addReg(Reg32)
.addReg(SystemZ::A1)
.addReg(AddrReg);

EmitToStreamer(*OutStreamer, EAR1);
EmitToStreamer(*OutStreamer, SLLG);
EmitToStreamer(*OutStreamer, EAR2);
} else if (GuardType == "global") {
// Obtain the global value.
const auto *GV = M->getGlobalVariable(
"__stack_chk_guard", PointerType::getUnqual(M->getContext()));
assert(GV &&
"could not create reference to global variable __stack_chk_guard");
auto *Sym = TM.getSymbol(GV);
// Ref->
// Emit the address load.
MCInst Load;
if (M->getPICLevel() == PICLevel::NotPIC) {
Load = MCInstBuilder(SystemZ::LARL)
.addReg(AddrReg)
.addExpr(MCSymbolRefExpr::create(Sym, OutContext));
} else {
Load =
MCInstBuilder(SystemZ::LGRL)
.addReg(AddrReg)
.addExpr(MCSymbolRefExpr::create(Sym, SystemZ::S_GOT, OutContext))
.addExpr(getGlobalOffsetTable(OutContext));
}
EmitToStreamer(*OutStreamer, Load);
} else {
llvm_unreachable(
(Twine("Unknown stack protector type \"") + GuardType + "\"")
.str()
.c_str());
}
return AddrReg;
}

// Emit the largest nop instruction smaller than or equal to NumBytes
// bytes. Return the size of nop emitted.
static unsigned EmitNop(MCContext &OutContext, MCStreamer &OutStreamer,
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/Target/SystemZ/SystemZAsmPrinter.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,8 @@ class LLVM_LIBRARY_VISIBILITY SystemZAsmPrinter : public AsmPrinter {
void LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI,
SystemZMCInstLower &Lower);
void LowerPATCHABLE_RET(const MachineInstr &MI, SystemZMCInstLower &Lower);
Register emitLoadStackGuardAddress(const MachineInstr *MI);
void emitStackProtectorLocEntry();
void emitAttributes(Module &M);
};
} // end namespace llvm
Expand Down
9 changes: 7 additions & 2 deletions llvm/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@
//
//===----------------------------------------------------------------------===//

#include "SystemZTargetMachine.h"
#include "SystemZISelLowering.h"
#include "SystemZTargetMachine.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/CodeGen/SelectionDAGISel.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/KnownBits.h"
#include "llvm/Support/raw_ostream.h"
Expand Down Expand Up @@ -369,7 +370,11 @@ class SystemZDAGToDAGISel : public SelectionDAGISel {
if (F.hasFnAttribute("mrecord-mcount"))
report_fatal_error("mrecord-mcount only supported with fentry-call");
}

if (F.getParent()->getStackProtectorGuard() != "global") {
if (F.hasFnAttribute("mstack-protector-guard-record"))
report_fatal_error("mstack-protector-guard-record only supported with "
"mstack-protector-guard=global");
}
Subtarget = &MF.getSubtarget<SystemZSubtarget>();
return SelectionDAGISel::runOnMachineFunction(MF);
}
Expand Down
Loading