Ejemplo n.º 1
0
BOOL memory_get_string_indirect(struct dbg_process* pcs, void* addr, BOOL unicode, char* buffer, int size)
{
    void*       ad;
    SIZE_T	sz;

    buffer[0] = 0;
    if (addr && 
        pcs->process_io->read(pcs->handle, addr, &ad, sizeof(ad), &sz) && sz == sizeof(ad) && ad)
    {
        return memory_get_string(pcs, ad, TRUE, unicode, buffer, size);
    }
    return FALSE;
}
Ejemplo n.º 2
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 */
}
Ejemplo n.º 3
0
static DWORD dbg_handle_exception(const EXCEPTION_RECORD* rec, BOOL first_chance)
{
    BOOL                is_debug = FALSE;
    THREADNAME_INFO*    pThreadName;
    struct dbg_thread*  pThread;

    assert(dbg_curr_thread);

    WINE_TRACE("exception=%x first_chance=%c\n",
               rec->ExceptionCode, first_chance ? 'Y' : 'N');

    switch (rec->ExceptionCode)
    {
    case EXCEPTION_BREAKPOINT:
    case EXCEPTION_SINGLE_STEP:
        is_debug = TRUE;
        break;
    case EXCEPTION_NAME_THREAD:
        pThreadName = (THREADNAME_INFO*)(rec->ExceptionInformation);
        if (pThreadName->dwThreadID == -1)
            pThread = dbg_curr_thread;
        else
            pThread = dbg_get_thread(dbg_curr_process, pThreadName->dwThreadID);
        if(!pThread)
        {
            dbg_printf("Thread ID=%04x not in our list of threads -> can't rename\n", pThreadName->dwThreadID);
            return DBG_CONTINUE;
        }
        if (dbg_read_memory(pThreadName->szName, pThread->name, 9))
            dbg_printf("Thread ID=%04x renamed using MS VC6 extension (name==\"%s\")\n",
                       pThread->tid, pThread->name);
        return DBG_CONTINUE;
    }

    if (first_chance && !is_debug && !DBG_IVAR(BreakOnFirstChance) &&
            !(rec->ExceptionFlags & EH_STACK_INVALID))
    {
        /* pass exception to program except for debug exceptions */
        return DBG_EXCEPTION_NOT_HANDLED;
    }

    if (!is_debug)
    {
        /* print some infos */
        dbg_printf("%s: ",
                   first_chance ? "First chance exception" : "Unhandled exception");
        switch (rec->ExceptionCode)
        {
        case EXCEPTION_INT_DIVIDE_BY_ZERO:
            dbg_printf("divide by zero");
            break;
        case EXCEPTION_INT_OVERFLOW:
            dbg_printf("overflow");
            break;
        case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
            dbg_printf("array bounds");
            break;
        case EXCEPTION_ILLEGAL_INSTRUCTION:
            dbg_printf("illegal instruction");
            break;
        case EXCEPTION_STACK_OVERFLOW:
            dbg_printf("stack overflow");
            break;
        case EXCEPTION_PRIV_INSTRUCTION:
            dbg_printf("privileged instruction");
            break;
        case EXCEPTION_ACCESS_VIOLATION:
            if (rec->NumberParameters == 2)
                dbg_printf("page fault on %s access to 0x%08lx",
                           rec->ExceptionInformation[0] == EXCEPTION_WRITE_FAULT ? "write" :
                           rec->ExceptionInformation[0] == EXCEPTION_EXECUTE_FAULT ? "execute" : "read",
                           rec->ExceptionInformation[1]);
            else
                dbg_printf("page fault");
            break;
        case EXCEPTION_DATATYPE_MISALIGNMENT:
            dbg_printf("Alignment");
            break;
        case DBG_CONTROL_C:
            dbg_printf("^C");
            break;
        case CONTROL_C_EXIT:
            dbg_printf("^C");
            break;
        case STATUS_POSSIBLE_DEADLOCK:
        {
            ADDRESS64       addr;

            addr.Mode   = AddrModeFlat;
            addr.Offset = rec->ExceptionInformation[0];

            dbg_printf("wait failed on critical section ");
            print_address(&addr, FALSE);
        }
        if (!DBG_IVAR(BreakOnCritSectTimeOut))
        {
            dbg_printf("\n");
            return DBG_EXCEPTION_NOT_HANDLED;
        }
        break;
        case EXCEPTION_WINE_STUB:
        {
            char dll[32], name[64];
            memory_get_string(dbg_curr_process,
                              (void*)rec->ExceptionInformation[0], TRUE, FALSE,
                              dll, sizeof(dll));
            if (HIWORD(rec->ExceptionInformation[1]))
                memory_get_string(dbg_curr_process,
                                  (void*)rec->ExceptionInformation[1], TRUE, FALSE,
                                  name, sizeof(name));
            else
                sprintf( name, "%ld", rec->ExceptionInformation[1] );
            dbg_printf("unimplemented function %s.%s called", dll, name);
        }
        break;
        case EXCEPTION_WINE_ASSERTION:
            dbg_printf("assertion failed");
            break;
        case EXCEPTION_VM86_INTx:
            dbg_printf("interrupt %02lx in vm86 mode", rec->ExceptionInformation[0]);
            break;
        case EXCEPTION_VM86_STI:
            dbg_printf("sti in vm86 mode");
            break;
        case EXCEPTION_VM86_PICRETURN:
            dbg_printf("PIC return in vm86 mode");
            break;
        case EXCEPTION_FLT_DENORMAL_OPERAND:
            dbg_printf("denormal float operand");
            break;
        case EXCEPTION_FLT_DIVIDE_BY_ZERO:
            dbg_printf("divide by zero");
            break;
        case EXCEPTION_FLT_INEXACT_RESULT:
            dbg_printf("inexact float result");
            break;
        case EXCEPTION_FLT_INVALID_OPERATION:
            dbg_printf("invalid float operation");
            break;
        case EXCEPTION_FLT_OVERFLOW:
            dbg_printf("floating point overflow");
            break;
        case EXCEPTION_FLT_UNDERFLOW:
            dbg_printf("floating point underflow");
            break;
        case EXCEPTION_FLT_STACK_CHECK:
            dbg_printf("floating point stack check");
            break;
        case CXX_EXCEPTION:
            if(rec->NumberParameters == 3 && rec->ExceptionInformation[0] == CXX_FRAME_MAGIC)
                dbg_printf("C++ exception(object = 0x%08lx, type = 0x%08lx)",
                           rec->ExceptionInformation[1], rec->ExceptionInformation[2]);
            else
                dbg_printf("C++ exception with strange parameter count %d or magic 0x%08lx",
                           rec->NumberParameters, rec->ExceptionInformation[0]);
            break;
        default:
            dbg_printf("0x%08x", rec->ExceptionCode);
            break;
        }
    }
    if( (rec->ExceptionFlags & EH_STACK_INVALID) ) {
        dbg_printf( ", invalid program stack" );
    }

    if (dbg_exception_prolog(is_debug, first_chance, rec))
    {
        dbg_interactiveP = TRUE;
        return 0;
    }
    dbg_exception_epilog();

    return DBG_CONTINUE;
}
Ejemplo n.º 4
0
static void print_typed_basic(const struct dbg_lvalue* lvalue)
{
    LONGLONG            val_int;
    void*               val_ptr;
    long double         val_real;
    DWORD64             size64;
    DWORD               tag, size, count, bt;
    struct dbg_type     type = lvalue->type;
    struct dbg_type     sub_type;

    if (!types_get_real_type(&type, &tag)) return;

    switch (tag)
    {
    case SymTagBaseType:
        if (!types_get_info(&type, TI_GET_LENGTH, &size64) ||
            !types_get_info(&type, TI_GET_BASETYPE, &bt))
        {
            WINE_ERR("Couldn't get information\n");
            RaiseException(DEBUG_STATUS_INTERNAL_ERROR, 0, 0, NULL);
        }
        size = (DWORD)size64;
        switch (bt)
        {
        case btInt:
            if (!be_cpu->fetch_integer(lvalue, size, TRUE, &val_int)) return;
            dbg_printf("%lld", val_int);
            break;
        case btUInt:
            if (!be_cpu->fetch_integer(lvalue, size, FALSE, &val_int)) return;
            dbg_printf("%llu", val_int);
            break;
        case btFloat:
            if (!be_cpu->fetch_float(lvalue, size, &val_real)) return;
            dbg_printf("%Lf", val_real);
            break;
        case btChar:
            if (!be_cpu->fetch_integer(lvalue, size, TRUE, &val_int)) return;
            /* FIXME: should do the same for a Unicode character (size == 2) */
            if (size == 1 && (val_int < 0x20 || val_int > 0x80))
                dbg_printf("%d", (int)val_int);
            else
                dbg_printf("'%c'", (char)val_int);
            break;
        default:
            WINE_FIXME("Unsupported basetype %lu\n", bt);
            break;
        }
        break;
    case SymTagPointerType:
        if (!memory_read_value(lvalue, sizeof(void*), &val_ptr)) return;

        sub_type.module = lvalue->type.module;
        if (!types_get_info(&type, TI_GET_TYPE, &sub_type.id) ||
            sub_type.id == dbg_itype_none)
        {
            dbg_printf("Internal symbol error: unable to access memory location %p", val_ptr);
            break;
        }
        if (!types_get_real_type(&sub_type, &tag)) return;

        if (types_get_info(&sub_type, TI_GET_SYMTAG, &tag) && tag == SymTagBaseType &&
            types_get_info(&sub_type, TI_GET_BASETYPE, &bt) && bt == btChar &&
            types_get_info(&sub_type, TI_GET_LENGTH, &size64))
        {
            char    buffer[1024];

            if (!val_ptr) dbg_printf("0x0");
            else if (memory_get_string(dbg_curr_process, val_ptr, 
                                       lvalue->cookie == DLV_TARGET,
                                       size64 == 2, buffer, sizeof(buffer)))
                dbg_printf("\"%s\"", buffer);
            else
                dbg_printf("*** invalid address %p ***", val_ptr);
        }
        else dbg_printf("%p", val_ptr);
        break;
    case SymTagArrayType:
    case SymTagUDT:
        assert(lvalue->cookie == DLV_TARGET);
        if (!memory_read_value(lvalue, sizeof(val_ptr), &val_ptr)) return;
        dbg_printf("%p", val_ptr);
        break;
    case SymTagEnum:
        {
            BOOL        ok = FALSE;

            assert(lvalue->cookie == DLV_TARGET);
            /* FIXME: it depends on underlying type for enums 
             * (not supported yet in dbghelp)
             * Assuming 4 as for an int
             */
            if (!be_cpu->fetch_integer(lvalue, 4, TRUE, &val_int)) return;

            if (types_get_info(&type, TI_GET_CHILDRENCOUNT, &count))
            {
                char                    buffer[sizeof(TI_FINDCHILDREN_PARAMS) + 256 * sizeof(DWORD)];
                TI_FINDCHILDREN_PARAMS* fcp = (TI_FINDCHILDREN_PARAMS*)buffer;
                WCHAR*                  ptr;
                char                    tmp[256];
                VARIANT                 variant;
                int                     i;

                fcp->Start = 0;
                while (count)
                {
                    fcp->Count = min(count, 256);
                    if (types_get_info(&type, TI_FINDCHILDREN, fcp))
                    {
                        sub_type.module = type.module;
                        for (i = 0; i < min(fcp->Count, count); i++)
                        {
                            sub_type.id = fcp->ChildId[i];
                            if (!types_get_info(&sub_type, TI_GET_VALUE, &variant)) 
                                continue;
                            switch (variant.n1.n2.vt)
                            {
                            case VT_I4: ok = (val_int == variant.n1.n2.n3.lVal); break;
                            default: WINE_FIXME("Unsupported variant type (%u)\n", variant.n1.n2.vt);
                            }
                            if (ok)
                            {
                                ptr = NULL;
                                types_get_info(&sub_type, TI_GET_SYMNAME, &ptr);
                                if (!ptr) continue;
                                WideCharToMultiByte(CP_ACP, 0, ptr, -1, tmp, sizeof(tmp), NULL, NULL);
                                HeapFree(GetProcessHeap(), 0, ptr);
                                dbg_printf("%s", tmp);
                                count = 0; /* so that we'll get away from outter loop */
                                break;
                            }
                        }
                    }
                }
                count -= min(count, 256);
                fcp->Start += 256;
            }
            if (!ok) dbg_printf("%lld", val_int);
        }
        break;
    default:
        WINE_FIXME("Unsupported tag %lu\n", tag);
        break;
    }
}
Ejemplo n.º 5
0
/***********************************************************************
 *           memory_examine
 *
 * Implementation of the 'x' command.
 */
