summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target
diff options
context:
space:
mode:
authorSasa Stankovic <Sasa.Stankovic@imgtec.com>2014-02-28 10:00:38 +0000
committerSasa Stankovic <Sasa.Stankovic@imgtec.com>2014-02-28 10:00:38 +0000
commit8c5736b9217bd3757760a6d193f79502234eea55 (patch)
tree7b6c0f3ebd586aedd08ea2035e13310637b72b03 /llvm/lib/Target
parent763b93965c9d9da29193cab393cc45eefdcc35d4 (diff)
downloadbcm5719-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.h28
-rw-r--r--llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp11
-rw-r--r--llvm/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp97
-rw-r--r--llvm/lib/Target/Mips/MipsAsmPrinter.cpp35
-rw-r--r--llvm/lib/Target/Mips/MipsAsmPrinter.h2
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;
OpenPOWER on IntegriCloud