Example #1
0
bool DecoderWindows::decodeCreateThread( DEBUG_EVENT &e, Event::ptr &newEvt, int_process* &proc, std::vector<Event::ptr> &events )
{
	pthrd_printf("Decoded CreateThread event, PID: %d, TID: %d\n", e.dwProcessId, e.dwThreadId);
	proc = ProcPool()->findProcByPid(e.dwProcessId);
	assert(proc);

	// FIXME once things actually work
	windows_process* wproc = dynamic_cast<windows_process*>(proc);
	assert(wproc);

	if(e.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT) {
		newEvt = WinEventThreadInfo::ptr(new WinEventThreadInfo((Dyninst::LWP)(e.dwThreadId), e.u.CreateProcessInfo.hThread,
			e.u.CreateProcessInfo.lpStartAddress, e.u.CreateProcessInfo.lpThreadLocalBase));
		newEvt->setThread(proc->threadPool()->initialThread()->thread());
		wproc->plat_setHandles(e.u.CreateProcessInfo.hProcess, e.u.CreateProcessInfo.hFile, (Dyninst::Address)e.u.CreateProcessInfo.lpBaseOfImage);
	} else {
		newEvt = WinEventNewThread::ptr(new WinEventNewThread((Dyninst::LWP)(e.dwThreadId), e.u.CreateThread.hThread,
			e.u.CreateThread.lpStartAddress, e.u.CreateThread.lpThreadLocalBase));
	}


	newEvt->setProcess(proc->proc());
	newEvt->setSyncType(Event::sync_process);
	events.push_back(newEvt);
	return true;
}
Example #2
0
Event::ptr DecoderWindows::decodeBreakpointEvent(DEBUG_EVENT e, int_process* proc, int_thread* thread)
{
	Event::ptr evt;
	// This handles user-level breakpoints; if we can't associate this with a thread we know about, it's not
	// something the user installed (or we're in an inconsistent state). Forward to the mutatee.
	if(!thread) return evt;
	Dyninst::Address adjusted_addr = (Dyninst::Address)(e.u.Exception.ExceptionRecord.ExceptionAddress);

	if (rpcMgr()->isRPCTrap(thread, adjusted_addr)) {
		pthrd_printf("Decoded event to rpc completion on %d/%d at %lx\n",
			proc->getPid(), thread->getLWP(), adjusted_addr);
		evt = Event::ptr(new EventRPC(thread->runningRPC()->getWrapperForDecode()));
		return evt;
	}

	sw_breakpoint *ibp = proc->getBreakpoint(adjusted_addr);

	if (ibp) {
	   pthrd_printf("Decoded breakpoint on %d/%d at %lx\n", proc->getPid(), 
					thread->getLWP(), adjusted_addr);
       EventBreakpoint::ptr event_bp = EventBreakpoint::ptr(new EventBreakpoint(new int_eventBreakpoint(adjusted_addr, ibp, thread)));
	   evt = event_bp;
	   evt->setThread(thread->thread());
	}
	return evt;

}
Example #3
0
Handler::handler_ret_t iRPCPreCallbackHandler::handleEvent(Event::ptr ev)
{
   EventRPC *event = static_cast<EventRPC *>(ev.get());
   int_iRPC::ptr rpc = event->getllRPC()->rpc;

   int_thread::State newstate = rpc->getRestoreToState();
   if (newstate == int_thread::none)
      return ret_success;

   int_thread *thr = ev->getThread()->llthrd();
   thr->getUserState().setState(newstate);
   return ret_success;
}
Example #4
0
 void spreadsheet_cell_text::handle_event(event::ptr e)
 {
     switch (e->type())
     {
     case event::key_up:
     {
         key_event::ptr ke = boost::dynamic_pointer_cast<key_event>(e);
         switch ( ke->fn_key() )
         {
         case key_backspace:
             INFO("Backspace hit in ssheet_cell_text");
             if (text_.size() > 0)
                 text_.resize(text_.size()-1);
             if (parent_.lock())
                 parent_.lock()->redraw(parent_.lock()->rect());
             return;
         }
         
         if ((ke->fn_key() != key_backspace) && (ke->character() != 0))
         {
             text_+=ke->character();
             if (parent_.lock())
                 parent_.lock()->redraw(parent_.lock()->rect());
             return;
         }
     }
     }
     
     spreadsheet_cell::handle_event(e);
 }
Example #5
0
    void ScreenMaster::onEvent(const Event::ptr& event){
	switch(event->getEventType()){
	case GAME_START:
	    gameScreen();
	    break;
	}
    }
Example #6
0
    /// Handle common widget events
    /// Try to handle the passed event, if there is nothing to do with it pass it up to the parent.
    /// Every non container should call widget::handle_event(e) from within its handle_event
    /// routine if it hasn't handled the event on its own. 
    /// (or container::handle_event(e) which does just that)
    void widget::handle_event(event::ptr e)
    {
        // default handlers for focus/un_focus mouse_enter/leave events
        // a derived widget should call widget::handle_event() for these basic events
        switch (e->type())
        {
        case event::focus:
            if (focusable_)
            {
                focused_ = true;
                redraw(rect());
                return; // only return if we are focusable, otherwise try our parent
            }
            break;
        case event::un_focus:
            if (focusable_)
            {
                focused_ = false;
                pressed_ = false;
                redraw(rect());
                return; // only return if we are focusable, otherwise try our parent
            }
            break;
        case event::mouse_enter:
            hover_ = true;
            redraw(rect());
            return;
            break;
        case event::mouse_leave:
            hover_ = false;
            pressed_ = false;
            redraw(rect());
            return;
            break;
        case event::key_up:
        {
            key_event::ptr ke = boost::shared_static_cast<key_event>(e);
            if (on_keyup(ke->fn_key())) return;
            break;
        }
        case event::mouse_motion:
        case event::mouse_up:
        case event::mouse_down:
        {
            // if this is a mouse event, translate the coordinates back relative to the parent
            mouse_event::ptr me = boost::shared_static_cast<mouse_event>(e);
            widget::ptr widget_parent = boost::shared_dynamic_cast<widget>(parent_.lock());
            if (widget_parent)
            {
                me->x(me->x() + widget_parent->position().x());
                me->y(me->y() + widget_parent->position().y());
            }
            // this is handed up to the parent below
        }
        }

        parent_.lock()->handle_event(e);
    }
