diff options
| author | Sasa Stankovic <Sasa.Stankovic@imgtec.com> | 2014-02-28 10:00:38 +0000 |
|---|---|---|
| committer | Sasa Stankovic <Sasa.Stankovic@imgtec.com> | 2014-02-28 10:00:38 +0000 |
| commit | 8c5736b9217bd3757760a6d193f79502234eea55 (patch) | |
| tree | 7b6c0f3ebd586aedd08ea2035e13310637b72b03 /llvm/lib/Target | |
| parent | 763b93965c9d9da29193cab393cc45eefdcc35d4 (diff) | |
| download | bcm5719-llvm-8c5736b9217bd3757760a6d193f79502234eea55.tar.gz bcm5719-llvm-8c5736b9217bd3757760a6d193f79502234eea55.zip | |
[mips] Implement NaCl sandboxing of indirect jumps:
* Align targets of indirect jumps to instruction bundle boundaries (in MI layer).
* Add masking instructions before indirect jumps (in MC layer).
Differential Revision: http://llvm-reviews.chandlerc.com/D2847
llvm-svn: 202479
Diffstat (limited to 'llvm/lib/Target')
| -rw-r--r-- | llvm/lib/Target/Mips/MCTargetDesc/MipsMCNaCl.h | 28 | ||||
| -rw-r--r-- | llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp | 11 | ||||
| -rw-r--r-- | llvm/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp | 97 | ||||
| -rw-r--r-- | llvm/lib/Target/Mips/MipsAsmPrinter.cpp | 35 | ||||
| -rw-r--r-- | llvm/lib/Target/Mips/MipsAsmPrinter.h | 2 |
5 files changed, 170 insertions, 3 deletions
diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCNaCl.h b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCNaCl.h new file mode 100644 index 00000000000..62d67d9f3f1 --- /dev/null +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCNaCl.h @@ -0,0 +1,28 @@ +//===-- MipsMCNaCl.h - NaCl-related declarations --------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef MIPSMCNACL_H +#define MIPSMCNACL_H + +#include "llvm/MC/MCELFStreamer.h" + +namespace llvm { + +// Log2 of the NaCl MIPS sandbox's instruction bundle size. +static const unsigned MIPS_NACL_BUNDLE_ALIGN = 4u; + +// This function creates an MCELFStreamer for Mips NaCl. +MCELFStreamer *createMipsNaClELFStreamer(MCContext &Context, MCAsmBackend &TAB, + raw_ostream &OS, + MCCodeEmitter *Emitter, + bool RelaxAll, bool NoExecStack); + +} + +#endif diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp index faecde41b06..b663bf83405 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp @@ -11,9 +11,10 @@ // //===----------------------------------------------------------------------===// -#include "MipsMCTargetDesc.h" #include "InstPrinter/MipsInstPrinter.h" #include "MipsMCAsmInfo.h" +#include "MipsMCNaCl.h" +#include "MipsMCTargetDesc.h" #include "MipsTargetStreamer.h" #include "llvm/ADT/Triple.h" #include "llvm/MC/MCCodeGenInfo.h" @@ -109,8 +110,12 @@ static MCStreamer *createMCStreamer(const Target &T, StringRef TT, raw_ostream &OS, MCCodeEmitter *Emitter, const MCSubtargetInfo &STI, bool RelaxAll, bool NoExecStack) { - MCStreamer *S = - createELFStreamer(Context, MAB, OS, Emitter, RelaxAll, NoExecStack); + MCStreamer *S; + if (!Triple(TT).isOSNaCl()) + S = createELFStreamer(Context, MAB, OS, Emitter, RelaxAll, NoExecStack); + else + S = createMipsNaClELFStreamer(Context, MAB, OS, Emitter, RelaxAll, + NoExecStack); new MipsTargetELFStreamer(*S, STI); return S; } diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp new file mode 100644 index 00000000000..a442e5b31bb --- /dev/null +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp @@ -0,0 +1,97 @@ +//===-- MipsNaClELFStreamer.cpp - ELF Object Output for Mips NaCl ---------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements MCELFStreamer for Mips NaCl. It emits .o object files +// as required by NaCl's SFI sandbox. It inserts address-masking instructions +// before dangerous control-flow instructions. It aligns on bundle size all +// functions and all targets of indirect branches. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "mips-mc-nacl" + +#include "Mips.h" +#include "MipsMCNaCl.h" +#include "llvm/MC/MCELFStreamer.h" + +using namespace llvm; + +namespace { + +const unsigned IndirectBranchMaskReg = Mips::T6; + +/// Extend the generic MCELFStreamer class so that it can mask dangerous +/// instructions. + +class MipsNaClELFStreamer : public MCELFStreamer { +public: + MipsNaClELFStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &OS, + MCCodeEmitter *Emitter) + : MCELFStreamer(Context, TAB, OS, Emitter) {} + + ~MipsNaClELFStreamer() {} + +private: + bool isIndirectJump(const MCInst &MI) { + return MI.getOpcode() == Mips::JR || MI.getOpcode() == Mips::RET; + } + + void emitMask(unsigned AddrReg, unsigned MaskReg, + const MCSubtargetInfo &STI) { + MCInst MaskInst; + MaskInst.setOpcode(Mips::AND); + MaskInst.addOperand(MCOperand::CreateReg(AddrReg)); + MaskInst.addOperand(MCOperand::CreateReg(AddrReg)); + MaskInst.addOperand(MCOperand::CreateReg(MaskReg)); + MCELFStreamer::EmitInstruction(MaskInst, STI); + } + + // Sandbox indirect branch or return instruction by inserting mask operation + // before it. + void sandboxIndirectJump(const MCInst &MI, const MCSubtargetInfo &STI) { + unsigned AddrReg = MI.getOperand(0).getReg(); + + EmitBundleLock(false); + emitMask(AddrReg, IndirectBranchMaskReg, STI); + MCELFStreamer::EmitInstruction(MI, STI); + EmitBundleUnlock(); + } + +public: + /// This function is the one used to emit instruction data into the ELF + /// streamer. We override it to mask dangerous instructions. + virtual void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) { + if (isIndirectJump(Inst)) + sandboxIndirectJump(Inst, STI); + else + MCELFStreamer::EmitInstruction(Inst, STI); + } +}; + +} // end anonymous namespace + +namespace llvm { + +MCELFStreamer *createMipsNaClELFStreamer(MCContext &Context, MCAsmBackend &TAB, + raw_ostream &OS, + MCCodeEmitter *Emitter, bool RelaxAll, + bool NoExecStack) { + MipsNaClELFStreamer *S = new MipsNaClELFStreamer(Context, TAB, OS, Emitter); + if (RelaxAll) + S->getAssembler().setRelaxAll(true); + if (NoExecStack) + S->getAssembler().setNoExecStack(true); + + // Set bundle-alignment as required by the NaCl ABI for the target. + S->EmitBundleAlignMode(MIPS_NACL_BUNDLE_ALIGN); + + return S; +} + +} diff --git a/llvm/lib/Target/Mips/MipsAsmPrinter.cpp b/llvm/lib/Target/Mips/MipsAsmPrinter.cpp index 67c17a92f0f..d5df855a5ec 100644 --- a/llvm/lib/Target/Mips/MipsAsmPrinter.cpp +++ b/llvm/lib/Target/Mips/MipsAsmPrinter.cpp @@ -15,6 +15,7 @@ #define DEBUG_TYPE "mips-asm-printer" #include "InstPrinter/MipsInstPrinter.h" #include "MCTargetDesc/MipsBaseInfo.h" +#include "MCTargetDesc/MipsMCNaCl.h" #include "Mips.h" #include "MipsAsmPrinter.h" #include "MipsInstrInfo.h" @@ -27,6 +28,7 @@ #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineJumpTableInfo.h" #include "llvm/CodeGen/MachineMemOperand.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/DataLayout.h" @@ -72,6 +74,11 @@ bool MipsAsmPrinter::runOnMachineFunction(MachineFunction &MF) { StubsNeeded[Symbol] = Signature; } MCP = MF.getConstantPool(); + + // In NaCl, all indirect jump targets must be aligned to bundle size. + if (Subtarget->isTargetNaCl()) + NaClAlignIndirectJumpTargets(MF); + AsmPrinter::runOnMachineFunction(MF); return true; } @@ -270,6 +277,12 @@ const char *MipsAsmPrinter::getCurrentABIString() const { void MipsAsmPrinter::EmitFunctionEntryLabel() { MipsTargetStreamer &TS = getTargetStreamer(); + + // NaCl sandboxing requires that indirect call instructions are masked. + // This means that function entry points should be bundle-aligned. + if (Subtarget->isTargetNaCl()) + EmitAlignment(std::max(MF->getAlignment(), MIPS_NACL_BUNDLE_ALIGN)); + if (Subtarget->inMicroMipsMode()) TS.emitDirectiveSetMicroMips(); // leave out until FSF available gas has micromips changes @@ -906,6 +919,28 @@ void MipsAsmPrinter::PrintDebugValueComment(const MachineInstr *MI, // TODO: implement } +// Align all targets of indirect branches on bundle size. Used only if target +// is NaCl. +void MipsAsmPrinter::NaClAlignIndirectJumpTargets(MachineFunction &MF) { + // Align all blocks that are jumped to through jump table. + if (MachineJumpTableInfo *JtInfo = MF.getJumpTableInfo()) { + const std::vector<MachineJumpTableEntry> &JT = JtInfo->getJumpTables(); + for (unsigned I = 0; I < JT.size(); ++I) { + const std::vector<MachineBasicBlock*> &MBBs = JT[I].MBBs; + + for (unsigned J = 0; J < MBBs.size(); ++J) + MBBs[J]->setAlignment(MIPS_NACL_BUNDLE_ALIGN); + } + } + + // If basic block address is taken, block can be target of indirect branch. + for (MachineFunction::iterator MBB = MF.begin(), E = MF.end(); + MBB != E; ++MBB) { + if (MBB->hasAddressTaken()) + MBB->setAlignment(MIPS_NACL_BUNDLE_ALIGN); + } +} + // Force static initialization. extern "C" void LLVMInitializeMipsAsmPrinter() { RegisterAsmPrinter<MipsAsmPrinter> X(TheMipsTarget); diff --git a/llvm/lib/Target/Mips/MipsAsmPrinter.h b/llvm/lib/Target/Mips/MipsAsmPrinter.h index 2808b940da4..c99c6d357d0 100644 --- a/llvm/lib/Target/Mips/MipsAsmPrinter.h +++ b/llvm/lib/Target/Mips/MipsAsmPrinter.h @@ -73,6 +73,8 @@ private: void EmitFPCallStub(const char *, const Mips16HardFloatInfo::FuncSignature *); + void NaClAlignIndirectJumpTargets(MachineFunction &MF); + public: const MipsSubtarget *Subtarget; |

