Bring in some retguard improvements from base

- Add retguard for octeon/mips64.
- Move the hashed __retguard_* symbols into individual sections and mark
  them as COMDATs so that the linker can individually discard them, instead
  of just ignoring duplicate symbols but keep the (duplicate) space.

from Brad
This commit is contained in:
jca 2020-01-07 22:59:43 +00:00
parent a71dde3f39
commit af04cfdc9c
10 changed files with 563 additions and 15 deletions

View File

@ -1,4 +1,4 @@
# $OpenBSD: Makefile,v 1.239 2019/12/27 00:15:46 jca Exp $
# $OpenBSD: Makefile,v 1.240 2020/01/07 22:59:43 jca Exp $
# XXX If broken on an architecture, remove the arch from LLVM_ARCHS.
ONLY_FOR_ARCHS = ${LLVM_ARCHS}
@ -18,7 +18,8 @@ PKGSPEC-main = llvm-=${LLVM_V}
PKGNAME-main = llvm-${LLVM_V}
PKGNAME-python = py-llvm-${LLVM_V}
PKGNAME-lldb = lldb-${LLVM_V}
REVISION-main = 4
REVISION-main = 5
REVISION-lldb= 0
CATEGORIES = devel
@ -93,7 +94,7 @@ CONFIGURE_ARGS = -DLLVM_ENABLE_FFI:Bool=False \
# Disable some protections in the compiler to regain performance
.if ${MACHINE_ARCH} == "aarch64" || ${MACHINE_ARCH} == "amd64" || \
${MACHINE_ARCH} == "i386"
${MACHINE_ARCH} == "i386" || ${MACHINE_ARCH} == "mips64"
CXXFLAGS += -fno-ret-protector
.endif
.if ${MACHINE_ARCH} == "amd64" || ${MACHINE_ARCH} == "i386"

View File

@ -1,4 +1,4 @@
$OpenBSD: patch-lib_CodeGen_ReturnProtectorPass_cpp,v 1.2 2019/07/07 14:04:07 jca Exp $
$OpenBSD: patch-lib_CodeGen_ReturnProtectorPass_cpp,v 1.3 2020/01/07 22:59:43 jca Exp $
- Add RETGUARD to clang for amd64. This security mechanism uses per-function
random cookies to protect access to function return instructions, with the
@ -20,11 +20,14 @@ $OpenBSD: patch-lib_CodeGen_ReturnProtectorPass_cpp,v 1.2 2019/07/07 14:04:07 jc
- Put the new retguard symbols in their own section,
'.openbsd.randomdata.retguard', to make them easier to work with in the
kernel hibernate code.
- Move the hashed __retguard_* symbols into individual sections and mark
them as COMDATs so that the linker can individually discard them, instead
of just ignoring duplicate symbols but keep the (duplicate) space.
Index: lib/CodeGen/ReturnProtectorPass.cpp
--- lib/CodeGen/ReturnProtectorPass.cpp.orig
+++ lib/CodeGen/ReturnProtectorPass.cpp
@@ -0,0 +1,60 @@
@@ -0,0 +1,62 @@
+//===- ReturnProtectorPass.cpp - Set up rteurn protectors -----------------===//
+//
+// The LLVM Compiler Infrastructure
@ -60,14 +63,16 @@ Index: lib/CodeGen/ReturnProtectorPass.cpp
+ // Create a symbol for the cookie
+ Module *M = F.getParent();
+ std::hash<std::string> hasher;
+ std::string cookiename = "__retguard_" + std::to_string(hasher((M->getName() + F.getName()).str()) % 4000);
+ std::string hash = std::to_string(hasher((M->getName() + F.getName()).str()) % 4000);
+ std::string cookiename = "__retguard_" + hash;
+ Type *cookietype = Type::getInt8PtrTy(M->getContext());
+ GlobalVariable *cookie = dyn_cast_or_null<GlobalVariable>(
+ M->getOrInsertGlobal(cookiename, cookietype));
+ cookie->setInitializer(Constant::getNullValue(cookietype));
+ cookie->setLinkage(GlobalVariable::WeakAnyLinkage);
+ cookie->setLinkage(GlobalVariable::LinkOnceAnyLinkage);
+ cookie->setVisibility(GlobalValue::HiddenVisibility);
+ cookie->setSection(".openbsd.randomdata.retguard");
+ cookie->setComdat(M->getOrInsertComdat(cookiename));
+ cookie->setSection(".openbsd.randomdata.retguard." + hash);
+ cookie->setExternallyInitialized(true);
+ F.addFnAttr("ret-protector-cookie", cookiename);
+ NumSymbols++;

