Пример #1
0
bool CSymbolEngine::UnloadModuleSymbols( DWORD64 ModBase )
{
	// Check preconditions 

	if( m_hProcess == NULL )
	{
		_ASSERTE( !_T("Symbol engine is not yet initialized.") );
		m_LastError = ERROR_INVALID_FUNCTION;
		return false;
	}

	if( ModBase == 0 )
	{
		_ASSERTE( !_T("Module base address is null.") );
		m_LastError = ERROR_INVALID_PARAMETER;
		return false;
	}


	// Unload symbols

	if( !SymUnloadModule64( m_hProcess, ModBase ) )
	{
		m_LastError = GetLastError();
		_ASSERTE( !_T("SymUnloadModule64() failed.") );
		return false;
	}


	// Complete 

	return true;
}
Пример #2
0
void InitializeSymbolLookup()
{
	static bool bIsInitialized = false;

	if( bIsInitialized )
	{
		return;
	}

	bIsInitialized = true;

	hApplicationProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, ApplicationProcessId);
	if( hApplicationProcess == NULL )
	{
		DWORD error = GetLastError();
		DebugLog("OpenProcess failed: error = %d", error);
		return;
	}

	DWORD SymOpts = 0;

	SymOpts |= SYMOPT_ALLOW_ABSOLUTE_SYMBOLS;
//	SymOpts |= SYMOPT_CASE_INSENSITIVE;
	SymOpts |= SYMOPT_DEBUG;
	SymOpts |= SYMOPT_DEFERRED_LOADS;
	SymOpts |= SYMOPT_EXACT_SYMBOLS;
	SymOpts |= SYMOPT_FAIL_CRITICAL_ERRORS;
	SymOpts |= SYMOPT_LOAD_LINES;
	SymOpts |= SYMOPT_UNDNAME;

	SymSetOptions(SymOpts);

	if( !SymInitialize(hApplicationProcess, NULL, TRUE) )  // defer the loading of process modules
	{
		DWORD error = GetLastError();
		DebugLog("SymInitialize failed: error = %d", error);
		return;
	}

	LoadModules();

	DWORD FileSize = 0;
	DWORD64 dwBaseAddress = 0;

	DWORD64 result = SymLoadModuleExW(hApplicationProcess, NULL, app_filename, NULL, dwBaseAddress, FileSize, NULL, 0);

	if( result == 0 )
	{
		DWORD error = GetLastError();
		DebugLog("SymLoadModuleEx failed: error = %d", error);

		SymUnloadModule64(hApplicationProcess, dwBaseAddress);

		return;
	}
}
Пример #3
0
void Pdb::UnloadModuleSymbols()
{
	for(int i = 0; i < module.GetCount(); i++) {
		ModuleInfo& f = module[i];
		if(f.symbols) {
			SymUnloadModule64(hProcess, f.base);
			LLOG("Unloaded symbols for " << f.path << ' ' << Hex(module[i].base) << '/' << hProcess);
		}
	}
}
Пример #4
0
//--------------------------------------------------------------------------------------
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;
}
Пример #5
0
/**
 * Interface used by PDMR3LdrRelocate for telling us that a GC module has been relocated.
 *
 * @param   pVM             The VM handle.
 * @param   OldImageBase    The old image base.
 * @param   NewImageBase    The new image base.
 * @param   cbImage         The image size.
 * @param   pszFilename     The image filename.
 * @param   pszName         The module name.
 */
