1

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.

3
  • What does this show: ? poi(0x00000000ffad0de0+8) Commented Dec 3, 2013 at 16:39
  • 0:000> ? poi(0x00000000ffad0de0+8) shows: Evaluate expression: 33214502518391168 = 0076006a`00000180 Commented Dec 4, 2013 at 2:17
  • Almost there. 0x180 = 0n384 which is the low DWORD of the 64 bit value you see. Try using the dwo operator for double words: ? dwo(0x00000000ffad0de0+8) Commented Dec 4, 2013 at 14:12

1 Answer 1

8

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
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.