Showing posts with label Windbg. Show all posts
Showing posts with label Windbg. Show all posts

Saturday, December 7, 2013

Debugging Map using Windbg

Here is the script which we can use for displaying the MAP:

.if ($sicmp("${$arg1}", "-n") == 0) {
    .if (@@(@$t0->_Isnil) == 0) {
        .if (@$t2 == 1) {
            .printf /D "%p\n", @$t0, @$t0
            .printf "key = "
            ?? @$t0->_Myval.first
            .printf "value = "
            ?? @$t0->_Myval.second
        } .else {
            r? $t9 = @$t0->_Myval
            command
        }
    }

    $$ Recurse into _Left, _Right unless they point to the root of the tree
    .if (@@(@$t0->_Left) != @@(@$t1)) {
        .push /r /q
        r? $t0 = @$t0->_Left
        $$>a< ${$arg0} -n
        .pop /r /q
    }
    .if (@@(@$t0->_Right) != @@(@$t1)) {
        .push /r /q
        r? $t0 = @$t0->_Right
        $$>a< ${$arg0} -n
        .pop /r /q
    }
} .else {
    r? $t0 = ${$arg1}

    .if (${/d:$arg2}) {
        .if ($sicmp("${$arg2}", "-c") == 0) {
            r $t2 = 0
            aS ${/v:command} "${$arg3}"
        }
    } .else {
        r $t2 = 1
        aS ${/v:command} " "
    }

    .printf "size = %d\n", @@(@$t0._Mysize)
   
    r? $t0 = @$t0._Myhead->_Parent
    r? $t1 = @$t0->_Parent

    $$>a< ${$arg0} -n

    ad command
}

traverse_map.script
A WinDbg script that traverses std::map objects.

Usage:

$$>a< traverse_map.script [-c "cmd"]

where cmd can reference @$t9, e.g. "?? @$t9.second" (this is the pair held by the map) and can also reference @$t0, which is the actual tree node pointer.

Examples:

$$>a< traverse_map.script my_map -c ".block { .echo ----; ?? @$t9.first; ?? @$t9.second; }"
$$>a< traverse_map.script m -c ".block { .if (@@(@$t9.first) == 8) { .echo ----; ?? @$t9.second } }"
$$>a< traverse_map.script my_map

Sample Program:-

class MapTest
{
public:
void PopulateMap();
private:
map m_Map1;
map m_Map2;
};

void MapTest::PopulateMap()
{
m_Map1[0] = 99;
m_Map1[1] = 100;

m_Map2[0] = wstring(L"Hello");
m_Map2[1] = wstring(L"World");

//stop the debugger here
__asm int 3
}

int _tmain(int argc, _TCHAR* argv[])
{

map  mm;
mm[1] = 1;
mm[2] = 2;

//stop the debugger
__asm int 3
MapTest mt;
mt.PopulateMap();
}


TestApp!wmain+0x8a:
0125203a 8d4d94          lea     ecx,[ebp-6Ch]
0:000> $$>a<C:\Users\ankurm\Desktop\traverse_map1.script mm
size = 2
002e8a48
key = int 0n1
value = int 0n1
002e8aa0
key = int 0n2
value = int 0n2
0:000> g
(2f68.2260): Break instruction exception - code 80000003 (first chance)
eax=00000000 ebx=7efde000 ecx=8c2cadb9 edx=65a7d238 esi=001af620 edi=001af784
eip=01251f26 esp=001af620 ebp=001af790 iopl=0         nv up ei pl zr na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246
TestApp!MapTest::PopulateMap+0x186:
01251f26 cc              int     3
0:000> dv
           this = 0x001af8ec
0:000> $$>a<C:\Users\ankurm\Desktop\traverse_map1.script this->m_Map1
size = 2
002e8bc0
key = int 0n0
value = int 0n99
002e8c18
key = int 0n1
value = int 0n100
0:000> $$>a<C:\Users\ankurm\Desktop\traverse_map1.script this->m_Map2
size = 2
002e8c70
key = int 0n0
value = class std::basic_string,std::allocator >
   +0x000 _Myfirstiter     : (null) 
   +0x004 _Alval           : std::allocator
   =01240000 npos             : 0x905a4d
   +0x008 _Bx              : std::basic_string,std::allocator >::_Bxty
   +0x018 _Mysize          : 5
   +0x01c _Myres           : 7
