예제 #1
0
파일: symbol.c 프로젝트: Kelimion/wine
/***********************************************************************
 *           symbol_get_function_line_status
 *
 * Find the symbol nearest to a given address.
 */
enum dbg_line_status symbol_get_function_line_status(const ADDRESS64* addr)
{
    IMAGEHLP_LINE64     il;
    DWORD               disp;
    ULONG64             disp64, start;
    DWORD_PTR           lin = (DWORD_PTR)memory_to_linear_addr(addr);
    char                buffer[sizeof(SYMBOL_INFO) + 256];
    SYMBOL_INFO*        sym = (SYMBOL_INFO*)buffer;
    struct dbg_type     func;

    il.SizeOfStruct = sizeof(il);
    sym->SizeOfStruct = sizeof(SYMBOL_INFO);
    sym->MaxNameLen = sizeof(buffer) - sizeof(SYMBOL_INFO);

    /* do we have some info for lin address ? */
    if (!SymFromAddr(dbg_curr_process->handle, lin, &disp64, sym))
    {
        ADDRESS64   jumpee;
        /* some compilers insert thunks in their code without debug info associated
         * take care of this situation
         */
        if (be_cpu->is_jump((void*)lin, &jumpee))
            return symbol_get_function_line_status(&jumpee);
        return dbg_no_line_info;
    }

    switch (sym->Tag)
    {
    case SymTagThunk:
        /* FIXME: so far dbghelp doesn't return the 16 <=> 32 thunks
         * and furthermore, we no longer take care of them !!!
         */
        return dbg_in_a_thunk;
    case SymTagFunction:
    case SymTagPublicSymbol: break;
    default:
        WINE_FIXME("Unexpected sym-tag 0x%08x\n", sym->Tag);
    case SymTagData:
        return dbg_no_line_info;
    }
    /* we should have a function now */
    if (!SymGetLineFromAddr64(dbg_curr_process->handle, lin, &disp, &il))
        return dbg_no_line_info;

    func.module = sym->ModBase;
    func.id     = sym->info;

    if (symbol_get_debug_start(&func, &start) && lin < start)
        return dbg_not_on_a_line_number;

    if (!sym->Size) sym->Size = 0x100000;
    if (il.FileName && il.FileName[0] && disp < sym->Size)
        return (disp == 0) ? dbg_on_a_line_number : dbg_not_on_a_line_number;

    return dbg_no_line_info;
}
예제 #2
0
파일: break.c 프로젝트: yy221/winedbg
/***********************************************************************
 *           break_should_continue
 *
 * Determine if we should continue execution after a SIGTRAP signal when
 * executing in the given mode.
 */
BOOL break_should_continue(ADDRESS64* addr, DWORD code)
{
    enum dbg_exec_mode  mode = dbg_curr_thread->exec_mode;


    if (dbg_curr_thread->stopped_xpoint > 0)
    {
        if (!should_stop(dbg_curr_thread->stopped_xpoint)) return TRUE;

        switch (dbg_curr_process->bp[dbg_curr_thread->stopped_xpoint].xpoint_type)
        {
        case be_xpoint_break:
        case be_xpoint_watch_exec:
            dbg_printf("Stopped on breakpoint %d at ", dbg_curr_thread->stopped_xpoint);
            print_address(&dbg_curr_process->bp[dbg_curr_thread->stopped_xpoint].addr, TRUE);
            dbg_printf("\n");
            break;
        case be_xpoint_watch_read:
        case be_xpoint_watch_write:
            dbg_printf("Stopped on watchpoint %d at ", dbg_curr_thread->stopped_xpoint);
            print_address(addr, TRUE);
            dbg_printf(" new value %s\n",
                       wine_dbgstr_longlong(dbg_curr_process->bp[dbg_curr_thread->stopped_xpoint].w.oldval));
        }
        return FALSE;
    }

    /*
     * If our mode indicates that we are stepping line numbers,
     * get the current function, and figure out if we are exactly
     * on a line number or not.
     */
    if (mode == dbg_exec_step_over_line || mode == dbg_exec_step_into_line)
    {
	if (symbol_get_function_line_status(addr) == dbg_on_a_line_number)
            dbg_curr_thread->exec_count--;
    }
    else if (mode == dbg_exec_step_over_insn || mode == dbg_exec_step_into_insn)
        dbg_curr_thread->exec_count--;

    if (dbg_curr_thread->exec_count > 0 || mode == dbg_exec_finish)
    {
	/*
	 * We still need to execute more instructions.
	 */
	return TRUE;
    }

    /* no breakpoint, continue if in continuous mode */
    return mode == dbg_exec_cont || mode == dbg_exec_finish;
}
예제 #3
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;
}