示例#1
0
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;
}
示例#2
0
文件: array.cpp 项目: mutle/rubinius
  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);
  }
示例#3
0
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;
}
示例#4
0
文件: arch.c 项目: Requaos/harvey
static void
linkproc(void)
{
	Proc *up = externup();
	spllo();
	up->kpfun(up->kparg);
	pexit("kproc dying", 0);
}
示例#5
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;
}
示例#6
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;
  }
示例#7
0
文件: proc.cpp 项目: vasco/rubinius
  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());
  }
示例#8
0
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());
  }
}
示例#9
0
    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;
    }
示例#10
0
  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
  }
示例#11
0
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());
  }
}
示例#12
0
  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());
  }
示例#13
0
文件: capi.cpp 项目: cutorad/rubinius
    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;
    }
示例#14
0
    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);
        
    }
示例#15
0
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;
}
示例#16
0
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;
}
示例#17
0
文件: main.cpp 项目: febwave/netpoint
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;
}
示例#18
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();
}
示例#20
0
/**
 * 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;
}
示例#21
0
文件: proc.c 项目: Shamar/harvey
static int
tfn(void *arg)
{
	Proc *up = externup();
	return up->trend == nil || up->tfn(arg);
}
示例#22
0
 inline ID<Proc>::ID(const Proc& proc) : ID<Asset> (proc.getID()) {};
示例#23
0
  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";
	}
}
示例#26
0
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);
  }
}