002e8ce0
key = int 0n1
value = class std::basic_string,std::allocator >
   +0x000 _Myfirstiter     : (null) 
   +0x004 _Alval           : std::allocator
   =01240000 npos             : 0x905a4d
   +0x008 _Bx              : std::basic_string,std::allocator >::_Bxty
   +0x018 _Mysize          : 5
   +0x01c _Myres           : 7


References:-
http://blogs.microsoft.co.il/sasha/2013/07/25/displaying-and-searching-stdmap-contents-in-windbg/
https://github.com/goldshtn/windbg-extensions

Monday, September 24, 2012

Manually Verifing the stack

#define SAVE_EBP   static unsigned int dwValue1 = 0, dwValue2 = 0; __asm mov eax, [ebp] __asm mov dwValue1, eax
#define COPY_EBP  __asm mov eax, [ebp] __asm mov dwValue2, eax 
#define CHECK_EBP if(dwValue1 != dwValue2) { int i = 0; i = 1/i; }

e.g.

void function()
{
SAVE_EBP
.
.
.
.

COPY_EBP
CHECK_EBP
}

Inspecting CString, wstring, and static char buffer

    char *pString = new char[20];
    ::strcpy_s(pString, 20*sizeof(char), "Test string");
    CString *pStr = new CString("Hello World");
    std::wstring stdString = L"STD String";
    CDialogEx::OnOK(); <= Break point

0:000> dv /V /i /t

prv local  001af284 @ebp-0x3c class ATL::CStringT > > * pStr = 0x0097b830
prv local  001af290 @ebp-0x30 char * pString = 0x0097b7e0 "Test string"
prv local  001af25c @ebp-0x64 class std::basic_string,std::allocator > stdString = class std::basic_string,std::allocator >
0:000> dt -a11 0x0097b7e0 char
[0] @ 0097b7e0
---------------------------------------------
84 'T'

[1] @ 0097b7e1
---------------------------------------------
101 'e'
[2] @ 0097b7e2
---------------------------------------------
115 's'
[3] @ 0097b7e3
---------------------------------------------
116 't'
[4] @ 0097b7e4
---------------------------------------------
32 ' '
[5] @ 0097b7e5
---------------------------------------------
115 's'
[6] @ 0097b7e6
---------------------------------------------
116 't'
[7] @ 0097b7e7
---------------------------------------------
114 'r'
[8] @ 0097b7e8
---------------------------------------------
105 'i'
[9] @ 0097b7e9
---------------------------------------------
110 'n'
[10] @ 0097b7ea
---------------------------------------------
103 'g'
0:000> da 0x0097b7e0
0097b7e0  "Test string"
0:000> !stl -n (std::basic_string,std::allocator >) 001af25c
[du 0x97b920]
0097b920  "STD String"
0:000> dpu 001af25c L2
001af25c  0097b8d8 ".."
001af260  0097b920 "STD String"
0:000> !stl stdString
[du 0x97b920]
0097b920  "STD String"
0:000> !SDbgExt.stlwstring 001af25c
wstring size=10 reserved=15 buf=0097b920 "STD String"
0:000> dt 0x0097b830 CString
mfc_test_del!CString
   +0x000 m_pszData        : 0x0097b880  "Hello World"

Inspecting CObList using Windbg

void Cmfc_test_delDlg::OnBnClickedOk()
{
    CObList *pList = new CObList();
    pList->AddTail(new CAge(10));
    pList->AddTail(new CAge(20));
    pList->AddTail(new CAge(30));
    pList->AddTail(new CAge(40));
    pList->AddTail(new CAge(50));
    pList->AddTail(new CAge(60));
    // TODO: Add your control notification handler code here
    CDialogEx::OnOK();
}
0:000> *Beakpoint is at CDialogEx::OnOK() in Cmfc_test_delDlg::OnBnClickedOk()
0:000> bl
 0 e 00335010 [c:\vs\mfc_test_del\mfc_test_del\mfc_test_deldlg.cpp @ 158]    0001 (0001)  0:**** mfc_test_del!Cmfc_test_delDlg::OnBnClickedOk