VMMR3DECL(void) DBGFR3ModuleRelocate(PVM pVM, RTGCUINTPTR OldImageBase, RTGCUINTPTR NewImageBase, RTGCUINTPTR cbImage,
                                      const char *pszFilename, const char *pszName)
{
#ifdef HAVE_DBGHELP
    if (pVM->dbgf.s.fSymInited)
    {
        if (!SymUnloadModule64(pVM, OldImageBase))
            Log(("SymUnloadModule64(,%RGv) failed, lasterr=%d\n", OldImageBase, GetLastError()));

        DWORD ImageSize = (DWORD)cbImage; Assert(ImageSize == cbImage);
        DWORD64 LoadedImageBase = SymLoadModule64(pVM, NULL, (char *)(void *)pszFilename, (char *)(void *)pszName, NewImageBase, ImageSize);
        if (!LoadedImageBase)
            Log(("SymLoadModule64(,,%s,,) -> lasterr=%d (relocate)\n", pszFilename, GetLastError()));
        else
            Log(("Reloaded debuginfo for %s - %s %llx\n", pszName, pszFilename, LoadedImageBase));
    }
#else

#endif
}
Пример #6
0
bool CATDbgHelper::Close( void )
{
	LOG_FUNC_ENTRY("CATDbgHelper::Close");
	if ( ! SymUnloadModule64( GetCurrentProcess(), m_BaseAddress ) )
	{
		LOG_STRING("Dbghelp:Module unload failed.");
	}
	CDBGHELPER_CLIENTS--;
	if ( CDBGHELPER_OPEN && CDBGHELPER_CLIENTS == 0)
	{
		// Cleanup dbghelper.
		if ( ! SymCleanup( GetCurrentProcess() ) )
		{
			LOG_STRING("dbghelper cleanup failed.");
			return false;
		}
		LOG_STRING("dbghelper closed.");
		// Set state not opened.
		CDBGHELPER_OPEN = false;
	}
	return true;
}
Пример #7
0
void *Ploopgrab(LPVOID args)
{
    DEBUG_EVENT  dbg;
    DWORD cont = DBG_CONTINUE, size = 0;
    TCHAR pszFilename[MAX_PATH+1];
    DWORD64 mod;
    struct proc_uc *tmp = args;
    struct ps_prochandle *P = tmp->ps;
    int first_execp = 0;
    BOOL wow = 0;
    char *s;
    DWORD Options = SymGetOptions();

    if (DebugActiveProcess(P->pid) == 0) {
        dprintf( "failed to debug process (%d): %d\n", P->pid, GetLastError() );
        pthread_mutex_lock(&P->mutex);
        P->status = PS_STOP;
        P->flags = CREATE_FAILED;
        if (P->status == PS_STOP)
            pthread_cond_signal(&P->cond);
        pthread_mutex_unlock(&P->mutex);
        return NULL;
    }

    DebugSetProcessKillOnExit(FALSE);

    P->wstat = 0;
    P->exitcode = 0;
    P->event = CreateEvent(NULL,FALSE,FALSE,NULL);
    P->dll_load_order = 1;
    SymSetOptions(Options|SYMOPT_INCLUDE_32BIT_MODULES|SYMOPT_DEFERRED_LOADS|SYMOPT_DEBUG);

    while (1) {
        if (WaitForDebugEvent(&dbg, INFINITE) == 0) {
            return NULL;
        }

        cont = DBG_CONTINUE;
        pthread_mutex_lock(&P->mutex);

        switch (dbg.dwDebugEventCode) {
        case CREATE_PROCESS_DEBUG_EVENT:
            P->thandle = dbg.u.CreateProcessInfo.hThread;
            P->phandle = dbg.u.CreateProcessInfo.hProcess;
            if ((SymInitialize(P->phandle, 0, FALSE) == FALSE)) {
                dprintf("SymInitialize failed (%d): %d\n", P->pid, GetLastError());
                break;
            }

            s = GetFileNameFromHandle(dbg.u.CreateProcessInfo.hFile, pszFilename);
            addmodule(P, dbg.u.CreateProcessInfo.hFile, s, dbg.u.CreateProcessInfo.lpBaseOfImage, PE_TYPE_EXE, P->dll_load_order);
            size = GetFileSize(dbg.u.CreateProcessInfo.hFile, NULL);
            if (size == INVALID_FILE_SIZE) {
                size = 0;
            }

            if ((mod = SymLoadModuleEx(P->phandle,  dbg.u.CreateProcessInfo.hFile, s, NULL,
                                       (ULONG_PTR) dbg.u.CreateProcessInfo.lpBaseOfImage, size, NULL, 0)) == FALSE) {
                dprintf("SymLoadModule64 Failed for %s: %d\n", s, GetLastError());
                break;
            }

#if __amd64__
            if (Is32bitProcess(P->phandle)) {
                P->model = PR_MODEL_ILP32;
                wow = 1;
            } else
                P->model = PR_MODEL_ILP64;
#else
            P->model = PR_MODEL_ILP32;
#endif

            CloseHandle(dbg.u.CreateProcessInfo.hFile);
            P->status = PS_RUN;
            P->msg.type = 0;
            break;
        case CREATE_THREAD_DEBUG_EVENT:
            P->status = PS_RUN;
            P->msg.type = 0;
            break;
        case LOAD_DLL_DEBUG_EVENT:
            s = GetFileNameFromHandle(dbg.u.LoadDll.hFile, pszFilename);
            if (first_execp) {
                P->dll_load_order++;
            }
            addmodule(P, dbg.u.LoadDll.hFile, s, dbg.u.LoadDll.lpBaseOfDll, PE_TYPE_DLL, P->dll_load_order);
            size = GetFileSize(dbg.u.CreateProcessInfo.hFile, NULL);
            if (size == INVALID_FILE_SIZE) {
                size = 0;
            }
#if __amd64__
            /* Not tracing 64 bit dlls for 32 bit process */
            if (P->model == PR_MODEL_ILP32 && is64bitmodule(dbg.u.LoadDll.lpBaseOfDll, s)) {
                CloseHandle(dbg.u.LoadDll.hFile );
                break;
            }
#endif
            if ((mod = SymLoadModuleEx(P->phandle,  dbg.u.LoadDll.hFile, s, NULL,
                                       (ULONG_PTR) dbg.u.LoadDll.lpBaseOfDll, size, NULL, 0)) == FALSE) {
                dprintf("SymLoadModule64 failed for %s: %d\n", s, GetLastError());
                break;
            }

            CloseHandle(dbg.u.LoadDll.hFile );

            if (first_execp == 0) {
                P->status = PS_RUN;
                P->msg.type = RD_DLACTIVITY;
            } else {
                P->status = PS_STOP;
                P->msg.type = RD_DLACTIVITY;
            }
            break;
        case UNLOAD_DLL_DEBUG_EVENT:
            if (SymUnloadModule64(P->phandle, (ULONG_PTR) dbg.u.UnloadDll.lpBaseOfDll) ==  FALSE) {
                dprintf("SymUnloadModule64 failed-Imagebase %p: %d\n", dbg.u.UnloadDll.lpBaseOfDll, GetLastError());
                break;
            }
            delmodule(P, (ULONG64) dbg.u.UnloadDll.lpBaseOfDll);
            P->status = PS_RUN;
            P->msg.type = RD_DLACTIVITY;
            break;
        case EXIT_PROCESS_DEBUG_EVENT:
            P->exitcode = dbg.u.ExitProcess.dwExitCode;
            P->status = PS_UNDEAD;
            P->msg.type = RD_NONE;
            //SymCleanup(P->phandle);
            break;
        case EXIT_THREAD_DEBUG_EVENT:
            P->status = PS_RUN;
            P->msg.type = 0;
            break;
        case EXCEPTION_DEBUG_EVENT:
            switch(dbg.u.Exception.ExceptionRecord.ExceptionCode) {
            case EXCEPTION_BREAKPOINT:
                if (first_execp++ == 0) {
                    pthread_cond_signal(&P->cond);
                }
                P->status = PS_STOP;
                P->msg.type = 0;

                break;
            default:
                if (dbg.u.Exception.dwFirstChance == 0)
                    P->wstat = dbg.u.Exception.ExceptionRecord.ExceptionCode;
                P->status = PS_RUN;
                cont = DBG_EXCEPTION_NOT_HANDLED;
                break;
            }
            break;
        default:
            P->status = PS_RUN;
            dprintf("Debug Event not processed: %d\n", dbg.dwDebugEventCode);
            break;
        }

        if (P->status != PS_RUN)
            SetEvent(P->event);

        while (P->status == PS_STOP)
            pthread_cond_wait(&P->cond, &P->mutex);
        pthread_mutex_unlock(&P->mutex);

        ContinueDebugEvent(dbg.dwProcessId, dbg.dwThreadId, cont);
    }

}
Пример #8
0
static void *Ploopcreate(LPVOID args)
{
    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    DEBUG_EVENT  dbg;
    DWORD cont;
    BOOL wow = 0;
    DWORD Options = SymGetOptions(), excep, size = 0;
    TCHAR pszFilename[MAX_PATH+1];
    struct proc_uc *tmp = args;
    struct ps_prochandle *P = tmp->ps;
    int first_execp = 0;
    char *s, targs[256], *ctmp;
    char *const *argv = tmp->args;
    int len;

    ctmp = targs;
    while (*argv != NULL) {
        len = strlen(*argv);
        sprintf(ctmp, "%s ", *argv);
        ctmp = ctmp + len + 1;
        argv++;
    }

    *ctmp = '\0';
    ZeroMemory( &si, sizeof(si) );
    si.cb = sizeof(si);
    ZeroMemory( &pi, sizeof(pi) );
    if(!CreateProcess( NULL,   //  module name
                       targs,        // Command line
                       NULL,           // Process handle not inheritable
                       NULL,           // Thread handle not inheritable
                       FALSE,          // Set handle inheritance to FALSE
                       DEBUG_ONLY_THIS_PROCESS,              // No creation flags
                       NULL,           // Use parent's environment block
                       NULL,           // Use parent's starting directory
                       &si,            // Pointer to STARTUPINFO structure
                       &pi )           // Pointer to PROCESS_INFORMATION structure
      ) {
        pthread_mutex_lock(&P->mutex);
        P->status = PS_STOP;
        P->flags = CREATE_FAILED;
        pthread_cond_signal(&P->cond);
        pthread_mutex_unlock(&P->mutex);
        return NULL;
    }
    P->pid = pi.dwProcessId;
    P->tid = pi.dwThreadId;
    P->wstat = 0;
    P->exitcode = 0;
    P->event = CreateEvent(NULL,FALSE,FALSE,NULL);
    P->dll_load_order = 1;
#if __amd64__
    /* There seems to be a bug in 64 bit version of dbghelp.dll
     * when SYMOPT_DEFERRED_LOADS is set,
     * dtrace -n "pid$target:kernel32::entry, pid$target:KernelBase::entry" -c test.exe,
     * when SymEnumSymbols (Psymbol_iter_by_addr) is called on this two dll,
     * the second call (KernelBase) will enumerate the
     * symbols from the previous enumurated (kernel32) dll (from the first call).
     * This behaviour is not present in 32 bit.
     */
    Options &= ~SYMOPT_DEFERRED_LOADS;
#endif
    SymSetOptions(Options|SYMOPT_INCLUDE_32BIT_MODULES|SYMOPT_DEBUG);

    while (1) {
        if (WaitForDebugEvent(&dbg, INFINITE) == 0) {
            return NULL;
        }
        cont = DBG_CONTINUE;
        pthread_mutex_lock(&P->mutex);

        switch (dbg.dwDebugEventCode) {
        case CREATE_PROCESS_DEBUG_EVENT:

            P->phandle = dbg.u.CreateProcessInfo.hProcess;
            P->thandle = dbg.u.CreateProcessInfo.hThread;
            if ((SymInitialize(P->phandle, 0, FALSE) == FALSE)) {
                dprintf("SymInitialize failed: %d\n", GetLastError());
                break;
            }

            s = GetFileNameFromHandle(dbg.u.CreateProcessInfo.hFile, pszFilename);
            addmodule(P, dbg.u.CreateProcessInfo.hFile, s, dbg.u.CreateProcessInfo.lpBaseOfImage,
                      PE_TYPE_EXE, P->dll_load_order);
            size = GetFileSize(dbg.u.CreateProcessInfo.hFile, NULL);
            if (size == INVALID_FILE_SIZE) {
                size = 0;
            }
            if (SymLoadModuleEx(P->phandle, dbg.u.CreateProcessInfo.hFile, s, NULL,
                                (ULONG_PTR) dbg.u.CreateProcessInfo.lpBaseOfImage, size, NULL, 0) == 0) {
                dprintf("SymLoadModule64 failed for %s:%d\n", s, GetLastError());
                break;
            }

#if __amd64__
            if (Is32bitProcess(P->phandle)) {
                P->model = PR_MODEL_ILP32;
                wow = 1;
            } else
                P->model = PR_MODEL_ILP64;
#else
            P->model = PR_MODEL_ILP32;
#endif
            P->status = PS_STOP;
            P->msg.type = 0;
            CloseHandle(dbg.u.CreateProcessInfo.hFile);
            pthread_cond_signal(&P->cond);
            break;
        case CREATE_THREAD_DEBUG_EVENT:
            P->status = PS_RUN;
            P->msg.type = 0;
            break;
        case LOAD_DLL_DEBUG_EVENT:
            s = GetFileNameFromHandle(dbg.u.LoadDll.hFile, pszFilename);
            if (first_execp == 2) {
                P->dll_load_order++;
            }
            addmodule(P, dbg.u.LoadDll.hFile, s, dbg.u.LoadDll.lpBaseOfDll, PE_TYPE_DLL, P->dll_load_order);

            size = GetFileSize(dbg.u.LoadDll.hFile, NULL);
            if (size == INVALID_FILE_SIZE) {
                size = 0;
            }
#if __amd64__
            /* Not tracing 64 bit dlls for 32 bit process */
            if (P->model == PR_MODEL_ILP32 && is64bitmodule(dbg.u.LoadDll.lpBaseOfDll, s)) {
                CloseHandle(dbg.u.LoadDll.hFile );
                break;
            }
#endif
            if (SymLoadModuleEx(P->phandle, dbg.u.LoadDll.hFile, s, NULL,
                                (ULONG_PTR) dbg.u.LoadDll.lpBaseOfDll, size, NULL, 0) == FALSE) {
                dprintf("SymLoadModule64 dailed for %s:%d\n", s, GetLastError());
                break;
            }

            CloseHandle(dbg.u.LoadDll.hFile );
            P->status = PS_STOP;
            P->msg.type = RD_DLACTIVITY;
            break;
        case UNLOAD_DLL_DEBUG_EVENT:
            if (SymUnloadModule64(P->phandle, (ULONG_PTR) dbg.u.UnloadDll.lpBaseOfDll) ==  FALSE) {
                dprintf("SymUnloadModule64 failed-Imagebase %p:%d\n", dbg.u.UnloadDll.lpBaseOfDll, GetLastError());
                break;
            }
            delmodule(P, (ULONG64) dbg.u.UnloadDll.lpBaseOfDll);
            P->status = PS_RUN;
            P->msg.type = RD_DLACTIVITY;
            break;
        case EXIT_PROCESS_DEBUG_EVENT:
            P->exitcode = dbg.u.ExitProcess.dwExitCode;
            P->status = PS_UNDEAD;
            P->msg.type = RD_NONE;
            break;
        case EXIT_THREAD_DEBUG_EVENT:
            P->status = PS_RUN;
            P->msg.type = 0;
            break;
        case EXCEPTION_DEBUG_EVENT:
            switch(excep = dbg.u.Exception.ExceptionRecord.ExceptionCode) {
            case EXCEPTION_BREAKPOINT:
            case 0x4000001F:	/* WOW64 exception breakpoint */
                /* NOTE: Dtrace sets a BP at main (entry point of the process), which is implemented
                 * with Psetbkpt, Pdelbkpt & Pexecbkpt. But I have implemnted it here.
                 */
                if ((excep == EXCEPTION_BREAKPOINT && first_execp == 0 && wow == 0) ||
                        (excep == 0x4000001F && first_execp == 0 && wow == 1) ) {
                    SYMBOL_INFO *Symbol;
                    GElf_Sym sym;
                    ULONG64 buffer[(sizeof(SYMBOL_INFO) +  MAX_SYM_NAME * sizeof(TCHAR) + sizeof(ULONG64) - 1) / sizeof(ULONG64)];

                    Symbol = (SYMBOL_INFO *) buffer;
                    Symbol->SizeOfStruct= sizeof(SYMBOL_INFO );
                    Symbol->MaxNameLen = MAX_SYM_NAME;

                    if (Pxlookup_by_name(P, LM_ID_BASE, "a.out", "main", &sym, NULL) != 0 &&
                            Pxlookup_by_name(P, LM_ID_BASE, "a.out", "WinMain", &sym, NULL) != 0) {
                        dprintf("failed to find entry point (main):%d\n", GetLastError());
                        break;
                    }

                    if (setbkpt(P, (uintptr_t) sym.st_value) != 0) {
                        dprintf("failed to set breakpoint for %s at address %p\n", Symbol->Name, Symbol->Address);
                        break;
                    }

                    first_execp = 1;
                    P->status = PS_RUN;
                    P->msg.type = 0;
                    break;
                }

                if (dbg.u.Exception.ExceptionRecord.ExceptionAddress != (PVOID) P->addr) {
                    dprintf("expecting execption at %p:but recived from %p\n", P->addr,
                            dbg.u.Exception.ExceptionRecord.ExceptionAddress);
                    P->status = PS_RUN;
                    cont = DBG_EXCEPTION_NOT_HANDLED;
                    break;
                }

                if (delbkpt(P, P->addr) != 0) {
                    dprintf("failed to delete brk point at %p:(main)\n", P->addr);
                    break;
                }

                if (adjbkpt(P, wow) != 0) {
                    dprintf("failed to normalize brk point (main)\n");
                    break;
                }
                first_execp = 2;
                P->status = PS_STOP;
                P->msg.type = RD_MAININIT;
                break;/*
				if (first_execp == 0) {
					P->status = PS_STOP;
					P->msg.type = RD_MAININIT;
					first_execp = 2;
				} else {
					P->status = PS_RUN;
					cont = DBG_EXCEPTION_NOT_HANDLED;
				}
				break;*/

            default:
                if (dbg.u.Exception.dwFirstChance == 0)
                    P->wstat = dbg.u.Exception.ExceptionRecord.ExceptionCode;
                P->status = PS_RUN;
                cont = DBG_EXCEPTION_NOT_HANDLED;
                break;
            }
            break;
        default:
            P->status = PS_RUN;
            dprintf("Debug Event not processed: %d\n", dbg.dwDebugEventCode);
            break;
        }

        if (P->status != PS_RUN)
            SetEvent(P->event);
        while (P->status == PS_STOP)
            pthread_cond_wait(&P->cond, &P->mutex);
        pthread_mutex_unlock(&P->mutex);

        ContinueDebugEvent(dbg.dwProcessId, dbg.dwThreadId, cont);
    }

}
Пример #9
0
int main(int argc, char *argv[]) {
  DWORD  error;
  HANDLE process;
  ULONG64 module_base;
  int i;
  char* search;
  char buf[256];   /* Enough to hold one hex address, I trust! */
  int rv = 0;
  /* We may add SYMOPT_UNDNAME if --demangle is specified: */
  DWORD symopts = SYMOPT_DEFERRED_LOADS | SYMOPT_DEBUG | SYMOPT_LOAD_LINES;
  char* filename = "a.out";         /* The default if -e isn't specified */
  int print_function_name = 0;      /* Set to 1 if -f is specified */

  for (i = 1; i < argc; i++) {
    if (strcmp(argv[i], "--functions") == 0 || strcmp(argv[i], "-f") == 0) {
      print_function_name = 1;
    } else if (strcmp(argv[i], "--demangle") == 0 ||
               strcmp(argv[i], "-C") == 0) {
      symopts |= SYMOPT_UNDNAME;
    } else if (strcmp(argv[i], "-e") == 0) {
      if (i + 1 >= argc) {
        fprintf(stderr, "FATAL ERROR: -e must be followed by a filename\n");
        return 1;
      }
      filename = argv[i+1];
      i++;     /* to skip over filename too */
    } else if (strcmp(argv[i], "--help") == 0) {
      usage();
      exit(0);
    } else {
      usage();
      exit(1);
    }
  }

  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;
  }

  buf[sizeof(buf)-1] = '\0';  /* Just to be safe */
  while (fgets(buf, sizeof(buf)-1, stdin)) {
    /* GNU addr2line seems to just do a strtol and ignore any
     * weird characters it gets, so we will too.
     */
    unsigned __int64 addr = _strtoui64(buf, NULL, 16);
    ULONG64 buffer[(sizeof(SYMBOL_INFO) +
                    MAX_SYM_NAME*sizeof(TCHAR) +
                    sizeof(ULONG64) - 1)
                   / sizeof(ULONG64)];
    PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer;
    IMAGEHLP_LINE64 line;
    DWORD dummy;
    pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
    pSymbol->MaxNameLen = MAX_SYM_NAME;
    if (print_function_name) {
      if (SymFromAddr(process, (DWORD64)addr, NULL, pSymbol)) {
        printf("%s\n", pSymbol->Name);
      } else {
        printf("??\n");
      }
    }
    line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
    if (SymGetLineFromAddr64(process, (DWORD64)addr, &dummy, &line)) {
      printf("%s:%d\n", line.FileName, (int)line.LineNumber);
    } else {
      printf("??:0\n");
    }
  }
  SymUnloadModule64(process, module_base);
  SymCleanup(process);
  return rv;
}
Пример #10
0
BOOL DebugMainLoop(const DebugOptions *pOptions)
{
    BOOL fFinished = FALSE;
    BOOL fBreakpointSignalled = FALSE;
    BOOL fWowBreakpointSignalled = FALSE;
    BOOL fTerminating = FALSE;

    while(!fFinished)
    {
        DEBUG_EVENT DebugEvent;            // debugging event information
        DWORD dwContinueStatus = DBG_CONTINUE;    // exception continuation
        PPROCESS_INFO pProcessInfo;
        PTHREAD_INFO pThreadInfo;
        HANDLE hProcess;

        // Wait for a debugging event to occur. The second parameter indicates
        // that the function does not return until a debugging event occurs.
        if(!WaitForDebugEvent(&DebugEvent, INFINITE))
        {
            OutputDebug("WaitForDebugEvent: 0x%08lx", GetLastError());

            return FALSE;
        }

        // Process the debugging event code.
        switch (DebugEvent.dwDebugEventCode) {
        case EXCEPTION_DEBUG_EVENT: {
            PEXCEPTION_RECORD pExceptionRecord = &DebugEvent.u.Exception.ExceptionRecord;
            NTSTATUS ExceptionCode = pExceptionRecord->ExceptionCode;

            // Process the exception code. When handling
            // exceptions, remember to set the continuation
            // status parameter (dwContinueStatus). This value
            // is used by the ContinueDebugEvent function.
            if (pOptions->verbose_flag) {
                lprintf("EXCEPTION PID=%lu TID=%lu ExceptionCode=0x%lx dwFirstChance=%lu\r\n",
                        DebugEvent.dwProcessId,
                        DebugEvent.dwThreadId,
                        pExceptionRecord->ExceptionCode,
                        DebugEvent.u.Exception.dwFirstChance
                );
            }

            // Find the process in the process list
            pProcessInfo = &g_Processes[DebugEvent.dwProcessId];

            dwContinueStatus = DBG_EXCEPTION_NOT_HANDLED;

            if (DebugEvent.u.Exception.dwFirstChance) {
                if (pExceptionRecord->ExceptionCode == (DWORD)STATUS_BREAKPOINT) {
                    // Signal the aedebug event
                    if (!fBreakpointSignalled) {
                        fBreakpointSignalled = TRUE;

                        if (pOptions->hEvent) {
                            SetEvent(pOptions->hEvent);
                            CloseHandle(pOptions->hEvent);
                        }

                        if (pOptions->dwThreadId) {
                            DWORD dwThreadId = pOptions->dwThreadId;
                            const DWORD dwFailed = (DWORD)-1;
                            DWORD dwRet = dwFailed;
                            pThreadInfo = &pProcessInfo->Threads[dwThreadId];
                            HANDLE hThread = pThreadInfo->hThread;
                            if (hThread != NULL) {
                                dwRet = ResumeThread(hThread);
                            }
                            if (dwRet == dwFailed) {
                                lprintf("error: failed to resume thread %lu\n", dwThreadId);
                            }
                        }

                        /*
                         * We ignore first-chance breakpoints by default.
                         *
                         * We get one of these whenever we attach to a process.
                         * But in some cases, we never get a second-chance, e.g.,
                         * when we're attached through MSVCRT's abort().
                         */
                        if (!pOptions->breakpoint_flag) {
                            dwContinueStatus = DBG_CONTINUE;
                            break;
                        }
                    }
                }

                if (ExceptionCode == STATUS_WX86_BREAKPOINT) {
                    if (!fWowBreakpointSignalled) {
                        fWowBreakpointSignalled = TRUE;
                        dwContinueStatus = DBG_CONTINUE;
                        break;
                    }
                }

               /*
                 * Ignore thread naming exception.
                 *
                 * http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx
                 *
                 * TODO: Note down the thread name
                 */
                if (ExceptionCode == 0x406d1388) {
                    dwContinueStatus = DBG_CONTINUE;
                    break;
                }

                if (!pOptions->first_chance) {
                    break;
                }
            }

            // XXX: Deferred symbols don't get loaded without this
            SymRefreshModuleList(pProcessInfo->hProcess);

            dumpException(pProcessInfo->hProcess,
                          &DebugEvent.u.Exception.ExceptionRecord);

            // Find the thread in the thread list
            THREAD_INFO_LIST::const_iterator it;
            for (it = pProcessInfo->Threads.begin(); it != pProcessInfo->Threads.end(); ++it) {
                DWORD dwThreadId = it->first;
                HANDLE hThread = it->second.hThread;
                if (dwThreadId != DebugEvent.dwThreadId &&
                    ExceptionCode != STATUS_BREAKPOINT &&
                    ExceptionCode != STATUS_WX86_BREAKPOINT) {
                        continue;
                }

                dumpStack(pProcessInfo->hProcess, hThread, NULL);
            }

            if (!DebugEvent.u.Exception.dwFirstChance) {
                /*
                 * Terminate the process. As continuing would cause the JIT debugger
                 * to be invoked again.
                 */
                fTerminating = TRUE;
                TerminateProcess(pProcessInfo->hProcess, (UINT)ExceptionCode);
            }

            break;
        }

        case CREATE_THREAD_DEBUG_EVENT:
            if (pOptions->verbose_flag) {
                lprintf("CREATE_THREAD PID=%lu TID=%lu\r\n",
                        DebugEvent.dwProcessId,
                        DebugEvent.dwThreadId
                );
            }

            // Add the thread to the thread list
            pProcessInfo = &g_Processes[DebugEvent.dwProcessId];
            pThreadInfo = &pProcessInfo->Threads[DebugEvent.dwThreadId];
            pThreadInfo->hThread = DebugEvent.u.CreateThread.hThread;
            break;

        case CREATE_PROCESS_DEBUG_EVENT: {
            HANDLE hFile = DebugEvent.u.CreateProcessInfo.hFile;

            char szImageName[MAX_PATH];
            char *lpImageName = NULL;
            if (hFile && GetFileNameFromHandle(hFile, szImageName, _countof(szImageName))) {
                lpImageName = szImageName;
            }

            if (pOptions->verbose_flag) {
                PCSTR lpModuleName = lpImageName ? getBaseName(lpImageName) : "";

                lprintf("CREATE_PROCESS PID=%lu TID=%lu lpBaseOfImage=%p %s\r\n",
                        DebugEvent.dwProcessId,
                        DebugEvent.dwThreadId,
                        DebugEvent.u.CreateProcessInfo.lpBaseOfImage,
                        lpModuleName
                );
            }

            hProcess = DebugEvent.u.CreateProcessInfo.hProcess;

            pProcessInfo = &g_Processes[DebugEvent.dwProcessId];
            pProcessInfo->hProcess = hProcess;

            pThreadInfo = &pProcessInfo->Threads[DebugEvent.dwThreadId];
            pThreadInfo->hThread = DebugEvent.u.CreateProcessInfo.hThread;

            if (!InitializeSym(hProcess, FALSE)) {
                OutputDebug("error: SymInitialize failed: 0x%08lx\n", GetLastError());
                exit(EXIT_FAILURE);
            }

            SymRegisterCallback64(hProcess, &symCallback, 0);

            loadModule(hProcess, hFile, lpImageName, DebugEvent.u.CreateProcessInfo.lpBaseOfImage);

            break;
        }

        case EXIT_THREAD_DEBUG_EVENT:
            if (pOptions->verbose_flag) {
                lprintf("EXIT_THREAD PID=%lu TID=%lu dwExitCode=0x%lx\r\n",
                        DebugEvent.dwProcessId,
                        DebugEvent.dwThreadId,
                        DebugEvent.u.ExitThread.dwExitCode
                );
            }

            // Remove the thread from the thread list
            pProcessInfo = &g_Processes[DebugEvent.dwProcessId];
            hProcess = pProcessInfo->hProcess;

            // Dump the stack on abort()
            if (!fTerminating && isAbnormalExitCode(DebugEvent.u.ExitThread.dwExitCode)) {
                pThreadInfo = &pProcessInfo->Threads[DebugEvent.dwThreadId];
                refreshSymbolsAndDumpStack(hProcess, pThreadInfo->hThread);
            }

            pProcessInfo->Threads.erase(DebugEvent.dwThreadId);
            break;

        case EXIT_PROCESS_DEBUG_EVENT: {
            if (pOptions->verbose_flag) {
                lprintf("EXIT_PROCESS PID=%lu TID=%lu dwExitCode=0x%lx\r\n",
                        DebugEvent.dwProcessId,
                        DebugEvent.dwThreadId,
                        DebugEvent.u.ExitProcess.dwExitCode
                );
            }

            pProcessInfo = &g_Processes[DebugEvent.dwProcessId];
            hProcess = pProcessInfo->hProcess;

            // Dump the stack on abort()
            if (!fTerminating && isAbnormalExitCode(DebugEvent.u.ExitThread.dwExitCode)) {
                pThreadInfo = &pProcessInfo->Threads[DebugEvent.dwThreadId];
                refreshSymbolsAndDumpStack(hProcess, pThreadInfo->hThread);
            }

            // Remove the process from the process list
            g_Processes.erase(DebugEvent.dwProcessId);

            if (!SymCleanup(hProcess)) {
                OutputDebug("SymCleanup failed with 0x%08lx\n", GetLastError());
            }

            if (g_Processes.empty()) {
                fFinished = TRUE;
            }

            break;
        }

        case LOAD_DLL_DEBUG_EVENT: {
            HANDLE hFile = DebugEvent.u.LoadDll.hFile;

            char szImageName[MAX_PATH];
            char *lpImageName = NULL;
            if (hFile && GetFileNameFromHandle(hFile, szImageName, _countof(szImageName))) {
                lpImageName = szImageName;
            }

            if (pOptions->verbose_flag) {
                PCSTR lpModuleName = lpImageName ? getBaseName(lpImageName) : "";

                lprintf("LOAD_DLL PID=%lu TID=%lu lpBaseOfDll=%p %s\r\n",
                        DebugEvent.dwProcessId,
                        DebugEvent.dwThreadId,
                        DebugEvent.u.LoadDll.lpBaseOfDll,
                        lpModuleName
                );
            }

            pProcessInfo = &g_Processes[DebugEvent.dwProcessId];
            hProcess = pProcessInfo->hProcess;

            loadModule(hProcess, hFile, lpImageName, DebugEvent.u.LoadDll.lpBaseOfDll);

            break;
        }

        case UNLOAD_DLL_DEBUG_EVENT:
            if (pOptions->verbose_flag) {
                lprintf("UNLOAD_DLL PID=%lu TID=%lu lpBaseOfDll=%p\r\n",
                        DebugEvent.dwProcessId,
                        DebugEvent.dwThreadId,
                        DebugEvent.u.UnloadDll.lpBaseOfDll
                );
            }

            pProcessInfo = &g_Processes[DebugEvent.dwProcessId];
            hProcess = pProcessInfo->hProcess;

            SymUnloadModule64(hProcess, (UINT_PTR)DebugEvent.u.UnloadDll.lpBaseOfDll);

            break;

        case OUTPUT_DEBUG_STRING_EVENT: {
            if (pOptions->verbose_flag) {
                lprintf("OUTPUT_DEBUG_STRING PID=%lu TID=%lu\r\n",
                        DebugEvent.dwProcessId,
                        DebugEvent.dwThreadId
                );
            }

            pProcessInfo = &g_Processes[DebugEvent.dwProcessId];

            assert(!DebugEvent.u.DebugString.fUnicode);

            LPSTR lpDebugStringData = readProcessString(pProcessInfo->hProcess,
                                                        DebugEvent.u.DebugString.lpDebugStringData,
                                                        DebugEvent.u.DebugString.nDebugStringLength);

            lprintf("%s", lpDebugStringData);

            free(lpDebugStringData);
            break;
        }

        case RIP_EVENT:
            if (pOptions->verbose_flag) {
                lprintf("RIP PID=%lu TID=%lu\r\n",
                        DebugEvent.dwProcessId,
                        DebugEvent.dwThreadId
                );
            }
            break;

        default:
            if (pOptions->verbose_flag) {
                lprintf("EVENT%lu PID=%lu TID=%lu\r\n",
                    DebugEvent.dwDebugEventCode,
                    DebugEvent.dwProcessId,
                    DebugEvent.dwThreadId
                );
            }
            break;
        }

        // Resume executing the thread that reported the debugging event.
        ContinueDebugEvent(
            DebugEvent.dwProcessId,
            DebugEvent.dwThreadId,
            dwContinueStatus
        );
    }

    return TRUE;
}
Пример #11
0
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;
}
Пример #12
0
bool CATDbgHelper::AddressToLine( CATMemoryAddress* result )
{
	LOG_FUNC_ENTRY("CATDbgHelper::AddressToLine");
	
	// Set state out of range
	result->SetAddressToLineState( CATMemoryAddress::OUT_OF_RANGE );

	// check that dbghelper has been initialized successfully.
	if ( ! CDBGHELPER_OPEN )
		return false;

	// Check has binary been moved, if so unload and load to new base address.
	if ( result->GetModuleStartAddress() + AT_VIRTUAL_OFFSET_DBGHELPER != m_BaseAddress )
	{
		// Unload.
		if ( SymUnloadModule64( GetCurrentProcess(), m_BaseAddress ) )
		{
			// Set new base address.
			m_BaseAddress = result->GetModuleStartAddress() + AT_VIRTUAL_OFFSET_DBGHELPER;
			// (Re)load.
			DWORD64 loading = SymLoadModule64( GetCurrentProcess(), NULL, m_pBinaryFile, NULL, m_BaseAddress, NULL );
			if ( loading != m_BaseAddress  && loading != 0)	
			{
				LOG_STRING("Dbghelp:Module load failed " << (int) GetLastError());
				return false;
			}
		}
		else
			LOG_STRING("Dbghelp:Module unload failed " << (int) GetLastError() );
	}
	// Address to find (offset+given address).
	unsigned long iAddressToFind = result->GetAddress() + AT_VIRTUAL_OFFSET_DBGHELPER;
	// Displacements of line/symbol information.
	DWORD64 displacementSymbol;
	DWORD displacementLine;
	// Structure to get symbol information.
	CSymbolInfo symbol;
	// Structure to get line information.
	CLineInfo line;
	// Find Symbol for given address 
	if( ! SymFromAddr( GetCurrentProcess(), iAddressToFind , &displacementSymbol, &symbol.si ) )
	{
		LOG_STRING("Failed to find symbol information for given line.");
		return AddressToFunction( result );
	}
	// Find line information
	if( ! SymGetLineFromAddr64( GetCurrentProcess(), iAddressToFind, &displacementLine, &line ) )
	{
		// If it fails get symbol line information
		LOG_STRING("Dbghelp:Failed to find line information for address, trying for symbol of address.");
		if( ! SymGetLineFromAddr64( GetCurrentProcess(), symbol.si.Address, &displacementLine, &line ) )
		{
			LOG_STRING("Dbghelp:Failed to find line information for symbol address.");
			return AddressToFunction( result );
		}
	}
	// Set the results.
	result->SetFileName( string( line.FileName ) );
	result->SetFunctionName( string( symbol.si.Name ) );
	result->SetExactLineNumber( (int) line.LineNumber );
	result->SetAddressToLineState( CATMemoryAddress::EXACT );
	// Return.
	return true;
}