Esempio n. 1
0
 void add_thread (ThreadId t, CFG cfg, 
                  VarNameIt sh_begin, VarNameIt sh_end)
     
 {
   auto it = m_cfg_map.find (t);
   if (it != m_cfg_map.end ())
     return;
   
   std::set<varname_t> shared_vs;
   shared_vs.insert (sh_begin, sh_end);
   
   std::set<varname_t> local_vs;
   for (auto &b: boost::make_iterator_range (cfg.begin (), cfg.end ()))
   {
     for (auto &s: b)
     {
       auto ls = s.getLive ();
       if (ls.defs_begin () != ls.defs_end ())
         local_vs.insert (ls.defs_begin (), ls.defs_end ());
       if (ls.uses_begin () != ls.uses_end ())
         local_vs.insert (ls.uses_begin (), ls.uses_end ());
     }
   }
   set_difference (local_vs, shared_vs);
   
   m_cfg_map.insert (std::make_pair (t, cfg));
   m_gv_map.insert (std::make_pair (t, shared_vs));
   m_lv_map.insert (std::make_pair (t, local_vs));
 }
Esempio n. 2
0
void MainWindow::on_actionLoad_XML_triggered()
{
    scene->clear();
    graph.clear();

    QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"), "", "Files (*.xml)", NULL);
    CFG cfg = parser.getCFG(fileName);

    // add all blocks
    for(Block block : cfg.getBlocks()) {
        Node* node = new Node(block.getName(), 50, 50);
        node->setX(qrand() % ((500 + 1) - (-500)) + (-500));
        node->setY(qrand() % ((500 + 1) - (-500)) + (-500));
        scene->addItem(node);
        graph.addNode(node);
    }

    // add all edges
    for(Block block : cfg.getBlocks()) {
        AbstractNode* from = graph.getNode(block.getName());
        for(QString succName : block.getSuccessors()) {
            AbstractNode* to = graph.getNode(succName);
            EdgeItem* edge = new EdgeItem(from,to,true);
            edge->adjust();
            scene->addItem(edge);
            graph.addEdge(from,to,edge);
        }
    }

    graph.setStart(graph.getNode(cfg.getStart().getName()));
}
Esempio n. 3
0
void AnalysisConsumer::HandleCode(Decl *D, AnalysisMode Mode,
                                  SetOfConstDecls *VisitedCallees) {
  if (!D->hasBody())
    return;
  Mode = getModeForDecl(D, Mode);
  if (Mode == AM_None)
    return;
//  DisplayFunction(D, Mode, IMode);
  CFG *DeclCFG = Mgr->getCFG(D);
  if (DeclCFG) {
    unsigned CFGSize = DeclCFG->size();
    MaxCFGSize = MaxCFGSize < CFGSize ? CFGSize : MaxCFGSize;
  }

  // Clear the AnalysisManager of old AnalysisDeclContexts.
  Mgr->ClearContexts();
  myLiveVariables* L = /*Mgr->getAnalysis<LiveVariables>(D)*/myLiveVariables::create(*(Mgr->getAnalysisDeclContext(D)), Mgr->getASTContext().getSourceManager());
  L->dumpBlockLiveness(Mgr->getASTContext().getSourceManager());
//  BugReporter BR(*Mgr);

//  if (Mode & AM_Syntax)
//    checkerMgr->runCheckersOnASTBody(D, *Mgr, BR);
//  if ((Mode & AM_Path) && checkerMgr->hasPathSensitiveCheckers()) {
//    RunPathSensitiveChecks(D, IMode, VisitedCallees);
//    if (IMode != ExprEngine::Inline_Minimal)
//      NumFunctionsAnalyzed++;
//  }
}
Esempio n. 4
0
TEST_F(TestCFG, RecursionElimination) {
    cfg << "<S> ::= <S>a|b";
    CFG expected;
    expected << "<S> ::= b<S'>";
    expected << "<S'> ::= a<S'>|";
    EXPECT_EQ(expected, cfg.withoutRecursion());

    cfg.clear();
    cfg << "<S> ::= <S><S>a|b<A>";
    cfg << "<A> ::= b<B>c|<A>e|";
    cfg << "<B> ::= <B>a|<B>b|c|d|";
    expected.clear();
    expected << "<S> ::= b<A><S'>";
    expected << "<S'> ::= <S>a<S'>|";
    expected << "<A> ::= b<B>c<A'>|<A'>";
    expected << "<A'> ::= e<A'>|";
    expected << "<B> ::= c<B'>|d<B'>|<B'>";
    expected << "<B'> ::= a<B'>|b<B'>|";
    EXPECT_EQ(expected, cfg.withoutRecursion());

    // cfg.clear();
    // cfg << "<S> ::= <A>a|a";
    // cfg << "<A> ::= <B>b|b";
    // cfg << "<B> ::= <S>c|c";
    // expected.clear();
    // expected << "<S> ::= <A>a|a";
    // expected << "<A> ::= <B>b|b";
    // expected << "<B> ::= bac<B'>|ac<B'>|c<B'>";
    // expected << "<B'> ::= bac<B'>|";
    // EXPECT_EQ(expected, cfg.withoutRecursion());
}
Esempio n. 5
0
CFG CFGGenerator::getCFG(FunctionDefinition& f) {
    CFG result;
    result.fStart = result.newBlock();
    result.fCurrent = result.fStart;
    this->addStatement(result, &f.fBody);
    result.newBlock();
    result.fExit = result.fCurrent;
    return result;
}
Esempio n. 6
0
void lfort::runUninitializedVariablesAnalysis(
    const DeclContext &dc,
    const CFG &cfg,
    AnalysisDeclContext &ac,
    UninitVariablesHandler &handler,
    UninitVariablesAnalysisStats &stats) {
  CFGBlockValues vals(cfg);
  vals.computeSetOfDeclarations(dc);
  if (vals.hasNoDeclarations())
    return;

  stats.NumVariablesAnalyzed = vals.getNumEntries();

  // Precompute which expressions are uses and which are initializations.
  ClassifyRefs classification(ac);
  cfg.VisitBlockStmts(classification);

  // Mark all variables uninitialized at the entry.
  const CFGBlock &entry = cfg.getEntry();
  ValueVector &vec = vals.getValueVector(&entry);
  const unsigned n = vals.getNumEntries();
  for (unsigned j = 0; j < n ; ++j) {
    vec[j] = Uninitialized;
  }

  // Proceed with the workist.
  DataflowWorklist worklist(cfg, *ac.getAnalysis<PostOrderCFGView>());
  llvm::BitVector previouslyVisited(cfg.getNumBlockIDs());
  worklist.enqueueSuccessors(&cfg.getEntry());
  llvm::BitVector wasAnalyzed(cfg.getNumBlockIDs(), false);
  wasAnalyzed[cfg.getEntry().getBlockID()] = true;
  PruneBlocksHandler PBH(cfg.getNumBlockIDs());

  while (const CFGBlock *block = worklist.dequeue()) {
    PBH.currentBlock = block->getBlockID();

    // Did the block change?
    bool changed = runOnBlock(block, cfg, ac, vals,
                              classification, wasAnalyzed, PBH);
    ++stats.NumBlockVisits;
    if (changed || !previouslyVisited[block->getBlockID()])
      worklist.enqueueSuccessors(block);    
    previouslyVisited[block->getBlockID()] = true;
  }

  if (!PBH.hadAnyUse)
    return;

  // Run through the blocks one more time, and report uninitialized variabes.
  for (CFG::const_iterator BI = cfg.begin(), BE = cfg.end(); BI != BE; ++BI) {
    const CFGBlock *block = *BI;
    if (PBH.hadUse[block->getBlockID()]) {
      runOnBlock(block, cfg, ac, vals, classification, wasAnalyzed, handler);
      ++stats.NumBlockVisits;
    }
  }
}
Esempio n. 7
0
void GRState::print(llvm::raw_ostream& Out, CFG &C, const char* nl,
                    const char* sep) const {
  // Print the store.
  GRStateManager &Mgr = getStateManager();
  Mgr.getStoreManager().print(getStore(), Out, nl, sep);

  // Print Subexpression bindings.
  bool isFirst = true;

  for (Environment::iterator I = Env.begin(), E = Env.end(); I != E; ++I) {
    if (C.isBlkExpr(I.getKey()))
      continue;

    if (isFirst) {
      Out << nl << nl << "Sub-Expressions:" << nl;
      isFirst = false;
    }
    else { Out << nl; }

    Out << " (" << (void*) I.getKey() << ") ";
    LangOptions LO; // FIXME.
    I.getKey()->printPretty(Out, 0, PrintingPolicy(LO));
    Out << " : " << I.getData();
  }

  // Print block-expression bindings.
  isFirst = true;

  for (Environment::iterator I = Env.begin(), E = Env.end(); I != E; ++I) {
    if (!C.isBlkExpr(I.getKey()))
      continue;

    if (isFirst) {
      Out << nl << nl << "Block-level Expressions:" << nl;
      isFirst = false;
    }
    else { Out << nl; }

    Out << " (" << (void*) I.getKey() << ") ";
    LangOptions LO; // FIXME.
    I.getKey()->printPretty(Out, 0, PrintingPolicy(LO));
    Out << " : " << I.getData();
  }

  Mgr.getConstraintManager().print(this, Out, nl, sep);

  // Print checker-specific data.
  for (std::vector<Printer*>::iterator I = Mgr.Printers.begin(),
                                       E = Mgr.Printers.end(); I != E; ++I) {
    (*I)->Print(Out, this, nl, sep);
  }
}
Esempio n. 8
0
int FunctionMetadata::calculateNumUserVisibleVRegs() {
    SourceInfo* source_info = source.get();

    CFG* cfg = source_info->cfg;
    assert(cfg && "We don't calculate the CFG inside this function because it can raise an exception and its "
                  "therefore not safe to call at every point");

    if (!cfg->hasVregsAssigned()) {
        ScopeInfo* scope_info = source->getScopeInfo();
        cfg->assignVRegs(param_names, scope_info);
    }
    return cfg->sym_vreg_map_user_visible.size();
}
bool operator == (const CFG& cfg1, const CFG& cfg2) {
  if (cfg1.getTerminals() != cfg2.getTerminals()) return false;
  if (cfg1.getRules() != cfg2.getRules()) return false;
  if (cfg1.getVariables() != cfg2.getVariables()) return false;
  if (cfg1.getStartSymbol() != cfg2.getStartSymbol()) return false;
  return true;
}
Esempio n. 10
0
KernelStatistics *KernelStatistics::computeKernelStatistics(AnalysisDeclContext
    &AC, StringRef name, CompilerKnownClasses &compilerClasses) {
  // No CFG?  Bail out.
  CFG *cfg = AC.getCFG();
  if (!cfg) return 0;

  #ifdef DEBUG_ANALYSIS
  cfg->viewCFG(AC.getASTContext().getLangOpts());
  #endif

  KernelStatsImpl *KS = new KernelStatsImpl(AC, name, compilerClasses);
  KS->runOnAllBlocks();

  return new KernelStatistics(KS);
}
Esempio n. 11
0
int main(int argc, char **argv) {

	Manager manager;
	PropList props;
//	LOADER(props) = &Loader::LOADER_Gliss_PowerPC;
	try {
		WorkSpace *fw = manager.load(argv[1], props);
		
		// Find main CFG
		cout << "Looking for the main CFG\n";
		CFG *cfg = fw->getCFGInfo()->findCFG("main");
		if(cfg == 0) {
			cerr << "ERROR: cannot find main !\n";
			return 1;
		}
		else
			cout << "main found at 0x" << cfg->address() << '\n';
		
		// Build dominance
		Dominance dom;
		dom.processCFG(fw, cfg);
		
		// Display dominance information
		for(CFG::BBIterator bb1(cfg); bb1; bb1++) {
			bool first = true;
			cout << bb1->number() << " dominates {";
			for(CFG::BBIterator bb2(cfg); bb2; bb2++)
				if(Dominance::dominates(bb1, bb2)) {
					if(first)
						first = false;
					else
						cout << ", ";
					cout << bb2->number();
				}
			cout << "}\n";
		}
		
		// Display the result
		cout << "SUCCESS\n";
	}
	catch(LoadException e) {
		cerr << "ERROR: " << e.message() << '\n';
		exit(1);
	}
	return 0;
}
Esempio n. 12
0
File: cfg.cpp Progetto: cmj0121/Zerg
std::string CFG::varcnt(void) {
	int cnt = 0;
	char cntvar[64] = {0};
	CFG *root = this;

	while (NULL != root->prev()) {
		root = root->prev();
	}

	cnt = root->_varcnt_();
	if (0 != cnt) {
		snprintf(cntvar, sizeof(cntvar), "0x%X", cnt * PARAM_SIZE);
	}

	_D(LOG_DEBUG, "variable count on %s - %d", root->label().c_str(), cnt);
	return cntvar;
}
Esempio n. 13
0
 inline void printState(const LR0State& state, const CFG& cfg) {
     ECHO("Kernel:");
     for (auto& item : state.kernel) {
         ECHO(cfg.toReadableForm(cfg[item.productionNumber]));
         // TRACE(item.position);
         // TRACE(item.targetState);
     }
     ECHO("Items:");
     for (auto& item : state.items) {
         ECHO(cfg.toReadableForm(cfg[item.productionNumber]));
         TRACE(item.position);
         TRACE(item.targetState);
         TRACE(static_cast<int>(item.action));
     }
     // TRACE(state.kernel.size());
     // TRACE(state.items.size());
     ECHO("");
 }
