//===- DetectDanglingPointers.cpp - Insert calls to mark objects read-only  --//
// 
//                          The SAFECode Compiler 
//
// 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 a program so that it marks the shadow pages of
// heap objects read-only; this is used for the dangling pointer detection as
// described in the DSN 2006 paper "Efficiently Detecting All Dangling Pointer
// Uses in Production Servers."
//
// Notes:
//  o) This pass must be run before the pass that adds poolunregister() calls.
//     This is because the run-time must change the memory protections before
//     unregistering the object.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "dpchecks"

#include "llvm/ADT/Statistic.h"

#include "safecode/SAFECode.h"
#include "safecode/SAFECodeConfig.h"
#include "safecode/Support/AllocatorInfo.h"
#include "safecode/DetectDanglingPointers.h"

#include <iostream>
#include <utility>
#include <vector>

char NAMESPACE_SC::DetectDanglingPointers::ID = 0;

NAMESPACE_SC_BEGIN

// Statistics
STATISTIC (Changes,    "Number of Shadowing Calls Inserted");

//
// Method: createFunctionProtos()
//
// Description:
//  Create the function prototypes for shadowing and unshadowing objects.
//
void
DetectDanglingPointers::createFunctionProtos (Module & M) {
  //
  // Get basic integer and pointer types.
  //
  const Type * Int8Type  = IntegerType::getInt8Ty(getGlobalContext());
  const Type * Int32Type  = IntegerType::getInt32Ty(getGlobalContext());
  Type * VoidPtrTy = PointerType::getUnqual(Int8Type);

  //
  // Get the function that unshadows heap objects.
  //
  std::vector<const Type *> Arg(1, VoidPtrTy);
  FunctionType * Ty = FunctionType::get(VoidPtrTy, Arg, false);
  ProtectObj = M.getOrInsertFunction("pool_unshadow", Ty);

  //
  // Get the function that shadows heap objects.
  //
  Arg.push_back (Int32Type);
  Ty = FunctionType::get(VoidPtrTy, Arg, false);
  ShadowObj  = M.getOrInsertFunction("pool_shadow", Ty);

  return;
}

void
DetectDanglingPointers::processFrees (Module & M,
                                      std::set<Function *> & FreeFuncs) {
  //
  // Scan through all uses of all heap deallocation functions.  For each one,
  // insert a call to the run-time library that will change the page
  // protections so that reads and writes to the object will cause a hardware
  // fault.
  //
  std::vector<std::pair<CallInst *, Value *> > Worklist;
  SAFECodeConfiguration::AllocatorInfoListTy::iterator i;
  for (i = SCConfig.alloc_begin(); i != SCConfig.alloc_end(); ++i) {
    // Get the allocator information structure
    AllocatorInfo * info = *i;

    //
    // Clear the work list.
    //
    Worklist.clear();

    // Reference to the deallocation function
    Function * freeFunc = M.getFunction(info->getFreeCallName());
    if (freeFunc) {
      //
      // Record the deallocation function in the set so that we can quickly
      // look it up later.
      //
      FreeFuncs.insert (freeFunc);

      //
      // Iterate over all uses of the free function and add instrumentation.
      //
      Value::use_iterator  it, end;
      for (it = freeFunc->use_begin(), end = freeFunc->use_end();
           it != end;
           ++it) {
        if (CallInst * CI = dyn_cast<CallInst>(*it)) {
          //
          // Backup one instruction since the preceding instruction should be
          // a call to poolunregister().
          //
          BasicBlock::iterator InsertPt = CI;
          assert (InsertPt != CI->getParent()->begin());
          --InsertPt;

          //
          // Create the call.
          //
          Value * Pointer = info->getFreedPointer (CI);
          CallInst * OrigPtr = CallInst::Create (ProtectObj,
                                                 Pointer,
                                                 "",
                                                 InsertPt);

          //
          // Add to the worklist the call instruction that we will need to
          // change and the new pointer value that should be freed.
          //
          Worklist.push_back (std::make_pair(CI, OrigPtr));
        }
      }
    }

    //
    // Update the statistics if the worklist has any elements.  This avoids
    // printing a statistic of zero in the results.
    //
    if (Worklist.size()) Changes += Worklist.size();

    //
    // Go through the work list and change all of the deallocation calls to
    // use the original pointer returned from the pool_unshadow() call.
    //
    while (Worklist.size()) {
      CallInst * FreeCall = Worklist.back().first;
      Value *    OrigPtr  = Worklist.back().second;
      Worklist.pop_back();

      FreeCall->setOperand (2, OrigPtr);
    }
  }

  return;
}

bool
DetectDanglingPointers::runOnModule (Module & M) {
  //
  // If dangling pointer protection is disabled, do nothing.
  //
  if (!(SCConfig.dpChecks())) return false;

  //
  // Get prerequisite analysis results.
  //
  intrinPass = &getAnalysis<InsertSCIntrinsic>();

  //
  // Create the functions for shadowing and unshadowing objects.
  //
  createFunctionProtos (M);

  //
  // Process the deallocation functions first.  This allows us to collect the
  // a list of the deallocation functions while instrumenting them so that they
  // free the originally allocated object and not the shadow object.
  //
  std::set<Function *> FreeFuncs;
  processFrees (M, FreeFuncs);

  //
  // Scan through all calls to allocation functions.  For each allocation,
  // add a call after it to remap the object to a shadow object.  Then, replace
  // all uses of the original pointer with the shadow pointer.
  //
  SAFECodeConfiguration::AllocatorInfoListTy::iterator i;
  for (i = SCConfig.alloc_begin(); i != SCConfig.alloc_end(); ++i) {
    // Get the allocator information structure
    AllocatorInfo * info = *i;

    // Reference to the allocation function
    Function * allocFunc = M.getFunction(info->getAllocCallName());
    if (allocFunc) {
      //
      // Iterate over all uses of the allocation function.
      //
      Value::use_iterator  it, end;
      for (it = allocFunc->use_begin(), end = allocFunc->use_end();
           it != end;
           ++it) {
        if (CallInst * CI = dyn_cast<CallInst>(*it)) {
          if (CI->getCalledFunction() == allocFunc) {
            //
            // This is an allocation site.  Add a call after it to create a
            // shadow copy of the allocated object.
            //
            std::vector<Value *> args;
            args.push_back (CI);
            args.push_back (info->getAllocSize (CI));
            BasicBlock::iterator InsertPt = CI;
            ++InsertPt;
            CallInst * Shadow = CallInst::Create (ShadowObj, args.begin(), args.end(), "", InsertPt);

            //
            // Replace all uses of the originally allocated pointer with the
            // shadow pointer.
            //
            CI->replaceAllUsesWith (Shadow);

            //
            // The previous statement modified the call to pool_shadow() so
            // that it takes its return value as its argument.  Change its
            // argument back to the original allocated object.
            //
            Shadow->setOperand (1, CI);

            //
            // Update the statistics.
            //
            ++Changes;
          }
        }
      }
    }
  }

  //
  // We most likely changed something; conservatively claim that we made
  // modifications.
  //
  return true;
}

NAMESPACE_SC_END

