Process::cb_ret_t Backend::handleTimeEvent() { // Get all subscribed events set<Event*>& events = Time::getTimeSubscribers(); set<Event*>::iterator eventIter = events.begin(); for(;eventIter != events.end(); eventIter++) { Event* event = *eventIter; ProcessSet::ptr procset = ((Time *)event)->getProcset(); ProcessSet::iterator procIter = procset->begin(); if(procset->size() == 0) continue; if(!event || !event->isEnabled(*procIter)) continue; // this is to avoid a race condition where a time event occurs in the middle of iterating through the processes DYSECTVERBOSE(true, "Time event with timeout %d detected on %d processes", ((Time *)event)->getTimeout(), procset->size()); for(;procIter != procset->end(); procIter++) { Process::ptr procPtr = *procIter; if(event && event->isEnabled(procPtr)) { Thread::ptr threadPtr = procPtr->threads().getInitialThread(); Walker *proc = (Walker *)procPtr->getData(); handleEvent(procPtr, threadPtr, event); } } if(event->getOwner()->getLifeSpan() == fireOnce) event->disable(); } return Process::cbDefault; }
MachSyscall makeFromID(Process::ptr proc, MachSyscall::SyscallIDIndependent id) { Architecture arch = proc->getArchitecture(); OSType os = proc->getOS(); Platform plat(arch,os); return MachSyscall::makeFromPlatform(plat, id); }
bool PCLibraryState::getAOut(LibAddrPair &ao) { Process::ptr proc = pdebug->getProc(); CHECK_PROC_LIVE; Library::ptr lib = proc->libraries().getExecutable(); if (!lib) { sw_printf("[%s:%u] - Could not get executable\n", FILE__, __LINE__); return false; } ao = LibAddrPair(lib->getName(), lib->getLoadAddress()); return true; }
bool PCLibraryState::updateLibraries() { Process::ptr proc = pdebug->getProc(); CHECK_PROC_LIVE; LibraryPool::iterator i; for (i = proc->libraries().begin(); i != proc->libraries().end(); i++) { checkForNewLib(*i); } return true; }
bool StackCallback::beginStackWalk(Thread::ptr thr) { assert(!cur); Process::ptr proc = thr->getProcess(); ProcessState *pstate = ProcessState::getProcessStateByPid(proc->getPid()); if (!pstate) { sw_printf("[%s:%u] - Error, unknown process state for %d while starting stackwalk\n", FILE__, __LINE__, proc->getPid()); return false; } cur_walker = pstate->getWalker(); cur = tree.getHead(); return true; }
bool PCLibraryState::findInCache(Process::ptr proc, Address addr, LibAddrPair &lib) { cache_t tmp; if (!loadedLibs.find(addr, tmp)) { return false; } Library::ptr lib_ptr = tmp.second; if (proc->libraries().find(lib_ptr) != proc->libraries().end()) { lib = tmp.first; return true; } removeLibFromCache(tmp); return false; }
bool Location::disable(ProcessSet::ptr lprocset) { assert(owner != 0); if(codeLocations.empty()) { return Err::verbose(true, "No code locations"); } if(!lprocset) { return Err::warn(false, "Process set not present"); } ProcessSet::iterator procIter = lprocset->begin(); for(;procIter != lprocset->end(); procIter++) { Process::ptr procPtr = *procIter; Walker* proc = (Walker*)procPtr->getData(); vector<DysectAPI::CodeLocation*>::iterator locationIter = codeLocations.begin(); for(;locationIter != codeLocations.end(); locationIter++) { DysectAPI::CodeLocation* location = *locationIter; if(!location->addProcLib(proc)) { return Err::warn(false, "Symbol not found in process"); } vector<Dyninst::Address> addrs; if(!location->getAddrs(proc, addrs) || addrs.empty()) { return Err::warn(false, "Addresses for symbol could not be determined"); } // Breakpoint locations at hand for(int i = 0; i < addrs.size() ; i++) { Dyninst::Address addr = addrs[i]; if(!procPtr->rmBreakpoint(addr, bp)) { Err::verbose(false, "Breakpoint not removed! %s", ProcControlAPI::getLastErrorMsg()); } } } } return true; }
ProcessSet::ptr ProcessMgr::filterExited(ProcessSet::ptr inSet) { if(!inSet) return inSet; if(inSet->empty()) return inSet; ProcessSet::ptr procs = ProcessSet::newProcessSet(); // Filter out exited processes ProcessSet::iterator procIter = inSet->begin(); for(; procIter != inSet->end(); procIter++) { Process::ptr process = *procIter; if(process->isTerminated() || process->isExited() || process->isCrashed() || process->isDetached()) { continue; } procs->insert(process); } return procs; }
bool PCLibraryState::getLibraries(std::vector<LibAddrPair> &libs, bool allow_refresh) { Process::ptr proc = pdebug->getProc(); CHECK_PROC_LIVE; LibraryPool::iterator i; for (i = proc->libraries().begin(); i != proc->libraries().end(); i++) { if (allow_refresh) checkForNewLib(*i); libs.push_back(LibAddrPair((*i)->getName(), (*i)->getLoadAddress())); } vector<pair<LibAddrPair, unsigned int> > arch_libs; vector<pair<LibAddrPair, unsigned int> >::iterator j; updateLibsArch(arch_libs); for (j = arch_libs.begin(); j != arch_libs.end(); j++) { libs.push_back(j->first); } return true; }
bool Location::enable(ProcessSet::ptr lprocset) { assert(owner != 0); if(codeLocations.empty()) { return Err::verbose(true, "No code locations"); } if(!lprocset) { return Err::warn(false, "Process set not present"); } ProcessSet::iterator procIter = lprocset->begin(); AddressSet::ptr addrset = AddressSet::newAddressSet(); if(lprocset->size() <= 0) { return Err::info(true, "Process set empty!"); } // Find library location for target processes for(;procIter != lprocset->end(); procIter++) { Process::ptr procPtr = *procIter; Walker* proc = (Walker*)procPtr->getData(); vector<DysectAPI::CodeLocation*>::iterator locationIter = codeLocations.begin(); for(;locationIter != codeLocations.end(); locationIter++) { DysectAPI::CodeLocation* location = *locationIter; if(!location->addProcLib(proc)) { return Err::warn(false, "Symbol not found in process"); } vector<Dyninst::Address> addrs; if(!location->getAddrs(proc, addrs) || addrs.empty()) { return Err::warn(false, "Addresses for symbol could not be determined"); } // Breakpoint locations at hand for(int i = 0; i < addrs.size() ; i++) { Dyninst::Address addr = addrs[i]; if(!procPtr->addBreakpoint(addr, bp)) { return Err::verbose(false, "Breakpoint not installed: %s", ProcControlAPI::getLastErrorMsg()); } else { Err::verbose(true, "Breakpoint installed at %lx", addr); } //addrset->insert(addr, procPtr); } //if(addrs.empty()) { // Err::verbose(true, "No addresses"); //} } } //if(addrset->size() <= 0) { // return Err::verbose(true, "Empty address set"); //} //if(!lprocset->addBreakpoint(addrset, nbp)) { // return Err::warn(false, "Could not insert breakpoints!"); //} else { // Err::info(true, "%d breakpoints inserted in %d processes", addrset->size(), lprocset->size()); //} return true; }
ProcDebug::ProcDebug(Process::ptr p) : ProcessState(p->getPid()), proc(p) { }
bool PCLibraryState::memoryScan(Process::ptr proc, Address addr, LibAddrPair &lib) { LibraryPool::iterator i; Library::ptr nearest_predecessor = Library::ptr(); signed int pred_distance = 0; Library::ptr nearest_successor = Library::ptr(); signed int succ_distance = 0; /** * Search the entire library list for the dynamic sections that come * directly before and after our target address (nearest_predecessor * and nearest_successor). * * They dynamic linker (and who-knows-what on future systems) can have a * dynamic address of zero. Remember any library with a zero dynamic * address with zero_dynamic_libs, and manually check those if the * nearest_successor and nearest_predecessor. **/ std::vector<Library::ptr> zero_dynamic_libs; for (i = proc->libraries().begin(); i != proc->libraries().end(); i++) { Library::ptr slib = *i; checkForNewLib(slib); Address dyn_addr = slib->getDynamicAddress(); if (!dyn_addr) { zero_dynamic_libs.push_back(slib); continue; } signed int distance = addr - dyn_addr; if (distance == 0) { lib.first = slib->getName(); lib.second = slib->getLoadAddress(); sw_printf("[%s:%u] - Found library %s contains address %lx\n", FILE__, __LINE__, lib.first.c_str(), addr); return true; } else if (distance < 0) { if (!pred_distance || pred_distance < distance) { nearest_predecessor = slib; pred_distance = distance; } } else if (distance > 0) { if (!succ_distance || succ_distance > distance) { nearest_successor = slib; succ_distance = distance; } } } /** * Likely a static binary, set nearest_predecessor so that * the following check will test it. **/ if (!nearest_predecessor && !nearest_successor) { nearest_predecessor = proc->libraries().getExecutable(); } /** * Check if predessor contains our address first--this should be the typical case **/ if (nearest_predecessor && checkLibraryContains(addr, nearest_predecessor)) { lib.first = nearest_predecessor->getName(); lib.second = nearest_predecessor->getLoadAddress(); sw_printf("[%s:%u] - Found library %s contains address %lx\n", FILE__, __LINE__, lib.first.c_str(), addr); return true; } /** * Check successor **/ if (nearest_successor && checkLibraryContains(addr, nearest_successor)) { lib.first = nearest_successor->getName(); lib.second = nearest_successor->getLoadAddress(); sw_printf("[%s:%u] - Found library %s contains address %lx\n", FILE__, __LINE__, lib.first.c_str(), addr); return true; } /** * The address wasn't located by the dynamic section tests. Check * any libraries without dynamic pointers, plus the executable. **/ std::vector<Library::ptr>::iterator k = zero_dynamic_libs.begin(); for (; k != zero_dynamic_libs.end(); k++) { if (checkLibraryContains(addr, *k)) { lib.first = (*k)->getName(); lib.second = (*k)->getLoadAddress(); return true; } } if(checkLibraryContains(addr, proc->libraries().getExecutable())) { lib.first = proc->libraries().getExecutable()->getName(); lib.second = proc->libraries().getExecutable()->getLoadAddress(); sw_printf("[%s:%u] - Found executable %s contains address %lx\n", FILE__, __LINE__, lib.first.c_str(), addr); return true; } sw_printf("[%s:%u] - Could not find library for addr %lx\n", FILE__, __LINE__, addr); return false; }
DysectErrorCode Backend::irpc(Process::ptr process, string libraryPath, string funcName, void *arg, int argLength) { int funcAddrOffset = -1, argOffset = -1; bool result, found = false; unsigned char *begin, *end, *c, *buffer; unsigned long size, *valuePtr, *ptr, value; string libraryName; Symtab *symtab = NULL; Address loadAddress; Offset funcOffset; vector<SymtabAPI::Function *> functions; if (symtabs.find(libraryPath) == symtabs.end()) { result = Symtab::openFile(symtab, libraryPath.c_str()); if (result == false) { DYSECTWARN(false, "Failed to find file %s for symtab", libraryPath.c_str()); return Error; } } else { symtab = symtabs[libraryPath]; } libraryName = basename(libraryPath.c_str()); LibraryPool &libs = process->libraries(); LibraryPool::iterator libsIter; for (libsIter = libs.begin(); libsIter != libs.end(); libsIter++) { Library::ptr libraryPtr = *libsIter; if (libraryPtr->getName().find(libraryName) == string::npos) continue; loadAddress = (*libsIter)->getLoadAddress(); found = true; DYSECTLOG(true, "found library %s at 0x%lx", libraryName.c_str(), loadAddress); break; } if (found == false) { DYSECTWARN(false, "Failed to find library %s", libraryName.c_str()); return Error; } begin = call_snippet_begin; end = call_snippet_end; size = (unsigned long)*end - (unsigned long)*begin; for (c = begin; c != end; c++) { valuePtr = (unsigned long *)c; if (*valuePtr == 0x1122334455667788) { funcAddrOffset = (long)(c - begin); } if (*valuePtr == 0xaabbccddeeffaabb) { argOffset = (long)(c - begin); } } result = symtab->findFunctionsByName(functions, funcName); if (result == false || functions.size() < 1) { DYSECTWARN(false, "Failed to find %s function", funcName.c_str()); return Error; } funcOffset = functions[0]->getOffset(); DYSECTLOG(true, "found %s at offset 0x%lx", funcName.c_str(), funcOffset); buffer = (unsigned char *)malloc(size); if (!buffer) { DYSECTWARN(false, "Failed to allocate %d bytes for target %d", size); return Error; } memcpy(buffer, begin, size); c = buffer + funcAddrOffset; value = loadAddress + funcOffset; memcpy(c, &value, sizeof(unsigned long)); c = buffer + argOffset; memcpy(c, arg, argLength); IRPC::ptr irpc; irpc = IRPC::createIRPC((void *)buffer, size, false); if (!irpc) { DYSECTWARN(false, "Failed to create IRPC in target"); return Error; } result = process->postIRPC(irpc); if (!result) { DYSECTWARN(false, "Failed to post IRPC in target"); return Error; } DYSECTLOG(true, "irpc successful for target"); return OK; }
bool Probe::processRequests() { if(requestQueue.empty()) { return true; } pthread_mutex_lock(&requestQueueMutex); vector<ProbeRequest*> queue = requestQueue; requestQueue.clear(); pthread_mutex_unlock(&requestQueueMutex); ProcessSet::ptr continueSet = ProcessSet::newProcessSet(); // Sort queue deque<ProbeRequest*> sortedQueue; vector<ProbeRequest*>::iterator requestIter = queue.begin(); for(int i = 0; requestIter != queue.end(); requestIter++) { ProbeRequest* request = *requestIter; if(!request) { DYSECTWARN(true, "Invalid request in request queue"); break; } if(request->type == DisableType) { sortedQueue.push_back(request); } else { sortedQueue.push_front(request); } } if (sortedQueue.size() == 0) return true; DYSECTVERBOSE(true, "Handling %d process requests", sortedQueue.size()); deque<ProbeRequest*>::iterator sortedRequestIter = sortedQueue.begin(); for(int i = 0; sortedRequestIter != sortedQueue.end(); sortedRequestIter++) { ProbeRequest* request = *sortedRequestIter; if(!request) { DYSECTWARN(true, "Invalid request in request queue"); break; } DYSECTVERBOSE(true, "processRequests() %d", i++); Probe* probe = request->probe; if(!probe) { DYSECTWARN(false, "Probe not found for disable request!"); break; } ProcessSet::ptr waitingProcs = request->scope; if(waitingProcs && waitingProcs->size() > 0) { DYSECTVERBOSE(true, "Adding %d request processes to %d continue set...", waitingProcs->size(), continueSet->size()); continueSet = continueSet->set_union(waitingProcs); } ProcessSet::ptr operationSet = ProcessSet::newProcessSet(); ProcessSet::ptr stopSet = ProcessSet::newProcessSet(); ProcessSet::ptr scope = request->scope; if(scope && scope->size() > 0) { DYSECTVERBOSE(true, "Adding processes from scope set (%d) to affected procs (%d)", scope->size(), operationSet->size()); operationSet = operationSet->set_union(scope); } // // Filter out detached // operationSet = ProcessMgr::filterDetached(operationSet); stopSet = ProcessMgr::filterDetached(stopSet); DYSECTVERBOSE(true, "%d procs in op set, %d procs in stop set", operationSet->size(), stopSet->size()); // // Stop processes // stopSet = operationSet->getAnyThreadRunningSubset(); if(stopSet && stopSet->size() > 0) { DYSECTVERBOSE(true, "Stopping %d processes", stopSet->size()); stopSet->stopProcs(); } // // Carry out operations // if(operationSet && operationSet->size() > 0) { if(request->type == DisableType) { DYSECTVERBOSE(true, "Disabling %d processes", operationSet->size()); probe->disable(operationSet); } else { DYSECTVERBOSE(true, "Enabling %d processes", operationSet->size()); probe->enableChildren(operationSet); } } // // Processes must be started when all operations have been carried out. // if(operationSet && operationSet->size() > 0) { continueSet = continueSet->set_union(operationSet); } delete(request); } continueSet = ProcessMgr::filterDetached(continueSet); if(continueSet && continueSet->size() > 0) { DYSECTVERBOSE(true, "Continuing %d processes", continueSet->size()); if(continueSet->size() == 1) { ProcessSet::iterator procIter = continueSet->begin(); Process::ptr process = *procIter; DYSECTVERBOSE(true, "Continuing process %d", process->getPid()); } continueSet->continueProcs(); } DYSECTVERBOSE(true, "Done handling requests"); return true; }
test_results_t pc_libraryMutator::executeTest() { //std::cerr << "ExecuteTest" << std::endl; proclibs.clear(); got_breakpoint = false; myerror = false; Process::registerEventCallback(EventType::Breakpoint, on_breakpoint); Process::registerEventCallback(EventType::Library, on_library); std::vector<Process::ptr>::iterator i; for (i = comp->procs.begin(); i != comp->procs.end(); i++) { std::string libc_fullname; Library::ptr libc_lib; Process::ptr proc = *i; Process::const_ptr cproc = proc; proc_info_lib &pi = proclibs[cproc]; for (LibraryPool::iterator j = proc->libraries().begin(); j != proc->libraries().end(); j++) { Library::ptr lib = *j; #if !defined(os_windows_test) if (lib->getName().find("libc") != std::string::npos) { pi.found_libc = true; libc_fullname = lib->getName(); libc_lib = lib; } #else if (lib->getName().find("msvcrt") != std::string::npos) { pi.found_libc = true; libc_fullname = lib->getName(); libc_lib = lib; } #endif if (lib->getName().find("pc_library_mutatee") != std::string::npos || lib->getName().find("pc_library.") != std::string::npos) { pi.found_exec = true; } } if(!libc_fullname.empty()) { Library::ptr libc_lib2 = proc->libraries().getLibraryByName(libc_fullname); if (libc_lib != libc_lib2) { logerror("Failed to find libc in getLibraryByName\n"); myerror = true; } } bool result = proc->continueProc(); if (!result) { logerror("Failed to continue process\n"); myerror = true; } } syncloc loc[NUM_PARALLEL_PROCS]; bool result = comp->recv_broadcast((unsigned char *) loc, sizeof(syncloc)); if (!result) { logerror("Failed to recieve sync broadcast\n"); myerror = true; } for (unsigned j=0; j<comp->procs.size(); j++) { if (loc[j].code != SYNCLOC_CODE) { logerror("Recieved unexpected message code\n"); myerror = true; } } result = comp->send_broadcast((unsigned char *) loc, sizeof(syncloc)); if (!result) { logerror("Failed to send sync broadcast\n"); myerror = true; } if (got_breakpoint) { logerror("Recieved breakpoint, shouldn't have\n"); myerror = true; } if (comp->procs.size() != proclibs.size()) { logerror("Didn't get library events from enough processes\n"); myerror = true; } for (std::map<Process::const_ptr, proc_info_lib>::iterator j = proclibs.begin(); j != proclibs.end(); j++) { const proc_info_lib &pi = j->second; if (pi.loaded_libtesta == -1) { logerror("Didn't load libtestA\n"); myerror = true; } if (pi.loaded_libtestb == -1) { logerror("Didn't load libtestB\n"); myerror = true; } if (pi.unloaded_libtesta == -1) { logerror("Didn't unload libtestA\n"); myerror = true; } if (pi.unloaded_libtestb == -1) { logerror("Didn't unload libtestB\n"); myerror = true; } if (pi.loaded_libtesta != 0 || pi.loaded_libtestb != 1 || pi.unloaded_libtestb != 2 || pi.unloaded_libtesta != 3) { logerror("Unexpected library load order\n"); myerror = true; } if(!isAttach) { #if !defined(os_windows_test) if (!pi.found_exec) { logerror("Failed to find executable\n"); myerror = true; } #endif if (!pi.found_libc) { logerror("Failed to find libc\n"); myerror = true; } } } Process::removeEventCallback(on_library); Process::removeEventCallback(on_breakpoint); return myerror ? FAILED : PASSED; }