#define WIN32_LEAN_AND_MEAN #include #include #include #include #include // here be typedefs and definitions of imported functions typedef DWORD (WINAPI*SetOptsFunc)(DWORD); typedef BOOL (WINAPI*InitFunc)(HANDLE, LPCSTR, BOOL); typedef DWORD64 (WINAPI*LoadFunc)(HANDLE, HANDLE, LPCSTR, LPCSTR, DWORD64, DWORD, PMODLOAD_DATA, DWORD); typedef BOOL (WINAPI*EnumFunc)(HANDLE, DWORD64, LPCSTR, PSYM_ENUMERATESYMBOLS_CALLBACK, PVOID); typedef BOOL (WINAPI*CleanupFunc)(HANDLE); SetOptsFunc symSetOptions = NULL; InitFunc symInitialize = NULL; LoadFunc symLoadModuleEx = NULL; EnumFunc symEnumSymbols = NULL; CleanupFunc symCleanup = NULL; bool LoadImports(HMODULE hDbghelp) { symSetOptions = reinterpret_cast(GetProcAddress(hDbghelp, "SymSetOptions")); symInitialize = reinterpret_cast(GetProcAddress(hDbghelp, "SymInitialize")); symLoadModuleEx = reinterpret_cast(GetProcAddress(hDbghelp, "SymLoadModuleEx")); symEnumSymbols = reinterpret_cast(GetProcAddress(hDbghelp, "SymEnumSymbols")); symCleanup = reinterpret_cast(GetProcAddress(hDbghelp, "SymCleanup")); return symSetOptions && symInitialize && symLoadModuleEx && symEnumSymbols && symCleanup; } void DisplayFlags(PSYMBOL_INFO pSym, std::ostream& out) { DWORD flags = pSym->Flags; if(flags & SYMFLAG_REGISTER) { out << "\tregister\n"; } if(flags & SYMFLAG_PARAMETER) { out << "\tfunction parameter\n"; } if(flags & SYMFLAG_LOCAL) { out << "\tlocal variable\n"; } if(flags & SYMFLAG_CONSTANT) { out << "\tconstant of value " << pSym->Value << '\n'; } if(flags & SYMFLAG_EXPORT) { out << "\tmodule export\n"; } if(flags & SYMFLAG_FORWARDER) { out << "\ta forwarder\n"; } if(flags & SYMFLAG_FUNCTION) { out << "\tfunction\n"; } if(flags & SYMFLAG_THUNK) { out << "\tthunk\n"; } if(flags & SYMFLAG_TLSREL) { out << "\toffset into the TLS area\n"; } if(flags & SYMFLAG_SLOT) { out << "\tmanaged code slot\n"; } if(flags & SYMFLAG_ILREL) { out << "\taddress relative to the IL block\n"; } if(flags & SYMFLAG_METADATA) { out << "\tchunk of managed metadata\n"; } if(flags & SYMFLAG_CLR_TOKEN) { out << "\tCLR token\n"; } } // see http://msdn.microsoft.com/en-us/library/bkedss5f.aspx for more // info on what the typeTags mean const char* typeTags[] = { "", "Executable (Global)", "Compiland", "CompilandDetails", "CompilandEnv", "Function", "Block", "Data", "Unused", "Labe", "PublicSymbol", "UDT", "Enum", "FunctionType", "PointerType", "ArrayType", "BaseType", "Typedef", "BaseClass", "Friend", "FunctionArgType", "FuncDebugStart", "FuncDebugEnd", "UsingNamespace", "VTableShape", "VTable", "Custom", "Thunk", "CustomType", "" }; BOOL CALLBACK SymFound(PSYMBOL_INFO pSymInfo, ULONG, PVOID pFoundFlag) { *(static_cast(pFoundFlag)) = true; std::cout << "Found symbol\n"; std::cout << "Name: " << pSymInfo->Name << '\n'; if(pSymInfo->Address) { std::cout << "Address: 0x" << std::hex << pSymInfo->Address << '\n'; } if(pSymInfo->Flags) { std::cout << "Type Flags: "; DisplayFlags(pSymInfo, std::cout); } std::cout << "Type Tag: " << typeTags[pSymInfo->Tag] << '\n'; std::cout << '\n'; return TRUE; } int main(int argc, char** argv) { if(argc >= 2) { HMODULE hDbghelp = LoadLibrary(L"dbghelp_6.9.dll"); if(hDbghelp && LoadImports(hDbghelp)) { HANDLE hProc = GetCurrentProcess(); symSetOptions(SYMOPT_ALLOW_ZERO_ADDRESS | SYMOPT_AUTO_PUBLICS | SYMOPT_CASE_INSENSITIVE | SYMOPT_FAIL_CRITICAL_ERRORS | SYMOPT_LOAD_LINES | SYMOPT_UNDNAME | SYMOPT_OMAP_FIND_NEAREST); if(symInitialize(hProc, 0, FALSE)) { HANDLE hFile = CreateFileA(argv[1], GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if(hFile != INVALID_HANDLE_VALUE) { DWORD64 baseAddress = 0; if((baseAddress = symLoadModuleEx(hProc, hFile, argv[1], NULL, 0, GetFileSize(hFile, NULL), NULL, 0))) { bool anyFound = false; const char* matchString = argv[2] ? argv[2] : "*"; if(symEnumSymbols(hProc, baseAddress, matchString, &SymFound, &anyFound)) { if(!anyFound) { std::cout << "No symbols of pattern " << matchSymbolBuf << " found\n"; } } else std::cout << "Failed to enumerate symbols - error " << GetLastError() << '\n'; } else std::cout << "Couldn't load image module and symbols - error " << GetLastError(); CloseHandle(hFile); } else std::cout << "Couldn't open image file - error " << GetLastError(); symCleanup(hProc); FreeLibrary(hDbghelp); } else std::cout << "Couldn't load or find symbols in dbghelp.dll"; } else std::cout << "Couldn't initialize the symbol handler"; } else { // symbol name is case insensitive and can take // multiple wildcards so that "MySym", "*Sym" and "*Sym*" // are all valid and will match MySym and mysym std::cout << "Usage: SymFinder [image file] "; } std::cout << std::endl; }