bool PCLibraryState::cacheLibraryRanges(Library::ptr lib) { std::string filename = lib->getName(); Address base = lib->getLoadAddress(); SymbolReaderFactory *fact = getDefaultSymbolReader(); SymReader *reader = fact->openSymbolReader(filename); if (!reader) { sw_printf("[%s:%u] - Error could not open expected file %s\n", FILE__, __LINE__, filename.c_str()); return false; } int num_segments = reader->numSegments(); for (int i=0; i<num_segments; i++) { SymSegment segment; reader->getSegment(i, segment); if (segment.type != 1) continue; Address segment_start = segment.mem_addr + base; Address segment_end = segment_start + segment.mem_size; loadedLibs.insert(segment_start, segment_end, makeCache(LibAddrPair(lib->getName(), lib->getLoadAddress()), lib)); } return true; }
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; }
DysectErrorCode Backend::writeModuleVariable(Dyninst::ProcControlAPI::Process::ptr process, std::string variableName, std::string libraryPath, void *value, int size) { bool result, found = false; string libraryName; Symtab *symtab = NULL; Offset varOffset; Address loadAddress; vector<SymtabAPI::Variable *> variables; LibraryPool::iterator libsIter; 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]; } result = symtab->findVariablesByName(variables, variableName); if (result == false || variables.size() < 1) { DYSECTWARN(false, "Failed to find %s variable", variableName.c_str()); return Error; } varOffset = variables[0]->getOffset(); DYSECTLOG(true, "found %s at offset 0x%lx", variableName.c_str(), varOffset); libraryName = basename(libraryPath.c_str()); LibraryPool &libs = process->libraries(); 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; } process->writeMemory(loadAddress + varOffset, value, size); return OK; }
void PCLibraryState::checkForNewLib(Library::ptr lib) { if (lib->getData()) return; sw_printf("[%s:%u] - Detected new library %s at %lx, notifying\n", FILE__, __LINE__, lib->getName().c_str(), lib->getLoadAddress()); lib->setData((void *) 0x1); StepperGroup *group = pdebug->getWalker()->getStepperGroup(); LibAddrPair la(lib->getName(), lib->getLoadAddress()); group->newLibraryNotification(&la, library_load); }
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; }
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; }
Process::cb_ret_t on_library(Event::const_ptr ev) { EventLibrary::const_ptr evlib = ev->getEventLibrary(); if (!evlib) { logerror("error, received non library event\n"); myerror = true; return Process::cbDefault; } proc_info_lib &pi = proclibs[ev->getProcess()]; const LibraryPool& libpool = ev->getProcess()->libraries(); std::set<Library::ptr>::const_iterator i; for (i = evlib->libsAdded().begin(); i != evlib->libsAdded().end(); i++) { Library::ptr lib = *i; // FIXME //cerr << hex << "Callback library " << lib << dec << endl; if (lib->getName().find("testA") != string::npos) { pi.loaded_libtesta = pi.order++; } if (lib->getName().find("testB") != string::npos) { pi.loaded_libtestb = pi.order++; } bool found_lib = false; find_by_pointer F = find_by_pointer(lib); for(LibraryPool::const_iterator i = libpool.begin(); i != libpool.end(); ++i) { F(*i); } found_lib = F.found_it; if (!found_lib) { logerror("New library was not in library list\n"); myerror = true; } } for (i = evlib->libsRemoved().begin(); i != evlib->libsRemoved().end(); i++) { Library::ptr lib = *i; // Reduce these to "testA/testB" because Windows standard is for DLLs not to be "lib" prefixed if (lib->getName().find("testA") != string::npos) { pi.unloaded_libtesta = pi.order++; } if (lib->getName().find("testB") != string::npos) { pi.unloaded_libtestb = pi.order++; } find_by_pointer f(lib); for(LibraryPool::const_iterator i = libpool.begin(); i != libpool.end(); ++i) { f(*i); } if(f.found_it) { logerror("Removed library was still in library list\n"); myerror = true; } /* for (LibraryPool::const_iterator j = libpool.begin(); j != libpool.end(); j++) { if (*j == lib) { logerror("Removed library was still in library list\n"); myerror = true; } } */ } return Process::cbDefault; }