//===-- ARMNaClRewritePass.cpp - Native Client Rewrite Pass ------*- C++ -*-=//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Native Client Rewrite Pass
// This final pass inserts the sandboxing instructions needed to run inside
// the Native Client sandbox. Native Client requires certain software fault
// isolation (SFI) constructions to be put in place, to prevent escape from
// the sandbox. Native Client refuses to execute binaries without the correct
// SFI sequences.
//
// Potentially dangerous operations which are protected include:
// * Stores
// * Branches
// * Changes to SP
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "arm-sfi"
#include "ARM.h"
#include "ARMBaseInstrInfo.h"
#include "ARMNaClRewritePass.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/IR/Function.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/CommandLine.h"
#include <set>
#include <stdio.h>
using namespace llvm;
namespace llvm {
cl::opt<bool>
FlagSfiData("sfi-data", cl::desc("use illegal at data bundle beginning"));
cl::opt<bool>
FlagSfiLoad("sfi-load", cl::desc("enable sandboxing for load"));
cl::opt<bool>
FlagSfiStore("sfi-store", cl::desc("enable sandboxing for stores"));
cl::opt<bool>
FlagSfiStack("sfi-stack", cl::desc("enable sandboxing for stack changes"));
cl::opt<bool>
FlagSfiBranch("sfi-branch", cl::desc("enable sandboxing for branches"));
cl::opt<bool>
FlagNaClUseM23ArmAbi("nacl-use-m23-arm-abi",
cl::desc("use the Chrome M23 ARM ABI"));
}
namespace {
class ARMNaClRewritePass : public MachineFunctionPass {
public:
static char ID;
ARMNaClRewritePass() : MachineFunctionPass(ID) {}
const ARMBaseInstrInfo *TII;
const TargetRegisterInfo *TRI;
virtual void getAnalysisUsage(AnalysisUsage &AU) const;
virtual bool runOnMachineFunction(MachineFunction &Fn);
virtual const char *getPassName() const {
return "ARM Native Client Rewrite Pass";
}
private:
bool SandboxMemoryReferencesInBlock(MachineBasicBlock &MBB);
void SandboxMemory(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
MachineInstr &MI,
int AddrIdx,
bool IsLoad);
bool SandboxBranchesInBlock(MachineBasicBlock &MBB);
bool SandboxStackChangesInBlock(MachineBasicBlock &MBB);
void SandboxStackChange(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI);
void LightweightVerify(MachineFunction &MF);
};
char ARMNaClRewritePass::ID = 0;
}
static bool IsReturn(const MachineInstr &MI) {
return (MI.getOpcode() == ARM::BX_RET);
}
static bool IsIndirectJump(const MachineInstr &MI) {
switch (MI.getOpcode()) {
default: return false;
case ARM::BX:
case ARM::TAILJMPr:
return true;
}
}
static bool IsIndirectCall(const MachineInstr &MI) {
return MI.getOpcode() == ARM::BLX;
}
static bool IsDirectCall(const MachineInstr &MI) {
switch (MI.getOpcode()) {
default: return false;
case ARM::BL:
case ARM::BL_pred:
case ARM::TPsoft:
return true;
}
}
static void DumpInstructionVerbose(const MachineInstr &MI) {
DEBUG({
dbgs() << MI;
dbgs() << MI.getNumOperands() << " operands:" << "\n";
for (unsigned i = 0; i < MI.getNumOperands(); ++i) {
const MachineOperand& op = MI.getOperand(i