Example #7
0
    void StartScreen::onEvent(const Event::ptr& event){
	HSG_DEBUG("StartScreen::onEvent");
	switch(event->getEventType()){
	case SYSTEM_MOUSE_CLICK:
	{
	    EventClick* clickEvent = (EventClick*)event.get();

	    Vector3 gameCoords = m_coordSystem->toGameCoords(clickEvent->x, clickEvent->y);
	    float left = m_buttonSprite->getLocation().x - m_buttonSprite->getWidth() / 2;
	    float right = m_buttonSprite->getLocation().x  + m_buttonSprite->getWidth() / 2;
	    float top = m_buttonSprite->getLocation().y  + m_buttonSprite->getHeight() / 2;
	    float bottom = m_buttonSprite->getLocation().y  - m_buttonSprite->getHeight() / 2;

	    if(gameCoords.x > left && gameCoords.x < right
	       && gameCoords.y < top && gameCoords.y > bottom){

		m_gameQueue->postEvent(Event::ptr(new Event(GAME_START)));
	    }
	}
	break;
	}
    }
void GameOverScreen::update(float deltaTime)
{
	std::deque<Event::ptr>& events = Game::getInstance()->getEvents();
	std::deque<Event::ptr>::size_type numEvents = events.size();
	std::deque<Event::ptr>::size_type eventsHandled = 0;

	while (!events.empty() && eventsHandled++ < numEvents)
	{
		Event::ptr ev = events.front();
		events.pop_front();

		switch (ev->eventType)
		{
		case EventType::Keyboard:
			{
				KeyboardEvent* keyEvent = static_cast<KeyboardEvent*>(ev.get());
				keyboardEventHandler(keyEvent);
			}
			break;

		case EventType::MouseButton:
			{
				MouseButtonEvent* mbEvent = static_cast<MouseButtonEvent*>(ev.get());				
				mouseButtonEventHandler(mbEvent);
				
			}
			break;
		case EventType::MouseMove:
			{
				MouseMoveEvent* mmEvent = static_cast<MouseMoveEvent*>(ev.get());
				mouseMoveEventHandler(mmEvent);
			}
			break;
		}
	}
}
Example #9
0
bool Generator::getAndQueueEventInt(bool block)
{
   bool result = true;
   //static ArchEvent *arch_event = NULL;
   ArchEvent* arch_event = getCachedEvent();
   vector<Event::ptr> events;
   vector<ArchEvent *> archEvents;

   if (isExitingState()) {
      pthrd_printf("Generator exiting before processWait\n");
      result = false;
      goto done;
   }
   setState(process_blocked);
   result = processWait(block);
   if (isExitingState()) {
      pthrd_printf("Generator exiting after processWait\n");
      result = false;
      goto done;
   }
   if (!result) {
	   pthrd_printf("Generator exiting after processWait returned false\n");
	   result = false;
      goto done;
   }
   result = plat_continue(arch_event);
   if(!result) {
	   pthrd_printf("Generator exiting after plat_continue returned false\n");
	   result = false;
	   goto done;
   }
   setState(system_blocked);

   pthrd_printf("About to getEvent()\n");
   result = getMultiEvent(block, archEvents);
   pthrd_printf("Got event\n");
   if (isExitingState()) {
      pthrd_printf("Generator exiting after getEvent\n");
      result = false;
      goto done;
   }
   if (!result) {
      pthrd_printf("Error. Unable to recieve event\n");
      result = false;
      goto done;
   }

   setState(decoding);
   //mbox()->lock_queue();
   ProcPool()->condvar()->lock();

   for (vector<ArchEvent *>::iterator i = archEvents.begin(); i != archEvents.end(); i++) {
	   arch_event = *i;
      for (decoder_set_t::iterator j = decoders.begin(); j != decoders.end(); j++) {
         Decoder *decoder = *j;
         bool result = decoder->decode(arch_event, events);
         if (result)
            break;
      }
   }

   setState(statesync);
   for (vector<Event::ptr>::iterator i = events.begin(); i != events.end(); i++) {
      Event::ptr event = *i;
	  if(event) {
	      event->getProcess()->llproc()->updateSyncState(event, true);
	  }
   }

   ProcPool()->condvar()->unlock();

   setState(queueing);
   for (vector<Event::ptr>::iterator i = events.begin(); i != events.end(); ++i) {
      mbox()->enqueue(*i);
      Generator::cb_lock->lock();
      for (set<gen_cb_func_t>::iterator j = CBs.begin(); j != CBs.end(); ++j) {
         (*j)();
      }
      Generator::cb_lock->unlock(); 
   }
   //mbox()->unlock_queue();


   result = true;
 done:
   setState(none);
   setCachedEvent(arch_event);
   return result;
}
Example #10
0
 void numeric_spinner::handle_event(event::ptr e)
 {
     switch (e->type())
     {
         case event::key_down:
             {
                 key_event::ptr ke = boost::shared_static_cast<key_event>(e);
                 switch ( ke->fn_key() )
                 {
                     case key_enter:
                     case key_uparrow:
                         value_ = value_+increment_;
                         if (value_ > max_)
                         {	
                             if (wrap_) value_ = min_;
                             else value_ = max_;
                         }
                         build_label();
                         on_change();
                         redraw(rect());
                         return;
                         break;
                     case key_downarrow:
                         value_ = value_-increment_;
                         if (value_ < min_) 
                         {
                             if (wrap_) value_ = max_;
                             else value_ = min_;
                         }
                         build_label();
                         on_change();
                         redraw(rect());
                         return;
                         break;
                 }
                 break;
             }
         case event::mouse_up:
             {
                 mouse_event::ptr me = boost::shared_static_cast<mouse_event>(e);
                 if (region(me->x(), me->y()) == DOWN_ARROW)
                 {
                     value_ = value_-increment_;
                     if (value_ < min_) 
                     {
                         if (wrap_) value_ = max_;
                         else value_ = min_;
                     }
                 }
                 else
                 {
                     value_ = value_+increment_;
                     if (value_ > max_)
                     {	
                         if (wrap_) value_ = min_;
                         else value_ = max_;
                     }
                 }
                 build_label();
                 on_change();
                 redraw(rect());
                 return;
             }
     }
     widget::handle_event(e);
 }
