示例#1
0
/// Emit extern decls for functions imported from other modules, and emit
/// global declarations for function defined in this module and which are
/// available to other modules.
///
void PIC16AsmPrinter::EmitFunctionDecls(Module &M) {
 // Emit declarations for external functions.
  O <<"\n"<<TAI->getCommentString() << "Function Declarations - BEGIN." <<"\n";
  for (Module::iterator I = M.begin(), E = M.end(); I != E; I++) {
    if (I->isIntrinsic())
      continue;

    std::string Name = Mang->getMangledName(I);
    if (Name.compare("@abort") == 0)
      continue;
    
    if (!I->isDeclaration() && !I->hasExternalLinkage())
      continue;

    // Do not emit memcpy, memset, and memmove here.
    // Calls to these routines can be generated in two ways,
    // 1. User calling the standard lib function
    // 2. Codegen generating these calls for llvm intrinsics.
    // In the first case a prototype is alread availale, while in
    // second case the call is via and externalsym and the prototype is missing.
    // So declarations for these are currently always getting printing by
    // tracking both kind of references in printInstrunction.
    if (I->isDeclaration() && PAN::isMemIntrinsic(Name)) continue;

    const char *directive = I->isDeclaration() ? TAI->getExternDirective() :
                                                 TAI->getGlobalDirective();
      
    O << directive << Name << "\n";
    O << directive << PAN::getRetvalLabel(Name) << "\n";
    O << directive << PAN::getArgsLabel(Name) << "\n";
  }

  O << TAI->getCommentString() << "Function Declarations - END." <<"\n";
}
void MemoryInstrumenter::instrumentGlobals(Module &M) {
  TargetData &TD = getAnalysis<TargetData>();
  IDAssigner &IDA = getAnalysis<IDAssigner>();

  // Function HookGlobalsAlloc contains only one basic block.
  // The BB iterates through all global variables, and calls HookMemAlloc
  // for each of them.
  BasicBlock *BB = BasicBlock::Create(M.getContext(), "entry",
                                      GlobalsAllocHook);
  Instruction *Ret = ReturnInst::Create(M.getContext(), BB);

  for (Module::global_iterator GI = M.global_begin(), E = M.global_end();
       GI != E; ++GI) {
    // We are going to delete llvm.global_ctors.
    // Therefore, don't instrument it.
    if (GI->getName() == "llvm.global_ctors")
      continue;
    // Prevent global variables from sharing the same address, because it
    // breaks the assumption that global variables do not alias.
    // The same goes to functions.
    if (GI->hasUnnamedAddr()) {
      GI->setUnnamedAddr(false);
    }
    uint64_t TypeSize = TD.getTypeStoreSize(GI->getType()->getElementType());
    instrumentMemoryAllocation(GI,
                               ConstantInt::get(LongType, TypeSize),
                               NULL,
                               Ret);
    instrumentPointer(GI, NULL, Ret);
  }

  for (Module::iterator F = M.begin(); F != M.end(); ++F) {
    // These hooks added by us don't have a value ID.
    if (MemAllocHook == F || MainArgsAllocHook == F || TopLevelHook == F ||
        AddrTakenHook == F || CallHook == F || ReturnHook == F ||
        GlobalsAllocHook == F || MemHooksIniter == F || AfterForkHook == F ||
        BeforeForkHook == F) {
      continue;
    }
    // InvalidID: maybe this is inserted by alias checker in hybrid mode.
    if (IDA.getValueID(F) == IDAssigner::InvalidID)
      continue;
    // Ignore intrinsic functions because we cannot take the address of
    // an intrinsic. Also, no function pointers will point to instrinsic
    // functions.
    if (F->isIntrinsic())
      continue;
    // Prevent functions from sharing the same address.
    if (F->hasUnnamedAddr()) {
      F->setUnnamedAddr(false);
    }
    uint64_t TypeSize = TD.getTypeStoreSize(F->getType());
    assert(TypeSize == TD.getPointerSize());
    instrumentMemoryAllocation(F,
                               ConstantInt::get(LongType, TypeSize),
                               NULL,
                               Ret);
    instrumentPointer(F, NULL, Ret);
  }
}
示例#3
0
void MemoryInstrumenter::checkFeatures(Module &M) {
    // Check whether any memory allocation function can
    // potentially be pointed by function pointers.
    // Also, all intrinsic functions will be called directly,
    // i.e. not via function pointers.
    for (Module::iterator F = M.begin(); F != M.end(); ++F) {
        if (DynAAUtils::IsMalloc(F) || F->isIntrinsic()) {
            for (Value::use_iterator UI = F->use_begin(); UI != F->use_end(); ++UI) {
                User *Usr = *UI;
                assert(isa<CallInst>(Usr) || isa<InvokeInst>(Usr));
                CallSite CS(cast<Instruction>(Usr));
                for (unsigned i = 0; i < CS.arg_size(); ++i)
                    assert(CS.getArgument(i) != F);
            }
        }
    }

    // Check whether memory allocation functions are captured.
    for (Module::iterator F = M.begin(); F != M.end(); ++F) {
        // 0 is the return, 1 is the first parameter.
        if (F->isDeclaration() && F->doesNotAlias(0) && !DynAAUtils::IsMalloc(F)) {
            errs().changeColor(raw_ostream::RED);
            errs() << F->getName() << "'s return value is marked noalias, ";
            errs() << "but the function is not treated as malloc.\n";
            errs().resetColor();
        }
    }

    // Global variables shouldn't be of the array type.
    for (Module::global_iterator GI = M.global_begin(), E = M.global_end();
            GI != E; ++GI) {
        assert(!GI->getType()->isArrayTy());
    }
    // A function parameter or an instruction can be an array, but we don't
    // instrument such constructs for now. Issue a warning on such cases.
    for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) {
        for (Function::arg_iterator AI = F->arg_begin(); AI != F->arg_end(); ++AI) {
            if (AI->getType()->isArrayTy()) {
                errs().changeColor(raw_ostream::RED);
                errs() << F->getName() << ":" << *AI << " is an array\n";
                errs().resetColor();
            }
        }
    }
    for (Module::iterator F = M.begin(); F != M.end(); ++F) {
        for (Function::iterator BB = F->begin(); BB != F->end(); ++BB) {
            for (BasicBlock::iterator Ins = BB->begin(); Ins != BB->end(); ++Ins) {
                if (Ins->getType()->isArrayTy()) {
                    errs().changeColor(raw_ostream::RED);
                    errs() << F->getName() << ":" << *Ins << " is an array\n";
                    errs().resetColor();
                }
            }
        }
    }
}
示例#4
0
bool MergeFunctions::runOnModule(Module &M) {
  bool Changed = false;

  std::map<unsigned long, std::vector<Function *> > FnMap;

  for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) {
    if (F->isDeclaration() || F->isIntrinsic())
      continue;

    if (!F->hasLocalLinkage() && !F->hasExternalLinkage() &&
        !F->hasWeakLinkage())
      continue;

    if (hasAddressTaken(F))
      continue;

    FnMap[hash(F)].push_back(F);
  }

  // TODO: instead of running in a loop, we could also fold functions in callgraph
  // order. Constructing the CFG probably isn't cheaper than just running in a loop.

  bool LocalChanged;
  do {
    LocalChanged = false;
    for (std::map<unsigned long, std::vector<Function *> >::iterator
         I = FnMap.begin(), E = FnMap.end(); I != E; ++I) {
      DOUT << "size: " << FnMap.size() << "\n";
      std::vector<Function *> &FnVec = I->second;
      DOUT << "hash (" << I->first << "): " << FnVec.size() << "\n";

      for (int i = 0, e = FnVec.size(); i != e; ++i) {
        for (int j = i + 1; j != e; ++j) {
          bool isEqual = equals(FnVec[i], FnVec[j]);

          DOUT << "  " << FnVec[i]->getName()
               << (isEqual ? " == " : " != ")
               << FnVec[j]->getName() << "\n";

          if (isEqual) {
            if (fold(FnVec, i, j)) {
              LocalChanged = true;
              FnVec.erase(FnVec.begin() + j);
              --j, --e;
            }
          }
        }
      }

    }
    Changed |= LocalChanged;
  } while (LocalChanged);

  return Changed;
}
void MemoryInstrumenter::checkFeatures(Module &M) {
  // Check whether any memory allocation function can
  // potentially be pointed by function pointers.
  // Also, all intrinsic functions will be called directly,
  // i.e. not via function pointers.
  for (Module::iterator F = M.begin(); F != M.end(); ++F) {
    if (DynAAUtils::IsMalloc(F) || F->isIntrinsic()) {
      for (Value::use_iterator UI = F->use_begin(); UI != F->use_end(); ++UI) {
        User *Usr = *UI;
        assert(isa<CallInst>(Usr) || isa<InvokeInst>(Usr));
        CallSite CS(cast<Instruction>(Usr));
        for (unsigned i = 0; i < CS.arg_size(); ++i)
          assert(CS.getArgument(i) != F);
      }
    }
  }

  // Check whether memory allocation functions are captured.
  for (Module::iterator F = M.begin(); F != M.end(); ++F) {
    // 0 is the return, 1 is the first parameter.
    if (F->isDeclaration() && F->doesNotAlias(0) && !DynAAUtils::IsMalloc(F)) {
      errs().changeColor(raw_ostream::RED);
      errs() << F->getName() << "'s return value is marked noalias, ";
      errs() << "but the function is not treated as malloc.\n";
      errs().resetColor();
    }
  }

  // Sequential types except pointer types shouldn't be used as the type of
  // an instruction, a function parameter, or a global variable.
  for (Module::global_iterator GI = M.global_begin(), E = M.global_end();
       GI != E; ++GI) {
    if (isa<SequentialType>(GI->getType()))
      assert(GI->getType()->isPointerTy());
  }
  for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) {
    for (Function::arg_iterator AI = F->arg_begin(); AI != F->arg_end(); ++AI) {
      if (isa<SequentialType>(AI->getType()))
        assert(AI->getType()->isPointerTy());
    }
  }
  for (Module::iterator F = M.begin(); F != M.end(); ++F) {
    for (Function::iterator BB = F->begin(); BB != F->end(); ++BB) {
      for (BasicBlock::iterator Ins = BB->begin(); Ins != BB->end(); ++Ins) {
        if (isa<SequentialType>(Ins->getType()))
          assert(Ins->getType()->isPointerTy());
      }
    }
  }

  // We don't support multi-process programs for now.
  if (!HookFork)
    assert(M.getFunction("fork") == NULL);
}
示例#6
0
文件: IRWriter.cpp 项目: orcc/jade
void IRWriter::writeIntrisics(Actor* actor){
    Module* module = actor->getModule();

    for (Module::iterator FI = module->begin(), FE = module->end();
         FI != FE; ++FI) {

        if (FI->isIntrinsic()) {
            writer->addFunctionProtosExternal(FI);
        }else if (FI->getName().compare("printf")==0){
            writer->linkExternalFunction(FI, FunctionMng::createPrintf(decoder->getModule()));
        }
    }
}
bool StripAttributes::runOnModule(Module &M) {
  DataLayout DL(&M);
  for (Module::iterator Func = M.begin(), E = M.end(); Func != E; ++Func) {
    // Avoid stripping attributes from intrinsics because the
    // constructor for Functions just adds them back again.  It would
    // be confusing if the attributes were sometimes present on
    // intrinsics and sometimes not.
    if (!Func->isIntrinsic()) {
      stripGlobalValueAttrs(Func);
      stripFunctionAttrs(&DL, Func);
    }
  }
  for (Module::global_iterator GV = M.global_begin(), E = M.global_end();
       GV != E; ++GV) {
    stripGlobalValueAttrs(GV);
  }
  return true;
}
示例#8
0
/// CleanupAndPrepareModules - Get the specified modules ready for code
/// generator testing.
///
static void CleanupAndPrepareModules(BugDriver &BD, Module *&Test,
                                     Module *Safe) {
  // Clean up the modules, removing extra cruft that we don't need anymore...
  Test = BD.performFinalCleanups(Test);

  // If we are executing the JIT, we have several nasty issues to take care of.
  if (!BD.isExecutingJIT()) return;

  // First, if the main function is in the Safe module, we must add a stub to
  // the Test module to call into it.  Thus, we create a new function `main'
  // which just calls the old one.
  if (Function *oldMain = Safe->getFunction("main"))
    if (!oldMain->isDeclaration()) {
      // Rename it
      oldMain->setName("llvm_bugpoint_old_main");
      // Create a NEW `main' function with same type in the test module.
      Function *newMain = Function::Create(oldMain->getFunctionType(),
                                           GlobalValue::ExternalLinkage,
                                           "main", Test);
      // Create an `oldmain' prototype in the test module, which will
      // corresponds to the real main function in the same module.
      Function *oldMainProto = Function::Create(oldMain->getFunctionType(),
                                                GlobalValue::ExternalLinkage,
                                                oldMain->getName(), Test);
      // Set up and remember the argument list for the main function.
      std::vector<Value*> args;
      for (Function::arg_iterator
             I = newMain->arg_begin(), E = newMain->arg_end(),
             OI = oldMain->arg_begin(); I != E; ++I, ++OI) {
        I->setName(OI->getName());    // Copy argument names from oldMain
        args.push_back(I);
      }

      // Call the old main function and return its result
      BasicBlock *BB = BasicBlock::Create(Safe->getContext(), "entry", newMain);
      CallInst *call = CallInst::Create(oldMainProto, args.begin(), args.end(),
                                        "", BB);

      // If the type of old function wasn't void, return value of call
      ReturnInst::Create(Safe->getContext(), call, BB);
    }

  // The second nasty issue we must deal with in the JIT is that the Safe
  // module cannot directly reference any functions defined in the test
  // module.  Instead, we use a JIT API call to dynamically resolve the
  // symbol.

  // Add the resolver to the Safe module.
  // Prototype: void *getPointerToNamedFunction(const char* Name)
  Constant *resolverFunc =
    Safe->getOrInsertFunction("getPointerToNamedFunction",
                    Type::getInt8PtrTy(Safe->getContext()),
                    Type::getInt8PtrTy(Safe->getContext()),
                       (Type *)0);

  // Use the function we just added to get addresses of functions we need.
  for (Module::iterator F = Safe->begin(), E = Safe->end(); F != E; ++F) {
    if (F->isDeclaration() && !F->use_empty() && &*F != resolverFunc &&
        !F->isIntrinsic() /* ignore intrinsics */) {
      Function *TestFn = Test->getFunction(F->getName());

      // Don't forward functions which are external in the test module too.
      if (TestFn && !TestFn->isDeclaration()) {
        // 1. Add a string constant with its name to the global file
        Constant *InitArray = ConstantArray::get(F->getContext(), F->getName());
        GlobalVariable *funcName =
          new GlobalVariable(*Safe, InitArray->getType(), true /*isConstant*/,
                             GlobalValue::InternalLinkage, InitArray,
                             F->getName() + "_name");

        // 2. Use `GetElementPtr *funcName, 0, 0' to convert the string to an
        // sbyte* so it matches the signature of the resolver function.

        // GetElementPtr *funcName, ulong 0, ulong 0
        std::vector<Constant*> GEPargs(2,
                     Constant::getNullValue(Type::getInt32Ty(F->getContext())));
        Value *GEP =
                ConstantExpr::getGetElementPtr(funcName, &GEPargs[0], 2);
        std::vector<Value*> ResolverArgs;
        ResolverArgs.push_back(GEP);

        // Rewrite uses of F in global initializers, etc. to uses of a wrapper
        // function that dynamically resolves the calls to F via our JIT API
        if (!F->use_empty()) {
          // Create a new global to hold the cached function pointer.
          Constant *NullPtr = ConstantPointerNull::get(F->getType());
          GlobalVariable *Cache =
            new GlobalVariable(*F->getParent(), F->getType(), 
                               false, GlobalValue::InternalLinkage,
                               NullPtr,F->getName()+".fpcache");

          // Construct a new stub function that will re-route calls to F
          const FunctionType *FuncTy = F->getFunctionType();
          Function *FuncWrapper = Function::Create(FuncTy,
                                                   GlobalValue::InternalLinkage,
                                                   F->getName() + "_wrapper",
                                                   F->getParent());
          BasicBlock *EntryBB  = BasicBlock::Create(F->getContext(),
                                                    "entry", FuncWrapper);
          BasicBlock *DoCallBB = BasicBlock::Create(F->getContext(),
                                                    "usecache", FuncWrapper);
          BasicBlock *LookupBB = BasicBlock::Create(F->getContext(),
                                                    "lookupfp", FuncWrapper);

          // Check to see if we already looked up the value.
          Value *CachedVal = new LoadInst(Cache, "fpcache", EntryBB);
          Value *IsNull = new ICmpInst(*EntryBB, ICmpInst::ICMP_EQ, CachedVal,
                                       NullPtr, "isNull");
          BranchInst::Create(LookupBB, DoCallBB, IsNull, EntryBB);

          // Resolve the call to function F via the JIT API:
          //
          // call resolver(GetElementPtr...)
          CallInst *Resolver =
            CallInst::Create(resolverFunc, ResolverArgs.begin(),
                             ResolverArgs.end(), "resolver", LookupBB);

          // Cast the result from the resolver to correctly-typed function.
          CastInst *CastedResolver =
            new BitCastInst(Resolver,
                            PointerType::getUnqual(F->getFunctionType()),
                            "resolverCast", LookupBB);

          // Save the value in our cache.
          new StoreInst(CastedResolver, Cache, LookupBB);
          BranchInst::Create(DoCallBB, LookupBB);

          PHINode *FuncPtr = PHINode::Create(NullPtr->getType(),
                                             "fp", DoCallBB);
          FuncPtr->addIncoming(CastedResolver, LookupBB);
          FuncPtr->addIncoming(CachedVal, EntryBB);

          // Save the argument list.
          std::vector<Value*> Args;
          for (Function::arg_iterator i = FuncWrapper->arg_begin(),
                 e = FuncWrapper->arg_end(); i != e; ++i)
            Args.push_back(i);

          // Pass on the arguments to the real function, return its result
          if (F->getReturnType()->isVoidTy()) {
            CallInst::Create(FuncPtr, Args.begin(), Args.end(), "", DoCallBB);
            ReturnInst::Create(F->getContext(), DoCallBB);
          } else {
            CallInst *Call = CallInst::Create(FuncPtr, Args.begin(), Args.end(),
                                              "retval", DoCallBB);
            ReturnInst::Create(F->getContext(),Call, DoCallBB);
          }

          // Use the wrapper function instead of the old function
          F->replaceAllUsesWith(FuncWrapper);
        }
      }
    }
  }

  if (verifyModule(*Test) || verifyModule(*Safe)) {
    errs() << "Bugpoint has a bug, which corrupted a module!!\n";
    abort();
  }
}
示例#9
0
// Entry point of the module
bool PrepareCSI::runOnModule(Module &M){
  vector<pair<string, set<set<string> > > > schemeData;
  if(VariantsFile.empty()){
    outs() << "Reading stdin for instrumentation scheme...\n";
    schemeData = readScheme(cin);
    outs() << "Finished reading stdin for scheme\n";
  }
  else{
    ifstream inFile(VariantsFile.c_str(), ios::in);
    if(!inFile || !inFile.is_open())
      report_fatal_error("cannot open specified instrumentation scheme file: " +
                         VariantsFile);
    schemeData = readScheme(inFile);
  }
  
  DEBUG(printScheme(schemeData));
  
  // verify that all passes provided exist
  DEBUG(dbgs() << "verifying...\n");
  verifyScheme(schemeData);
  
  DEBUG(printScheme(schemeData));
  
  Context = &M.getContext();
  
  // Find the matching pattern for each function
  map<Function*, set<set<string> >*> matches;
  for(Module::iterator F = M.begin(), E = M.end(); F != E; ++F){
    if(F->isDeclaration() || F->isIntrinsic())
      continue;
    bool found = false;
    for(vector<pair<string, set<set<string> > > >::iterator i = schemeData.begin(), e = schemeData.end(); i != e; ++i){
      if(patternMatch(F->getName(), i->first)){
        matches[F] = &(i->second);
        found = true;
        break;
      }
    }
    if(!found){
      errs() << "WARNING: No scheme match found for function '"
	     << F->getName() << "'.  Skipping.\n";
      continue;
    }
  }

  // Filter patterns matched to each function, and replicate
  for(map<Function*, set<set<string> >*>::iterator i = matches.begin(), e = matches.end(); i != e; ++i){
    Function* F = i->first;
    
    // go through all filters for each possible scheme.  if it passes all
    // filters, make a replica of this function with those tags on it, and add
    // that replica to the "replicas" set.  else, print warning
    set<const set<string>*> replicas;
    
    for(set<set<string> >::iterator j = i->second->begin(), je = i->second->end(); j != je; ++j){
      bool passed = true;
      if(!NoFilter){
        for(vector<FilterFn>::const_iterator fi = Filters.begin(), fe = Filters.end(); fi != fe; ++fi){
          if(!(*fi)(*j, F)){
            passed = false;
            break;
          }
        }
      }
      if(passed)
        replicas.insert(&*j);
      else{
        outs() << "WARNING: filtered out scheme '";
        for(set<string>::iterator k = j->begin(), ke = j->end(); k != ke; ++k){
          if(k != j->begin())
            outs() << ",";
          outs() << *k;
        }
        outs() << "' for function '" << F->getName().str() << "'\n";
        continue;
      }
    }
    
    switch (replicas.size()) {
    case 0:
      continue;
    case 1: {
      // instrument the original body (don't replicate and trampoline)
      const set<string>* scheme = *(replicas.begin());
      for(set<string>::iterator j = scheme->begin(), je = scheme->end(); j != je; ++j)
        addInstrumentationType(*F, *j);
      break;
    }
    default:
      // if the function is variable-argument, currently don't support
      if(F->isVarArg()){
        outs() << "WARNING: cannot instrument variable-argument function '"
               << F->getName() << "'\n";
        continue;
      }
      
      // make a function for each scheme
      vector<Function*> funcReplicas;
      for(set<const set<string>*>::iterator j = replicas.begin(), je = replicas.end(); j != je; ++j){
        ValueToValueMapTy valueMap;
        SmallVector<ReturnInst*, 1> returns;
        Function* newF = CloneFunction(F, valueMap, false, NULL);

        string name = F->getName().str();
        if((*j)->begin() == (*j)->end())
          name += "$none";
        for(set<string>::iterator k = (*j)->begin(), ke = (*j)->end(); k != ke; ++k){
          name += "$" + *k;
          addInstrumentationType(*newF, *k);
        }
        newF->setName(name);
        
        // NOTE: this does not preserve function ordering, thus it could
        // randomly slightly impact performance positively or negatively
        F->getParent()->getFunctionList().push_back(newF);
        funcReplicas.push_back(newF);
      }
      
      // assign this function a global switcher variable
      IntegerType* tInt = Type::getInt32Ty(*Context);
      string globalName = "__CSI_inst_"+getUniqueCFunctionName(*F);
      const GlobalValue::LinkageTypes linkage =
         F->hasAvailableExternallyLinkage()
         ? GlobalValue::WeakAnyLinkage
         : GlobalValue::ExternalLinkage;
      GlobalVariable * const functionGlobal =
         new GlobalVariable(M, tInt, true, linkage,
                            ConstantInt::get(tInt, 0), globalName);
      
      functionGlobal->setSection("__CSI_func_inst");

      // set up the trampoline call for this function
      switchIndirect(F, functionGlobal, funcReplicas);
    }
  }
  
  return(true);
}