Thursday, July 27, 2006

How to get the stack when 'k' tells you 'Stack unwind information not available. Following frames may be wrong.'

Sometimes Windbg is not able to recreate the stack when using the k command.
This problem might come up with frame pointer optimization for example.
In such cases you can easily construct the call stack manually with some usage of your brain:

First execute:
0:000> dps @ebp

This will list the raw contents of the stack along with a matching symbol if available (top down)

then execute 'd' (which repeats the last d* command) as long as you reach the bottom of the stack. Know you need to distinguish between calls on the stack and variables and so forth. With few knowledge of the code executed it is pretty obvious to devide the calls from the rest. I personally copy the calls to the scratch pad not to get lost.

Wednesday, June 07, 2006

How to find out what code modifies memory

You can use 'ba' (Break on Access) to define a breakpoint that hits when the portion of memory is read and/or modified.

ba w4 myPointer will cause the debugger to break, whenever myPointer is modified (assume a 32bit system)

How to debug double deletes / access after delete

It can happen that you come along an access violation but the source of the error has occured long time back in the past, because your code tries to access memory that has alreafy been freed.

I order to debug such a scenario you need to enable full page heap:

gflags -p /enable YourApp.exe /full

Then do the stuff to reproduce the AV. When you get it type this:

!heap -p -a [address of AV]

If you have luck you will get the call call stack of deallocation.

Friday, April 21, 2006

How to find out on which thread a blocked thread is waiting

First get the stack of the blocked thread by

0:002> kb
ChildEBP RetAddr Args to Child
00edfdd8 7c90e9c0 7c8025db 0000026c 00000000 ntdll!KiFastSystemCallRet
00edfddc 7c8025db 0000026c 00000000 00000000 ntdll!ZwWaitForSingleObject+0xc
00edfe40 7c802542 0000026c ffffffff 00000000 kernel32!WaitForSingleObjectEx+0xa8
00edfe54 6640114a 0000026c ffffffff 00813190 kernel32!WaitForSingleObject+0x12
[...]

The first parameter passed to WaitForSingleObject is the handle to the thread this thread is waiting for (Precondition: we are waiting for a thread and not another synchronisation object).


We can get more information about this handle by

0:002> !handle 0000026c f
Handle 0000026c
Type Thread
Attributes 0
GrantedAccess 0x1f03ff:
Delete,ReadControl,WriteDac,WriteOwner,Synch
Terminate,Suspend,Alert,GetContext,SetContext,SetInfo,QueryInfo,SetToken,Impersonate,DirectImpersonate
HandleCount 7
PointerCount 10
Name
Object specific information
Thread Id b94.ff4
Priority 3
Base Priority -16


Now we identified the questionable thread with b94.ff4

Thursday, March 23, 2006

Use !critsec to find out, which thread is waiting for a critical section

If you need to find out which thread is owning a critical section a blocked thread is waiting for you can first get the stack args by

kb

Then you need to get the critical section address from the stack. This is an argument passed to ntdll!RtlEnterCriticalSection API as first parameter.

By typing

!critsec 'address'

You'll get information about the section like: LockCount, RecursionCount, OwningThread, EntryCount, ContentionCount and the Locked state.

CritSec +81347c at 0081347c
LockCount 8
RecursionCount 1
OwningThread c6c
EntryCount 8
ContentionCount 8
*** Locked

Tuesday, March 14, 2006

Debug Tutorial Part 4: Writing WINDBG Extensions

Cool article from Toby Opferman about how extending windbg. Must read:
Debug Tutorial Part 4: Writing WINDBG Extensions

Friday, March 10, 2006

A word for WinDbg (Mike Taulty)

A very good starting point if you are planning to dig a bit into windbg:

W word for WinDbg
W word for WinDbg (2)

Wednesday, March 01, 2006

Starting UltraEdit from WinDbg

By setting follwoing env variable:
WINDBG_INVOKE_EDITOR=C:\PROGRA~1\ULTRAE~1\uedit32.exe %f/%l/1
{you might need to adapt the path}

You get the ability to open a source file from within windbg by simply right clicking on the source window header and then clicking "Edit this file..."

(this works also with other editors ;-) )

use "lmv m " to display detailed information about a specific module

e.g.:

0:003> lmv m actbar2
start end module name
35000000 350d0000 Actbar2 (export symbols) C:\SnapShots\voneinem_view_a0032858_c\VespucciPool\common\bin\debug\Actbar2.ocx
Loaded symbol image file: C:\SnapShots\voneinem_view_a0032858_c\VespucciPool\common\bin\debug\Actbar2.ocx
Image path: C:\SnapShots\voneinem_view_a0032858_c\VespucciPool\common\bin\debug\Actbar2.ocx
Image name: Actbar2.ocx
Timestamp: Wed Oct 27 16:52:02 2004 (417FB612)
CheckSum: 000D7481
ImageSize: 000D0000
File version: 2.5.2.121
Product version: 2.5.2.121
File flags: 0 (Mask 3F)
File OS: 40004 NT Win32
File type: 2.0 Dll
File date: 00000000.00000000
Translations: 0000.04b0 0409.04b0
CompanyName: Data Dynamics
ProductName: Data Dynamics ActiveBar 2.0 Control
InternalName: ActiveBar 2.5
OriginalFilename: ActiveBar2.ocx
ProductVersion: 2, 5, 2, 121
FileVersion: 2, 5, 2, 121
PrivateBuild: 2, 5, 2, 121
SpecialBuild: 2, 5, 2, 121
FileDescription: ActiveBar 2.5 Control
LegalCopyright: Copyright © 1999-2004 Data Dynamics
LegalTrademarks: Copyright © 1999-2004 Data Dynamics
Comments: Copyright © 1999-2004 Data Dynamics