Esempio n. 14
0
int main(int argc, char *argv[]) {
    //regex_test();
    /*
    CFG<Parse_data> *cfg = read_grammar(ss.str());
    if (cfg)
        cout << endl << cfg->str() << endl << endl;
        */
    SymbolTable *symtab = new SymbolTable();
    Lexer<int> *lexer = read_lexer(file_to_string(argv[1]), symtab);
    CFG<int> *cfg = read_grammar(file_to_string(argv[2]), symtab);
    //cout << cfg->dfa->str() << endl << endl;
    cfg->parse(lexer->lex(file_to_string(argv[3]), true, true), true);

    // for (int i = 0; i < lexer->rules.size()-2; ++i) {
    //     cout << lexer->rules[i].regex.dfa->str() << endl;
    // }
    
    return 0;
}
Esempio n. 15
0
    inline void expandState(LR0State& state, const CFG& cfg) {
        for (auto& item : state.items) {
            // TRACE(item.productionNumber);
            const Production& prod = cfg[item.productionNumber];
            if (item.position >= prod.size()) {
                continue;
            }

            auto symbol = prod[item.position];
            if (cfg.isNonTerminal(symbol)) {
                for (std::size_t i = 0; i < cfg.size(); i++) {
                    const Production& production = cfg[i];
                    if (production.getName() == symbol) {
                        state.items.emplace_back(LR0Item{i, 0});
                    }
                }
            }
        }
    }
