WARNING: Stack unwind information not available. Following frames may be wrong.

I’m sure if you have ever used the WinDbg family of debuggers sometime, you must have seen the above message. What does it really mean? How does it affect you?

Quick Background on stack operation

In x86, the way the stack is built up, the entry point of the function (a.k.a. prolog) generated by the compiler contains some key instructions including one which saves the previous value of the EBP register for that thread on the stack. The next instruction sets the EBP register to point to the current stack pointer (ESP).

What am I talking about? If you don’t know what EBP and ESP are, I recommend you take a quick look at the links in the reference section at the end.

Frame Pointer Omission

So in some cases the compiler may choose to omit the setting of the EBP register and may instead directly use ESP to reference locals and parameters. In such cases the EBP register (a.k.a. ‘frame pointer’) is deemed as ‘omitted’ and the generated code is called FPO (Frame Pointer Omission) code.

In such cases the debugger will typically complain that it cannot unwind the stack based on the EBP (unless it has symbol files which match the module whose function has FPO enabled). Under those cases it will emit the warning which is the title of this post.

Recommendation

  • For builds which have /Oy enabled, it is necessary to have symbol files to successfully reconstruct the stack.
  • In the real world the most common reason to encounter the above message is faulty symbol paths. Check your symbol path.
  • In cases where you can tolerate the overhead of setting up the frame pointer, leave FPO off (/Oy-). See the last reference in my post for something which Windows team has supposedly done regarding this.

References

Advertisements

YADCU – Yet another dump capture utility

The plethora of dump capture tools is amazing and sometimes confusing. But here is one from Mark Russinovich which looks interesting: ProcDump. Some unique capabilities I can see in this tool are things like CPU threshold based triggers, the ability to clone a process so that it is suspended for minimum time when dump is captured, ability to launch another image on the event trigger, etc. Take a look at it, it should add to your debugging toolbox!

The meaning of CID in output of kernel debugger commands

Recently someone asked me what was the real meaning of the ‘Cid’ field which appears in the output of commands such as !process and !thread in the kernel debugger (kd). Though from a practical perspective I was aware that these represent the Process ID and Thread ID, I was unsure of what Cid stands for. In course of a search, I found a public source which answers the question. Cid is short for CLIENT_ID which in turn is an undocumented structure.

The public source is a free PDF version of the excellent “Undocumented Windows 2000 Secrets: A Programmer’s Cookbook” book, which you can now find at http://undocumented.rawol.com/. I think this resource is a very useful one for all those interested in Windows Internals and debugging as well. Go take a look at it!

Quick Tip: vfbasics!_AVRF_EXCEPTION_LOG_ENTRY symbol not resolved?

