Archive for the ‘WinDBG’ Category

Object Tracking and WinDBG

Wednesday, August 25th, 2010

The Object Manager (Ob) in Windows provides and excellent feature called object tracking, which causes the Ob to maintain a list of every active object in the system. When activated, it allows you to find every driver object, event object, file object, mutex object, etc. at any point in time via the !object command. While the overhead of this is likely to be unacceptable for everyday use, in certain debugging situations it can be immensely helpful. For example, I recently debugged an issue where autochk would not run when our file system filter was installed on the system. I suspected that  a rogue file object was preventing NTFS from dismounting, so I turned on object tracking in order to quickly find the file object causing the problem (turned out to be multiple file objects).

Unfortunately things have changed in Windows 7 and the debugging tools haven’t caught up so this no longer works, but I’ll provide a solution to that once I get there…

Enabling Object Tracking

Object tracking is enabled via the FLG_MAINTAIN_OBJECT_TYPELIST GFlags option. You can enable this via the GFlags utility on the target machine, but I prefer to do it via the debugger on a per-boot basis so that I don’t have to remember to shut it off:

1: kd> !gflag + otl
Current NtGlobalFlag contents: 0x00004000
    otl - Maintain a list of objects for each type

Important note: This must be done very early in the boot process before the Ob initializes. I recommend setting an initial break in the debugger by using the WinDBG command CTRL+ALT+K and using the !gflag command at the initial break.

Once you’ve enabled the command, just hit Go and proceed to run whatever tests or do whatever you like. Once you’re ready to start inspecting objects, the path you will take will differ on Vista (and earlier) and Windows 7.

Dumping Objects Prior To Win7

Prior to Win7, life is fairly straightforward as the !object command supports walking the object list. The syntax for the command is:

!object 0 Name

Where Name is documented to be:

Name
If the first argument is zero, the second argument is interpreted as the name of a class of system objects for which to display all instances.

So, for example:

!object 0 File
!object 0 Event
!object 0 Semaphore
!object 0 Device
!object 0 Driver

Any of these will dump out all of the objects of that particular type and you can then pick through and do whatever it is you do with that information.

Dumping Objects on Win7

Now for the fun part. If you attempt to run any of the above !object  commands on a Win7 target, you’ll get the following error:

1: kd> !object 0 File
Scanning 723 objects of type 'File'
WARNING: Object header 83d8bb48 flag (42) does not have
OB_FLAG_CREATOR_INFO (4) set

The problem is that starting with Win7, that flag no longer exists. Instead, the object header tracks whether or not this feature is enabled via another field in the header. So, unfortunately, the Ob changed but the !object command wasn’t updated to reflect the changes.

We can get this back though from a gratuitously complicated debugger command that walks the list starting at an entry. Finding the starting entry could be simplified, but I’ll make you find it manually because that’s how I did it when I wrote the script and I don’t want to make it too easy on you :)

Also, I’ll apologize in advance for the script being on a single line and thus guaranteeing that it will require some sort of WinDBG Rosetta Stone in order to decipher (again, because that’s how I did it when I wrote it…Job security!).

First, you’ll need to dump the global type variable for the type of objects you want to see. Examples of these are IoFileObjectType, ExEventObjectType, IoDriverObjectType, etc. (if you’re having trouble finding the name of the one you want just let me know). I’ll pick the file object type:

1: kd> x nt!iofileobjecttype
82775a54 nt!IoFileObjectType = 0x83d656e0
1: kd> dt nt!_object_type 0x83d656e0
   +0x000 TypeList         : _LIST_ENTRY [ 0x83d8bb38 - 0x846022d0 ]
   +0x008 Name             : _UNICODE_STRING "File"
   +0x010 DefaultObject    : 0x0000005c Void
   +0x014 Index            : 0x1c ''
   +0x018 TotalNumberOfObjects : 0x2d3
   +0x01c TotalNumberOfHandles : 0xaa
   +0x020 HighWaterNumberOfObjects : 0x691
   +0x024 HighWaterNumberOfHandles : 0xb6
   +0x028 TypeInfo         : _OBJECT_TYPE_INITIALIZER
   +0x078 TypeLock         : _EX_PUSH_LOCK
   +0x07c Key              : 0x656c6946
   +0x080 CallbackList     : _LIST_ENTRY [ 0x83d65760 - 0x83d65760 ] 