View File

@ -0,0 +1,15 @@
$OpenBSD: patch-lib_Target_Mips_CMakeLists_txt,v 1.1 2020/01/07 22:59:43 jca Exp $
Add retguard for octeon/mips64.
Index: lib/Target/Mips/CMakeLists.txt
--- lib/Target/Mips/CMakeLists.txt.orig
+++ lib/Target/Mips/CMakeLists.txt
@@ -47,6 +47,7 @@ add_llvm_target(MipsCodeGen
MipsPreLegalizerCombiner.cpp
MipsRegisterBankInfo.cpp
MipsRegisterInfo.cpp
+ MipsReturnProtectorLowering.cpp
MipsSEFrameLowering.cpp
MipsSEInstrInfo.cpp
MipsSEISelDAGToDAG.cpp

View File

@ -1,5 +1,6 @@
$OpenBSD: patch-lib_Target_Mips_MipsAsmPrinter_cpp,v 1.1 2019/07/09 13:21:37 jca Exp $
$OpenBSD: patch-lib_Target_Mips_MipsAsmPrinter_cpp,v 1.2 2020/01/07 22:59:43 jca Exp $
- Add retguard for octeon/mips64.
- Restore previous section after setting the MIPS ABI marker. This keeps
the .text section in use after the file header, improving compatibility
with gcc. Without this change, module-level inline assembly blocks could
@ -8,7 +9,91 @@ $OpenBSD: patch-lib_Target_Mips_MipsAsmPrinter_cpp,v 1.1 2019/07/09 13:21:37 jca
Index: lib/Target/Mips/MipsAsmPrinter.cpp
--- lib/Target/Mips/MipsAsmPrinter.cpp.orig
+++ lib/Target/Mips/MipsAsmPrinter.cpp
@@ -795,10 +795,12 @@ void MipsAsmPrinter::EmitStartOfAsmFile(Module &M) {
@@ -241,6 +241,83 @@ void MipsAsmPrinter::EmitInstruction(const MachineInst
case Mips::PATCHABLE_TAIL_CALL:
LowerPATCHABLE_TAIL_CALL(*MI);
return;
+ case Mips::RETGUARD_GET_FUNCTION_ADDR:
+ {
+ MCSymbol *PCSym = OutContext.createTempSymbol();
+ MCSymbol *FuncSym = OutContext.lookupSymbol(MI->getMF()->getName());
+ if (FuncSym == nullptr)
+ llvm_unreachable("Function name has no symbol");
+
+ // Branch and link forward, calculate the distance
+ // from here to the start of the function, and fill the
+ // address in the given dest register
+ unsigned OUT = MI->getOperand(0).getReg();
+ unsigned IN1 = MI->getOperand(1).getReg();
+ unsigned IN2 = MI->getOperand(2).getReg();
+ MCSymbol *ReturnSym = MI->getOperand(3).getMCSymbol();
+
+ // Save the value of RA in IN1
+ EmitToStreamer(*OutStreamer, MCInstBuilder(Mips::OR64)
+ .addReg(IN1)
+ .addReg(Mips::RA_64)
+ .addReg(Mips::ZERO_64));
+ // BAL to get the PC into RA
+ EmitToStreamer(*OutStreamer, MCInstBuilder(Mips::BAL)
+ .addExpr(MCSymbolRefExpr::create(ReturnSym, OutContext)));
+ // NOP
+ EmitToStreamer(*OutStreamer, MCInstBuilder(Mips::SLL)
+ .addReg(Mips::ZERO_64)
+ .addReg(Mips::ZERO_64)
+ .addImm(0));
+
+ // Emit a symbol for "here/PC" because BAL will put
+ // the address of the instruction following the NOP into RA
+ // and we need this symbol to do the math
+ OutStreamer->EmitLabel(PCSym);
+
+ // Store PC in IN2
+ EmitToStreamer(*OutStreamer, MCInstBuilder(Mips::OR64)
+ .addReg(IN2)
+ .addReg(Mips::RA_64)
+ .addReg(Mips::ZERO_64));
+ // Restore original RA
+ EmitToStreamer(*OutStreamer, MCInstBuilder(Mips::OR64)
+ .addReg(Mips::RA_64)
+ .addReg(IN1)
+ .addReg(Mips::ZERO_64));
+ // Load the offset from PCSym to the start of the function
+ EmitToStreamer(*OutStreamer, MCInstBuilder(Mips::LUi64)
+ .addReg(IN1)
+ .addExpr(MipsMCExpr::create(MipsMCExpr::MipsExprKind::MEK_HI,
+ MCBinaryExpr::createSub(
+ MCSymbolRefExpr::create(PCSym, OutContext),
+ MCSymbolRefExpr::create(FuncSym, OutContext),
+ OutContext),
+ OutContext)));
+ EmitToStreamer(*OutStreamer, MCInstBuilder(Mips::DADDiu)
+ .addReg(IN1)
+ .addReg(IN1)
+ .addExpr(MipsMCExpr::create(MipsMCExpr::MipsExprKind::MEK_LO,
+ MCBinaryExpr::createSub(
+ MCSymbolRefExpr::create(PCSym, OutContext),
+ MCSymbolRefExpr::create(FuncSym, OutContext),
+ OutContext),
+ OutContext)));
+
+ // Sub distance from here to start of function
+ // to get address of the start of function
+ EmitToStreamer(*OutStreamer, MCInstBuilder(Mips::DSUBu)
+ .addReg(OUT)
+ .addReg(IN2)
+ .addReg(IN1));
+ return;
+ }
+ case Mips::RETGUARD_EMIT_SYMBOL:
+ {
+ MCSymbol *ReturnSym = MI->getOperand(0).getMCSymbol();
+ OutStreamer->EmitLabel(ReturnSym);
+ return;
+ }
}
if (EmitJalrReloc &&
@@ -795,10 +872,12 @@ void MipsAsmPrinter::EmitStartOfAsmFile(Module &M) {
TS.emitDirectiveOptionPic0();
}

View File

@ -0,0 +1,35 @@
$OpenBSD: patch-lib_Target_Mips_MipsFrameLowering_cpp,v 1.1 2020/01/07 22:59:43 jca Exp $
Add retguard for octeon/mips64.
Index: lib/Target/Mips/MipsFrameLowering.cpp
--- lib/Target/Mips/MipsFrameLowering.cpp.orig
+++ lib/Target/Mips/MipsFrameLowering.cpp
@@ -15,6 +15,7 @@
#include "MCTargetDesc/MipsBaseInfo.h"
#include "MipsInstrInfo.h"
#include "MipsMachineFunction.h"
+#include "MipsReturnProtectorLowering.h"
#include "MipsTargetMachine.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
@@ -123,6 +124,10 @@ uint64_t MipsFrameLowering::estimateStackSize(const Ma
if (MFI.getObjectOffset(I) > 0)
Size += MFI.getObjectSize(I);
+ // Account for saving return protector register
+ if (MFI.getReturnProtectorNeeded())
+ Size += TRI.getSpillSize(*TRI.getMinimalPhysRegClass(Mips::T9_64));
+
// Conservatively assume all callee-saved registers will be saved.
for (const MCPhysReg *R = TRI.getCalleeSavedRegs(&MF); *R; ++R) {
unsigned RegSize = TRI.getSpillSize(*TRI.getMinimalPhysRegClass(*R));
@@ -149,4 +154,8 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, Mac
}
return MBB.erase(I);
+}
+
+const ReturnProtectorLowering *MipsFrameLowering::getReturnProtector() const {
+ return &RPL;
}

View File

@ -0,0 +1,37 @@
$OpenBSD: patch-lib_Target_Mips_MipsFrameLowering_h,v 1.1 2020/01/07 22:59:43 jca Exp $
Add retguard for octeon/mips64.
Index: lib/Target/Mips/MipsFrameLowering.h
--- lib/Target/Mips/MipsFrameLowering.h.orig
+++ lib/Target/Mips/MipsFrameLowering.h
@@ -15,6 +15,7 @@
#define LLVM_LIB_TARGET_MIPS_MIPSFRAMELOWERING_H
#include "Mips.h"
+#include "MipsReturnProtectorLowering.h"
#include "llvm/CodeGen/TargetFrameLowering.h"
namespace llvm {
@@ -25,8 +26,11 @@ class MipsFrameLowering : public TargetFrameLowering {
const MipsSubtarget &STI;
public:
+
+ const MipsReturnProtectorLowering RPL;
+
explicit MipsFrameLowering(const MipsSubtarget &sti, unsigned Alignment)
- : TargetFrameLowering(StackGrowsDown, Alignment, 0, Alignment), STI(sti) {}
+ : TargetFrameLowering(StackGrowsDown, Alignment, 0, Alignment), STI(sti), RPL() {}
static const MipsFrameLowering *create(const MipsSubtarget &ST);
@@ -39,6 +43,8 @@ class MipsFrameLowering : public TargetFrameLowering {
bool enableShrinkWrapping(const MachineFunction &MF) const override {
return true;
}
+
+ const ReturnProtectorLowering *getReturnProtector() const override;
MachineBasicBlock::iterator
eliminateCallFramePseudoInstr(MachineFunction &MF,

View File

@ -1,11 +1,44 @@
$OpenBSD: patch-lib_Target_Mips_MipsInstrInfo_td,v 1.1 2019/07/09 13:21:37 jca Exp $
$OpenBSD: patch-lib_Target_Mips_MipsInstrInfo_td,v 1.2 2020/01/07 22:59:43 jca Exp $
- Add retguard for octeon/mips64.
- Implement SGE pseudo-instructions. Needed when building libcrypto.
Index: lib/Target/Mips/MipsInstrInfo.td
--- lib/Target/Mips/MipsInstrInfo.td.orig
+++ lib/Target/Mips/MipsInstrInfo.td
@@ -3007,6 +3007,20 @@ def LDMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rt),
@@ -2022,6 +2022,31 @@ def LONG_BRANCH_ADDiu : PseudoSE<(outs GPR32Opnd:$dst)
def LONG_BRANCH_ADDiu2Op : PseudoSE<(outs GPR32Opnd:$dst),
(ins GPR32Opnd:$src, brtarget:$tgt), []>;
+// Pseudo instructions used by retguard. In order to calculste the PC
+// for PIC code, we use a pair of pseudos to get the function address
+// into T9, which is normally used to hold this value but is trashed
+// by function epilogue.
+let isCodeGenOnly = 1, hasNoSchedulingInfo = 1 in {
+
+ // Use BAL to get the PC into RA, then calculate the address of the
+ // current function and save this value in $rd. $rs and $rt are used
+ // as scratch registers and are trashed by this pseudo. $tgt is the
+ // symbol to branch to when calling BAL.
+ let Size = 32 in {
+ def RETGUARD_GET_FUNCTION_ADDR: PseudoSE<(outs GPR64:$rd),
+ (ins GPR64:$rs, GPR64:$rt, brtarget:$tgt), []>;
+ }
+
+ // Emit the symbol used for $tgt in RETGUARD_GET_FUNCTION_ADDR. We
+ // emit this symbol immediately before the usual function return, with
+ // the effect that the BAL branches to an immediate return and resumes
+ // execution through the rest of the RETGUARD epilogue. We pair BAL
+ // with RET to satisfy return branch predictors.
+ let Size = 0 in {
+ def RETGUARD_EMIT_SYMBOL: PseudoSE<(outs), (ins brtarget:$tgt), []>;
+ }
+}
+
//===----------------------------------------------------------------------===//
// Instruction definition
//===----------------------------------------------------------------------===//
@@ -3007,6 +3032,20 @@ def LDMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rt),
def SDMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rt),
(ins mem_simm16:$addr), "sd $rt, $addr">,
ISA_MIPS1_NOT_MIPS3;

View File

@ -0,0 +1,280 @@
$OpenBSD: patch-lib_Target_Mips_MipsReturnProtectorLowering_cpp,v 1.1 2020/01/07 22:59:43 jca Exp $
Add retguard for octeon/mips64.
Index: lib/Target/Mips/MipsReturnProtectorLowering.cpp
--- lib/Target/Mips/MipsReturnProtectorLowering.cpp.orig
+++ lib/Target/Mips/MipsReturnProtectorLowering.cpp
@@ -0,0 +1,272 @@
+//===-- MipsReturnProtectorLowering.cpp --------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the Mips implementation of ReturnProtectorLowering
+// class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MCTargetDesc/MipsBaseInfo.h"
+#include "MipsInstrInfo.h"
+#include "MipsMachineFunction.h"
+#include "MipsReturnProtectorLowering.h"
+#include "llvm/CodeGen/MachineFrameInfo.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/IR/Function.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Target/TargetOptions.h"
+#include <cstdlib>
+
+using namespace llvm;
+
+void MipsReturnProtectorLowering::insertReturnProtectorPrologue(
+ MachineFunction &MF, MachineBasicBlock &MBB, GlobalVariable *cookie) const {
+
+ MachineBasicBlock::instr_iterator MI = MBB.instr_begin();
+ DebugLoc MBBDL = MBB.findDebugLoc(MI);
+ const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
+ const TargetMachine &TM = MF.getTarget();
+ unsigned REG = MF.getFrameInfo().getReturnProtectorRegister();
+
+ const GlobalValue *FName = &MF.getFunction();
+
+ // Select some scratch registers
+ unsigned TempReg1 = Mips::AT_64;
+ unsigned TempReg2 = Mips::V0_64;
+ if (!MBB.isLiveIn(TempReg1))
+ MBB.addLiveIn(TempReg1);
+ if (!MBB.isLiveIn(TempReg2))
+ MBB.addLiveIn(TempReg2);
+
+ if (TM.isPositionIndependent()) {
+
+ if (!MBB.isLiveIn(Mips::T9_64))
+ MBB.addLiveIn(Mips::T9_64);
+
+ // TempReg1 loads the GOT pointer
+ // TempReg2 load the offset from GOT to random cookie pointer
+ BuildMI(MBB, MI, MBBDL, TII->get(Mips::LUi64), TempReg1)
+ .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_HI);
+ BuildMI(MBB, MI, MBBDL, TII->get(Mips::LUi64), TempReg2)
+ .addGlobalAddress(cookie, 0, MipsII::MO_GOT_HI16);
+ BuildMI(MBB, MI, MBBDL, TII->get(Mips::DADDu), TempReg1)
+ .addReg(TempReg1)
+ .addReg(Mips::T9_64);
+ BuildMI(MBB, MI, MBBDL, TII->get(Mips::DADDiu), TempReg2)
+ .addReg(TempReg2)
+ .addGlobalAddress(cookie, 0, MipsII::MO_GOT_LO16);
+ BuildMI(MBB, MI, MBBDL, TII->get(Mips::DADDu), TempReg1)
+ .addReg(TempReg1)
+ .addReg(TempReg2);
+ BuildMI(MBB, MI, MBBDL, TII->get(Mips::LD), REG)
+ .addReg(TempReg1)
+ .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_LO);
+ BuildMI(MBB, MI, MBBDL, TII->get(Mips::LD), REG)
+ .addReg(REG)
+ .addImm(0);
+ } else {
+ // TempReg1 loads the high 32 bits
+ // TempReg2 loads the low 32 bits
+ BuildMI(MBB, MI, MBBDL, TII->get(Mips::LUi64), TempReg1)
+ .addGlobalAddress(cookie, 0, MipsII::MO_HIGHEST);
+ BuildMI(MBB, MI, MBBDL, TII->get(Mips::LUi64), TempReg2)
+ .addGlobalAddress(cookie, 0, MipsII::MO_ABS_HI);
+ BuildMI(MBB, MI, MBBDL, TII->get(Mips::DADDiu), TempReg1)
+ .addReg(TempReg1)
+ .addGlobalAddress(cookie, 0, MipsII::MO_HIGHER);
+ BuildMI(MBB, MI, MBBDL, TII->get(Mips::DSLL), TempReg1)
+ .addReg(TempReg1)
+ .addImm(32);
+ BuildMI(MBB, MI, MBBDL, TII->get(Mips::DADDu), TempReg1)
+ .addReg(TempReg1)
+ .addReg(TempReg2);
+ BuildMI(MBB, MI, MBBDL, TII->get(Mips::LD), REG)
+ .addReg(TempReg1)
+ .addGlobalAddress(cookie, 0, MipsII::MO_ABS_LO);
+ }
+
+ BuildMI(MBB, MI, MBBDL, TII->get(Mips::XOR64), REG)
+ .addReg(REG)
+ .addReg(Mips::RA_64);
+}
+
+void MipsReturnProtectorLowering::insertReturnProtectorEpilogue(
+ MachineFunction &MF, MachineInstr &MI, GlobalVariable *cookie) const {
+
+
+ MachineBasicBlock &MBB = *MI.getParent();
+ DebugLoc MBBDL = MI.getDebugLoc();
+ const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
+ const TargetMachine &TM = MF.getTarget();
+ unsigned REG = MF.getFrameInfo().getReturnProtectorRegister();
+
+ const GlobalValue *FName = &MF.getFunction();
+
+ // Select some scratch registers
+ unsigned TempReg1 = Mips::T7_64;
+ unsigned TempReg2 = Mips::T8_64;
+ if (REG == Mips::T7_64 || REG == Mips::T8_64) {
+ TempReg1 = Mips::T5_64;
+ TempReg2 = Mips::T6_64;
+ }
+ if (!MBB.isLiveIn(TempReg1))
+ MBB.addLiveIn(TempReg1);
+ if (!MBB.isLiveIn(TempReg2))
+ MBB.addLiveIn(TempReg2);
+
+ // Undo the XOR to retrieve the random cookie
+ BuildMI(MBB, MI, MBBDL, TII->get(Mips::XOR64), REG)
+ .addReg(REG)
+ .addReg(Mips::RA_64);
+
+ // Load the random cookie
+ if (TM.isPositionIndependent()) {
+
+ if (!MBB.isLiveIn(Mips::T9_64))
+ MBB.addLiveIn(Mips::T9_64);
+
+ // T9 is trashed by this point, and we cannot trust saving
+ // the value from function entry on the stack, so calculate
+ // the address of the function entry using a pseudo
+ MCSymbol *BALTarget = MF.getContext().createTempSymbol();
+ BuildMI(MBB, MI, MBBDL, TII->get(Mips::RETGUARD_GET_FUNCTION_ADDR), Mips::T9_64)
+ .addReg(TempReg1)
+ .addReg(TempReg2)
+ .addSym(BALTarget);
+
+ // TempReg1 loads the GOT pointer
+ // TempReg2 load the offset from GOT to random cookie pointer
+ BuildMI(MBB, MI, MBBDL, TII->get(Mips::LUi64), TempReg1)
+ .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_HI);
+ BuildMI(MBB, MI, MBBDL, TII->get(Mips::LUi64), TempReg2)
+ .addGlobalAddress(cookie, 0, MipsII::MO_GOT_HI16);
+ BuildMI(MBB, MI, MBBDL, TII->get(Mips::DADDu), TempReg1)
+ .addReg(TempReg1)
+ .addReg(Mips::T9_64);
+ BuildMI(MBB, MI, MBBDL, TII->get(Mips::DADDiu), TempReg2)
+ .addReg(TempReg2)
+ .addGlobalAddress(cookie, 0, MipsII::MO_GOT_LO16);
+ BuildMI(MBB, MI, MBBDL, TII->get(Mips::DADDu), TempReg1)
+ .addReg(TempReg1)
+ .addReg(TempReg2);
+ BuildMI(MBB, MI, MBBDL, TII->get(Mips::LD), TempReg1)
+ .addReg(TempReg1)
+ .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_LO);
+ BuildMI(MBB, MI, MBBDL, TII->get(Mips::LD), TempReg1)
+ .addReg(TempReg1)
+ .addImm(0);
+ // Verify the random cookie
+ BuildMI(MBB, MI, MBBDL, TII->get(Mips::TNE))
+ .addReg(TempReg1)
+ .addReg(REG)
+ .addImm(0);
+ // Emit the BAL target symbol from above
+ BuildMI(MBB, MI, MBBDL, TII->get(Mips::RETGUARD_EMIT_SYMBOL))
+ .addSym(BALTarget);
+ } else {
+ // TempReg1 loads the high 32 bits
+ // TempReg2 loads the low 32 bits
+ BuildMI(MBB, MI, MBBDL, TII->get(Mips::LUi64), TempReg1)
+ .addGlobalAddress(cookie, 0, MipsII::MO_HIGHEST);
+ BuildMI(MBB, MI, MBBDL, TII->get(Mips::LUi64), TempReg2)
+ .addGlobalAddress(cookie, 0, MipsII::MO_ABS_HI);
+ BuildMI(MBB, MI, MBBDL, TII->get(Mips::DADDiu), TempReg1)
+ .addReg(TempReg1)
+ .addGlobalAddress(cookie, 0, MipsII::MO_HIGHER);
+ BuildMI(MBB, MI, MBBDL, TII->get(Mips::DSLL), TempReg1)
+ .addReg(TempReg1)
+ .addImm(32);
+ BuildMI(MBB, MI, MBBDL, TII->get(Mips::DADDu), TempReg1)
+ .addReg(TempReg1)
+ .addReg(TempReg2);
+ BuildMI(MBB, MI, MBBDL, TII->get(Mips::LD), TempReg1)
+ .addReg(TempReg1)
+ .addGlobalAddress(cookie, 0, MipsII::MO_ABS_LO);
+ // Verify the random cookie
+ BuildMI(MBB, MI, MBBDL, TII->get(Mips::TNE))
+ .addReg(TempReg1)
+ .addReg(REG)
+ .addImm(0);
+ }
+}
+
+bool MipsReturnProtectorLowering::opcodeIsReturn(unsigned opcode) const {
+ switch (opcode) {
+ case Mips::RetRA:
+ return true;
+ default:
+ return false;
+ }
+}
+
+void MipsReturnProtectorLowering::fillTempRegisters(
+ MachineFunction &MF, std::vector<unsigned> &TempRegs) const {
+
+ const Function &F = MF.getFunction();
+
+ // long double arguments (f128) occupy two arg registers, so shift
+ // subsequent arguments down by one register
+ size_t shift_reg = 0;
+ for (const auto &arg : F.args()) {
+ if (arg.getType()->isFP128Ty())
+ shift_reg += 1;
+ }
+
+ if (!F.isVarArg()) {
+ // We can use any of the caller saved unused arg registers
+ switch (F.arg_size() + shift_reg) {
+ case 0:
+ // A0 is used to return f128 values in soft float
+ case 1:
+ TempRegs.push_back(Mips::A1_64);
+ LLVM_FALLTHROUGH;
+ case 2:
+ TempRegs.push_back(Mips::A2_64);
+ LLVM_FALLTHROUGH;
+ case 3:
+ TempRegs.push_back(Mips::A3_64);
+ LLVM_FALLTHROUGH;
+ case 4:
+ TempRegs.push_back(Mips::T0_64);
+ LLVM_FALLTHROUGH;
+ case 5:
+ TempRegs.push_back(Mips::T1_64);
+ LLVM_FALLTHROUGH;
+ case 6:
+ TempRegs.push_back(Mips::T2_64);
+ LLVM_FALLTHROUGH;
+ case 7:
+ TempRegs.push_back(Mips::T3_64);
+ LLVM_FALLTHROUGH;
+ case 8:
+ TempRegs.push_back(Mips::T4_64);
+ LLVM_FALLTHROUGH;
+ case 9:
+ TempRegs.push_back(Mips::T5_64);
+ LLVM_FALLTHROUGH;
+ case 10:
+ TempRegs.push_back(Mips::T6_64);
+ LLVM_FALLTHROUGH;
+ case 11:
+ TempRegs.push_back(Mips::T7_64);
+ LLVM_FALLTHROUGH;
+ case 12:
+ TempRegs.push_back(Mips::T8_64);
+ LLVM_FALLTHROUGH;
+ default:
+ break;
+ }
+ }
+ // For FastCC this is the only scratch reg that isn't V0 or T9
+ TempRegs.push_back(Mips::AT_64);
+}

