Reputation: 1099
Debugging .Net String value in windbg and WinDbg and SoS, how do I print/dump a large string? show a script that dump the string to a local file:
$$ 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
}
this script is on x86. I modify the code and try on .net 4.0, x64 system.
the only difference is that the offset is different. for example:
$$ .net 4.0 , the offset is different
$$ MT Field Offset Type VT Attr Value Name
$$ 000007fee4abc7e8 4000103 8 System.Int32 1 instance 460 m_stringLength
$$ 000007fee4abb328 4000104 c System.Char 1 instance 26 m_firstChar
$$ 000007fee4ab6900 4000105 10 System.String 0 shared static Empty
So, I change my code to:
r@$t0= poi(${$string}+8)*2
.writemem ${$arg3}${$string}.txt ${$string}+c ${$string}+c+@$t0
Here, I wonder the function poi,
1. why here need '*2'?
2. I find a string address, run !do, like this:
0:000> !do 0x00000000ffad0de0
Name: System.String
MethodTable: 000007fef5da6738
EEClass: 000007fef592ed68
Size: 794(0x31a) bytes
File: C:\Windows\Microsoft.Net\assembly\GAC_64\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
String: jv15Rr2HXPn3....
Fields:
MT Field Offset Type VT Attr Value Name
000007fef5dac620 4000103 8 System.Int32 1 instance 384 m_stringLength
000007fef5dab160 4000104 c System.Char 1 instance 6a m_firstChar
000007fef5da6738 4000105 10 System.String 0 shared static Empty
I run
0:000> ? poi(0x00000000ffad0de0)+8
Evaluate expression: 8791627818816 = 000007fe`f5da6740
to get the length value of 384, but the output value is wrong(displayed is 8791627818816). What is wrong?
Thank you for helping me!
updated 1): I tried:
0:000> r@$t0= poi(0x00000000ffad0de0+8)
0:000> r@$t0
$t0=0076006a00000180
the result seems not correct.
Update 2): I tried to debug the script:
.echo ${$str}
r@$t0= poi(${$str}+8)*2
.printf "@$t0 is %d\n", @$t0
.echo ${$arg3}${$str}.txt
.printf "${$str}+c: %p\n", ${$str}+c
.printf "${$str}+c+@$t0: %p\n", ${$str}+c+@$t0
$$.writemem ${$arg3}${$str}.txt ${$str}+c ${$str}+c+@$t0
then I got the output:
0x00000000ffad4550
@$t0 is 640
c:\stringtest\0x00000000ffad4550.txt
0x00000000ffad4550+c: 00000000ffad455c
0x00000000ffad4550+c+@$t0: 00ec00d4ffad47dc
then I run the .writemem for the output address:
0:000> .writemem c:\stringtest\ss.txt 00000000ffad455c L0n640
Writing 280 bytes.
I got the correct string, it's like this:
/txrqcf...........j7ULyzqxSmB3bpu
I run the command:
0:000> .writemem c:\stringtest\ss.txt 00000000ffad455c 00ec00d4ffad47dc
^ Range error
I got the error Range error, I check the link to find out the result, but I have no idea.
Upvotes: 1
Views: 7786
Reputation: 59575
poi(${$string}+8) is the string length in characters.
*2 is needed because Strings in C# are Unicode and for writing memory, we need the bytes, not characters.
+c is the offset of the char[] on 64 bit. That's the start address to write from.
? poi(0x00000000ffad0de0)+8
This is incorrect, because poi(0x00000000ffad0de0) gives you the value of the method table of the .NET object, which is 000007fef5da6738 and then you add 8, which is 7FEF5DA6740.
What you want to do is
? poi(0x00000000ffad0de0+8)
inside the braces.
To bypass the range error, use the L? syntax instead range start and range end:
.writemem ${$arg3}${$str}.txt ${$str}+c L? @$t0
Upvotes: 8