예제 #1
0
static BOOL tgt_process_active_close_process(struct dbg_process* pcs, BOOL kill)
{
    if (pcs == dbg_curr_process)
    {
        /* remove all set breakpoints in debuggee code */
        break_set_xpoints(FALSE);
        /* needed for single stepping (ugly).
         * should this be handled inside the server ???
         */
        be_cpu->single_step(&dbg_context, FALSE);
        if (dbg_curr_thread->in_exception)
        {
            SetThreadContext(dbg_curr_thread->handle, &dbg_context);
            ContinueDebugEvent(dbg_curr_pid, dbg_curr_tid, DBG_CONTINUE);
        }
    }
    if (kill)
    {
        TerminateProcess(pcs->handle, 0);
    }
    else
    {
        if (!DebugActiveProcessStop(pcs->pid)) return FALSE;
    }
    SymCleanup(pcs->handle);
    dbg_del_process(pcs);

    return TRUE;
}
예제 #2
0
static void dbg_init_current_thread(void* start)
{
    if (start)
    {
        if (dbg_curr_process->threads &&
                !dbg_curr_process->threads->next && /* first thread ? */
                DBG_IVAR(BreakAllThreadsStartup))
        {
            ADDRESS64   addr;

            break_set_xpoints(FALSE);
            addr.Mode   = AddrModeFlat;
            addr.Offset = (DWORD_PTR)start;
            break_add_break(&addr, TRUE, TRUE);
            break_set_xpoints(TRUE);
        }
    }
}
예제 #3
0
static unsigned dbg_handle_debug_event(DEBUG_EVENT* de)
{
    union {
        char	bufferA[256];
        WCHAR	buffer[256];
    } u;
    DWORD       cont = DBG_CONTINUE;

    dbg_curr_pid = de->dwProcessId;
    dbg_curr_tid = de->dwThreadId;

    if ((dbg_curr_process = dbg_get_process(de->dwProcessId)) != NULL)
        dbg_curr_thread = dbg_get_thread(dbg_curr_process, de->dwThreadId);
    else
        dbg_curr_thread = NULL;

    switch (de->dwDebugEventCode)
    {
    case EXCEPTION_DEBUG_EVENT:
        if (!dbg_curr_thread)
        {
            WINE_ERR("%04x:%04x: not a registered process or thread (perhaps a 16 bit one ?)\n",
                     de->dwProcessId, de->dwThreadId);
            break;
        }

        WINE_TRACE("%04x:%04x: exception code=%08x\n",
                   de->dwProcessId, de->dwThreadId,
                   de->u.Exception.ExceptionRecord.ExceptionCode);

        if (dbg_curr_process->continue_on_first_exception)
        {
            dbg_curr_process->continue_on_first_exception = FALSE;
            if (!DBG_IVAR(BreakOnAttach)) break;
        }
        if (dbg_fetch_context())
        {
            cont = dbg_handle_exception(&de->u.Exception.ExceptionRecord,
                                        de->u.Exception.dwFirstChance);
            if (cont && dbg_curr_thread)
            {
                SetThreadContext(dbg_curr_thread->handle, &dbg_context);
            }
        }
        break;

    case CREATE_PROCESS_DEBUG_EVENT:
        dbg_curr_process = dbg_add_process(&be_process_active_io, de->dwProcessId,
                                           de->u.CreateProcessInfo.hProcess);
        if (dbg_curr_process == NULL)
        {
            WINE_ERR("Couldn't create process\n");
            break;
        }
        fetch_module_name(de->u.CreateProcessInfo.lpImageName,
                          de->u.CreateProcessInfo.fUnicode,
                          de->u.CreateProcessInfo.lpBaseOfImage,
                          u.buffer, sizeof(u.buffer) / sizeof(WCHAR), TRUE);

        WINE_TRACE("%04x:%04x: create process '%s'/%p @%p (%u<%u>)\n",
                   de->dwProcessId, de->dwThreadId,
                   wine_dbgstr_w(u.buffer),
                   de->u.CreateProcessInfo.lpImageName,
                   de->u.CreateProcessInfo.lpStartAddress,
                   de->u.CreateProcessInfo.dwDebugInfoFileOffset,
                   de->u.CreateProcessInfo.nDebugInfoSize);
        dbg_set_process_name(dbg_curr_process, u.buffer);

        if (!dbg_init(dbg_curr_process->handle, u.buffer, FALSE))
            dbg_printf("Couldn't initiate DbgHelp\n");
        if (!dbg_load_module(dbg_curr_process->handle, de->u.CreateProcessInfo.hFile, u.buffer,
                             (DWORD_PTR)de->u.CreateProcessInfo.lpBaseOfImage, 0))
            dbg_printf("couldn't load main module (%u)\n", GetLastError());

        WINE_TRACE("%04x:%04x: create thread I @%p\n",
                   de->dwProcessId, de->dwThreadId, de->u.CreateProcessInfo.lpStartAddress);

        dbg_curr_thread = dbg_add_thread(dbg_curr_process,
                                         de->dwThreadId,
                                         de->u.CreateProcessInfo.hThread,
                                         de->u.CreateProcessInfo.lpThreadLocalBase);
        if (!dbg_curr_thread)
        {
            WINE_ERR("Couldn't create thread\n");
            break;
        }
        dbg_init_current_process();
        dbg_init_current_thread(de->u.CreateProcessInfo.lpStartAddress);
        break;

    case EXIT_PROCESS_DEBUG_EVENT:
        WINE_TRACE("%04x:%04x: exit process (%d)\n",
                   de->dwProcessId, de->dwThreadId, de->u.ExitProcess.dwExitCode);

        if (dbg_curr_process == NULL)
        {
            WINE_ERR("Unknown process\n");
            break;
        }
        tgt_process_active_close_process(dbg_curr_process, FALSE);
        dbg_printf("Process of pid=%04x has terminated\n", de->dwProcessId);
        break;

    case CREATE_THREAD_DEBUG_EVENT:
        WINE_TRACE("%04x:%04x: create thread D @%p\n",
                   de->dwProcessId, de->dwThreadId, de->u.CreateThread.lpStartAddress);

        if (dbg_curr_process == NULL)
        {
            WINE_ERR("Unknown process\n");
            break;
        }
        if (dbg_get_thread(dbg_curr_process, de->dwThreadId) != NULL)
        {
            WINE_TRACE("Thread already listed, skipping\n");
            break;
        }

        dbg_curr_thread = dbg_add_thread(dbg_curr_process,
                                         de->dwThreadId,
                                         de->u.CreateThread.hThread,
                                         de->u.CreateThread.lpThreadLocalBase);
        if (!dbg_curr_thread)
        {
            WINE_ERR("Couldn't create thread\n");
            break;
        }
        dbg_init_current_thread(de->u.CreateThread.lpStartAddress);
        break;

    case EXIT_THREAD_DEBUG_EVENT:
        WINE_TRACE("%04x:%04x: exit thread (%d)\n",
                   de->dwProcessId, de->dwThreadId, de->u.ExitThread.dwExitCode);

        if (dbg_curr_thread == NULL)
        {
            WINE_ERR("Unknown thread\n");
            break;
        }
        /* FIXME: remove break point set on thread startup */
        dbg_del_thread(dbg_curr_thread);
        break;

    case LOAD_DLL_DEBUG_EVENT:
        if (dbg_curr_thread == NULL)
        {
            WINE_ERR("Unknown thread\n");
            break;
        }
        fetch_module_name(de->u.LoadDll.lpImageName,
                          de->u.LoadDll.fUnicode,
                          de->u.LoadDll.lpBaseOfDll,
                          u.buffer, sizeof(u.buffer) / sizeof(WCHAR), FALSE);

        WINE_TRACE("%04x:%04x: loads DLL %s @%p (%u<%u>)\n",
                   de->dwProcessId, de->dwThreadId,
                   wine_dbgstr_w(u.buffer), de->u.LoadDll.lpBaseOfDll,
                   de->u.LoadDll.dwDebugInfoFileOffset,
                   de->u.LoadDll.nDebugInfoSize);
        dbg_load_module(dbg_curr_process->handle, de->u.LoadDll.hFile, u.buffer,
                        (DWORD_PTR)de->u.LoadDll.lpBaseOfDll, 0);
        break_set_xpoints(FALSE);
        break_check_delayed_bp();
        break_set_xpoints(TRUE);
        if (DBG_IVAR(BreakOnDllLoad))
        {
            dbg_printf("Stopping on DLL %s loading at 0x%08lx\n",
                       dbg_W2A(u.buffer, -1), (unsigned long)de->u.LoadDll.lpBaseOfDll);
            if (dbg_fetch_context()) cont = 0;
        }
        break;

    case UNLOAD_DLL_DEBUG_EVENT:
        WINE_TRACE("%04x:%04x: unload DLL @%p\n",
                   de->dwProcessId, de->dwThreadId,
                   de->u.UnloadDll.lpBaseOfDll);
        break_delete_xpoints_from_module((unsigned long)de->u.UnloadDll.lpBaseOfDll);
        SymUnloadModule(dbg_curr_process->handle,
                        (unsigned long)de->u.UnloadDll.lpBaseOfDll);
        break;

    case OUTPUT_DEBUG_STRING_EVENT:
        if (dbg_curr_thread == NULL)
        {
            WINE_ERR("Unknown thread\n");
            break;
        }

        memory_get_string(dbg_curr_process,
                          de->u.DebugString.lpDebugStringData, TRUE,
                          de->u.DebugString.fUnicode, u.bufferA, sizeof(u.bufferA));
        WINE_TRACE("%04x:%04x: output debug string (%s)\n",
                   de->dwProcessId, de->dwThreadId, u.bufferA);
        break;

    case RIP_EVENT:
        WINE_TRACE("%04x:%04x: rip error=%u type=%u\n",
                   de->dwProcessId, de->dwThreadId, de->u.RipInfo.dwError,
                   de->u.RipInfo.dwType);
        break;

    default:
        WINE_TRACE("%04x:%04x: unknown event (%x)\n",
                   de->dwProcessId, de->dwThreadId, de->dwDebugEventCode);
    }
    if (!cont) return TRUE;  /* stop execution */
    ContinueDebugEvent(de->dwProcessId, de->dwThreadId, cont);
    return FALSE;  /* continue execution */
}
예제 #4
0
파일: break.c 프로젝트: yy221/winedbg
/***********************************************************************
 *           break_restart_execution
 *
 * Set the bp to the correct state to restart execution
 * in the given mode.
 */
