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);
  }
}
Exemple #2
0
// run - This incorporates all types used by the specified module
//
bool FindUsedTypes::runOnModule(Module &m) {
  UsedTypes.clear();  // reset if run multiple times...

  // Loop over global variables, incorporating their types
  for (Module::const_global_iterator I = m.global_begin(), E = m.global_end();
       I != E; ++I) {
    IncorporateType(I->getType());
    if (I->hasInitializer())
      IncorporateValue(I->getInitializer());
  }

  for (Module::iterator MI = m.begin(), ME = m.end(); MI != ME; ++MI) {
    IncorporateType(MI->getType());
    const Function &F = *MI;

    // Loop over all of the instructions in the function, adding their return
    // type as well as the types of their operands.
    //
    for (const_inst_iterator II = inst_begin(F), IE = inst_end(F);
         II != IE; ++II) {
      const Instruction &I = *II;

      IncorporateType(I.getType());  // Incorporate the type of the instruction
      for (User::const_op_iterator OI = I.op_begin(), OE = I.op_end();
           OI != OE; ++OI)
        IncorporateValue(*OI);  // Insert inst operand types as well
    }
  }

  return false;
}
Exemple #3
0
/// computeTypeMapping - Loop over all of the linked values to compute type
/// mappings.  For example, if we link "extern Foo *x" and "Foo *x = NULL", then
/// we have two struct types 'Foo' but one got renamed when the module was
/// loaded into the same LLVMContext.
void ModuleLinker::computeTypeMapping() {
  // Incorporate globals.
  for (Module::global_iterator I = SrcM->global_begin(),
       E = SrcM->global_end(); I != E; ++I) {
    GlobalValue *DGV = getLinkedToGlobal(I);
    if (DGV == 0) continue;
    
    if (!DGV->hasAppendingLinkage() || !I->hasAppendingLinkage()) {
      TypeMap.addTypeMapping(DGV->getType(), I->getType());
      continue;      
    }
    
    // Unify the element type of appending arrays.
    ArrayType *DAT = cast<ArrayType>(DGV->getType()->getElementType());
    ArrayType *SAT = cast<ArrayType>(I->getType()->getElementType());
    TypeMap.addTypeMapping(DAT->getElementType(), SAT->getElementType());
  }
  
  // Incorporate functions.
  for (Module::iterator I = SrcM->begin(), E = SrcM->end(); I != E; ++I) {
    if (GlobalValue *DGV = getLinkedToGlobal(I))
      TypeMap.addTypeMapping(DGV->getType(), I->getType());
  }

  // Incorporate types by name, scanning all the types in the source module.
  // At this point, the destination module may have a type "%foo = { i32 }" for
  // example.  When the source module got loaded into the same LLVMContext, if
  // it had the same type, it would have been renamed to "%foo.42 = { i32 }".
  // Though it isn't required for correctness, attempt to link these up to clean
  // up the IR.
  std::vector<StructType*> SrcStructTypes;
  SrcM->findUsedStructTypes(SrcStructTypes);
  
  SmallPtrSet<StructType*, 32> SrcStructTypesSet(SrcStructTypes.begin(),
                                                 SrcStructTypes.end());
  
  for (unsigned i = 0, e = SrcStructTypes.size(); i != e; ++i) {
    StructType *ST = SrcStructTypes[i];
    if (!ST->hasName()) continue;
    
    // Check to see if there is a dot in the name followed by a digit.
    size_t DotPos = ST->getName().rfind('.');
    if (DotPos == 0 || DotPos == StringRef::npos ||
        ST->getName().back() == '.' || !isdigit(ST->getName()[DotPos+1]))
      continue;
    
    // Check to see if the destination module has a struct with the prefix name.
    if (StructType *DST = DstM->getTypeByName(ST->getName().substr(0, DotPos)))
      // Don't use it if this actually came from the source module.  They're in
      // the same LLVMContext after all.
      if (!SrcStructTypesSet.count(DST))
        TypeMap.addTypeMapping(DST, ST);
  }

  // Don't bother incorporating aliases, they aren't generally typed well.
  
  // Now that we have discovered all of the type equivalences, get a body for
  // any 'opaque' types in the dest module that are now resolved. 
  TypeMap.linkDefinedTypeBodies();
}
/// 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();
  }
}