Ejemplo n.º 1
12
static enum dbg_start minidump_do_reload(struct tgt_process_minidump_data* data)
{
    ULONG                       size;
    MINIDUMP_DIRECTORY*         dir;
    void*                       stream;
    DWORD                       pid = 1; /* by default */
    HANDLE                      hProc = (HANDLE)0x900DBAAD;
    int                         i;
    MINIDUMP_MODULE_LIST*       mml;
    MINIDUMP_MODULE*            mm;
    MINIDUMP_STRING*            mds;
    char                        exec_name[1024];
    char                        name[1024];
    unsigned                    len;

    /* fetch PID */
    if (MiniDumpReadDumpStream(data->mapping, MiscInfoStream, &dir, &stream, &size))
    {
        MINIDUMP_MISC_INFO* mmi = (MINIDUMP_MISC_INFO*)stream;
        if (mmi->Flags1 & MINIDUMP_MISC1_PROCESS_ID)
            pid = mmi->ProcessId;
    }

    /* fetch executable name (it's normally the first one in module list) */
    strcpy(exec_name, "<minidump-exec>"); /* default */
    if (MiniDumpReadDumpStream(data->mapping, ModuleListStream, &dir, &stream, &size))
    {
        mml = (MINIDUMP_MODULE_LIST*)stream;
        if (mml->NumberOfModules)
        {
            char*               ptr;

            mm = &mml->Modules[0];
            mds = (MINIDUMP_STRING*)((char*)data->mapping + mm->ModuleNameRva);
            len = WideCharToMultiByte(CP_ACP, 0, mds->Buffer,
                                      mds->Length / sizeof(WCHAR), 
                                      name, sizeof(name) - 1, NULL, NULL);
            name[len] = 0;
            for (ptr = name + len - 1; ptr >= name; ptr--)
            {
                if (*ptr == '/' || *ptr == '\\')
                {
                    strcpy(exec_name, ptr + 1);
                    break;
                }
            }
            if (ptr < name) strcpy(exec_name, name);
        }
    }

    if (MiniDumpReadDumpStream(data->mapping, SystemInfoStream, &dir, &stream, &size))
    {
        MINIDUMP_SYSTEM_INFO*   msi = (MINIDUMP_SYSTEM_INFO*)stream;
        const char *str;
        char tmp[128];

        dbg_printf("WineDbg starting on minidump on pid %lu\n", pid);
        switch (msi->ProcessorArchitecture)
        {
        case PROCESSOR_ARCHITECTURE_UNKNOWN: 
            str = "Unknown";
            break;
        case PROCESSOR_ARCHITECTURE_INTEL:
            strcpy(tmp, "Intel ");
            switch (msi->ProcessorLevel)
            {
            case 3: str = "80386"; break;
            case 4: str = "80486"; break;
            case 5: str = "Pentium"; break;
            case 6: str = "Pentium Pro/II"; break;
            default: str = "???"; break;
            }
            strcat(tmp, str);
            if (msi->ProcessorLevel == 3 || msi->ProcessorLevel == 4)
            {
                if (HIWORD(msi->ProcessorRevision) == 0xFF)
                    sprintf(tmp + strlen(tmp), "-%c%d",
                            'A' + HIBYTE(LOWORD(msi->ProcessorRevision)),
                            LOBYTE(LOWORD(msi->ProcessorRevision)));
                else
                    sprintf(tmp + strlen(tmp), "-%c%d",
                            'A' + HIWORD(msi->ProcessorRevision),
                            LOWORD(msi->ProcessorRevision));
            }
            else sprintf(tmp + strlen(tmp), "-%d.%d",
                         HIWORD(msi->ProcessorRevision),
                         LOWORD(msi->ProcessorRevision));
            str = tmp;
            break;
        case PROCESSOR_ARCHITECTURE_MIPS:
            str = "Mips";
            break;
        case PROCESSOR_ARCHITECTURE_ALPHA:
            str = "Alpha";
            break;
        case PROCESSOR_ARCHITECTURE_PPC:
            str = "PowerPC";
            break;
        default:
            str = "???";
            break;
        }
        dbg_printf("  %s was running on #%d %s CPU%s",
                   exec_name, msi->u.s.NumberOfProcessors, str, 
                   msi->u.s.NumberOfProcessors < 2 ? "" : "s");
        switch (msi->MajorVersion)
        {
        case 3:
            switch (msi->MinorVersion)
            {
            case 51: str = "NT 3.51"; break;
            default: str = "3-????"; break;
            }
            break;
        case 4:
            switch (msi->MinorVersion)
            {
            case 0: str = (msi->PlatformId == VER_PLATFORM_WIN32_NT) ? "NT 4.0" : "95"; break;
            case 10: str = "98"; break;
            case 90: str = "ME"; break;
            default: str = "5-????"; break;
            }
            break;
        case 5:
            switch (msi->MinorVersion)
            {
            case 0: str = "2000"; break;
            case 1: str = "XP"; break;
            case 2: str = "Server 2003"; break;
            default: str = "5-????"; break;
            }
            break;
        default: str = "???"; break;
        }
        dbg_printf(" on Windows %s (%lu)\n", str, msi->BuildNumber);
        /* FIXME CSD: msi->CSDVersionRva */
    }