0:000> *Lets look at local variable
0:000> dv /V /i /t
prv local  00a8ef58 @ebp-0x14 class Cmfc_test_delDlg * this = 0x00a8f864
prv local  00a8ef4c @ebp-0x20 class CObList * pList = 0x01e58cc8
0:000> *Display  the type for CObList
0:000> dt 0x01e58cc8 CObList
mfc_test_del!CObList
   +0x000 __VFN_table : 0x007f7f6c
   =007f7fb4 CObject::classCObject : CRuntimeClass
   =008b0c28 CObList::classCObList : CRuntimeClass
   +0x004 m_pNodeHead      : 0x01e5b5dc CObList::CNode  <= Pointer to linked list from Start
   +0x008 m_pNodeTail      : 0x01e5b618 CObList::CNode   <= Pointer to listed list from  End
   +0x00c m_nCount         : 0n6                                                <= Number of elements in the linked list
   +0x010 m_pNodeFree      : 0x01e5b624 CObList::CNode
   +0x014 m_pBlocks        : 0x01e5b5d8 CPlex
   +0x018 m_nBlockSize     : 0n10                                           <= memory reserved for 10 elements
0:000> *Find the head of the list
0:000> ?poi(0x01e58cc8+0x004 )
Evaluate expression: 31831516 = 01e5b5dc
0:000> *Display the list
0:000> dt CObList::CNode -l 0x01e5b5dc pNext
mfc_test_del!CObList::CNode
pNext at 0x1e5b5dc
---------------------------------------------
   +0x000 pNext            : 0x01e5b5e8 CObList::CNode
   +0x004 pPrev            : (null)
   +0x008 data             : 0x01e58d20 CObject
pNext at 0x1e5b5e8
---------------------------------------------
   +0x000 pNext            : 0x01e5b5f4 CObList::CNode
   +0x004 pPrev            : 0x01e5b5dc CObList::CNode
   +0x008 data             : 0x01e5b690 CObject
pNext at 0x1e5b5f4
---------------------------------------------
   +0x000 pNext            : 0x01e5b600 CObList::CNode
   +0x004 pPrev            : 0x01e5b5e8 CObList::CNode
   +0x008 data             : 0x01e5b6d8 CObject
pNext at 0x1e5b600
---------------------------------------------
   +0x000 pNext            : 0x01e5b60c CObList::CNode
   +0x004 pPrev            : 0x01e5b5f4 CObList::CNode
   +0x008 data             : 0x01e5b720 CObject
pNext at 0x1e5b60c
---------------------------------------------
   +0x000 pNext            : 0x01e5b618 CObList::CNode
   +0x004 pPrev            : 0x01e5b600 CObList::CNode
   +0x008 data             : 0x01e5b768 CObject
pNext at 0x1e5b618
---------------------------------------------
   +0x000 pNext            : (null)
   +0x004 pPrev            : 0x01e5b60c CObList::CNode
   +0x008 data             : 0x01e5b7b0 CObject
0:000> *Display the list from back
0:000> dt CObList::CNode -l 0x1e5b618 pPrev
mfc_test_del!CObList::CNode
pPrev at 0x1e5b618
---------------------------------------------
   +0x000 pNext            : (null)
   +0x004 pPrev            : 0x01e5b60c CObList::CNode
   +0x008 data             : 0x01e5b7b0 CObject
pPrev at 0x1e5b60c
---------------------------------------------
   +0x000 pNext            : 0x01e5b618 CObList::CNode
   +0x004 pPrev            : 0x01e5b600 CObList::CNode
   +0x008 data             : 0x01e5b768 CObject
pPrev at 0x1e5b600
---------------------------------------------
   +0x000 pNext            : 0x01e5b60c CObList::CNode
   +0x004 pPrev            : 0x01e5b5f4 CObList::CNode
   +0x008 data             : 0x01e5b720 CObject
pPrev at 0x1e5b5f4
---------------------------------------------
   +0x000 pNext            : 0x01e5b600 CObList::CNode
   +0x004 pPrev            : 0x01e5b5e8 CObList::CNode
   +0x008 data             : 0x01e5b6d8 CObject
pPrev at 0x1e5b5e8
---------------------------------------------
   +0x000 pNext            : 0x01e5b5f4 CObList::CNode
   +0x004 pPrev            : 0x01e5b5dc CObList::CNode
   +0x008 data             : 0x01e5b690 CObject
pPrev at 0x1e5b5dc
---------------------------------------------
   +0x000 pNext            : 0x01e5b5e8 CObList::CNode
   +0x004 pPrev            : (null)
   +0x008 data             : 0x01e58d20 CObject
0:000> *Check the data field
0:000> dt 0x01e58d20 CAge
mfc_test_del!CAge
   +0x000 __VFN_table : 0x007f0c58
   =007f7fb4 CObject::classCObject : CRuntimeClass
   +0x004 m_years          : 0n10
0:000> *Same thing can be done using !list too.
0:000> !list -t CObList::CNode.pNext -x "dt" -a "CObList::CNode" -e 01e5b5dc

