int main(void) { Proc* proc = new Proc(); Environment* env = new Environment(); Country greece("Greece"), albania("Albania"), skopia("Skopia"), bulgaria("Bulgaria"), romania("Romania"); env->getCountries()->push_back(&greece); env->getCountries()->push_back(&albania); env->getCountries()->push_back(&skopia); env->getCountries()->push_back(&bulgaria); env->getCountries()->push_back(&romania); greece.addCountry(&albania); greece.addCountry(&bulgaria); greece.addCountry(&skopia); albania.addCountry(&bulgaria); bulgaria.addCountry(&skopia); bulgaria.addCountry(&romania); romania.addCountry(&skopia); proc->actions.push_back(new Color(Country::RED)); proc->actions.push_back(new Color(Country::BLUE)); proc->actions.push_back(new Color(Country::YELLOW)); proc->actions.push_back(new Color(Country::GREEN)); proc->proccess(env,new Color(Country::RED)); env->print(); return 0; }
VALUE rb_iterate(VALUE(*ifunc)(VALUE), VALUE ary, VALUE(*cb)(ANYARGS), VALUE cb_data) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); // Minor optimization. if(ifunc == rb_each && kind_of<Array>(env->get_object(ary))) { for(size_t i = 0; i < rb_ary_size(ary); i++) { (*cb)(rb_ary_entry(ary, i), cb_data, Qnil); } return ary; } NativeMethod* nm = NativeMethod::create(env->state(), (String*)Qnil, env->state()->shared.globals.rubinius.get(), env->state()->symbol("call"), (void*)cb, Fixnum::from(ITERATE_BLOCK)); nm->set_ivar(env->state(), env->state()->symbol("cb_data"), env->get_object(cb_data)); Proc* prc = Proc::create(env->state(), env->state()->shared.globals.proc.get()); prc->bound_method(env->state(), nm); env->set_outgoing_block(env->get_handle(prc)); return (*ifunc)(ary); }
bool Monitor::TerminateProc(int i) { if (WaitForSingleObject(vectMutex, 1000) == ERROR_TIMEOUT) { ReleaseMutex(vectMutex); return false; } Proc *pk = P[i]; ReleaseMutex(vectMutex); WaitForSingleObject(pk->Access, INFINITY); /*DWORD P1; if (GetExitCodeProcess(pk->prInf.hProcess, &P1) == FALSE) { ReleaseMutex(pk->Access); return false; } if (P1 != STILL_ACTIVE) return false;*/ pk->Stop(); ReleaseMutex(pk->Access); if (WaitForSingleObject(pk->prInf.hProcess, 3000) == WAIT_TIMEOUT) return false; return true; }
static void linkproc(void) { Proc *up = externup(); spllo(); up->kpfun(up->kparg); pexit("kproc dying", 0); }
int main() { StmtList *SL, *SL1; Stmt *S1, *S2, *S3, *S4, *S5, *S6; Expr *E; // statement list for Add function S1 = new AssignStmt("i",new Ident("n")); S2 = new AssignStmt("s",new Number(0)); S3 = new AssignStmt("s", new Plus(new Ident("s"), new Ident("i"))); S4 = new AssignStmt("i", new Minus(new Ident("i"), new Number(1))); SL1 = new StmtList(); SL1->insert(S4); SL1->insert(S3); E = new Ident("i"); S5 = new WhileStmt(E,SL1); S6 = new AssignStmt("return", new Ident("s")); SL = new StmtList(); SL->insert(S6); SL->insert(S5); SL->insert(S2); SL->insert(S1); cout << "Add(n)" << endl; cout << "i := n; s := 0;" << endl; cout << "while i do s := s+i; i := i-1 od;" << endl; cout << "return := s" << endl; Proc *Add; list<string> *paramlist; paramlist = new list<string>; paramlist->push_front("n"); cout << "Creating function" << endl; Add = new Proc(paramlist,SL); map<string,int> NT; map<string,Proc*> FT; NT.clear(); FT.clear(); FT["add"] = Add; list<Expr*> *arglist; Expr *E1; int n; cout << "Enter n: "; cin >> n; E1 = new Number(n); arglist = new list<Expr*>; arglist->push_front(E1); cout << "Calling function" << endl; cout << "Add(" << E1->eval(NT,FT) << ") = "; cout << Add->apply(NT,FT,arglist) << endl; return 0; }
Proc* Proc::from_env(STATE, Object* self, Object* env) { if(Proc* p = try_as<Proc>(env)) { return p; } if(BlockEnvironment* be = try_as<BlockEnvironment>(env)) { Proc* proc = Proc::create(state, self); proc->block(state, be); return proc; } return NULL; }
Proc* Proc::from_env(STATE, Object* env) { if(Proc* p = try_as<Proc>(env)) { return p; } if(BlockEnvironment* be = try_as<BlockEnvironment>(env)) { Proc* proc = Proc::create(state, G(proc)); proc->block(state, be); return proc; } return reinterpret_cast<Proc*>(Primitives::failure()); }
void BinUtil::TextSeg::dump(std::ostream& o, int flags, const char* pre) const { string pfx(pre); string pfx1 = pfx + " "; Seg::dump(o, flags, pre); o << pfx << " Procedures (" << numProcs() << ")\n"; for (ProcVec::const_iterator it = m_procs.begin(); it != m_procs.end(); ++it) { Proc* x = *it; x->dump(o, flags, pfx1.c_str()); } }
Proc* wrap_c_function(void* cb, VALUE cb_data, int arity) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); NativeMethod* nm = NativeMethod::create(env->state(), (String*)Qnil, env->state()->shared.globals.rubinius.get(), env->state()->symbol("call"), cb, Fixnum::from(arity)); nm->set_ivar(env->state(), env->state()->symbol("cb_data"), env->get_object(cb_data)); Proc* prc = Proc::create(env->state(), env->state()->shared.globals.proc.get()); prc->bound_method(env->state(), nm); return prc; }
NetgenOutStream(ostream * aout, Proc proc ) : out(aout), printheader(1) { #ifdef PARALLEL if ( netgen::id == proc.GetProc() ) print = true; else print = false; #else if ( 0 == proc.GetProc() ) print = true; else print = false; #endif }
int ACodeNode::compare(const ACodeNode* x, const ACodeNode* y) { if (x->begLine() == y->begLine()) { bool endLinesEqual = (x->endLine() == y->endLine()); if (endLinesEqual) { // We have two ACodeNode's with identical line intervals... // Use lexicographic comparison for procedures if (x->type() == ANode::TyProc && y->type() == ANode::TyProc) { Proc *px = (Proc*)x, *py = (Proc*)y; int cmp1 = px->name().compare(py->name()); if (cmp1 != 0) { return cmp1; } int cmp2 = px->linkName().compare(py->linkName()); if (cmp2 != 0) { return cmp2; } } // Use VMAInterval sets otherwise. bool x_lt_y = (x->vmaSet() < y->vmaSet()); bool y_lt_x = (y->vmaSet() < x->vmaSet()); bool vmaSetsEqual = (!x_lt_y && !y_lt_x); if (vmaSetsEqual) { // Try ranking a leaf node before a non-leaf node if ( !(x->isLeaf() && y->isLeaf())) { if (x->isLeaf()) { return -1; } // x < y else if (y->isLeaf()) { return 1; } // x > y } // Give up! return 0; } else if (x_lt_y) { return -1; } else if (y_lt_x) { return 1; } else { DIAG_Die(DIAG_Unimplemented); } } else { return SrcFile::compare(x->endLine(), y->endLine()); } } else { return SrcFile::compare(x->begLine(), y->begLine()); } }
Proc* Proc::from_env(STATE, Object* self, Object* env) { if(Proc* p = try_as<Proc>(env)) { if(p->klass() != self && p->klass() != G(proc)->get_const(state, "Method")) { p = as<Proc>(p->duplicate(state)); p->klass(state, as<Class>(self)); } return p; } if(BlockEnvironment* be = try_as<BlockEnvironment>(env)) { Proc* proc = Proc::create(state, self); proc->block(state, be); return proc; } return reinterpret_cast<Proc*>(Primitives::failure()); }
Proc* wrap_c_function(void* cb, VALUE cb_data, int arity) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); NativeMethod* nm = NativeMethod::create(env->state(), nil<String>(), env->state()->vm()->shared.globals.rubinius.get(), env->state()->symbol("call"), cb, Fixnum::from(arity), 0); nm->set_ivar(env->state(), env->state()->symbol("cb_data"), env->get_object(cb_data)); Object* current_block = env->block(); if(!current_block->nil_p()) { nm->set_ivar(env->state(), env->state()->symbol("original_block"), current_block); } Proc* prc = Proc::create(env->state(), env->state()->vm()->shared.globals.proc.get()); prc->bound_method(env->state(), nm); return prc; }
Host::Host(long *GT, EPQ** GEQ, Alg** algList, long priorities, FILE* infile, bool v) :GT(GT), GEQ(GEQ), algList(algList), priorities(priorities), verbose(v){ long PID, T, CPUT, priority; char IOs[1024], buf[4096]; char* IOsStart = IOs; char* IOsEnd = IOs; vector<Event*> eventV; while(fgets(buf, 4096, infile)){ IOs[0] = '\0'; if(3 == sscanf(buf, "P%ld,%ld,%ld(%1023[0123456789,])%ld;", &PID, &T, &CPUT, IOs, &priority)){ sscanf(buf, "%*[P0123456789,(])%ld;", &priority); } if(verbose){ printf("%ld, %ld, %ld, %s, %ld\n", PID, T, CPUT, IOs, priority); } Proc* tmp = new Proc(PID, T, CPUT, priority); while(*IOsEnd != '\0'){ if(*IOsEnd == ','){ *IOsEnd = '\0'; tmp->PIOQ.push(new Event(tmp, atol(IOsStart))); IOsStart = IOsEnd+1; } IOsEnd++; } if(IOsStart != IOsEnd){ tmp->PIOQ.push(new Event(tmp, atol(IOsStart))); } tmp->setIOs(); eventV.push_back(new Event(tmp, T)); IOsStart = IOs; IOsEnd = IOs; } *GEQ = new EPQ(EventComparator(), eventV); }
Proc* File::findProc(const char* name, const char* linkname) const { Proc* found = NULL; ProcMap::const_iterator it = m_procMap->find(name); if (it != m_procMap->end()) { if (linkname && linkname[0] != '\0') { for ( ; (it != m_procMap->end() && strcmp(it->first.c_str(), name) == 0); ++it) { Proc* p = it->second; if (strcmp(p->linkName().c_str(), linkname) == 0) { return p; // found = p } } } else { found = it->second; } } return found; }
string Alien::toXML(uint oFlags) const { string self = ANode::toXML(oFlags) + " f" + MakeAttrStr(m_filenm) + " n" + MakeAttrStr(m_displaynm); self = self + " " + XMLLineRange(oFlags) + " " + XMLVMAIntervals(oFlags); // add information on the function definition // If the alien has an ancestor and the same procedure definition exists, // we'll add an attribute 'ln' to point to the ID of the function definition. // This is needed to inform hpcprof that the alien shouldn't be considered // as different function. // 1a: get the load module of the alien LM *lm = ancestorLM(); // 1b: check if the alien has the file pointer to its definition File *file = lm->findFile(m_filenm); if (file) { // 2: check if there's the same procedure name in the file Proc *proc = file->findProc(m_displaynm); if (proc) { #if 0 // 3: check if alien's line range is within the function definition bool inc = SrcFile::include(proc->begLine(), proc->endLine(), begLine(), endLine()); if (inc) { // 4: add the link attribute to the function definition self = self + " ln" + xml::MakeAttrStr(StrUtil::toStr(proc->id())); } #endif self = self + " ln" + xml::MakeAttrStr(StrUtil::toStr(proc->id())); } } return self; }
int main (int argc, char **argv) { GtkBuilder *gtkBuilder; Controls* pControls = NULL; Proc* pProc = NULL; pControls = new Controls(); pProc = new Proc(); gtk_set_locale(); /* Initialize the widget set */ gtk_init (&argc, &argv); /* Create the main window */ gtkBuilder= gtk_builder_new(); gtk_builder_add_from_file(gtkBuilder,"npMain.glade",NULL); if(pControls->Initialize(gtkBuilder) == 0) { pControls->DoRoute(gtkBuilder, (void*)pProc); pProc->Set(pControls); gtk_widget_show_all (pControls->mainWindow); gtk_main (); } g_object_unref ( G_OBJECT(gtkBuilder) ); delete pControls; delete pProc; return 0; }
// Disassemble the instructions in each procedure void BinUtil::TextSeg::ctor_disassembleProcs() { // ------------------------------------------------------------ // Disassemble the instructions in each procedure. // ------------------------------------------------------------ VMA sectionBase = begVMA(); for (ProcVec::iterator it = m_procs.begin(); it != m_procs.end(); ++it) { Proc* p = *it; VMA procBeg = p->begVMA(); VMA procEnd = p->endVMA(); ushort insnSz = 0; VMA lastInsnVMA = procBeg; // vma of last valid instruction in the proc // Iterate over each vma at which an instruction might begin for (VMA vma = procBeg; vma < procEnd; ) { MachInsn *mi = &(m_contents[vma - sectionBase]); insnSz = LM::isa->getInsnSize(mi); if (insnSz == 0) { // This is not a recognized instruction (cf. data on CISC ISAs). ++vma; // Increment the VMA, and try to decode again. continue; } int num_ops = LM::isa->getInsnNumOps(mi); if (num_ops == 0) { // This instruction contains data. No need to decode. vma += insnSz; continue; } // We have a valid instruction at this vma! lastInsnVMA = vma; for (ushort opIndex = 0; opIndex < num_ops; opIndex++) { Insn *newInsn = makeInsn(m_lm->abfd(), mi, vma, opIndex, insnSz); m_lm->insertInsn(vma, opIndex, newInsn); } vma += insnSz; } // 'insnSz' is now the size of the last instruction or 0 // Now we can update the procedure's end address and size since we // know where the last instruction begins. The procedure's // original end address was guessed to be the begin address of the // following procedure while determining all procedures above. p->endVMA(lastInsnVMA); p->size(p->endVMA() - p->begVMA() + insnSz); } }
// Somehow, a == NO_ADDRESS has come to mean decode anything not already decoded void FrontEnd::decode(Prog *prog, ADDRESS a) { if (a != NO_ADDRESS) { std::cout<<"decode main at a!= NOADDRESS\n"; prog->setNewProc(a); if (VERBOSE) LOG << "starting decode at address " << a << "\n"; UserProc* p = (UserProc*)prog->findProc(a); if (p == NULL) { if (VERBOSE) LOG << "no proc found at address " << a << "\n"; return; } if (p->isLib()) { LOG << "NOT decoding library proc at address 0x" << a << "\n"; return; } std::ofstream os; PROGMAP::const_iterator it; for (Proc *pProc = prog->getFirstProc(it); pProc != NULL; pProc = prog->getNextProc(it)) { std::cout<<"Proc name Before main "<<pProc->getName()<<"\n"; } processProc(a, p, os); for (Proc *pProc = prog->getFirstProc(it); pProc != NULL; pProc = prog->getNextProc(it)) { std::cout<<"Proc name After decode main "<<pProc->getName()<<"\n"; } p->setDecoded(); } else { // a == NO_ADDRESS std::cout<<"decode child proc\n"; bool change = true; while (change) { change = false; PROGMAP::const_iterator it; for (Proc *pProc = prog->getFirstProc(it); pProc != NULL; pProc = prog->getNextProc(it)) { if (pProc->isLib()) continue; UserProc *p = (UserProc*)pProc; if (p->isDecoded()) continue; // undecoded userproc.. decode it change = true; std::ofstream os; std::cout<<"Signature Before :"<<p->getSignature()->prints()<<"\n"; int res = processProc(p->getNativeAddress(), p, os); std::cout<<"Signature After :"<<p->getSignature()->prints()<<"\n"; //std::cout<<"Sig type:"<<p->getSignature()->prints()<<"\n"; std::cout<<"process Proc finish< res:"<<res<<"\n"; if (res == 1) p->setDecoded(); else break; // Break out of the loops if not decoding children if (Boomerang::get()->noDecodeChildren) break; } if (Boomerang::get()->noDecodeChildren) break; } } prog->wellForm(); }
/** * Parse and execute a command supplied in interactive mode. * * \param argc The number of arguments. * \param argv Pointers to the arguments. * * \return A value indicating what happened. * * \retval 0 Success * \retval 1 Faillure * \retval 2 The user exited with \a quit or \a exit */ int Boomerang::parseCmd(int argc, const char **argv) { static Prog *prog = NULL; if (!strcmp(argv[0], "decode")) { if (argc <= 1) { std::cerr << "not enough arguments for cmd\n"; return 1; } const char *fname = argv[1]; Prog *p = loadAndDecode(fname); if (p == NULL) { std::cerr << "failed to load " << fname << "\n"; return 1; } prog = p; #if USE_XML } else if (!strcmp(argv[0], "load")) { if (argc <= 1) { std::cerr << "not enough arguments for cmd\n"; return 1; } const char *fname = argv[1]; XMLProgParser *p = new XMLProgParser(); Prog *pr = p->parse(fname); if (pr == NULL) { // try guessing pr = p->parse((outputPath + fname + "/" + fname + ".xml").c_str()); if (pr == NULL) { std::cerr << "failed to read xml " << fname << "\n"; return 1; } } prog = pr; } else if (!strcmp(argv[0], "save")) { if (prog == NULL) { std::cerr << "need to load or decode before save!\n"; return 1; } XMLProgParser *p = new XMLProgParser(); p->persistToXML(prog); #endif } else if (!strcmp(argv[0], "decompile")) { if (argc > 1) { Proc *proc = prog->findProc(argv[1]); if (proc == NULL) { std::cerr << "cannot find proc " << argv[1] << "\n"; return 1; } if (proc->isLib()) { std::cerr << "cannot decompile a lib proc\n"; return 1; } int indent = 0; ((UserProc*)proc)->decompile(new ProcList, indent); } else { prog->decompile(); } } else if (!strcmp(argv[0], "codegen")) { if (argc > 1 ) { Cluster *cluster = prog->findCluster(argv[1]); if (cluster == NULL) { std::cerr << "cannot find cluster " << argv[1] << "\n"; return 1; } prog->generateCode(cluster); } else { prog->generateCode(); } } else if (!strcmp(argv[0], "move")) { if (argc <= 1) { std::cerr << "not enough arguments for cmd\n"; return 1; } if (!strcmp(argv[1], "proc")) { if (argc <= 3) { std::cerr << "not enough arguments for cmd\n"; return 1; } Proc *proc = prog->findProc(argv[2]); if (proc == NULL) { std::cerr << "cannot find proc " << argv[2] << "\n"; return 1; } Cluster *cluster = prog->findCluster(argv[3]); if (cluster == NULL) { std::cerr << "cannot find cluster " << argv[3] << "\n"; return 1; } proc->setCluster(cluster); } else if (!strcmp(argv[1], "cluster")) { if (argc <= 3) { std::cerr << "not enough arguments for cmd\n"; return 1; } Cluster *cluster = prog->findCluster(argv[2]); if (cluster == NULL) { std::cerr << "cannot find cluster " << argv[2] << "\n"; return 1; } Cluster *parent = prog->findCluster(argv[3]); if (parent == NULL) { std::cerr << "cannot find cluster " << argv[3] << "\n"; return 1; } parent->addChild(cluster); } else { std::cerr << "don't know how to move a " << argv[1] << "\n"; return 1; } } else if (!strcmp(argv[0], "add")) { if (argc <= 1) { std::cerr << "not enough arguments for cmd\n"; return 1; } if (!strcmp(argv[1], "cluster")) { if (argc <= 2) { std::cerr << "not enough arguments for cmd\n"; return 1; } Cluster *cluster = new Cluster(argv[2]); if (cluster == NULL) { std::cerr << "cannot create cluster " << argv[2] << "\n"; return 1; } Cluster *parent = prog->getRootCluster(); if (argc > 3) { parent = prog->findCluster(argv[3]); if (cluster == NULL) { std::cerr << "cannot find cluster " << argv[3] << "\n"; return 1; } } parent->addChild(cluster); } else { std::cerr << "don't know how to add a " << argv[1] << "\n"; return 1; } } else if (!strcmp(argv[0], "delete")) { if (argc <= 1) { std::cerr << "not enough arguments for cmd\n"; return 1; } if (!strcmp(argv[1], "cluster")) { if (argc <= 2) { std::cerr << "not enough arguments for cmd\n"; return 1; } Cluster *cluster = prog->findCluster(argv[2]); if (cluster == NULL) { std::cerr << "cannot find cluster " << argv[2] << "\n"; return 1; } if (cluster->hasChildren() || cluster == prog->getRootCluster()) { std::cerr << "cluster " << argv[2] << " is not empty\n"; return 1; } if (prog->clusterUsed(cluster)) { std::cerr << "cluster " << argv[2] << " is not empty\n"; return 1; } unlink(cluster->getOutPath("xml")); unlink(cluster->getOutPath("c")); assert(cluster->getParent()); cluster->getParent()->removeChild(cluster); } else { std::cerr << "don't know how to delete a " << argv[1] << "\n"; return 1; } } else if (!strcmp(argv[0], "rename")) { if (argc <= 1) { std::cerr << "not enough arguments for cmd\n"; return 1; } if (!strcmp(argv[1], "proc")) { if (argc <= 3) { std::cerr << "not enough arguments for cmd\n"; return 1; } Proc *proc = prog->findProc(argv[2]); if (proc == NULL) { std::cerr << "cannot find proc " << argv[2] << "\n"; return 1; } Proc *nproc = prog->findProc(argv[3]); if (nproc != NULL) { std::cerr << "proc " << argv[3] << " already exists\n"; return 1; } proc->setName(argv[3]); } else if (!strcmp(argv[1], "cluster")) { if (argc <= 3) { std::cerr << "not enough arguments for cmd\n"; return 1; } Cluster *cluster = prog->findCluster(argv[2]); if (cluster == NULL) { std::cerr << "cannot find cluster " << argv[2] << "\n"; return 1; } Cluster *ncluster = prog->findCluster(argv[3]); if (ncluster == NULL) { std::cerr << "cluster " << argv[3] << " already exists\n"; return 1; } cluster->setName(argv[3]); } else { std::cerr << "don't know how to rename a " << argv[1] << "\n"; return 1; } } else if (!strcmp(argv[0], "info")) { if (argc <= 1) { std::cerr << "not enough arguments for cmd\n"; return 1; } if (!strcmp(argv[1], "prog")) { std::cout << "prog " << prog->getName() << ":\n"; std::cout << "\tclusters:\n"; prog->getRootCluster()->printTree(std::cout); std::cout << "\n\tlibprocs:\n"; PROGMAP::const_iterator it; for (Proc *p = prog->getFirstProc(it); p; p = prog->getNextProc(it)) if (p->isLib()) std::cout << "\t\t" << p->getName() << "\n"; std::cout << "\n\tuserprocs:\n"; for (Proc *p = prog->getFirstProc(it); p; p = prog->getNextProc(it)) if (!p->isLib()) std::cout << "\t\t" << p->getName() << "\n"; std::cout << "\n"; return 0; } else if (!strcmp(argv[1], "cluster")) { if (argc <= 2) { std::cerr << "not enough arguments for cmd\n"; return 1; } Cluster *cluster = prog->findCluster(argv[2]); if (cluster == NULL) { std::cerr << "cannot find cluster " << argv[2] << "\n"; return 1; } std::cout << "cluster " << cluster->getName() << ":\n"; if (cluster->getParent()) std::cout << "\tparent = " << cluster->getParent()->getName() << "\n"; else std::cout << "\troot cluster.\n"; std::cout << "\tprocs:\n"; PROGMAP::const_iterator it; for (Proc *p = prog->getFirstProc(it); p; p = prog->getNextProc(it)) if (p->getCluster() == cluster) std::cout << "\t\t" << p->getName() << "\n"; std::cout << "\n"; return 0; } else if (!strcmp(argv[1], "proc")) { if (argc <= 2) { std::cerr << "not enough arguments for cmd\n"; return 1; } Proc *proc = prog->findProc(argv[2]); if (proc == NULL) { std::cerr << "cannot find proc " << argv[2] << "\n"; return 1; } std::cout << "proc " << proc->getName() << ":\n"; std::cout << "\tbelongs to cluster " << proc->getCluster()->getName() << "\n"; std::cout << "\tnative address " << std::hex << proc->getNativeAddress() << std::dec << "\n"; if (proc->isLib()) std::cout << "\tis a library proc.\n"; else { std::cout << "\tis a user proc.\n"; UserProc *p = (UserProc*)proc; if (p->isDecoded()) std::cout << "\thas been decoded.\n"; //if (p->isAnalysed()) // std::cout << "\thas been analysed.\n"; } std::cout << "\n"; return 0; } else { std::cerr << "don't know how to print info about a " << argv[1] << "\n"; return 1; } } else if (!strcmp(argv[0], "print")) { if (argc <= 1) { std::cerr << "not enough arguments for cmd\n"; return 1; } Proc *proc = prog->findProc(argv[1]); if (proc == NULL) { std::cerr << "cannot find proc " << argv[1] << "\n"; return 1; } if (proc->isLib()) { std::cerr << "cannot print a libproc.\n"; return 1; } ((UserProc*)proc)->print(std::cout); std::cout << "\n"; return 0; } else if (!strcmp(argv[0], "exit")) { return 2; } else if (!strcmp(argv[0], "quit")) { return 2; } else if (!strcmp(argv[0], "help")) { helpcmd(); return 0; } else { std::cerr << "unknown cmd " << argv[0] << ".\n"; return 1; } return 0; }
static int tfn(void *arg) { Proc *up = externup(); return up->trend == nil || up->tfn(arg); }
inline ID<Proc>::ID(const Proc& proc) : ID<Asset> (proc.getID()) {};
Object* Proc::call(STATE, Arguments& args) { bool lambda_style = CBOOL(lambda()); int flags = 0; Proc* self = this; OnStack<1> os(state, self); // Check the arity in lambda mode if(lambda_style && !block()->nil_p()) { flags = CallFrame::cIsLambda; int total = self->block()->compiled_code()->total_args()->to_native(); int required = self->block()->compiled_code()->required_args()->to_native(); bool arity_ok = false; if(Fixnum* fix = try_as<Fixnum>(self->block()->compiled_code()->splat())) { switch(fix->to_native()) { case -2: arity_ok = true; break; case -4: // splat = -4 means { |(a, b)| } if(args.total() == 1) { Array* ary = 0; Object* obj = args.get_argument(0); if(!(ary = try_as<Array>(obj))) { if(CBOOL(obj->respond_to(state, G(sym_to_ary), cFalse))) { if(!(ary = try_as<Array>(obj->send(state, G(sym_to_ary))))) { Exception::type_error(state, "to_ary must return an Array"); return 0; } } } if(ary) args.use_argument(ary); } // fall through for arity check case -3: // splat = -3 is used to distinguish { |a, | } from { |a| } if(args.total() == (size_t)required) arity_ok = true; break; default: if(args.total() >= (size_t)required) { arity_ok = true; } } } else { arity_ok = args.total() <= (size_t)total && args.total() >= (size_t)required; } if(!arity_ok) { Exception* exc = Exception::make_argument_error(state, required, args.total(), block()->compiled_code()->name()); exc->locations(state, Location::from_call_stack(state)); state->raise_exception(exc); return NULL; } } if(self->bound_method()->nil_p()) { if(self->block()->nil_p()) { Dispatch dispatch(state->symbol("__yield__")); return dispatch.send(state, args); } else { return self->block()->call(state, args, flags); } } else if(NativeMethod* nm = try_as<NativeMethod>(self->bound_method())) { return nm->execute(state, nm, G(object), args); } else if(NativeFunction* nf = try_as<NativeFunction>(self->bound_method())) { return nf->call(state, args); } else { Exception* exc = Exception::make_type_error(state, BlockEnvironment::type, self->bound_method(), "NativeMethod nor NativeFunction bound to proc"); exc->locations(state, Location::from_call_stack(state)); state->raise_exception(exc); return NULL; } }
void FrontEnd::decode(Prog* prog, bool decodeMain, const char *pname) { if (pname) {prog->setName(pname); std::cout<<"decode pname == "<<pname<<"\n"; } else {std::cout<<"decode pname==null\n";} if (!decodeMain) return; Boomerang::get()->alert_start_decode(pBF->getLimitTextLow(), pBF->getLimitTextHigh() - pBF->getLimitTextLow()); bool gotMain; ADDRESS a; a = getMainEntryPoint(gotMain); std::cout<< "start: " << a << " gotmain: " << (gotMain ? "true" : "false") << "\n"; if (VERBOSE) LOG << "start: " << a << " gotmain: " << (gotMain ? "true" : "false") << "\n"; if (a == NO_ADDRESS) { std::vector<ADDRESS> entrypoints = getEntryPoints(); for (std::vector<ADDRESS>::iterator it = entrypoints.begin(); it != entrypoints.end(); it++) decode(prog, *it); return; } decode(prog, a); prog->setEntryPoint(a); if (gotMain) { static const char *mainName[] = { "main", "WinMain", "DriverEntry" }; const char *name = pBF->SymbolByAddress(a); std::cout<<"Proc name "<<name<<"\n"; if (name == NULL) name = mainName[0]; for (size_t i = 0; i < sizeof(mainName)/sizeof(char*); i++) { if (!strcmp(name, mainName[i])) { Proc *proc = prog->findProc(a); if (proc == NULL) { if (VERBOSE) LOG << "no proc found for address " << a << "\n"; return; } FuncType *fty = dynamic_cast<FuncType*>(Type::getNamedType(name)); if (fty == NULL) LOG << "unable to find signature for known entrypoint " << name << "\n"; else { std::cout<<"Sig type:"<<fty->getSignature()->getReturns()[0]->type->prints(); proc->setSignature(fty->getSignature()->clone()); proc->getSignature()->setName(name); //proc->getSignature()->setFullSig(true); // Don't add or remove parameters proc->getSignature()->setForced(true); // Don't add or remove parameters } break; } } } return; }
/*============================================================================== * 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"; } }
void BinUtil::TextSeg::ctor_initProcs() { Dbg::LM* dbgInfo = m_lm->getDebugInfo(); // Any procedure with a parent has a <Proc*, parentVMA> entry std::map<Proc*, VMA> parentMap; // ------------------------------------------------------------ // Each text section finds and creates its own routines. // Traverse the symbol table (which is sorted by VMA) searching // for function symbols in our section. Create a Proc for // each one found. // // Note that symbols can appear multiple times (e.g. a weak symbol // 'sbrk' along with a gloabl symbol '__sbrk'), but we should not // have multiple procedures. // ------------------------------------------------------------ bfd* abfd = m_lm->abfd(); asymbol** symtab = m_lm->bfdSymTab(); // sorted uint symtabSz = m_lm->bfdSymTabSz(); // FIXME:PERF: exploit sortedness of 'symtab' to start iteration for (uint i = 0; i < symtabSz; i++) { asymbol* sym = symtab[i]; if (isIn(bfd_asymbol_value(sym)) && Proc::isProcBFDSym(sym)) { // NOTE: initially we have [begVMA, endVMA) where endVMA is the // *end* of the last insn. This is changed after decoding below. VMA begVMA = bfd_asymbol_value(sym); VMA endVMA = 0; Proc::Type procType; if (sym->flags & BSF_LOCAL) { procType = Proc::Local; } else if (sym->flags & BSF_WEAK) { procType = Proc::Weak; } else if (sym->flags & BSF_GLOBAL) { procType = Proc::Global; } else { procType = Proc::Unknown; } Proc* proc = m_lm->findProc(begVMA); if (proc) { DIAG_Assert(proc->begVMA() == begVMA, "TextSeg::ctor_initProcs: Procedure beginning at 0x" << hex << begVMA << " overlaps with:\n" << proc->toString()); if (procType == Proc::Global) { // 'global' types take precedence proc->type(procType); } continue; } // Create a procedure based on best information we have. We // always prefer explicit debug information over that inferred // from the symbol table. string procNm; string symNm = bfd_asymbol_name(sym); Dbg::LM::iterator it = dbgInfo->find(begVMA); Dbg::Proc* dbg = (it != dbgInfo->end()) ? it->second : NULL; if (!dbg) { procNm = findProcName(abfd, sym); string pnm = BinUtil::canonicalizeProcName(procNm); Dbg::LM::iterator1 it1 = dbgInfo->find1(pnm); dbg = (it1 != dbgInfo->end1()) ? it1->second : NULL; } if (!dbg) { Dbg::LM::iterator1 it1 = dbgInfo->find1(symNm); dbg = (it1 != dbgInfo->end1()) ? it1->second : NULL; } // Finding the end VMA (end of last insn). The computation is // as follows because sometimes the debug information is // *wrong*. (Intel 9 has generated significant over-estimates). // // N.B. exploits the fact that the symbol table is sorted by vma VMA endVMA_approx = findProcEnd(i); if (dbg) { if (!dbg->name.empty()) { procNm = dbg->name; } else if (!symNm.empty()) { // sometimes a procedure name is in the symbol table even // though it is not in the dwarf section. this case occurs // when gcc outlines routines from OpenMP parallel sections. procNm = symNm; } #if 1 // Remove capability below... the DWARF sizes can be wrong!! endVMA = endVMA_approx; #else endVMA = std::min(dbg->endVMA, endVMA_approx); if (endVMA != endVMA_approx) { int64_t diff = endVMA - endVMA_approx; DIAG_DevMsg(0, procNm << ": inconsistent end VMA: " << diff << " [" << std::showbase << std::hex << begVMA << "-" << endVMA << "/" << endVMA_approx << std::dec << "]"); } #endif } if (!dbg || endVMA == 0) { endVMA = endVMA_approx; } uint size = endVMA - begVMA; if (size == 0) { continue; } // We now have a valid procedure. Initilize with [begVMA, endVMA), // but note this is changed after disassembly. proc = new Proc(this, procNm, symNm, procType, begVMA, endVMA, size); m_procs.push_back(proc); m_lm->insertProc(VMAInterval(begVMA, endVMA), proc); // Add symbolic info if (dbg) { proc->filename(dbg->filenm); proc->begLine(dbg->begLine); if (dbg->parent) { parentMap.insert(std::make_pair(proc, dbg->parent->begVMA)); } } } } // ------------------------------------------------------------ // If a text section does not have any function symbols, consider // the whole section a quasi procedure // ------------------------------------------------------------ if (numProcs() == 0) { // [begVMA, endVMA) Proc* proc = new Proc(this, name(), name(), Proc::Quasi, begVMA(), endVMA(), size()); m_procs.push_back(proc); m_lm->insertProc(VMAInterval(begVMA(), endVMA()), proc); } // ------------------------------------------------------------ // Embed parent information // ------------------------------------------------------------ for (std::map<Proc*, VMA>::iterator it = parentMap.begin(); it != parentMap.end(); ++it) { Proc* child = it->first; VMA parentVMA = it->second; Proc* parent = m_lm->findProc(parentVMA); DIAG_AssertWarn(parent, "Could not find parent within this section:\n" << child->toString()); if (parent == child) { DIAG_WMsg(0, "Procedure has itself as parent!\n" << child->toString()); continue; // skip } child->parent(parent); } }