void memory_examine(const struct dbg_lvalue *lvalue, int count, char format)
{
    int			i;
    char                buffer[256];
    ADDRESS64           addr;
    void               *linear;

    types_extract_as_address(lvalue, &addr);
    linear = memory_to_linear_addr(&addr);

    if (format != 'i' && count > 1)
    {
        print_address(&addr, FALSE);
        dbg_printf(": ");
    }

    switch (format)
    {
    case 'u':
        if (count == 1) count = 256;
        memory_get_string(dbg_curr_process, linear, 
                          TRUE, TRUE, buffer, min(count, sizeof(buffer)));
        dbg_printf("%s\n", buffer);
        return;
    case 's':
        if (count == 1) count = 256;
        memory_get_string(dbg_curr_process, linear,
                          TRUE, FALSE, buffer, min(count, sizeof(buffer)));
        dbg_printf("%s\n", buffer);
        return;
    case 'i':
        while (count-- && memory_disasm_one_insn(&addr));
        return;
    case 'g':
        while (count--)
        {
            GUID guid;
            if (!dbg_read_memory(linear, &guid, sizeof(guid)))
            {
                memory_report_invalid_addr(linear);
                break;
            }
            dbg_printf("{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\n",
                       guid.Data1, guid.Data2, guid.Data3,
                       guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3],
                       guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]);
            linear = (char*)linear + sizeof(guid);
            addr.Offset += sizeof(guid);
            if (count)
            {
                print_address(&addr, FALSE);
                dbg_printf(": ");
            }
        }
        return;

