Windows System Software -- Consulting, Training, Development -- Unique Expertise, Guaranteed Results
The free OSR Learning Library has more than 50 articles on a wide variety of topics about writing and debugging device drivers and Minifilters. From introductory level to advanced. All the articles have been recently reviewed and updated, and are written using the clear and definitive style you've come to expect from OSR over the years.
Check out The OSR Learning Library at: https://www.osr.com/osr-learning-library/
Whenever I use windbg on a x64 kernel dump, and go through the local variables for each of the callstack functions, I see a lot of junk values.
My question is, is this because the arguments to functions are lost in x64 crash dumps (since most of them are passed in registers) ?
If not, then why I see so many junk values in Local variables of x64 crash dumps, and how can Windbg recover the function arguments passed in register in call stack functions?
Upcoming OSR Seminars | ||
---|---|---|
OSR has suspended in-person seminars due to the Covid-19 outbreak. But, don't miss your training! Attend via the internet instead! | ||
Kernel Debugging | 16-20 October 2023 | Live, Online |
Developing Minifilters | 13-17 November 2023 | Live, Online |
Internals & Software Drivers | 4-8 Dec 2023 | Live, Online |
Writing WDF Drivers | 10-14 July 2023 | Live, Online |
Comments
The first two are the same and won't be junk.
Kv output won't show "parameters", because even if they are passed on the
stack (more than 4 params needed), the local stack value may get reused or
the value changed. This is useless for any parameter viewing.
You can inspect the entire stack frame for values manually and guess more
than you can be sure.
Dejan.
Long answer:
In the Windows ABI the first four arguments are passed in RCX, RDX, R8, and R9. There is an area on the stack called the Home Space* that can be used to "home" the arguments onto the stack. This is always the first 32 bytes on the stack after the return address*. The remaining arguments to the function are then passed on the stack after the Home Space.
In the debug build of your code the compiler always homes the arguments onto the stack. This allows the debugger to always show you the arguments even if the registers get reused. You can see this behavior very clearly if you look at KeBugcheckEx, which is always compiled without optimizations:
However, in the optimized build the function is free to use that Home Space however it wants. Some functions ignore it, some functions store non-volatile registers, some even home random arguments for some reason...For example:
The debugger is dumb very trusting so it just always assumes the arguments are in the Home Space. So, sometimes you get junk and sometimes you get the right values. This is also why the parameters are always garbage if you break at the start of the function but magically fix themselves once you single step.
-scott
This is also called the Shadow Space or Spill Space...I like Home Space
Note that there's always 32-bytes of Home Space, even if the function doesn't take any arguments...
-scott
OSR
Wow, even after so many years of reading assembly I never knew this shadow space exists! Thanks for the detailed answer.
So basically in the release builds, the arguments to the functions are junks (since I assume the compiler will never pass arguments to the shadow stack in release builds when optimization is on), correct?
Also another question: Sometimes when I view the local variables on a crash dump, some of the local functions are straight up missing. So are these optimized out? if so, then does this mean that If i see a local (not function argument) variable in the local variables view of windbg, then it should always be correct (since in this case I at least know that it was not optimized out) ? And if it's a junk value, then it means that it was overwritten with a junk value which means a stack overflow?
This is all part of the Windows x64 calling convention. Linux does it a little bit differently.
The first 4 arguments go in rcx, rdx, r8, and r9. They are not stored on the stack, in either release or debug builds, even though space is allocated for them. In the debug build, the function that RECEIVES the parameters tucks them away on the stack to help the debugger.
I assume you mean local variables. In general, you should not make any "should always be" assumptions with the debugger. It does the best that it can, but sometimes the information it needs is simply not present.
Tim Roberts, [email protected]
Providenza & Boekelheide, Inc.
Well, almost all of the crash dumps that I analyze contain a lot of junk values in Local view.
My main goal is to understand whether these junk values mean an overflow happened, or it's because of loss of information (because of optimization, argument passing, etc).
I apologize, yes I meant local variables, not local functions.
So is there anyway that I can be 100% sure whether or not a local variable having a junk value is because of optimization/registry argument passing, or because of some overflow/corruption?
100% sure? No. Since the spill region happens BEFORE the function call, if there is a stack overflow, it will usually have trashed the return address as well. It would be a very specific corruption that hops over the return address.
Tim Roberts, [email protected]
Providenza & Boekelheide, Inc.
Both will show "variable is not available" for optimized away variables.
Unless corruption happened or Mosmatched PDBs, the values are very likely
to be correct here.
It is the STACK output (kv command or Stack window) that are not likely to
show any correct values for arguments.
But I have seen random values for some of the locals in the kernel crash dumps many many times, Specially in x64 crash dumps, and almost always they had nothing to do with the crash dump so I always assumed these random values/NULLs that happen in local variables in x64 is because of the fact that function arguments are lost since they are passed in registers (assuming its a release build)
Also if there is a pdb mismatch, then the symbols wont even load to begin with.
doesn't answer