dt 0x1e5b5dc CObList::CNode
mfc_test_del!CObList::CNode
   +0x000 pNext            : 0x01e5b5e8 CObList::CNode
   +0x004 pPrev            : (null)
   +0x008 data             : 0x01e58d20 CObject
dt 0x1e5b5e8 CObList::CNode
mfc_test_del!CObList::CNode
   +0x000 pNext            : 0x01e5b5f4 CObList::CNode
   +0x004 pPrev            : 0x01e5b5dc CObList::CNode
   +0x008 data             : 0x01e5b690 CObject
dt 0x1e5b5f4 CObList::CNode
mfc_test_del!CObList::CNode
   +0x000 pNext            : 0x01e5b600 CObList::CNode
   +0x004 pPrev            : 0x01e5b5e8 CObList::CNode
   +0x008 data             : 0x01e5b6d8 CObject
dt 0x1e5b600 CObList::CNode
mfc_test_del!CObList::CNode
   +0x000 pNext            : 0x01e5b60c CObList::CNode
   +0x004 pPrev            : 0x01e5b5f4 CObList::CNode
   +0x008 data             : 0x01e5b720 CObject
dt 0x1e5b60c CObList::CNode
mfc_test_del!CObList::CNode
   +0x000 pNext            : 0x01e5b618 CObList::CNode
   +0x004 pPrev            : 0x01e5b600 CObList::CNode
   +0x008 data             : 0x01e5b768 CObject
dt 0x1e5b618 CObList::CNode
mfc_test_del!CObList::CNode
   +0x000 pNext            : (null)
   +0x004 pPrev            : 0x01e5b60c CObList::CNode
   +0x008 data             : 0x01e5b7b0 CObject
0:000> !list -t CObList::CNode.pNext -x "dt" -a "CObList::CNode data" -e 01e5b5dc
dt 0x1e5b5dc CObList::CNode data
mfc_test_del!CObList::CNode
   +0x008 data : 0x01e58d20 CObject
dt 0x1e5b5e8 CObList::CNode data
mfc_test_del!CObList::CNode
   +0x008 data : 0x01e5b690 CObject
dt 0x1e5b5f4 CObList::CNode data
mfc_test_del!CObList::CNode
   +0x008 data : 0x01e5b6d8 CObject
dt 0x1e5b600 CObList::CNode data
mfc_test_del!CObList::CNode
   +0x008 data : 0x01e5b720 CObject
dt 0x1e5b60c CObList::CNode data
mfc_test_del!CObList::CNode
   +0x008 data : 0x01e5b768 CObject
dt 0x1e5b618 CObList::CNode data
mfc_test_del!CObList::CNode
   +0x008 data : 0x01e5b7b0 CObject
 

Tuesday, September 11, 2012

Windows: Transition from User to Kernel


1. Find the notepad process object
kd> !process 0 0 notepad.exe
PROCESS 859c29b8  SessionId: 1  Cid: 0914    Peb: 7ffd4000  ParentCid: 0600
    DirBase: 3ec4c420  ObjectTable: 921e3470  HandleCount:  57.
    Image: notepad.exe

2.Switch to notepad process context
kd> .process /i 859c29b8 
You need to continue execution (press 'g' ) for the context
to be switched. When the debugger breaks in again, you will be in
the new process context.
kd> g
Break instruction exception - code 80000003 (first chance)
nt!RtlpBreakWithStatusInstruction:
826b9394 cc              int     3

3. Disassemble the NtCreateFile
kd> uf ntdll!ntCreateFile
ntdll!NtCreateFile:
77234a10 b842000000      mov     eax,42h
77234a15 ba0003fe7f      mov     edx,offset SharedUserData!SystemCallStub (7ffe0300)
77234a1a ff12            call    dword ptr [edx]
77234a1c c22c00          ret     2Ch

4. Find the content at 7ffe0300
kd> dd 7ffe0300 L1
7ffe0300  772364f0

5. Disassemble the code at 7ffe0300
kd> uf 772364f0
ntdll!KiFastSystemCall:
772364f0 8bd4            mov     edx,esp
772364f2 0f34            sysenter
772364f4 c3              ret

6. Find the address of KiServiceTable
kd> x nt!KiServiceTable
826bd6f0 nt!KiServiceTable =

7. Now display the function in System Service Table
kd> dps 0x826bd6f0+0x4*0x42 L1
826bd7f8  82898e82 nt!NtCreateFile

Saturday, April 10, 2010

Handle Leak, Memory Leak