Note the TypeList field. That’s the list of currently valid objects for that type in the system in the form of OBJECT_HEADER_CREATOR_INFO structures, which currently exist directly before the object header. So, TypeList entry address + sizeof(OBJECT_HEADER_CREATOR_INFO) + FIELD_OFFSET(OBJECT_HEADER, Body) is where the actual object address is. I’ll put that all together into the following command (I’m going to break it up C style with “\” characters so you can see it, please remove before actually using and make into a single line):

r @$t0 = @@(sizeof(nt!_object_header_creator_info) \
+ #FIELD_OFFSET(nt!_object_header, Body)); \
!list "-x \".block {as /x Res @$extret+@$t0} ;\
.block{.echo ${Res}; !object ${Res}} ; \
ad /q Res\" 0x83d8bb38" 

Note that the address used at the end of the command is from the dt output above in bold. Also remember that it’s written to occupy a single line, so it needs to get pasted into the KD prompt with no newlines and those backslashes removed. Running the command should provide you with relatively the same output at the old !object command on previous O/S releases.

If you’d like to clean up the script or, even better, turn it into a debugger extension that takes a name like !object, please let me know or send along the results. Right now it’s on my ever increases prioritized list of things to do and I’d like to take it off :)

Undocumented !process flags and switches

Monday, August 23rd, 2010

There are two options added to the !process command that haven’t made it into the documentation yet.

The first option is the /h switch, which appears to allow for searching the process list for a process with too many open handles:

0: kd> !process /h 0n10000
Searching processes with HandleCount > 10000

The only problem with this is that it appears to stop on the first process that is above that limit. This prevents it from being a generically useful command as you’re probably looking for any processes with large handle counts. For that purpose, I’ve whipped up this WinDBG script that will search for any process with open handles above a specified amount:

.if (${/d:$arg2} != 1)
{
    .echo Performing scan for processes with handle count > ${$arg1};
    !for_each_process "$$>a<${$arg0} ${$arg1} 1";
}
.else
{
    r? @$t0 = ((nt!_eprocess *)${@#Process});
    aS handleCount "@@(@$t0->ObjectTable->HandleCount)";
    .block
    {
        .if (${handleCount} > ${$arg1})
        {
           .printf /on "Process %p has %d handles\n", @$t0, ${handleCount};
        }
    }
    ad handleCount;
}

Save that to a file called bighandle.wbs and execute the following command in WinDBG:

0: kd> $$>a<c:\\dumps\\bighandle.wbs 0n500
Performing scan for processes with handle count > 0n500
Process 848bfd40 has 5568 handles
Process 862e9530 has 579 handles
Process 86374d40 has 997 handles
Process 86334150 has 661 handles
Process 849eb4a0 has 973 handles 

Note that the double backslashes are important on the command line and it won’t work properly without them. This script could be enhanced to just grab the process with the greatest number of handles, if you want to give that a whirl and submit it pass it along to me (snoone at analyze-v dot com).

The other interesting undocumented feature of !process is bit 5 in the flags (0×20). This causes !process to include information about the process PEB in the output. This also requires that bit 4 (0×10) be present due to the fact that the PEB is process context specific. So, for example:

0: kd> !process 849eb4a0 31

(Remaining output left as an exercise to the reader.)

Break on user mode module load

Friday, August 20th, 2010

Every now and then I need to have the debugger break in when a user mode module loads. For example, I may want to set a process specific breakpoint but the process in question isn’t loaded yet. Normally this would be a giant pain, but with a few quick debugger commands it’s all too easy.

First thing we need to do is get the debugger notified of user module loads. Normally the OS doesn’t bother letting the kernel debugger know when a user module gets loaded, but this can be enabled via GFlags option Enable loading of kernel debugger symbols (a misnomer in this usage). Instead of running the GFlags application on the target machine, we can enable it dynamically in the debugger with the !gflags command:

0: kd> !gflag +ksl
Current NtGlobalFlag contents: 0x00040000
    ksl - Enable loading of kernel debugger symbols

Now that we have that done, we can use the sxe ld command to enable a breakpoint when the module of interest loads. Note that this could be a DLL, EXE, service, driver, whatever:

0: kd> sxe ld notepad.exe

Now I’ll run Notepad on the target machine and hopefully get a breakpoint (which indeed I did):

0: kd> g
nt!DbgLoadUserImageSymbols+0x30:
8281a182 int     3
0: kd> kc
nt!DbgLoadUserImageSymbols
nt!MiLoadUserSymbols
nt!MiMapViewOfImageSection
nt!MiMapViewOfSection
nt!MmInitializeProcessAddressSpace
nt!PspAllocateProcess
nt!NtCreateUserProcess
nt!KiFastCallEntry

You’ll note that we’re actually in the correct process context at this point:

0: kd> !process -1 0
PROCESS 84aaed40  SessionId: 1  Cid: 0000    Peb: 00000000  ParentCid: 0948
    DirBase: 7efc7600  ObjectTable: 961c2460  HandleCount:   0.
    Image: notepad.exe

So I can set a process specific breakpoint on a hot OS routine and start my analysis in the process that I’m interested in making the call that I’m interested in:

0: kd> bp /p @$proc ntfs!ntfscommoncreate
0: kd> g
Breakpoint 0 hit
Ntfs!NtfsCommonCreate:
889095fd push    94h
1: kd> kc
Ntfs!NtfsCommonCreate
Ntfs!NtfsCommonCreateCallout
nt!KiSwapKernelStackAndExit
nt!KiSwitchKernelStackAndCallout
nt!KeExpandKernelStackAndCalloutEx
Ntfs!NtfsCommonCreateOnNewStack
Ntfs!NtfsFsdCreate
nt!IofCallDriver
fltmgr!FltpLegacyProcessingAfterPreCallbacksCompleted
fltmgr!FltpCreate
nt!IofCallDriver
nt!IopParseDevice
nt!ObpLookupObjectName
nt!ObOpenObjectByName
nt!IopCreateFile
nt!NtOpenFile
nt!PfSnGetPrefetchInstructions
nt!PfSnBeginAppLaunch
nt!PfProcessCreateNotification
nt!PspUserThreadStartup
nt!KiThreadStartup

Symbol servers and !chkimg

Thursday, August 19th, 2010

For whatever reason, my comments on the NT Debugging blog never get approved, so I figured I’d clarify something about a recent post and subsequent comment here.

If you’re ever debugging a similar issue yourself, the !chkimg extension can automate all the steps taken in the blog post by leveraging a properly configured symbol server. As it turns out, in addition to indexing symbol files on a symbol server you can also index image files. This is a handy feature that’s necessary when debugging mini-dump files, due to the fact that the original image files are required when debugging dumps of that type. !chkimg is aware of this, and will attempt to file the original image from your symbol server and download it to your local symbol store.

In order to facilitate debugging kernel mini-dumps, Microsoft indexes the O/S images on the MS symbol server. This means that if you want to verify any O/S image in your target machine, all you need to do is point your symbol search path to the MS symbol server and run !chkimg.

0: kd> !chkimg ntfs
SYMSRV:  Ntfs.sys from http://msdl.microsoft.com/download/symbols
DBGHELP: c:\websymbols\Ntfs.sys\4A5BBF4512f000\Ntfs.sys - OK
0 errors : ntfs

Quickly add the dump path to your symbol path

Tuesday, August 17th, 2010

I often get dump files from customers zipped up with the appropriate PDBs for the images in the dump. I then have to extract the dump file to a folder, double click on the DMP file, and then add the path to the unzipped dump to my symbol search path so that I grab the appropriate PDBs (I wish the debugger engine would put the dump directory in the path automatically, but that’s another issue). That can lead to a lot of copy/pasting or typing, but luckily there’s a built in alias to the rescue: $CrashDumpPath.

Aliases are quite a nifty feature of WinDBG and I’m working on a post that will do them justice. In the meantime, just know that $CrashDumpPath is a built in alias that always expands out to the path of the crash dump file in any expression. For example, to quickly add the path of the crash dump file to my symbol search path, I can just call .sympath+ with the dump path alias:

0: kd> .sympath
Symbol search path is: <empty>
Expanded Symbol search path is: <empty>
0: kd> .sympath+ $CurrentDumpPath
Symbol search path is: C:\dumps\mpwhang
Expanded Symbol search path is: c:\dumps\mpwhang

This takes the variability out this step for me and also allows for easier scripting. Other built in aliases can be found on this page under the heading Automatic Aliases.

Process specific breakpoints

Thursday, May 20th, 2010

I’ve talked previously about thread specific breakpoints, which allow you to set a breakpoint that will only fire for a specific thread. Equally useful are process specific breakpoints, which will only fire for any thread within a given process.

To set a process specific breakpoint, you specify the /p switch to the bp command and supply a process object address:

bp /p 84996030 ntfs!ntfscommoncreate

The process address could, for example, be retrieved from the output of the !process 0 0 command or you can use the handy $proc pseudo register to specify the current process:

bp /p @$proc ntfs!ntfscommoncreate

DPCs execute on their own call stack (x86 Edition)

Thursday, April 29th, 2010

Deferred Procedure Call (DPCs) are callbacks to an arbitrary thread context at IRQL DISPATCH_LEVEL. There is a DPC queue per processor, and queueing a DPC performs two steps:

1) Inserts the DPC onto the DPC queue of the current processor.

2) Requests a DISPATCH_LEVEL software interrupt on the current processor.