    dbg_curr_process = dbg_add_process(&be_process_minidump_io, pid, hProc);
    dbg_curr_pid = pid;
    dbg_curr_process->pio_data = data;
    dbg_set_process_name(dbg_curr_process, exec_name);

    SymInitialize(hProc, NULL, FALSE);

    if (MiniDumpReadDumpStream(data->mapping, ThreadListStream, &dir, &stream, &size))
    {
        MINIDUMP_THREAD_LIST*     mtl = (MINIDUMP_THREAD_LIST*)stream;
        MINIDUMP_THREAD*          mt = &mtl->Threads[0];

        dbg_add_thread(dbg_curr_process, mt->ThreadId, NULL, 
                       (void*)(DWORD_PTR)mt->Teb);
    }
    /* first load ELF modules, then do the PE ones */
    if (MiniDumpReadDumpStream(data->mapping, Wine_ElfModuleListStream, &dir,
                               &stream, &size))
    {
        char    buffer[MAX_PATH];

        mml = (MINIDUMP_MODULE_LIST*)stream;
        for (i = 0, mm = &mml->Modules[0]; i < mml->NumberOfModules; i++, mm++)
        {
            mds = (MINIDUMP_STRING*)((char*)data->mapping + mm->ModuleNameRva);
            len = WideCharToMultiByte(CP_ACP, 0, mds->Buffer,
                                      mds->Length / sizeof(WCHAR), 
                                      name, sizeof(name) - 1, NULL, NULL);
            name[len] = 0;
            if (SymFindFileInPath(hProc, NULL, name, (void*)(DWORD_PTR)mm->CheckSum,
                                  0, 0, SSRVOPT_DWORD, buffer, validate_file, NULL))
                SymLoadModule(hProc, NULL, buffer, NULL, mm->BaseOfImage, mm->SizeOfImage);
            else
                SymLoadModuleEx(hProc, NULL, name, NULL, mm->BaseOfImage, mm->SizeOfImage,
                                NULL, SLMFLAG_VIRTUAL);
        }
    }
    if (MiniDumpReadDumpStream(data->mapping, ModuleListStream, &dir, &stream, &size))
    {
        mml = (MINIDUMP_MODULE_LIST*)stream;
        for (i = 0, mm = &mml->Modules[0]; i < mml->NumberOfModules; i++, mm++)
        {
            mds = (MINIDUMP_STRING*)((char*)data->mapping + mm->ModuleNameRva);
            len = WideCharToMultiByte(CP_ACP, 0, mds->Buffer,
                                      mds->Length / sizeof(WCHAR), 
                                      name, sizeof(name) - 1, NULL, NULL);
            name[len] = 0;
            SymLoadModule(hProc, NULL, name, NULL, 
                          mm->BaseOfImage, mm->SizeOfImage);
        }
    }
    if (MiniDumpReadDumpStream(data->mapping, ExceptionStream, &dir, &stream, &size))
    {
        MINIDUMP_EXCEPTION_STREAM*      mes = (MINIDUMP_EXCEPTION_STREAM*)stream;

        if ((dbg_curr_thread = dbg_get_thread(dbg_curr_process, mes->ThreadId)))
        {
            ADDRESS64   addr;

            dbg_curr_tid = mes->ThreadId;
            dbg_curr_thread->in_exception = TRUE;
            dbg_curr_thread->excpt_record.ExceptionCode = mes->ExceptionRecord.ExceptionCode;
            dbg_curr_thread->excpt_record.ExceptionFlags = mes->ExceptionRecord.ExceptionFlags;
            dbg_curr_thread->excpt_record.ExceptionRecord = (void*)(DWORD_PTR)mes->ExceptionRecord.ExceptionRecord;
            dbg_curr_thread->excpt_record.ExceptionAddress = (void*)(DWORD_PTR)mes->ExceptionRecord.ExceptionAddress;
            dbg_curr_thread->excpt_record.NumberParameters = mes->ExceptionRecord.NumberParameters;
            for (i = 0; i < dbg_curr_thread->excpt_record.NumberParameters; i++)
            {
                dbg_curr_thread->excpt_record.ExceptionInformation[i] = mes->ExceptionRecord.ExceptionInformation[i];
            }
            memcpy(&dbg_context, (char*)data->mapping + mes->ThreadContext.Rva,
                   min(sizeof(dbg_context), mes->ThreadContext.DataSize));
            memory_get_current_pc(&addr);
            stack_fetch_frames();
            be_cpu->print_context(dbg_curr_thread->handle, &dbg_context, 0);
            stack_info();
            be_cpu->print_segment_info(dbg_curr_thread->handle, &dbg_context);
            stack_backtrace(mes->ThreadId);
            source_list_from_addr(&addr, 0);
        }
    }
    return start_ok;
}
Ejemplo n.º 2
0
void source_list_from_addr(const ADDRESS64* addr, int nlines)
{
    IMAGEHLP_LINE       il;
    ADDRESS64           la;
    DWORD               disp;

    if (!addr)
    {
        memory_get_current_pc(&la);
        addr = &la;
    }

    il.SizeOfStruct = sizeof(il);
    if (SymGetLineFromAddr(dbg_curr_process->handle,
                           (unsigned long)memory_to_linear_addr(addr),
                           &disp, &il))
        source_list(&il, NULL, nlines);
}
Ejemplo n.º 3
0
void dbg_wait_next_exception(DWORD cont, int count, int mode)
{
    ADDRESS64           addr;
    char                hexbuf[MAX_OFFSET_TO_STR_LEN];

    if (cont == DBG_CONTINUE)
    {
        dbg_curr_thread->exec_count = count;
        dbg_curr_thread->exec_mode = mode;
    }
    dbg_resume_debuggee(cont);

    wait_exception();
    if (!dbg_curr_process) return;

    memory_get_current_pc(&addr);
    WINE_TRACE("Entering debugger     PC=%s mode=%d count=%d\n",
               memory_offset_to_string(hexbuf, addr.Offset, 0),
               dbg_curr_thread->exec_mode,
               dbg_curr_thread->exec_count);
}
Ejemplo n.º 4
0
void memory_disassemble(const struct dbg_lvalue* xstart, 
                        const struct dbg_lvalue* xend, int instruction_count)
{
    static ADDRESS64 last = {0,0,0};
    int stop = 0;
    int i;

    if (!xstart && !xend) 
    {
        if (!last.Segment && !last.Offset) memory_get_current_pc(&last);
    }
    else
    {
        if (xstart)
            types_extract_as_address(xstart, &last);
        if (xend) 
            stop = types_extract_as_integer(xend);
    }
    for (i = 0; (instruction_count == 0 || i < instruction_count)  &&
                (stop == 0 || last.Offset <= stop); i++)
        memory_disasm_one_insn(&last);
}
Ejemplo n.º 5
0
static void dbg_resume_debuggee(DWORD cont)
{
    if (dbg_curr_thread->in_exception)
    {
        ADDRESS64       addr;
        char            hexbuf[MAX_OFFSET_TO_STR_LEN];

        dbg_exception_epilog();
        memory_get_current_pc(&addr);
        WINE_TRACE("Exiting debugger      PC=%s mode=%d count=%d\n",
                   memory_offset_to_string(hexbuf, addr.Offset, 0),
                   dbg_curr_thread->exec_mode,
                   dbg_curr_thread->exec_count);
        if (dbg_curr_thread)
        {
            if (!SetThreadContext(dbg_curr_thread->handle, &dbg_context))
                dbg_printf("Cannot set ctx on %04x\n", dbg_curr_tid);
        }
    }
    dbg_interactiveP = FALSE;
    if (!ContinueDebugEvent(dbg_curr_pid, dbg_curr_tid, cont))
        dbg_printf("Cannot continue on %04x (%08x)\n", dbg_curr_tid, cont);
}
Ejemplo n.º 6
0
/***********************************************************************
 *           break_add_break_from_lineno
 *
 * Add a breakpoint from a line number in current file
 */