void break_restart_execution(int count)
{
    ADDRESS64                   addr;
    enum dbg_line_status        status;
    enum dbg_exec_mode          mode, ret_mode;
    ADDRESS64                   callee;
    void*                       linear;

    memory_get_current_pc(&addr);
    linear = memory_to_linear_addr(&addr);

    /*
     * This is the mode we will be running in after we finish.  We would like
     * to be able to modify this in certain cases.
     */
    ret_mode = mode = dbg_curr_thread->exec_mode;

    /* we've stopped on a xpoint (other than step over) */
    if (dbg_curr_thread->stopped_xpoint > 0)
    {
	/*
	 * If we have set a new value, then save it in the BP number.
	 */
	if (count != 0 && mode == dbg_exec_cont)
        {
	    dbg_curr_process->bp[dbg_curr_thread->stopped_xpoint].skipcount = count;
        }
        /* If we've stopped on a breakpoint, single step over it (, then run) */
        if (is_xpoint_break(dbg_curr_thread->stopped_xpoint))
            mode = dbg_exec_step_into_insn;
    }
    else if (mode == dbg_exec_cont && count > 1)
    {
        dbg_printf("Not stopped at any breakpoint; argument ignored.\n");
    }

    if (mode == dbg_exec_finish && be_cpu->is_function_return(linear))
    {
	mode = ret_mode = dbg_exec_step_into_insn;
    }

    /*
     * See if the function we are stepping into has debug info
     * and line numbers.  If not, then we step over it instead.
     * FIXME - we need to check for things like thunks or trampolines,
     * as the actual function may in fact have debug info.
     */
    if (be_cpu->is_function_call(linear, &callee))
    {
	status = symbol_get_function_line_status(&callee);
#if 0
        /* FIXME: we need to get the thunk type */
	/*
	 * Anytime we have a trampoline, step over it.
	 */
	if ((mode == EXEC_STEP_OVER || mode == EXEC_STEPI_OVER)
	    && status == dbg_in_a_thunk)
        {
            WINE_WARN("Not stepping into trampoline at %p (no lines)\n", 
                      memory_to_linear_addr(&callee));
	    mode = EXEC_STEP_OVER_TRAMPOLINE;
        }
#endif
	if (mode == dbg_exec_step_into_line && status == dbg_no_line_info)
        {
            WINE_WARN("Not stepping into function at %p (no lines)\n",
                      memory_to_linear_addr(&callee));
	    mode = dbg_exec_step_over_line;
        }
    }

    if (mode == dbg_exec_step_into_line && 
        symbol_get_function_line_status(&addr) == dbg_no_line_info)
    {
        dbg_printf("Single stepping until exit from function,\n"
                   "which has no line number information.\n");
        ret_mode = mode = dbg_exec_finish;
    }

    switch (mode)
    {
    case dbg_exec_cont: /* Continuous execution */
        be_cpu->single_step(&dbg_context, FALSE);
        break_set_xpoints(TRUE);
        break;

#if 0
    case EXEC_STEP_OVER_TRAMPOLINE:
        /*
         * This is the means by which we step over our conversion stubs
         * in callfrom*.s and callto*.s.  We dig the appropriate address
         * off the stack, and we set the breakpoint there instead of the
         * address just after the call.
         */
        be_cpu->get_addr(dbg_curr_thread->handle, &dbg_context,
                         be_cpu_addr_stack, &addr);
        /* FIXME: we assume stack grows as on an i386 */
        addr.Offset += 2 * sizeof(unsigned int);
        dbg_read_memory(memory_to_linear_addr(&addr),
                        &addr.Offset, sizeof(addr.Offset));
        dbg_curr_process->bp[0].addr = addr;
        dbg_curr_process->bp[0].enabled = TRUE;
        dbg_curr_process->bp[0].refcount = 1;
        dbg_curr_process->bp[0].skipcount = 0;
        dbg_curr_process->bp[0].xpoint_type = be_xpoint_break;
        dbg_curr_process->bp[0].condition = NULL;
        be_cpu->single_step(&dbg_context, FALSE);
        break_set_xpoints(TRUE);
        break;
#endif

    case dbg_exec_finish:
    case dbg_exec_step_over_insn:  /* Stepping over a call */
    case dbg_exec_step_over_line:  /* Stepping over a call */
        if (be_cpu->is_step_over_insn(linear))
        {
            be_cpu->disasm_one_insn(&addr, FALSE);
            dbg_curr_process->bp[0].addr = addr;
            dbg_curr_process->bp[0].enabled = TRUE;
            dbg_curr_process->bp[0].refcount = 1;
	    dbg_curr_process->bp[0].skipcount = 0;
            dbg_curr_process->bp[0].xpoint_type = be_xpoint_break;
            dbg_curr_process->bp[0].condition = NULL;
            be_cpu->single_step(&dbg_context, FALSE);
            break_set_xpoints(TRUE);
            break;
        }
        /* else fall through to single-stepping */

    case dbg_exec_step_into_line: /* Single-stepping a line */
    case dbg_exec_step_into_insn: /* Single-stepping an instruction */
        be_cpu->single_step(&dbg_context, TRUE);
        break;
    default: RaiseException(DEBUG_STATUS_INTERNAL_ERROR, 0, 0, NULL);
    }
    dbg_curr_thread->step_over_bp = dbg_curr_process->bp[0];
    dbg_curr_thread->exec_mode = ret_mode;
}
예제 #5
0
파일: break.c 프로젝트: yy221/winedbg
/***********************************************************************
 *           break_suspend_execution
 *
 * Remove all bp before entering the debug loop
 */
void	break_suspend_execution(void)
{
    break_set_xpoints(FALSE);
    dbg_curr_process->bp[0] = dbg_curr_thread->step_over_bp;
}