WinDbg and SoS, how do I print/dump a large string?
I am debugging a hangdump coming from a production server using WinDbg with the SoS extension.
There is a string parameter in one of the stacks, that I need to know the value of. However, it is a rather large string, and WinDbg won't print it when I am using DumpObj
. This is the output from DumpObj
:
0:036> !do 00000001b30d8668
Name: System.String
MethodTable: 0000064278436728
EEClass: 000006427803e520
Size: 5125300(0x4e34b4) bytes
(C:\WINDOWS\assembly\GAC_64\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)
String: <String is invalid or too large to print>
Fields:
MT Field Offset Type VT Attr Value Name
000006427843d998 4000096 8 System.Int32 1 instance 2562638 m_arrayLength
000006427843d998 4000097 c System.Int32 1 instance 2562637 m_stringLength
0000064278438170 4000098 10 System.Char 1 instance 3c m_firstChar
0000064278436728 4000099 20 System.String 0 shared static Empty
>> Domain:Value 0000000000163260:000000007fff0370 00000000001a6760:000000007fff0370 <<
0000064278438020 400009a 28 System.Char[] 0 shared static WhitespaceChars
开发者_运维技巧 >> Domain:Value 0000000000163260:000000007fff0b60 00000000001a6760:000000007fff89f0 <<
How can I get the value of this string instance ? Preferably dumped to a file.
Here is a script I wrote to dump strings to a file within windbg.
$$ Dumps the managed strings to a file
$$ Platform x86
$$ Usage $$>a<"c:\temp\dumpstringtofolder.txt" 6544f9ac 5000 c:\temp\stringtest
$$ First argument is the string method table pointer
$$ Second argument is the Min size of the string that needs to be used filter
$$ the strings
$$ Third is the path of the file
.foreach ($string {!dumpheap -short -mt ${$arg1} -min ${$arg2}})
{
$$ MT Field Offset Type VT Attr Value Name
$$ 65452978 40000ed 4 System.Int32 1 instance 71117 m_stringLength
$$ 65451dc8 40000ee 8 System.Char 1 instance 3c m_firstChar
$$ 6544f9ac 40000ef 8 System.String 0 shared static Empty
$$ start of string is stored in the 8th offset, which can be inferred from above
$$ Size of the string which is stored in the 4th offset
r@$t0= poi(${$string}+4)*2
.writemem ${$arg3}${$string}.txt ${$string}+8 ${$string}+8+@$t0
}
and this is how it can be used$$>a<”c:\temp\dumpstringtofolder.txt” 6544f9ac 5000 c:\temp\stringtest
The dumped contents would be in Unicode format and to view its contents use something like this Console.WriteLine(ASCIIEncoding.Unicode.GetString(File.ReadAllBytes(@"c:\temp\stringtest03575270.txt")));
HTH
I would think twice before dumping 2562638 characters worth of text, but if you really want to, the text is stored following the fields of the string instance, so you can do a du <address+offset> <end address>
to dump the actual text of the string. The output will look something like this:
00000000`132ab050 "this is an extremely long string"
00000000`132ab090 " of text, so don't even bother t"
00000000`132ab0d0 "o try to dump it to the screen -"
By logging the session output to a file, you can easily capture the output and do whatever post-processing you need.
I have modified @Naveen's script to work on x64 platforms.
Great script btw!
$$ Dumps the managed strings to a file
$$ Platform x64
$$ Usage $$>a<"c:\temp\dumpstringtofolder.txt" 00007ffa6c509808 5000 c:\temp\stringtest
$$ First argument is the string method table pointer
$$ Second argument is the Min size of the string that needs to be used filter
$$ the strings
$$ Third is the path of the file
.foreach ($string {!dumpheap -short -mt ${$arg1} -min ${$arg2}})
{
$$ MT Field Offset Type VT Attr Value Name
$$ 00007ffa6c50c158 400027b 8 System.Int32 1 instance 18 m_stringLength
$$ 00007ffa6c50a9c0 400027c c System.Char 1 instance 53 m_firstChar
$$ 00007ffa6c509808 4000280 c0 System.String 0 shared static Empty
$$ start of string is stored in the 8th offset, which can be inferred from above
$$ Size of the string which is stored in the c-th offset
r@$t0= (poi(${$string}+8) & 00000000FFFFFFFF) *2
.writemem ${$arg3}${$string}.txt (${$string}+c) (${$string}+c+@$t0)
}
If you are in a hurry, run the !do after enabling logs in WinDbg. In the log file, you will get the entire string.
In WinDbg menu, go to Edit-> Open/Close log file, to set log file path.
精彩评论