#define DO_DUMP2(_t,_l,_f,_vv) {                                        \
            _t _v;                                                      \
            for (i = 0; i < count; i++) {                               \
                if (!dbg_read_memory(linear, &_v, sizeof(_t)))          \
                { memory_report_invalid_addr(linear); break; }          \
                dbg_printf(_f, (_vv));                                  \
                addr.Offset += sizeof(_t);                              \
                linear = (char*)linear + sizeof(_t);                    \
                if ((i % (_l)) == (_l) - 1 && i != count - 1)           \
                {                                                       \
                    dbg_printf("\n");                                   \
                    print_address(&addr, FALSE);                        \
                    dbg_printf(": ");                                   \
                }                                                       \
            }                                                           \
            dbg_printf("\n");                                           \
        }                                                               \
	return
#define DO_DUMP(_t,_l,_f) DO_DUMP2(_t,_l,_f,_v)

    case 'x': DO_DUMP(int, 4, " %8.8x");
    case 'd': DO_DUMP(unsigned int, 4, " %10d");
    case 'w': DO_DUMP(unsigned short, 8, " %04x");
    case 'c': DO_DUMP2(char, 32, " %c", (_v < 0x20) ? ' ' : _v);
    case 'b': DO_DUMP2(char, 16, " %02x", (_v) & 0xff);
    }
}