Monthly Archive for 5월, 2008

[windbg] windbg script - RawStack Trace

User쪽 Thread Rawstack를 보여주는 스크립트  
$$ _rawstack_user.dbg
.if( ( 0 = ${/d:$arg1} ) )
{
~*e r? $t1 = ((ntdll!_NT_TIB *)@$teb)->StackLimit; r? $t2 = ((ntdll!_NT_TIB *)@$teb)->StackBase;kvn;!teb;dps @$t1 @$t2
}
.else
{
~${$arg1}e r? $t1 = ((ntdll!_NT_TIB *)@$teb)->StackLimit; r? $t2 = ((ntdll!_NT_TIB *)@$teb)->StackBase;kvn;!teb;dps @$t1 @$t2
}

Kernel쪽 Thread Rawstack를 보여주는 스크립트  
$$ _rawstack_kernel.dbg
.if( ( 0 = ${/d:$arg1} ) )
{
!for_each_thread ".thread /r /p @#Thread; .if (@$teb != 0 & @$proc == ${$arg1} ) { !thread @#Thread; r? $t1 = ((ntdll!_NT_TIB *)@$teb)->StackLimit; r? $t2 = ((ntdll!_NT_TIB *)@$teb)->StackBase;!teb;dps @$t1 @$t2 }"
}
.else
{
!for_each_thread ".thread /r /p @#Thread; .if (@$teb != 0) { !thread @#Thread; r? $t1 = ((ntdll!_NT_TIB *)@$teb)->StackLimit; r? $t2 = ((ntdll!_NT_TIB *)@$teb)->StackBase;!teb;dps @$t1 @$t2 }"
}

위의 두가지를 통합해주는 스크립트( np!dbgmode 는 Debug Mode를 확인해서 $t0에 넣어주는 로직임 )
$$ 실제 Command Line 처리
.block
{
aS ${/v:np!_rawstack_user} "$$>a<${root}\\_rawstack_user.dbg";
aS ${/v:np!_rawstack_kernel} "$$>a<${root}\\_rawstack_kernel.dbg";
};
.block
{
np!dbgmode
.if ((@$t0!=1) & (@$t0!=2))
{
.if( ( 0 = ${/d:$arg1} ) )
{
np!_rawstack_user;
}
.else
{
np!_rawstack_user ${$arg1}
}

}
.else
{
.if( ( 0 = ${/d:$arg1} ) )
{
np!_rawstack_kernel;
}
.else
{
np!_rawstack_kernel ${$arg1}
}
}
}

.block
{
ad /q ${/v:np!_rawstack_user};
ad /q ${/v:np!_rawstack_kernel};

};

아직 미완성이라 잘될지 안될지 모르지만 .. 한번 올려봅니다.

Windbg Script 정리

개인적으로 사용하고 있는 Windbg Script를 정리하여 라이브러리화 하고 있습니다 .
생각보다 뿌듯하내요

windbgsc.PNG

windbgsc2.png

사내에서 사용하는 것이라 공개는 좀 힘들꺼 같아요 ^ ^

그냥 자랑만 !! ㅋ

[tip] Memory Dump에서 Virtual PC 여부 확인

간만에 posting을 합니다.  그래봤자 3일 후후 좀 요즘 게을러지내요. Memory Dump를 보다 보면 Virtual PC내에서 발생하는 덤프들이 종종이습니다. 그리고 분석으로 위해서 Virtual PC여부를 확인하고자 한다면 간단한 Command 몇가지로 확인이 가능합니다.

kd> !vm

*** Virtual Memory Usage ***
 Physical Memory:      131452 (    525808 Kb)
 Page File: \??\C:\pagefile.sys
   Current:    393216 Kb  Free Space:    390816 Kb
   Minimum:    393216 Kb  Maximum:       786432 Kb
 Available Pages:       77408 (    309632 Kb)
 ResAvail Pages:        98085 (    392340 Kb)
 Locked IO Pages:         121 (       484 Kb)
 Free System PTEs:     248603 (    994412 Kb)
 Free NP PTEs:          28472 (    113888 Kb)
 Free Special NP:           0 (         0 Kb)
 Modified Pages:          774 (      3096 Kb)
 Modified PF Pages:       770 (      3080 Kb)
 NonPagedPool Usage:      764 (      3056 Kb)
 NonPagedPool Max:      32768 (    131072 Kb)
 PagedPool 0 Usage:      3449 (     13796 Kb)
 PagedPool 1 Usage:       506 (      2024 Kb)
 PagedPool 2 Usage:       492 (      1968 Kb)
 PagedPool Usage:        4447 (     17788 Kb)
 PagedPool Maximum:     65536 (    262144 Kb)
 Shared Commit:           998 (      3992 Kb)
 Special Pool:              0 (         0 Kb)
 Shared Process:         1764 (      7056 Kb)
 PagedPool Commit:       4447 (     17788 Kb)
 Driver Commit:          1188 (      4752 Kb)
 Committed pages:       94917 (    379668 Kb)
 Commit limit:         222283 (    889132 Kb)

 Total Private:         86287 (    345148 Kb)
         0358 svchost.exe      10519 (     42076 Kb)
         0754 sqlservr.exe      8769 (     35076 Kb)
         0480 explorer.exe      7821 (     31284 Kb)
         01f4 winlogon.exe      6325 (     25300 Kb)
         0784 nspsvc.exe        6273 (     25092 Kb)
         05d0 nspmain.exe       4819 (     19276 Kb)
         0514 spoolsv.exe       4481 (     17924 Kb)
         022c lsass.exe         4431 (     17724 Kb)
         0604 rundll32.exe      4015 (     16060 Kb)
         0220 services.exe      3945 (     15780 Kb)
         0308 svchost.exe       3512 (     14048 Kb)
         0400 svchost.exe       3364 (     13456 Kb)
         0478 svchost.exe       3098 (     12392 Kb)
         02c8 svchost.exe       2571 (     10284 Kb)
         01dc csrss.exe         2355 (      9420 Kb)
         05c8 vmusrvc.exe       2342 (      9368 Kb)
         05dc ctfmon.exe        2243 (      8972 Kb)
         07bc sqlwriter.exe     1824 (      7296 Kb)
         0708 vmsrvc.exe        1817 (      7268 Kb)
         07dc vpcmap.exe        1171 (      4684 Kb)
         0148 smss.exe           585 (      2340 Kb)
         0004 System               7 (        28 Kb)

