Does the CPU really pause during assembly debugging? - debugging

I've been learning x64 assembly language and, as in other languages, I can throw a breakpoint in when debugging and step through the program. The breakpoint is said to pause program execution and the debugging utility even displays which values are in the CPU registers at the given point in time. However, how is it possible that the values are the real values given there are many other programs running on the computer which must be using the same CPU registers to execute when I'm debugging? Are these values actually not in the CPU when the program is paused during debugging? Thanks.
Update: Windows 10 user mode code.

The operating system is scheduling threads based on various information like priority, processor affinity etc. When the OS decides to give another thread the chance to run, that's called a Context switch (Wikipedia). During the context switch, the operating system will save the current thread's registers and then restore the new thread's registers.
Internally, the operating system needs to maintain all that information. You can easily have 1000 threads, so the OS must have 1000 times all the registers somewhere in memory.
You can safely use a user mode debugger and have a look at the kernel structures. Since you're on Windows, I'll use windbg, which is part of the Debugging Tools for Windows.
In order to follow, start any program (notepad is always a good candidate) and attach WinDbg (F6).
First, let's get the correct information from Microsoft:
0:000> .symfix
0:000> .reload /f
Those commands will make sure that we have the correct symbols (PDBs).
Next, let's look at a kernel thread (not at the user mode part of the thread, since the kernel schedules it):
0:000> dt nt!_KTHREAD
+0x000 Header : _DISPATCHER_HEADER
+0x010 CycleTime : Uint8B
+0x018 HighCycleTime : Uint4B
+0x020 QuantumTarget : Uint8B
+0x028 InitialStack : Ptr32 Void
[...]
+0x1b8 WaitPrcb : Ptr32 _KPRCB
[...]
+0x1f4 ThreadCounters : Ptr32 _KTHREAD_COUNTERS
+0x1f8 XStateSave : Ptr32 _XSTATE_SAVE
As we can see, the information to maintain a thread is quite large (0x1f8+4 or 508 bytes).
If you read the Wikipedia article, you found out:
This is usually stored in a data structure called a process control block (PCB) or switchframe.
That's the _KPRCB structure at offset 1b8. Let's look at that one:
0:000> dt nt!_KPRCB
ntdll!_KPRCB
+0x000 MinorVersion : Uint2B
+0x002 MajorVersion : Uint2B
+0x004 CurrentThread : Ptr32 _KTHREAD
+0x008 NextThread : Ptr32 _KTHREAD
[...]
+0x3658 Context : Ptr32 _CONTEXT
+0x365c ContextFlags : Uint4B
+0x3660 ExtendedState : Ptr32 _XSAVE_AREA
Given we switch the context, let's assume that _CONTEXT is the right thing to look at.
0:000> dt nt!_CONTEXT
+0x000 ContextFlags : Uint4B
+0x004 Dr0 : Uint4B
+0x008 Dr1 : Uint4B
+0x00c Dr2 : Uint4B
+0x010 Dr3 : Uint4B
+0x014 Dr6 : Uint4B
+0x018 Dr7 : Uint4B
+0x01c FloatSave : _FLOATING_SAVE_AREA
+0x08c SegGs : Uint4B
+0x090 SegFs : Uint4B
+0x094 SegEs : Uint4B
+0x098 SegDs : Uint4B
+0x09c Edi : Uint4B
+0x0a0 Esi : Uint4B
+0x0a4 Ebx : Uint4B
+0x0a8 Edx : Uint4B
+0x0ac Ecx : Uint4B
+0x0b0 Eax : Uint4B
+0x0b4 Ebp : Uint4B
+0x0b8 Eip : Uint4B
+0x0bc SegCs : Uint4B
+0x0c0 EFlags : Uint4B
+0x0c4 Esp : Uint4B
+0x0c8 SegSs : Uint4B
+0x0cc ExtendedRegisters : [512] UChar
So yes, there they are: the registers.
And, know what? Seems I attached to a 32 bit process, so you probably got different results. Anyway, try again and you'll get:
0:000> dt nt!_CONTEXT
+0x000 P1Home : Uint8B
+0x008 P2Home : Uint8B
+0x010 P3Home : Uint8B
+0x018 P4Home : Uint8B
+0x020 P5Home : Uint8B
+0x028 P6Home : Uint8B
+0x030 ContextFlags : Uint4B
[...]
+0x078 Rax : Uint8B
+0x080 Rcx : Uint8B
+0x088 Rdx : Uint8B
+0x090 Rbx : Uint8B
+0x098 Rsp : Uint8B
+0x0a0 Rbp : Uint8B
+0x0a8 Rsi : Uint8B
+0x0b0 Rdi : Uint8B
+0x0b8 R8 : Uint8B
+0x0c0 R9 : Uint8B
[...]
+0x280 Xmm14 : _M128A
+0x290 Xmm15 : _M128A
+0x300 VectorRegister : [26] _M128A
+0x4a0 VectorControl : Uint8B
+0x4a8 DebugControl : Uint8B
+0x4b0 LastBranchToRip : Uint8B
+0x4b8 LastBranchFromRip : Uint8B
+0x4c0 LastExceptionToRip : Uint8B
+0x4c8 LastExceptionFromRip : Uint8B
Summary: the kernel creates as many "objects" of type _CONTEXT as needed where it maintains the registers. Whenever a context switch shall happen, the kernel saves the current registers and restores other ones.
When debugging, your thread is suspended, so it will not run on the CPU. The CPU can also not be halted, because you need to be able to interact with the debugger. The CPU is executing instructions of the debugger. However, the debugger will give the information from _KTHREAD to you.
That's all quite simplified, but maybe enough for the moment. There are things like software and hardware context switches (read at OSWiki) and other things. It's certainly also interesting how the kernel gets its registers before it restores other user mode registers etc., but that's too much for a SO post.