Note that there are exceptions to both of those, though I’m not interested in talking about them at this moment

When the operating system is about to return to an IRQL < DISPATCH_LEVEL, the DISPATCH_LEVEL software interrupt is delivered to the processor. On XP, the ISR for this interrupt is hal!HalpDispatchInterrupt, which does some interrupt management work and calls nt!KiDispatchInterrupt. You can get a feel for how this works by setting a breakpoint on KiDispatchInterrupt and checking out a few call stacks, which should look like the following:

kidispatch

While KiInterruptDispatch serves a few different purposes, for our discussion all we care about is the beginning of the function shown here:

kidispatch_asm

Note the call near the end of the listing to nt!KiRetireDpcList. This is the function that will sit in a loop dequeing DPCs from the current processor’s DPC queue and calling the callbacks. There’s some interesting code leading up to that call though, so let’s go line by line and figure out exactly what this code is doing.

nt!KiDispatchInterrupt:
mov     ebx,dword ptr fs:[1Ch]

This line is moving the contents of offset 0x1c from the far segment into EBX. In kernel mode, the base of the far segment is the base address of what is called the PCR for the current processor:

fs_pcr

Thus, this code is grabbing whatever field is at offset 0x1c from the base of the PCR structure. Luckily we have the type information for the PCR, which is nt!_KPCR so we can easily see what is at that offset in the structure:

pcr_1c

That is the SelfPcr field, which is just the flat address of the PCR (in this case that would be 0xffdff000). Let’s move on to the next fragment:

nt!KiDispatchInterrupt+0x7:
lea  eax,[ebx+980h]
cli
cmp  eax,dword ptr [eax]
je   nt!KiDispatchInterrupt+0x2f (805459df)

Here, we add 0×980 to the base address of the PCR and store the result in EAX. We then disable interrupts on the current processor and check to see if the contents of the pointer match the pointer address.

The CMP instruction will do a logical subtract of the two values and set the Z-Flag to one if the result is zero, which would mean that the two values are the same. The JE instruction will, “Jump if the Z-Flag Equals one”, so if the contents of the pointer match the address of the pointer then this code will jump over the code segment that calls KiRetireDpcList.

