/* static */ BOOL wxDbgHelpDLL::CallSymEnumSymbols(HANDLE hProcess, ULONG64 baseOfDll, wxPSYM_ENUMERATESYMBOLS_CALLBACK callback, const PVOID callbackParam) { #ifdef UNICODE if ( SymEnumSymbolsW ) { if ( SymEnumSymbolsW(hProcess, baseOfDll, NULL, callback, callbackParam) ) return TRUE; } if ( SymEnumSymbols ) { wxEnumSymbolsCallbackBridge br(callback, callbackParam); if ( SymEnumSymbols(hProcess, baseOfDll, NULL, wxEnumSymbolsCallback, &br) ) return TRUE; } #else // !UNICODE if ( SymEnumSymbols ) { if ( SymEnumSymbols(hProcess, baseOfDll, NULL, callback, callbackParam) ) return TRUE; } #endif // UNICODE/!UNICODE return FALSE; }
int Psymbol_iter_by_addr(struct ps_prochandle *P, const char *object_name, int which, int mask, proc_sym_f *func, void *cd) { prmap_t *map ; struct lookup_uc uc; proc_mod_t *mod = findmodulebyname(P, object_name); /* this fails miserable - dtrace -n pid$target:user32:N*:entry pid$target:M*::entry -c exe the second probe spec will be ignored */ if (mod == NULL || mod->loaded_order < P->dll_load_order) return 0; if (strcmp("a.out", object_name) == 0) map = Plmid_to_map(P, 0, P->exe_module->name); else map = Plmid_to_map(P, 0, object_name); if (map == NULL) { return -1; } uc.f = func; uc.cd = cd; uc.ps = P; uc.count = 0; if (SymEnumSymbols(P->phandle, mod->imgbase, NULL, SymEnumSymbolsProc, &uc) == FALSE) { dprintf("Psymbol_iter_by_addr: SymEnumSymbols failed %s: %x\n", object_name, GetLastError()); return -1; } if (uc.count != 0) return 0; return dw_iter_by_addr(P, object_name, which, mask, func, cd); }
void FunctionResolver::resolveParameters(const ULONG64& functionAddress, const ULONG64& modBase, const ULONG& typeIndex, std::vector<FunctionParameter>& resolvedParameters) { IMAGEHLP_STACK_FRAME sf; sf.InstructionOffset = functionAddress; if (!SymSetContext(this->m_hProcess, &sf, 0)) { throw; } // Retrieve all parameters of this function. SymEnumSymbols(this->m_hProcess, NULL, NULL, EnumParamsCallback, &resolvedParameters); }
BOOL CShadowSSDTMgr::GetShadowSSDTNativeAddrBySymbol() { BOOL boRetn; PDWORD pW32pServiceTable = 0; DWORD dwload = 0; PLOADED_IMAGE ploadImage = {0}; char imgPath[MAX_PATH]; // 初始化 if ( !InitSymbolsHandler() ) { return FALSE; } // 获取系统目录"C:\WINDOWS\system32" GetSystemDirectory( imgPath, MAX_PATH ); // 加载模块 ploadImage = ImageLoad( "win32k.sys", imgPath ); // 加载符号"C:\WINDOWS\system32\win32k.sys" strcat( imgPath, "\\win32k.sys" ); dwload=SymLoadModule ( g_ixerhProc, ploadImage->hFile, imgPath, "win32k.pdb", 0, ploadImage->SizeOfImage ); boRetn=SymEnumSymbols( g_ixerhProc, dwload, NULL, (PSYM_ENUMERATESYMBOLS_CALLBACK)EnumSymRoutine, NULL ); if (g_W32pServiceTable) { pW32pServiceTable = (PDWORD)( g_W32pServiceTable - dwload + (DWORD)ploadImage->MappedAddress ); boRetn=SymEnumSymbols( g_ixerhProc, dwload, NULL, (PSYM_ENUMERATESYMBOLS_CALLBACK)EnumSymRoutine, pW32pServiceTable ); } ImageUnload(ploadImage); SymCleanup(g_ixerhProc); return boRetn; }
int symbol_info_locals(void) { IMAGEHLP_STACK_FRAME ihsf; ADDRESS64 addr; stack_get_current_frame(&ihsf); addr.Mode = AddrModeFlat; addr.Offset = ihsf.InstructionOffset; print_address(&addr, FALSE); dbg_printf(": (%08lx)\n", (DWORD_PTR)ihsf.FrameOffset); SymEnumSymbols(dbg_curr_process->handle, 0, NULL, info_locals_cb, (void*)(DWORD_PTR)ihsf.FrameOffset); return TRUE; }
BOOL symbol_is_local(const char* name) { struct sgv_data sgv; IMAGEHLP_STACK_FRAME ihsf; sgv.num = 0; sgv.num_thunks = 0; sgv.name = name; sgv.do_thunks = FALSE; if (stack_get_current_frame(&ihsf)) { sgv.frame_offset = ihsf.FrameOffset; SymEnumSymbols(dbg_curr_process->handle, 0, name, sgv_cb, (void*)&sgv); } return sgv.num > 0; }
static void stack_print_addr_and_args(int nf) { char buffer[sizeof(SYMBOL_INFO) + 256]; SYMBOL_INFO* si = (SYMBOL_INFO*)buffer; IMAGEHLP_STACK_FRAME ihsf; IMAGEHLP_LINE64 il; IMAGEHLP_MODULE im; DWORD64 disp64; print_bare_address(&dbg_curr_thread->frames[nf].addr_pc); stack_get_frame(nf, &ihsf); /* grab module where symbol is. If we don't have a module, we cannot print more */ im.SizeOfStruct = sizeof(im); if (!SymGetModuleInfo(dbg_curr_process->handle, ihsf.InstructionOffset, &im)) return; si->SizeOfStruct = sizeof(*si); si->MaxNameLen = 256; if (SymFromAddr(dbg_curr_process->handle, ihsf.InstructionOffset, &disp64, si)) { struct sym_enum se; DWORD disp; dbg_printf(" %s", si->Name); if (disp64) dbg_printf("+0x%lx", (DWORD_PTR)disp64); SymSetContext(dbg_curr_process->handle, &ihsf, NULL); se.first = TRUE; se.frame = ihsf.FrameOffset; dbg_printf("("); SymEnumSymbols(dbg_curr_process->handle, 0, NULL, sym_enum_cb, &se); dbg_printf(")"); il.SizeOfStruct = sizeof(il); if (SymGetLineFromAddr64(dbg_curr_process->handle, ihsf.InstructionOffset, &disp, &il)) dbg_printf(" [%s:%u]", il.FileName, il.LineNumber); dbg_printf(" in %s", im.ModuleName); } else dbg_printf(" in %s (+0x%lx)", im.ModuleName, (DWORD_PTR)(ihsf.InstructionOffset - im.BaseOfImage)); }
//-------------------------------------------------------------------------------------- ULONGLONG GetSymbolByName(char *lpszModuleName, HMODULE hModule, char *lpszName) { ULONGLONG Ret = 0; // try to load debug symbols for module if (SymLoadModuleEx(GetCurrentProcess(), NULL, lpszModuleName, NULL, (DWORD64)hModule, 0, NULL, 0)) { ENUM_SYM_PARAM Param; Param.Address = NULL; Param.lpszName = lpszName; // get specified symbol address by name if (!SymEnumSymbols( GetCurrentProcess(), (DWORD64)hModule, NULL, EnumSymbolsProc, &Param)) { DbgMsg(__FILE__, __LINE__, "SymEnumSymbols() ERROR %d\n", GetLastError()); } if (Param.Address == NULL) { DbgMsg(__FILE__, __LINE__, __FUNCTION__"() ERROR: Can't locate symbol\n"); } else { Ret = Param.Address; } // unload symbols SymUnloadModule64(GetCurrentProcess(), (DWORD64)hModule); } else { DbgMsg(__FILE__, __LINE__, "SymLoadModuleEx() ERROR %d\n", GetLastError()); } return Ret; }
void symbol_info(const char* str) { char buffer[512]; DWORD opt; if (strlen(str) + 3 >= sizeof(buffer)) { dbg_printf("Symbol too long (%s)\n", str); return; } buffer[0] = '*'; buffer[1] = '!'; strcpy(&buffer[2], str); /* this is a wine specific options to return also ELF modules in the * enumeration */ SymSetOptions((opt = SymGetOptions()) | 0x40000000); SymEnumSymbols(dbg_curr_process->handle, 0, buffer, symbols_info_cb, NULL); SymSetOptions(opt); }
/** * * Enumerates one module in a process * * @param dwDllBases_i - Base address of module to enumerate * @return bool - Return true * @exception Nil * @see Nil * @since 1.0 */ bool ProcessSymbolCollection::EnumerateModuleSymbols( DWORD dwDllBases_i, SymbolCollection*& pModSymColl_o, LPCTSTR lpctszModuleFileName_i, const DWORD dwModuleSize_i, const bool bRefresh_i ) { UNREFERENCED_PARAMETER( lpctszModuleFileName_i ); UNREFERENCED_PARAMETER( dwModuleSize_i ); bool bFound = false; if( bRefresh_i ) { // Find in map bFound = m_ModSymMap.Lookup( dwDllBases_i, pModSymColl_o ) != FALSE; if( bFound ) { // Remove entry from map m_ModSymMap.RemoveKey( dwDllBases_i ); delete pModSymColl_o; }// End if }// End if if( bRefresh_i || !m_ModSymMap.Lookup( dwDllBases_i, pModSymColl_o )) { // Allocate a new module symbol collection pModSymColl_o = new SymbolCollection; SymEnumSymbols( m_hProcess, dwDllBases_i, 0, EnumModuleSymbolsCB, pModSymColl_o ); // Add this entry to map m_ModSymMap[dwDllBases_i] = pModSymColl_o; }// End if return true; }// End Enumerate
const bool Symbols::EnumerateModuleSymbols(const char * const pModulePath, const DWORD64 dwBaseAddress) { DWORD64 dwBaseOfDll = SymLoadModuleEx(m_hProcess, m_hFile, pModulePath, nullptr, dwBaseAddress, 0, nullptr, 0); if (dwBaseOfDll == 0) { fprintf(stderr, "Could not load modules for %s. Error = %X.\n", pModulePath, GetLastError()); return false; } UserContext userContext = { this, pModulePath }; const bool bSuccess = BOOLIFY(SymEnumSymbols(m_hProcess, dwBaseOfDll, "*!*", SymEnumCallback, &userContext)); if (!bSuccess) { fprintf(stderr, "Could not enumerate symbols for %s. Error = %X.\n", pModulePath, GetLastError()); } return bSuccess; }
int Pxlookup_by_name(struct ps_prochandle *P, Lmid_t lmid, const char *oname, const char *sname, GElf_Sym *symp, void *sip) { int ol = 0, sl = 0; char *Mask; const char *obj = oname; struct lookup_uc uc; if (sname == NULL) return -1; if (oname == NULL) obj = "*"; else if (strcmp("a.out", oname) == 0) obj = P->exe_module->name; Mask = malloc((ol = strlen(obj)) + (sl = strlen(sname)) + 2); strncpy(Mask, obj, ol); strncpy(&Mask[ol++], "!", 1); strncpy(&Mask[ol], sname, sl); Mask[ol + sl] = 0; memset(symp, 0, sizeof(GElf_Sym)); uc.ps = P; uc.cd = symp; uc.f = NULL; if (SymEnumSymbols(P->phandle, 0, Mask, MyEnumSymbolsCallback, &uc) == FALSE) { dprintf("SymEnumSymbols failed (%d): %x\n", P->pid, GetLastError()); free(Mask); return -1; } free(Mask); if (symp->st_value != 0) return 0; return dw_lookup_by_name(P, oname, sname, symp); }
int enumerate_symbols(Context * ctx, int frame, EnumerateSymbolsCallBack * call_back, void * args) { ULONG64 buffer[(sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR) + sizeof(ULONG64) - 1) / sizeof(ULONG64)]; SYMBOL_INFO * symbol = (SYMBOL_INFO *)buffer; IMAGEHLP_STACK_FRAME stack_frame; EnumerateSymbolsContext enum_context; HANDLE process = get_context_handle(ctx->parent == NULL ? ctx : ctx->parent); symbol->SizeOfStruct = sizeof(SYMBOL_INFO); symbol->MaxNameLen = MAX_SYM_NAME; if (frame == STACK_TOP_FRAME) frame = get_top_frame(ctx); if (frame == STACK_TOP_FRAME) return -1; if (get_stack_frame(ctx, frame, 0, &stack_frame) < 0) return -1; if (!SymSetContext(process, &stack_frame, NULL)) { DWORD err = GetLastError(); if (err == ERROR_SUCCESS) { /* Don't know why Windows does that */ } else { set_win32_errno(err); return -1; } } enum_context.ctx = ctx; enum_context.frame = frame; enum_context.call_back = call_back; enum_context.args = args; if (!SymEnumSymbols(process, 0, NULL, enumerate_symbols_proc, &enum_context)) { set_win32_errno(GetLastError()); return -1; } return 0; }
BOOL JpfsvpSearchSymbolCommand( __in PJPFSV_COMMAND_PROCESSOR_STATE ProcessorState, __in PCWSTR CommandName, __in UINT Argc, __in PCWSTR* Argv ) { SEARCH_SYMBOL_CTX Ctx; HANDLE Process = JpfsvGetProcessHandleContext( ProcessorState->Context ); UNREFERENCED_PARAMETER( CommandName ); if ( Argc < 1 ) { ( ProcessorState->OutputRoutine ) ( L"Usage: x <mask>\n" ); return FALSE; } Ctx.OutputRoutine = ProcessorState->OutputRoutine; Ctx.ContextHandle = ProcessorState->Context; if ( ! SymEnumSymbols( Process, 0, Argv[ 0 ], JpfsvsOutputSymbol, &Ctx ) ) { DWORD Err = GetLastError(); JpfsvpOutputError( ProcessorState, HRESULT_FROM_WIN32( Err ) ); return FALSE; } return TRUE; }
static VOID TestTraceNotepadAndDoHarshCleanup() { PROCESS_INFORMATION pi; JPFSV_HANDLE NpCtx; PROC_SET Set; DWORD_PTR FailedProc; TEST_OK( CdiagCreateSession( NULL, NULL, &DiagSession ) ); // // Launch notepad. // LaunchNotepad( &pi ); // // Give notepad some time to start... // Sleep( 1000 ); // // Start a trace. // TEST_OK( JpfsvLoadContext( pi.dwProcessId, NULL, &NpCtx ) ); TEST_OK( JpfsvAttachContext( NpCtx, JpfsvTracingTypeDefault, NULL ) ); // // Instrument some procedures. // Set.Count = 0; Set.ContextHandle = NpCtx; Set.Process = JpfsvGetProcessHandleContext( NpCtx ); TEST( Set.Process ); TEST( SymEnumSymbols( Set.Process, 0, L"user32!*", AddProcedureSymCallback, &Set ) ); TEST_OK( JpfsvStartTraceContext( NpCtx, 5, 1024, DiagSession ) ); TEST_OK( JpfsvSetTracePointsContext( NpCtx, JpfsvAddTracepoint, Set.Count, Set.Procedures, &FailedProc ) ); // // Skip stopping, skip detach. // TEST_OK( JpfsvUnloadContext( NpCtx ) ); TEST_OK( CdiagDereferenceSession( DiagSession ) ); // // Kill notepad. // TEST( TerminateProcess( pi.hProcess, 0 ) ); CloseHandle( pi.hProcess ); CloseHandle( pi.hThread ); // // Wait i.o. not to confuse further tests with dying process. // Sleep( 1000 ); }
int main(int argc, char *argv[]) { DWORD error; HANDLE process; ULONG64 module_base; SYM_CONTEXT ctx; int i; char* search; char* filename = NULL; int rv = 0; /* We may add SYMOPT_UNDNAME if --demangle is specified: */ DWORD symopts = SYMOPT_DEFERRED_LOADS | SYMOPT_DEBUG; for (i = 1; i < argc; i++) { if (strcmp(argv[i], "--demangle") == 0 || strcmp(argv[i], "-C") == 0) { symopts |= SYMOPT_UNDNAME; } else if (strcmp(argv[i], "--help") == 0) { usage(); exit(0); } else { break; } } if (i != argc - 1) { usage(); exit(1); } filename = argv[i]; process = GetCurrentProcess(); if (!SymInitialize(process, NULL, FALSE)) { error = GetLastError(); fprintf(stderr, "SymInitialize returned error : %d\n", error); return 1; } search = malloc(SEARCH_CAP); if (SymGetSearchPath(process, search, SEARCH_CAP)) { if (strlen(search) + sizeof(";" WEBSYM) > SEARCH_CAP) { fprintf(stderr, "Search path too long\n"); SymCleanup(process); return 1; } strcat(search, ";" WEBSYM); } else { error = GetLastError(); fprintf(stderr, "SymGetSearchPath returned error : %d\n", error); rv = 1; /* An error, but not a fatal one */ strcpy(search, WEBSYM); /* Use a default value */ } if (!SymSetSearchPath(process, search)) { error = GetLastError(); fprintf(stderr, "SymSetSearchPath returned error : %d\n", error); rv = 1; /* An error, but not a fatal one */ } SymSetOptions(symopts); module_base = SymLoadModuleEx(process, NULL, filename, NULL, 0, 0, NULL, 0); if (!module_base) { /* SymLoadModuleEx failed */ error = GetLastError(); fprintf(stderr, "SymLoadModuleEx returned error : %d for %s\n", error, filename); SymCleanup(process); return 1; } ShowSymbolInfo(process, module_base); memset(&ctx, 0, sizeof(ctx)); ctx.module_base = module_base; if (!SymEnumSymbols(process, module_base, NULL, EnumSymProc, &ctx)) { error = GetLastError(); fprintf(stderr, "SymEnumSymbols returned error: %d\n", error); rv = 1; } else { DWORD j; qsort(ctx.syms, ctx.syms_len, sizeof(ctx.syms[0]), sym_cmp); for (j = 0; j < ctx.syms_len; j++) { printf("%016I64x X %s\n", ctx.syms[j].addr, ctx.syms[j].name); } /* In a perfect world, maybe we'd clean up ctx's memory? */ } SymUnloadModule64(process, module_base); SymCleanup(process); return rv; }
/*********************************************************************** * symbol_get_lvalue * * Get the address of a named symbol. * Return values: * sglv_found: if the symbol is found * sglv_unknown: if the symbol isn't found * sglv_aborted: some error occurred (likely, many symbols of same name exist, * and user didn't pick one of them) */ enum sym_get_lval symbol_get_lvalue(const char* name, const int lineno, struct dbg_lvalue* rtn, BOOL bp_disp) { struct sgv_data sgv; int i; char buffer[512]; DWORD opt; IMAGEHLP_STACK_FRAME ihsf; if (strlen(name) + 4 > sizeof(buffer)) { WINE_WARN("Too long symbol (%s)\n", name); return sglv_unknown; } sgv.num = 0; sgv.num_thunks = 0; sgv.name = &buffer[2]; sgv.do_thunks = DBG_IVAR(AlwaysShowThunks); if (strchr(name, '!')) { strcpy(buffer, name); } else { buffer[0] = '*'; buffer[1] = '!'; strcpy(&buffer[2], name); } /* this is a wine specific options to return also ELF modules in the * enumeration */ SymSetOptions((opt = SymGetOptions()) | 0x40000000); SymEnumSymbols(dbg_curr_process->handle, 0, buffer, sgv_cb, (void*)&sgv); if (!sgv.num) { const char* ptr = strchr(name, '!'); if ((ptr && ptr[1] != '_') || (!ptr && *name != '_')) { if (ptr) { int offset = ptr - name; memcpy(buffer, name, offset + 1); buffer[offset + 1] = '_'; strcpy(&buffer[offset + 2], ptr + 1); } else { buffer[0] = '*'; buffer[1] = '!'; buffer[2] = '_'; strcpy(&buffer[3], name); } SymEnumSymbols(dbg_curr_process->handle, 0, buffer, sgv_cb, (void*)&sgv); } } SymSetOptions(opt); /* now grab local symbols */ if (stack_get_current_frame(&ihsf) && sgv.num < NUMDBGV) { sgv.frame_offset = ihsf.FrameOffset; SymEnumSymbols(dbg_curr_process->handle, 0, name, sgv_cb, (void*)&sgv); } if (!sgv.num) { dbg_printf("No symbols found for %s\n", name); return sglv_unknown; } /* recompute potential offsets for functions (linenumber, skip prolog) */ for (i = 0; i < sgv.num; i++) { if (sgv.syms[i].flags & (SYMFLAG_REGISTER|SYMFLAG_REGREL|SYMFLAG_LOCAL|SYMFLAG_THUNK)) continue; if (lineno == -1) { struct dbg_type type; ULONG64 addr; type.module = sgv.syms[i].lvalue.type.module; type.id = sgv.syms[i].sym_info; if (bp_disp && symbol_get_debug_start(&type, &addr)) sgv.syms[i].lvalue.addr.Offset = addr; } else { DWORD disp; IMAGEHLP_LINE il; BOOL found = FALSE; il.SizeOfStruct = sizeof(il); SymGetLineFromAddr(dbg_curr_process->handle, (DWORD)memory_to_linear_addr(&sgv.syms[i].lvalue.addr), &disp, &il); do { if (lineno == il.LineNumber) { sgv.syms[i].lvalue.addr.Offset = il.Address; found = TRUE; break; } } while (SymGetLineNext(dbg_curr_process->handle, &il)); if (!found) WINE_FIXME("No line (%d) found for %s (setting to symbol start)\n", lineno, name); } } i = 0; if (dbg_interactiveP) { if (sgv.num - sgv.num_thunks > 1 || /* many symbols non thunks (and showing only non thunks) */ (sgv.num > 1 && DBG_IVAR(AlwaysShowThunks)) || /* many symbols (showing symbols & thunks) */ (sgv.num == sgv.num_thunks && sgv.num_thunks > 1)) { dbg_printf("Many symbols with name '%s', " "choose the one you want (<cr> to abort):\n", name); for (i = 0; i < sgv.num; i++) { if (sgv.num - sgv.num_thunks > 1 && (sgv.syms[i].flags & SYMFLAG_THUNK) && !DBG_IVAR(AlwaysShowThunks)) continue; dbg_printf("[%d]: ", i + 1); if (sgv.syms[i].flags & SYMFLAG_LOCAL) { dbg_printf("%s %sof %s\n", sgv.syms[i].flags & SYMFLAG_PARAMETER ? "Parameter" : "Local variable", sgv.syms[i].flags & (SYMFLAG_REGISTER|SYMFLAG_REGREL) ? "(in a register) " : "", name); } else if (sgv.syms[i].flags & SYMFLAG_THUNK) { print_address(&sgv.syms[i].lvalue.addr, TRUE); /* FIXME: should display where the thunks points to */ dbg_printf(" thunk %s\n", name); } else { print_address(&sgv.syms[i].lvalue.addr, TRUE); dbg_printf("\n"); } } do { i = 0; if (input_read_line("=> ", buffer, sizeof(buffer))) { if (buffer[0] == '\0') return sglv_aborted; i = atoi(buffer); if (i < 1 || i > sgv.num) dbg_printf("Invalid choice %d\n", i); } else return sglv_aborted; } while (i < 1 || i > sgv.num); /* The array is 0-based, but the choices are 1..n, * so we have to subtract one before returning. */ i--; } } else { /* FIXME: could display the list of non-picked up symbols */ if (sgv.num > 1) dbg_printf("More than one symbol named %s, picking the first one\n", name); } *rtn = sgv.syms[i].lvalue; return sglv_found; }
HRESULT ParseImageSymbols( _In_ HMODULE hmod, _Inout_ PEXPORT_DATA pExportData) { DWORD64 dwModuleBase; ULONG i; IMAGEHLP_STACK_FRAME StackFrame; SYMINFO_EX sym; dwModuleBase = (DWORD_PTR)hmod; /* Loop through all exports */ for (i = 0; i < pExportData->cNumberOfExports; i++) { PEXPORT pExport = &pExportData->aExports[i]; ULONG64 ullFunction = dwModuleBase + pExportData->aExports[i].ulRva; ULONG64 ullDisplacement; /* Check if this is a forwarder */ if (pExport->pszForwarder != NULL) { /* Load the module and get the function address */ ullFunction = GetFunctionFromForwarder(pExport->pszForwarder); if (ullFunction == 0) { printf("Failed to get function for forwarder '%s'. Skipping.\n", pExport->pszForwarder); continue; } } RtlZeroMemory(&sym, sizeof(sym)); sym.si.SizeOfStruct = sizeof(SYMBOL_INFO); sym.si.MaxNameLen = MAX_SYMBOL_NAME; /* Try to find the symbol */ if (!SymFromAddr(ghProcess, ullFunction, &ullDisplacement, &sym.si)) { error("Error: SymFromAddr() failed."); continue; } /* Get the symbol name */ pExport->pszSymbol = _strdup(sym.si.Name); /* Check if it is a function */ if (sym.si.Tag == SymTagFunction) { /* Get the calling convention */ if (!SymGetTypeInfo(ghProcess, dwModuleBase, sym.si.TypeIndex, TI_GET_CALLING_CONVENTION, &pExport->dwCallingConvention)) { /* Fall back to __stdcall */ pExport->dwCallingConvention = CV_CALL_NEAR_STD; } /* Set the context to the function address */ RtlZeroMemory(&StackFrame, sizeof(StackFrame)); StackFrame.InstructionOffset = ullFunction; if (!SymSetContext(ghProcess, &StackFrame, NULL)) { error("SymSetContext failed for i = %u.", i); continue; } /* Enumerate all symbols for this function */ if (!SymEnumSymbols(ghProcess, 0, // use SymSetContext NULL, EnumParametersCallback, pExport)) { error("SymEnumSymbols failed for i = %u.", i); continue; } } else if (sym.si.Tag == SymTagPublicSymbol) { pExport->dwCallingConvention = CV_CALL_NEAR_STD; } else if (sym.si.Tag == SymTagData) { pExport->fData = TRUE; } } return S_OK; }
/*********************************************************************** * symbol_get_line * * Find the symbol nearest to a given address. * Returns sourcefile name and line number in a format that the listing * handler can deal with. */ BOOL symbol_get_line(const char* filename, const char* name, IMAGEHLP_LINE* line) { struct sgv_data sgv; char buffer[512]; DWORD opt, disp, linear; unsigned i, found = FALSE; IMAGEHLP_LINE il; sgv.num = 0; sgv.num_thunks = 0; sgv.name = &buffer[2]; sgv.do_thunks = FALSE; buffer[0] = '*'; buffer[1] = '!'; strcpy(&buffer[2], name); /* this is a wine specific options to return also ELF modules in the * enumeration */ SymSetOptions((opt = SymGetOptions()) | 0x40000000); if (!SymEnumSymbols(dbg_curr_process->handle, 0, buffer, sgv_cb, (void*)&sgv)) { SymSetOptions(opt); return FALSE; } if (!sgv.num && (name[0] != '_')) { buffer[2] = '_'; strcpy(&buffer[3], name); if (!SymEnumSymbols(dbg_curr_process->handle, 0, buffer, sgv_cb, (void*)&sgv)) { SymSetOptions(opt); return FALSE; } } SymSetOptions(opt); for (i = 0; i < sgv.num; i++) { linear = (DWORD)memory_to_linear_addr(&sgv.syms[i].lvalue.addr); il.SizeOfStruct = sizeof(il); if (!SymGetLineFromAddr(dbg_curr_process->handle, linear, &disp, &il)) continue; if (filename && strcmp(line->FileName, filename)) continue; if (found) { WINE_FIXME("Several found, returning first (may not be what you want)...\n"); break; } found = TRUE; *line = il; } if (!found) { if (filename) dbg_printf("No such function %s in %s\n", name, filename); else dbg_printf("No such function %s\n", name); return FALSE; } return TRUE; }
static VOID TestTraceKernel() { ULONG BufferCount; ULONG BufferSize; PROC_SET Set; DWORD_PTR FailedProc; UINT Tracepoints, Count; UINT EnumCount; JPFSV_TRACEPOINT Tracepnt; HRESULT Hr; JPFSV_HANDLE KernelCtx; JPFSV_TRACING_TYPE TracingType; ULONG TypesTested = 0; TEST_OK( CdiagCreateSession( NULL, NULL, &DiagSession ) ); for ( TracingType = JpfsvTracingTypeDefault; TracingType <= JpfsvTracingTypeMax; TracingType++ ) { UINT Index; BOOL Instrumentable; WCHAR LogFile[ MAX_PATH ]; UINT PaddingSize; TEST_OK( StringCchPrintf( LogFile, _countof( LogFile ), L"__kern%d.log", TracingType ) ); // // Start a trace. // KernelCtx = NULL; Hr = JpfsvLoadContext( JPFSV_KERNEL, NULL, &KernelCtx ); if ( Hr == JPFSV_E_UNSUP_ON_WOW64 ) { CFIX_INCONCLUSIVE( L"Not supported on WOW64" ); return; } TEST_OK( Hr ); TEST( JPFSV_E_NO_TRACESESSION == JpfsvGetTracepointContext( KernelCtx, 0xF00, &Tracepnt ) ); DeleteFile( LogFile ); if ( TracingType != JpfsvTracingTypeWmk ) { TEST( E_INVALIDARG == JpfsvAttachContext( KernelCtx, TracingType, NULL ) ); Hr = JpfsvAttachContext( KernelCtx, TracingType, LogFile ); } else { TEST( E_INVALIDARG == JpfsvAttachContext( KernelCtx, TracingType, LogFile ) ); Hr = JpfsvAttachContext( KernelCtx, TracingType, NULL ); } if ( Hr == JPFSV_E_UNSUPPORTED_TRACING_TYPE || Hr == HRESULT_FROM_NT( 0xC0049300L ) ) // STATUS_KFBT_KERNEL_NOT_SUPPORTED { continue; } TEST_OK( Hr ); if ( TracingType == JpfsvTracingTypeWmk ) { BufferCount = 0; BufferSize = 0; } else { BufferCount = 5; BufferSize = 1024; } // // Instrument some procedures. // Set.Count = 0; Set.ContextHandle = KernelCtx; Set.Process = JpfsvGetProcessHandleContext( KernelCtx ); TEST( Set.Process ); // // Not all patchable... // TEST( SymEnumSymbols( Set.Process, 0, L"tcpip!*", AddProcedureSymCallback, &Set ) ); TEST_OK( JpfsvStartTraceContext( KernelCtx, BufferCount, BufferSize, DiagSession ) ); TEST( E_UNEXPECTED == JpfsvStartTraceContext( KernelCtx, BufferCount, BufferSize, DiagSession ) ); TEST( Set.Count > 0 ); TEST_OK( JpfsvCountTracePointsContext( KernelCtx, &Count ) ); TEST( 0 == Count ); TEST_STATUS( ( ULONG ) HRESULT_FROM_NT( STATUS_FBT_PROC_NOT_PATCHABLE ), JpfsvSetTracePointsContext( KernelCtx, JpfsvAddTracepoint, Set.Count, Set.Procedures, &FailedProc ) ); // // Instrumentable... // Set.Count = 0; Set.ContextHandle = KernelCtx; Set.Process = JpfsvGetProcessHandleContext( KernelCtx ); TEST( SymEnumSymbols( Set.Process, 0, IsVistaOrLater() ? L"tcpip!IPReg*" : L"tcpip!IPRc*", AddProcedureSymCallback, &Set ) ); TEST( Set.Count > 0 ); for ( Index = 0; Index < Set.Count; Index++ ) { TEST_OK( JpfsvCheckProcedureInstrumentability( KernelCtx, Set.Procedures[ Index ], &Instrumentable, &PaddingSize ) ); TEST( Instrumentable ); TEST( PaddingSize == 5 ); } // // Not instrumentable... // Set.Count = 0; Set.ContextHandle = KernelCtx; Set.Process = JpfsvGetProcessHandleContext( KernelCtx ); TEST( SymEnumSymbols( Set.Process, 0, IsVistaOrLater() ? L"tcpip!__report_gsfailure" : L"tcpip!_wcsicmp", AddProcedureSymCallback, &Set ) ); TEST( Set.Count > 0 ); TEST_OK( JpfsvCheckProcedureInstrumentability( KernelCtx, Set.Procedures[ 0 ], &Instrumentable, &PaddingSize ) ); TEST( ! Instrumentable ); TEST( PaddingSize == 0 ); // // All patchable... // Set.Count = 0; Set.ContextHandle = KernelCtx; Set.Process = JpfsvGetProcessHandleContext( KernelCtx ); TEST( Set.Process ); TEST( SymEnumSymbols( Set.Process, 0, IsVistaOrLater() ? L"tcpip!IPReg*" : L"tcpip!IPRc*", AddProcedureSymCallback, &Set ) ); TEST( Set.Count >= 3 ); TEST_OK( JpfsvSetTracePointsContext( KernelCtx, JpfsvAddTracepoint, Set.Count, Set.Procedures, &FailedProc ) ); // again - should be a noop. TEST_OK( JpfsvSetTracePointsContext( KernelCtx, JpfsvAddTracepoint, Set.Count, Set.Procedures, &FailedProc ) ); TEST( FailedProc == 0 ); TEST_OK( JpfsvCountTracePointsContext( KernelCtx, &Tracepoints ) ); TEST( Tracepoints > Set.Count / 2 ); // Duplicate-cleaned! TEST( Tracepoints <= Set.Count ); TEST_OK( JpfsvGetTracepointContext( KernelCtx, Set.Procedures[ 0 ], &Tracepnt ) ); TEST( Tracepnt.Procedure == Set.Procedures[ 0 ] ); TEST( wcslen( Tracepnt.SymbolName ) ); TEST( wcslen( Tracepnt.ModuleName ) ); TEST( JPFSV_E_TRACEPOINT_NOT_FOUND == JpfsvGetTracepointContext( KernelCtx, 0xBA2, &Tracepnt ) ); // // Count enum callbacks. // EnumCount = 0; TEST_OK( JpfsvEnumTracePointsContext( KernelCtx, CountTracepointsCallback, &EnumCount ) ); TEST( EnumCount == Tracepoints ); // // Stop while tracing active -> implicitly revoke all tracepoints. // TEST_OK( JpfsvStopTraceContext( KernelCtx, TRUE ) ); TEST_OK( JpfsvCountTracePointsContext( KernelCtx, &Count ) ); TEST( 0 == Count ); // // Trace again. // DeleteFile( LogFile ); TEST_OK( JpfsvStartTraceContext( KernelCtx, BufferCount, BufferSize, DiagSession ) ); TEST_OK( JpfsvSetTracePointsContext( KernelCtx, JpfsvAddTracepoint, Set.Count, Set.Procedures, &FailedProc ) ); TEST( FailedProc == 0 ); TEST_OK( JpfsvCountTracePointsContext( KernelCtx, &Count ) ); TEST( Tracepoints == Count ); // // Clean shutdown. // TEST_OK( JpfsvSetTracePointsContext( KernelCtx, JpfsvRemoveTracepoint, Set.Count, Set.Procedures, &FailedProc ) ); TEST( FailedProc == 0 ); TEST_OK( JpfsvCountTracePointsContext( KernelCtx, &Count ) ); TEST( 0 == Count ); TEST_OK( JpfsvStopTraceContext( KernelCtx, TRUE ) ); TEST_OK( DetachContextSafe( KernelCtx ) ); TEST_OK( JpfsvUnloadContext( KernelCtx ) ); TypesTested++; } TEST_OK( CdiagDereferenceSession( DiagSession ) ); if ( TypesTested == 0 ) { CFIX_INCONCLUSIVE( L"No TracingTypes supported" ); } }
static VOID TestDyingPeerWithTracing() { PROCESS_INFORMATION pi; JPFSV_HANDLE NpCtx; PROC_SET Set; DWORD_PTR FailedProc; TEST_OK( CdiagCreateSession( NULL, NULL, &DiagSession ) ); // // Launch notepad. // LaunchNotepad( &pi ); // // Give notepad some time to start... // Sleep( 1000 ); TEST_OK( JpfsvLoadContext( pi.dwProcessId, NULL, &NpCtx ) ); TEST_OK( JpfsvAttachContext( NpCtx, JpfsvTracingTypeDefault, NULL ) ); Set.Count = 0; Set.ContextHandle = NpCtx; Set.Process = JpfsvGetProcessHandleContext( NpCtx ); TEST( Set.Process ); TEST( SymEnumSymbols( Set.Process, 0, L"user32!*", AddProcedureSymCallback, &Set ) ); // // Instrument some procedures // TEST_OK( JpfsvStartTraceContext( NpCtx, 5, 1024, DiagSession ) ); TEST( Set.Count > 0 ); TEST_OK( JpfsvSetTracePointsContext( NpCtx, JpfsvAddTracepoint, Set.Count, Set.Procedures, &FailedProc ) ); Sleep( 1000 ); // // Kill notepad - the dying peer-mechanism should // kick in *on the read thread*. // TEST( TerminateProcess( pi.hProcess, 0 ) ); CloseHandle( pi.hProcess ); CloseHandle( pi.hThread ); TEST( JPFSV_E_PEER_DIED == JpfsvStopTraceContext( NpCtx, TRUE ) ); TEST_OK( DetachContextSafe( NpCtx ) ); TEST_OK( JpfsvUnloadContext( NpCtx ) ); TEST_OK( CdiagDereferenceSession( DiagSession ) ); // // Wait i.o. not to confuse further tests with dying process. // Sleep( 1000 ); }
void write_stack_trace(PCONTEXT pContext, TextOutputStream& outputStream) { HANDLE m_hProcess = GetCurrentProcess(); DWORD dwMachineType = 0; CONTEXT context = *pContext; // Could use SymSetOptions here to add the SYMOPT_DEFERRED_LOADS flag if ( !SymInitialize( m_hProcess, (PSTR)environment_get_app_path(), TRUE ) ) { return; } STACKFRAME sf; memset( &sf, 0, sizeof(sf) ); #ifdef _M_IX86 // Initialize the STACKFRAME structure for the first call. This is only // necessary for Intel CPUs, and isn't mentioned in the documentation. sf.AddrPC.Offset = context.Eip; sf.AddrPC.Mode = AddrModeFlat; sf.AddrStack.Offset = context.Esp; sf.AddrStack.Mode = AddrModeFlat; sf.AddrFrame.Offset = context.Ebp; sf.AddrFrame.Mode = AddrModeFlat; dwMachineType = IMAGE_FILE_MACHINE_I386; #endif while ( 1 ) { // Get the next stack frame if ( ! StackWalk( dwMachineType, m_hProcess, GetCurrentThread(), &sf, &context, 0, SymFunctionTableAccess, SymGetModuleBase, 0 ) ) break; if ( 0 == sf.AddrFrame.Offset ) // Basic sanity check to make sure break; // the frame is OK. Bail if not. // Get the name of the function for this stack frame entry BYTE symbolBuffer[ sizeof(SYMBOL_INFO) + MAX_SYM_NAME ]; PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)symbolBuffer; pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO); pSymbol->MaxNameLen = MAX_SYM_NAME; DWORD64 symDisplacement = 0; // Displacement of the input address, // relative to the start of the symbol IMAGEHLP_MODULE module = { sizeof(IMAGEHLP_MODULE) }; if(SymGetModuleInfo(m_hProcess, sf.AddrPC.Offset, &module)) { outputStream << module.ModuleName << "!"; if ( SymFromAddr(m_hProcess, sf.AddrPC.Offset, &symDisplacement, pSymbol)) { char undecoratedName[MAX_SYM_NAME]; UnDecorateSymbolName(pSymbol->Name, undecoratedName, MAX_SYM_NAME, UNDNAME_COMPLETE); outputStream << undecoratedName; outputStream << "("; // Use SymSetContext to get just the locals/params for this frame IMAGEHLP_STACK_FRAME imagehlpStackFrame; imagehlpStackFrame.InstructionOffset = sf.AddrPC.Offset; SymSetContext( m_hProcess, &imagehlpStackFrame, 0 ); // Enumerate the locals/parameters EnumerateSymbolsContext context(sf, outputStream); SymEnumSymbols( m_hProcess, 0, 0, EnumerateSymbolsCallback, &context ); outputStream << ")"; outputStream << " + " << Offset(reinterpret_cast<void*>(symDisplacement)); // Get the source line for this stack frame entry IMAGEHLP_LINE lineInfo = { sizeof(IMAGEHLP_LINE) }; DWORD dwLineDisplacement; if ( SymGetLineFromAddr( m_hProcess, sf.AddrPC.Offset, &dwLineDisplacement, &lineInfo ) ) { outputStream << " " << lineInfo.FileName << " line " << Unsigned(lineInfo.LineNumber); } } else { outputStream << Address(reinterpret_cast<void*>(sf.AddrPC.Offset)); } } outputStream << "\n"; } SymCleanup(m_hProcess); return; }
int dbg_help_client_t::init(char* path) { DWORD64 dwBaseAddr=0; int chars; char exe_path[MAX_PATH]; chars = GetModuleFileName(NULL, exe_path, MAX_PATH); if (chars == 0) { fprintf(stderr,"Could not find base path for XED executable\n"); fflush(stderr); exit(1); } //fprintf(stderr,"EXE PATH %s\n", exe_path); char* dir = find_base_path(exe_path); //fprintf(stderr,"DIR %s\n", dir); char* dbghelp = append3(dir,"\\","dbghelp.dll"); //fprintf(stderr,"DBGHLP %s\n", dbghelp); if (_access_s(dbghelp,4) != 0) { //fprintf(stderr, // "WARNING: Could not find dbghelp.dll in xed.exe directory\n"); //fflush(stderr); return 0; } //fprintf(stderr,"FOUND DBGHELP\n"); if (validate_version(dbghelp)) { fprintf(stderr, "WARNING: dbghelp.dll version is too old\n"); fflush(stderr); return 0; } //FIXME: Add a version check for the dll ( ImagehlpApiVersion is NOT //the right thing) SymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS); hProcess = GetCurrentProcess(); if (SymInitialize(hProcess, NULL, FALSE)) { // nothing } else { error = GetLastError(); fprintf(stderr,"SymInitialize returned error : %d 0x%x\n", error, error); fflush(stderr); return 0; } actual_base = SymLoadModuleEx(hProcess, NULL, path, NULL, dwBaseAddr, 0, NULL, 0); if (actual_base) { // nothing } else { error = GetLastError(); fprintf(stderr,"SymLoadModuleEx returned error : %d 0x%x\n", error, error); fflush(stderr); return 0; } if (SymEnumerateModules64(hProcess, (PSYM_ENUMMODULES_CALLBACK64)enum_modules, this)) { // nothing } else { error = GetLastError(); fprintf(stderr,"SymEnumerateModules64 returned error : %d 0x%x\n", error, error); fflush(stderr); return 0; } if (SymEnumSymbols(hProcess, actual_base, 0, enum_sym, this)) { // nothing } else { error = GetLastError(); fprintf(stderr,"SymEnumSymbols failed: %d 0x%x\n", error, error); fflush(stderr); return 0; } make_symbol_vector(&sym_tab); initialized = true; return 1; }
/*********************************************************************** * symbol_get_lvalue * * Get the address of a named symbol. * Return values: * sglv_found: if the symbol is found * sglv_unknown: if the symbol isn't found * sglv_aborted: some error occurred (likely, many symbols of same name exist, * and user didn't pick one of them) */ enum sym_get_lval symbol_get_lvalue(const char* name, const int lineno, struct dbg_lvalue* rtn, BOOL bp_disp) { struct sgv_data sgv; int i; char buffer[512]; DWORD opt; IMAGEHLP_STACK_FRAME ihsf; if (strlen(name) + 4 > sizeof(buffer)) { WINE_WARN("Too long symbol (%s)\n", name); return sglv_unknown; } sgv.num = 0; sgv.num_thunks = 0; sgv.name = &buffer[2]; sgv.do_thunks = DBG_IVAR(AlwaysShowThunks); if (strchr(name, '!')) { strcpy(buffer, name); } else { buffer[0] = '*'; buffer[1] = '!'; strcpy(&buffer[2], name); } /* this is a wine specific options to return also ELF modules in the * enumeration */ SymSetOptions((opt = SymGetOptions()) | 0x40000000); SymEnumSymbols(dbg_curr_process->handle, 0, buffer, sgv_cb, (void*)&sgv); if (!sgv.num) { const char* ptr = strchr(name, '!'); if ((ptr && ptr[1] != '_') || (!ptr && *name != '_')) { if (ptr) { int offset = ptr - name; memcpy(buffer, name, offset + 1); buffer[offset + 1] = '_'; strcpy(&buffer[offset + 2], ptr + 1); } else { buffer[0] = '*'; buffer[1] = '!'; buffer[2] = '_'; strcpy(&buffer[3], name); } SymEnumSymbols(dbg_curr_process->handle, 0, buffer, sgv_cb, (void*)&sgv); } } SymSetOptions(opt); /* now grab local symbols */ if (stack_get_current_frame(&ihsf) && sgv.num < NUMDBGV) { sgv.frame_offset = ihsf.FrameOffset; SymEnumSymbols(dbg_curr_process->handle, 0, name, sgv_cb, (void*)&sgv); } if (!sgv.num) { dbg_printf("No symbols found for %s\n", name); return sglv_unknown; } /* recompute potential offsets for functions (linenumber, skip prolog) */ for (i = 0; i < sgv.num; i++) { if (sgv.syms[i].flags & (SYMFLAG_REGISTER|SYMFLAG_REGREL|SYMFLAG_LOCAL|SYMFLAG_THUNK)) continue; if (lineno == -1) { struct dbg_type type; ULONG64 addr; type.module = sgv.syms[i].lvalue.type.module; type.id = sgv.syms[i].sym_info; if (bp_disp && symbol_get_debug_start(&type, &addr)) sgv.syms[i].lvalue.addr.Offset = addr; } else { DWORD disp; IMAGEHLP_LINE64 il; BOOL found = FALSE; il.SizeOfStruct = sizeof(il); SymGetLineFromAddr64(dbg_curr_process->handle, (DWORD_PTR)memory_to_linear_addr(&sgv.syms[i].lvalue.addr), &disp, &il); do { if (lineno == il.LineNumber) { sgv.syms[i].lvalue.addr.Offset = il.Address; found = TRUE; break; } } while (SymGetLineNext64(dbg_curr_process->handle, &il)); if (!found) WINE_FIXME("No line (%d) found for %s (setting to symbol start)\n", lineno, name); } } if (sgv.num - sgv.num_thunks > 1 || /* many symbols non thunks (and showing only non thunks) */ (sgv.num > 1 && DBG_IVAR(AlwaysShowThunks)) || /* many symbols (showing symbols & thunks) */ (sgv.num == sgv.num_thunks && sgv.num_thunks > 1)) { return symbol_current_picker(name, &sgv, rtn); } /* first symbol is the one we want: * - only one symbol found, * - or many symbols but only one non thunk when AlwaysShowThunks is FALSE */ *rtn = sgv.syms[0].lvalue; return sglv_found; }
static VOID TestTraceNotepad() { PROCESS_INFORMATION pi; JPFSV_HANDLE NpCtx; PROC_SET Set; DWORD_PTR FailedProc; UINT Tracepoints, Count; UINT EnumCount = 0; JPFSV_TRACEPOINT Tracepnt; TEST_OK( CdiagCreateSession( NULL, NULL, &DiagSession ) ); // // Launch notepad. // LaunchNotepad( &pi ); // // Give notepad some time to start... // Sleep( 1000 ); // // Start a trace. // TEST_OK( JpfsvLoadContext( pi.dwProcessId, NULL, &NpCtx ) ); TEST( JPFSV_E_NO_TRACESESSION == JpfsvGetTracepointContext( NpCtx, 0xF00, &Tracepnt ) ); TEST_OK( JpfsvAttachContext( NpCtx, JpfsvTracingTypeDefault, NULL ) ); // // Instrument some procedures. // Set.Count = 0; Set.ContextHandle = NpCtx; Set.Process = JpfsvGetProcessHandleContext( NpCtx ); TEST( Set.Process ); TEST( SymEnumSymbols( Set.Process, 0, L"user32!*", AddProcedureSymCallback, &Set ) ); TEST_OK( JpfsvStartTraceContext( NpCtx, 5, 1024, DiagSession ) ); TEST( E_UNEXPECTED == JpfsvStartTraceContext( NpCtx, 5, 1024, DiagSession ) ); TEST( Set.Count > 0 ); TEST_OK( JpfsvCountTracePointsContext( NpCtx, &Count ) ); TEST( 0 == Count ); TEST_OK( JpfsvSetTracePointsContext( NpCtx, JpfsvAddTracepoint, Set.Count, Set.Procedures, &FailedProc ) ); // again - should be a noop. TEST_OK( JpfsvSetTracePointsContext( NpCtx, JpfsvAddTracepoint, Set.Count, Set.Procedures, &FailedProc ) ); TEST( FailedProc == 0 ); TEST_OK( JpfsvCountTracePointsContext( NpCtx, &Tracepoints ) ); TEST( Tracepoints > Set.Count / 2 ); // Duplicate-cleaned! TEST( Tracepoints <= Set.Count ); TEST_OK( JpfsvGetTracepointContext( NpCtx, Set.Procedures[ 0 ], &Tracepnt ) ); TEST( Tracepnt.Procedure == Set.Procedures[ 0 ] ); TEST( wcslen( Tracepnt.SymbolName ) ); TEST( wcslen( Tracepnt.ModuleName ) ); TEST( JPFSV_E_TRACEPOINT_NOT_FOUND == JpfsvGetTracepointContext( NpCtx, 0xBA2, &Tracepnt ) ); // // Count enum callbacks. // TEST_OK( JpfsvEnumTracePointsContext( NpCtx, CountTracepointsCallback, &EnumCount ) ); TEST( EnumCount == Tracepoints ); // // Pump a little... // Sleep( 2000 ); // // Stop while tracing active -> implicitly revoke all tracepoints. // TEST_OK( JpfsvStopTraceContext( NpCtx, TRUE ) ); TEST_OK( JpfsvCountTracePointsContext( NpCtx, &Count ) ); TEST( 0 == Count ); // // Trace again. // TEST_OK( JpfsvStartTraceContext( NpCtx, 5, 1024, DiagSession ) ); TEST_OK( JpfsvSetTracePointsContext( NpCtx, JpfsvAddTracepoint, Set.Count, Set.Procedures, &FailedProc ) ); TEST( FailedProc == 0 ); TEST_OK( JpfsvCountTracePointsContext( NpCtx, &Count ) ); TEST( Tracepoints == Count ); // // Pump a little... // Sleep( 2000 ); // // Clean shutdown. // TEST_OK( JpfsvSetTracePointsContext( NpCtx, JpfsvRemoveTracepoint, Set.Count, Set.Procedures, &FailedProc ) ); TEST( FailedProc == 0 ); TEST_OK( JpfsvCountTracePointsContext( NpCtx, &Count ) ); TEST( 0 == Count ); TEST_OK( JpfsvStopTraceContext( NpCtx, TRUE ) ); TEST_OK( DetachContextSafe( NpCtx ) ); TEST_OK( JpfsvUnloadContext( NpCtx ) ); TEST_OK( CdiagDereferenceSession( DiagSession ) ); // // Kill notepad. // TEST( TerminateProcess( pi.hProcess, 0 ) ); CloseHandle( pi.hProcess ); CloseHandle( pi.hThread ); // // Wait i.o. not to confuse further tests with dying process. // Sleep( 1000 ); }
ULONG getSymbols() { CString FilePathName; PCSTR path; DWORD error; DWORD64 dw64Base; DWORD dwFileSize; g_CountOfFunFound = 0; dw64Base = getNtBase(); if (dw64Base==0) { ::MessageBox(NULL,"Get base 0",NULL,NULL); return 0 ; } char szSystemDir[1024]={0}; GetSystemDirectory(szSystemDir, sizeof(szSystemDir)); FilePathName = szSystemDir; FilePathName = FilePathName+"\\"+PathFindFileName(osname); path=FilePathName; //记得要带上symsrv.dll和dbghelp.dll char *pSymPath = "srv*C:\\winddk\\symbolsl*http://msdl.microsoft.com/download/symbols"; myprint("retriving symbols for %s,symbols store in %s\r\n",path, pSymPath); SymCleanup(GetCurrentProcess()); if (SymInitialize(GetCurrentProcess(), pSymPath, TRUE)) { // SymInitialize returned success } else { // SymInitialize failed error = GetLastError(); myprint("SymInitialize returned error : %d\n", error); return 0; } DWORD err=0; // get the file size HANDLE hFile = CreateFile( FilePathName, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL ); if( INVALID_HANDLE_VALUE == hFile ) { err = GetLastError(); ::MessageBox(NULL,"out",NULL,NULL); return false; } if( INVALID_FILE_SIZE == ( dwFileSize = GetFileSize(hFile, NULL)) ) { } CloseHandle(hFile); DWORD64 dw64ModAddress=SymLoadModule64( GetCurrentProcess(),NULL, (char*)path,NULL,dw64Base,dwFileSize); if(dw64ModAddress==0) { error = GetLastError(); myprint("SymLoadModule64 returned error : %d\n", error); return 0; } if(!SymEnumSymbols( GetCurrentProcess(), dw64ModAddress, NULL, // Null point out that list all symbols SymEnumSymbolsProc, NULL)) { //_tprintf( _T("Failed when SymEnumSymbols(): %d \n"), GetLastError() ); return 0; } myprint("g_CountOfFunFound %d\r\n", g_CountOfFunFound); bool bRetSym = (g_CountOfFunFound>sizeof(dync_funs)/sizeof(dync_funs[0])); return bRetSym?dw64Base:0; }