View File

@ -0,0 +1,54 @@
$OpenBSD: patch-lib_Target_Mips_MipsReturnProtectorLowering_h,v 1.1 2020/01/07 22:59:43 jca Exp $
Add retguard for octeon/mips64.
Index: lib/Target/Mips/MipsReturnProtectorLowering.h
--- lib/Target/Mips/MipsReturnProtectorLowering.h.orig
+++ lib/Target/Mips/MipsReturnProtectorLowering.h
@@ -0,0 +1,46 @@
+//===-- MipsReturnProtectorLowering.h - --------------------- -*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the Mips implementation of ReturnProtectorLowering
+// class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_MIPS_MIPSRETURNPROTECTORLOWERING_H
+#define LLVM_LIB_TARGET_MIPS_MIPSRETURNPROTECTORLOWERING_H
+
+#include "llvm/CodeGen/ReturnProtectorLowering.h"
+
+namespace llvm {
+
+class MipsReturnProtectorLowering : public ReturnProtectorLowering {
+public:
+ /// insertReturnProtectorPrologue/Epilogue - insert return protector
+ /// instrumentation in prologue or epilogue.
+ virtual void
+ insertReturnProtectorPrologue(MachineFunction &MF, MachineBasicBlock &MBB,
+ GlobalVariable *cookie) const override;
+ virtual void
+ insertReturnProtectorEpilogue(MachineFunction &MF, MachineInstr &MI,
+ GlobalVariable *cookie) const override;
+
+ /// opcodeIsReturn - Reuturn true is the given opcode is a return
+ /// instruction needing return protection, false otherwise.
+ virtual bool opcodeIsReturn(unsigned opcode) const override;
+
+ /// fillTempRegisters - Fill the list of available temp registers we can
+ /// use as a return protector register.
+ virtual void
+ fillTempRegisters(MachineFunction &MF,
+ std::vector<unsigned> &TempRegs) const override;
+};
+
+} // namespace llvm
+
+#endif