I was debugging some issues with the help of Application Verifier and WinDbg. Since I was onsite I did not have any access to Microsoft’s private symbol servers, so I was using the public symbol server (http://msdl.microsoft.com/download/symbols). On executing the !avrf extension command in WinDbg I was presented with the following error message in WinDbg:

***    Your debugger is not using the correct symbols                 ***
***                                                                   ***
***    In order for this command to work properly, your symbol path   ***
***    must point to .pdb files that have full type information.      ***
***                                                                   ***
***    Certain .pdb files (such as the public OS symbols) do not      ***
***    contain the required information.  Contact the group that      ***
***    provided you with these symbols if you need this command to    ***
***    work.                                                          ***
***                                                                   ***
***    Type referenced: vfbasics!_AVRF_EXCEPTION_LOG_ENTRY                ***

It turns out that my WinDbg symbol path was as follows, and due to it pointing just to the public symbol server it was loading public symbols for vfbasics.dll:

0:001> .sympath
Symbol search path is: SRV*c:localsymbols*
http://msdl.microsoft.com/download/symbols
Expanded Symbol search path is: srv*c:localsymbols*http://msdl.microsoft.com/download/symbols
0:001> lml
start             end                 module name
00000000`76dc0000 00000000`76f68000   ntdll      (pdb symbols)          c:localsymbolsntdll.pdbFDAD9EE7D6E44F4F9672ECB401A802192ntdll.pdb
000007fe`f0e50000 000007fe`f0ebe000   verifier   (pdb symbols)          c:localsymbolsverifier.pdb43FCE2D63C4544F9B1C67110EB3406951verifier.pdb
000007fe`f1660000 000007fe`f1693000   vrfcore    (pdb symbols)          c:localsymbolsvrfcore.pdb751D23CCD6504794AF2F18C1E547FE371vrfcore.pdb
000007fe`f28e0000 000007fe`f292a000   vfbasics   (pdb symbols)          c:localsymbolsvfbasics.pdb1ABCDFEFF9F4602A7F055801457A7D61vfbasics.pdb

To resolve the issue, I explicitly pre-pended the path to private symbols for vfbasics (which is c:windowssystem32 or in general %WINDIR%System32:

.sympath c:windowssystem32*SRV*c:localsymbols*http://msdl.microsoft.com/download/symbols

.reload

ld vfbasics

0:001> lml
start             end                 module name
00000000`76dc0000 00000000`76f68000   ntdll      (export symbols)       C:WindowsSYSTEM32ntdll.dll
000007fe`f28e0000 000007fe`f292a000   vfbasics   (private pdb symbols)  C:WindowsSYSTEM32vfbasics.pdb

Then !avrf works just fine!

If you liked this post, please do rate it and try to leave some comments if you can!

t-SQL Anti-Pattern: Index Key Order and Query Expression Order

This is really not a T-SQL anti-pattern as much as it is a database design issue, but we see it so often that it’s worthwhile bringing it up and clarifying things.

For illustrating the scenario, let’s examine the table Person.Contact in the AdventureWorks database. It has 2 columns called FirstName and LastName. Let’s say an application frequently queries this table with these columns in the WHERE clause. The query looks like this:

SELECT ContactID from Person.Contact

WHERE FirstName = ‘Carla’ and LastName = ‘Adams’

 

In order to support the query for seeking to the data, we create this index:

create nonclustered index idx_contact_names on Person.Contact(FirstName, LastName)

 

Now, let’s say there’s another application which fires another query on this table, and that query looks like this:

SELECT ContactID from Person.Contact

WHERE LastName = ‘Alberts’ and FirstName = ‘Amy’

 

Notice the difference between the 2 queries: the predicate ordering in the expression is different. Now, for the problem: some developers will now create another index, with the column order as (LastName, FirstName). That is not required. If you view the execution plan for both the queries, you will notice that the index is being used!

 

image

If you end up creating 2 indexes for the above scenario, SQL Server will effectively use only one of them for queries such as the above. The other index will only add to the overhead of index maintenance required during DML operations. So it is a redundant index and as such should be dropped.

 

Conclusion

The predicate order is independent of the choice of index to be created / the choice of index being used. SQL Server will use the index which yields a good plan.

Tip of the day: “An attempt was made to load a program with an incorrect format” .NET P/INVOKE issue

The other day I was using a 3rd party utility which was built on the .NET platform. My primary work computer happens to be a x64 installation. So on this computer when I fired the utility up, and tried to perform some tasks it would error with a .NET Exception which basically had the following characteristics:

– Message: “An attempt was made to load a program with an incorrect format”

– Exception: System.BadImageFormatException

After some troubleshooting it turned out that this utility was trying to load a plain-old DLL (which exported some functions) presumably using P/Invoke. The DLL was built for 32-bit platforms. Now it turns out that by design a 64-bit process (the 3rd party utility would run as a 64-bit process owing to the 64-bit .NET runtime) would be prevented from loading a non-COM 32-bit DLL (32-bit COM DLLs are loaded in a DLLHOST.EXE surrogate when invoked from a 64-bit client process, BTW…) with the above exception.

To configure the utility to run as a 32-bit .NET process, it turns out you can use the CORFLAGS utility. You run it as follows to switch the 32-bit execution mode ON:

corflags utility.exe /32Bit+

To turn it off, just use /32Bit- in the above command line.