Esempio n. 16
0
void FindUnreachableCode(AnalysisDeclContext &AC, Preprocessor &PP,
                         Callback &CB) {

  CFG *cfg = AC.getCFG();
  if (!cfg)
    return;

  // Scan for reachable blocks from the entrance of the CFG.
  // If there are no unreachable blocks, we're done.
  llvm::BitVector reachable(cfg->getNumBlockIDs());
  unsigned numReachable =
    scanMaybeReachableFromBlock(&cfg->getEntry(), PP, reachable);
  if (numReachable == cfg->getNumBlockIDs())
    return;
  
  // If there aren't explicit EH edges, we should include the 'try' dispatch
  // blocks as roots.
  if (!AC.getCFGBuildOptions().AddEHEdges) {
    for (CFG::try_block_iterator I = cfg->try_blocks_begin(),
         E = cfg->try_blocks_end() ; I != E; ++I) {
      numReachable += scanMaybeReachableFromBlock(*I, PP, reachable);
    }
    if (numReachable == cfg->getNumBlockIDs())
      return;
  }

  // There are some unreachable blocks.  We need to find the root blocks that
  // contain code that should be considered unreachable.  
  for (CFG::iterator I = cfg->begin(), E = cfg->end(); I != E; ++I) {
    const CFGBlock *block = *I;
    // A block may have been marked reachable during this loop.
    if (reachable[block->getBlockID()])
      continue;
    
    DeadCodeScan DS(reachable, PP);
    numReachable += DS.scanBackwards(block, CB);
    
    if (numReachable == cfg->getNumBlockIDs())
      return;
  }
}
Esempio n. 17
0
void ProgAnalysis::traverseCFG(CFG *cfg, std::set<CFG *> &cfgs, std::set<CFG *> &cfgs_done) {

  // Addition of rules only depends of whether the pds
  // is of type wpds::WPDS or not (all others inherit from wpds::ewpds::EWPDS).

  wali::wpds::ewpds::EWPDS *epds = 0;
  if(wpdsType != USING_WPDS) {
    epds = static_cast<wali::wpds::ewpds::EWPDS *>(pds);
  }

  const std::set<CFGEdge *> &edges = cfg->getEdges();
  std::set<CFGEdge *>::const_iterator it;

  for(it = edges.begin(); it != edges.end(); it++) {

    CFGEdge *edge = *it;
    
    if(!edge->isCall()) {
      pds->add_rule(pds_state, edge->getSource()->getWpdsKey(), pds_state, edge->getTarget()->getWpdsKey(), edge->getWeight());
    } else {
      CFG *callee = edge->getCallee();
      if(wpdsType == USING_WPDS) {
	pds->add_rule(pds_state, edge->getSource()->getWpdsKey(), pds_state, callee->getEntry()->getWpdsKey(), edge->getTarget()->getWpdsKey(), 
		      edge->getWeight());
      } else {
	epds->add_rule(pds_state, edge->getSource()->getWpdsKey(), pds_state, callee->getEntry()->getWpdsKey(), edge->getTarget()->getWpdsKey(), 
		       edge->getWeight(), edge->getMergeFn());
      }
      if(cfgs_done.find(callee) == cfgs_done.end()) {
	cfgs.insert(callee);
      }
    }

    // store the weight
    if(!se.is_valid()) {
      se = edge->getWeight();
    }

  }

}
Esempio n. 18
0
void AnalysisConsumer::AnalyzeFunction(CFG& cfg, ASTContext &contex, unsigned &report_ctr) {
        // Compute the ranges information.
    	cfg.print(llvm::outs(),LangOptions());
        APAbstractDomain Dom(cfg);
        Dom.InitializeValues(cfg);
        APChecker Observer(contex,diagnostics_engine_, preprocessor_ptr_);
        Dom.getAnalysisData().Observer = &Observer;
        Dom.getAnalysisData().setContext(contex);
        Solver S(Dom);
        S.runOnCFG(cfg, true);
        Observer.ObserveFixedPoint(true, compute_diff_, report_ctr);
    }
