1

I'm just doing some debugging on a Windows 7 crash dump, and I've come across a singly-linked list that I'm not able to fully understand.

Here's the output from WinDBG:

dt _GENERAL_LOOKASIDE_POOL fffff80002a14800 -b
....
0x000 SingleListHead: _SINGLE_LIST_ENTRY
    +0x000 Next: 0x0000000000220001
....

From what I've been reading, it seems that each singly linked list begins with a list head, which contains a pointer to the first element in the list, or null if the list is empty.

Microsoft state: MSDN article

For a SINGLE_LIST_ENTRY that serves as a list entry, the Next member points to the next entry in the list, or NULL if there is no next entry in the list. For a SINGLE_LIST_ENTRY that serves as the list header, the Next member points to the first entry in the list, or NULL if the list is empty.

I'm 99% sure this list contains some entries, but I don't understand how the value of 0x0000000000220001 is supposed to be pointing to anything. This value certainly doesn't resolve to a valid page mapping, so I can only assume it's some kind of offset. However, I'm not sure.

If anyone could help shine some light on this, I'd appreciate it.

Thanks

UPDATE

I've just found a document (translated from Chinese) that seems to explain the structure a little more. If anyone could offer some input on it, I'd appreciate it.

Lookaside List article

What I'm actually looking at is a lookaside list that Windows should be using for the allocation of IRPs, here's the full output from WinDBG (values changed from original question):

lkd> !lookaside iopsmallirplookasidelist

Lookaside "" @ fffff80002a14800 "Irps"
Type     =     0000 NonPagedPool
Current Depth  =        0   Max Depth  =        4
Size           =      280   Max Alloc  =     1120
AllocateMisses =      127   FreeMisses =       26
TotalAllocates =      190   TotalFrees =       90
Hit Rate       =       33%  Hit Rate   =       71%

lkd> dt _general_lookaside fffff80002a14800 -b
ntdll!_GENERAL_LOOKASIDE
  +0x000 ListHead         : _SLIST_HEADER
  +0x000 Alignment        : 0x400001
  +0x008 Region           : 0xfffffa80`01e83b11
  +0x000 Header8          : <unnamed-tag>
     +0x000 Depth            : 0y0000000000000001 (0x1)
     +0x000 Sequence         : 0y001000000 (0x40)
     +0x000 NextEntry        : 0y000000000000000000000000000000000000000 (0)
     +0x008 HeaderType       : 0y1
     +0x008 Init             : 0y0
     +0x008 Reserved         : 0y11111111111111111101010000000000000011110100000111011000100       (0x7fffea0007a0ec4)
     +0x008 Region           : 0y111
  +0x000 Header16         : <unnamed-tag>
     +0x000 Depth            : 0y0000000000000001 (0x1)
     +0x000 Sequence         : 0y000000000000000000000000000000000000000001000000 (0x40)
     +0x008 HeaderType       : 0y1
     +0x008 Init             : 0y0
     +0x008 Reserved         : 0y00
     +0x008 NextEntry        : 0y111111111111111111111010100000000000000111101000001110110001 (0xfffffa8001e83b1)
  +0x000 HeaderX64        : <unnamed-tag>
     +0x000 Depth            : 0y0000000000000001 (0x1)
     +0x000 Sequence         : 0y000000000000000000000000000000000000000001000000 (0x40)
     +0x008 HeaderType       : 0y1
     +0x008 Reserved         : 0y000
     +0x008 NextEntry        : 0y111111111111111111111010100000000000000111101000001110110001 (0xfffffa8001e83b1)
  +0x000 SingleListHead   : _SINGLE_LIST_ENTRY
      +0x000 Next             : 0x00000000`00400001 
  +0x010 Depth            : 4
  +0x012 MaximumDepth     : 0x20
  +0x014 TotalAllocates   : 0xbe
  +0x018 AllocateMisses   : 0x7f
  +0x018 AllocateHits     : 0x7f
  +0x01c TotalFrees       : 0x5a
  +0x020 FreeMisses       : 0x1a
  +0x020 FreeHits         : 0x1a
  +0x024 Type             : 0 ( NonPagedPool )
  +0x028 Tag              : 0x73707249
  +0x02c Size             : 0x118
  +0x030 AllocateEx       : 0xfffff800`029c30e0 
  +0x030 Allocate         : 0xfffff800`029c30e0 
  +0x038 FreeEx           : 0xfffff800`029c30d0 
  +0x038 Free             : 0xfffff800`029c30d0 
  +0x040 ListEntry        : _LIST_ENTRY [ 0xfffff800`02a147c0 - 0xfffff800`02a148c0 ]
     +0x000 Flink            : 0xfffff800`02a147c0 
     +0x008 Blink            : 0xfffff800`02a148c0 
  +0x050 LastTotalAllocates : 0xbe
  +0x054 LastAllocateMisses : 0x7f
  +0x054 LastAllocateHits : 0x7f
  +0x058 Future           : 
   [00] 0
   [01] 0