Related

Windbg: what is the benefit of specifying pseudo register when using "dt" command

When using the "Dislay Type" command in Windbg you have the option to specify a pseudo register. This will add the base address. However it is unclear to me what the benefit is of specifying the pseudo register.
When adding the "#$teb" pseudo register:
dt ntdll!_TEB #$teb ThreadLocalStoragePointer
+0x02c ThreatLocalStoragePointer : (null)
Without adding the "#$teb" pseudo register:
dt ntdll!_TEB ThreadLocalStoragePointer
+0x02c ThreatLocalStoragePointer : Ptr32 Void
if you specify a pseudo register it will be evaluated to an address
the output will display the result of evaluation
it is like specifying an address like dt ntdll!_teb 12345678`9abcdef0
if you do not provide an evaluable expression dt will simply print the structure
example
0:001> dt ntdll!_TEB ProcessEnvironmentBlock->ProcessParameters->CommandLine #$teb
+0x060 ProcessEnvironmentBlock :
+0x020 ProcessParameters :
+0x070 CommandLine : _UNICODE_STRING "dbstk.exe"
0:001> dt ntdll!_TEB ProcessEnvironmentBlock->ProcessParameters->CommandLine
+0x060 ProcessEnvironmentBlock :
+0x020 ProcessParameters :
+0x070 CommandLine : _UNICODE_STRING
0:001>
to address comment
yes it is like casting (TEB *) 0x12345678`9abcdef
you can also use c++ expression evaluator like below on all builtin PseudoRegisters or use an address
0:001> ?? #$teb->ProcessEnvironmentBlock->ProcessParameters->CommandLine
struct _UNICODE_STRING
"dbstk.exe"
+0x000 Length : 0x12
+0x002 MaximumLength : 0x14
+0x008 Buffer : 0x000002a6`27290fb0 "dbstk.exe"
0:001> ? #$teb
Evaluate expression: 1080494329856 = 000000fb`927b1000
0:001> dt ntdll!_TEB ProcessEnvironmentBlock->ProcessParameters->CommandLine 000000fb`927b1000
+0x060 ProcessEnvironmentBlock :
+0x020 ProcessParameters :
+0x070 CommandLine : _UNICODE_STRING "dbstk.exe"
0:001>

What does inc dword ptr gs : [] doing here?

While debugging windows kernel with WinDbg,
I found following line:
inc dword ptr gs : [2EB8h]
Can someone please explain what this means?
(Intel Syntax, x86, Windows-10)
The GS segment in kernel mode (windows x64) points to the Kernel Processor Control Region (KPCR).
You can dump it with the !pcr command:
kd> !pcr
KPCR for Processor 0 at fffff802fbd73000:
Major 1 Minor 1
NtTib.ExceptionList: fffff802fd6d8000
NtTib.StackBase: fffff802fd6d9070
NtTib.StackLimit: 0000000000b0e968
NtTib.SubSystemTib: fffff802fbd73000
NtTib.Version: 00000000fbd73180
NtTib.UserPointer: fffff802fbd737f0
NtTib.SelfTib: 000000007f005000
SelfPcr: 0000000000000000
Prcb: fffff802fbd73180
Irql: 0000000000000000
IRR: 0000000000000000
IDR: 0000000000000000
InterruptMode: 0000000000000000
IDT: 0000000000000000
GDT: 0000000000000000
TSS: 0000000000000000
CurrentThread: ffffe001e41a3080
NextThread: 0000000000000000
IdleThread: fffff802fbde9740
DpcQueue: Unable to read nt!_KDPC_DATA.DpcListHead.Flink # fffff802fbd75f00
You can confirm that the KPCR really is pointed to by the GS segment register by reading the MSR (Model Specific Register) named IA32_GS_BASE (which value is 0xc0000101):
kd> rdmsr 0xc0000101
msr[c0000101] = fffff802`fbd73000
As you can see they both point, in my example, to 0xfffff802fbd73000.
The PCR is described by the KPCR structure:
kd> dt nt!_kpcr
+0x000 NtTib : _NT_TIB
+0x000 GdtBase : Ptr64 _KGDTENTRY64
+0x008 TssBase : Ptr64 _KTSS64
+0x010 UserRsp : Uint8B
+0x018 Self : Ptr64 _KPCR
+0x020 CurrentPrcb : Ptr64 _KPRCB //points to the _KPRCB member at 0x180
+0x028 LockArray : Ptr64 _KSPIN_LOCK_QUEUE
+0x030 Used_Self : Ptr64 Void
+0x038 IdtBase : Ptr64 _KIDTENTRY64
+0x040 Unused : [2] Uint8B
+0x050 Irql : UChar
+0x051 SecondLevelCacheAssociativity : UChar
+0x052 ObsoleteNumber : UChar
+0x053 Fill0 : UChar
+0x054 Unused0 : [3] Uint4B
+0x060 MajorVersion : Uint2B
+0x062 MinorVersion : Uint2B
+0x064 StallScaleFactor : Uint4B
+0x068 Unused1 : [3] Ptr64 Void
+0x080 KernelReserved : [15] Uint4B
+0x0bc SecondLevelCacheSize : Uint4B
+0x0c0 HalReserved : [16] Uint4B
+0x100 Unused2 : Uint4B
+0x108 KdVersionBlock : Ptr64 Void
+0x110 Unused3 : Ptr64 Void
+0x118 PcrAlign1 : [24] Uint4B
+0x180 Prcb : _KPRCB
As you can see the last field of the KPCR structure is another structure (not a pointer, but the structure itself) named KPRCB (which stands for Kernel Processor Control Block) at offset 0x180.
Here's the start of this structure:
kd> dt nt!_kprcb
+0x000 MxCsr : Uint4B
+0x004 LegacyNumber : UChar
+0x005 ReservedMustBeZero : UChar
+0x006 InterruptRequest : UChar
+0x007 IdleHalt : UChar
+0x008 CurrentThread : Ptr64 _KTHREAD
+0x010 NextThread : Ptr64 _KTHREAD
+0x018 IdleThread : Ptr64 _KTHREAD
+0x020 NestingLevel : UChar
+0x021 ClockOwner : UChar
+0x022 PendingTickFlags : UChar
+0x022 PendingTick : Pos 0, 1 Bit
+0x022 PendingBackupTick : Pos 1, 1 Bit
+0x023 IdleState : UChar
+0x024 Number : Uint4B
...
Above output truncated for brevity as this structure (and thus the PCR) is extremely large: the size of the PCR in windows 10 x64 is 0x8040 bytes (0x7EC0 for the KPRCB).
Given your 0x2eb8 offset in GS (which points to the PCR), we can just subtract the KPRCB offset from the PCR (0x180):
kd> ? 0x2eb8 - 0x180
Evaluate expression: 11576 = 00000000`00002d38
And then check which field is at offset 0x2d38 in the KPRCB:
0: kd> .shell -ci "dt nt!_kprcb" findstr /i 0x2d38
+0x2d38 KeSystemCalls : Uint4B
(note: you can just dt nt!_kprcb and look at offset 0x2d38).
So, the incremented field in your example is named KeSystemCalls and is a 32-bit field (Uint4B) as shown in your code.
Field Usage
Searching in the IDA disassembler (ntoskrnel.exe windows 10 - x64) we have 2 hits on the 0x2eb8 value:
KiSystemCall64
VslpDispatchIumSyscall
The first one is the "normal" syscall dispatcher while the second one is the syscall dispatcher for IUM processes (aka Trustlets).
In both of these functions the use of the field is exactly the same (example in KiSystemCall64):
.text:0000000140187360 call r10 ; perform syscall
.text:0000000140187363
.text:0000000140187363 loc_140187363:
.text:0000000140187363 inc dword ptr gs:2EB8h ; increment syscall counter
So this field is simply a monotonic counter for the number of system calls that happened since the system boot.
This Answer is Just an Extension to Nietsa's answer
Apart From Being used to Create Process->cookie
KeSystemCalls member in poi(nt!KiProcessorBlock) Structure
kd> ?? ##masm(poi(nt!KiProcessorBlock)) == #$prcb
bool true
kd> ? #$pcr
Evaluate expression: -2104316928 = 8292ac00
kd> ? #$pcr+120
Evaluate expression: -2104316640 = 8292ad20
kd> ? #$prcb
Evaluate expression: -2104316640 = 8292ad20
kd> ? poi(nt!KiProcessorBlock)
Evaluate expression: -2104316640 = 8292ad20
is also used to provide the performance counter values for
"\system\System Calls/sec" data
C:\>powershell -c "&{get-counter -counter \"\System\System Calls/sec\"}"
Timestamp CounterSamples
144196.186791101
if one follows the pdh api
s = PdhCollectQueryData(hQuery);
one can observe the calls to NtQueryInformationSystem with SYSTEM_INFO_CLASS 2 == SystemPerformanceInformation which Leads to nt!ExpQuerySystemInformation on the kernel side filling the information from KPRCB
kd> # \+590h nt!ExpQuerySystemInformation l 600
nt!ExpQuerySystemInformation+0x57f:
82a01d73 038290050000 add eax,dword ptr [edx+590h]
kd> ?? #FIELD_OFFSET(nt!_KPRCB , KeSystemCalls)
long 0n1424
kd> ? 0n1424
Evaluate expression: 1424 = 00000590 <<<< (windows 7 sp2 32 bit )

Debugging a NotificationEvent in Kernel Debug (Windows)

I'm debugging a process which is like frozen:
I suspect the root cause is the thread below THREAD 877f4030 Cid 0568.0fb8 that is stuck on the user-mode call to GetOverlappedResult.
I have opened the dump with kd.exe.
Namely, I'm interested into knowing more about the NotificationEvent which obviously is never releasing our thread.
In the thread info we have:
879f6fdc NotificationEvent
In what type should I cast address 879f6fdc ? or in which structure field should I search for it, so as to understand, or have a clue to what is blocking the situation ?
As far as the Thread Infos goes, this thread currently does not list any IRP that would be in undesired or unfinished state.
Below entire Thread Information for the corresponding thread:
THREAD 877f4030 Cid 0568.0fb8 Teb: 7ff3d000 Win32Thread: 00000000 WAIT: (UserRequest) UserMode Non-Alertable
879f6fdc NotificationEvent
Not impersonating
DeviceMap 89809fc8
Owning Process 87950030 Image: OurProduct.exe
Attached Process N/A Image: N/A
Wait Start TickCount 1472232 Ticks: 5394 (0:00:01:24.146)
Context Switch Count 2791788 IdealProcessor: 0
UserTime 00:00:06.848
KernelTime 00:00:09.890
Win32 Start Address MSVCR120!_threadstartex (0x721fbfb4)
Stack Init 8c761fd0 Current 8c761bc8 Base 8c762000 Limit 8c75f000 Call 0
Priority 8 BasePriority 8 UnusualBoost 0 ForegroundBoost 0 IoPriority 2 PagePriority 5
Kernel stack not resident.
ChildEBP RetAddr Args to Child
8c761be0 824cfced 877f4030 00000000 8ab36120 nt!KiSwapContext+0x26 (FPO: [Uses EBP] [0,0,4])
8c761c18 824ceb4b 877f40f0 877f4030 879f6fdc nt!KiSwapThread+0x266
8c761c40 824c856f 877f4030 877f40f0 00000000 nt!KiCommitThreadWait+0x1df
8c761cb8 8267ae07 879f6fdc 00000006 826bca01 nt!KeWaitForSingleObject+0x393
8c761d20 8248f8a6 00001018 00000000 00000000 nt!NtWaitForSingleObject+0xc6
8c761d20 774f7094 00001018 00000000 00000000 nt!KiSystemServicePostCall (FPO: [0,3] TrapFrame # 8c761d34)
09f9f61c 774f6a24 758b179c 00001018 00000000 ntdll!KiFastSystemCallRet (FPO: [0,0,0])
09f9f620 758b179c 00001018 00000000 00000000 ntdll!NtWaitForSingleObject+0xc (FPO: [3,0,0])
09f9f68c 758b7841 00001018 ffffffff 00000000 KERNELBASE!WaitForSingleObjectEx+0x98 (FPO: [Non-Fpo])
09f9f6a0 758cb9e1 00001018 ffffffff 064f3d10 KERNELBASE!WaitForSingleObject+0x12 (FPO: [Non-Fpo])
09f9f6b8 745be159 00001018 0639ee0c 09f9f6ec KERNELBASE!GetOverlappedResult+0x57 (FPO: [Non-Fpo])
What is the correct way to proceed and know which event or synchronisation mechanism is faulting ?
some commands on the NotificationEvent address:
0: kd> !object 879f6fdc
879f6fdc: Not a valid object (ObjectType invalid)
0: kd> dt nt!_KEVENT 879f6fdc
+0x000 Header : _DISPATCHER_HEADER
and then:
0: kd> dt nt!_DISPATCHER_HEADER 879f6fdc
+0x000 Type : 0 ''
+0x001 TimerControlFlags : 0 ''
+0x001 Absolute : 0y0
+0x001 Coalescable : 0y0
+0x001 KeepShifting : 0y0
+0x001 EncodedTolerableDelay : 0y00000 (0)
+0x001 Abandoned : 0 ''
+0x001 Signalling : 0 ''
+0x002 ThreadControlFlags : 0x4 ''
+0x002 CpuThrottled : 0y0
+0x002 CycleProfiling : 0y0
+0x002 CounterProfiling : 0y1
+0x002 Reserved : 0y00000 (0)
+0x002 Hand : 0x4 ''
+0x002 Size : 0x4 ''
+0x003 TimerMiscFlags : 0 ''
+0x003 Index : 0y0
+0x003 Processor : 0y00000 (0)
+0x003 Inserted : 0y0
+0x003 Expired : 0y0
+0x003 DebugActive : 0 ''
+0x003 ActiveDR7 : 0y0
+0x003 Instrumented : 0y0
+0x003 Reserved2 : 0y0000
+0x003 UmsScheduled : 0y0
+0x003 UmsPrimary : 0y0
+0x003 DpcActive : 0 ''
+0x000 Lock : 0n262144
+0x004 SignalState : 0n0
+0x008 WaitListHead : _LIST_ENTRY [ 0x877f40f0 - 0x877f40f0 ]
from a former investigation I remember that if +0x003 DpcActive was 1, it would mean we'd be waiting for some hardware operation to put it to 0. But in this case it is 0.
So right now, I just don't know what this NotificationEvent is waiting for.
Any idea ?
Events do not wait, Threads do. NotificationEvents are signaled by whoever would perform the operation and then notify the the waiters about the completion of the operation. In other words your stack is an example of a Async IO where we pass an overlapped structure with an hEvent set. reference https://msdn.microsoft.com/en-us/library/windows/desktop/ms684342(v=vs.85).aspx
You should be inspecting the source which has scheduled this IO or the type of IO we are waiting for instead of dumping out the event. The event will be signaled when the operation is completed.

_IMAGE_DOS_HEADER symbol not found

I have recently installed windbg inside windows 7 in Vmware .. Installed windows SDK and Windows Symbols.
But still when I open executable "notepad.exe" inside windbg, and run the following
dt _IMAGE_DOS_HEADER command, it says symbol not found.
I have PATH set already _NT_SYMBOL_PATH=SMVSRV*c:\Symbols*http://msdl.microsoft.com/download/symbols
Tried the same on windows XP ... same issues ..
Please advice.
Thanks !
Set it to srv**http://msdl.microsoft.com/download/symbols. Despite what documentation is saying, prefix symsrv does not work for me, while srv does:
0:000> .sympath srv**http://msdl.microsoft.com/download/symbols
Symbol search path is: srv**http://msdl.microsoft.com/download/symbols
Expanded Symbol search path is: srv**http://msdl.microsoft.com/download/symbols
0:000> .reload
Reloading current modules
...................
0:000> dt _IMAGE_DOS_HEADER
ntdll!_IMAGE_DOS_HEADER
+0x000 e_magic : Uint2B
+0x002 e_cblp : Uint2B
+0x004 e_cp : Uint2B
+0x006 e_crlc : Uint2B
+0x008 e_cparhdr : Uint2B
+0x00a e_minalloc : Uint2B
+0x00c e_maxalloc : Uint2B
+0x00e e_ss : Uint2B
+0x010 e_sp : Uint2B
+0x012 e_csum : Uint2B
+0x014 e_ip : Uint2B
+0x016 e_cs : Uint2B
+0x018 e_lfarlc : Uint2B
+0x01a e_ovno : Uint2B
+0x01c e_res : [4] Uint2B
+0x024 e_oemid : Uint2B
+0x026 e_oeminfo : Uint2B
+0x028 e_res2 : [10] Uint2B
+0x03c e_lfanew : Int4B
0:000>

Windows Driver BugCheck 7E On driver load

This one is stumping me.
My driver works perfectly fine in all of the guest virtual systems (Windows xp/7 both x86 and x64), as well as a few certain hosts.
However, on my PC I'm receiving a 0x7E stop code right as I start up the driver in OSRLoader.
Yes, Testsigning and debug mode are both enabled.
Here is some dump information (warning, huge):
0: kd> !analyze -v
*******************************************************************************
* *
* Bugcheck Analysis *
* *
*******************************************************************************
SYSTEM_THREAD_EXCEPTION_NOT_HANDLED_M (1000007e)
This is a very common bugcheck. Usually the exception address pinpoints
the driver/function that caused the problem. Always note this address
as well as the link date of the driver/image that contains this address.
Some common problems are exception code 0x80000003. This means a hard
coded breakpoint or assertion was hit, but this system was booted
/NODEBUG. This is not supposed to happen as developers should never have
hardcoded breakpoints in retail code, but ...
If this happens, make sure a debugger gets connected, and the
system is booted /DEBUG. This will let us see why this breakpoint is
happening.
Arguments:
Arg1: ffffffff80000003, The exception code that was not handled
Arg2: fffff88000c0af0f, The address that the exception occurred at
Arg3: fffff88002fb1d78, Exception Record Address
Arg4: fffff88002fb15e0, Context Record Address
Debugging Details:
------------------
EXCEPTION_CODE: (HRESULT) 0x80000003 (2147483651) - One or more arguments are invalid
FAULTING_IP:
CI!CiValidateImageHeader+167
fffff880`00c0af0f cc int 3
EXCEPTION_RECORD: fffff88002fb1d78 -- (.exr 0xfffff88002fb1d78)
ExceptionAddress: fffff88000c0af0f (CI!CiValidateImageHeader+0x0000000000000167)
ExceptionCode: 80000003 (Break instruction exception)
ExceptionFlags: 00000000
NumberParameters: 1
Parameter[0]: 0000000000000000
CONTEXT: fffff88002fb15e0 -- (.cxr 0xfffff88002fb15e0)
rax=0000000000000000 rbx=00000000000000ff rcx=1748c3f2dac60000
rdx=0000000000000008 rsi=fffff88002fb2100 rdi=00000000c0000428
rip=fffff88000c0af0f rsp=fffff88002fb1fb0 rbp=0000000000000000
r8=0000000000000001 r9=fffff80002d0bbe0 r10=fffff80002e4a900
r11=fffff88002fb1fa8 r12=0000000000006000 r13=fffff98018700000
r14=fffffa8002621520 r15=0000000000000001
iopl=0 nv up ei ng nz na pe nc
cs=0010 ss=0018 ds=002b es=002b fs=0053 gs=002b efl=00000282
CI!CiValidateImageHeader+0x167:
fffff880`00c0af0f cc int 3
Resetting default scope
CUSTOMER_CRASH_COUNT: 1
DEFAULT_BUCKET_ID: VISTA_DRIVER_FAULT
BUGCHECK_STR: 0x7E
PROCESS_NAME: System
CURRENT_IRQL: 0
ERROR_CODE: (NTSTATUS) 0x80000003 - {EXCEPTION} Breakpoint A breakpoint has been reached.
EXCEPTION_PARAMETER1: 0000000000000000
LAST_CONTROL_TRANSFER: from fffff80002f35b18 to fffff88000c0af0f
STACK_TEXT:
fffff880`02fb1fb0 fffff800`02f35b18 : 00000000`00000006 00000000`000fffff fffffa80`02621520 00000000`00000000 : CI!CiValidateImageHeader+0x167
fffff880`02fb2090 fffff800`02f3591a : 00000000`00000000 00000000`01000000 fffffa80`055e6010 00000000`00000000 : nt!SeValidateImageHeader+0x58
fffff880`02fb20d0 fffff800`0302dea2 : fffffa80`02621520 fffffa80`055e6010 00000000`00000001 00000000`00000006 : nt!MiValidateImageHeader+0x21a
fffff880`02fb21a0 fffff800`02fba3cf : fffff880`02fb2400 00000000`00000000 fffff880`02fb26b8 fffff880`02fb23f8 : nt! ?? ::NNGAKEGL::`string'+0x4e3e3
fffff880`02fb23b0 fffff800`02cce293 : fffffa80`02505b60 fffff880`02fb2658 fffff880`02fb2448 00000000`00000000 : nt!NtCreateSection+0x162
fffff880`02fb2430 fffff800`02cca830 : fffff800`030a7f16 00000000`00000000 fffff800`02fbc607 00000000`00000001 : nt!KiSystemServiceCopyEnd+0x13
fffff880`02fb2638 fffff800`030a7f16 : 00000000`00000000 fffff800`02fbc607 00000000`00000001 fffffa80`0254c518 : nt!KiServiceLinkage
fffff880`02fb2640 fffff800`030a82dc : ffffffff`80000ea4 fffffa80`00100000 fffffa80`0254c518 00000000`00000000 : nt!MmCheckSystemImage+0x96
fffff880`02fb2770 fffff800`030a84f7 : ffffffff`80000ea4 fffff800`00000001 fffff8a0`0b36c500 00000000`00000000 : nt!MiCreateSectionForDriver+0xcc
fffff880`02fb2820 fffff800`030b3d9a : 00000000`00000000 fffff880`02fb29f8 fffffa80`02505b60 fffff800`02e48e00 : nt!MiObtainSectionForDriver+0xd7
fffff880`02fb2880 fffff800`030b69bd : fffff880`02fb29f8 00000000`00000000 00000000`00000000 00000000`00000000 : nt!MmLoadSystemImage+0x23a
fffff880`02fb29a0 fffff800`030b7375 : 00000000`00000001 00000000`00000000 00000000`00000000 fffffa80`02829388 : nt!IopLoadDriver+0x44d
fffff880`02fb2c70 fffff800`02cdc1e1 : fffff8a0`00000000 ffffffff`80000e90 fffff800`030b7320 fffffa80`02505b60 : nt!IopLoadUnloadDriver+0x55
fffff880`02fb2cb0 fffff800`02f6e6e6 : b9ce705b`ee973fcb fffffa80`02505b60 00000000`00000080 fffffa80`024ef5f0 : nt!ExpWorkerThread+0x111
fffff880`02fb2d40 fffff800`02cad566 : fffff880`009eb180 fffffa80`02505b60 fffff880`009f5f40 50320c1b`3fdc0847 : nt!PspSystemThreadStartup+0x5a
fffff880`02fb2d80 00000000`00000000 : fffff880`02fb3000 fffff880`02fad000 fffff880`02fb13f0 00000000`00000000 : nt!KiStartSystemThread+0x16
FOLLOWUP_IP:
CI!CiValidateImageHeader+167
fffff880`00c0af0f cc int 3
SYMBOL_STACK_INDEX: 0
SYMBOL_NAME: CI!CiValidateImageHeader+167
FOLLOWUP_NAME: MachineOwner
MODULE_NAME: CI
IMAGE_NAME: CI.dll
DEBUG_FLR_IMAGE_TIMESTAMP: 4a5be01d
STACK_COMMAND: .cxr 0xfffff88002fb15e0 ; kb
FAILURE_BUCKET_ID: X64_0x7E_CI!CiValidateImageHeader+167
BUCKET_ID: X64_0x7E_CI!CiValidateImageHeader+167
Followup: MachineOwner
---------
As the little bit at the top states, I have booted with /DEBUG on and it shows nothing more than I already have.
The first log in my code doesn't even get hit:
/*
* DriverEntry
* Driver entry point
*/
NTSTATUS DriverEntry(IN PDRIVER_OBJECT driver, IN PUNICODE_STRING path)
{
// Setup vars
UNICODE_STRING devLink, devName;
PDEVICE_OBJECT devObj = NULL;
NTSTATUS ntsReturn;
// Log Entry
LOG("Driver Entry");
// Setup driver unload function
driver->DriverUnload = DrvUnload;
WinDbg shows nothing of the sort in its view.
How do I know what is causing this? The breakpoint causes a BSOD when windbg isn't attached, and (obviously) freezes my computer when it is attached, giving me no real usable data.
It looks like you hit a debug assert in CI.dll. You can just type g from the debugger and continue loading your driver.
That is the default behavior of x64 builds of Windows. If you don't want to see that assertion you have to F8 at boot time and select "Disable Driver Signature Enforcement" which is valid per boot. (You have to do it every time you restart). Or, you can use 32-bit Windows and 32-bit version of your driver for debugging.
Here is more info:
http://msdn.microsoft.com/en-us/library/ff547565(v=vs.85).aspx

Resources