int KFuncTable::InterceptWin32(const char *Caller, const char *Callee, PIMAGE_THUNK_DATA pName, PIMAGE_THUNK_DATA pThunk, const char *baseAddress) { int no = 0; // if module not added to module table, quit if (LookupModule(Caller, Callee) == -1) return 0; while ( pThunk->u1.Function ) { int id; PBYTE pFunctionName = (PBYTE) ( baseAddress + (unsigned) pName->u1.ForwarderString + 2); FARPROC pInterceptedFunction = LookupInterceptedAPI((FARPROC) pThunk->u1.Function, id); if ( pInterceptedFunction ) if ( HackCopy(& pThunk->u1.Function, & pInterceptedFunction, sizeof(FARPROC)) ) { m_func[id].f_hooked = TRUE; no ++; } pName ++; pThunk++; } return no; }
// Adds a modules to the MODULE_FILE_INFO list. If the module imports other // modules, this routine recurses to add them, and check their imports. errModuleDependencyList MODULE_DEPENDENCY_LIST::AddModule( PSTR pszFileName ) { PE_EXE peFile( pszFileName ); // Get easy access to the executable if ( FALSE == peFile.IsValid() ) // A valid PE file??? return (errModuleDependencyList)peFile.GetErrorType(); PMODULE_FILE_INFO pNew = new MODULE_FILE_INFO( pszFileName ); if ( !pNew ) return errMDL_GENERAL_FAILURE; pNew->m_pNext = m_pList; m_pList = pNew; m_cModules++; // // Now see if this module imports any other modules. If so, we need // to recurse and add them as well. // if (0 == peFile.GetDataDirectoryEntrySize( IMAGE_DIRECTORY_ENTRY_IMPORT )) return errMDL_NO_ERROR; // Make a pointer to the imports table PIMAGE_IMPORT_DESCRIPTOR pImportDir; pImportDir = (PIMAGE_IMPORT_DESCRIPTOR) peFile.GetDataDirectoryEntryPointer(IMAGE_DIRECTORY_ENTRY_IMPORT); if ( !pImportDir ) return errMDL_NO_ERROR; // While there are still non-null IMAGE_IMPORT_DESCRIPTORs... while ( pImportDir->Name ) { // Get a pointer to the imported module's base name PSTR pszBaseName; pszBaseName = (PSTR)peFile.GetReadablePointerFromRVA(pImportDir->Name); if ( !pszBaseName ) break; // Check to see if it's already in our list. Don't add again if so. if ( 0 == LookupModule( pszBaseName, FALSE ) ) { // Search path supposedly has the same searching algorithm as // the the Win32 loader... char szPath[MAX_PATH]; PSTR pszDontCare; if ( SearchPath(0, pszBaseName, 0, MAX_PATH, szPath, &pszDontCare)) AddModule( szPath ); else pNew->AddNotFoundModule( pszBaseName ); } pImportDir++; // Advance to next imported module } return errMDL_NO_ERROR; }
bool Yap_getUnknown(Term mod) { ModEntry *m = LookupModule(mod); return Yap_getUnknownModule(m); }
Win32CallstackResolver::Win32CallstackResolver(char *moduleDB, size_t DBSize, string pdbSearchPaths, volatile bool *killSignal) { wstring configPath = StringFormat::UTF82Wide(FileIO::GetAppFolderFilename("config.ini")); { FILE *f = NULL; _wfopen_s(&f, configPath.c_str(), L"a"); if(f) fclose(f); } wchar_t inputBuf[2048]; GetPrivateProfileStringW(L"renderdoc", L"ignores", NULL, &inputBuf[0], 2048, configPath.c_str()); wstring ignores = inputBuf; split(ignores, pdbIgnores, L';'); wstring widepdbsearch = StringFormat::UTF82Wide(pdbSearchPaths); split(widepdbsearch, pdbRememberedPaths, L';'); pdblocateProcess = NULL; pdblocatePipe = NULL; OpenPdblocateHandle(); if(memcmp(moduleDB, "WN32CALL", 8)) { RDCWARN("Can't load callstack resolve for this log. Possibly from another platform?"); return; } char *chunks = moduleDB + 8; char *end = chunks + DBSize - 8; EnumModChunk *chunk = (EnumModChunk *)(chunks); WCHAR *modName = (WCHAR *)(chunks+sizeof(EnumModChunk)); if(pdblocatePipe == NULL) return; // loop over all our modules for(; chunks < end; chunks += sizeof(EnumModChunk)+(chunk->imageNameLen)*sizeof(WCHAR) ) { chunk = (EnumModChunk *)chunks; modName = (WCHAR *)(chunks+sizeof(EnumModChunk)); if(killSignal && *killSignal) break; Module m; m.name = modName; m.base = chunk->base; m.size = chunk->size; m.moduleId = 0; if(find(pdbIgnores.begin(), pdbIgnores.end(), m.name) != pdbIgnores.end()) { RDCWARN("Not attempting to get symbols for %ls", m.name.c_str()); modules.push_back(m); continue; } // get default pdb (this also looks up symbol server etc) // relies on pdblocate. Always done in unicode std::wstring defaultPdb = LookupModule(modName, chunk->guid, chunk->age); // strip newline if(defaultPdb != L"" && defaultPdb[defaultPdb.length()-1] == '\n') defaultPdb.pop_back(); // if we didn't even get a default pdb we'll have to prompt first time through bool failed = false; if(defaultPdb == L"") { defaultPdb = strlower(basename(m.name)); size_t it = defaultPdb.find(L".dll"); if(it != wstring::npos) { defaultPdb[it+1] = L'p'; defaultPdb[it+2] = L'd'; defaultPdb[it+3] = L'b'; } it = defaultPdb.find(L".exe"); if(it != wstring::npos) { defaultPdb[it+1] = L'p'; defaultPdb[it+2] = L'd'; defaultPdb[it+3] = L'b'; } failed = true; } std::wstring pdbName = defaultPdb; int fallbackIdx = -1; while(m.moduleId == 0) { if(failed) { fallbackIdx++; // try one of the folders we've been given, just in case the symbols // are there if(fallbackIdx < (int)pdbRememberedPaths.size()) { pdbName = pdbRememberedPaths[fallbackIdx] + L"\\" + basename(pdbName); } else { pdbName = dirname(defaultPdb) + L"\\" + basename(defaultPdb); // prompt for new pdbName, unless it's renderdoc or dbghelp if(pdbName.find(L"renderdoc.") != wstring::npos || pdbName.find(L"dbghelp.") != wstring::npos) pdbName = L""; else pdbName = pdbBrowse(pdbName); // user cancelled, just don't load this pdb if(pdbName == L"") break; } failed = false; } m.moduleId = GetModuleID(pdbName, chunk->guid, chunk->age); if(m.moduleId == 0) { failed = true; } else { if(fallbackIdx >= (int)pdbRememberedPaths.size()) { wstring dir = dirname(pdbName); if(find(pdbRememberedPaths.begin(), pdbRememberedPaths.end(), dir) == pdbRememberedPaths.end()) { pdbRememberedPaths.push_back(dir); } } } } // didn't load the pdb? go to the next module. if (m.moduleId == 0) { modules.push_back(m); // still add the module, with 0 module id RDCWARN("Couldn't get symbols for %ls", m.name.c_str()); // silently ignore renderdoc.dll and dbghelp.dll without asking to permanently ignore if(m.name.find(L"renderdoc") != wstring::npos || m.name.find(L"dbghelp") != wstring::npos) continue; wchar_t text[1024]; wsprintf(text, L"Do you want to permanently ignore this file?\nPath: %ls", m.name.c_str()); int ret = MessageBoxW(NULL, text, L"Ignore this pdb?", MB_YESNO); if(ret == IDYES) pdbIgnores.push_back(m.name); continue; } SetModuleBaseAddress(m.moduleId, chunk->base); RDCLOG("Loaded Symbols for %ls", m.name.c_str()); modules.push_back(m); } sort( pdbIgnores.begin(), pdbIgnores.end() ); pdbIgnores.erase( unique( pdbIgnores.begin(), pdbIgnores.end() ), pdbIgnores.end() ); merge(pdbIgnores, ignores, L';'); WritePrivateProfileStringW(L"renderdoc", L"ignores", ignores.c_str(), configPath.c_str()); }