lkd> !slist fffff80002a14800
SLIST HEADER:
   +0x000 Header16.Sequence          : 40
   +0x000 Header16.Depth            : 1

SLIST CONTENTS:
fffffa8001e83b10  0000000000000000 0000000000000000 
                  0000000000000404 0000000000000000 

Sorry if some of the formatting is lost. Essentially, this should be a lookaside list that contains a list of chunks that are all of the same size 0x118 (sizeof(_IRP) + sizeof(_IO_STACK_LOCATION))

However I'm not entirely sure how the list is actually put together, I'm not sure if this should be a singly linked list of memory chunks, or if I'm reading all of it incorrectly.

Tony
  • 3,587
  • 8
  • 44
  • 77
  • Are you sure that `fffff80002a14800` address really contains `_GENERAL_LOOKASIDE_POOL` structure? What shows `db fffff80002a14800` command? The region begins with address fffff80000000000 and 512G in size is used to store code and data structures initialized when Windows starts up. – Serg Nov 12 '13 at 17:04
  • I'm fairly sure that's the right structure. The address came from the !lookaside WinDBG command and should belong to the 'IopSmallIrpLookasideList'. The db command shows what appears to be a kernel pool chunk with the tag 'Irps'. – Tony Nov 12 '13 at 17:13
  • Gentle reminder: do avoid assuming you'll see sane pointer values in the minidump of a process or OS that crashed. – Hans Passant Nov 12 '13 at 18:00
  • Fair point Hans, however I've also taken a look on a live system, and the pointer values are of the same format. – Tony Nov 12 '13 at 19:03
  • Try `!pool fffff80002a14800` and `!object fffff80002a14800` commands. That they will show. Can you share dump? – Serg Nov 13 '13 at 05:43
  • Both the !pool and !object commands don't reveal any information. The address doesn't point to an object. I've found a document that seems to contain an overview of the structure. I'll update the question. – Tony Nov 13 '13 at 11:00

2 Answers2

1

SINGLE_LIST_ENTRY implements intrusive linked-lists. Look for struct list_head which offers similar functionnality within the linux kernel.

As for the .Next member, it really is a pointer to a SINGLE_LIST_ENTRY that is most likely embedded inside another struct.

diapir
  • 2,872
  • 1
  • 19
  • 26
  • Hmmm, I'm confused how to actually get the next entry in the list? – Tony Nov 12 '13 at 15:57
  • Well in this case, the .next value is 0x0000000000220001. Which doesn't resolve to a physical address through the page tables. – Tony Nov 12 '13 at 16:35
1

In case of small irp list with win7x86rtm:

lkd> !lookaside iopsmallirplookasidelist 
Lookaside "" @ 82d5ffc0 "Irps"
....
lkd> dt _SINGLE_LIST_ENTRY 82d5ffc0 
nt!_SINGLE_LIST_ENTRY
   +0x000 Next             : 0x86737e30 _SINGLE_LIST_ENTRY
....
lkd> !pool 0x86737e30 
Pool page 86737e30 region is Nonpaged pool
*86737e28 size:   a0 previous size:   48  (Allocated) *Irp 
        Pooltag Irp  : Io, IRP packets

The size of memory chank is a0 bytes

lkd> ?? sizeof(_pool_header)+sizeof(_single_list_entry)+sizeof(_irp)+sizeof(_io_stack_location)
unsigned int 0xa0

which include pool header, pointer, irp, stack location

Minor update:

Author Tarjei Mandt aka @kernelpool

In _GENERAL_LOOKASIDE structure, SingleListHead.Next points to the first free pool chunk on the singly-linked lookaside list. The size of the lookaside list is limited by the value of Depth, periodically adjusted by the balance set manager according to the number of hits and misses on the lookaside list. Hence, a frequently used lookaside list will have a larger Depth value than an infrequently used list. The intial Depth is 4 nt!ExMinimumLookasideDepth, with maximum being MaximumDepth (256)...more

Serg
  • 2,140
  • 1
  • 12
  • 14
  • I've got both of the structures, however I don't understand how the lookaside list is actually storing the free/used blocks. I'll add the output of windbg to the question. Thanks – Tony Nov 13 '13 at 12:30