If you’ve never looked at much assembly that might seem a bit weird, so let’s see what’s add offset 0×980 from the PCR and see if we can figure out what this code is doing.

If you go to a full listing of the PCR structure, you’ll notice that the last offset given is 0×120 and that is the PrcbData field:

pcr_prcb

Thus, in order to figure out what’s at offset 0×980 from the base of the PCR we’ll need to go to offset 0×860 into the PRCB. We’ll find this by doing a dt nt!_kprcb and scanning the output:

prcb_queue

Aha! That field is labeled as the DpcListHead (a.k.a. the DPC queue) and the type is a LIST_ENTRY, which is the standard type for a doubly linked list in the kernel.

LIST_ENTRY structures have two fields, a Flink field that points to the next entry and a Blink field that points to the previous entry. When a list is empty, the Flink field points back to the address of the head of the list. So our previous check above is testing the value of the Flink field against the address of the list head, in other words it is checking to see if the list is empty. If it is, the code avoids draining the DPC queue (which makes sense).

If the list is not empty, then the code sets up to call KiRetireDpcList:

nt!KiDispatchInterrupt+0x12:
push    ebp
push    dword ptr [ebx]
mov     dword ptr [ebx],0FFFFFFFFh
mov     edx,esp
mov     esp,dword ptr [ebx+988h]
push    edx
mov     ebp,eax
call    nt!KiRetireDpcList (80545e0e)

I’m going to save the first three instructions for another time if I ever get to talk about Structured Exception Handling (SEH). Right now it’s sufficient to set that the code there prevents kernel mode exceptions from being raised to user mode exception handlers.

The next two instructions are interesting though:

mov     edx,esp
mov     esp,dword ptr [ebx+988h]

Note that the code saves the current stack pointer and then overwrites ESP with a different pointer value from the PCR. We saw previously that the last offset in the PCR is 0×120, which is the beginning of the PRCB. So, whatever value is at offset 0×868 from the PRCB is what we put into the stack pointer register. If you scroll up to the previous graphic, you’ll see that field labeled as DpcStack:

   +0x868 DpcStack         : Ptr32 Void

Thus, each processor has its own DPC stack that is used when DPCs are executed. Shortly this is going to lead to an unexpected problem that this post will hopefully help you solve.

Lastly, the old stack pointer is pushed onto the stack and finally the call to KiRetireDpcList occurs. When it completes, the old stack is restored and all is right in the World.

However, there’s an interesting issue that can arise in your crash analysis. What if the system crashes inside a DPC? Due to the stack swap that occurs in KiRetireDpcList you’ll get this when you try to dump the call stack:

stackswapped

In other words, you’ll get a listing for the DPC stack and you won’t necessarily be able to see the actual kernel stack of the current thread. While in 99% of the cases the DPC stack will be the only stack that you care about, there’s that 1% where knowing the current thread stack will provide the insight necessary to solve the crash (in almost 10 years I’ve seen two). Luckily, it’s going to be relatively straightforward to get the stack back. Even more luckily, it’s mostly formulaic so even if you’re not sure why you can get it back you’ll still be able to :)

First thing you need is the old stack pointer, which is the first thing on the stack before the return address in the call to nt!KiRetireDpcList:

oldesp

Then we’re going to dump this out with the dps command and find the return address to hal!HalpDispatchInterrupt that the nt!KiDispatchInterrupt will return to. We’ll also want the first thing on the stack after the return address:

prevebp_halp

In my case, I have 0xf715da0c and hal!HalpDispatchInterrupt+0xbb. Now all that’s left is to feed those two values into the special k syntax that allows you to specify your own EBP, ESP, and EIP overrides:

origstack

Note that there’s a cheater shortcut, I could have just done k = f715da00 f715da00 @eip in this case and gotten a slightly busted but still legible stack. The technique above gives a more attractive and correct stack in the end

Possibly we can cover why this command works in the future, but for now hopefully that’s enough of a guide for you to go experiment yourselves. Don’t forget that you can always play with this on a live system where you can verify your results by simply stepping out of nt!KiRetireDpcList.