!vm Command를 통해서 보면 Virtual PC의 경우 위 3가지 모듈이 있는것을 확인할 수 있습니다.  그리고 현재의 System 정보를 통해서도 확인이 가능합니다.

kd> !sysinfo machineid
Machine ID Information [From Smbios 2.3, DMIVersion 35, Size=1644]
BiosVendor = American Megatrends Inc.
BiosVersion = 080002
BiosReleaseDate = 02/22/2006
SystemManufacturer = Microsoft Corporation
SystemProductName = Virtual Machine
SystemVersion = VS2005R2
BaseBoardManufacturer = Microsoft Corporation
BaseBoardProduct = Virtual Machine
BaseBoardVersion = 5.0

마지막으로 현재 Load된 모듈을 통해서 확인하는 방법이 있지요.

kd> lmt m vpc*
start    end        module name
bf9d5000 bf9ed000   vpc_s3_bf9d5000  Sun Sep 18 19:59:18 2005 (432D4886)
f8286000 f829d000   vpc_s3    Sun Sep 18 19:59:20 2005 (432D4888)

외부에서 들어오는 Dump나 Winqual의 덤프를 보다보면 생각보다 Virtual PC에서 발생하는 경우가 많습니다. 혹시나 Virtual PC여부를 확인하고자 하신다면 한번 사용해보세요. 또한 VMware의 경우도 거의 비슷한 방법으로 확인이 가능합니다.

[생각] Heap Corruption

Heap Corruption은 가장 잡기 힘든 Exception중 하나 입니다. 그 이유는 Corruption이 발생한 위치에 문제가 있는 경우 보다는 다른 곳에서 Heap Overrun이 발생하고 그 후 Overrun된 Heap를 사용하고나 해제 할때 또는 Overrun된 위치에 할당된 영역을 재사용 하거나 해제 하려 할 때 주로 발생합니다. Heap Corruption을 만났을때 저의 경우는 몇가지 과정을 거치면서 분석을 합니다.

  1. 현재 Call Stack의 코드에서 발생한 문제인가 ?? 
    - 이런 경우라면 바로 답이 나오기 때문에 굉장히 쉽습니다. 
  2. 만약 현재 Call Stack 상의 코드 문제가 아니라면 같은 상황이 재현이 가능한가 ?? 
    - 만약 재현이 가능하다면 gflag를 이용해 Enabled Page Heap 을 설정한후 디버깅하는 것이 좋습니다. 이렇게 설정하고 나면 실재로 Overrun이 발생하는 부분을 대부분 잡을 수 있습니다.  ( 물론 아닌 경우가 더 많습니다. ) 그리고 !heap Extension을 이용해서 Corruption이 발생한 Heap의 할당,해제 위치를 추적할 수 있습니다. (  _DPH_BLOCK_INFORMATION 을 이용함  )
  3. 현재 Call Stack의 코드가 문제가 없고 재현도 불가능하다면 ??
    - 이런 경우라면 !heap Extension을 이용하여 Corruption이 발생한 Heap 주변에 위치한 Segment Link를 하나 하나 뒤져가며 그 안에 들어 있는 값을 보면서 유추해 봐야합니다. 시간이 많이 필요하게 되지요.

이렇게해서 찾지 못한다면 GG를 선언하고 조용히 다음기회를 노려야합니다. 가끔 생각지도 않은 부분을 수정했는데 해결되는 경우가 있습니다. 그리고 String 관련 CRT Function이나 Windows API를 살펴보는 것도 도움이 됩니다.  ( 주로 이런 부분에서 많이 발생합니다. )

Application의 Heap Corruption Exception은 Kernel Mode의  IRQL_NOT_LESS_OR_EQUAL ( 0×0A BugCheck , 0×0A Bugcheck은 IRQL에 변화를 준 녀석을 찾는게 가장 중요하다고 생각함.) 과 비슷해서 현재 발생한 Stack 보다 다른 Thread또는 반복적으로 발생하는 코드들이 원인되는 경우가 많습니다. 그런 이유에서 코드 하나 하나 꼼꼼히 살펴보는 것이 해결에 지름길 입니다.

[windbg] Disassembling Routines and Searching for Instructions

http://blogs.msdn.com/debuggingtoolbox/archive/2007/07/20/windbg-script-disassembling-routines-and-searching-for-patterns.aspx

 멋지군요 ㅎㅎ

 Script를 잘만들면 좋을 텐데 ㅜ.ㅜ