Esempio n. 19
0
void MallocOverflowSecurityChecker::checkASTCodeBody(const Decl *D,
                                             AnalysisManager &mgr,
                                             BugReporter &BR) const {

  CFG *cfg = mgr.getCFG(D);
  if (!cfg)
    return;

  // A list of variables referenced in possibly overflowing malloc operands.
  llvm::SmallVector<MallocOverflowCheck, 2> PossibleMallocOverflows;

  for (CFG::iterator it = cfg->begin(), ei = cfg->end(); it != ei; ++it) {
    CFGBlock *block = *it;
    for (CFGBlock::iterator bi = block->begin(), be = block->end();
         bi != be; ++bi) {
      if (const CFGStmt *CS = bi->getAs<CFGStmt>()) {
        if (const CallExpr *TheCall = dyn_cast<CallExpr>(CS->getStmt())) {
          // Get the callee.
          const FunctionDecl *FD = TheCall->getDirectCallee();

          if (!FD)
            return;

          // Get the name of the callee. If it's a builtin, strip off the prefix.
          IdentifierInfo *FnInfo = FD->getIdentifier();
          if (!FnInfo)
            return;

          if (FnInfo->isStr ("malloc") || FnInfo->isStr ("_MALLOC")) {
            if (TheCall->getNumArgs() == 1)
              CheckMallocArgument(PossibleMallocOverflows, TheCall->getArg(0),
                                  mgr.getASTContext());
          }
        }
      }
    }
  }

  OutputPossibleOverflows(PossibleMallocOverflows, D, BR, mgr);
}
Esempio n. 20
0
/* Dump user databases */
int
main(){
  umask(066);
  try {
    cfg.read(CFG_FILE); /* read parameters from the config file */
    local_dump_db(cfg, 0, NULL);
  }
  catch(Err e)        { process_result(e); }
  catch(Json::Err e)  { process_result(e); }
  catch(JsonDB::Err e){ process_result(e); }
  catch (Exc e)       { process_result(e); }
  exit(0);
}
Esempio n. 21
0
parser::LL1::LL1(const CFG& cfg) : Parser(cfg) {
    cfg.prepareFirst();
    for (std::size_t i = 0; i < cfg.size(); i++) {
        const Production& prod = cfg[i];
        std::string prodName = prod.getName();
        auto& row = table[prodName];
        for (auto& symbol : prod.getFirstSet()) {
            if (row.count(symbol) > 0) {
                conflict = true;
                return;
            }
            row[symbol] = i;
        }

        if (prod.isNullable()) {
            auto follow = cfg.follow(prodName);
            if (cfg.endable(prodName)) {
                follow.insert(END_OF_SENTENCE);
            }
            for (auto& symbol : follow) {
                if (row.count(symbol) > 0) {
                    conflict = true;
                    return;
                }
                row[symbol] = i;
            }
        }
    }

    // for (auto& pair : table) {
    //     TRACE(pair.first);
    //     for (auto& p : pair.second) {
    //         ECHO(p.first + " -> " + std::to_string(p.second));
    //     }
    // }
}
Esempio n. 22
0
void clang::runUninitializedVariablesAnalysis(
    const DeclContext &dc,
    const CFG &cfg,
    AnalysisDeclContext &ac,
    UninitVariablesHandler &handler,
    UninitVariablesAnalysisStats &stats) {
  CFGBlockValues vals(cfg);
  vals.computeSetOfDeclarations(dc);
  if (vals.hasNoDeclarations())
    return;

  stats.NumVariablesAnalyzed = vals.getNumEntries();

  // Mark all variables uninitialized at the entry.
  const CFGBlock &entry = cfg.getEntry();
  for (CFGBlock::const_succ_iterator i = entry.succ_begin(), 
        e = entry.succ_end(); i != e; ++i) {
    if (const CFGBlock *succ = *i) {
      ValueVector &vec = vals.getValueVector(&entry, succ);
      const unsigned n = vals.getNumEntries();
      for (unsigned j = 0; j < n ; ++j) {
        vec[j] = Uninitialized;
      }
    }
  }

  // Proceed with the workist.
  DataflowWorklist worklist(cfg);
  llvm::BitVector previouslyVisited(cfg.getNumBlockIDs());
  worklist.enqueueSuccessors(&cfg.getEntry());
  llvm::BitVector wasAnalyzed(cfg.getNumBlockIDs(), false);
  wasAnalyzed[cfg.getEntry().getBlockID()] = true;

  while (const CFGBlock *block = worklist.dequeue()) {
    // Did the block change?
    bool changed = runOnBlock(block, cfg, ac, vals, wasAnalyzed);
    ++stats.NumBlockVisits;
    if (changed || !previouslyVisited[block->getBlockID()])
      worklist.enqueueSuccessors(block);    
    previouslyVisited[block->getBlockID()] = true;
  }
  
  // Run through the blocks one more time, and report uninitialized variabes.
  for (CFG::const_iterator BI = cfg.begin(), BE = cfg.end(); BI != BE; ++BI) {
    const CFGBlock *block = *BI;
    if (wasAnalyzed[block->getBlockID()]) {
      runOnBlock(block, cfg, ac, vals, wasAnalyzed, &handler);
      ++stats.NumBlockVisits;
    }
  }
}
Esempio n. 23
0
void DefinednessBBAnalyzer::processBB(Map &starting, CFGBlock *block) const {
    DefinednessVisitor visitor(starting);
    for (int i = 0; i < block->body.size(); i++) {
        block->body[i]->accept(&visitor);
    }
    if (block == cfg->getStartingBlock() && arguments) {
        arguments->accept(&visitor);
    }

    if (VERBOSITY("analysis") >= 2) {
        printf("At end of block %d:\n", block->idx);
        for (const auto &p : starting) {
            printf("%s: %d\n", p.first.c_str(), p.second);
        }
    }
}
Esempio n. 24
0
void DefinednessBBAnalyzer::processBB(Map& starting, CFGBlock* block) const {
    DefinednessVisitor visitor(starting);

    if (block == cfg->getStartingBlock() && arg_names.args) {
        for (auto e : (*arg_names.args))
            visitor._doSet(e);
        if (arg_names.vararg->size())
            visitor._doSet(*arg_names.vararg);
        if (arg_names.kwarg->size())
            visitor._doSet(*arg_names.kwarg);
    }

    for (int i = 0; i < block->body.size(); i++) {
        block->body[i]->accept(&visitor);
    }

    if (VERBOSITY("analysis") >= 2) {
        printf("At end of block %d:\n", block->idx);
        for (const auto& p : starting) {
            printf("%s: %d\n", p.first.c_str(), p.second);
        }
    }
}
Esempio n. 25
0
File: pmbu.cpp Progetto: igstan/rtc
void pMBUfactHandler::doInsensitiveAnalysis(CFG& cfg)
{
  //- 1. collect starting points (into relevant_ecrs)
  cfg.traverseRootNodes(pMBUfactHandler::collectStartingPoints);

  //- 2. follow assignment edges backwards
  suco_set<ECR *> worklist;
  worklist.Union(pMBUfactHandler::relevant_ecrs);
  while(!worklist.IsEmpty()){
    ECR& ecr = *worklist.RemoveHead();
    //- for each ecr in worklist: traverse its aos
    suco_iterator<AO *> aoi(ecr.getAOset());
    while(aoi.Iterate()){
      //  1. collect locs in results
      if(aoi.Current()->isLocArgRet()){
        pMBUfactHandler::results.Insert(aoi.Current());
      }
      //  2. follow incl-edges backwards
      //NOTE: technically, only want to follow "copy" edges,
      // and skip assignments from a (+) node; but the existence
      // of such a node would've rendered the starting point
      // "unsafe", so it should never be encountered!?
      suco_iterator<TCassignEdge *> edi(aoi.Current()->getIncomingAssignEdges());
      while(edi.Iterate()){
        ECR& fecr = edi.Current()->getFrom().getECR();
        if(!pMBUfactHandler::relevant_ecrs.Contains(&fecr)){
          suco_set<ECR *> fecr_aliases;
          fecr.collectAliasECRs(fecr_aliases);	//- using this because getAliasECRs filters loc/arg/ret
//          fecr_aliases.Subtract(pMBUfactHandler::relevant_ecrs);	//-TODO: avoid repetition
          pMBUfactHandler::relevant_ecrs.Union(fecr_aliases);
          worklist.UnionConsume(fecr_aliases);
        }
      }
    }
  }
}
Esempio n. 26
0
void SystemDependenceGraph::build()
{
    boost::unordered_map<CFGVertex, Vertex> cfgVerticesToSdgVertices;
    boost::unordered_map<SgNode*, Vertex>   astNodesToSdgVertices;

    //map<SgFunctionCallExp*, vector<SDGNode*> > funcCallToArgs;

    vector<CallSiteInfo> functionCalls;


    map<SgNode*, vector<Vertex> > actualInParameters;
    map<SgNode*, vector<Vertex> > actualOutParameters;

    map<SgNode*, Vertex> formalInParameters;
    map<SgNode*, Vertex> formalOutParameters;

    vector<SgFunctionDefinition*> funcDefs = 
        SageInterface::querySubTree<SgFunctionDefinition>(project_, V_SgFunctionDefinition);
    foreach (SgFunctionDefinition* funcDef, funcDefs)
    {
        SgFunctionDeclaration* funcDecl = funcDef->get_declaration();

        CFG* cfg = new CFG(funcDef, cfgNodefilter_);
        functionsToCFGs_[funcDecl] = cfg;

        // For each function, build an entry node for it.
        SDGNode* entry = new SDGNode(SDGNode::Entry);
        entry->astNode = funcDef;
        //entry->funcDef = funcDef;
        Vertex entryVertex = addVertex(entry);
        functionsToEntries_[funcDecl] = entryVertex;

        // Add all out formal parameters to SDG.
        const SgInitializedNamePtrList& formalArgs = funcDecl->get_args();
        foreach (SgInitializedName* initName, formalArgs)
        {
            // If the parameter is passed by reference, create a formal-out node.
            if (isParaPassedByRef(initName->get_type()))
            {
                SDGNode* formalOutNode = new SDGNode(SDGNode::FormalOut);
                formalOutNode->astNode = initName;
                Vertex formalOutVertex = addVertex(formalOutNode);
                formalOutParameters[initName] = formalOutVertex;

                // Add a CD edge from call node to this formal-out node.
                addTrueCDEdge(entryVertex, formalOutVertex);
            }
        }

        // A vertex representing the returned value.
        Vertex returnVertex;

        // If the function returns something, build a formal-out node.
        if (!isSgTypeVoid(funcDecl->get_type()->get_return_type()))
        {
            SDGNode* formalOutNode = new SDGNode(SDGNode::FormalOut);
            // Assign the function declaration to the AST node of this vertex to make
            // it possible to classify this node into the subgraph of this function.
            formalOutNode->astNode = funcDecl;
            returnVertex = addVertex(formalOutNode);
            formalOutParameters[funcDecl] = returnVertex;

            // Add a CD edge from call node to this formal-out node.
            addTrueCDEdge(entryVertex, returnVertex);
        }

        // Add all CFG vertices to SDG.
        foreach (CFGVertex cfgVertex, boost::vertices(*cfg))
        {
            if (cfgVertex == cfg->getEntry() || cfgVertex == cfg->getExit())
                continue;

            SgNode* astNode = (*cfg)[cfgVertex]->getNode();

            // If this node is an initialized name and it is a parameter, make it 
            // as a formal in node.
            SgInitializedName* initName = isSgInitializedName(astNode);
            if (initName && isSgFunctionParameterList(initName->get_parent()))
            {
                SDGNode* formalInNode = new SDGNode(SDGNode::FormalIn);
                formalInNode->astNode = initName;
                Vertex formalInVertex = addVertex(formalInNode);
                formalInParameters[initName] = formalInVertex;

                cfgVerticesToSdgVertices[cfgVertex] = formalInVertex;
                astNodesToSdgVertices[astNode] = formalInVertex;

                // Add a CD edge from call node to this formal-in node.
                addTrueCDEdge(entryVertex, formalInVertex);
                continue;
            }

            // Add a new node to SDG.
            SDGNode* newSdgNode = new SDGNode(SDGNode::ASTNode);
            //newSdgNode->cfgNode = (*cfg)[cfgVertex];
            newSdgNode->astNode = astNode;
            Vertex sdgVertex = addVertex(newSdgNode);

            cfgVerticesToSdgVertices[cfgVertex] = sdgVertex;
            astNodesToSdgVertices[astNode] = sdgVertex;


            // Connect a vertex containing the return statement to the formal-out return vertex.
            if (isSgReturnStmt(astNode)
                    || isSgReturnStmt(astNode->get_parent()))
            {
                SDGEdge* newEdge = new SDGEdge(SDGEdge::DataDependence);
                addEdge(sdgVertex, returnVertex, newEdge);                
            }

            // If this CFG node contains a function call expression, extract its all parameters
            // and make them as actual-in nodes.

            if (SgFunctionCallExp* funcCallExpr = isSgFunctionCallExp(astNode))
            {
                CallSiteInfo callInfo;
                callInfo.funcCall = funcCallExpr;
                callInfo.vertex = sdgVertex;

                // Change the node type.
                newSdgNode->type = SDGNode::FunctionCall;
                vector<SDGNode*> argsNodes;

                // Get the associated function declaration.
                SgFunctionDeclaration* funcDecl = funcCallExpr->getAssociatedFunctionDeclaration();
                
                if (funcDecl == NULL) 
                    continue;
                    
                ROSE_ASSERT(funcDecl);
                const SgInitializedNamePtrList& formalArgs = funcDecl->get_args();

                SgExprListExp* args = funcCallExpr->get_args();
                const SgExpressionPtrList& actualArgs = args->get_expressions();
                
                if (formalArgs.size() != actualArgs.size())
                {
                    cout << "The following function has variadic arguments:\n";
                    cout << funcDecl->get_file_info()->get_filename() << endl;
                    cout << funcDecl->get_name() << formalArgs.size() << " " << actualArgs.size() << endl;
                    continue;
                }

                for (int i = 0, s = actualArgs.size(); i < s; ++i)
                {
                    // Make sure that this parameter node is added to SDG then we
                    // change its node type from normal AST node to a ActualIn arg.
                    ROSE_ASSERT(astNodesToSdgVertices.count(actualArgs[i]));

                    Vertex paraInVertex = astNodesToSdgVertices.at(actualArgs[i]);
                    SDGNode* paraInNode = (*this)[paraInVertex]; 
                    paraInNode->type = SDGNode::ActualIn;

                    actualInParameters[formalArgs[i]].push_back(paraInVertex);
                    callInfo.inPara.push_back(paraInVertex);

                    // Add a CD edge from call node to this actual-in node.
                    addTrueCDEdge(sdgVertex, paraInVertex);

                    // If the parameter is passed by reference, create a parameter-out node.
                    if (isParaPassedByRef(formalArgs[i]->get_type()))
                    {
                        SDGNode* paraOutNode = new SDGNode(SDGNode::ActualOut);
                        paraOutNode->astNode = actualArgs[i];
                        //argsNodes.push_back(paraInNode);

                        // Add an actual-out parameter node.
                        Vertex paraOutVertex = addVertex(paraOutNode);
                        actualOutParameters[formalArgs[i]].push_back(paraOutVertex);
                        callInfo.outPara.push_back(paraOutVertex);

                        // Add a CD edge from call node to this actual-out node.
                        addTrueCDEdge(sdgVertex, paraOutVertex);
                    }
                }

                if (!isSgTypeVoid(funcDecl->get_type()->get_return_type())) 
                {
                    // If this function returns a value, create a actual-out vertex.
                    SDGNode* paraOutNode = new SDGNode(SDGNode::ActualOut);
                    paraOutNode->astNode = funcCallExpr;

                    // Add an actual-out parameter node.
                    Vertex paraOutVertex = addVertex(paraOutNode);
                    actualOutParameters[funcDecl].push_back(paraOutVertex);
                    callInfo.outPara.push_back(paraOutVertex);
                    callInfo.isVoid = false;
                    callInfo.returned = paraOutVertex;

                    // Add a CD edge from call node to this actual-out node.
                    addTrueCDEdge(sdgVertex, paraOutVertex);
                }

                functionCalls.push_back(callInfo);
                //funcCallToArgs[funcCallExpr] = argsNodes;
            }
        }

        // Add control dependence edges.
        addControlDependenceEdges(cfgVerticesToSdgVertices, *cfg, entryVertex);
    }
void UnreachableCodeChecker::checkEndAnalysis(ExplodedGraph &G,
                                              BugReporter &B,
                                              ExprEngine &Eng) const {
  CFGBlocksSet reachable, visited;

  if (Eng.hasWorkRemaining())
    return;

  const Decl *D = nullptr;
  CFG *C = nullptr;
  ParentMap *PM = nullptr;
  const LocationContext *LC = nullptr;
  // Iterate over ExplodedGraph
  for (ExplodedGraph::node_iterator I = G.nodes_begin(), E = G.nodes_end();
      I != E; ++I) {
    const ProgramPoint &P = I->getLocation();
    LC = P.getLocationContext();
    if (!LC->inTopFrame())
      continue;

    if (!D)
      D = LC->getAnalysisDeclContext()->getDecl();

    // Save the CFG if we don't have it already
    if (!C)
      C = LC->getAnalysisDeclContext()->getUnoptimizedCFG();
    if (!PM)
      PM = &LC->getParentMap();

    if (Optional<BlockEntrance> BE = P.getAs<BlockEntrance>()) {
      const CFGBlock *CB = BE->getBlock();
      reachable.insert(CB->getBlockID());
    }
  }

  // Bail out if we didn't get the CFG or the ParentMap.
  if (!D || !C || !PM)
    return;

  // Don't do anything for template instantiations.  Proving that code
  // in a template instantiation is unreachable means proving that it is
  // unreachable in all instantiations.
  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
    if (FD->isTemplateInstantiation())
      return;

  // Find CFGBlocks that were not covered by any node
  for (CFG::const_iterator I = C->begin(), E = C->end(); I != E; ++I) {
    const CFGBlock *CB = *I;
    // Check if the block is unreachable
    if (reachable.count(CB->getBlockID()))
      continue;

    // Check if the block is empty (an artificial block)
    if (isEmptyCFGBlock(CB))
      continue;

    // Find the entry points for this block
    if (!visited.count(CB->getBlockID()))
      FindUnreachableEntryPoints(CB, reachable, visited);

    // This block may have been pruned; check if we still want to report it
    if (reachable.count(CB->getBlockID()))
      continue;

    // Check for false positives
    if (isInvalidPath(CB, *PM))
      continue;

    // It is good practice to always have a "default" label in a "switch", even
    // if we should never get there. It can be used to detect errors, for
    // instance. Unreachable code directly under a "default" label is therefore
    // likely to be a false positive.
    if (const Stmt *label = CB->getLabel())
      if (label->getStmtClass() == Stmt::DefaultStmtClass)
        continue;

    // Special case for __builtin_unreachable.
    // FIXME: This should be extended to include other unreachable markers,
    // such as llvm_unreachable.
    if (!CB->empty()) {
      bool foundUnreachable = false;
      for (CFGBlock::const_iterator ci = CB->begin(), ce = CB->end();
           ci != ce; ++ci) {
        if (Optional<CFGStmt> S = (*ci).getAs<CFGStmt>())
          if (const CallExpr *CE = dyn_cast<CallExpr>(S->getStmt())) {
            if (CE->getBuiltinCallee() == Builtin::BI__builtin_unreachable ||
                CE->isBuiltinAssumeFalse(Eng.getContext())) {
              foundUnreachable = true;
              break;
            }
          }
      }
      if (foundUnreachable)
        continue;
    }

    // We found a block that wasn't covered - find the statement to report
    SourceRange SR;
    PathDiagnosticLocation DL;
    SourceLocation SL;
    if (const Stmt *S = getUnreachableStmt(CB)) {
      // In macros, 'do {...} while (0)' is often used. Don't warn about the
      // condition 0 when it is unreachable.
      if (S->getBeginLoc().isMacroID())
        if (const auto *I = dyn_cast<IntegerLiteral>(S))
          if (I->getValue() == 0ULL)
            if (const Stmt *Parent = PM->getParent(S))
              if (isa<DoStmt>(Parent))
                continue;
      SR = S->getSourceRange();
      DL = PathDiagnosticLocation::createBegin(S, B.getSourceManager(), LC);
      SL = DL.asLocation();
      if (SR.isInvalid() || !SL.isValid())
        continue;
    }
    else
      continue;

    // Check if the SourceLocation is in a system header
    const SourceManager &SM = B.getSourceManager();
    if (SM.isInSystemHeader(SL) || SM.isInExternCSystemHeader(SL))
      continue;

    B.EmitBasicReport(D, this, "Unreachable code", "Dead code",
                      "This statement is never executed", DL, SR);
  }
}
void UnreachableCodeChecker::checkEndAnalysis(ExplodedGraph &G,
                                              BugReporter &B,
                                              ExprEngine &Eng) const {
  CFGBlocksSet reachable, visited;

  if (Eng.hasWorkRemaining())
    return;

  CFG *C = 0;
  ParentMap *PM = 0;
  // Iterate over ExplodedGraph
  for (ExplodedGraph::node_iterator I = G.nodes_begin(), E = G.nodes_end();
      I != E; ++I) {
    const ProgramPoint &P = I->getLocation();
    const LocationContext *LC = P.getLocationContext();

    // Save the CFG if we don't have it already
    if (!C)
      C = LC->getAnalysisContext()->getUnoptimizedCFG();
    if (!PM)
      PM = &LC->getParentMap();

    if (const BlockEntrance *BE = dyn_cast<BlockEntrance>(&P)) {
      const CFGBlock *CB = BE->getBlock();
      reachable.insert(CB->getBlockID());
    }
  }

  // Bail out if we didn't get the CFG or the ParentMap.
  if (!C || !PM)
    return;

  ASTContext &Ctx = B.getContext();

  // Find CFGBlocks that were not covered by any node
  for (CFG::const_iterator I = C->begin(), E = C->end(); I != E; ++I) {
    const CFGBlock *CB = *I;
    // Check if the block is unreachable
    if (reachable.count(CB->getBlockID()))
      continue;

    // Check if the block is empty (an artificial block)
    if (isEmptyCFGBlock(CB))
      continue;

    // Find the entry points for this block
    if (!visited.count(CB->getBlockID()))
      FindUnreachableEntryPoints(CB, reachable, visited);

    // This block may have been pruned; check if we still want to report it
    if (reachable.count(CB->getBlockID()))
      continue;

    // Check for false positives
    if (CB->size() > 0 && isInvalidPath(CB, *PM))
      continue;

    // Special case for __builtin_unreachable.
    // FIXME: This should be extended to include other unreachable markers,
    // such as llvm_unreachable.
    if (!CB->empty()) {
      CFGElement First = CB->front();
      if (const CFGStmt *S = First.getAs<CFGStmt>()) {
        if (const CallExpr *CE = dyn_cast<CallExpr>(S->getStmt())) {
          if (CE->isBuiltinCall(Ctx) == Builtin::BI__builtin_unreachable)
            continue;
        }
      }
    }

    // We found a block that wasn't covered - find the statement to report
    SourceRange SR;
    SourceLocation SL;
    if (const Stmt *S = getUnreachableStmt(CB)) {
      SR = S->getSourceRange();
      SL = S->getLocStart();
      if (SR.isInvalid() || SL.isInvalid())
        continue;
    }
    else
      continue;

    // Check if the SourceLocation is in a system header
    const SourceManager &SM = B.getSourceManager();
    if (SM.isInSystemHeader(SL) || SM.isInExternCSystemHeader(SL))
      continue;

    B.EmitBasicReport("Unreachable code", "Dead code", "This statement is never"
        " executed", SL, SR);
  }
}
Esempio n. 29
0
CFGReverseBlockReachabilityAnalysis::CFGReverseBlockReachabilityAnalysis(const CFG &cfg)
  : analyzed(cfg.getNumBlockIDs(), false) {}
Esempio n. 30
0
/// CheckFallThrough - Check that we don't fall off the end of a
/// Statement that should return a value.
///
/// \returns AlwaysFallThrough iff we always fall off the end of the statement,
/// MaybeFallThrough iff we might or might not fall off the end,
/// NeverFallThroughOrReturn iff we never fall off the end of the statement or
/// return.  We assume NeverFallThrough iff we never fall off the end of the
/// statement but we may return.  We assume that functions not marked noreturn
/// will return.
static ControlFlowKind CheckFallThrough(AnalysisContext &AC) {
    CFG *cfg = AC.getCFG();
    if (cfg == 0) return UnknownFallThrough;

    // The CFG leaves in dead things, and we don't want the dead code paths to
    // confuse us, so we mark all live things first.
    llvm::BitVector live(cfg->getNumBlockIDs());
    unsigned count = reachable_code::ScanReachableFromBlock(cfg->getEntry(),
                     live);

    bool AddEHEdges = AC.getAddEHEdges();
    if (!AddEHEdges && count != cfg->getNumBlockIDs())
        // When there are things remaining dead, and we didn't add EH edges
        // from CallExprs to the catch clauses, we have to go back and
        // mark them as live.
        for (CFG::iterator I = cfg->begin(), E = cfg->end(); I != E; ++I) {
            CFGBlock &b = **I;
            if (!live[b.getBlockID()]) {
                if (b.pred_begin() == b.pred_end()) {
                    if (b.getTerminator() && isa<CXXTryStmt>(b.getTerminator()))
                        // When not adding EH edges from calls, catch clauses
                        // can otherwise seem dead.  Avoid noting them as dead.
                        count += reachable_code::ScanReachableFromBlock(b, live);
                    continue;
                }
            }
        }

    // Now we know what is live, we check the live precessors of the exit block
    // and look for fall through paths, being careful to ignore normal returns,
    // and exceptional paths.
    bool HasLiveReturn = false;
    bool HasFakeEdge = false;
    bool HasPlainEdge = false;
    bool HasAbnormalEdge = false;
    for (CFGBlock::pred_iterator I=cfg->getExit().pred_begin(),
            E = cfg->getExit().pred_end();
            I != E;
            ++I) {
        CFGBlock& B = **I;
        if (!live[B.getBlockID()])
            continue;
        if (B.size() == 0) {
            if (B.getTerminator() && isa<CXXTryStmt>(B.getTerminator())) {
                HasAbnormalEdge = true;
                continue;
            }

            // A labeled empty statement, or the entry block...
            HasPlainEdge = true;
            continue;
        }
        Stmt *S = B[B.size()-1];
        if (isa<ReturnStmt>(S)) {
            HasLiveReturn = true;
            continue;
        }
        if (isa<ObjCAtThrowStmt>(S)) {
            HasFakeEdge = true;
            continue;
        }
        if (isa<CXXThrowExpr>(S)) {
            HasFakeEdge = true;
            continue;
        }
        if (const AsmStmt *AS = dyn_cast<AsmStmt>(S)) {
            if (AS->isMSAsm()) {
                HasFakeEdge = true;
                HasLiveReturn = true;
                continue;
            }
        }
        if (isa<CXXTryStmt>(S)) {
            HasAbnormalEdge = true;
            continue;
        }

        bool NoReturnEdge = false;
        if (CallExpr *C = dyn_cast<CallExpr>(S)) {
            if (std::find(B.succ_begin(), B.succ_end(), &cfg->getExit())
                    == B.succ_end()) {
                HasAbnormalEdge = true;
                continue;
            }
            Expr *CEE = C->getCallee()->IgnoreParenCasts();
            if (getFunctionExtInfo(CEE->getType()).getNoReturn()) {
                NoReturnEdge = true;
                HasFakeEdge = true;
            } else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CEE)) {
                ValueDecl *VD = DRE->getDecl();
                if (VD->hasAttr<NoReturnAttr>()) {
                    NoReturnEdge = true;
                    HasFakeEdge = true;
                }
            }
        }
        // FIXME: Remove this hack once temporaries and their destructors are
        // modeled correctly by the CFG.
        if (CXXExprWithTemporaries *E = dyn_cast<CXXExprWithTemporaries>(S)) {
            for (unsigned I = 0, N = E->getNumTemporaries(); I != N; ++I) {
                const FunctionDecl *FD = E->getTemporary(I)->getDestructor();
                if (FD->hasAttr<NoReturnAttr>() ||
                        FD->getType()->getAs<FunctionType>()->getNoReturnAttr()) {
                    NoReturnEdge = true;
                    HasFakeEdge = true;
                    break;
                }
            }
        }
        // FIXME: Add noreturn message sends.
        if (NoReturnEdge == false)
            HasPlainEdge = true;
    }
    if (!HasPlainEdge) {
        if (HasLiveReturn)
            return NeverFallThrough;
        return NeverFallThroughOrReturn;
    }
    if (HasAbnormalEdge || HasFakeEdge || HasLiveReturn)
        return MaybeFallThrough;
    // This says AlwaysFallThrough for calls to functions that are not marked
    // noreturn, that don't return.  If people would like this warning to be more
    // accurate, such functions should be marked as noreturn.
    return AlwaysFallThrough;
}