Random Other Points

1) The DISPATCH_LEVEL software interrupt isn’t always requested, so the DPC isn’t always drained when returning to an IRQL < DISPATCH_LEVEL.

2) The Idle thread also checks the DPC queue and, if it isn’t empty, drains the queue by dequeueing entries and calling the callbacks. In this case, the DPCs execute on the Idle thread’s stack

3) It is possible to target a DPC to a processor other than the current processor

Undocumented !verifier flags value (!verifier 0×200)

Wednesday, April 14th, 2010

Starting with Windows Vista, Driver Verifier has been updated to include circular trace buffers for interesting events. My favorite up until this point has been the pool allocate and free log, which records the call stack, calling thread, and address of pool allocations and frees. If the system then crashes due to a double free or access to a freed pool block, the debugger’s !verifier 0×80 command can be used to dump the alloc/free log. Even better, the command takes an optional address value that will show only the allocations and frees of the pool block containing that address.

You can see the results in this example from the WinDBG docs:

0: kd> !verifier 80 a2b1cf20
Parsing 00004000 array entries, searching for address a2b1cf20.
=======================================
Pool block a2b1ce98, Size 00000168, Thread a2b1ce98
808f1be6 ndis!ndisFreeToNPagedPool+0x39
808f11c1 ndis!ndisPplFree+0x47
808f100f ndis!NdisFreeNetBufferList+0x3b
8088db41 NETIO!NetioFreeNetBufferAndNetBufferList+0xe
8c588d68 tcpip!UdpEndSendMessages+0xdf
8c588cb5 tcpip!UdpSendMessagesDatagramsComplete+0x22
8088d622 NETIO!NetioDereferenceNetBufferListChain+0xcf
8c5954ea tcpip!FlSendNetBufferListChainComplete+0x1c
809b2370 ndis!ndisMSendCompleteNetBufferListsInternal+0x67
808f1781 ndis!NdisFSendNetBufferListsComplete+0x1a
8c04c68e pacer!PcFilterSendNetBufferListsComplete+0xb2
809b230c ndis!NdisMSendNetBufferListsComplete+0x70
8ac4a8ba test1!HandleCompletedTxPacket+0xea
=======================================
Pool block a2b1ce98, Size 00000164, Thread a2b1ce98
822af87f nt!VerifierExAllocatePoolWithTagPriority+0x5d
808f1c88 ndis!ndisAllocateFromNPagedPool+0x1d
808f11f3 ndis!ndisPplAllocate+0x60
808f1257 ndis!NdisAllocateNetBufferList+0x26
80890933 NETIO!NetioAllocateAndReferenceNetBufferListNetBufferMdlAndData+0x14
8c5889c2 tcpip!UdpSendMessages+0x503
8c05c565 afd!AfdTLSendMessages+0x27
8c07a087 afd!AfdTLFastDgramSend+0x7d
8c079f82 afd!AfdFastDatagramSend+0x5ae
8c06f3ea afd!AfdFastIoDeviceControl+0x3c1
8217474f nt!IopXxxControlFile+0x268
821797a1 nt!NtDeviceIoControlFile+0x2a
8204d16a nt!KiFastCallEntry+0x127

In the output, the most recent event is at the top. Thus, here you can see that the buffer was allocated with ndisAllocateFromNPagedPool and freed with ndisAllocateFromNPagedPool.

In addition to the pool allocation log, !verifier 0×100 shows the IRP log, which logs all IoCallDriver, IoCompleteRequest, and IoCancelIrp calls.

Based on the docs you’d think that’s all there is, but there’s an undocumented log that can be accessed with !verifier 0×200 and that is the critical region log.

This is not to be confused with the user mode concept of critical regions. In a driver, one can call KeEnterCriticalRegion and KeExitCriticalRegion in order to disable and re-enable APC delivery. Without getting too much in to why a driver needs to disable APC delivery, what’s important to note is that every call to KeEnterCriticalRegion must be matched with a call to KeExitCriticalRegion. If a driver gets this wrong, then the system will crash with an APC_INDEX_MISMATCH bugcheck when it notices that the enter/exit count is off.

