예제 #1
0
파일: irpc.C 프로젝트: chubbymaggie/dyninst
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;
}
예제 #2
0
파일: irpc.C 프로젝트: chubbymaggie/dyninst
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;
}
예제 #3
0
파일: irpc.C 프로젝트: chubbymaggie/dyninst
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;
}