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; }
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; }
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; }
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); }
void ScreenMaster::onEvent(const Event::ptr& event){ switch(event->getEventType()){ case GAME_START: gameScreen(); break; } }
/// 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); }
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; } } }
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; }
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); }
// 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"); } }
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; }
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; }
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; }
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; }