The way this works is that entering a critical region decrements a field of the KTHREAD structure and exiting a critical region increments the field of the structure. At various points in the O/S, the field of the KTHREAD is checked to make sure that it is zero. If it isn’t, then the system crashes with the previously mentioned APC_INDEX_MISMATCH bugcheck code. One such place that this is checked is in the system service dispatcher before returning back to the caller, which is why you’ll see these bugchecks come from KiSystemServiceExit.

What makes these crashes particularly difficult to track down is that the crash is a secondary failure, by the time the system notices that the count field is incorrect the code that caused the bad state is gone. Enter the critical region log, which will trace every call to KeEnterCriticalRegion and KeLeaveCriticalRegion for the Verified drivers. Now, when the system crashes you can just type !verifier 0×200 in the debugger and find the mismatched call.

Note that this only works with Driver Verifier enabled, just another reason to make sure that you’re always testing with Verifier!

Expressing negative decimal numbers in WinDBG

Tuesday, April 6th, 2010

Surprisingly, after almost a decade of using WinDBG I have never had to use a negative decimal value in a WinDBG expression. Until recently, that is…Because the MASM syntax was a bit trickier than expected, I thought I’d record it here for posterity.

When using the MASM evaluator (which is the default in WinDBG), hex values are the default and decimal numbers are indicated by using the 0n override.  Thus, for example, if I wanted to evaluate 123 in an expression I could use 0n123:

3: kd> ?0n123
Evaluate expression: 123 = 00000000`0000007b

However, if I want to use -123 there’s a bit of a catch. My natural inclination was to put the minus sign to the right of the 0n and the left of the 123, such as this: 0n-123. However, this yields an unexpected result:

3: kd> ?0n-123
Evaluate expression: -291 = ffffffff`fffffedd

That’s actually -0×123, not -123. To make matters even worse, the latest debugger even shows this syntax when displaying negative decimal values:

3: kd> dt nt!_mdl fffffa80077f1df0
   +0×000 Next             : (null)
   +0×008 Size             : 0n56
   +0x00a MdlFlags         : 0n-32701
   +0×010 Process          : 0xfffffa80`069dab30 _EPROCESS
   +0×018 MappedSystemVa   : 0xfffffa80`06797294 Void
   +0×020 StartVa          : 0×00000000`0404f000 Void
   +0×028 ByteCount        : 0x1c
   +0x02c ByteOffset       : 0x79c

However, the correct syntax is to put the minus sign to the left of the 0n:

3: kd> ?-0n123
Evaluate expression: -123 = ffffffff`ffffff85

For the C++ evaluator, things are much easier because the default radix is decimal. Thus, all you need to do is specify -123:

3: kd> ? @@c++(-123)
Evaluate expression: -123 = ffffffff`ffffff85

The trick now comes when you want to specify a negative hex number, which also requires the minus sign to be on the left of the modifier:

3: kd> ? @@c++(0x-123)
Evaluate expression: -123 = ffffffff`ffffff85
3: kd> ? @@c++(-0×123)
Evaluate expression: -291 = ffffffff`fffffedd

WinDBG caches data from the target (.cache)

Monday, April 5th, 2010

Been a bit of an unexpected  break for a while now, but hopefully back to regular posting…

You might never need to know this, but WinDBG will actually cache data read from the target. For example, this means that if you dd a memory location multiple times only the first dump of the memory will actually be read from target. Obviously this cache is invalidated when the target is resumed, so most of us won’t have an issue with this caching. However, if the memory you’re dumping is something like mapped device memory then this is an issue as the cache could be stale.

Enter the .cache command, which controls the size and state of the local cache (amongst other things, we’ve seen .cache before). Turning off the cache is as easy as executing .cache 0, which sets the size of the local cache to zero. This causes all of your reads to hit the target and ensure that you’re seeing the latest data. There are also the flushall, flushu, and flush parameters, which allow for flushing all or some of the cache from the local machine.