Just recently finished upgrading my laptop to Win7 and remembered a quick WinDBG tip.
If you want to associate your .dmp files with WinDBG, execute the following WinDBG command line:
windbg.exe -IA
Just recently finished upgrading my laptop to Win7 and remembered a quick WinDBG tip.
If you want to associate your .dmp files with WinDBG, execute the following WinDBG command line:
windbg.exe -IA
It’s half-time in the New England Patriots game so now’s a good a time as ever to stack about the x64 compiler’s usage of the execution stack.
The x64 compiler on Windows performs all stack manipulation during the function prolog. This includes saving non-volatile registers on the stack, making room for local variables, and even making room for parameters passed to the functions that it calls (remember that the first four parameters are passed in registers with any remaining parameters passed on the stack).
This leads to another interesting feature of the x64 compiler’s use of the stack. All subroutines are guaranteed to have a “spill” or “home” space allocated for them on the stack by the caller. This space is large enough to house the first four parameters passed to the routine via registers: RCX, RDX, R8, and R9. In addition, this space comes before the space where the fifth parameter can be found.
A picture probably clears this up. Upon entry to a subroutine, RSP points to a location that contains the return address of the routine. RSP+8 points to the RCX home space, RSP+10 is the RDX home space, etc:
It is important to realize however that these locations on the stack are not reserved to just hold RCX, RDX, R8, and R9. In some cases, the prolog of the function may “home” all of the parameter registers into these locations. In other cases, the prolog may “home” a subset. In other cases, the prolog may store completely unrelated register values here. Or the compiler may choose to ignore this space and not store anything here. It is effectively just a scratch space for the subroutine to use in whatever way it sees fit.
We’re going to extensively utilize the scatch space in any x64 crash that we analyze since it’s a great place to find parameters passed to functions and non-volatile registers that aren’t present in trap frames. Next up we’ll see just how we can use the space to easily reconstruct the parameter passed to a function.
(Just finished typing in time for kick off!)
Update
Anonymous makes a really interesting point in the comments:
It’s important to get this right – even though stack manipulations are performed during prolog, RSP itself _can_ change during execution of function body. For example, due to “_alloca” call (other cases, anybody?).
This isn’t a common programming practice in kernel mode, so I failed to mention that. If anyone else knows of any cases please let us know!
We’re working up to analyzing an interesting crash by learning more about working with the x64…
In order to work with x64 dumps we’re going to need to understand the calling convention used, that is going to allow us to do things such as identify the parameters passed to a particular function.
The basic rule here is that the first four parameters to a function are passed in registers, with the remaining parameters to the routine passed on the stack. The typical registers used here are:
Parameter 1 - RCX
Parameter2 - RDX
Parameter 3 - R8
Parameter 4 - R9
(NOTE: There are special rules when it comes to things such as floating point operations. Full details for those scenarios can be found here.)
For example, if a routine begins by accessing the contents of the RDX register, we can know that this routine is accessing the second parameter. We can also imply from that the fact that the caller must have loaded RDX with a meaningful value in a previous frame:
There is a major issue with this convention however. And that is the fact that all four of these parameters are treated as volatile by the compiler, meaning that their contents do not need to be saved across subroutine calls. Thus it is entirely possible and in fact quite likely that the compiler will overwrite the contents of these registers with unrelated values over the course of the subroutine. This makes reconstructing parameter values quite difficult on the x64.
The next x64 post will talk about the unique way that the x64 compiler utilizes the execution stack, which will then lead to a more detailed discussion on how we can utilize the stack to get parameter information back when we need it.
Just posted a nifty new WinDBG extension on OSR Online. It provides quick access to all of the WinDBG commands that you’ve used in your current debug session:
http://www.osronline.com/article.cfm?article=547
It’s something that I’ve wanted for a while, so I finally decided to just shut up and code it!
The first thing that anyone working with x64 dumps needs to know is that trap frames on the x64 do not contain non-volatile register state. What this means for you the analyst is that when you use the .trap command with an x64 target you cannot trust the register contents displayed for rbx, rbp, rdi, rsi, and r12-r15. If you need the contents of these registers at the time of the crash you will need to find the contents indirectly.
I highly recommend that you read my full treatment of this topic in the last issue of The NT Insider: http://www.osronline.com/article.cfm?id=542. In an upcoming post I’ll be showing another example of this as well.
I was over on the Sysinternals forums and analyzed a crash dump for a member there. The dump turned out to be fascinating and also reminded me just how painful debugging x64 crashes can be…
I was so interested by the crash that I was going to just write up an analysis and dump it here (no pun intended), but I think I’m going to take a bit more of a scientific approach and tackle a couple of important x64 crash dump details/techniques before diving in to the crash. Hopefully that will lead to a more meaningful analysis and help everyone out there that has to work with x64 crashes (which will be all of you eventually!).
I’ve mentioned this here before, but more information on crash dumps and Windows 7 in the latest issue of The NT Insider:
http://www.osronline.com/article.cfm?article=545
Also, if you’re a subscriber the mailed issue has another article on common crash dump analysis/bug reporting mistakes that will hopefully be useful.