To get a quick list of modules simply type "lm"

Display unicode strings the easy way

Did you ever wonder why windbg does not display unicode strings but simply shows the pointer?

Try ".enable_unicode 1"! This causes all 16-bit (USHORT) arrays and pointers to be displayed as Unicode strings.

(".enable_unicode 0" restores the default)

Wednesday, February 15, 2006

Monday, February 13, 2006

.NET debugging using WinDbg

This is a very good step by step cook book about .NET debugging using WinDbg

A word for WinDbg (2)

Thursday, November 17, 2005

Using DbgHelp.dll MiniDumpWriteDump function with Borland C++ Builder 5

I have written a handy class that allows to use the DbgHelp.dll MiniDumpWriteDump function in Borland C++ Builder 5 environment. Feel free to use it:

//DLL wrapper class
#define CALLING_CONVENTION __stdcall

class CDbgHelpDLL
{
public:
CDbgHelpDLL()
{
m_hDLL = ::LoadLibraryA("dbghelp.dll");
if(NULL != m_hDLL)
{
//CodeSite API
DLLMiniDumpWriteDump = (BOOL (CALLING_CONVENTION *)
(HANDLE,
DWORD,
HANDLE,
MINIDUMP_TYPE,
CONST PMINIDUMP_EXCEPTION_INFORMATION,
CONST PMINIDUMP_USER_STREAM_INFORMATION,
CONST PMINIDUMP_CALLBACK_INFORMATION))
::GetProcAddress(m_hDLL, "MiniDumpWriteDump");
}
else
{
DLLMiniDumpWriteDump = NULL;
}
}
~CDbgHelpDLL()
{
if(NULL != m_hDLL)
{
::FreeLibrary(m_hDLL);
m_hDLL = NULL;
}
}

BOOL MiniDumpWriteDump(
HANDLE hProcess,
DWORD ProcessId,
HANDLE hFile,
MINIDUMP_TYPE DumpType,
PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
PMINIDUMP_CALLBACK_INFORMATION CallbackParam
)
{
if (DLLMiniDumpWriteDump){
return DLLMiniDumpWriteDump( hProcess,
ProcessId,
hFile,
DumpType,
ExceptionParam,
UserStreamParam,
CallbackParam);
}
else
{
return FALSE;
}
}



private:
HINSTANCE m_hDLL;
//DLL functions
BOOL (CALLING_CONVENTION *DLLMiniDumpWriteDump)( HANDLE hProcess,
DWORD ProcessId,
HANDLE hFile,
MINIDUMP_TYPE DumpType,
CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam);
};

In order to compile with dbghelp.h from ms, you need to "patch" it:

before // for those without specstrings.h add:

//CBuilder
#ifdef __BORLANDC__
using namespace System;
#endif

Change this:
#ifdef __BORLANDC__
enum hdEnums {
#else
typedef enum {
#endif
hdBase = 0, // root directory for dbghelp
hdSym, // where symbols are stored
hdSrc, // where source is stored
hdMax // end marker
};

and this:
#ifdef __BORLANDC__
enum sfEnums {
#else
typedef enum {
#endif
sfImage = 0,
sfDbg,
sfPdb,
sfMpd,
sfMax
};

and here we go ...
Happy crash dumping with borland ;-)

Wednesday, November 16, 2005

Using WinDbg with Borland

I'm using this tool and I must say it's great! Of course you just get the info that is there in the map file. Therefore no info about local variables. But with a bit knowledge, you can oracle those from the stack memory :-)

Ms-dbg
brings microsoft-compatible debugging to Borland. With "map2dbg" you can convert from a borland MAP file to a ms DBG file. This lets you use standard debugging tools like DrWatson and imagehlp.dll. For instance, in "calldemo" we use it to generate a callstack of the current program. Helpful for debugging clients a thousand miles away.

Source:
http://www.wischik.com/lu/programmer/

Application debugging in a production environment (Hans De Smaele)

Very, very cool article:

http://www.microsoft.com/belux/nl/msdn/community/articles/feb05_applicationdebugging.mspx

Application debugging in a production environment


Summary: This document is made for people who have to support and maintain a production environment. Answers are given on questions like: "Yesterday it still worked and now it doesn't anymore, what did happen?" or "Why does it work on this computer and not on another one?". Every part of the paper is explained as a walkthrough in order to use it as reference material and/or as a workbook to learn some particular debugging scenarios. (125 printed pages)

This article covers the following topics:
  • Debugging and instrumenting scripts
  • Using tools to do first analysis (FileMon, RegMon, Dependency Walker, ...)
  • A step-by-step guide for using the WinDbg debugger
  • Symbol and symbol servers
  • Calling conventions
  • Stack tracing and related subjects
  • Debugging of "free builds"
  • Creation and debugging of "dump files"
  • Working with ILDASM and ILASM
  • Other useful WinDbg extensions
  • Remote debugging
  • Debug scenarios

Tuesday, November 15, 2005