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:
parent
a71dde3f39
commit
af04cfdc9c
@ -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"
|
||||
|
@ -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++;
|
||||
|
15
devel/llvm/patches/patch-lib_Target_Mips_CMakeLists_txt
Normal file
15
devel/llvm/patches/patch-lib_Target_Mips_CMakeLists_txt
Normal 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
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
37
devel/llvm/patches/patch-lib_Target_Mips_MipsFrameLowering_h
Normal file
37
devel/llvm/patches/patch-lib_Target_Mips_MipsFrameLowering_h
Normal 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,
|
@ -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;
|
||||
|
@ -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);
|
||||
+}
|
@ -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
|
@ -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");
|
||||
|
Loading…
Reference in New Issue
Block a user