Example #11
0
 // event_handler interface
 void application::handle_event(event::ptr e)
 {
     //INFO("application::handle_event()");
     switch(e->type())
     {
         case event::key_down:
             {
                 // FIXME :Carter: shouldnt this be a polymorphic cast?
                 key_event::ptr ke = boost::shared_static_cast<key_event>(e);
                 switch (ke->fn_key())
                 {
                     case key_escape:
                         quit();
                         break;
                     case key_tab:
                     case key_rightarrow:
                     case key_downarrow:
                         {
                             INFO("next pressed");
                             component::weak_ptr prev_focused_widget = focused_widget_;
                             focused_widget_ = focused_widget_.lock()->focus_next();
                             component::weak_ptr temp_widget = prev_focused_widget;
                             while (!focused_widget_.lock())
                             {
                                 INFO("no more focusable widgets, asking parent");
                                 temp_widget = temp_widget.lock()->parent();
                                 if (!temp_widget.lock())
                                     throw error_message_exception("application::handle_event() - "
                                             "unable to find next focusable widget");
                                 focused_widget_ = temp_widget.lock()->focus_next();
                             }
                             prev_focused_widget.lock()->handle_event(event::create(event::un_focus));
                             focused_widget_.lock()->handle_event(event::create(event::focus));
                             break;
                         }
                     case key_enter:
                         INFO("enter pressed");
                         break;
                     case key_leftarrow:
                     case key_uparrow:
                         {
                             INFO("prev pressed");
                             component::weak_ptr prev_focused_widget = focused_widget_;
                             focused_widget_ = focused_widget_.lock()->focus_prev();
                             component::weak_ptr temp_widget = prev_focused_widget;
                             while (!focused_widget_.lock())
                             {
                                 temp_widget = temp_widget.lock()->parent();
                                 if (!temp_widget.lock())
                                     throw error_message_exception("application::handle_event() - "
                                             "unable to find previous focusable widget");
                                 focused_widget_ = temp_widget.lock()->focus_prev();
                             }
                             prev_focused_widget.lock()->handle_event(event::create(event::un_focus));
                             focused_widget_.lock()->handle_event(event::create(event::focus));
                             break;
                         }
                     default:
                         // unhandled key
                         break;
                 }
                 break;
             }
         case event::key_up:
             break;
         case event::mouse_down:
             break;
         case event::mouse_up:
             break;
         case event::mouse_motion:
             break;
         case event::quit:
             quit();
             break;
         default:
             break;
             //INFO("application::handle_event - unknown event");
     }
 }
