Exemplo n.º 1
0
/// Get the specified modules ready for code generator testing.
///
static void CleanupAndPrepareModules(BugDriver &BD,
                                     std::unique_ptr<Module> &Test,
                                     Module *Safe) {
  // Clean up the modules, removing extra cruft that we don't need anymore...
  Test = BD.performFinalCleanups(Test.get());

  // 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.get());
      // 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.get());
      // 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, "", 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 *)nullptr);

  // 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 =
          ConstantDataArray::getString(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(InitArray->getType(),
                                                    funcName, GEPargs);
        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
          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, "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(), 2,
                                             "fp", DoCallBB);
          FuncPtr->addIncoming(CastedResolver, LookupBB);
          FuncPtr->addIncoming(CachedVal, EntryBB);

          // Save the argument list.
          std::vector<Value*> Args;
          for (Argument &A : FuncWrapper->args())
            Args.push_back(&A);

          // Pass on the arguments to the real function, return its result
          if (F->getReturnType()->isVoidTy()) {
            CallInst::Create(FuncPtr, Args, "", DoCallBB);
            ReturnInst::Create(F->getContext(), DoCallBB);
          } else {
            CallInst *Call = CallInst::Create(FuncPtr, Args,
                                              "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();
  }
}
Exemplo n.º 2
0
bool SpBasicBlockInstrumenter::runOnModule(Module &M) {

  cerr << "instrument: --- Basic Block Spectrum ---\n";

  Function *Main = M.getFunction("main");
  LLVMContext &C = M.getContext();
  
  if (Main == 0) {
    cerr << "WARNING: cannot insert block instrumentation into a module"
         << " with no main function!\n";
    return false;  // No main, no instrumentation!
  }

  // Add library function prototype
  Constant *SpFn = M.getOrInsertFunction("_updateSpectrum", 
                          Type::getVoidTy(C), 
                          Type::getInt32Ty(C),  // spectrum index
                          Type::getInt32Ty(C),  // component index
                          NULL);


  unsigned spectrumIndex = IndexManager::getSpectrumIndex();
  unsigned nComponents = 0;
  
  // Loop through all functions within module
  for (Module::iterator F = M.begin(), ME = M.end(); F != ME; ++F) {

    // skip function declarations
    if(F->isDeclaration()) 
      continue;

    // skip the _registerAll function
    if(F->getName()=="_registerAll")
      continue;
    
    // Loop through all basic blocks within function
    for (Function::iterator B = F->begin(), FE = F->end(); B != FE; ++B) {
      //skip dead blocks
      //is this really safe??
      BasicBlock *bb = B;
      if (B!=F->begin() && (pred_begin(bb)==pred_end(bb))) continue; //skip dead blocks

      // Loop through all instructions within basic block
      for (BasicBlock::iterator I = B->begin(), BE = B->end(); I != BE; I++) {

        if(isa<DbgStopPointInst>(*I)) {
          DbgStopPointInst &DSPI = cast<DbgStopPointInst>(*I);
          std::string file, dir, name="-";
          llvm::GetConstantStringInfo(DSPI.getDirectory(), dir);
          llvm::GetConstantStringInfo(DSPI.getFileName(), file);
          int line = DSPI.getLine();

          // add source context of this invariant to context file
          ContextManager::addSpectrumContext(
            spectrumIndex,     // spectrumIndex
            nComponents,       // componentIndex
            dir,               // path
            file,              // file
            line,              // line
            name);             // name
  
          // add call to lib function
          std::vector<Value*> Args(2);
          Args[0] = ConstantInt::get(Type::getInt32Ty(C), spectrumIndex);
          Args[1] = ConstantInt::get(Type::getInt32Ty(C), nComponents++);
          
          CallInst::Create(SpFn, Args.begin(), Args.end(), "", I);

          break;
        }
      }
    }
  }

  // add the registration of the instrumented spectrum points in the _registerAll() function
  addSpectrumRegistration(M, spectrumIndex, nComponents, "Basic_Blocks");
  
  llvm::cerr << "instrument: " << nComponents << " basic blocks instrumented\n";

  // notify change of program 
  return true;
}
Exemplo n.º 3
0
/// Given a reduced list of functions that still exposed the bug, check to see
/// if we can extract the loops in the region without obscuring the bug.  If so,
/// it reduces the amount of code identified.
///
static bool ExtractLoops(BugDriver &BD,
                         bool (*TestFn)(BugDriver &, std::unique_ptr<Module>,
                                        std::unique_ptr<Module>, std::string &),
                         std::vector<Function *> &MiscompiledFunctions,
                         std::string &Error) {
  bool MadeChange = false;
  while (1) {
    if (BugpointIsInterrupted) return MadeChange;

    ValueToValueMapTy VMap;
    std::unique_ptr<Module> ToNotOptimize = CloneModule(BD.getProgram(), VMap);
    Module *ToOptimize = SplitFunctionsOutOfModule(ToNotOptimize.get(),
                                                   MiscompiledFunctions, VMap)
                             .release();
    std::unique_ptr<Module> ToOptimizeLoopExtracted =
        BD.extractLoop(ToOptimize);
    if (!ToOptimizeLoopExtracted) {
      // If the loop extractor crashed or if there were no extractible loops,
      // then this chapter of our odyssey is over with.
      delete ToOptimize;
      return MadeChange;
    }

    errs() << "Extracted a loop from the breaking portion of the program.\n";

    // Bugpoint is intentionally not very trusting of LLVM transformations.  In
    // particular, we're not going to assume that the loop extractor works, so
    // we're going to test the newly loop extracted program to make sure nothing
    // has broken.  If something broke, then we'll inform the user and stop
    // extraction.
    AbstractInterpreter *AI = BD.switchToSafeInterpreter();
    bool Failure;
    std::unique_ptr<Module> New =
        testMergedProgram(BD, std::move(ToOptimizeLoopExtracted),
                          std::move(ToNotOptimize), Error, Failure);
    if (!New)
      return false;

    // Delete the original and set the new program.
    Module *Old = BD.swapProgramIn(New.release());
    for (unsigned i = 0, e = MiscompiledFunctions.size(); i != e; ++i)
      MiscompiledFunctions[i] = cast<Function>(VMap[MiscompiledFunctions[i]]);
    delete Old;

    if (Failure) {
      BD.switchToInterpreter(AI);

      // Merged program doesn't work anymore!
      errs() << "  *** ERROR: Loop extraction broke the program. :("
             << " Please report a bug!\n";
      errs() << "      Continuing on with un-loop-extracted version.\n";

      BD.writeProgramToFile(OutputPrefix + "-loop-extract-fail-tno.bc",
                            ToNotOptimize.get());
      BD.writeProgramToFile(OutputPrefix + "-loop-extract-fail-to.bc",
                            ToOptimize);
      BD.writeProgramToFile(OutputPrefix + "-loop-extract-fail-to-le.bc",
                            ToOptimizeLoopExtracted.get());

      errs() << "Please submit the "
             << OutputPrefix << "-loop-extract-fail-*.bc files.\n";
      delete ToOptimize;
      return MadeChange;
    }
    delete ToOptimize;
    BD.switchToInterpreter(AI);

    outs() << "  Testing after loop extraction:\n";
    // Clone modules, the tester function will free them.
    std::unique_ptr<Module> TOLEBackup =
        CloneModule(ToOptimizeLoopExtracted.get(), VMap);
    std::unique_ptr<Module> TNOBackup = CloneModule(ToNotOptimize.get(), VMap);

    for (unsigned i = 0, e = MiscompiledFunctions.size(); i != e; ++i)
      MiscompiledFunctions[i] = cast<Function>(VMap[MiscompiledFunctions[i]]);

    Failure = TestFn(BD, std::move(ToOptimizeLoopExtracted),
                     std::move(ToNotOptimize), Error);
    if (!Error.empty())
      return false;

    ToOptimizeLoopExtracted = std::move(TOLEBackup);
    ToNotOptimize = std::move(TNOBackup);

    if (!Failure) {
      outs() << "*** Loop extraction masked the problem.  Undoing.\n";
      // If the program is not still broken, then loop extraction did something
      // that masked the error.  Stop loop extraction now.

      std::vector<std::pair<std::string, FunctionType*> > MisCompFunctions;
      for (Function *F : MiscompiledFunctions) {
        MisCompFunctions.emplace_back(F->getName(), F->getFunctionType());
      }

      if (Linker::linkModules(*ToNotOptimize,
                              std::move(ToOptimizeLoopExtracted)))
        exit(1);

      MiscompiledFunctions.clear();
      for (unsigned i = 0, e = MisCompFunctions.size(); i != e; ++i) {
        Function *NewF = ToNotOptimize->getFunction(MisCompFunctions[i].first);

        assert(NewF && "Function not found??");
        MiscompiledFunctions.push_back(NewF);
      }

      BD.setNewProgram(ToNotOptimize.release());
      return MadeChange;
    }

    outs() << "*** Loop extraction successful!\n";

    std::vector<std::pair<std::string, FunctionType*> > MisCompFunctions;
    for (Module::iterator I = ToOptimizeLoopExtracted->begin(),
           E = ToOptimizeLoopExtracted->end(); I != E; ++I)
      if (!I->isDeclaration())
        MisCompFunctions.emplace_back(I->getName(), I->getFunctionType());

    // Okay, great!  Now we know that we extracted a loop and that loop
    // extraction both didn't break the program, and didn't mask the problem.
    // Replace the current program with the loop extracted version, and try to
    // extract another loop.
    if (Linker::linkModules(*ToNotOptimize, std::move(ToOptimizeLoopExtracted)))
      exit(1);

    // All of the Function*'s in the MiscompiledFunctions list are in the old
    // module.  Update this list to include all of the functions in the
    // optimized and loop extracted module.
    MiscompiledFunctions.clear();
    for (unsigned i = 0, e = MisCompFunctions.size(); i != e; ++i) {
      Function *NewF = ToNotOptimize->getFunction(MisCompFunctions[i].first);

      assert(NewF && "Function not found??");
      MiscompiledFunctions.push_back(NewF);
    }

    BD.setNewProgram(ToNotOptimize.release());
    MadeChange = true;
  }
}
Exemplo n.º 4
0
/// Given a reduced list of functions that still expose the bug, extract as many
/// basic blocks from the region as possible without obscuring the bug.
///
static bool ExtractBlocks(BugDriver &BD,
                          bool (*TestFn)(BugDriver &, std::unique_ptr<Module>,
                                         std::unique_ptr<Module>,
                                         std::string &),
                          std::vector<Function *> &MiscompiledFunctions,
                          std::string &Error) {
  if (BugpointIsInterrupted) return false;

  std::vector<BasicBlock*> Blocks;
  for (unsigned i = 0, e = MiscompiledFunctions.size(); i != e; ++i)
    for (BasicBlock &BB : *MiscompiledFunctions[i])
      Blocks.push_back(&BB);

  // Use the list reducer to identify blocks that can be extracted without
  // obscuring the bug.  The Blocks list will end up containing blocks that must
  // be retained from the original program.
  unsigned OldSize = Blocks.size();

  // Check to see if all blocks are extractible first.
  bool Ret = ReduceMiscompiledBlocks(BD, TestFn, MiscompiledFunctions)
                                  .TestFuncs(std::vector<BasicBlock*>(), Error);
  if (!Error.empty())
    return false;
  if (Ret) {
    Blocks.clear();
  } else {
    ReduceMiscompiledBlocks(BD, TestFn,
                            MiscompiledFunctions).reduceList(Blocks, Error);
    if (!Error.empty())
      return false;
    if (Blocks.size() == OldSize)
      return false;
  }

  ValueToValueMapTy VMap;
  Module *ProgClone = CloneModule(BD.getProgram(), VMap).release();
  Module *ToExtract =
      SplitFunctionsOutOfModule(ProgClone, MiscompiledFunctions, VMap)
          .release();
  std::unique_ptr<Module> Extracted =
      BD.extractMappedBlocksFromModule(Blocks, ToExtract);
  if (!Extracted) {
    // Weird, extraction should have worked.
    errs() << "Nondeterministic problem extracting blocks??\n";
    delete ProgClone;
    delete ToExtract;
    return false;
  }

  // Otherwise, block extraction succeeded.  Link the two program fragments back
  // together.
  delete ToExtract;

  std::vector<std::pair<std::string, FunctionType*> > MisCompFunctions;
  for (Module::iterator I = Extracted->begin(), E = Extracted->end();
       I != E; ++I)
    if (!I->isDeclaration())
      MisCompFunctions.emplace_back(I->getName(), I->getFunctionType());

  if (Linker::linkModules(*ProgClone, std::move(Extracted)))
    exit(1);

  // Set the new program and delete the old one.
  BD.setNewProgram(ProgClone);

  // Update the list of miscompiled functions.
  MiscompiledFunctions.clear();

  for (unsigned i = 0, e = MisCompFunctions.size(); i != e; ++i) {
    Function *NewF = ProgClone->getFunction(MisCompFunctions[i].first);
    assert(NewF && "Function not found??");
    MiscompiledFunctions.push_back(NewF);
  }

  return true;
}
Exemplo n.º 5
0
void StatsTracker::writeIStats() {
  Module *m = executor.kmodule->module;
  uint64_t istatsMask = 0;
  llvm::raw_fd_ostream &of = *istatsFile;
  
  // We assume that we didn't move the file pointer
  unsigned istatsSize = of.tell();

  of.seek(0);

  of << "version: 1\n";
  of << "creator: klee\n";
  of << "pid: " << getpid() << "\n";
  of << "cmd: " << m->getModuleIdentifier() << "\n\n";
  of << "\n";
  
  StatisticManager &sm = *theStatisticManager;
  unsigned nStats = sm.getNumStatistics();

  // Max is 13, sadly
  istatsMask |= 1<<sm.getStatisticID("Queries");
  istatsMask |= 1<<sm.getStatisticID("QueriesValid");
  istatsMask |= 1<<sm.getStatisticID("QueriesInvalid");
  istatsMask |= 1<<sm.getStatisticID("QueryTime");
  istatsMask |= 1<<sm.getStatisticID("ResolveTime");
  istatsMask |= 1<<sm.getStatisticID("Instructions");
  istatsMask |= 1<<sm.getStatisticID("InstructionTimes");
  istatsMask |= 1<<sm.getStatisticID("InstructionRealTimes");
  istatsMask |= 1<<sm.getStatisticID("Forks");
  istatsMask |= 1<<sm.getStatisticID("CoveredInstructions");
  istatsMask |= 1<<sm.getStatisticID("UncoveredInstructions");
  istatsMask |= 1<<sm.getStatisticID("States");
  istatsMask |= 1<<sm.getStatisticID("MinDistToUncovered");

  of << "positions: instr line\n";

  for (unsigned i=0; i<nStats; i++) {
    if (istatsMask & (1<<i)) {
      Statistic &s = sm.getStatistic(i);
      of << "event: " << s.getShortName() << " : " 
         << s.getName() << "\n";
    }
  }

  of << "events: ";
  for (unsigned i=0; i<nStats; i++) {
    if (istatsMask & (1<<i))
      of << sm.getStatistic(i).getShortName() << " ";
  }
  of << "\n";
  
  // set state counts, decremented after we process so that we don't
  // have to zero all records each time.
  if (istatsMask & (1<<stats::states.getID()))
    updateStateStatistics(1);

  std::string sourceFile = "";

  CallSiteSummaryTable callSiteStats;
  if (UseCallPaths)
    callPathManager.getSummaryStatistics(callSiteStats);

  of << "ob=" << objectFilename << "\n";

  for (Module::iterator fnIt = m->begin(), fn_ie = m->end(); 
       fnIt != fn_ie; ++fnIt) {
    if (!fnIt->isDeclaration()) {
      // Always try to write the filename before the function name, as otherwise
      // KCachegrind can create two entries for the function, one with an
      // unnamed file and one without.
      const InstructionInfo &ii = executor.kmodule->infos->getFunctionInfo(fnIt);
      if (ii.file != sourceFile) {
        of << "fl=" << ii.file << "\n";
        sourceFile = ii.file;
      }
      
      of << "fn=" << fnIt->getName().str() << "\n";
      for (Function::iterator bbIt = fnIt->begin(), bb_ie = fnIt->end(); 
           bbIt != bb_ie; ++bbIt) {
        for (BasicBlock::iterator it = bbIt->begin(), ie = bbIt->end(); 
             it != ie; ++it) {
          Instruction *instr = &*it;
          const InstructionInfo &ii = executor.kmodule->infos->getInfo(instr);
          unsigned index = ii.id;
          if (ii.file!=sourceFile) {
            of << "fl=" << ii.file << "\n";
            sourceFile = ii.file;
          }
          of << ii.assemblyLine << " ";
          of << ii.line << " ";
          for (unsigned i=0; i<nStats; i++)
            if (istatsMask&(1<<i))
              of << sm.getIndexedValue(sm.getStatistic(i), index) << " ";
          of << "\n";

          if (UseCallPaths && 
              (isa<CallInst>(instr) || isa<InvokeInst>(instr))) {
            CallSiteSummaryTable::iterator it = callSiteStats.find(instr);
            if (it!=callSiteStats.end()) {
              for (std::map<llvm::Function*, CallSiteInfo>::iterator
                     fit = it->second.begin(), fie = it->second.end(); 
                   fit != fie; ++fit) {
                Function *f = fit->first;
                CallSiteInfo &csi = fit->second;
                const InstructionInfo &fii = 
                  executor.kmodule->infos->getFunctionInfo(f);
  
                if (fii.file!="" && fii.file!=sourceFile)
                  of << "cfl=" << fii.file << "\n";
                of << "cfn=" << f->getName().str() << "\n";
                of << "calls=" << csi.count << " ";
                of << fii.assemblyLine << " ";
                of << fii.line << "\n";

                of << ii.assemblyLine << " ";
                of << ii.line << " ";
                for (unsigned i=0; i<nStats; i++) {
                  if (istatsMask&(1<<i)) {
                    Statistic &s = sm.getStatistic(i);
                    uint64_t value;

                    // Hack, ignore things that don't make sense on
                    // call paths.
                    if (&s == &stats::uncoveredInstructions) {
                      value = 0;
                    } else {
                      value = csi.statistics.getValue(s);
                    }

                    of << value << " ";
                  }
                }
                of << "\n";
              }
            }
          }
        }
      }
    }
  }

  if (istatsMask & (1<<stats::states.getID()))
    updateStateStatistics((uint64_t)-1);
  
  // Clear then end of the file if necessary (no truncate op?).
  unsigned pos = of.tell();
  for (unsigned i=pos; i<istatsSize; ++i)
    of << '\n';
  
  of.flush();
}
Exemplo n.º 6
0
int main(int argc, char **argv) {
  // Print a stack trace if we signal out.
  sys::PrintStackTraceOnErrorSignal();
  PrettyStackTraceProgram X(argc, argv);

  LLVMContext &Context = getGlobalContext();
  llvm_shutdown_obj Y;  // Call llvm_shutdown() on exit.
  cl::ParseCommandLineOptions(argc, argv, "llvm extractor\n");

  // Use lazy loading, since we only care about selected global values.
  SMDiagnostic Err;
  std::auto_ptr<Module> M;
  M.reset(getLazyIRFileModule(InputFilename, Err, Context));

  if (M.get() == 0) {
    Err.Print(argv[0], errs());
    return 1;
  }

  // Use SetVector to avoid duplicates.
  SetVector<GlobalValue *> GVs;

  // Figure out which globals we should extract.
  for (size_t i = 0, e = ExtractGlobals.size(); i != e; ++i) {
    GlobalValue *GV = M.get()->getNamedGlobal(ExtractGlobals[i]);
    if (!GV) {
      errs() << argv[0] << ": program doesn't contain global named '"
             << ExtractGlobals[i] << "'!\n";
      return 1;
    }
    GVs.insert(GV);
  }

  // Extract globals via regular expression matching.
  for (size_t i = 0, e = ExtractRegExpGlobals.size(); i != e; ++i) {
    std::string Error;
    Regex RegEx(ExtractRegExpGlobals[i]);
    if (!RegEx.isValid(Error)) {
      errs() << argv[0] << ": '" << ExtractRegExpGlobals[i] << "' "
        "invalid regex: " << Error;
    }
    bool match = false;
    for (Module::global_iterator GV = M.get()->global_begin(), 
           E = M.get()->global_end(); GV != E; GV++) {
      if (RegEx.match(GV->getName())) {
        GVs.insert(&*GV);
        match = true;
      }
    }
    if (!match) {
      errs() << argv[0] << ": program doesn't contain global named '"
             << ExtractRegExpGlobals[i] << "'!\n";
      return 1;
    }
  }

  // Figure out which functions we should extract.
  for (size_t i = 0, e = ExtractFuncs.size(); i != e; ++i) {
    GlobalValue *GV = M.get()->getFunction(ExtractFuncs[i]);
    if (!GV) {
      errs() << argv[0] << ": program doesn't contain function named '"
             << ExtractFuncs[i] << "'!\n";
      return 1;
    }
    GVs.insert(GV);
  }
  // Extract functions via regular expression matching.
  for (size_t i = 0, e = ExtractRegExpFuncs.size(); i != e; ++i) {
    std::string Error;
    StringRef RegExStr = ExtractRegExpFuncs[i];
    Regex RegEx(RegExStr);
    if (!RegEx.isValid(Error)) {
      errs() << argv[0] << ": '" << ExtractRegExpFuncs[i] << "' "
        "invalid regex: " << Error;
    }
    bool match = false;
    for (Module::iterator F = M.get()->begin(), E = M.get()->end(); F != E; 
         F++) {
      if (RegEx.match(F->getName())) {
        GVs.insert(&*F);
        match = true;
      }
    }
    if (!match) {
      errs() << argv[0] << ": program doesn't contain global named '"
             << ExtractRegExpFuncs[i] << "'!\n";
      return 1;
    }
  }

  // Materialize requisite global values.
  if (!DeleteFn)
    for (size_t i = 0, e = GVs.size(); i != e; ++i) {
      GlobalValue *GV = GVs[i];
      if (GV->isMaterializable()) {
        std::string ErrInfo;
        if (GV->Materialize(&ErrInfo)) {
          errs() << argv[0] << ": error reading input: " << ErrInfo << "\n";
          return 1;
        }
      }
    }
  else {
    // Deleting. Materialize every GV that's *not* in GVs.
    SmallPtrSet<GlobalValue *, 8> GVSet(GVs.begin(), GVs.end());
    for (Module::global_iterator I = M->global_begin(), E = M->global_end();
         I != E; ++I) {
      GlobalVariable *G = I;
      if (!GVSet.count(G) && G->isMaterializable()) {
        std::string ErrInfo;
        if (G->Materialize(&ErrInfo)) {
          errs() << argv[0] << ": error reading input: " << ErrInfo << "\n";
          return 1;
        }
      }
    }
    for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) {
      Function *F = I;
      if (!GVSet.count(F) && F->isMaterializable()) {
        std::string ErrInfo;
        if (F->Materialize(&ErrInfo)) {
          errs() << argv[0] << ": error reading input: " << ErrInfo << "\n";
          return 1;
        }
      }
    }
  }

  // In addition to deleting all other functions, we also want to spiff it
  // up a little bit.  Do this now.
  PassManager Passes;
  Passes.add(new TargetData(M.get())); // Use correct TargetData

  std::vector<GlobalValue*> Gvs(GVs.begin(), GVs.end());

  Passes.add(createGVExtractionPass(Gvs, DeleteFn));
  if (!DeleteFn)
    Passes.add(createGlobalDCEPass());           // Delete unreachable globals
  Passes.add(createStripDeadDebugInfoPass());    // Remove dead debug info
  Passes.add(createStripDeadPrototypesPass());   // Remove dead func decls

  std::string ErrorInfo;
  tool_output_file Out(OutputFilename.c_str(), ErrorInfo,
                       raw_fd_ostream::F_Binary);
  if (!ErrorInfo.empty()) {
    errs() << ErrorInfo << '\n';
    return 1;
  }

  if (OutputAssembly)
    Passes.add(createPrintModulePass(&Out.os()));
  else if (Force || !CheckBitcodeOutputToConsole(Out.os(), true))
    Passes.add(createBitcodeWriterPass(Out.os()));

  Passes.run(*M.get());

  // Declare success.
  Out.keep();

  return 0;
}
Exemplo n.º 7
0
/// Based on GetAllUndefinedSymbols() from LLVM3.2
///
/// GetAllUndefinedSymbols - calculates the set of undefined symbols that still
/// exist in an LLVM module. This is a bit tricky because there may be two
/// symbols with the same name but different LLVM types that will be resolved to
/// each other but aren't currently (thus we need to treat it as resolved).
///
/// Inputs:
///  M - The module in which to find undefined symbols.
///
/// Outputs:
///  UndefinedSymbols - A set of C++ strings containing the name of all
///                     undefined symbols.
///
static void
GetAllUndefinedSymbols(Module *M, std::set<std::string> &UndefinedSymbols) {
  static const std::string llvmIntrinsicPrefix="llvm.";
  std::set<std::string> DefinedSymbols;
  UndefinedSymbols.clear();
  KLEE_DEBUG_WITH_TYPE("klee_linker",
                       dbgs() << "*** Computing undefined symbols ***\n");

  for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
    if (I->hasName()) {
      if (I->isDeclaration())
        UndefinedSymbols.insert(I->getName());
      else if (!I->hasLocalLinkage()) {
#if LLVM_VERSION_CODE < LLVM_VERSION(3, 5)
            assert(!I->hasDLLImportLinkage() && "Found dllimported non-external symbol!");
#else
            assert(!I->hasDLLImportStorageClass() && "Found dllimported non-external symbol!");
#endif
        DefinedSymbols.insert(I->getName());
      }
    }

  for (Module::global_iterator I = M->global_begin(), E = M->global_end();
       I != E; ++I)
    if (I->hasName()) {
      if (I->isDeclaration())
        UndefinedSymbols.insert(I->getName());
      else if (!I->hasLocalLinkage()) {
#if LLVM_VERSION_CODE < LLVM_VERSION(3, 5)
            assert(!I->hasDLLImportLinkage() && "Found dllimported non-external symbol!");
#else
            assert(!I->hasDLLImportStorageClass() && "Found dllimported non-external symbol!");
#endif
        DefinedSymbols.insert(I->getName());
      }
    }

  for (Module::alias_iterator I = M->alias_begin(), E = M->alias_end();
       I != E; ++I)
    if (I->hasName())
      DefinedSymbols.insert(I->getName());


  // Prune out any defined symbols from the undefined symbols set
  // and other symbols we don't want to treat as an undefined symbol
  std::vector<std::string> SymbolsToRemove;
  for (std::set<std::string>::iterator I = UndefinedSymbols.begin();
       I != UndefinedSymbols.end(); ++I )
  {
    if (DefinedSymbols.count(*I))
    {
      SymbolsToRemove.push_back(*I);
      continue;
    }

    // Strip out llvm intrinsics
    if ( (I->size() >= llvmIntrinsicPrefix.size() ) &&
       (I->compare(0, llvmIntrinsicPrefix.size(), llvmIntrinsicPrefix) == 0) )
    {
      KLEE_DEBUG_WITH_TYPE("klee_linker", dbgs() << "LLVM intrinsic " << *I <<
                      " has will be removed from undefined symbols"<< "\n");
      SymbolsToRemove.push_back(*I);
      continue;
    }

    // Symbol really is undefined
    KLEE_DEBUG_WITH_TYPE("klee_linker",
                         dbgs() << "Symbol " << *I << " is undefined.\n");
  }

  // Remove KLEE intrinsics from set of undefined symbols
  for (SpecialFunctionHandler::const_iterator sf = SpecialFunctionHandler::begin(),
       se = SpecialFunctionHandler::end(); sf != se; ++sf)
  {
    if (UndefinedSymbols.find(sf->name) == UndefinedSymbols.end())
      continue;

    SymbolsToRemove.push_back(sf->name);
    KLEE_DEBUG_WITH_TYPE("klee_linker",
                         dbgs() << "KLEE intrinsic " << sf->name <<
                         " has will be removed from undefined symbols"<< "\n");
  }

  // Now remove the symbols from undefined set.
  for (size_t i = 0, j = SymbolsToRemove.size(); i < j; ++i )
    UndefinedSymbols.erase(SymbolsToRemove[i]);

  KLEE_DEBUG_WITH_TYPE("klee_linker",
                       dbgs() << "*** Finished computing undefined symbols ***\n");
}
Exemplo n.º 8
0
bool BUDataStructures::runOnModuleInternal(Module& M) {
  std::vector<const Function*> Stack;
  hash_map<const Function*, unsigned> ValMap;
  unsigned NextID = 1;

  Function *MainFunc = M.getFunction("main");
  if (MainFunc && !MainFunc->isDeclaration()) {
    calculateGraphs(MainFunc, Stack, NextID, ValMap);
    CloneAuxIntoGlobal(getDSGraph(MainFunc));
  } else {
    DEBUG(errs() << debugname << ": No 'main' function found!\n");
  }

  // Calculate the graphs for any functions that are unreachable from main...
  for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
    if (!I->isDeclaration() && !hasDSGraph(I)) {
      if (MainFunc)
        DEBUG(errs() << debugname << ": Function unreachable from main: "
	      << I->getName() << "\n");
      calculateGraphs(I, Stack, NextID, ValMap);     // Calculate all graphs.
      CloneAuxIntoGlobal(getDSGraph(I));
    }

  // If we computed any temporary indcallgraphs, free them now.
  for (std::map<std::vector<const Function*>,
         std::pair<DSGraph*, std::vector<DSNodeHandle> > >::iterator I =
         IndCallGraphMap.begin(), E = IndCallGraphMap.end(); I != E; ++I) {
    I->second.second.clear();  // Drop arg refs into the graph.
    delete I->second.first;
  }
  IndCallGraphMap.clear();

  // At the end of the bottom-up pass, the globals graph becomes complete.
  // FIXME: This is not the right way to do this, but it is sorta better than
  // nothing!  In particular, externally visible globals and unresolvable call
  // nodes at the end of the BU phase should make things that they point to
  // incomplete in the globals graph.
  //

  finalizeGlobals();

  GlobalsGraph->removeTriviallyDeadNodes(true);
  GlobalsGraph->maskIncompleteMarkers();

  // Mark external globals incomplete.
  GlobalsGraph->markIncompleteNodes(DSGraph::IgnoreGlobals);

  formGlobalECs();

  // Merge the globals variables (not the calls) from the globals graph back
  // into the main function's graph so that the main function contains all of
  // the information about global pools and GV usage in the program.
  if (MainFunc && !MainFunc->isDeclaration()) {
    DSGraph* MainGraph = getDSGraph(MainFunc);
    const DSGraph* GG = MainGraph->getGlobalsGraph();
    ReachabilityCloner RC(MainGraph, GG,
                          DSGraph::DontCloneCallNodes |
                          DSGraph::DontCloneAuxCallNodes);

    // Clone the global nodes into this graph.
    for (DSScalarMap::global_iterator I = GG->getScalarMap().global_begin(),
           E = GG->getScalarMap().global_end(); I != E; ++I)
      if (isa<GlobalVariable>(*I))
        RC.getClonedNH(GG->getNodeForValue(*I));

    MainGraph->maskIncompleteMarkers();
    MainGraph->markIncompleteNodes(DSGraph::MarkFormalArgs |
                                   DSGraph::IgnoreGlobals);
  }

  NumCallEdges += callee.size();

  return false;
}
Exemplo n.º 9
0
Module *klee::linkWithLibrary(Module *module,
                              const std::string &libraryName,
                              std::set<std::string>* kleeFunctions,
                              std::set<std::string>* intrinsicFunctions) {
    DEBUG_WITH_TYPE("klee_linker", dbgs() << "Linking file " << libraryName << "\n");
#if LLVM_VERSION_CODE >= LLVM_VERSION(3, 3)
    if (!sys::fs::exists(libraryName)) {
        klee_error("Link with library %s failed. No such file.",
                   libraryName.c_str());
    }

    OwningPtr<MemoryBuffer> Buffer;
    if (error_code ec = MemoryBuffer::getFile(libraryName,Buffer)) {
        klee_error("Link with library %s failed: %s", libraryName.c_str(),
                   ec.message().c_str());
    }

    sys::fs::file_magic magic = sys::fs::identify_magic(Buffer->getBuffer());

    LLVMContext &Context = getGlobalContext();
    std::string ErrorMessage;

    if (magic == sys::fs::file_magic::bitcode) {
        Module *Result = 0;
        Result = ParseBitcodeFile(Buffer.get(), Context, &ErrorMessage);


        if (!Result || Linker::LinkModules(module, Result, Linker::DestroySource,
                                           &ErrorMessage))
            klee_error("Link with library %s failed: %s", libraryName.c_str(),
                       ErrorMessage.c_str());

        if (kleeFunctions && intrinsicFunctions) {
            for (Module::iterator fi = Result->begin(), fe = Result->end(); fi != fe; fi++) {
                std::string functionName = fi->getName().str();
                if (fi->getName().startswith("klee") || fi->getName().startswith("llvm")) {
                    kleeFunctions->insert(functionName);
                } else {
                    intrinsicFunctions->insert(functionName);
                }
            }
        }

        delete Result;

    } else if (magic == sys::fs::file_magic::archive) {
        OwningPtr<object::Binary> arch;
        if (error_code ec = object::createBinary(Buffer.take(), arch))
            klee_error("Link with library %s failed: %s", libraryName.c_str(),
                       ec.message().c_str());

        if (object::Archive *a = dyn_cast<object::Archive>(arch.get())) {
            // Handle in helper
            if (!linkBCA(a, module, ErrorMessage))
                klee_error("Link with library %s failed: %s", libraryName.c_str(),
                           ErrorMessage.c_str());
        }
        else {
            klee_error("Link with library %s failed: Cast to archive failed", libraryName.c_str());
        }

    } else if (magic.is_object()) {
        OwningPtr<object::Binary> obj;
        if (object::ObjectFile *o = dyn_cast<object::ObjectFile>(obj.get())) {
            klee_warning("Link with library: Object file %s in archive %s found. "
                         "Currently not supported.",
                         o->getFileName().data(), libraryName.c_str());
        }
    } else {
        klee_error("Link with library %s failed: Unrecognized file type.",
                   libraryName.c_str());
    }

    return module;
#else
    Linker linker("klee", module, false);

    llvm::sys::Path libraryPath(libraryName);
    bool native = false;

    if (linker.LinkInFile(libraryPath, native)) {
        klee_error("Linking library %s failed", libraryName.c_str());
    }

    return linker.releaseModule();
#endif
}
Exemplo n.º 10
0
bool InternalizePass::runOnModule(Module &M) {
  CallGraph *CG = getAnalysisIfAvailable<CallGraph>();
  CallGraphNode *ExternalNode = CG ? CG->getExternalCallingNode() : 0;
  bool Changed = false;

  // Never internalize functions which code-gen might insert.
  // FIXME: We should probably add this (and the __stack_chk_guard) via some
  // type of call-back in CodeGen.
  ExternalNames.insert("__stack_chk_fail");

  // Mark all functions not in the api as internal.
  // FIXME: maybe use private linkage?
  for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
    if (!I->isDeclaration() &&         // Function must be defined here
        // Available externally is really just a "declaration with a body".
        !I->hasAvailableExternallyLinkage() &&
        !I->hasLocalLinkage() &&  // Can't already have internal linkage
        !ExternalNames.count(I->getName())) {// Not marked to keep external?
      I->setLinkage(GlobalValue::InternalLinkage);
      // Remove a callgraph edge from the external node to this function.
      if (ExternalNode) ExternalNode->removeOneAbstractEdgeTo((*CG)[I]);
      Changed = true;
      ++NumFunctions;
      DEBUG(dbgs() << "Internalizing func " << I->getName() << "\n");
    }

  // Never internalize the llvm.used symbol.  It is used to implement
  // attribute((used)).
  // FIXME: Shouldn't this just filter on llvm.metadata section??
  ExternalNames.insert("llvm.used");
  ExternalNames.insert("llvm.compiler.used");

  // Never internalize anchors used by the machine module info, else the info
  // won't find them.  (see MachineModuleInfo.)
  ExternalNames.insert("llvm.global_ctors");
  ExternalNames.insert("llvm.global_dtors");
  ExternalNames.insert("llvm.global.annotations");

  // Never internalize symbols code-gen inserts.
  ExternalNames.insert("__stack_chk_guard");

  // Mark all global variables with initializers that are not in the api as
  // internal as well.
  // FIXME: maybe use private linkage?
  for (Module::global_iterator I = M.global_begin(), E = M.global_end();
       I != E; ++I)
    if (!I->isDeclaration() && !I->hasLocalLinkage() &&
        // Available externally is really just a "declaration with a body".
        !I->hasAvailableExternallyLinkage() &&
        !ExternalNames.count(I->getName())) {
      I->setLinkage(GlobalValue::InternalLinkage);
      Changed = true;
      ++NumGlobals;
      DEBUG(dbgs() << "Internalized gvar " << I->getName() << "\n");
    }

  // Mark all aliases that are not in the api as internal as well.
  for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end();
       I != E; ++I)
    if (!I->isDeclaration() && !I->hasInternalLinkage() &&
        // Available externally is really just a "declaration with a body".
        !I->hasAvailableExternallyLinkage() &&
        !ExternalNames.count(I->getName())) {
      I->setLinkage(GlobalValue::InternalLinkage);
      Changed = true;
      ++NumAliases;
      DEBUG(dbgs() << "Internalized alias " << I->getName() << "\n");
    }

  return Changed;
}
Exemplo n.º 11
0
bool InvLoadInstrumenter::runOnModule(Module &M) {
  Function *Main = M.getFunction("main");
  LLVMContext &C = M.getContext();
  
  cerr << "instrument: --- Load Invariant ---\n";

  if (Main == 0) {
    cerr << "WARNING: cannot insert load instrumentation into a module"
         << " with no main function!\n";
    return false;  // No main, no instrumentation!
  }

  // Add library function prototypes
  Constant *LoadDoubleFn = M.getOrInsertFunction("_handleInvariantChangeDouble", 
                              Type::getVoidTy(C),   // returns void
                              Type::getInt32Ty(C),  // invTypeIndex
                              Type::getInt32Ty(C),  // invIndex
                              Type::getDoubleTy(C), // val
                              NULL);
  Constant *LoadIntegerFn = M.getOrInsertFunction("_handleInvariantChangeInt", 
                              Type::getVoidTy(C),   // returns void
                              Type::getInt32Ty(C),  // invTypeIndex
                              Type::getInt32Ty(C),  // invIndex
                              Type::getInt32Ty(C),  // val
                              NULL);
  Constant *LoadPointerFn = M.getOrInsertFunction("_handleInvariantChangePtr", 
                              Type::getVoidTy(C),   // returns void
                              Type::getInt32Ty(C),  // invTypeIndex
                              Type::getInt32Ty(C),  // invIndex
                              PointerType::getUnqual(Type::getInt32Ty(C)),  // val
                              NULL);
  Constant *LoadUintFn = M.getOrInsertFunction("_handleInvariantChangeUInt", 
                              Type::getVoidTy(C),   // returns void
                              Type::getInt32Ty(C),  // invTypeIndex
                              Type::getInt32Ty(C),  // invIndex
                              Type::getInt32Ty(C),  // val
                              NULL);

  TargetData targetData(&M);
  unsigned int nInvariants = 0;
  unsigned int invariantTypeIndex = IndexManager::getInvariantTypeIndex();
  
  // Loop through all functions within module
  for (Module::iterator F = M.begin(), ME = M.end(); F != ME; ++F) {
    std::string dir="-", file="-", name="-";
    int line = 0;
          
    // skip the _registerAll function
    if(F->getName()=="_registerAll")
      continue;

    // Loop through all basic blocks within function
    for (Function::iterator B = F->begin(), FE = F->end(); B != FE; ++B) {
      // Loop through all instructions within basic block
      for (BasicBlock::iterator I = B->begin(), BE = B->end(); I != BE; I++) {

        // remember information of the last known debug stoppoint
        if(isa<DbgStopPointInst>(*I)) {
          DbgStopPointInst &DSPI = cast<DbgStopPointInst>(*I);
          
          llvm::GetConstantStringInfo(DSPI.getDirectory(), dir);
          llvm::GetConstantStringInfo(DSPI.getFileName(), file);
          line = DSPI.getLine();
        }

        // Consider only load instructions
        if(isa<LoadInst>(*I)) {
          LoadInst &LD = cast<LoadInst>(*I);
          Value *Val = LD.getOperand(0);        // value to be loaded
          const Type *InstType = LD.getType();  // type of loaded value
          std::vector<Value*> Args(3);
          
          // try to get name of the loaded value:
          // "variableName"
          // "-" if it cannot be found
          if(Val->hasName()) {
            name = Val->getName();
          } else if(Val->getUnderlyingObject()->hasName()) {
            name = Val->getUnderlyingObject()->getName();
          } else {
            name = "-";
          }

          // add source context of this invariant to context file
          ContextManager::addInvariantTypeContext(
            invariantTypeIndex,     // invariantTypeIndex
            nInvariants,            // invariantIndex
            dir,                    // path
            file,                   // file
            line,                   // line
            name);                  // name
          
          // needs to be instrumented after the value has been loaded
          I++;

          // insert call to correct library function,
          // which depends on the type of the loaded value,
          // after the current load instruction
          if(InstType->isInteger()) {
            Args[0] = ConstantInt::get(Type::getInt32Ty(C), invariantTypeIndex);
            Args[1] = ConstantInt::get(Type::getInt32Ty(C), nInvariants++);
            Args[2] = CastInst::CreateIntegerCast(&LD, Type::getInt32Ty(C), true, "ld.cast", I);
            CallInst::Create(LoadIntegerFn, Args.begin(), Args.end(), "", I);
          } else if(InstType->isFloatingPoint()) {
            Args[0] = ConstantInt::get(Type::getInt32Ty(C), invariantTypeIndex);
            Args[1] = ConstantInt::get(Type::getInt32Ty(C), nInvariants++);
            Args[2] = CastInst::CreateFPCast(&LD, Type::getDoubleTy(C), "ld.cast", I);
            CallInst::Create(LoadDoubleFn, Args.begin(), Args.end(), "", I);
          } else if(isa<PointerType>(InstType)) {
            Args[0] = ConstantInt::get(Type::getInt32Ty(C), invariantTypeIndex);
            Args[1] = ConstantInt::get(Type::getInt32Ty(C), nInvariants++);
            Args[2] = CastInst::CreatePointerCast(&LD, PointerType::getUnqual(Type::getInt32Ty(C)), "ld.cast", I);
            CallInst::Create(LoadPointerFn, Args.begin(), Args.end(), "", I);
          } else {
            Args[0] = ConstantInt::get(Type::getInt32Ty(C), invariantTypeIndex);
            Args[1] = ConstantInt::get(Type::getInt32Ty(C), nInvariants++);
            Args[2] = ConstantInt::get(Type::getInt32Ty(C), 0);
            CallInst::Create(LoadUintFn, Args.begin(), Args.end(), "", I);
          }

          I--;
        }
      }
    }
  }

  // add the registration of the instrumented invariants in the _registerAll() function
  addInvariantTypeRegistration(M, invariantTypeIndex, nInvariants, "Loads", 0);
  
  llvm::cerr << "instrument: " << nInvariants << " load operations instrumented\n";
  
  // notify change of program 
  return true;
}
Exemplo n.º 12
0
void ComputeSSO::HandleQueries(Module& M)
{

    for(set<QueryInput*>::iterator qit = queryinputs.begin();qit!=queryinputs.end();++qit)
    {
        bool constCheck;
        errs()<<"\n\n\n\n*******************************************************Query ";
        errs()<<"\nOperation : "<<(*qit)->operation;
        errs()<<"\nConstCheck : "<<(*qit)->constcheck;
        string operation = (*qit)->operation;
        set<string> labels = (*qit)->labels;
        set<Value*> vals = (*qit)->labVals;
        std::set<GraphNode*> taintedA;
        std::set<GraphNode*> taintedB;
        std::set<GraphNode*> intersectGraph;

        for(set<string>::iterator label = labels.begin();label != labels.end();++label)
            errs()<<" - "<<*label;
        errs()<<"\n*******************************************************\n ";

        constCheck = (*qit)->constcheck;
        if(constCheck)
        {
            for(set<Value*>::iterator val = vals.begin();val != vals.end();++val)
            {
                taintedA = taintGraphMap[*val];
            }
            intersectGraph = taintedA;
        }
        else
        {

            for(set<Value*>::iterator val = vals.begin();val != vals.end();++val)
            {
                taintedA = taintGraphMap[*val];
                ++val;
                if(val!=vals.end())
                    taintedB = taintGraphMap[*val];
            }
            if(strcmp(operation.c_str(),"intersect")==0)
            {
                //  intersectGraph = getIntersect(taintedA,taintedB);

                for(set<GraphNode*>::iterator gnode = taintedA.begin();gnode != taintedA.end();++gnode)
                {
                    if(taintedB.count(*gnode) > 0)
                    {
                        GraphNode* interNode = (*gnode)->clone();
                        intersectGraph.insert(interNode);
                    }

                }
            }
        }





        int branches =0;
        errs()<<"\n Intersect graph size :"<<intersectGraph.size();
        //print intersect graph nodes:

        //     PrintTainted(intersectGraph);

        //        for(set<GraphNode*>::iterator gnode = intersectGraph.begin();gnode != intersectGraph.end();++gnode)
        //        {
        //            errs()<<"\n Node: "<<(*gnode)->getLabel();
        //        }

        //Print appropriate vals....:
        for (Module::iterator F = M.begin(), endF = M.end(); F != endF; ++F) {
            string funcName = F->getName();
            //  errs()<<"\nTaints in function: "<<funcName;
            for (Function::iterator BB = F->begin(), endBB = F->end(); BB != endBB; ++BB) {
                string bbName ="noName";
                if(BB->hasName())
                {
                    bbName = BB->getName();
                }
                //  errs()<<" - block: "<<bbName;

                for (BasicBlock::iterator I = BB->begin(), endI = BB->end(); I
                     != endI; ++I) {
                    GraphNode* g = depGraph->findNode(I);
                    if (intersectGraph.count(g)) {
                        errs()<<"\n Node found..:";
                        I->dump();

                            errs()<<"Taint in function : "<<funcName<<"  :";
                            I->dump();

                            if (BranchInst *BI = dyn_cast<BranchInst>(I))
                            {
                                if(constCheck)
                                {
                                    Value* conditional = BI->getCondition();

                                    for (unsigned int i = 0; i < cast<User> (conditional)->getNumOperands(); i++)
                                    {
                                        Value *v1 = cast<User> (conditional)->getOperand(i);
                                        if(isa<ConstantInt>(v1))
                                        {
                                            errs()<<"Branch Inst tainted in func : "<<funcName<<"  :";
                                            BI->dump();
                                            branches++;
                                        }

                                    }

                                }
                                else
                                {
                                    //    BI->getCondition()->dump();
                                    errs()<<"Branch Inst tainted : ";
                                    BI->dump();
                                    branches++;
                                }
                            }

                    }
                }
            }
        }


        errs()<<"\n Number of conditionals tainted : " <<branches;
    }

    errs()<<"\n*******************************************************\n ";
}
Exemplo n.º 13
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);
}
Exemplo n.º 14
0
bool PoolAllocateSimple::runOnModule(Module &M) {
  if (M.begin() == M.end()) return false;

  //
  // Get pointers to 8 and 32 bit LLVM integer types.
  //
  VoidType  = Type::getVoidTy(M.getContext());
  Int8Type  = IntegerType::getInt8Ty(M.getContext());
  Int32Type = IntegerType::getInt32Ty(M.getContext());

  // Get the Target Data information and the Graphs
  if (CompleteDSA) {
    Graphs = &getAnalysis<EQTDDataStructures>();
  } else {
    Graphs = &getAnalysis<BasicDataStructures>();
  }
  assert (Graphs && "No DSA pass available!\n");
  DataLayout & TD = getAnalysis<DataLayout>();

  // Add the pool* prototypes to the module
  AddPoolPrototypes(&M);

  //
  // Create a single DSGraph which contains all of the information found in all
  // the DSGraphs we got from DSA.  We do this because we're going to start
  // making modifications to the points-to results.
  //
  GlobalECs = Graphs->getGlobalECs();
  CombinedDSGraph = new DSGraph (GlobalECs,
                                 TD,
                                 Graphs->getTypeSS(),
                                 Graphs->getGlobalsGraph());
  for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) {
    if (Graphs->hasDSGraph (*I))
      CombinedDSGraph->cloneInto (Graphs->getDSGraph(*I));
  }

  //
  // Now fold all of the heap nodes in our DSGraph (i.e., make them
  // type-unknown).  We do this because heap nodes may change type if we
  // consider the effects of dangling pointers.
  //
  FoldNodesInDSGraph (*CombinedDSGraph);
  FoldNodesInDSGraph (*(CombinedDSGraph->getGlobalsGraph()));

  //
  // Create the global pool.
  //
  TheGlobalPool = CreateGlobalPool(1, 1, M);

  //
  // Now that all call targets are available, rewrite the function bodies of
  // the clones.
  //
  for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) {
    //
    // Skip functions that this pass added.
    //
    std::string name = I->getName();
    if (name == "__poolalloc_init") continue;
    if (name == PoolInit->getName().str()) continue;

    //
    // Skip declarations.
    //
    if (!(I->isDeclaration()))
      ProcessFunctionBodySimple(*I, TD);
  }

  return true;
}
Exemplo n.º 15
0
bool LoaderPass::runOnModule(Module &M) {
  ProfileInfoLoader PIL("profile-loader", Filename);

  EdgeInformation.clear();
  std::vector<unsigned> Counters = PIL.getRawEdgeCounts();
  if (Counters.size() > 0) {
    ReadCount = 0;
    for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) {
      if (F->isDeclaration()) continue;
      DEBUG(dbgs() << "Working on " << F->getName() << "\n");
      readEdge(getEdge(0,&F->getEntryBlock()), Counters);
      for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
        TerminatorInst *TI = BB->getTerminator();
        for (unsigned s = 0, e = TI->getNumSuccessors(); s != e; ++s) {
          readEdge(getEdge(BB,TI->getSuccessor(s)), Counters);
        }
      }
    }
    if (ReadCount != Counters.size()) {
      errs() << "WARNING: profile information is inconsistent with "
             << "the current program!\n";
    }
    NumEdgesRead = ReadCount;
  }

  Counters = PIL.getRawOptimalEdgeCounts();
  if (Counters.size() > 0) {
    ReadCount = 0;
    for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) {
      if (F->isDeclaration()) continue;
      DEBUG(dbgs() << "Working on " << F->getName() << "\n");
      readEdge(getEdge(0,&F->getEntryBlock()), Counters);
      for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
        TerminatorInst *TI = BB->getTerminator();
        if (TI->getNumSuccessors() == 0) {
          readEdge(getEdge(BB,0), Counters);
        }
        for (unsigned s = 0, e = TI->getNumSuccessors(); s != e; ++s) {
          readEdge(getEdge(BB,TI->getSuccessor(s)), Counters);
        }
      }
      while (SpanningTree.size() > 0) {

        unsigned size = SpanningTree.size();

        BBisUnvisited.clear();
        for (std::set<Edge>::iterator ei = SpanningTree.begin(),
             ee = SpanningTree.end(); ei != ee; ++ei) {
          BBisUnvisited.insert(ei->first);
          BBisUnvisited.insert(ei->second);
        }
        while (BBisUnvisited.size() > 0) {
          recurseBasicBlock(*BBisUnvisited.begin());
        }

        if (SpanningTree.size() == size) {
          DEBUG(dbgs()<<"{");
          for (std::set<Edge>::iterator ei = SpanningTree.begin(),
               ee = SpanningTree.end(); ei != ee; ++ei) {
            DEBUG(dbgs()<< *ei <<",");
          }
          assert(0 && "No edge calculated!");
        }

      }
    }
    if (ReadCount != Counters.size()) {
      errs() << "WARNING: profile information is inconsistent with "
             << "the current program!\n";
    }
    NumEdgesRead = ReadCount;
  }

  BlockInformation.clear();
  Counters = PIL.getRawBlockCounts();
  if (Counters.size() > 0) {
    ReadCount = 0;
    for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) {
      if (F->isDeclaration()) continue;
      for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB)
        if (ReadCount < Counters.size())
          // Here the data realm changes from the unsigned of the file to the
          // double of the ProfileInfo. This conversion is save because we know
          // that everything thats representable in unsinged is also
          // representable in double.
          BlockInformation[F][BB] = (double)Counters[ReadCount++];
    }
    if (ReadCount != Counters.size()) {
      errs() << "WARNING: profile information is inconsistent with "
             << "the current program!\n";
    }
  }

  FunctionInformation.clear();
  Counters = PIL.getRawFunctionCounts();
  if (Counters.size() > 0) {
    ReadCount = 0;
    for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) {
      if (F->isDeclaration()) continue;
      if (ReadCount < Counters.size())
        // Here the data realm changes from the unsigned of the file to the
        // double of the ProfileInfo. This conversion is save because we know
        // that everything thats representable in unsinged is also
        // representable in double.
        FunctionInformation[F] = (double)Counters[ReadCount++];
    }
    if (ReadCount != Counters.size()) {
      errs() << "WARNING: profile information is inconsistent with "
             << "the current program!\n";
    }
  }

  return false;
}
/// ExtractLoops - Given a reduced list of functions that still exposed the bug,
/// check to see if we can extract the loops in the region without obscuring the
/// bug.  If so, it reduces the amount of code identified.
///
static bool ExtractLoops(BugDriver &BD,
                         bool (*TestFn)(BugDriver &, Module *, Module *),
                         std::vector<Function*> &MiscompiledFunctions) {
  bool MadeChange = false;
  while (1) {
    if (BugpointIsInterrupted) return MadeChange;
    
    DenseMap<const Value*, Value*> ValueMap;
    Module *ToNotOptimize = CloneModule(BD.getProgram(), ValueMap);
    Module *ToOptimize = SplitFunctionsOutOfModule(ToNotOptimize,
                                                   MiscompiledFunctions,
                                                   ValueMap);
    Module *ToOptimizeLoopExtracted = BD.ExtractLoop(ToOptimize);
    if (!ToOptimizeLoopExtracted) {
      // If the loop extractor crashed or if there were no extractible loops,
      // then this chapter of our odyssey is over with.
      delete ToNotOptimize;
      delete ToOptimize;
      return MadeChange;
    }

    errs() << "Extracted a loop from the breaking portion of the program.\n";

    // Bugpoint is intentionally not very trusting of LLVM transformations.  In
    // particular, we're not going to assume that the loop extractor works, so
    // we're going to test the newly loop extracted program to make sure nothing
    // has broken.  If something broke, then we'll inform the user and stop
    // extraction.
    AbstractInterpreter *AI = BD.switchToSafeInterpreter();
    if (TestMergedProgram(BD, ToOptimizeLoopExtracted, ToNotOptimize, false)) {
      BD.switchToInterpreter(AI);

      // Merged program doesn't work anymore!
      errs() << "  *** ERROR: Loop extraction broke the program. :("
             << " Please report a bug!\n";
      errs() << "      Continuing on with un-loop-extracted version.\n";

      BD.writeProgramToFile(OutputPrefix + "-loop-extract-fail-tno.bc",
                            ToNotOptimize);
      BD.writeProgramToFile(OutputPrefix + "-loop-extract-fail-to.bc",
                            ToOptimize);
      BD.writeProgramToFile(OutputPrefix + "-loop-extract-fail-to-le.bc",
                            ToOptimizeLoopExtracted);

      errs() << "Please submit the " 
             << OutputPrefix << "-loop-extract-fail-*.bc files.\n";
      delete ToOptimize;
      delete ToNotOptimize;
      delete ToOptimizeLoopExtracted;
      return MadeChange;
    }
    delete ToOptimize;
    BD.switchToInterpreter(AI);

    outs() << "  Testing after loop extraction:\n";
    // Clone modules, the tester function will free them.
    Module *TOLEBackup = CloneModule(ToOptimizeLoopExtracted);
    Module *TNOBackup  = CloneModule(ToNotOptimize);
    if (!TestFn(BD, ToOptimizeLoopExtracted, ToNotOptimize)) {
      outs() << "*** Loop extraction masked the problem.  Undoing.\n";
      // If the program is not still broken, then loop extraction did something
      // that masked the error.  Stop loop extraction now.
      delete TOLEBackup;
      delete TNOBackup;
      return MadeChange;
    }
    ToOptimizeLoopExtracted = TOLEBackup;
    ToNotOptimize = TNOBackup;

    outs() << "*** Loop extraction successful!\n";

    std::vector<std::pair<std::string, const FunctionType*> > MisCompFunctions;
    for (Module::iterator I = ToOptimizeLoopExtracted->begin(),
           E = ToOptimizeLoopExtracted->end(); I != E; ++I)
      if (!I->isDeclaration())
        MisCompFunctions.push_back(std::make_pair(I->getName(),
                                                  I->getFunctionType()));

    // Okay, great!  Now we know that we extracted a loop and that loop
    // extraction both didn't break the program, and didn't mask the problem.
    // Replace the current program with the loop extracted version, and try to
    // extract another loop.
    std::string ErrorMsg;
    if (Linker::LinkModules(ToNotOptimize, ToOptimizeLoopExtracted, &ErrorMsg)){
      errs() << BD.getToolName() << ": Error linking modules together:"
             << ErrorMsg << '\n';
      exit(1);
    }
    delete ToOptimizeLoopExtracted;

    // All of the Function*'s in the MiscompiledFunctions list are in the old
    // module.  Update this list to include all of the functions in the
    // optimized and loop extracted module.
    MiscompiledFunctions.clear();
    for (unsigned i = 0, e = MisCompFunctions.size(); i != e; ++i) {
      Function *NewF = ToNotOptimize->getFunction(MisCompFunctions[i].first);
                                                  
      assert(NewF && "Function not found??");
      assert(NewF->getFunctionType() == MisCompFunctions[i].second && 
             "found wrong function type?");
      MiscompiledFunctions.push_back(NewF);
    }

    BD.setNewProgram(ToNotOptimize);
    MadeChange = true;
  }
}
Exemplo n.º 17
0
// the verifier iterates through each path to gather the total
// number of edge frequencies
bool PathProfileVerifier::runOnModule (Module &M) {
    PathProfileInfo& pathProfileInfo = getAnalysis<PathProfileInfo>();

    // setup a data structure to map path edges which index an
    // array of edge counters
    NestedBlockToIndexMap arrayMap;
    unsigned i = 0;
    for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) {
        if (F->isDeclaration()) continue;

        arrayMap[0][F->begin()][0] = i++;

        for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
            TerminatorInst *TI = BB->getTerminator();

            unsigned duplicate = 0;
            BasicBlock* prev = 0;
            for (unsigned s = 0, e = TI->getNumSuccessors(); s != e;
                    prev = TI->getSuccessor(s), ++s) {
                if (prev == TI->getSuccessor(s))
                    duplicate++;
                else duplicate = 0;

                arrayMap[BB][TI->getSuccessor(s)][duplicate] = i++;
            }
        }
    }

    std::vector<unsigned> edgeArray(i);

    // iterate through each path and increment the edge counters as needed
    for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) {
        if (F->isDeclaration()) continue;

        pathProfileInfo.setCurrentFunction(F);

        DEBUG(dbgs() << "function '" << F->getName() << "' ran "
              << pathProfileInfo.pathsRun()
              << "/" << pathProfileInfo.getPotentialPathCount()
              << " potential paths\n");

        for( ProfilePathIterator nextPath = pathProfileInfo.pathBegin(),
                endPath = pathProfileInfo.pathEnd();
                nextPath != endPath; nextPath++ ) {
            ProfilePath* currentPath = nextPath->second;

            ProfilePathEdgeVector* pev = currentPath->getPathEdges();
            DEBUG(dbgs () << "path #" << currentPath->getNumber() << ": "
                  << currentPath->getCount() << "\n");
            // setup the entry edge (normally path profiling doesn't care about this)
            if (currentPath->getFirstBlockInPath() == &F->getEntryBlock())
                edgeArray[arrayMap[0][currentPath->getFirstBlockInPath()][0]]
                += currentPath->getCount();

            for( ProfilePathEdgeIterator nextEdge = pev->begin(),
                    endEdge = pev->end(); nextEdge != endEdge; nextEdge++ ) {
                if (nextEdge != pev->begin())
                    DEBUG(dbgs() << " :: ");

                BasicBlock* source = nextEdge->getSource();
                BasicBlock* target = nextEdge->getTarget();
                unsigned duplicateNumber = nextEdge->getDuplicateNumber();
                DEBUG(dbgs () << source->getNameStr() << " --{" << duplicateNumber
                      << "}--> " << target->getNameStr());

                // Ensure all the referenced edges exist
                // TODO: make this a separate function
                if( !arrayMap.count(source) ) {
                    errs() << "  error [" << F->getNameStr() << "()]: source '"
                           << source->getNameStr()
                           << "' does not exist in the array map.\n";
                } else if( !arrayMap[source].count(target) ) {
                    errs() << "  error [" << F->getNameStr() << "()]: target '"
                           << target->getNameStr()
                           << "' does not exist in the array map.\n";
                } else if( !arrayMap[source][target].count(duplicateNumber) ) {
                    errs() << "  error [" << F->getNameStr() << "()]: edge "
                           << source->getNameStr() << " -> " << target->getNameStr()
                           << " duplicate number " << duplicateNumber
                           << " does not exist in the array map.\n";
                } else {
                    edgeArray[arrayMap[source][target][duplicateNumber]]
                    += currentPath->getCount();
                }
            }

            DEBUG(errs() << "\n");

            delete pev;
        }
    }

    std::string errorInfo;
    std::string filename = EdgeProfileFilename;

    // Open a handle to the file
    FILE* edgeFile = fopen(filename.c_str(),"wb");

    if (!edgeFile) {
        errs() << "error: unable to open file '" << filename << "' for output.\n";
        return false;
    }

    errs() << "Generating edge profile '" << filename << "' ...\n";

    // write argument info
    unsigned type = ArgumentInfo;
    unsigned num = pathProfileInfo.argList.size();
    int zeros = 0;

    fwrite(&type,sizeof(unsigned),1,edgeFile);
    fwrite(&num,sizeof(unsigned),1,edgeFile);
    fwrite(pathProfileInfo.argList.c_str(),1,num,edgeFile);
    if (num&3)
        fwrite(&zeros, 1, 4-(num&3), edgeFile);

    type = EdgeInfo;
    num = edgeArray.size();
    fwrite(&type,sizeof(unsigned),1,edgeFile);
    fwrite(&num,sizeof(unsigned),1,edgeFile);

    // write each edge to the file
    for( std::vector<unsigned>::iterator s = edgeArray.begin(),
            e = edgeArray.end(); s != e; s++)
        fwrite(&*s, sizeof (unsigned), 1, edgeFile);

    fclose (edgeFile);

    return true;
}