View File

@ -1,4 +1,4 @@
$OpenBSD: patch-tools_clang_lib_Driver_ToolChains_Clang_cpp,v 1.10 2019/09/08 10:40:39 jca Exp $
$OpenBSD: patch-tools_clang_lib_Driver_ToolChains_Clang_cpp,v 1.11 2020/01/07 22:59:43 jca Exp $
- Make LLVM create strict aligned code for OpenBSD/arm64.
- Disable -fstrict-aliasing per default on OpenBSD.
@ -22,6 +22,7 @@ $OpenBSD: patch-tools_clang_lib_Driver_ToolChains_Clang_cpp,v 1.10 2019/09/08 10
jumping into the instruction stream partway through other instructions. Work to
remove these gadgets will continue through other mechanisms.
- Add retguard for arm64.
- Add retguard for octeon/mips64.
- Improve the X86FixupGadgets pass
- On OpenBSD disable the malloc/calloc/realloc/free/str*dup builtins, since
they can perform strange transforms and optimizations. Some of those could
@ -57,7 +58,7 @@ Index: tools/clang/lib/Driver/ToolChains/Clang.cpp
if (Arg *A = Args.getLastArg(options::OPT_freroll_loops,
options::OPT_fno_reroll_loops))
@@ -4544,9 +4548,44 @@ void Clang::ConstructJob(Compilation &C, const JobActi
@@ -4544,9 +4548,46 @@ void Clang::ConstructJob(Compilation &C, const JobActi
false))
CmdArgs.push_back(Args.MakeArgString("-mspeculative-load-hardening"));
@ -75,6 +76,8 @@ Index: tools/clang/lib/Driver/ToolChains/Clang.cpp
+ }
+ if (RetProtector &&
+ ((getToolChain().getArch() == llvm::Triple::x86_64) ||
+ (getToolChain().getArch() == llvm::Triple::mips64) ||
+ (getToolChain().getArch() == llvm::Triple::mips64el) ||
+ (getToolChain().getArch() == llvm::Triple::aarch64)) &&
+ !Args.hasArg(options::OPT_fno_stack_protector) &&
+ !Args.hasArg(options::OPT_pg)) {
@ -103,7 +106,7 @@ Index: tools/clang/lib/Driver/ToolChains/Clang.cpp
// Translate -mstackrealign
if (Args.hasFlag(options::OPT_mstackrealign, options::OPT_mno_stackrealign,
false))
@@ -5029,6 +5068,18 @@ void Clang::ConstructJob(Compilation &C, const JobActi
@@ -5029,6 +5070,18 @@ void Clang::ConstructJob(Compilation &C, const JobActi
options::OPT_fno_rewrite_imports, false);
if (RewriteImports)
CmdArgs.push_back("-frewrite-imports");