Example #12
0
PCEventHandler::RTSignalResult
PCEventHandler::handleRTSignal(EventSignal::const_ptr ev, PCProcess *evProc) const {
    // Check whether the signal was sent from the RT library by checking variables
    // in the library -- if we cannot be determine whether this signal came from
    // the RT library, assume it did not.
    
    if( evProc->runtime_lib.size() == 0 ) return NotRTSignal;

    Address sync_event_breakpoint_addr = evProc->getRTEventBreakpointAddr();
    Address sync_event_id_addr = evProc->getRTEventIdAddr();
    Address sync_event_arg1_addr = evProc->getRTEventArg1Addr();

    int breakpoint = 0;
    int status = 0;
    Address arg1 = 0;
    int zero = 0;

    // Check that all addresses could be determined
    if(    sync_event_breakpoint_addr == 0 
        || sync_event_id_addr == 0 
        || sync_event_arg1_addr == 0 ) 
    {
        return NotRTSignal;
    }

    // First, check breakpoint...
    if( !evProc->readDataWord((const void *)sync_event_breakpoint_addr,
                sizeof(int), &breakpoint, false) ) return NotRTSignal;

    switch(breakpoint) {
        case NoRTBreakpoint:
            proccontrol_printf("%s[%d]: signal is not RT library signal\n",
                    FILE__, __LINE__);
            return NotRTSignal;
        case NormalRTBreakpoint:
        case SoftRTBreakpoint:
            // More work to do
            break;
        default:
            proccontrol_printf("%s[%d]: invalid value for RT library breakpoint variable\n",
                    FILE__, __LINE__);
            return NotRTSignal;
    }

    // Make sure we don't get this event twice....
    if( !evProc->writeDataWord((void *)sync_event_breakpoint_addr, sizeof(int), &zero) ) {
        proccontrol_printf("%s[%d]: failed to reset RT library breakpoint variable\n",
                FILE__, __LINE__);
        return NotRTSignal;
    }

    // Get the type of the event
    if( !evProc->readDataWord((const void *)sync_event_id_addr, sizeof(int),
                &status, false) ) return NotRTSignal;

    if( status == DSE_undefined ) {
        proccontrol_printf("%s[%d]: signal is not RT library signal\n", FILE__, __LINE__);
        return NotRTSignal;
    }

    // get runtime library arg1 address
    if( !evProc->readDataWord((const void *)sync_event_arg1_addr,
                evProc->getAddressWidth(), &arg1, false) ) {
        proccontrol_printf("%s[%d]: failed to read RT library arg1 variable\n",
                FILE__, __LINE__);
        return NotRTSignal;
    }

    if( !isValidRTSignal(ev->getSignal(), (RTBreakpointVal) breakpoint, arg1, status) ) return NotRTSignal;

    BPatch_process *bproc = BPatch::bpatch->getProcessByPid(evProc->getPid());
    if( bproc == NULL ) {
        proccontrol_printf("%s[%d]: no corresponding BPatch_process for process %d\n",
                FILE__, __LINE__, evProc->getPid());
        return ErrorInDecoding;
    }

    // See pcEventHandler.h (SYSCALL HANDLING) for a description of what
    // is going on here

    Event::ptr newEvt;

    switch(status) {
    case DSE_forkEntry:
        proccontrol_printf("%s[%d]: decoded forkEntry, arg = %lx\n",
                      FILE__, __LINE__, arg1);
		if (PCEventMuxer::useBreakpoint(EventType(EventType::Pre, EventType::Fork)))
		{
                proccontrol_printf("%s[%d]: reporting fork entry event to BPatch layer\n",
                        FILE__, __LINE__);
                BPatch::bpatch->registerForkingProcess(evProc->getPid(), NULL);
              
        }
        break;
    case DSE_forkExit:
        proccontrol_printf("%s[%d]: decoded forkExit, arg = %lx\n",
                      FILE__, __LINE__, arg1);
		if (PCEventMuxer::useBreakpoint(EventType(EventType::Post, EventType::Fork))) {
                proccontrol_printf("%s[%d]: reporting fork exit event to ProcControlAPI\n",
                        FILE__, __LINE__);
                newEvt = Event::ptr(new EventFork(EventType::Pre, (Dyninst::PID)arg1));
        }
        break;
    case DSE_execEntry:
        proccontrol_printf("%s[%d]: decoded execEntry, arg = %lx\n",
                      FILE__, __LINE__, arg1);
        // For now, just note that the process is going to exec
        evProc->setExecing(true);
        break;
    case DSE_execExit:
        proccontrol_printf("%s[%d]: decoded execExit, arg = %lx\n",
                      FILE__, __LINE__, arg1);
        // This is not currently used by Dyninst internals for anything
        // We rely on ProcControlAPI for this and it should be impossible
        // to get this via a breakpoint
        return ErrorInDecoding;
    case DSE_exitEntry:
        proccontrol_printf("%s[%d]: decoded exitEntry, arg = %lx\n",
                      FILE__, __LINE__, arg1);
        /* Entry of exit, used for the callback. We need to trap before
           the process has actually exited as the callback may want to
           read from the process */
		if (PCEventMuxer::useBreakpoint(EventType(EventType::Pre, EventType::Exit))) {
			if (PCEventMuxer::useCallback(EventType(EventType::Pre, EventType::Exit))) {
                proccontrol_printf("%s[%d]: reporting exit entry event to ProcControlAPI\n",
                        FILE__, __LINE__);
                newEvt = Event::ptr(new EventExit(EventType::Pre, (int)arg1));
			}
			else {
                proccontrol_printf("%s[%d]: reporting exit entry event to BPatch layer\n",
                        FILE__, __LINE__);
                evProc->triggerNormalExit((int)arg1);
			}
        }
        break;
    case DSE_loadLibrary:
        proccontrol_printf("%s[%d]: decoded loadLibrary (error), arg = %lx\n",
                      FILE__, __LINE__, arg1);
        // This is no longer used
        return ErrorInDecoding;
    case DSE_lwpExit:
        proccontrol_printf("%s[%d]: decoded lwpExit (error), arg = %lx\n",
                      FILE__, __LINE__, arg1);
        // This is not currently used on any platform
        return ErrorInDecoding;
    case DSE_snippetBreakpoint:
        proccontrol_printf("%s[%d]: decoded snippetBreak, arg = %lx\n",
                      FILE__, __LINE__, arg1);
        bproc->setLastSignal(ev->getSignal());
        evProc->setDesiredProcessState(PCProcess::ps_stopped);
        break;
    case DSE_stopThread:
        proccontrol_printf("%s[%d]: decoded stopThread, arg = %lx\n",
                      FILE__, __LINE__, arg1);
        bproc->setLastSignal(ev->getSignal());
        if( !handleStopThread(evProc, arg1) ) {
            proccontrol_printf("%s[%d]: failed to handle stopped thread event\n",
                    FILE__, __LINE__);
            return ErrorInDecoding;
        }
        break;
    case DSE_dynFuncCall:
        proccontrol_printf("%s[%d]: decoded dynamic callsite event, arg = %lx\n",
                FILE__, __LINE__, arg1);
        if( !handleDynFuncCall(evProc, bproc, arg1) ) {
            proccontrol_printf("%s[%d]: failed to handle dynamic callsite event\n",
                    FILE__, __LINE__);
            return ErrorInDecoding;
        }
        break;
    case DSE_userMessage:
        proccontrol_printf("%s[%d]: decoded user message event, arg = %lx\n",
                FILE__, __LINE__, arg1);
        if( !handleUserMessage(evProc, bproc, arg1) ) {
            proccontrol_printf("%s[%d]: failed to handle user message event\n",
                    FILE__, __LINE__);
            return ErrorInDecoding;
        }
        break;
    default:
        return NotRTSignal;
    }

    // Behavior common to all syscalls
    if( newEvt != NULL ) {
        // Report the event to ProcControlAPI, make sure process remains stopped
        evProc->setReportingEvent(true);

        newEvt->setProcess(ev->getProcess());
        newEvt->setThread(ev->getThread());

        // In the callback thread, the process and thread are stopped
        newEvt->setSyncType(Event::sync_process);
        newEvt->setUserEvent(true);

        ProcControlAPI::mbox()->enqueue(newEvt);
    }

    return IsRTSignal;
}
Example #13
0
Handler::handler_ret_t iRPCLaunchHandler::handleEvent(Event::ptr ev)
{
   int_process *proc = ev->getProcess()->llproc();
   int_thread *thr = ev->getThread()->llthrd();

   int_iRPC::ptr posted_rpc = thr->nextPostedIRPC();
   if (!posted_rpc || thr->runningRPC())
      return Handler::ret_success;

   assert(posted_rpc->getState() != int_iRPC::Posted);

   pthrd_printf("Handling next posted irpc %lu on %d/%d of type %s in state %s\n",
                posted_rpc->id(), proc->getPid(), thr->getLWP(),
                posted_rpc->getStrType(), posted_rpc->getStrState());

   /**
    * Check if we've successfully made it to the stopped state.
    *  (There's no longer any work to be done to move from prepping to prepped--
    *  it all happens in the procstop logic.)
    **/
   if (posted_rpc->getState() == int_iRPC::Prepping) {
      pthrd_printf("Marking RPC %lu on %d/%d as prepped\n", posted_rpc->id(), proc->getPid(), thr->getLWP());
      assert(posted_rpc->isRPCPrepped());
      posted_rpc->setState(int_iRPC::Prepped);
   }

   std::set<response::ptr> async_resps;
   /**
    * Save registers and memory
    **/
   if (posted_rpc->getState() == int_iRPC::Prepped) {
      pthrd_printf("Saving RPC state on %d/%d\n", proc->getPid(), thr->getLWP());
      bool result = posted_rpc->saveRPCState();
      if (!result) {
         pthrd_printf("Failed to save RPC state on %d/%d\n", proc->getPid(), thr->getLWP());
         return Handler::ret_error;
      }
   }

   //Wait for async
   if (posted_rpc->getState() == int_iRPC::Saving) {
      if (!posted_rpc->checkRPCFinishedSave()) {
         pthrd_printf("Async, RPC has not finished save\n");
         posted_rpc->getPendingResponses(async_resps);
         proc->handlerPool()->notifyOfPendingAsyncs(async_resps, ev);
         return Handler::ret_async;
      }
      else {
         posted_rpc->setState(int_iRPC::Saved);
      }
   }

   /**
    * Write PC register and memory
    **/
   if (posted_rpc->getState() == int_iRPC::Saved) {
      pthrd_printf("Writing RPC on %d\n", proc->getPid());
      bool result = posted_rpc->writeToProc();
      if (!result) {
         pthrd_printf("Failed to write RPC on %d\n", proc->getPid());
         return Handler::ret_error;
      }
   }
   //Wait for async
   if (posted_rpc->getState() == int_iRPC::Writing) {
      if (!posted_rpc->checkRPCFinishedWrite()) {
         pthrd_printf("Async, RPC has not finished memory write\n");
         posted_rpc->getPendingResponses(async_resps);
         proc->handlerPool()->notifyOfPendingAsyncs(async_resps, ev);
         return Handler::ret_async;
      }
      else {
         posted_rpc->setState(int_iRPC::Ready);
      }
   }

   if (posted_rpc->getState() == int_iRPC::Ready) {
      posted_rpc->runIRPC();
   }

   return Handler::ret_success;
}
Example #14
0
Handler::handler_ret_t iRPCHandler::handleEvent(Event::ptr ev)
{
   //An RPC has completed, clean-up
   int_thread *thr = ev->getThread()->llthrd();
   int_process *proc = ev->getProcess()->llproc();
   EventRPC *event = static_cast<EventRPC *>(ev.get());
   int_eventRPC *ievent = event->getInternal();
   int_iRPC::ptr rpc = event->getllRPC()->rpc;
   iRPCMgr *mgr = rpcMgr();
   bool isLastRPC = !thr->hasPostedRPCs();
   assert(rpc);
   assert(mgr);
   assert(rpc->getState() == int_iRPC::Cleaning);
   // Is this a temporary thread created just for this RPC?
   bool ephemeral = thr->isRPCEphemeral();

   pthrd_printf("Handling RPC %lu completion on %d/%d\n", rpc->id(),
                proc->getPid(), thr->getLWP());

   if ((rpc->getType() == int_iRPC::InfMalloc || rpc->getType() == int_iRPC::Allocation) &&
       !ievent->alloc_regresult)
   {
      //Post a request for the return value of the allocation
      pthrd_printf("Cleaning up allocation RPC\n");
      ievent->alloc_regresult = reg_response::createRegResponse();
      bool result = proc->plat_collectAllocationResult(thr, ievent->alloc_regresult);
      if( (long)ievent->alloc_regresult->getResult() < 0){
            perr_printf("System call returned value is negative.\n");
            assert(0);
      }
      assert(result);
      if(!result) return ret_error;

      proc->handlerPool()->notifyOfPendingAsyncs(ievent->alloc_regresult, ev);
   }

   if (rpc->shouldSaveData() && !ievent->memrestore_response) {
      //Post a request to restore the memory used by the RPC
      pthrd_printf("Restoring memory to %lx from %p of size %lu\n",
                   rpc->addr(), rpc->allocation()->orig_data, rpc->allocSize());
      assert(rpc->allocation()->orig_data);
      ievent->memrestore_response = result_response::createResultResponse();
      bool result = proc->writeMem(rpc->allocation()->orig_data,
                                            rpc->addr(),
                                            rpc->allocSize(),
                                            ievent->memrestore_response);
      assert(result);
      if(!result) return ret_error;
   }
   if (rpc->directFree()) {
	   assert(rpc->addr());
	   thr->llproc()->direct_infFree(rpc->addr());
   }
   if (ephemeral) {
      // Don't restore registers; instead, kill the thread if there
      // aren't any other pending iRPCs for it.
      // We count as an active iRPC...
      assert(mgr->numActiveRPCs(thr) > 0);
      if (mgr->numActiveRPCs(thr) == 1) {
         pthrd_printf("Terminating RPC thread %d\n",
                      thr->getLWP());
         thr->terminate();
         // CLEANUP on aisle 1
#if defined(os_windows)
         windows_process *winproc = dynamic_cast<windows_process *>(thr->llproc());
         if (winproc) {
            pthrd_printf("Destroying RPC thread %d\n",
                         thr->getLWP());
            winproc->destroyRPCThread();
         }
#endif
      } else {
         pthrd_printf("RPC thread %d has %d active RPCs, parking thread\n",
                      thr->getLWP(), mgr->numActiveRPCs(thr));
         // don't do an extra desync here, it's handled by throwEventsBeforeContinue()
      }
   }
   else if (!ievent->regrestore_response &&
            (!ievent->alloc_regresult || ievent->alloc_regresult->isReady()))
   {
      //Restore the registers--need to wait for above getreg first
      ievent->regrestore_response = result_response::createResultResponse();
      pthrd_printf("Restoring all registers\n");
      bool result = thr->restoreRegsForRPC(isLastRPC, ievent->regrestore_response);
      assert(result);
      if(!result) return ret_error;
   }

   set<response::ptr> async_pending;
   ievent->getPendingAsyncs(async_pending);
   if (!async_pending.empty()) {
      proc->handlerPool()->notifyOfPendingAsyncs(async_pending, ev);
      return ret_async;
   }

   if (ievent->alloc_regresult) {
      //Collect and use the return value of the allocation
      assert(ievent->alloc_regresult->isReady());

      Address addr = ievent->alloc_regresult->getResult();
      pthrd_printf("Allocation RPC %lu returned memory at %lx\n", rpc->id(), addr);
      if (rpc->getType() == int_iRPC::Allocation) {
         rpc->targetAllocation()->addr = addr;
      }
      else if (rpc->getType() == int_iRPC::InfMalloc) {
         rpc->setMallocResult(addr);
      }
   }

   if (rpc->isProcStopRPC()) {
      pthrd_printf("Restoring RPC state after procstop completion\n");
      thr->getIRPCWaitState().restoreStateProc();
      thr->getIRPCState().restoreState();
   }

   if (rpc->isMemManagementRPC() || rpc->isInternalRPC())
   {
      //Free memory associated with RPC for future use
      pthrd_printf("Freeing exec memory at %lx\n", rpc->addr());
      proc->freeExecMemory(rpc->addr());
   }


   pthrd_printf("RPC %lu is moving to state finished\n", rpc->id());
   thr->clearRunningRPC();
   rpc->setState(int_iRPC::Finished);

   if (rpc->countedSync()) {
     thr->decSyncRPCCount();
   }

   if (rpc->needsToRestoreInternal()) {
      rpc->thread()->getInternalState().restoreState();
   }
   if(mgr->numActiveRPCs(thr) == 0) {
      if (rpc->thread()->getUserRPCState().isDesynced())
         rpc->thread()->getUserRPCState().restoreState();
   } else {
	   thr->throwEventsBeforeContinue();
   }

   return ret_success;
}
Example #15
0
bool DecoderWindows::decode(ArchEvent *ae, std::vector<Event::ptr> &events)
{
	static Address ntdll_ignore_breakpoint_address = 0;

	assert(ae);
	ArchEventWindows* winEvt = static_cast<ArchEventWindows*>(ae);
	assert(winEvt);
	Event::ptr newEvt = Event::ptr();
	int_thread *thread = ProcPool()->findThread((Dyninst::LWP)(winEvt->evt.dwThreadId));
	int_process* proc = ProcPool()->findProcByPid(winEvt->evt.dwProcessId);
	if(!proc) { return false; }
	windows_process* windows_proc = dynamic_cast<windows_process*>(proc);
	if(!windows_proc)
	{
		perr_printf("DecoderWindows::decode() called on nonexistent/deleted process %d/%d\n", 
			winEvt->evt.dwProcessId, winEvt->evt.dwThreadId);
		return false;
	}
	//windows_proc->clearPendingDebugBreak();

	DEBUG_EVENT e = winEvt->evt;

	switch(e.dwDebugEventCode)
	{
	case CREATE_PROCESS_DEBUG_EVENT:
	case CREATE_THREAD_DEBUG_EVENT:
		pthrd_printf("decodeProcess/decodeThreadEvent\n");
		return decodeCreateThread(e, newEvt, proc, events);
	case EXCEPTION_DEBUG_EVENT:
		pthrd_printf("decodeException\n");
		switch(e.u.Exception.ExceptionRecord.ExceptionCode)
		{
		case EXCEPTION_SINGLE_STEP:
			pthrd_printf("Decoding singleStep event on PID %d, TID %d\n", e.dwProcessId, e.dwThreadId);
			newEvt = decodeSingleStepEvent(e, proc, thread);
			break;
			//fprintf(stderr, "Decoded Single-step event at 0x%lx, PID: %d, TID: %d\n", e.u.Exception.ExceptionRecord.ExceptionAddress, e.dwProcessId, e.dwThreadId);
		case EXCEPTION_BREAKPOINT:
			// Case 1: breakpoint is real breakpoint
			pthrd_printf("Caught breakpoint for pid %d, tid %d, PC 0x%lx\n", e.dwProcessId, e.dwThreadId, e.u.Exception.ExceptionRecord.ExceptionAddress);
			newEvt = decodeBreakpointEvent(e, proc, thread);
			if(newEvt)
			{
				pthrd_printf("Decoded Breakpoint event at 0x%lx, PID: %d, TID: %d\n", e.u.Exception.ExceptionRecord.ExceptionAddress, e.dwProcessId, e.dwThreadId);
				//fprintf(stderr, "Decoded Breakpoint event at 0x%lx, PID: %d, TID: %d\n", e.u.Exception.ExceptionRecord.ExceptionAddress, e.dwProcessId, e.dwThreadId);
				break;
			}
			else
			{
				if(proc->getState() != int_process::neonatal &&
					proc->getState() != int_process::neonatal_intermediate)
				{
					bool didSomething = false;

				   if (windows_proc->pendingDebugBreak())
					{
						pthrd_printf("Decoded Stop event, PID: %d, TID: %d\n", e.dwProcessId, e.dwThreadId);
						//newEvt = Event::ptr(new EventStop());
						windows_proc->setStopThread(e.dwThreadId);
						return true;
					}
					else
					{
						pthrd_printf("Decoded unhandled exception (breakpoint) event, PID: %d, TID: %d\n", e.dwProcessId, e.dwThreadId);
						// Case 3: breakpoint that's not from us, while running. Pass on exception.
						GeneratorWindows* winGen = static_cast<GeneratorWindows*>(GeneratorWindows::getDefaultGenerator());
						newEvt = EventSignal::ptr(new EventSignal(e.u.Exception.ExceptionRecord.ExceptionCode));
					}
				}
				else
				{
					// Case 4: breakpoint in ntdll.dll due to startup. This should be skipped and we should bootstrap.
					pthrd_printf("Breakpoint due to startup, ignoring\n");
					newEvt = Event::ptr(new EventBootstrap());
					ntdll_ignore_breakpoint_address = (Address) e.u.Exception.ExceptionRecord.ExceptionAddress;
					if(!thread) {
						pthrd_printf("DEBUG: Missing thread on startup breakpoint\n");
					}
				}
			}
			break;
		case EXCEPTION_ILLEGAL_INSTRUCTION:
			{
				pthrd_printf("SIGILL in mutatee\n");
				GeneratorWindows* winGen = static_cast<GeneratorWindows*>(GeneratorWindows::getDefaultGenerator());
				winGen->markUnhandledException(e.dwProcessId);
				newEvt = EventSignal::ptr(new EventSignal(e.u.Exception.ExceptionRecord.ExceptionCode));
				assert(0);
			}
			break;
		case EXCEPTION_ACCESS_VIOLATION:
			{
                // check if this is first chance or second chance:
                if (e.u.Exception.dwFirstChance != 0) {
                    int sig = e.u.Exception.ExceptionRecord.ExceptionCode;
                    int cause = e.u.Exception.ExceptionRecord.ExceptionInformation[0];
                    Address addr = e.u.Exception.ExceptionRecord.ExceptionInformation[1];
                    EventSignal* evSig = nullptr;
                    switch (cause) {
                    case 0: evSig = new EventSignal(sig, addr, EventSignal::ReadViolation, true); break;
                    case 1: evSig = new EventSignal(sig, addr, EventSignal::WriteViolation, true); break;
                    case 8: evSig = new EventSignal(sig, addr, EventSignal::ExecuteViolation, true); break;
                    default: evSig = new EventSignal(sig, addr, EventSignal::Unknown, true); break;
                    }
                    newEvt = EventSignal::ptr(evSig);
                } else {
                    pthrd_printf("segfault in mutatee, thread %d/%d\n", e.dwProcessId, e.dwThreadId);
				    unsigned problemArea = (unsigned int)(e.u.Exception.ExceptionRecord.ExceptionAddress);
				    cerr << "SEGFAULT @ " << hex << problemArea << dec << endl;
				    dumpSurroundingMemory(problemArea, proc);
				    GeneratorWindows* winGen = static_cast<GeneratorWindows*>(GeneratorWindows::getDefaultGenerator());
				    winGen->markUnhandledException(e.dwProcessId);
				    newEvt = EventSignal::ptr(new EventSignal(e.u.Exception.ExceptionRecord.ExceptionCode));
				    cerr << "Signal is " << e.u.Exception.ExceptionRecord.ExceptionCode << endl;
                }
			}
			break;
			// Thread naming exception. Ignore.
		case EXCEPTION_DEBUGGER_IO: {
			pthrd_printf("Debugger I/O exception: %lx\n", e.u.Exception.ExceptionRecord.ExceptionInformation[0]);
			newEvt = EventNop::ptr(new EventNop());
			newEvt->setSyncType(Event::async);
			break;
		}
		default:
			{
				pthrd_printf("Decoded unhandled exception event, PID: %d, TID: %d, Exception code = 0x%lx, Exception addr = 0x%lx\n", e.dwProcessId, e.dwThreadId,
					e.u.Exception.ExceptionRecord.ExceptionCode, e.u.Exception.ExceptionRecord.ExceptionAddress);
				GeneratorWindows* winGen = static_cast<GeneratorWindows*>(GeneratorWindows::getDefaultGenerator());
				winGen->markUnhandledException(e.dwProcessId);
				newEvt = EventSignal::ptr(new EventSignal(e.u.Exception.ExceptionRecord.ExceptionCode));
			}
			break;
		}
		break;
	case EXIT_PROCESS_DEBUG_EVENT:
		{
			pthrd_printf("Decoded ProcessExit event, PID: %d, TID: %d\n", e.dwProcessId, e.dwThreadId);
			if(proc->wasForcedTerminated()) {
				newEvt = EventForceTerminate::ptr(new EventForceTerminate(e.u.ExitProcess.dwExitCode));
			}
			else {
				newEvt = EventExit::ptr(new EventExit(EventType::Pre, e.u.ExitProcess.dwExitCode));
			}
//			GeneratorWindows* winGen = static_cast<GeneratorWindows*>(GeneratorWindows::getDefaultGenerator());
//			winGen->removeProcess(proc);
			newEvt->setSyncType(Event::sync_process);
			newEvt->setProcess(proc->proc());
			// Since we're doing thread exit/proc exit, and this means the thread will go away first,
			// we don't set the thread here
			if(thread)
				newEvt->setThread(thread->thread());
			// We do this here because the generator thread will exit before updateSyncState otherwise
//			int_threadPool::iterator i = proc->threadPool()->begin();
//			for (; i != proc->threadPool()->end(); i++) {
//				(*i)->getGeneratorState().setState(int_thread::exited);
//		 		(*i)->setExitingInGenerator(true);
//			}
			events.push_back(newEvt);

			return true;
		}
		break;
	case EXIT_THREAD_DEBUG_EVENT:
		pthrd_printf("Decoded ThreadExit event, PID: %d, TID: %d\n", e.dwProcessId, e.dwThreadId);
		if(thread) {
			thread->getGeneratorState().setState(int_thread::exited);
			thread->setExitingInGenerator(true);
			if (e.dwThreadId == windows_proc->getStopThread()) {
				newEvt = EventWinStopThreadDestroy::ptr(new EventWinStopThreadDestroy(EventType::Pre));
				windows_proc->clearStopThread();
			}
			else {
				newEvt = EventLWPDestroy::ptr(new EventLWPDestroy(EventType::Pre));
			}
		} else {
			// If the thread is NULL, we can't give the user an event with a valid thread object anymore.
			// So fail the decode.
			return false;
		}
		break;
	case LOAD_DLL_DEBUG_EVENT:
		pthrd_printf("Decoded LoadDLL event, PID: %d, TID: %d\n", e.dwProcessId, e.dwThreadId);
		newEvt = decodeLibraryEvent(e, proc);
		break;
	case UNLOAD_DLL_DEBUG_EVENT:
		pthrd_printf("Decoded UnloadDLL event, PID: %d, TID: %d\n", e.dwProcessId, e.dwThreadId);
		newEvt = decodeLibraryEvent(e, proc);
		break;
	case OUTPUT_DEBUG_STRING_EVENT:
		{
			TCHAR buf[1024];
			unsigned long bytes_read = 0;
			windows_process* winProc = dynamic_cast<windows_process*>(proc);
			BOOL result = ::ReadProcessMemory(winProc->plat_getHandle(), e.u.DebugString.lpDebugStringData, buf, 
				e.u.DebugString.nDebugStringLength, &bytes_read);
			if(result) {
				pthrd_printf("Decoded DebugString event, string: %s\n", buf);
			} else {
				pthrd_printf("Decoded DebugString event, but string was not readable!\n");
			}

			break;
		}
	case RIP_EVENT:
		pthrd_printf("Decoded RIP event, PID: %d, TID: %d, error = 0x%lx\n", e.dwProcessId, e.dwThreadId,
			e.u.RipInfo.dwError);
		newEvt = EventCrash::ptr(new EventCrash(e.u.RipInfo.dwError));
		assert(0);
		break;
	default:
		assert(!"invalid event type");
		return false;
	}
	if(newEvt)
	{
		assert(proc);
		if(newEvt->getSyncType() == Event::unset)
			newEvt->setSyncType(Event::sync_process);
		if(thread) {
			newEvt->setThread(thread->thread());
		}
		newEvt->setProcess(proc->proc());
		events.push_back(newEvt);
	}
	return true;
}