//===- CFIChecks.cpp - Insert indirect function call checks --------------- --//
// 
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
// 
//===----------------------------------------------------------------------===//
//
// This pass instruments indirect function calls to ensure that control-flow
// integrity is preserved at run-time.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "safecode"

#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/IR/Constants.h"

#include "safecode/CFIChecks.h"
#include "safecode/Utility.h"

namespace llvm {

char CFIChecks::ID = 0;

static RegisterPass<CFIChecks>
X ("cfichecks", "Insert control-flow integrity run-time checks");

// Pass Statistics
namespace {
  STATISTIC (Checks, "CFI Checks Added");
}

//
// Method: createTargetTable()
//
// Description:
//  Create a global variable that contains the targets of the specified
//  function call.
//
// Inputs:
//  CI - A call instruction.
//
// Outputs:
//  isComplete - Flag indicating whether all targets of the call are known.
//
// Return value:
//  A global variable pointing to an array of call targets.
//
GlobalVariable *
CFIChecks::createTargetTable (CallInst & CI, bool & isComplete) {
  //
  // Get the call graph.
  //
  CallGraph & CG = getAnalysis<CallGraph>();

  //
  // Get the call graph node for the function containing the call.
  //
  CallGraphNode * CGN = CG[CI.getParent()->getParent()];

  //
  // Iterate through all of the target call nodes and add them to the list of
  // targets to use in the global variable.
  //
  isComplete = false;
  PointerType * VoidPtrType = getVoidPtrType(CI.getContext());
  SmallVector<Constant *, 20> Targets;
  for (CallGraphNode::iterator ti = CGN->begin(); ti != CGN->end(); ++ti) {
    //
    // See if this call record corresponds to the call site in question.
    //
    const Value * V = ti->first;
    if (V != &CI)
      continue;

    //
    // Get the node in the graph corresponding to the callee.
    //
    CallGraphNode * CalleeNode = ti->second;

    //
    // Get the target function(s).  If we have a normal callee node as the
    // target, then just fetch the function it represents out of the callee
    // node.  Otherwise, this callee node represents external code that could
    // call any address-taken function.  In that case, we'll have to do extra
    // work to get the potential targets.
    //
    if (CalleeNode == CG.getCallsExternalNode()) {
      //
      // Assume that the check will be incomplete.
      //
      isComplete = false;

      //
      // Get the call graph node that represents external code that calls
      // *into* the program.  Get the list of callees of this node and make
      // them targets.
      //
      CallGraphNode * ExternalNode = CG.getExternalCallingNode();
      for (CallGraphNode::iterator ei = ExternalNode->begin();
                                   ei != ExternalNode->end(); ++ei) {
        if (Function * Target = ei->second->getFunction()) {
          //
          // Do not include intrinsic functions or functions that do not get
          // emitted into the executable in the list of targets.
          //
          if ((Target->isIntrinsic()) ||
              (Target->hasAvailableExternallyLinkage())) {
            continue;
          }

          //
          // Do not include functions with available externally linkage.  These
          // functions are never emitted into the final executable.
          //
          Targets.push_back (ConstantExpr::getZExtOrBitCast (Target,
                                                             VoidPtrType));
        }
      }
    } else {
      //
      // Get the function target out of the node.
      //
      Function * Target = CalleeNode->getFunction();

      //
      // If there is no target function, then this call can call code external
      // to the module.  In that case, mark the call as incomplete.
      //
      if (!Target) {
        isComplete = false;
        continue;
      }

      //
      // Do not include intrinsic functions or functions that do not get
      // emitted into the final exeutable as targets.
      //
      if ((Target->isIntrinsic()) ||
          (Target->hasAvailableExternallyLinkage())) {
        continue;
      }

      //
      // Add the target to the set of targets.  Cast it to a void pointer
      // first.
      //
      Targets.push_back (ConstantExpr::getZExtOrBitCast (Target, VoidPtrType));
    }
  }

  //
  // Truncate the list with a null pointer.
  //
  Targets.push_back(ConstantPointerNull::get (VoidPtrType));

  //
  // Create the constant array initializer containing all of the targets.
  //
  ArrayType * AT = ArrayType::get (VoidPtrType, Targets.size());
  Constant * TargetArray = ConstantArray::get (AT, Targets);
  return new GlobalVariable (*(CI.getParent()->getParent()->getParent()),
                             AT,
                             true,
                             GlobalValue::InternalLinkage,
                             TargetArray,
                             "TargetList");
}

//
// Method: visitCallInst()
//
// Description:
//  Place a run-time check on a call instruction.
//
void
CFIChecks::visitCallInst (CallInst & CI) {
  //
  // If the call is inline assembly code or a direct call, then don't insert a
  // check.
  //
  Value * CalledValue = CI.getCalledValue()->stripPointerCasts();
  if ((isa<Function>(CalledValue)) || (isa<InlineAsm>(CalledValue)))
    return;

  //
  // Create the call to the run-time check.
  // The first argument is the function pointer used in the call.
  // The second argument is the pointer to check.
  //
  Value * args[2];
  LLVMContext & Context = CI.getContext();
  bool isComplete = false;
  GlobalVariable * Targets = createTargetTable (CI, isComplete);
  args[0] = castTo (CI.getCalledValue(), getVoidPtrType(Context), &CI);
  args[1] = castTo (Targets, getVoidPtrType(Context), &CI);
  CallInst * Check = CallInst::Create (FunctionCheckUI, args, "", &CI);

  //
  // If there's debug information on the load instruction, add it to the
  // run-time check.
  //
  if (MDNode * MD = CI.getMetadata ("dbg"))
    Check->setMetadata ("dbg", MD);

  //
  // Update the statistics.
  //
  ++Checks;
  return;
}

bool
CFIChecks::runOnModule (Module & M) {
  //
  // Create a function prototype for the function that performs incomplete
  // function call checks.
  //
  Type *VoidTy    = Type::getVoidTy (M.getContext());
  Type *VoidPtrTy = getVoidPtrType (M.getContext());
  FunctionCheckUI = cast<Function>(M.getOrInsertFunction ("funccheckui",
                                                          VoidTy,
                                                          VoidPtrTy,
                                                          VoidPtrTy,
                                                          NULL));
  assert (FunctionCheckUI && "Function Check function has disappeared!\n");
  FunctionCheckUI->addFnAttr (Attribute::ReadNone);

  //
  // Visit all of the instructions in the function.
  //
  visit (M);
  return true;
}

}

