示例#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;
}
示例#2
0
/******************************************************************
 *		pe_load_dbg_file
 *
 * loads a .dbg file
 */
static BOOL pe_load_dbg_file(const struct process* pcs, struct module* module,
                             const char* dbg_name, DWORD timestamp)
{
    char                                tmp[MAX_PATH];
    HANDLE                              hFile = INVALID_HANDLE_VALUE, hMap = 0;
    const BYTE*                         dbg_mapping = NULL;
    const IMAGE_SEPARATE_DEBUG_HEADER*  hdr;
    const IMAGE_DEBUG_DIRECTORY*        dbg;
    BOOL                                ret = FALSE;

    WINE_TRACE("Processing DBG file %s\n", debugstr_a(dbg_name));

    if (SymFindFileInPath(pcs->handle, NULL, dbg_name, NULL, 0, 0, 0, tmp, dbg_match, NULL) &&
        (hFile = CreateFileA(tmp, GENERIC_READ, FILE_SHARE_READ, NULL,
                             OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) != INVALID_HANDLE_VALUE &&
        ((hMap = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL)) != 0) &&
        ((dbg_mapping = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0)) != NULL))
    {
        hdr = (const IMAGE_SEPARATE_DEBUG_HEADER*)dbg_mapping;
        if (hdr->TimeDateStamp != timestamp)
        {
            WINE_ERR("Warning - %s has incorrect internal timestamp\n",
                     debugstr_a(dbg_name));
            /*
             * Well, sometimes this happens to DBG files which ARE REALLY the
             * right .DBG files but nonetheless this check fails. Anyway,
             * WINDBG (debugger for Windows by Microsoft) loads debug symbols
             * which have incorrect timestamps.
             */
        }
        if (hdr->Signature == IMAGE_SEPARATE_DEBUG_SIGNATURE)
        {
            /* section headers come immediately after debug header */
            const IMAGE_SECTION_HEADER *sectp =
                (const IMAGE_SECTION_HEADER*)(hdr + 1);
            /* and after that and the exported names comes the debug directory */
            dbg = (const IMAGE_DEBUG_DIRECTORY*) 
                (dbg_mapping + sizeof(*hdr) + 
                 hdr->NumberOfSections * sizeof(IMAGE_SECTION_HEADER) +
                 hdr->ExportedNamesSize);


            ret = pe_load_debug_directory(pcs, module, dbg_mapping, sectp,
                                          hdr->NumberOfSections, dbg,
                                          hdr->DebugDirectorySize / sizeof(*dbg));
        }
        else
            ERR("Wrong signature in .DBG file %s\n", debugstr_a(tmp));
    }
    else
        WINE_ERR("-Unable to peruse .DBG file %s (%s)\n", debugstr_a(dbg_name), debugstr_a(tmp));

    if (dbg_mapping) UnmapViewOfFile(dbg_mapping);
    if (hMap) CloseHandle(hMap);
    if (hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile);
    return ret;
}
示例#3
0
int main(int argc, char* argv[])
{
   // Tell dbghelp to print diagnostics to the debugger output.
   SymSetOptions(SYMOPT_DEBUG);

   // Initialize dbghelp
   const HANDLE fakeProcess = (HANDLE)1;
   BOOL result = SymInitialize(fakeProcess, NULL, FALSE);

#ifdef TESTING
   // Set a search path and cache directory. If this isn't set
   // then _NT_SYMBOL_PATH will be used instead.
   // Force setting it here to make sure that the test succeeds.
   SymSetSearchPath(fakeProcess,
              "SRV*c:\\symbolstest*http://msdl.microsoft.com/download/symbols");

   // Valid PDB data to test the code.
   std::string gTextArg = "072FF0EB54D24DFAAE9D13885486EE09";
   const char* ageText = "2";
   const char* fileName = "kernel32.pdb";

   // Valid PE data to test the code
   fileName = "crypt32.dll";
   const char* dateStampText = "4802A0D7";
   const char* sizeText = "95000";
   //fileName = "chrome_child.dll";
   //const char* dateStampText = "5420D824";
   //const char* sizeText = "20a6000";
#else
   if (argc < 4)
   {
       printf("Error: insufficient arguments.\n");
       printf("Usage: %s guid age pdbname\n", argv[0]);
       printf("Usage: %s dateStamp size pename\n", argv[0]);
       printf("Example: %s 6720c31f4ac24f3ab0243e0641a4412f 1 "
              "chrome_child.dll.pdb\n", argv[0]);
       printf("Example: %s 4802A0D7 95000 crypt32.dll\n", argv[0]);
       return 0;
   }

   std::string gTextArg = argv[1];
   const char* dateStampText = argv[1];
   const char* ageText = argv[2];
   const char* sizeText = argv[2];
   const char* fileName = argv[3];
#endif

   // Parse the GUID and age from the text
   GUID g = {};
   DWORD age = 0;
   DWORD dateStamp = 0;
   DWORD size = 0;

   // Settings for SymFindFileInPath
   void* id = nullptr;
   DWORD flags = 0;
   DWORD two = 0;

   const char* ext = strrchr(fileName, '.');
   if (!ext)
   {
     printf("No extension found on %s. Fatal error.\n", fileName);
     return 0;
   }

   if (_stricmp(ext, ".pdb") == 0)
   {
     std::string gText;
     // Scan the GUID argument and remove all non-hex characters. This allows
     // passing GUIDs with '-', '{', and '}' characters.
     for (auto c : gTextArg)
     {
       if (isxdigit(c))
       {
         gText.push_back(c);
       }
     }
     printf("Parsing symbol data for a PDB file.\n");
     if (gText.size() != 32)
     {
         printf("Error: GUIDs must be exactly 32 characters"
                " (%s was stripped to %s).\n", gTextArg.c_str(), gText.c_str());
         return 10;
     }

     int count = sscanf_s(gText.substr(0, 8).c_str(), "%x", &g.Data1);
     DWORD temp;
     count += sscanf_s(gText.substr(8, 4).c_str(), "%x", &temp);
     g.Data2 = (unsigned short)temp;
     count += sscanf_s(gText.substr(12, 4).c_str(), "%x", &temp);
     g.Data3 = (unsigned short)temp;
     for (auto i = 0; i < ARRAYSIZE(g.Data4); ++i)
     {
         count += sscanf_s(gText.substr(16 + i * 2, 2).c_str(), "%x", &temp);
         g.Data4[i] = (unsigned char)temp;
     }
     count += sscanf_s(ageText, "%x", &age);

     if (count != 12)
     {
         printf("Error: couldn't parse the GUID/age string. Sorry.\n");
         return 10;
     }
     flags = SSRVOPT_GUIDPTR;
     id = &g;
     two = age;
     printf("Looking for %s %s %s.\n", gText.c_str(), ageText, fileName);
   }
   else
   {
     printf("Parsing symbol data for a PE (.dll or .exe) file.\n");
     if (strlen(dateStampText) != 8)
       printf("Warning!!! The datestamp (%s) is not eight characters long. "
              "This is usually wrong.\n", dateStampText);
     int count = sscanf_s(dateStampText, "%x", &dateStamp);
     count += sscanf_s(sizeText, "%x", &size);
     flags = SSRVOPT_DWORDPTR;
     id = &dateStamp;
     two = size;
     printf("Looking for %s %x %x.\n", fileName, dateStamp, two);
   }

   char filePath[MAX_PATH] = {};
   DWORD three = 0;

   if (SymFindFileInPath(fakeProcess, NULL, fileName, id, two, three,
               flags, filePath, NULL, NULL))
   {
       printf("Found symbol file - placed it in %s.\n", filePath);
   }
   else
   {
       printf("Error: symbols not found - error %u. Are dbghelp.dll and "
               "symsrv.dll in the same directory as this executable?\n",
               GetLastError());
       printf("Note that symbol server lookups sometimes fail randomly. "
              "Try again?\n");
   }

   SymCleanup(fakeProcess);

   return 0;
}