views:

79

answers:

1

Hi, I have taken a dump of W3wp.exe process and am trying to retrieve the contents of session using Windbg. My test application is ASP.net 3.5 running on Windows 7 64 bit and the session is inprocess. I can retrieve the contents of various other objects but am struggling to find where session contents is located.

Yes I know storing stuff in session is bad but I need this to help debug an issue at a clients site.

I found a great post by Tess Ferrendez (http://blogs.msdn.com/b/tess/archive/2007/09/18/debugging-script-dumping-out-asp-net-session-contents.aspx) that describes creating a script to iterate through everything in session.

I suspect however that this was aimed at a previous version of IIS (and possibly .net & 32bit) as Tess's script looks for InProcSessionState objects which dont seem to exist in my dump.

Any ideas how to get at the contents of session from a dump?

Thanks,

Alex

+2  A: 

This solution is for dumping x64 asp.net session objects.

Here is the sample code i used to add the items to session.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

public partial class _Default : System.Web.UI.Page 
{
    protected void Page_Load(object sender, EventArgs e)
    {
        this.Session.Add("Name", "Test");
        this.Session.Add("Name1", "Test1");
    }
}

Here is the script to get the contents of the HttpSession object

  .foreach ($obj {!dumpheap -mt ${$arg1} -short}) 
{
   $$ The !dumpheap -short option has last result as --------------- and 
   $$ this .if is to avoid this
   .if ($spat ("${$obj}","------------------------------")) 
     {} 
   .else 
     {
        $$ $t5 contains refernce to the array which has key and value for the
        $$ session contents

        r$t5 = poi(poi(poi(poi(${$obj}+0x8)+0x10)+0x8)+0x8);
         r$t1 = 0
        .for (r $t0=0; @$t0 < poi(@$t5+0x8); r$t0=@$t0+1 ) 
        {
          .if(@$t0 = 0) 
          { 
            $$ First occurence of the element in the array would be in the 20 offset
             r$t1=20
          }
          .else 
           { 
            $$ the rest of the elements would be in the 8th offset
            r$t1= 20+(@$t0*8)
           };

          $$ Check for null before trying to dump          

          .if (poi((@$t5-0x8)+@$t1) = 0 )
           {
              .continue
           } 
          .else
           {              
               .echo ************;
               ? @$t0
               $$ Session Key
               .printf "Session Key is :- "; !ds poi(poi((@$t5-0x8)+@$t1)+0x8);
               $$ Session value
               .printf "Session value is :- ";!ds poi(poi((@$t5-0x8)+@$t1)+0x10)
           }
        }
      }
}

Copy the above script in to a file and invoke the script like this $$>a<"c:\temp\test.txt" 000007fef4115c20 within Windbg. Passing the MT of System.Web.SessionState.HttpSessionState as the script argument.

And here is the output from the script

************ 
Evaluate expression: 0 = 00000000`00000000 
Session Key is :- Name  
Session value is :- Test 
************ 
Evaluate expression: 1 = 00000000`00000001 
Session Key is :- Name1  
Session value is :- Test1

I use the alias !ds for dumping strings instead of using !dumpobj. To create the alias use this command as !ds .printf "%mu \n", 10+

The script is little bit arcane unless you are used to writing windbg scripts.

Here is a brief explanation of the script

  1. $t5 - Contains reference to the array of type System.Collections.Specialized.NameObjectCollectionBase+NameObjectEntry
  2. The nested .for loop is to iterate through the array items. I have blogged about the same if you are interested in understanding custom dumparray
  3. The .if statement within the nested for loop .if (poi((@$t5-0x8)+@$t1) = 0) checks if the item is null before dumping the contents using !ds command.
  4. !ds poi(poi((@$t5-0x8)+@$t1)+0x8) :- The key string for the session . Example Name
  5. !ds poi(poi((@$t5-0x8)+@$t1)+0x10) :- The session value . Example Test

HTH

EDIT:- Also here is a platform independent script . This should work for x86 and x64

r $t9 = @$ptrsize;
$$ $t8 register contains the next offset of the variable 
$$ $t7 register contains array start address 
.if (@$ptrsize = 8)
{ 
  r $t8 = 10
  r $t7 = 20
  r $t6 = 10
} 
.else 
{
  r $t8 = 6
  r $t6 = 8
  r $t7 = 10
}  
.foreach ($obj {!dumpheap -mt ${$arg1} -short}) 
{
   $$ The !dumpheap -short option has last result as --------------- and 
   $$ this .if is to avoid this
   .if ($spat ("${$obj}","------------------------------")) 
     {} 
   .else 
     {
        $$ $t5 contains refernce to the array which has key and value for the
        $$ session contents

         r$t5 = poi(poi(poi(poi(${$obj}+@$t9)+@$t6)+@$t9)+@$t9);
        .for (r $t0=0; @$t0 < poi(@$t5+@$t9); r$t0=@$t0+1 ) 
        {
          .if(@$t0 = 0) 
          { 
            $$ First occurence of the element in the array would be in the 20 offset
             r$t1=@$t7
          }
          .else 
           { 
            $$ the rest of the elements would be in the 8th offset
            r$t1= @$t7+(@$t0*@$t9)
           };
          $$ Check for null before trying to dump          
          .if (poi((@$t5-@$t9)+@$t1) = 0 )
           {
              .continue
           } 
          .else
           {              
               .echo ************;
               ? @$t0
               $$ Session Key
               .printf "Session Key is :- "; !ds poi(poi((@$t5-@$t9)+@$t1)+@$t9);
               $$ Session value
               .printf "Session value is :- ";!ds poi(poi((@$t5-@$t9)+@$t1)+@$t6)
           }
        }
      }
}
Naveen
Hi Naveen thanks very much for looking at this issue however I am getting the following error: Memory access error at ')+0x4)+0x4); .for (r $t0=0; @$t0 < poi(@$t5+0x4); r$t0=@$t0+1 ) ;{ r$t1 = 0; .if(@$t0 = 0) { r$t1=10} .else { r$t1= 10+ @$t0*4};.echo ************; .if (poi((@$t5-0x4)+@$t1) =0) {} .else {!ds poi(poi((@$t5-0x4)+@$t1)+0x4);!ds poi(poi((@$t5-0x4)+@$t1)+0x8)} }'. I have replaced the address after the -mt switch with HttpSessionState MT address. Are you running this on a 64bit dump as the addresses look different?
alexmac
Hi Alexmac, Sorry about that i used the x86 instead of x64. I have fixed the script for x64 and updated the answer.
Naveen