How to Collect Information for Handle Leak Issues in Process Space for Post-mortem Analysis Click here!!!

Memory Leak Detection Using Windbg Click here!!!

Visual Leak Detector - Enhanced Memory Leak Detection for Visual C++ Click hete!!!

Tuesday, March 23, 2010

Argument of KiUserExceptionDispatcher() function

For hardware generated exceptions (such as access violations), one can look for ntdll!KiUserExceptionDispatcher on the stack, which takes a PCONTEXT and PEXCEPTION_RECORD as argument.

Stack Trace:

0021e9fc 77db5f79 fffffffe 0021f878 0021eb04 ntdll!_except_handler4+0x8e

0021ea20 77db5f4b 0021eae8 0021f878 0021eb04 ntdll!ExecuteHandler2+0x26

0021ead0 77db5dd7 0121eae8 0021eb04 0021eae8 ntdll!ExecuteHandler+0x24

0021ead0 77d8e13d 0121eae8 0021eb04 0021eae8 ntdll!KiUserExceptionDispatcher+0xf

0021ee20 77d8e04d 00000000 00000000 00000001 ntdll!RtlpWaitOnCriticalSection+0xc5

0:000> .exr 0x21eae8

ExceptionAddress: 77d8e13d (ntdll!RtlpWaitOnCriticalSection+0x000000c5)

ExceptionCode: c0000005 (Access violation)

ExceptionFlags: 00000000

NumberParameters: 2

Parameter[0]: 00000001

Parameter[1]: 00000014

Attempt to write to address 00000014

0:000> .cxr 0x21eb04

eax=00000000 ebx=fffffffc ecx=00000000 edx=00000004 esi=737b19a0 edi=737b19a4

eip=77d8e13d esp=0021edd0 ebp=0021ee20 iopl=0 nv up ei pl nz ac po cy

cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010213

ntdll!RtlpWaitOnCriticalSection+0xc5:

77d8e13d 83401401 add dword ptr [eax+14h],1 ds:0023:00000014=????????

0:000> dt -r1 0x21eb04 CONTEXT
ntdll!CONTEXT
+0x000 ContextFlags : 0x1003f
+0x004 Dr0 : 0
+0x008 Dr1 : 0
+0x00c Dr2 : 0
+0x010 Dr3 : 0
+0x014 Dr6 : 0
+0x018 Dr7 : 0
+0x01c FloatSave : _FLOATING_SAVE_AREA
   +0x000 ControlWord : 0xffff027f
   +0x004 StatusWord : 0xffff0000
   +0x008 TagWord : 0xffffffff
   +0x00c ErrorOffset : 0
   +0x010 ErrorSelector : 0
   +0x014 DataOffset : 0
   +0x018 DataSelector : 0xffff0000
   +0x01c RegisterArea : [80] ""
   +0x06c Cr0NpxState : 0
+0x08c SegGs : 0
+0x090 SegFs : 0x3b
+0x094 SegEs : 0x23
+0x098 SegDs : 0x23
+0x09c Edi : 0x737b19a4
+0x0a0 Esi : 0x737b19a0
+0x0a4 Ebx : 0xfffffffc
+0x0a8 Edx : 4
+0x0ac Ecx : 0
+0x0b0 Eax : 0
+0x0b4 Ebp : 0x21ee20
+0x0b8 Eip : 0x77d8e13d
+0x0bc SegCs : 0x1b
+0x0c0 EFlags : 0x10213
+0x0c4 Esp : 0x21edd0
+0x0c8 SegSs : 0x23
+0x0cc ExtendedRegisters : [512] "???"

0:000> dt -r1 0x21eae8 EXCEPTION_RECORD
ntdll!EXCEPTION_RECORD
+0x000 ExceptionCode : 0xc0000005
+0x004 ExceptionFlags : 0
+0x008 ExceptionRecord : (null)
+0x00c ExceptionAddress : 0x77d8e13d
+0x010 NumberParameters : 2
+0x014 ExceptionInformation : [15] 1

0:000> !error 0xc0000005
Error code: (NTSTATUS) 0xc0000005 (3221225477) - The instruction at "0x%08lx" referenced memory at "0x%08lx". The memory could not be "%s".


You can see the exception code is 0xc0000005 which is Access Violation
So whenever you find the KiUserExceptionDispatcher() function in call stack you can check for CONTEXT structure and EXCEPTION_RECORD structure, to find the exception code.

References:
Debugger tricks: Find all probable CONTEXT records in a crash dump