Hints for the native debugger’s expression evaluator

This is a list of a few hints for using the native debugger's expression evaluator. These are documented elsewhere, but I have run into a fair number of people that don't know about them.

  1. Format specifiers. These are expression suffixes that alter the expression's display. The most useful one is ',<size>' (example: pFoo,12) which tells the debugger to treat a pointer as an array of a particular size. 'eax,hr' is a requirement when debugging through optimized COM code. There is a complete listing here -- https://msdn.microsoft.com/library/default.asp?url=/library/en-us/vsdebug/html/_asug_format_specifiers_for_watch_variables.asp

  2. Context operator. This tells the debugger where to look. This is very useful when evaluating global variables from another dll (example:{,,foo}g_fooVar), or when setting a function breakpoint more explicitly (example: {,,kernel32}CreateProcessW) The complete listing is here -- https://msdn.microsoft.com/library/default.asp?url=/library/en-us/vsdebug/html/vchowcontextoperator.asp.

  3. Pseudo registers. @err is probably the most useful; this is the value of GetLastError(). '@err,hr' is even more useful. Also useful is @vframe, which can help you find stack variables when doing optimized debugging. @vframe usually points to the spot on the stack where the return address is pushed.

  4. Using typedefs. The native expression evaluator is very deeply tied to PDBs files. All types must either be in the PDB, or just slightly different then a PDB type. As an example, 'char*' works, but 'char**' doesn’t work because that is too different then a PDB type for the native EE to understand. However, your code probably has LPSTR defined, so use 'LPSTR *' instead.

  5. Evaluating strlen. Some CRT functions are written in ASM, and therefore don’t have a proper signature for the debugger to call. strlen is the classic example. Sometimes, you can use 'und_strlen' instead. If your binary doesn’t contain that symbol, you can always add a function to your binary that you can call:

     size_t CallStrlen(const char* s) { return strlen(s); } 
    
  6. Setting breakpoints with stripped symbols. If you are using Microsoft’s public symbol server (https://msdl.microsoft.com/download/symbols), then all of your OS symbols are stripped symbols. Setting breakpoints on functions with stripped symbols can be tricky because you need to know the size of the arguments to the function. There are a few options here.

    • You can go to MSDN and count the size of all the arguments in bytes.
    • You can also go to the disassembly window and step into a call to the function.
    • You could use dumpbin to find the address. Example:
      dumpbin /exports WINDOWS\system32\kernel32.dll | findstr /i CreateProcessW
            100   63 00001B8E CreateProcessW
      dumpbin /headers WINDOWS\system32\kernel32.dll | findstr /c:"image base"
            77E60000 image base (77E60000 to 77F45FFF)
      This tells you that CreateProcessW is at 0x77E60000+0x00001B8E=0x77E61B8E. You could set a breakpoint on that address. If you want, the Native EE can even tell you what's there by evaluating '(void*)0x77E61B8E'.
    • In Whidbey, you can also search for the symbol. For example, to search for CreateProcess, you could goto the immediate window and type .x kernel32!CreateProcess.*.
    • [Updated on Feb 22, 2005] You can 'dumpbin /linkermember' the import library. Example: dumpbin /linkermember kernel32.lib | findstr CreateProcess
      _CreateProcessA@40
      _CreateProcessW@40