PrologEpilogGenerator::PrologEpilogGenerator(Cfg &cfg) : mm(cfg.getMM()), cfg(cfg), outRegArgs(mm), prologInsts(mm), epilogInsts(mm), allocInsts(mm), saveSpInsts(mm), savePfsInsts(mm), saveUnatInsts(mm), saveGrsInsts(mm), saveFrsInsts(mm), saveBrsInsts(mm), savePrsInsts(mm), saveRpInsts(mm), restRpInsts(mm), restPrsInsts(mm), restBrsInsts(mm), restFrsInsts(mm), restGrsInsts(mm), restUnatInsts(mm), restPfsInsts(mm), restSpInsts(mm), epilogNodes(mm) { opndManager = cfg.getOpndManager(); p0 = opndManager->getP0(); sp = opndManager->getR12(); stackAddr = opndManager->newRegOpnd(OPND_G_REG, DATA_I64, SPILL_REG1); }
Graph* Connector::connect(Graph* g) { const std::vector<CfgNode*>& nodes = g->getNodes(); std::map<unsigned int, CfgNode*> id2node = getId2Node(nodes); for (unsigned int i = 0; i < nodes.size(); i++) { CfgNode* fromNode = nodes[i]; Cfg* cfg = fromNode->getCfg(); std::vector<unsigned int> nexts = cfg->getNext(); for (unsigned int j = 0; j < nexts.size(); j++) { CfgNode* toNode = id2node[nexts[j]]; if (toNode == NULL) THROWEXCEPTION("next statement is illegal; there is no node with id=%d", nexts[j]); if (connectNodes) // insert the connection in the graph g->addEdge(fromNode, toNode); msg(MSG_INFO, "Connecting module %s[Id = %d] -> %s[Id = %d]", cfg->getName().c_str(), cfg->getID(), id2node[nexts[j]]->getCfg()->getName().c_str(), id2node[nexts[j]]->getCfg()->getID()); if (connectModules) {// connect the modules DPRINTF("connecting instances"); cfg->connectInstances(toNode->getCfg()); } } } return g; }
IpfVarCodeSelector::IpfVarCodeSelector(Cfg &cfg, OpndVector &opnds) : mm(cfg.getMM()), cfg(cfg), opnds(opnds) { opndManager = cfg.getOpndManager(); }
static Handle<Code> MakeCode(FunctionLiteral* literal, Handle<Script> script, Handle<Context> context, bool is_eval) { ASSERT(literal != NULL); // Rewrite the AST by introducing .result assignments where needed. if (!Rewriter::Process(literal) || !AnalyzeVariableUsage(literal)) { // Signal a stack overflow by returning a null handle. The stack // overflow exception will be thrown by the caller. return Handle<Code>::null(); } { // Compute top scope and allocate variables. For lazy compilation // the top scope only contains the single lazily compiled function, // so this doesn't re-allocate variables repeatedly. HistogramTimerScope timer(&Counters::variable_allocation); Scope* top = literal->scope(); while (top->outer_scope() != NULL) top = top->outer_scope(); top->AllocateVariables(context); } #ifdef DEBUG if (Bootstrapper::IsActive() ? FLAG_print_builtin_scopes : FLAG_print_scopes) { literal->scope()->Print(); } #endif // Optimize the AST. if (!Rewriter::Optimize(literal)) { // Signal a stack overflow by returning a null handle. The stack // overflow exception will be thrown by the caller. return Handle<Code>::null(); } if (FLAG_multipass) { CfgGlobals scope(literal); Cfg* cfg = Cfg::Build(); #ifdef DEBUG if (FLAG_print_cfg && cfg != NULL) { SmartPointer<char> name = literal->name()->ToCString(); PrintF("Function \"%s\":\n", *name); cfg->Print(); PrintF("\n"); } #endif if (cfg != NULL) { return cfg->Compile(script); } } // Generate code and return it. Handle<Code> result = CodeGenerator::MakeCode(literal, script, is_eval); return result; }
/* * ssa_cfg_to_instr_list -- First restore conventional (non-SSA form). * Then convert the resulting CFG to InstrList form, delete the now-empty * CFG, and return the instruction list. */ InstrList* ssa_cfg_to_instr_list(SsaCfg *ssa_cfg) { Cfg *cfg = restore(ssa_cfg); InstrList *instr_list = cfg->to_instr_list(); delete cfg; return instr_list; }
QpTree::QpTree(Cfg &cfg) : cfg(cfg), mm(cfg.getMM()), qpMap(mm), slot(0), p0(cfg.getOpndManager()->getP0()) { qpMap.insert( make_pair(p0, new(mm) QpNode(NULL, MAX_QP_MASK)) ); // make root qpNode }
int main(int argc, char * argv[]){ remove("tmp/test1.txt"); remove("tmp/test2.txt"); remove("./tmp/graph.dot"); if (argc < 2) { cout << "erreur : pas de fichier assembleur en entrée" << endl; } Program prog(argv[1]); Function* functmp; list <Basic_block*> myBB; cout<<"Le programme a "<<prog.size()<<" lignes\n"<<endl; cout<<"Contenu du programme:"<<endl; //prog.display(); prog.in_file("tmp/restit.txt"); cout<<"\n Calcul des fonctions des block de base et restitution\n"<<endl; prog.comput_function(); cout<<"nombre de fonction: "<<prog.nbr_func()<<endl; Cfg *graph; for (int i=0; i<prog.nbr_func(); i++){ functmp= prog.get_function(i); if(functmp==NULL){ cout<<"null"<<endl; break; } // functmp->restitution("tmp/test1.txt"); functmp->comput_basic_block(); functmp->comput_label(); for(int j=0; j<functmp->nbr_BB(); j++){ //functmp->get_BB(j)->display(); } functmp->comput_succ_pred_BB(); graph =new Cfg(functmp->get_BB(0), functmp->nbr_BB()); cout<<"------------Function "<< (i+1) <<"/"<<prog.nbr_func()<<" DISPLAY----------\n" <<endl; //functmp->test(); graph->display(NULL); } // graph->restitution(NULL,"./tmp/graph.dot"); }
IpfCfgCodeSelector::IpfCfgCodeSelector(Cfg &cfg, NodeVector &nodes, OpndVector &opnds, CompilationInterface &compilationInterface) : mm(cfg.getMM()), cfg(cfg), nodes(nodes), opnds(opnds), compilationInterface(compilationInterface), opndManager(cfg.getOpndManager()) { }
void CfgTest::testSemiDominators () { BinaryFileFactory bff; BinaryFile* pBF = bff.Load(SEMI_PENTIUM); CPPUNIT_ASSERT(pBF != 0); Prog* prog = new Prog; FrontEnd* pFE = new PentiumFrontEnd(pBF, prog, &bff); Type::clearNamedTypes(); prog->setFrontEnd(pFE); pFE->decode(prog); bool gotMain; ADDRESS addr = pFE->getMainEntryPoint(gotMain); CPPUNIT_ASSERT (addr != NO_ADDRESS); UserProc* pProc = (UserProc*) prog->getProc(0); Cfg* cfg = pProc->getCFG(); DataFlow* df = pProc->getDataFlow(); df->dominators(cfg); // Find BB "L (6)" (as per Appel, Figure 19.8). BB_IT it; PBB bb = cfg->getFirstBB(it); while (bb && bb->getLowAddr() != SEMI_L) { bb = cfg->getNextBB(it); } CPPUNIT_ASSERT(bb); int nL = df->pbbToNode(bb); // The dominator for L should be B, where the semi dominator is D // (book says F) unsigned actual_dom = (unsigned)df->nodeToBB(df->getIdom(nL))->getLowAddr(); unsigned actual_semi = (unsigned)df->nodeToBB(df->getSemi(nL))->getLowAddr(); CPPUNIT_ASSERT_EQUAL((unsigned)SEMI_B, actual_dom); CPPUNIT_ASSERT_EQUAL((unsigned)SEMI_D, actual_semi); // Check the final dominator frontier as well; should be M and B std::ostringstream expected, actual; //expected << std::hex << SEMI_M << " " << SEMI_B << " "; expected << std::hex << SEMI_B << " " << SEMI_M << " "; std::set<int>::iterator ii; std::set<int>& DFset = df->getDF(nL); for (ii=DFset.begin(); ii != DFset.end(); ii++) actual << std::hex << (unsigned)df->nodeToBB(*ii)->getLowAddr() << " "; CPPUNIT_ASSERT_EQUAL(expected.str(), actual.str()); delete pFE; }
LiveAnalyzer::LiveAnalyzer(Cfg &cfg) : cfg(cfg), mm(cfg.getMM()), workSet(mm), liveManager(cfg), liveSet(liveManager.getLiveSet()), dceFlag(false) { }
void ConfigManager::shutdown() { lockGraph(); std::vector<CfgNode*> topoNodes = graph->topoSort(); // shutdown modules for (size_t i = 0; i < topoNodes.size(); i++) { Cfg* cfg = topoNodes[i]->getCfg(); msg(MSG_INFO, "shutting down module %s (id=%u)", cfg->getName().c_str(), cfg->getID()); cfg->shutdown(true, true); } // trigger sensorManager to get the final statistics of this Vermont run if (sensorManager) { sensorManager->retrieveStatistics(true); } // disconnect the modules for (size_t i = 0; i < topoNodes.size(); i++) { CfgNode* n = topoNodes[i]; Cfg* cfg = n->getCfg(); // disconnect the module from its sources .. vector<CfgNode*> sources = graph->getSources(n); msg(MSG_INFO, "disconnecting module %s (id=%u)", cfg->getName().c_str(), cfg->getID()); for (size_t k = 0; k < sources.size(); k++) { sources[k]->getCfg()->disconnectInstances(); } } unlockGraph(); }
void readCfg(Cfg& config, const string& cfg) { xmlDocPtr config_doc = xmlParseFile(cfg.c_str()); if(config_doc == NULL) { throw string("missing configuration file ")+cfg; } config.ReConfigure(config_doc->children); xmlFreeDoc(config_doc); }
IpfMethodCodeSelector::IpfMethodCodeSelector(Cfg &cfg, CompilationInterface &compilationInterface) : mm(cfg.getMM()), cfg(cfg), compilationInterface(compilationInterface), methodDesc(NULL), opnds(mm), nodes(mm) { }
void CfgTest::testDominators () { BinaryFileFactory bff; BinaryFile *pBF = bff.Load(FRONTIER_PENTIUM); CPPUNIT_ASSERT(pBF != 0); Prog* prog = new Prog; FrontEnd *pFE = new PentiumFrontEnd(pBF, prog, &bff); Type::clearNamedTypes(); prog->setFrontEnd(pFE); pFE->decode(prog); bool gotMain; ADDRESS addr = pFE->getMainEntryPoint(gotMain); CPPUNIT_ASSERT (addr != NO_ADDRESS); UserProc* pProc = (UserProc*) prog->getProc(0); Cfg* cfg = pProc->getCFG(); DataFlow* df = pProc->getDataFlow(); df->dominators(cfg); // Find BB "5" (as per Appel, Figure 19.5). BB_IT it; PBB bb = cfg->getFirstBB(it); while (bb && bb->getLowAddr() != FRONTIER_FIVE) { bb = cfg->getNextBB(it); } CPPUNIT_ASSERT(bb); std::ostringstream expected, actual; //expected << std::hex << FRONTIER_FIVE << " " << FRONTIER_THIRTEEN << " " << FRONTIER_TWELVE << " " << // FRONTIER_FOUR << " "; expected << std::hex << FRONTIER_THIRTEEN << " " << FRONTIER_FOUR << " " << FRONTIER_TWELVE << " " << FRONTIER_FIVE << " "; int n5 = df->pbbToNode(bb); std::set<int>::iterator ii; std::set<int>& DFset = df->getDF(n5); for (ii=DFset.begin(); ii != DFset.end(); ii++) actual << std::hex << (unsigned)df->nodeToBB(*ii)->getLowAddr() << " "; CPPUNIT_ASSERT_EQUAL(expected.str(), actual.str()); pBF->UnLoad(); delete pFE; }
/*============================================================================== * FUNCTION: createReturnBlock * OVERVIEW: Create a Return or a Oneway BB if a return statement already exists * PARAMETERS: pProc: pointer to enclosing UserProc * BB_rtls: list of RTLs for the current BB (not including pRtl) * pRtl: pointer to the current RTL with the semantics for the return statement (including a * ReturnStatement as the last statement) * RETURNS: Pointer to the newly created BB *============================================================================*/ PBB FrontEnd::createReturnBlock(UserProc* pProc, std::list<RTL*>* BB_rtls, RTL* pRtl) { Cfg* pCfg = pProc->getCFG(); PBB pBB; // Add the RTL to the list; this has the semantics for the return instruction as well as the ReturnStatement // The last Statement may get replaced with a GotoStatement if (BB_rtls == NULL) BB_rtls = new std::list<RTL*>; // In case no other semantics BB_rtls->push_back(pRtl); ADDRESS retAddr = pProc->getTheReturnAddr(); std::cout << "retAddr = " << std::hex << retAddr << " rtl = " <<std::hex<< pRtl->getAddress() << "\n"; // LOG << "retAddr = " << retAddr << " rtl = " << pRtl->getAddress() << "\n"; if (retAddr == NO_ADDRESS) { // Create the basic block pBB = pCfg->newBB(BB_rtls, RET, 0); Statement* s = pRtl->getList().back(); // The last statement should be the ReturnStatement pProc->setTheReturnAddr((ReturnStatement*)s, pRtl->getAddress()); } else { // We want to replace the *whole* RTL with a branch to THE first return's RTL. There can sometimes be extra // semantics associated with a return (e.g. Pentium return adds to the stack pointer before setting %pc and // branching). Other semantics (e.g. SPARC returning a value as part of the restore instruction) are assumed to // appear in a previous RTL. It is assumed that THE return statement will have the same semantics (NOTE: may // not always be valid). To avoid this assumption, we need branches to statements, not just to native addresses // (RTLs). PBB retBB = pProc->getCFG()->findRetNode(); assert(retBB); if (retBB->getFirstStmt()->isReturn()) { // ret node has no semantics, clearly we need to keep ours pRtl->deleteLastStmt(); } else pRtl->clear(); pRtl->appendStmt(new GotoStatement(retAddr)); try { pBB = pCfg->newBB(BB_rtls, ONEWAY, 1); // if BB already exists but is incomplete, exception is thrown pCfg->addOutEdge(pBB, retAddr, true); // Visit the return instruction. This will be needed in most cases to split the return BB (if it has other // instructions before the return instruction). targetQueue.visit(pCfg, retAddr, pBB); } catch(Cfg::BBAlreadyExistsError &) { if (VERBOSE) LOG << "not visiting " << retAddr << " due to exception\n"; } } return pBB; }
Configuration::Configuration( QWidget *parent, Cfg &cfg ) : QDialog( parent, 0, TRUE, WStyle_ContextHelp ) { setCaption( tr( "Configure Checkbook" ) ); // Setup layout to make everything pretty QVBoxLayout *layout = new QVBoxLayout( this ); layout->setMargin( 2 ); layout->setSpacing( 4 ); // Setup tabs for all info _mainWidget = new QTabWidget( this ); layout->addWidget( _mainWidget ); // Settings tab _mainWidget->addTab( initSettings(cfg), tr( "&Settings" ) ); // Account Types tab ColumnDef *d; _listEditTypes=new ListEdit(_mainWidget, "TYPES" ); d=new ColumnDef( tr("Type"), (ColumnDef::ColumnType)(ColumnDef::typeString | ColumnDef::typeUnique), tr("New Account Type")); _listEditTypes->addColumnDef( d ); _listEditTypes->addData( cfg.getAccountTypes() ); _mainWidget->addTab( _listEditTypes, tr( "&Account Types" ) ); // Categories tab _listEditCategories=new ListEdit(_mainWidget, "CATEGORIES" ); _listEditCategories->addColumnDef( new ColumnDef( tr("Category"), (ColumnDef::ColumnType)(ColumnDef::typeString | ColumnDef::typeUnique), tr("New Category")) ); d=new ColumnDef( tr("Type"), ColumnDef::typeList, tr("Expense") ); d->addColumnValue( tr("Expense") ); d->addColumnValue( tr("Income") ); _listEditCategories->addColumnDef( d ); QStringList lst=cfg.getCategories(); _listEditCategories->addData( lst ); _mainWidget->addTab( _listEditCategories, tr( "&Categories" ) ); // Payees tab _listEditPayees=new ListEdit(_mainWidget, "PAYEES"); _listEditPayees->addColumnDef( new ColumnDef( tr("Payee"), (ColumnDef::ColumnType)(ColumnDef::typeString | ColumnDef::typeUnique), tr("New Payee")) ); _listEditPayees->addData( cfg.getPayees() ); _mainWidget->addTab( _listEditPayees, tr("&Payees") ); }
std::vector<Cfg> tmr::post(const Cfg& cfg, unsigned short tid, MemorySetup msetup) { // execute low-level action auto post = get_post_cfgs(cfg, tid, msetup); #define RETURN return post; // check for high-level simulation #if REPLACE_INTERFERENCE_WITH_SUMMARY assert(msetup == PRF); assert(tid == 0); // initial and summaries do not need a summary auto& stmt = *cfg.pc[tid]; if (ignore_for_summary(stmt)) { RETURN; } // find those post cfgs that require a summary, i.e. that changed the shared heap auto require_summaries = find_effectful_configurations(cfg, post); if (require_summaries.size() == 0) { RETURN; } // frees shall have an empty summary if (stmt.clazz() == Statement::FREE) { // if a free comes that far, we are in trouble as it requires a non-empty summary throw std::runtime_error("Misbehaving Summary: free stmt requires non-empty summary."); } // prepare summary Cfg tmp = cfg.copy(); tmp.pc[tid] = &stmt.function().summary(); if (stmt.function().has_output()) tmp.inout[tid] = OValue(); // execute summary auto sumpost = get_post_cfgs(tmp, tid, msetup); // check summary for (const Cfg& postcfg : require_summaries) { bool covered = false; for (const Cfg& summarycfg : sumpost) { if (subset_shared(postcfg, summarycfg)) { covered = true; break; } } if (!covered) throw std::runtime_error("Misbehaving Summary: failed to mimic low-level action."); } #endif RETURN; }
// --- saveConfig ------------------------------------------------------------- void Configuration::saveConfig(Cfg &cfg) { // Settings cfg.setCurrencySymbol( symbolEdit->text() ); cfg.setUseSmallFont( smallFontCB->isChecked() ); cfg.setShowLocks( lockCB->isChecked() ); cfg.setShowBalances( balCB->isChecked() ); cfg.setOpenLastBook( openLastBookCB->isChecked() ); cfg.setShowLastTab( lastTabCB->isChecked() ); cfg.setSavePayees( savePayees->isChecked() ); // Typelist _listEditTypes->storeInList( cfg.getAccountTypes() ); // Category list QStringList lst; _listEditCategories->storeInList( lst ); cfg.setCategories( lst ); // Payees _listEditPayees->storeInList( cfg.getPayees() ); }
PackageInfo PackageManager::GetPackageManifest(const Cfg& cfg, const string& packageId, const std::string& texmfPrefix) { auto key = cfg.GetKey(packageId); if (key == nullptr) { MIKTEX_UNEXPECTED(); } PackageInfo packageInfo; packageInfo.id = packageId; for (auto val : *key) { if (val->GetName() == "displayName") { packageInfo.displayName = val->AsString(); } else if (val->GetName() == "creator") { packageInfo.creator = val->AsString(); } else if (val->GetName() == "title") { packageInfo.title = val->AsString(); } else if (val->GetName() == "version") { packageInfo.version = val->AsString(); } else if (val->GetName() == "targetSystem") { packageInfo.targetSystem = val->AsString(); } else if (val->GetName() == "description[]") { packageInfo.description = std::for_each(val->begin(), val->end(), Flattener('\n')).result; } else if (val->GetName() == "require[]") { packageInfo.requiredPackages = val->AsStringVector(); } else if (val->GetName() == "runSize") { packageInfo.sizeRunFiles = Utils::ToSizeT(val->AsString()); } else if (val->GetName() == "run[]") { for (const string& s : *val) { PathName path(s); #if defined(MIKTEX_UNIX) path.ConvertToUnix(); #endif if (texmfPrefix.empty() || (PathName::Compare(texmfPrefix, path, texmfPrefix.length()) == 0)) { packageInfo.runFiles.push_back(path.ToString()); } } } else if (val->GetName() == "docSize") { packageInfo.sizeDocFiles = Utils::ToSizeT(val->AsString()); } else if (val->GetName() == "doc[]") { for (const string& s : *val) { PathName path(s); #if defined(MIKTEX_UNIX) path.ConvertToUnix(); #endif if (texmfPrefix.empty() || (PathName::Compare(texmfPrefix, path, texmfPrefix.length()) == 0)) { packageInfo.docFiles.push_back(path.ToString()); } } } else if (val->GetName() == "sourceSize") { packageInfo.sizeSourceFiles = Utils::ToSizeT(val->AsString()); } else if (val->GetName() == "source[]") { for (const string& s : *val) { PathName path(s); #if defined(MIKTEX_UNIX) path.ConvertToUnix(); #endif if (texmfPrefix.empty() || (PathName::Compare(texmfPrefix, path, texmfPrefix.length()) == 0)) { packageInfo.sourceFiles.push_back(path.ToString()); } } } else if (val->GetName() == "timePackaged") { packageInfo.timePackaged = Utils::ToTimeT(val->AsString()); } else if (val->GetName() == "digest") { packageInfo.digest = MD5::Parse(val->AsString()); } else if (val->GetName() == "ctanPath") { packageInfo.ctanPath = val->AsString(); } else if (val->GetName() == "copyrightOwner") { packageInfo.copyrightOwner = val->AsString(); } else if (val->GetName() == "copyrightYear") { packageInfo.copyrightYear = val->AsString(); } else if (val->GetName() == "licenseType") { packageInfo.licenseType = val->AsString(); } } return packageInfo; }
LiveManager::LiveManager(Cfg &cfg) : cfg(cfg), qpTree(cfg), liveSet(cfg.getMM()) { }
void FrontSparcTest::testDelaySlot() { BinaryFileFactory bff; BinaryFile *pBF = bff.Load(BRANCH_SPARC); if (pBF == NULL) pBF = new BinaryFileStub(); // fallback on stub CPPUNIT_ASSERT(pBF != 0); CPPUNIT_ASSERT(pBF->GetMachine() == MACHINE_SPARC); Prog* prog = new Prog; FrontEnd *pFE = new SparcFrontEnd(pBF, prog, &bff); prog->setFrontEnd(pFE); // decode calls readLibraryCatalog(), which needs to have definitions for non-sparc architectures cleared Type::clearNamedTypes(); pFE->decode(prog); bool gotMain; ADDRESS addr = pFE->getMainEntryPoint(gotMain); CPPUNIT_ASSERT (addr != NO_ADDRESS); std::string name("testDelaySlot"); UserProc* pProc = new UserProc(prog, name, addr); std::ofstream dummy; bool res = pFE->processProc(addr, pProc, dummy, false); CPPUNIT_ASSERT(res == 1); Cfg* cfg = pProc->getCFG(); BB_IT it; PBB bb = cfg->getFirstBB(it); std::ostringstream o1; bb->print(o1); std::string expected("Call BB:\n" "in edges: \n" "out edges: 10a98 \n" "00010a80 0 *32* tmp := r14 - 120\n" " 0 *32* m[r14] := r16\n" " 0 *32* m[r14 + 4] := r17\n" " 0 *32* m[r14 + 8] := r18\n" " 0 *32* m[r14 + 12] := r19\n" " 0 *32* m[r14 + 16] := r20\n" " 0 *32* m[r14 + 20] := r21\n" " 0 *32* m[r14 + 24] := r22\n" " 0 *32* m[r14 + 28] := r23\n" " 0 *32* m[r14 + 32] := r24\n" " 0 *32* m[r14 + 36] := r25\n" " 0 *32* m[r14 + 40] := r26\n" " 0 *32* m[r14 + 44] := r27\n" " 0 *32* m[r14 + 48] := r28\n" " 0 *32* m[r14 + 52] := r29\n" " 0 *32* m[r14 + 56] := r30\n" " 0 *32* m[r14 + 60] := r31\n" " 0 *32* r24 := r8\n" " 0 *32* r25 := r9\n" " 0 *32* r26 := r10\n" " 0 *32* r27 := r11\n" " 0 *32* r28 := r12\n" " 0 *32* r29 := r13\n" " 0 *32* r30 := r14\n" " 0 *32* r31 := r15\n" " 0 *32* r14 := tmp\n" "00010a84 0 *32* r16 := 0x11400\n" "00010a88 0 *32* r16 := r16 | 808\n" "00010a8c 0 *32* r8 := r16\n" "00010a90 0 *32* tmp := r30\n" " 0 *32* r9 := r30 - 20\n" "00010a90 0 CALL scanf(\n" " )\n" " Reaching definitions: \n" " Live variables: \n"); std::string actual(o1.str()); CPPUNIT_ASSERT_EQUAL(expected, actual); bb = cfg->getNextBB(it); CPPUNIT_ASSERT(bb); std::ostringstream o2; bb->print(o2); expected = std::string("Call BB:\n" "in edges: 10a90 \n" "out edges: 10aa4 \n" "00010a98 0 *32* r8 := r16\n" "00010a9c 0 *32* tmp := r30\n" " 0 *32* r9 := r30 - 24\n" "00010a9c 0 CALL scanf(\n" " )\n" " Reaching definitions: \n" " Live variables: \n"); actual = std::string(o2.str()); CPPUNIT_ASSERT_EQUAL(expected, actual); bb = cfg->getNextBB(it); CPPUNIT_ASSERT(bb); std::ostringstream o3; bb->print(o3); expected = std::string("Twoway BB:\n" "in edges: 10a9c \n" "out edges: 10ac8 10ab8 \n" "00010aa4 0 *32* r8 := m[r30 - 20]\n" "00010aa8 0 *32* r16 := 5\n" "00010aac 0 *32* tmp := r16\n" " 0 *32* r0 := r16 - r8\n" " 0 *v* %flags := SUBFLAGS( tmp, r8, r0 )\n" "00010ab0 0 *32* r8 := 0x11400\n" "00010ab0 0 BRANCH 0x10ac8, condition not equals\n" "High level: %flags\n"); actual = std::string(o3.str()); CPPUNIT_ASSERT_EQUAL(expected, actual); bb = cfg->getNextBB(it); CPPUNIT_ASSERT(bb); std::ostringstream o4; bb->print(o4); expected = std::string("L1: Twoway BB:\n" "in edges: 10ab0 10ac4 \n" "out edges: 10ad8 10ad0 \n" "00010ac8 0 *32* r8 := 0x11400\n" "00010ac8 0 BRANCH 0x10ad8, condition equals\n" "High level: %flags\n"); actual = std::string(o4.str()); CPPUNIT_ASSERT_EQUAL(expected, actual); bb = cfg->getNextBB(it); CPPUNIT_ASSERT(bb); std::ostringstream o5; bb->print(o5); expected = std::string("Call BB:\n" "in edges: 10ab0 \n" "out edges: 10ac0 \n" "00010ab8 0 *32* r8 := r8 | 816\n" "00010ab8 0 CALL printf(\n" " )\n" " Reaching definitions: \n" " Live variables: \n"); actual = std::string(o5.str()); CPPUNIT_ASSERT_EQUAL(expected, actual); delete prog; }
Graph* ConfigManager::reconnect(Graph* g, Graph *old) { Graph *newGraph; Graph *oldGraph; newGraph = g; oldGraph = old; vector<CfgNode*> topoOld = oldGraph->topoSort(); vector<CfgNode*> topoNew = newGraph->topoSort(); /* disconnect all modules */ for (size_t i = 0; i < topoOld.size(); i++) { topoOld[i]->getCfg()->getInstance()->preReconfiguration(); topoOld[i]->getCfg()->disconnectInstances(); msg(MSG_INFO, "Disconnecting instance: %s", topoOld[i]->getCfg()->getName().c_str()); } /* call onReconfiguration1 on all modules */ for (size_t i = 0; i < topoOld.size(); i++) { topoOld[i]->getCfg()->onReconfiguration1(); } /* call preConfiguration2 on all modules */ for (size_t i = 0; i < topoOld.size(); i++) { topoOld[i]->getCfg()->onReconfiguration2(); } // compare the nodes in the old and new graph and search for // (nearly) identical modules which could be reused for (size_t i = 0; i < topoOld.size(); i++) { Cfg* oldCfg = topoOld[i]->getCfg(); for (size_t j = 0; j < topoNew.size(); j++) { Cfg* newCfg = topoNew[j]->getCfg(); if (oldCfg->getID() == newCfg->getID()) { // possible match msg(MSG_INFO, "found a match between %s(id=%d) -> %s(id=%d)", oldCfg->getName().c_str(), oldCfg->getID(), newCfg->getName().c_str(), newCfg->getID()); // check if we could use the same module instance in the new config if (newCfg->deriveFrom(oldCfg)) { msg(MSG_INFO, "reusing %s(id=%d)", oldCfg->getName().c_str(), oldCfg->getID()); newCfg->transferInstance(oldCfg); } else { deleter_list_item delme; delme.c = oldCfg; delme.delete_after = time(NULL) + DELETER_DELAY; // current time + 20 seconds deleter_list.push_back(delme); msg(MSG_INFO, "can't reuse %s(id=%d)", oldCfg->getName().c_str(), oldCfg->getID()); } } } } /* Now that we transfered all module instances which could be reused * into the new graph, we have to build up the new connections * * The Connector will take care to call preConnect for us!!! */ Connector con(false, true); newGraph->accept(&con); return newGraph; }
int main(int argc, char * argv[]){ if (argc < 2) { cout << "erreur : pas de fichier assembleur" << endl; } Program prog(argv[1]); Function* functmp; list <Function*> myfunc; list <Basic_block*> myBB; cout<<"Le programme a "<<prog.size()<<" lignes\n"<<endl; prog.comput_function(); cout<<"nombre de fonctions : "<<prog.nbr_func()<<endl; list<Function*>::iterator itfct; list<Basic_block*>::iterator itbb; Basic_block *bb; int i, j; list<int> frees; Dfg *d; Cfg *c; std::ostringstream *oss ; for(itfct=prog.function_list_begin(), i=0; itfct!=prog.function_list_end(); itfct++, i++){ functmp=*itfct; cout<<"------------Function DISPLAY----------\n" <<endl; functmp->display(); functmp->comput_basic_block(); functmp->comput_label(); functmp->comput_succ_pred_BB(); oss=new std::ostringstream; (*oss)<<"./tmp/func_"<<i<<".dot"; c=new Cfg(functmp->get_BB(0), functmp->nbr_BB()); c->restitution(NULL, oss->str()); cout<<"========== Function "<<i<<"==========="<<endl; cout<<"============================"<<endl; functmp ->compute_live_var(); j=0; int total1 = 0, total2 = 0, total3 = 0, total4 = 0; for(itbb=functmp->bb_list_begin(); itbb!=functmp->bb_list_end(); itbb++, j++){ bb=*itbb; bb->link_instructions(); bb->comput_pred_succ_dep(); total1 += bb->nb_cycles(); d = new Dfg(bb); d->scheduling(false); d->apply_scheduling(); total2 += bb->nb_cycles(); bb->reg_rename(); // il faut annuler le calcul des dépendances et le refaire bb->reset_pred_succ_dep(); bb->comput_pred_succ_dep(); total3 += bb->nb_cycles(); d= new Dfg(bb); d->scheduling(false); d->apply_scheduling(); total4 += bb->nb_cycles(); //return 0; } printf("Nombres de cycles : \n"); printf(" BASIC | SCHEDULED | RENAMED | RE-SCHEDULED\n"); printf(" %d | %d | %d | %d \n", total1, total2, total3, total4); } }
/** * parses configuration and adjusts/creates module graph accordingly * afterwards all modules are started */ void ConfigManager::parseConfig(std::string fileName) { lockGraph(); Graph* oldGraph = graph; graph = new Graph(); old_document = document; document = XMLDocument::parse_file(fileName); XMLElement* root = document->getRootNode(); // consistency checks if (!root) { unlockGraph(); THROWEXCEPTION("%s is an empty XML-Document!", fileName.c_str()); } if (!root->matches("ipfixConfig")) { unlockGraph(); THROWEXCEPTION("Root element does not match \"ipfixConfig\"." " This is not a valid configuration file!"); } /* process each root element node and add a new node (with its config * attached to the node) to the graph */ XMLNode::XMLSet<XMLElement*> rootElements = root->getElementChildren(); for (XMLNode::XMLSet<XMLElement*>::const_iterator it = rootElements.begin(); it != rootElements.end(); it++) { bool found = false; for (unsigned int i = 0; i < ARRAY_SIZE(configModules); i++) { if ((*it)->getName() == configModules[i]->getName()) { Cfg* cfg = configModules[i]->create(*it); // handle special modules SensorManagerCfg* smcfg = dynamic_cast<SensorManagerCfg*>(cfg); if (smcfg) { // SensorManager will not be connected to any modules, so its instance // needs to be started manually smcfg->setGraphIS(this); sensorManager = smcfg->getInstance(); } graph->addNode(cfg); found = true; } } if (!found) { msg(MSG_ERROR, "Unknown cfg entry %s found", (*it)->getName().c_str()); } } if (!oldGraph) { // this is the first config we have read Connector connector; graph->accept(&connector); } else { // first, connect the nodes on the new graph (but NOT the modules) Connector connector(true, false); graph->accept(&connector); // now connect the modules reusing those from the old graph graph = reconnect(graph, oldGraph); } // start the instances if not already running std::vector<CfgNode*> topoNodes = graph->topoSort(); for (size_t i = 0; i < topoNodes.size(); i++) { Cfg* cfg = topoNodes[topoNodes.size() -1 -i]->getCfg(); msg(MSG_INFO, "Starting module %s", cfg->getName().c_str()); cfg->start(false); } if (old_document) delete old_document; unlockGraph(); }
void SensorManager::collectDataWorker() { time_t lasttime = time(0); char* xmlpre = "<vermont>\n\t<sensorData time=\"%s\" host=\"%s\">\n"; char* xmlpost = "\t</sensorData>\n</vermont>\n"; char* xmlglobals = "\t\t<%s>%s</%s>\n"; if (!graphIS) { THROWEXCEPTION("GraphInstanceSupplier variable graphIS MUST be set when module is started!"); } string lockfile = outputFilename + ".lock"; char hostname[100]; if (gethostname(hostname, 100) != 0) THROWEXCEPTION("failed to get hostname by gethostname()!"); registerCurrentThread(); msg(MSG_FATAL, "SensorManager: checking sensor values every %u seconds", checkInterval); while (!exitFlag) { uint32_t sleepcount = checkInterval*2; uint32_t i = 0; while (i<sleepcount && !exitFlag) { // restart nanosleep with the remaining sleep time // if we got interrupted by a signal timespec req; req.tv_sec = 0; req.tv_nsec = 50000000; while (nanosleep(&req, &req) == -1 && errno == EINTR); i++; } if (exitFlag) break; // we must not wait for the graph lock, else there may be a race condition with // the ConfigManager while (!graphIS->tryLockGraph()) { if (exitFlag) break; timespec timeout = { 0, 200000 }; nanosleep(&timeout, NULL); } if (exitFlag) break; int fdlock = open(lockfile.c_str(), O_CREAT|O_RDONLY); if (fdlock == -1) msg(MSG_DEBUG, "failed to open file %s, error code %d", lockfile.c_str(), errno); if (flock(fdlock, LOCK_EX)!=0) msg(MSG_DEBUG, "failed to activate exclusive lock on file %s (flock())", lockfile.c_str()); FILE* file = fopen(outputFilename.c_str(), "w"); if (!file) { THROWEXCEPTION("failed to reopen file %s", outputFilename.c_str()); perror("error:"); } time_t curtime = time(0); char curtimestr[100]; ctime_r(&curtime, curtimestr); curtimestr[strlen(curtimestr)-1] = 0; fprintf(file, xmlpre, curtimestr, hostname); char text[100]; snprintf(text, 100, "%u", static_cast<uint32_t>(getpid())); fprintf(file, xmlglobals, "pid", text, "pid"); char lasttimestr[100]; ctime_r(&lasttime, lasttimestr); lasttimestr[strlen(lasttimestr)-1] = 0; fprintf(file, xmlglobals, "lastTime", lasttimestr, "lastTime"); #if defined(__linux__) char* xmlglobalsuint = "\t\t<%s>%u</%s>\n"; ThreadCPUInterface::SystemInfo si = ThreadCPUInterface::getSystemInfo(); fprintf(file, xmlglobalsuint, "processorAmount", si.noCPUs, "processorAmount"); for (uint16_t i=0; i<si.sysJiffies.size(); i++) { double sysutil = (si.sysJiffies[i]-lastSystemInfo.sysJiffies[i])/(static_cast<double>(curtime)-lasttime)/hertzValue*100; double userutil = (si.userJiffies[i]-lastSystemInfo.userJiffies[i])/(static_cast<double>(curtime)-lasttime)/hertzValue*100; fprintf(file, "\t\t<processor id=\"%u\"><util type=\"system\">%.2f%%</util><util type=\"user\">%.2f%%</util></processor>\n", i, sysutil, userutil); } fprintf(file, "\t\t<memory><free type=\"bytes\">%llu</free><total type=\"bytes\">%llu</total></memory>\n", si.freeMemory, si.totalMemory); lastSystemInfo = si; #endif DPRINTF("*** sensor data at %s", ctime(&curtime)); Graph* g = graphIS->getGraph(); vector<CfgNode*> nodes = g->getNodes(); vector<CfgNode*>::iterator iter = nodes.begin(); while (iter != nodes.end()) { Cfg* cfg = (*iter)->getCfg(); Sensor* s = cfg->getInstance(); vector<uint32_t> nextids = cfg->getNext(); writeSensorXML(file, s, cfg->getName().c_str(), cfg->getID(), true, curtime, lasttime, &nextids); iter++; } // iterate through all non-module sensors mutex.lock(); list<SensorEntry>::const_iterator siter = sensors.begin(); while (siter != sensors.end()) { writeSensorXML(file, siter->sensor, siter->name.c_str(), siter->id, false, curtime, lasttime, NULL); siter++; } mutex.unlock(); fprintf(file, xmlpost); fclose(file); close(fdlock); lasttime = time(0); graphIS->unlockGraph(); } unregisterCurrentThread(); }
bool DataFlow::placePhiFunctions(UserProc* proc) { // First free some memory no longer needed dfnum.resize(0); semi.resize(0); ancestor.resize(0); samedom.resize(0); vertex.resize(0); parent.resize(0); best.resize(0); bucket.resize(0); defsites.clear(); // Clear defsites map, defallsites.clear(); A_orig.clear(); // and A_orig, defStmts.clear(); // and the map from variable to defining Stmt bool change = false; // Set the sizes of needed vectors unsigned numBB = indices.size(); Cfg* cfg = proc->getCFG(); assert(numBB == cfg->getNumBBs()); A_orig.resize(numBB); // We need to create A_orig[n] for all n, the array of sets of locations defined at BB n // Recreate each call because propagation and other changes make old data invalid unsigned n; for (n=0; n < numBB; n++) { BasicBlock::rtlit rit; StatementList::iterator sit; PBB bb = BBs[n]; for (Statement* s = bb->getFirstStmt(rit, sit); s; s = bb->getNextStmt(rit, sit)) { LocationSet ls; LocationSet::iterator it; s->getDefinitions(ls); if (s->isCall() && ((CallStatement*)s)->isChildless()) // If this is a childless call defallsites.insert(n); // then this block defines every variable for (it = ls.begin(); it != ls.end(); it++) { if (canRename(*it, proc)) { A_orig[n].insert((*it)->clone()); defStmts[*it] = s; } } } } // For each node n for (n=0; n < numBB; n++) { // For each variable a in A_orig[n] std::set<Exp*, lessExpStar>& s = A_orig[n]; std::set<Exp*, lessExpStar>::iterator aa; for (aa = s.begin(); aa != s.end(); aa++) { Exp* a = *aa; defsites[a].insert(n); } } // For each variable a (in defsites, i.e. defined anywhere) std::map<Exp*, std::set<int>, lessExpStar>::iterator mm; for (mm = defsites.begin(); mm != defsites.end(); mm++) { Exp* a = (*mm).first; // *mm is pair<Exp*, set<int>> // Special processing for define-alls // for each n in defallsites std::set<int>::iterator da; for (da = defallsites.begin(); da != defallsites.end(); ++da) defsites[a].insert(*da); // W <- defsites[a]; std::set<int> W = defsites[a]; // set copy // While W not empty while (W.size()) { // Remove some node n from W int n = *W.begin(); // Copy first element W.erase(W.begin()); // Remove first element // for each y in DF[n] std::set<int>::iterator yy; std::set<int>& DFn = DF[n]; for (yy = DFn.begin(); yy != DFn.end(); yy++) { int y = *yy; // if y not element of A_phi[a] std::set<int>& s = A_phi[a]; if (s.find(y) == s.end()) { // Insert trivial phi function for a at top of block y: a := phi() change = true; Statement* as = new PhiAssign(a->clone()); PBB Ybb = BBs[y]; Ybb->prependStmt(as, proc); // A_phi[a] <- A_phi[a] U {y} s.insert(y); // if a !elementof A_orig[y] if (A_orig[y].find(a) == A_orig[y].end()) { // W <- W U {y} W.insert(y); } } } } } return change; } // end placePhiFunctions
/*============================================================================== * FUNCTION: processProc * OVERVIEW: Process a procedure, given a native (source machine) address. * PARAMETERS: address - the address at which the procedure starts * delta - the offset of the above address from the logical * address at which the procedure starts (i.e. the one * given by dis) * uUpper - the highest address of the text segment * pProc - the procedure object * decoder - NJMCDecoder object * RETURNS: <nothing> *============================================================================*/ void processProc(ADDRESS uAddr, ptrdiff_t delta, ADDRESS uUpper, UserProc* pProc, NJMCDecoder& decoder) { PBB pBB; // Pointer to the current basic block INSTTYPE type; // Cfg type of instruction (e.g. IRET) // Declare a queue of targets not yet processed yet. This has to be // individual to the procedure! TARGETS targets; // Indicates whether or not the next instruction to be decoded is the // lexical successor of the current one. Will be true for all NCTs and for // CTIs with a fall through branch. bool sequentialDecode = true; Cfg* pCfg = pProc->getCFG(); // Initialise the queue of control flow targets that have yet to be decoded. targets.push(uAddr); // Clear the pointer used by the caller prologue code to access the last // call rtl of this procedure //decoder.resetLastCall(); while ((uAddr = nextAddress(targets, pCfg)) != 0) { // The list of RTLs for the current basic block list<HRTL*>* BB_rtls = new list<HRTL*>(); // Keep decoding sequentially until a CTI without a fall through branch // is decoded ADDRESS start = uAddr; DecodeResult inst; while (sequentialDecode) { // Decode and classify the current instruction if (progOptions.trace) cout << "*" << hex << uAddr << "\t" << flush; // Decode the inst at uAddr. inst = decoder.decodeInstruction(uAddr, delta, pProc); // Need to construct a new list of RTLs if a basic block has just // been finished but decoding is continuing from its lexical // successor if (BB_rtls == NULL) BB_rtls = new list<HRTL*>(); HRTL* pRtl = inst.rtl; if (inst.numBytes == 0) { // An invalid instruction. Most likely because a call did // not return (e.g. call _exit()), etc. Best thing is to // emit a INVALID BB, and continue with valid instructions ostrstream ost; ost << "invalid instruction at " << hex << uAddr; warning(str(ost)); // Emit the RTL anyway, so we have the address and maybe // some other clues BB_rtls->push_back(new RTL(uAddr)); pBB = pCfg->newBB(BB_rtls, INVALID, 0); sequentialDecode = false; BB_rtls = NULL; continue; } HLJump* rtl_jump = static_cast<HLJump*>(pRtl); // Display RTL representation if asked if (progOptions.rtl) pRtl->print(); ADDRESS uDest; switch (pRtl->getKind()) { case JUMP_HRTL: { uDest = rtl_jump->getFixedDest(); // Handle one way jumps and computed jumps separately if (uDest != NO_ADDRESS) { BB_rtls->push_back(pRtl); sequentialDecode = false; pBB = pCfg->newBB(BB_rtls,ONEWAY,1); // Exit the switch now and stop decoding sequentially if the // basic block already existed if (pBB == 0) { sequentialDecode = false; BB_rtls = NULL; break; } // Add the out edge if it is to a destination within the // procedure if (uDest < uUpper) { visit(pCfg, uDest, targets, pBB); pCfg->addOutEdge(pBB, uDest, true); } else { ostrstream ost; ost << "Error: Instruction at " << hex << uAddr; ost << " branches beyond end of section, to "; ost << uDest; error(str(ost)); } } break; } case NWAYJUMP_HRTL: { BB_rtls->push_back(pRtl); // We create the BB as a COMPJUMP type, then change // to an NWAY if it turns out to be a switch stmt pBB = pCfg->newBB(BB_rtls, COMPJUMP, 0); if (isSwitch(pBB, rtl_jump->getDest(), pProc, pBF)) { processSwitch(pBB, delta, pCfg, targets, pBF); } else // Computed jump { // Not a switch statement ostrstream ost; string sKind("JUMP"); if (type == I_COMPCALL) sKind = "CALL"; ost << "COMPUTED " << sKind << " at " << hex << uAddr << endl; warning(str(ost)); BB_rtls = NULL; // New HRTLList for next BB } sequentialDecode = false; break; } case JCOND_HRTL: { uDest = rtl_jump->getFixedDest(); BB_rtls->push_back(pRtl); pBB = pCfg->newBB(BB_rtls, TWOWAY, 2); // Stop decoding sequentially if the basic block already existed // otherwise complete the basic block if (pBB == 0) sequentialDecode = false; else { // Add the out edge if it is to a destination within the // procedure if (uDest < uUpper) { visit(pCfg, uDest, targets, pBB); pCfg->addOutEdge(pBB, uDest, true); } else { ostrstream ost; ost << "Error: Instruction at " << hex << uAddr; ost << " branches beyond end of section, to "; ost << uDest; error(str(ost)); } // Add the fall-through outedge pCfg->addOutEdge(pBB, uAddr + inst.numBytes); } // Create the list of RTLs for the next basic block and continue // with the next instruction. BB_rtls = NULL; break; } case CALL_HRTL: { HLCall* call = static_cast<HLCall*>(pRtl); // Treat computed and static calls seperately if (call->isComputed()) { BB_rtls->push_back(pRtl); pBB = pCfg->newBB(BB_rtls, COMPCALL, 1); // Stop decoding sequentially if the basic block already // existed otherwise complete the basic block if (pBB == 0) sequentialDecode = false; else pCfg->addOutEdge(pBB, uAddr + inst.numBytes); } else // Static call { BB_rtls->push_back(pRtl); // Find the address of the callee. ADDRESS uNewAddr = call->getFixedDest(); // Add this non computed call site to the set of call // sites which need to be analysed later. pCfg->addCall(call); // Record the called address as the start of a new // procedure if it didn't already exist. if ((uNewAddr != NO_ADDRESS) && prog.findProc(uNewAddr) == NULL) { prog.visitProc(uNewAddr); if (progOptions.trace) cout << "p" << hex << uNewAddr << "\t" << flush; } // Check if this is the _exit function. May prevent us from // attempting to decode invalid instructions. char* name = prog.pBF->SymbolByAddress(uNewAddr); if (name && strcmp(name, "_exit") == 0) { // Create the new basic block pBB = pCfg->newBB(BB_rtls, CALL, 0); // Stop decoding sequentially sequentialDecode = false; } else { // Create the new basic block pBB = pCfg->newBB(BB_rtls, CALL, 1); if (call->isReturnAfterCall()) { // Constuct the RTLs for the new basic block list<HRTL*>* rtls = new list<HRTL*>(); // The only RTL in the basic block is a high level // return that doesn't have any RTs. rtls->push_back(new HLReturn(0, NULL)); BasicBlock* returnBB = pCfg->newBB(rtls, RET, 0); // Add out edge from call to return pCfg->addOutEdge(pBB, returnBB); // Put a label on the return BB (since it's an // orphan); a jump will be reqd pCfg->setLabel(returnBB); pBB->setJumpReqd(); // Give the enclosing proc a dummy callee epilogue pProc->setEpilogue(new CalleeEpilogue("__dummy", list<string>())); // Mike: do we need to set return locations? // This ends the function sequentialDecode = false; } else { // Add the fall through edge if the block didn't // already exist if (pBB != NULL) pCfg->addOutEdge(pBB, uAddr + inst.numBytes); } } } // Create the list of RTLs for the next basic block and continue // with the next instruction. BB_rtls = NULL; break; } case RET_HRTL: // Stop decoding sequentially sequentialDecode = false; // Add the RTL to the list BB_rtls->push_back(pRtl); // Create the basic block pBB = pCfg->newBB(BB_rtls, RET, 0); // Create the list of RTLs for the next basic block and continue // with the next instruction. BB_rtls = NULL; // New HRTLList for next BB break; case SCOND_HRTL: // This is just an ordinary instruction; no control transfer // Fall through case LOW_LEVEL_HRTL: // We must emit empty RTLs for NOPs, because they could be the // destinations of jumps (and splitBB won't work) // Just emit the current instr to the current BB BB_rtls->push_back(pRtl); break; } // switch (pRtl->getKind()) uAddr += inst.numBytes; // Update the RTL's number of bytes for coverage analysis (only) inst.rtl->updateNumBytes(inst.numBytes); // If sequentially decoding, check if the next address happens to // be the start of an existing BB. If so, finish off the current BB // (if any RTLs) as a fallthrough, and no need to decode again // (unless it's an incomplete BB, then we do decode it). // In fact, mustn't decode twice, because it will muck up the // coverage, but also will cause subtle problems like add a call // to the list of calls to be processed, then delete the call RTL // (e.g. Pentium 134.perl benchmark) if (sequentialDecode && pCfg->existsBB(uAddr)) { // Create the fallthrough BB, if there are any RTLs at all if (BB_rtls) { PBB pBB = pCfg->newBB(BB_rtls, FALL, 1); // Add an out edge to this address if (pBB) { pCfg->addOutEdge(pBB, uAddr); BB_rtls = NULL; // Need new list of RTLs } } // Pick a new address to decode from, if the BB is complete if (!pCfg->isIncomplete(uAddr)) sequentialDecode = false; } } // while sequentialDecode // Add this range to the coverage pProc->addRange(start, uAddr); // Must set sequentialDecode back to true sequentialDecode = true; } // while nextAddress() // This pass is to remove up to 3 nops between ranges. // These will be assumed to be padding for alignments of BBs // Possibly removes a lot of ranges that could otherwise be combined ADDRESS a1, a2; COV_CIT ii; Coverage temp; if (pProc->getFirstGap(a1, a2, ii)) { do { int gap = a2 - a1; if (gap < 8) { bool allNops = true; for (int i=0; i < gap; i+= 2) { // Beware endianness! getWord will work properly if (getWord(a1+i+delta) != 0x4e71) { allNops = false; break; } } if (allNops) // Remove this gap, by adding a range equal to the gap // Note: it's not safe to add the range now, so we put // the range into a temp Coverage object to be added later temp.addRange(a1, a2); } } while (pProc->getNextGap(a1, a2, ii)); } // Now add the ranges in temp pProc->addRanges(temp); }
Graph* Connector::connect(Graph* g) { const std::vector<CfgNode*>& nodes = g->getNodes(); std::map<unsigned int, CfgNode*> id2node = getId2Node(nodes); //add a ConnectionQueue to every Module which has more predecessors vector<Cfg*> check; for (unsigned int i = 0; i < nodes.size(); i++) { vector<unsigned int> nexts = nodes[i]->getCfg()->getNext(); for (unsigned int j = 0; j < nexts.size(); j++){ Cfg* successor = id2node[nexts[j]]->getCfg(); bool found = false; for(unsigned int k = 0; k < check.size(); k++){ if(check[k] == successor){ found = true; msg(MSG_INFO, "Creating ConnectionQueue for module %s[Id = %d] because of multiple predecessors", successor->getName().c_str(), successor->getID()); successor->getQueueInstance(true); break; } } if(!found) check.push_back(successor); } } //connect modules for (unsigned int i = 0; i < nodes.size(); i++) { CfgNode* fromNode = nodes[i]; Cfg* cfg = fromNode->getCfg(); std::vector<unsigned int> nexts = cfg->getNext(); if (nexts.size()==0) { cfg->setupWithoutSuccessors(); } else { for (unsigned int j = 0; j < nexts.size(); j++) { CfgNode* toNode = id2node[nexts[j]]; if (toNode == NULL) THROWEXCEPTION("next statement is illegal; there is no node with id=%d", nexts[j]); if (connectNodes) // insert the connection in the graph g->addEdge(fromNode, toNode); msg(MSG_INFO, "Connecting module %s[Id = %d/%08X] -> %s[Id = %d/%08X]", cfg->getName().c_str(), cfg->getID(), cfg->getInstance(), id2node[nexts[j]]->getCfg()->getName().c_str(), id2node[nexts[j]]->getCfg()->getID(), id2node[nexts[j]]->getCfg()->getInstance()); if (connectModules) {// connect the modules DPRINTF("connecting instances"); cfg->connectInstances(toNode->getCfg()); } } } } return g; }
void SensorManager::retrieveStatistics(bool ignoreshutdown) { const char* xmlpre = "<vermont>\n\t<sensorData time=\"%s\" host=\"%s\">\n"; const char* xmlpost = "\t</sensorData>\n</vermont>\n"; const char* xmlglobals = "\t\t<%s>%s</%s>\n"; string lockfile = outputFilename + ".lock"; // we must not wait for the graph lock, else there may be a race condition with // the ConfigManager while (!graphIS->tryLockGraph()) { if (smExitFlag) break; timespec timeout = { 0, 200000 }; nanosleep(&timeout, NULL); } if (!ignoreshutdown && smExitFlag) return; const char* openflags = (append ? "a" : "w"); FILE* file = fopen(outputFilename.c_str(), openflags); if (!file) { THROWEXCEPTION("failed to reopen file %s", outputFilename.c_str()); perror("error:"); } time_t curtime = time(0); char curtimestr[100]; ctime_r(&curtime, curtimestr); curtimestr[strlen(curtimestr)-1] = 0; fprintf(file, xmlpre, curtimestr, hostname); char text[100]; snprintf(text, 100, "%u", static_cast<uint32_t>(getpid())); fprintf(file, xmlglobals, "pid", text, "pid"); char lasttimestr[100]; ctime_r(&lasttime, lasttimestr); lasttimestr[strlen(lasttimestr)-1] = 0; fprintf(file, xmlglobals, "lastTime", lasttimestr, "lastTime"); #if defined(__linux__) const char* xmlglobalsuint = "\t\t<%s>%u</%s>\n"; ThreadCPUInterface::SystemInfo si = ThreadCPUInterface::getSystemInfo(); fprintf(file, "\t\t<jiffyFrequency>%llu</jiffyFrequency>\n", hertzValue); fprintf(file, xmlglobalsuint, "processorAmount", si.noCPUs, "processorAmount"); for (uint16_t i=0; i<si.sysJiffies.size(); i++) { double sysutil = (si.sysJiffies[i]-lastSystemInfo.sysJiffies[i])/(static_cast<double>(curtime)-lasttime)/hertzValue*100; double userutil = (si.userJiffies[i]-lastSystemInfo.userJiffies[i])/(static_cast<double>(curtime)-lasttime)/hertzValue*100; fprintf(file, "\t\t<processor id=\"%u\"><util type=\"system\">%.2f</util><util type=\"user\">%.2f</util></processor>\n", i, sysutil, userutil); } fprintf(file, "\t\t<memory><free type=\"bytes\">%llu</free><total type=\"bytes\">%llu</total></memory>\n", si.freeMemory, si.totalMemory); lastSystemInfo = si; #endif //DPRINTF("*** sensor data at %s", ctime(&curtime)); Graph* g = graphIS->getGraph(); vector<CfgNode*> nodes = g->getNodes(); vector<CfgNode*>::iterator iter = nodes.begin(); while (iter != nodes.end()) { Cfg* cfg = (*iter)->getCfg(); Sensor* s = cfg->getInstance(); vector<uint32_t> nextids = cfg->getNext(); writeSensorXML(file, s, cfg->getName().c_str(), cfg->getID(), true, curtime, lasttime, &nextids); iter++; } // iterate through all non-module sensors mutex.lock(); list<SensorEntry>::const_iterator siter = sensors.begin(); while (siter != sensors.end()) { writeSensorXML(file, siter->sensor, siter->name.c_str(), siter->id, false, curtime, lasttime, NULL); siter++; } mutex.unlock(); fprintf(file, "%s", xmlpost); fclose(file); graphIS->unlockGraph(); }
/*============================================================================== * FUNCTION: FrontEnd::processProc * OVERVIEW: Process a procedure, given a native (source machine) address. * PARAMETERS: address - the address at which the procedure starts * pProc - the procedure object * frag - if true, this is just a fragment of a procedure * spec - if true, this is a speculative decode * os - the output stream for .rtl output * NOTE: This is a sort of generic front end. For many processors, this will be overridden * in the FrontEnd derived class, sometimes calling this function to do most of the work * RETURNS: true for a good decode (no illegal instructions) *============================================================================*/ bool FrontEnd::processProc(ADDRESS uAddr, UserProc* pProc, std::ofstream &os, bool frag /* = false */, bool spec /* = false */) { PBB pBB; // Pointer to the current basic block std::cout<<"Entering Processing Proc\n"; // just in case you missed it first_line = true; if (AssProgram) std::cout <<"Name Of Program : " << AssProgram->name << std::endl; Boomerang::get()->alert_new(pProc); // We have a set of CallStatement pointers. These may be disregarded if this is a speculative decode // that fails (i.e. an illegal instruction is found). If not, this set will be used to add to the set of calls // to be analysed in the cfg, and also to call newProc() std::list<CallStatement*> callList; // Indicates whether or not the next instruction to be decoded is the lexical successor of the current one. // Will be true for all NCTs and for CTIs with a fall through branch. bool sequentialDecode = true; Cfg* pCfg = pProc->getCFG(); // If this is a speculative decode, the second time we decode the same address, we get no cfg. Else an error. if (spec && (pCfg == 0)) return false; assert(pCfg); // Initialise the queue of control flow targets that have yet to be decoded. targetQueue.initial(uAddr); // Clear the pointer used by the caller prologue code to access the last call rtl of this procedure //decoder.resetLastCall(); // ADDRESS initAddr = uAddr; int nTotalBytes = 0; ADDRESS startAddr = uAddr; ADDRESS lastAddr = uAddr; ADDRESS address = uAddr; std::cout << "Start at address = " << uAddr << std::endl; //------IMPORTANT------------------------------------------------------------------------ list<AssemblyLabel*>::iterator lbi; list<AssemblyLine*>* temp_lines = new list<AssemblyLine*>(); if (AssProgram){ for(lbi = AssProgram->labelList->begin(); lbi != AssProgram->labelList->end(); ++lbi ){ if((*lbi)->address == uAddr){ temp_lines = (*lbi)->lineList; std::cout << "***DECODE LABEL: " << (*lbi)->name << std::endl; std::cout << "***AT ADDRESS: " << (*lbi)->address << std::endl; std::cout << "***NUMBER OF INSTRUCTION: " << (*lbi)->lineList->size() << std::endl; break; } } } list<AssemblyLine*>::iterator li; if (temp_lines->size()>0) li = temp_lines->begin(); //--------------------------------------------------------------------------------------- while ((uAddr = targetQueue.nextAddress(pCfg)) != NO_ADDRESS) { // The list of RTLs for the current basic block std::list<RTL*>* BB_rtls = new std::list<RTL*>(); // Keep decoding sequentially until a CTI without a fall through branch is decoded //ADDRESS start = uAddr; DecodeResult inst; while (sequentialDecode) { // Decode and classify the current source instruction if (Boomerang::get()->traceDecoder) LOG << "*" << uAddr << "\t"; // Decode the inst at uAddr. if(ASS_FILE){ if(li != temp_lines->end()){ inst = decodeAssemblyInstruction(uAddr,"assemblySets.at(line)", (*li)); } } else inst = decodeInstruction(uAddr); // If invalid and we are speculating, just exit if (spec && !inst.valid) return false; // Need to construct a new list of RTLs if a basic block has just been finished but decoding is // continuing from its lexical successor if (BB_rtls == NULL) BB_rtls = new std::list<RTL*>(); RTL* pRtl = inst.rtl; if (inst.valid == false) { // Alert the watchers to the problem Boomerang::get()->alert_baddecode(uAddr); // An invalid instruction. Most likely because a call did not return (e.g. call _exit()), etc. // Best thing is to emit a INVALID BB, and continue with valid instructions if (VERBOSE) { LOG << "Warning: invalid instruction at " << uAddr << ": "; // Emit the next 4 bytes for debugging for (int ii=0; ii < 4; ii++) LOG << (unsigned)(pBF->readNative1(uAddr + ii) & 0xFF) << " "; LOG << "\n"; } // Emit the RTL anyway, so we have the address and maybe some other clues BB_rtls->push_back(new RTL(uAddr)); pBB = pCfg->newBB(BB_rtls, INVALID, 0); sequentialDecode = false; BB_rtls = NULL; continue; } //pProc->unionDefine = new list<UnionDefine*>(); pProc->bitVar = AssProgram->bitVar; pProc->replacement = AssProgram->replacement; // alert the watchers that we have decoded an instruction Boomerang::get()->alert_decode(uAddr, inst.numBytes); nTotalBytes += inst.numBytes; // Check if this is an already decoded jump instruction (from a previous pass with propagation etc) // If so, we throw away the just decoded RTL (but we still may have needed to calculate the number // of bytes.. ick.) std::map<ADDRESS, RTL*>::iterator ff = previouslyDecoded.find(uAddr); if (ff != previouslyDecoded.end()) pRtl = ff->second; if (pRtl == NULL) { // This can happen if an instruction is "cancelled", e.g. call to __main in a hppa program // Just ignore the whole instruction if (inst.numBytes > 0) uAddr += inst.numBytes; continue; } // Display RTL representation if asked std::cout<<"RTL: "<<std::endl; std::ostringstream st; pRtl->print(st); std::cout << st.str().c_str()<<std::endl; ADDRESS uDest; // For each Statement in the RTL //std::list<Statement*>& sl = pRtl->getList(); std::list<Statement*> sl = pRtl->getList(); // Make a copy (!) of the list. This is needed temporarily to work around the following problem. // We are currently iterating an RTL, which could be a return instruction. The RTL is passed to // createReturnBlock; if this is not the first return statement, it will get cleared, and this will // cause problems with the current iteration. The effects seem to be worse for MSVC/Windows. // This problem will likely be easier to cope with when the RTLs are removed, and there are special // Statements to mark the start of instructions (and their native address). // FIXME: However, this workaround breaks logic below where a GOTO is changed to a CALL followed by a return // if it points to the start of a known procedure std::list<Statement*>::iterator ss; #if 1 for (ss = sl.begin(); ss != sl.end(); ss++) { // } #else // The counter is introduced because ss != sl.end() does not work as it should // FIXME: why? Does this really fix the problem? int counter = sl.size(); for (ss = sl.begin(); counter > 0; ss++, counter--) { #endif Statement* s = *ss; s->setProc(pProc); // let's do this really early! if (refHints.find(pRtl->getAddress()) != refHints.end()) { const char *nam = refHints[pRtl->getAddress()].c_str(); ADDRESS gu = prog->getGlobalAddr((char*)nam); if (gu != NO_ADDRESS) { s->searchAndReplace(new Const((int)gu), new Unary(opAddrOf, Location::global(nam, pProc))); } } s->simplify(); GotoStatement* stmt_jump = static_cast<GotoStatement*>(s); // Check for a call to an already existing procedure (including self recursive jumps), or to the PLT // (note that a LibProc entry for the PLT function may not yet exist) ADDRESS dest; Proc* proc; if (s->getKind() == STMT_GOTO) { dest = stmt_jump->getFixedDest(); if (dest != NO_ADDRESS) { proc = prog->findProc(dest); if (proc == NULL) { if(!ASS_FILE){ if (pBF->IsDynamicLinkedProc(dest)) proc = prog->setNewProc(dest); } } if (proc != NULL && proc != (Proc*)-1) { s = new CallStatement(); CallStatement *call = static_cast<CallStatement*>(s); call->setDest(dest); call->setDestProc(proc); call->setReturnAfterCall(true); // also need to change it in the actual RTL std::list<Statement*>::iterator ss1 = ss; ss1++; assert(ss1 == sl.end()); pRtl->replaceLastStmt(s); *ss = s; } } } switch (s->getKind()) { case STMT_GOTO: { uDest = stmt_jump->getFixedDest(); // Handle one way jumps and computed jumps separately if (uDest != NO_ADDRESS) { BB_rtls->push_back(pRtl); sequentialDecode = false; pBB = pCfg->newBB(BB_rtls,ONEWAY,1); BB_rtls = NULL; // Clear when make new BB // Exit the switch now if the basic block already existed if (pBB == 0) { break; } // Add the out edge if it is to a destination within the // procedure if (uDest < pBF->getLimitTextHigh()) { targetQueue.visit(pCfg, uDest, pBB); pCfg->addOutEdge(pBB, uDest, true); } else { std::cout<<"Entering Processing Proc5\n"; if (!ASS_FILE) LOG << "Error: Instruction at " << uAddr << " branches beyond end of section, to " << uDest << "\n"; else{ targetQueue.visit(pCfg, uDest, pBB); pCfg->addOutEdge(pBB, uDest, true); } } } break; } case STMT_CASE: { Exp* pDest = stmt_jump->getDest(); if (pDest == NULL) { // Happens if already analysed (now redecoding) // SWITCH_INFO* psi = ((CaseStatement*)stmt_jump)->getSwitchInfo(); BB_rtls->push_back(pRtl); pBB = pCfg->newBB(BB_rtls, NWAY, 0); // processSwitch will update num outedges pBB->processSwitch(pProc); // decode arms, set out edges, etc sequentialDecode = false; // Don't decode after the jump BB_rtls = NULL; // New RTLList for next BB break; // Just leave it alone } // Check for indirect calls to library functions, especially in Win32 programs if (pDest && pDest->getOper() == opMemOf && pDest->getSubExp1()->getOper() == opIntConst && pBF->IsDynamicLinkedProcPointer(((Const*)pDest->getSubExp1())->getAddr())) { if (VERBOSE) LOG << "jump to a library function: " << stmt_jump << ", replacing with a call/ret.\n"; // jump to a library function // replace with a call ret // TODO: std::string func = pBF->GetDynamicProcName( ((Const*)stmt_jump->getDest()->getSubExp1())->getAddr()); //------------------------------------ CallStatement *call = new CallStatement; call->setDest(stmt_jump->getDest()->clone()); LibProc *lp = pProc->getProg()->getLibraryProc(func.c_str()); if (lp == NULL) LOG << "getLibraryProc returned NULL, aborting\n"; assert(lp); call->setDestProc(lp); std::list<Statement*>* stmt_list = new std::list<Statement*>; stmt_list->push_back(call); BB_rtls->push_back(new RTL(pRtl->getAddress(), stmt_list)); pBB = pCfg->newBB(BB_rtls, CALL, 1); appendSyntheticReturn(pBB, pProc, pRtl); sequentialDecode = false; BB_rtls = NULL; if (pRtl->getAddress() == pProc->getNativeAddress()) { // it's a thunk // Proc *lp = prog->findProc(func.c_str()); func = std::string("__imp_") + func; pProc->setName(func.c_str()); //lp->setName(func.c_str()); Boomerang::get()->alert_update_signature(pProc); } callList.push_back(call); ss = sl.end(); ss--; // get out of the loop break; } BB_rtls->push_back(pRtl); // We create the BB as a COMPJUMP type, then change to an NWAY if it turns out to be a switch stmt pBB = pCfg->newBB(BB_rtls, COMPJUMP, 0); LOG << "COMPUTED JUMP at " << uAddr << ", pDest = " << pDest << "\n"; if (Boomerang::get()->noDecompile) { // try some hacks if (pDest->isMemOf() && pDest->getSubExp1()->getOper() == opPlus && pDest->getSubExp1()->getSubExp2()->isIntConst()) { // assume subExp2 is a jump table ADDRESS jmptbl = ((Const*)pDest->getSubExp1()->getSubExp2())->getInt(); unsigned int i; for (i = 0; ; i++) { ADDRESS uDest = pBF->readNative4(jmptbl + i * 4); if (pBF->getLimitTextLow() <= uDest && uDest < pBF->getLimitTextHigh()) { LOG << " guessed uDest " << uDest << "\n"; targetQueue.visit(pCfg, uDest, pBB); pCfg->addOutEdge(pBB, uDest, true); } else break; } pBB->updateType(NWAY, i); } } sequentialDecode = false; BB_rtls = NULL; // New RTLList for next BB break; } case STMT_BRANCH: { uDest = stmt_jump->getFixedDest(); BB_rtls->push_back(pRtl); pBB = pCfg->newBB(BB_rtls, TWOWAY, 2); // Stop decoding sequentially if the basic block already existed otherwise complete the basic block if (pBB == 0) sequentialDecode = false; else { // Add the out edge if it is to a destination within the procedure if (!ASS_FILE){ if (uDest < pBF->getLimitTextHigh()) { targetQueue.visit(pCfg, uDest, pBB); pCfg->addOutEdge(pBB, uDest, true); } else LOG << "Error: Instruction at " << uAddr << " branches beyond end of section, to " << uDest << "\n"; } else { targetQueue.visit(pCfg, uDest, pBB); pCfg->addOutEdge(pBB, uDest, true); } // Add the fall-through outedge pCfg->addOutEdge(pBB, uAddr + inst.numBytes); } // Create the list of RTLs for the next basic block and continue with the next instruction. BB_rtls = NULL; break; } case STMT_CALL: { CallStatement* call = static_cast<CallStatement*>(s); // Check for a dynamic linked library function // TODO: solution dont use pBF if (!ASS_FILE){ if (call->getDest()->getOper() == opMemOf && call->getDest()->getSubExp1()->getOper() == opIntConst && pBF->IsDynamicLinkedProcPointer(((Const*)call->getDest()->getSubExp1())->getAddr())) { // Dynamic linked proc pointers are treated as static. const char *nam = pBF->GetDynamicProcName( ((Const*)call->getDest()->getSubExp1())->getAddr()); Proc *p = pProc->getProg()->getLibraryProc(nam); call->setDestProc(p); call->setIsComputed(false); } } else { if (call->getDest()->getOper() == opMemOf && call->getDest()->getSubExp1()->getOper() == opIntConst && funcsType.find(((Const*)call->getDest()->getSubExp1())->getAddr())->second) { // Dynamic linked proc pointers are treated as static. const char *nam = namesList.find(((Const*)call->getDest()->getSubExp1())->getAddr())->second; Proc *p = pProc->getProg()->getLibraryProc(nam); call->setDestProc(p); call->setIsComputed(false); } } // Is the called function a thunk calling a library function? // A "thunk" is a function which only consists of: "GOTO library_function" // Should i modify if (!ASS_FILE){ if( call && call->getFixedDest() != NO_ADDRESS ) { // Get the address of the called function. ADDRESS callAddr=call->getFixedDest(); // It should not be in the PLT either, but getLimitTextHigh() takes this into account if (callAddr < pBF->getLimitTextHigh()) { // Decode it. DecodeResult decoded=decodeInstruction(callAddr); if (decoded.valid) { // is the instruction decoded succesfully? // Yes, it is. Create a Statement from it. RTL *rtl = decoded.rtl; Statement* first_statement = *rtl->getList().begin(); if (first_statement) { first_statement->setProc(pProc); first_statement->simplify(); GotoStatement* stmt_jump = static_cast<GotoStatement*>(first_statement); // In fact it's a computed (looked up) jump, so the jump seems to be a case // statement. //TODO : We dont handle this case if ( first_statement->getKind() == STMT_CASE && stmt_jump->getDest()->getOper() == opMemOf && stmt_jump->getDest()->getSubExp1()->getOper() == opIntConst && pBF->IsDynamicLinkedProcPointer(((Const*)stmt_jump->getDest()->getSubExp1())-> getAddr())) // Is it an "DynamicLinkedProcPointer"? { // Yes, it's a library function. Look up it's name. ADDRESS a = ((Const*)stmt_jump->getDest()->getSubExp1())->getAddr(); // TODO : We dont handle this case const char *nam = pBF->GetDynamicProcName(a); // Assign the proc to the call Proc *p = pProc->getProg()->getLibraryProc(nam); if (call->getDestProc()) { // prevent unnecessary __imp procs prog->removeProc(call->getDestProc()->getName()); } call->setDestProc(p); call->setIsComputed(false); call->setDest(Location::memOf(new Const(a))); } } } } } } // Treat computed and static calls separately if (call->isComputed()) { BB_rtls->push_back(pRtl); pBB = pCfg->newBB(BB_rtls, COMPCALL, 1); // Stop decoding sequentially if the basic block already // existed otherwise complete the basic block if (pBB == 0) sequentialDecode = false; else pCfg->addOutEdge(pBB, uAddr + inst.numBytes); // Add this call to the list of calls to analyse. We won't // be able to analyse it's callee(s), of course. callList.push_back(call); } else { // Static call // Find the address of the callee. ADDRESS uNewAddr = call->getFixedDest(); // Calls with 0 offset (i.e. call the next instruction) are simply pushing the PC to the // stack. Treat these as non-control flow instructions and continue. if (uNewAddr == uAddr + inst.numBytes) break; // Call the virtual helper function. If implemented, will check for machine specific funcion // calls if (helperFunc(uNewAddr, uAddr, BB_rtls)) { // We have already added to BB_rtls pRtl = NULL; // Discard the call semantics break; } BB_rtls->push_back(pRtl); // Add this non computed call site to the set of call sites which need to be analysed later. //pCfg->addCall(call); callList.push_back(call); // Record the called address as the start of a new procedure if it didn't already exist. if (uNewAddr && uNewAddr != NO_ADDRESS && pProc->getProg()->findProc(uNewAddr) == NULL) { callList.push_back(call); //newProc(pProc->getProg(), uNewAddr); if (Boomerang::get()->traceDecoder) LOG << "p" << uNewAddr << "\t"; } // Check if this is the _exit or exit function. May prevent us from attempting to decode // invalid instructions, and getting invalid stack height errors const char* name; if (!ASS_FILE){ name = pBF->SymbolByAddress(uNewAddr); if (name == NULL && call->getDest()->isMemOf() && call->getDest()->getSubExp1()->isIntConst()) { ADDRESS a = ((Const*)call->getDest()->getSubExp1())->getInt(); if (pBF->IsDynamicLinkedProcPointer(a)) name = pBF->GetDynamicProcName(a); } } else { name = namesList.find(uNewAddr)->second; } if (name && noReturnCallDest(name)) { // Make sure it has a return appended (so there is only one exit from the function) //call->setReturnAfterCall(true); // I think only the Sparc frontend cares // Create the new basic block pBB = pCfg->newBB(BB_rtls, CALL, 1); appendSyntheticReturn(pBB, pProc, pRtl); // Stop decoding sequentially sequentialDecode = false; } else { // Create the new basic block pBB = pCfg->newBB(BB_rtls, CALL, 1); if (call->isReturnAfterCall()) { // Constuct the RTLs for the new basic block std::list<RTL*>* rtls = new std::list<RTL*>(); // The only RTL in the basic block is one with a ReturnStatement std::list<Statement*>* sl = new std::list<Statement*>; sl->push_back(new ReturnStatement()); rtls->push_back(new RTL(pRtl->getAddress()+1, sl)); BasicBlock* returnBB = pCfg->newBB(rtls, RET, 0); // Add out edge from call to return pCfg->addOutEdge(pBB, returnBB); // Put a label on the return BB (since it's an orphan); a jump will be reqd pCfg->setLabel(returnBB); pBB->setJumpReqd(); // Mike: do we need to set return locations? // This ends the function sequentialDecode = false; } else { // Add the fall through edge if the block didn't // already exist if (pBB != NULL) pCfg->addOutEdge(pBB, uAddr+inst.numBytes); } } } extraProcessCall(call, BB_rtls); // Create the list of RTLs for the next basic block and continue with the next instruction. BB_rtls = NULL; break; } case STMT_RET: { // Stop decoding sequentially sequentialDecode = false; pBB = createReturnBlock(pProc, BB_rtls, pRtl); // Create the list of RTLs for the next basic block and // continue with the next instruction. BB_rtls = NULL; // New RTLList for next BB } break; case STMT_BOOLASSIGN: // This is just an ordinary instruction; no control transfer // Fall through case STMT_JUNCTION: // FIXME: Do we need to do anything here? case STMT_ASSIGN: case STMT_PHIASSIGN: case STMT_IMPASSIGN: case STMT_IMPREF: // Do nothing break; } // switch (s->getKind()) } if (BB_rtls && pRtl) // If non null, we haven't put this RTL into a the current BB as yet BB_rtls->push_back(pRtl); if (inst.reDecode) // Special case: redecode the last instruction, without advancing uAddr by numBytes continue; uAddr += inst.numBytes; if (uAddr > lastAddr) lastAddr = uAddr; // If sequentially decoding, check if the next address happens to be the start of an existing BB. If so, // finish off the current BB (if any RTLs) as a fallthrough, and no need to decode again (unless it's an // incomplete BB, then we do decode it). // In fact, mustn't decode twice, because it will muck up the coverage, but also will cause subtle problems // like add a call to the list of calls to be processed, then delete the call RTL (e.g. Pentium 134.perl // benchmark) if (sequentialDecode && pCfg->existsBB(uAddr)) { // Create the fallthrough BB, if there are any RTLs at all if (BB_rtls) { PBB pBB = pCfg->newBB(BB_rtls, FALL, 1); // Add an out edge to this address if (pBB) { pCfg->addOutEdge(pBB, uAddr); BB_rtls = NULL; // Need new list of RTLs } } // Pick a new address to decode from, if the BB is complete if (!pCfg->isIncomplete(uAddr)) sequentialDecode = false; } if(AssProgram) ++ li ; } // while sequentialDecode // Add this range to the coverage // pProc->addRange(start, uAddr); // Must set sequentialDecode back to true sequentialDecode = true; } // while nextAddress() != NO_ADDRESS //ProgWatcher *w = prog->getWatcher(); //if (w) // w->alert_done(pProc, initAddr, lastAddr, nTotalBytes); // Add the callees to the set of CallStatements, and also to the Prog object std::list<CallStatement*>::iterator it; for (it = callList.begin(); it != callList.end(); it++) { ADDRESS dest = (*it)->getFixedDest(); // Don't speculatively decode procs that are outside of the main text section, apart from dynamically // linked ones (in the .plt) // TODO: change pBF pointers if (!ASS_FILE){ if (pBF->IsDynamicLinkedProc(dest) || !spec || (dest < pBF->getLimitTextHigh())) { pCfg->addCall(*it); // Don't visit the destination of a register call Proc *np = (*it)->getDestProc(); if (np == NULL && dest != NO_ADDRESS) { //np = newProc(pProc->getProg(), dest); np = pProc->getProg()->setNewProc(dest); } if (np != NULL) { np->setFirstCaller(pProc); pProc->addCallee(np); } } } else{ pCfg->addCall(*it); // Don't visit the destination of a register call Proc *np = (*it)->getDestProc(); if (np == NULL && dest != NO_ADDRESS) { //np = newProc(pProc->getProg(), dest); np = pProc->getProg()->setNewProc(dest); } if (np != NULL) { np->setFirstCaller(pProc); pProc->addCallee(np); } } } Boomerang::get()->alert_decode(pProc, startAddr, lastAddr, nTotalBytes); std::cout<< "finished processing proc " << pProc->getName() << " at address " << pProc->getNativeAddress() << "\n"; if (VERBOSE) LOG << "finished processing proc " << pProc->getName() << " at address " << pProc->getNativeAddress() << "\n"; return true; } /*============================================================================== * FUNCTION: FrontEnd::getInst * OVERVIEW: Fetch the smallest (nop-sized) instruction, in an endianness independent manner * NOTE: Frequently overridden * PARAMETERS: addr - host address to getch from * RETURNS: An integer with the instruction in it *============================================================================*/ int FrontEnd::getInst(int addr) { return (int)(*(unsigned char*)addr); } /*============================================================================== * FUNCTION: TargetQueue::visit * OVERVIEW: Visit a destination as a label, i.e. check whether we need to queue it as a new BB to create later. * Note: at present, it is important to visit an address BEFORE an out edge is added to that address. * This is because adding an out edge enters the address into the Cfg's BB map, and it looks like the * BB has already been visited, and it gets overlooked. It would be better to have a scheme whereby * the order of calling these functions (i.e. visit() and AddOutEdge()) did not matter. * PARAMETERS: pCfg - the enclosing CFG * uNewAddr - the address to be checked * pNewBB - set to the lower part of the BB if the address * already exists as a non explicit label (BB has to be split) * RETURNS: <nothing> *============================================================================*/ void TargetQueue::visit(Cfg* pCfg, ADDRESS uNewAddr, PBB& pNewBB) { // Find out if we've already parsed the destination bool bParsed = pCfg->label(uNewAddr, pNewBB); // Add this address to the back of the local queue, // if not already processed if (!bParsed) { targets.push(uNewAddr); if (Boomerang::get()->traceDecoder) LOG << ">" << uNewAddr << "\t"; } }