void break_add_break_from_lineno(const char *filename, int lineno, BOOL swbp)
{
    struct cb_break_lineno      bkln;
    bkln.addr.Offset = 0;
    bkln.lineno = lineno;

    if (!filename)
    {
        DWORD disp;
        ADDRESS64 curr;
        IMAGEHLP_LINE64 il;
        DWORD_PTR linear;

        memory_get_current_pc(&curr);
        linear = (DWORD_PTR)memory_to_linear_addr(&curr);
        il.SizeOfStruct = sizeof(il);
        if (!SymGetLineFromAddr64(dbg_curr_process->handle, linear, &disp, &il))
        {
            dbg_printf("Unable to add breakpoint (unknown address %lx)\n", linear);
            return;
        }
        filename = il.FileName;
        SymEnumLines(dbg_curr_process->handle, linear, NULL, filename, line_cb, &bkln);
    }
    else
    {
        /* we have to enumerate across modules */
        bkln.filename = filename;
        SymEnumerateModulesW64(dbg_curr_process->handle, mcb, &bkln);
    }
    if (bkln.addr.Offset)
        break_add_break(&bkln.addr, TRUE, swbp);
    else
        dbg_printf("Unknown line number\n"
                   "(either out of file, or no code at given line number)\n");
}
Ejemplo n.º 7
0
/***********************************************************************
 *              dbg_exception_prolog
 *
 * Examine exception and decide if interactive mode is entered(return TRUE)
 * or exception is silently continued(return FALSE)
 * is_debug means the exception is a breakpoint or single step exception
 */
