c++ 如何从WinDbg扩展中提取用户流?

3phpmpom  于 2022-12-15  发布在  其他
关注(0)|答案(3)|浏览(151)

我已经在转储中嵌入了一个自定义流(例如,将UserStreamParam参数传递给MiniDumpWriteDump函数)。现在,我尝试从WinDbg扩展中提取流。(注意,我已经验证了可以使用MiniDumpReadDumpStream函数检索流)。
我正在使用IDebugAdvanced2::Request方法和DEBUG_REQUEST_READ_USER_MINIDUMP_STREAM请求。我能够从标准流中检索数据。例如,下面的代码片段将正确检索misc info流的内容。

DEBUG_READ_USER_MINIDUMP_STREAM rums = {};
rums.StreamType = MiscInfoStream;
rums.Buffer = &buf;
rums.BufferSize = sizeof buf;
hr = p->Request(DEBUG_REQUEST_READ_USER_MINIDUMP_STREAM,
    &rums, sizeof rums, 0, 0, 0);

但是,尝试检索自己的流将导致错误(0x80070570,ERROR_FILE_CORRUPT)和WinDbg输出

Dir entry 11, ??? stream has unknown stream type 6381921

请注意,.dumpdebug输出中也显示了相同的消息。

Stream 11: type ??? (6381921), size 00000038, RVA 00033FA9
Dir entry 11, ??? stream has unknown stream type 6381921

问题是什么?我如何检索我的用户流的内容?

6za6bjd0

6za6bjd01#

很晚才答复
StreamType cannot be UserDefined流类型
jen-lung chiu of ms张贴,所以在osronline windbg列表很久以前
我不知道最新的dbgeng是否消除了此限制
您可以使用dbghelp函数独立检索它
(不推荐在windbg扩展中使用dbgelp函数)
或者自己用fopen()fread()解析流,如下所示

userstream:\>type ..\usrstr.cpp

#include <stdio.h>
#include <engextcpp.hpp>
#include <dbghelp.h>

const ULONG MBUFFSIZE = 0x1000;
PVOID   Buff = 0;

int __cdecl ReadUserStream (char *dmpfile)
{
    PMINIDUMP_HEADER MiniHeader = 0;
    PMINIDUMP_DIRECTORY MiniDir = 0;
    PMINIDUMP_USER_STREAM userstream = 0;
    size_t result = 0;
    ULONG Streams =0;
    ULONG i = 0;
    FILE * fp = fopen(dmpfile,"rb");
    if (fp)
    {
        result = fread(Buff, 1, sizeof(MINIDUMP_HEADER), fp );
        if ( result == sizeof(MINIDUMP_HEADER) )
        {
            MiniHeader = (PMINIDUMP_HEADER) Buff;
            Streams = MiniHeader->NumberOfStreams;
            for (i  = 0; i < Streams; i++ )
            {
                result = fread( Buff, 1, sizeof(MINIDUMP_DIRECTORY), fp );
                if ( result == sizeof(MINIDUMP_DIRECTORY) )
                {
                    MiniDir = (PMINIDUMP_DIRECTORY) Buff;
                    if ( MiniDir->StreamType > LastReservedStream )
                    {
                        userstream = (PMINIDUMP_USER_STREAM)Buff;
                        ULONG savedbuffsize = userstream->BufferSize;
                        ULONG savedtype = userstream->Type;
                        PCHAR savedbufferptr = (PCHAR)userstream->Buffer;
                        long pos = ftell(fp);
                        fseek(fp, (long)savedbufferptr,SEEK_SET);
                        result = fread( Buff, 1, savedbuffsize, fp );
                        if ( result == savedbuffsize )
                        {
                            printf(
                                "\n"
                                "Datastream Type = %.8x\n"
                                "Buffer Size     = %.8x\n"
                                "Buffer          = %p\n"
                                "Buffer content  = %s\n"
                                "\n",
                                savedtype,
                                savedbuffsize,
                                savedbufferptr,
                                Buff
                                );
                            fseek(fp,pos,SEEK_SET);
                            continue;
                        }
                        else
                        {
                            printf(
                                "failed to read buffer contents at offset %p of
user stream %x\n",
                                savedbufferptr,
                                savedtype);
                            fseek(fp,pos,SEEK_SET);
                            continue;
                        }
                    }

                }
                else
                {
                    printf("failed to fread Minidump directory exiting \n");
                    goto getout;
                }

            }
        }
        else
        {
            printf("failed to fread Minidump header exiting \n");
            goto getout;
        }
    }
    else
    {
        printf("failed to open dmp file exiting \n");
        goto getout;
    }
getout:
    if (fp)
        fclose(fp);
    return 0;
}

int __cdecl main (int argc, char * argv[])
{
    if (argc !=2)
    {
        printf("Usage %s %s\n",argv[0],"somedump.dmp");
        return 0;
    }
    Buff = malloc( MBUFFSIZE );
    if (Buff)
    {
        ReadUserStream(argv[1]);
        free(Buff);
        return 0;
    }
    else
    {
        printf("malloc failed exiting\n");
        return 0;
    }
}

包含userStreams的用户转储的输出
oleg staradumov debuginfo.com writeuserstream.cpp

userstream:\>usrstr.exe
Usage usrstr.exe somedump.dmp

userstream:\>usrstr.exe test.dmp
Datastream Type = 00010000
Buffer Size     = 00000021
Buffer          = 000010B6
Buffer content  = This is the first data stream...

Datastream Type = 00010001
Buffer Size     = 00000023
Buffer          = 000010D7
Buffer content  = and this is the second data stream
1zmg4dgp

1zmg4dgp2#

即使没有经过测试,如果您使用自定义值(大于LastReservedStream = 0xFFFF)而不是MiscInfoStream填充StreamType,它也应该可以工作。

cig3rfwq

cig3rfwq3#

我在寻找从dbg文件中读出用户流的方法时发现了这个主题。
Blabb的回答基本正确,对我帮助很大,但它有两个缺陷:
1.您应该使用MINIDUMP_HEADER.StreamDirectoryRva来查找MINIDUMP_DIRECTORY列表。
1.您不应该将MINIDUMP_DIRECTORY条目转换为MINIDUMP_USER_STREAM,因为这是一个错误(MINIDUMP_USER_STREAM是一个比MINIDUMP_DIRECTORY大的结构体,因此您在那里阅读的是未初始化的内存)。使用MINIDUMP_DIRECTORY来定位流中所需的部分。

相关问题