Как извлечь поток пользователя из расширения WinDbg?
Я встроил пользовательский поток в дамп (т.е. передал аргумент UserStreamParam в функцию MiniDumpWriteDump). Теперь я пытаюсь извлечь поток из расширения WinDbg. (Обратите внимание, что я проверил, что могу получить поток, используя функцию MiniDumpReadDumpStream).
Я использую метод IDebugAdvanced2::Request с запросом DEBUG_REQUEST_READ_USER_MINIDUMP_STREAM. Я могу получить данные из стандартных потоков. Например, следующий фрагмент правильно извлечет содержимое информационного потока misc.
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
В чем проблема? Как получить содержимое моего пользовательского потока?
3 ответа
Очень поздний ответ
StreamType cannot be UserDefined
StreamTypes
jen-lung chiu of ms
размещено так в списках osronline windbg давно назад
не знаю, устранено ли это ограничение в последнем dbgeng
вы либо получаете его с помощью функции dbghelp независимо
(использование функций dbghelp внутри расширений windbg не рекомендуется)
или проанализируйте поток самостоятельно с помощью 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;
}
}
вывод из userdump, в котором есть 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
Я нашел эту тему, когда искал способ считывать пользовательский поток изdbg
файл.
Ответ @blabb в основном верен и мне очень помог, но у него есть два недостатка:
- Вы должны использовать
MINIDUMP_HEADER.StreamDirectoryRva
чтобы найти список. - Вы не должны преобразовывать запись в , потому что это ошибка (
MINIDUMP_USER_STREAM
является большей структурой, чем , поэтому вы читаете там неинициализированную память) ИспользуйтеMINIDUMP_DIRECTORY
найти нужную часть потока.
Даже если не проверено, это должно работать, если вы заполняете StreamType пользовательским значением (больше, чем LastReservedStream = 0xFFFF) вместо MiscInfoStream.