static unsigned dbg_exception_prolog(BOOL is_debug, BOOL first_chance, const EXCEPTION_RECORD* rec)
{
    ADDRESS64   addr;
    BOOL        is_break;
    char        hexbuf[MAX_OFFSET_TO_STR_LEN];

    memory_get_current_pc(&addr);
    break_suspend_execution();
    dbg_curr_thread->excpt_record = *rec;
    dbg_curr_thread->in_exception = TRUE;

    if (!is_debug)
    {
        switch (addr.Mode)
        {
        case AddrModeFlat:
            dbg_printf(" in 32-bit code (%s)",
                       memory_offset_to_string(hexbuf, addr.Offset, 0));
            break;
        case AddrModeReal:
            dbg_printf(" in vm86 code (%04x:%04x)", addr.Segment, (unsigned) addr.Offset);
            break;
        case AddrMode1616:
            dbg_printf(" in 16-bit code (%04x:%04x)", addr.Segment, (unsigned) addr.Offset);
            break;
        case AddrMode1632:
            dbg_printf(" in 32-bit code (%04x:%08lx)", addr.Segment, (unsigned long) addr.Offset);
            break;
        default:
            dbg_printf(" bad address");
        }
        dbg_printf(".\n");
    }

    /* this will resynchronize builtin dbghelp's internal ELF module list */
    SymLoadModule(dbg_curr_process->handle, 0, 0, 0, 0, 0);

    if (is_debug) break_adjust_pc(&addr, rec->ExceptionCode, first_chance, &is_break);
    /*
     * Do a quiet backtrace so that we have an idea of what the situation
     * is WRT the source files.
     */
    stack_fetch_frames();

    if (is_debug && !is_break && break_should_continue(&addr, rec->ExceptionCode))
        return FALSE;

    if (addr.Mode != dbg_curr_thread->addr_mode)
    {
        const char* name = NULL;

        switch (addr.Mode)
        {
        case AddrMode1616:
            name = "16 bit";
            break;
        case AddrMode1632:
            name = "32 bit";
            break;
        case AddrModeReal:
            name = "vm86";
            break;
        case AddrModeFlat:
            name = "32 bit";
            break;
        }

        dbg_printf("In %s mode.\n", name);
        dbg_curr_thread->addr_mode = addr.Mode;
    }
    display_print();

    if (!is_debug)
    {
        /* This is a real crash, dump some info */
        be_cpu->print_context(dbg_curr_thread->handle, &dbg_context, 0);
        stack_info();
        be_cpu->print_segment_info(dbg_curr_thread->handle, &dbg_context);
        stack_backtrace(dbg_curr_tid);
    }
    else
    {
        static char*        last_name;
        static char*        last_file;

        char                buffer[sizeof(SYMBOL_INFO) + 256];
        SYMBOL_INFO*        si = (SYMBOL_INFO*)buffer;
        void*               lin = memory_to_linear_addr(&addr);
        DWORD64             disp64;
        IMAGEHLP_LINE       il;
        DWORD               disp;

        si->SizeOfStruct = sizeof(*si);
        si->MaxNameLen   = 256;
        il.SizeOfStruct = sizeof(il);
        if (SymFromAddr(dbg_curr_process->handle, (DWORD_PTR)lin, &disp64, si) &&
                SymGetLineFromAddr(dbg_curr_process->handle, (DWORD_PTR)lin, &disp, &il))
        {
            if ((!last_name || strcmp(last_name, si->Name)) ||
                    (!last_file || strcmp(last_file, il.FileName)))
            {
                HeapFree(GetProcessHeap(), 0, last_name);
                HeapFree(GetProcessHeap(), 0, last_file);
                last_name = strcpy(HeapAlloc(GetProcessHeap(), 0, strlen(si->Name) + 1), si->Name);
                last_file = strcpy(HeapAlloc(GetProcessHeap(), 0, strlen(il.FileName) + 1), il.FileName);
                dbg_printf("%s () at %s:%u\n", last_name, last_file, il.LineNumber);
            }
        }
    }
    if (!is_debug || is_break ||
            dbg_curr_thread->exec_mode == dbg_exec_step_over_insn ||
            dbg_curr_thread->exec_mode == dbg_exec_step_into_insn)
    {
        ADDRESS64 tmp = addr;
        /* Show where we crashed */
        memory_disasm_one_insn(&tmp);
    }
    source_list_from_addr(&addr, 0);

    return TRUE;
}
Ejemplo n.º 8
0
/***********************************************************************
 *           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;
}