|
|
|
|
|
|
|
Windows内核调试
帖子发起人: skyworth 发起时间: 2008-06-22 00:46 上午 回复: 4
|
帖子排序:
|
|
|
|
2008-06-22, 00:46 上午
|
skyworth
注册: 2008-06-07
发 贴: 55
|
|
|
手工输入程序源代码:
#include
#include
#define VAR_WATCH() printf("nDividend=%d, nDivisor=%d, nResult=%d.\n", nDividend, nDivisor, nResult)
int main(int argc, char* argv[])
{
int nDividend = 22;
int nDivisor = 0;
int nResult = 100;
__try
{
printf("Before div in __try block:\n");
VAR_WATCH();
nResult = nDividend / nDivisor;
printf("After div in __try block:\n");
VAR_WATCH();
}
__except(printf("In __except block\n"),
VAR_WATCH(),
GetExceptionCode() == EXCEPTION_INT_DIVIDE_BY_ZERO
? (nDivisor = 1,
printf("Devide by zero exception detected.\n"),
VAR_WATCH(), EXCEPTION_CONTINUE_EXECUTION)
: EXCEPTION_CONTINUE_SEARCH
)
{
printf("In handler block\n");
}
getchar();
return 0;
}
仔细检查无误,保存为fault.c。
用命令行编译:cl fault.c /Zi
生成fault.exe
执行,输出:
Before div in __try block:
nDividend=22, nDivisor=0, nResult=100.
In __except block
nDividend=22, nDivisor=1, nResult=100.
Devide by zero exception detected.
nDividend=22, nDivisor=1, nResult=100.
In __except block
nDividend=22, nDivisor=1, nResult=100.
Devide by zero exception detected.
nDividend=22, nDivisor=1, nResult=100.
In __except block
nDividend=22, nDivisor=1, nResult=100.
Devide by zero exception detected.
nDividend=22, nDivisor=1, nResult=100.
In __except block
nDividend=22, nDivisor=1, nResult=100.
Devide by zero exception detected.
nDividend=22, nDivisor=1, nResult=100.
In __except block
nDividend=22, nDivisor=1, nResult=100.
Devide by zero exception detected.
nDividend=22, nDivisor=1, nResult=100.
..................................
怀疑是编译器优化的原因。
禁用优化,重新编译: cl fault.c /Od /Zi
重新执行,结果和上面一样。
|
|
|
IP 地址: 已记录
|
报告
|
|
|
|
2008-06-22, 00:46 上午
|
skyworth
注册: 2008-06-07
发 贴: 55
|
|
|
无奈,让编译器生成汇编源程序,如下。
; Listing generated by Microsoft (R) Optimizing Compiler Version 15.00.21022.08
TITLE C:\TSource\fault.c
.686P
.XMM
include listing.inc
.model flat
INCLUDELIB LIBCMT
INCLUDELIB OLDNAMES
_DATA SEGMENT
$SG78567 DB 'Before div in __try block:', 0aH, 00H
$SG78568 DB 'nDividend=%d, nDivisor=%d, nResult=%d.', 0aH, 00H
$SG78569 DB 'After div in __try block:', 0aH, 00H
ORG $+1
$SG78570 DB 'nDividend=%d, nDivisor=%d, nResult=%d.', 0aH, 00H
$SG78572 DB 'In __except block', 0aH, 00H
ORG $+1
$SG78573 DB 'nDividend=%d, nDivisor=%d, nResult=%d.', 0aH, 00H
$SG78574 DB 'Devide by zero exception detected.', 0aH, 00H
$SG78575 DB 'nDividend=%d, nDivisor=%d, nResult=%d.', 0aH, 00H
$SG78576 DB 'In handler block', 0aH, 00H
_DATA ENDS
PUBLIC _main
EXTRN _getchar:PROC
EXTRN _printf:PROC
EXTRN ___security_cookie:DWORD
EXTRN __except_handler4:PROC
xdata$x SEGMENT
__sehtable$_main DD 0fffffffeH
DD 00H
DD 0ffffffc4H
DD 00H
DD 0fffffffeH
DD FLAT:$LN7@main
DD FLAT:$LN8@main
; Function compile flags: /Odtp
; File c:\tsource\fault.c
xdata$x ENDS
_TEXT SEGMENT
tv85 = -44 ; size = 4
$T78597 = -40 ; size = 4
_nResult$ = -36 ; size = 4
_nDividend$ = -32 ; size = 4
_nDivisor$ = -28 ; size = 4
__$SEHRec$ = -24 ; size = 24
_argc$ = 8 ; size = 4
_argv$ = 12 ; size = 4
_main PROC
; 7 : {
push ebp
mov ebp, esp
push -2 ; fffffffeH
push OFFSET __sehtable$_main
push OFFSET __except_handler4
mov eax, DWORD PTR fs:0
push eax
add esp, -28 ; ffffffe4H
push ebx
push esi
push edi
mov eax, DWORD PTR ___security_cookie
xor DWORD PTR __$SEHRec$[ebp+16], eax
xor eax, ebp
push eax
lea eax, DWORD PTR __$SEHRec$[ebp+8]
mov DWORD PTR fs:0, eax
mov DWORD PTR __$SEHRec$[ebp], esp
; 8 : int nDividend = 22;
mov DWORD PTR _nDividend$[ebp], 22 ; 00000016H
; 9 : int nDivisor = 0;
mov DWORD PTR _nDivisor$[ebp], 0
; 10 : int nResult = 100;
mov DWORD PTR _nResult$[ebp], 100 ; 00000064H
; 11 :
; 12 : __try
mov DWORD PTR __$SEHRec$[ebp+20], 0
; 13 : {
; 14 : printf("Before div in __try block:\n");
push OFFSET $SG78567
call _printf
add esp, 4
; 15 : VAR_WATCH();
mov eax, DWORD PTR _nResult$[ebp]
push eax
mov ecx, DWORD PTR _nDivisor$[ebp]
push ecx
mov edx, DWORD PTR _nDividend$[ebp]
push edx
push OFFSET $SG78568
call _printf
add esp, 16 ; 00000010H
mov ecx, DWORD PTR _nDivisor$[ebp]
; 16 :
; 17 : nResult = nDividend / nDivisor;
mov eax, DWORD PTR _nDividend$[ebp]
cdq
idiv ecx
mov DWORD PTR _nResult$[ebp], eax
; 18 :
; 19 : printf("After div in __try block:\n");
push OFFSET $SG78569
call _printf
add esp, 4
; 20 : VAR_WATCH();
mov edx, DWORD PTR _nResult$[ebp]
push edx
mov eax, DWORD PTR _nDivisor$[ebp]
push eax
mov ecx, DWORD PTR _nDividend$[ebp]
push ecx
push OFFSET $SG78570
call _printf
add esp, 16 ; 00000010H
; 21 : }
mov DWORD PTR __$SEHRec$[ebp+20], -2 ; fffffffeH
jmp $LN10@main
$LN7@main:
$LN12@main:
; 22 : __except(printf("In __except block\n"),
; 23 : VAR_WATCH(),
; 24 : GetExceptionCode() == EXCEPTION_INT_DIVIDE_BY_ZERO
; 25 : ? (nDivisor = 1,
; 26 : printf("Devide by zero exception detected.\n"),
; 27 : VAR_WATCH(), EXCEPTION_CONTINUE_EXECUTION)
; 28 : : EXCEPTION_CONTINUE_SEARCH
; 29 : )
mov edx, DWORD PTR __$SEHRec$[ebp+4]
mov eax, DWORD PTR [edx]
mov ecx, DWORD PTR [eax]
mov DWORD PTR $T78597[ebp], ecx
push OFFSET $SG78572
call _printf
add esp, 4
mov edx, DWORD PTR _nResult$[ebp]
push edx
mov eax, DWORD PTR _nDivisor$[ebp]
push eax
mov ecx, DWORD PTR _nDividend$[ebp]
push ecx
push OFFSET $SG78573
call _printf
add esp, 16 ; 00000010H
cmp DWORD PTR $T78597[ebp], -1073741676 ; c0000094H
jne SHORT $LN4@main
mov DWORD PTR _nDivisor$[ebp], 1
push OFFSET $SG78574
call _printf
add esp, 4
mov edx, DWORD PTR _nResult$[ebp]
push edx
mov eax, DWORD PTR _nDivisor$[ebp]
push eax
mov ecx, DWORD PTR _nDividend$[ebp]
push ecx
push OFFSET $SG78575
call _printf
add esp, 16 ; 00000010H
mov DWORD PTR tv85[ebp], -1
jmp SHORT $LN5@main
$LN4@main:
mov DWORD PTR tv85[ebp], 0
$LN5@main:
mov eax, DWORD PTR tv85[ebp]
$LN9@main:
$LN11@main:
ret 0
$LN8@main:
mov esp, DWORD PTR __$SEHRec$[ebp]
; 30 : {
; 31 : printf("In handler block\n");
push OFFSET $SG78576
call _printf
add esp, 4
; 32 : }
mov DWORD PTR __$SEHRec$[ebp+20], -2 ; fffffffeH
$LN10@main:
; 33 :
; 34 : getchar();
call _getchar
; 35 :
; 36 : return 0;
xor eax, eax
$LN6@main:
; 37 : }
mov ecx, DWORD PTR __$SEHRec$[ebp+8]
mov DWORD PTR fs:0, ecx
pop ecx
pop edi
pop esi
pop ebx
mov esp, ebp
pop ebp
ret 0
_main ENDP
_TEXT ENDS
END
|
|
|
IP 地址: 已记录
|
报告
|
|
|
|
2008-06-22, 00:56 上午
|
skyworth
注册: 2008-06-07
发 贴: 55
|
|
|
观察汇编源程序 line 108
mov ecx, DWORD PTR _nDivisor$[ebp]
; 16 :
; 17 : nResult = nDividend / nDivisor;
mov eax, DWORD PTR _nDividend$[ebp]
cdq
idiv ecx
mov DWORD PTR _nResult$[ebp], eax
可以知道除数保存在寄存器ecx中。
观察汇编源程序 line 171
mov DWORD PTR _nDivisor$[ebp], 1
push OFFSET $SG78574
可以知道,在异常块中只是把内存中的nDivisor变量的值变成了1,而寄存器ecx的值不变。
再次执行fault.exe,用WinDBG attach到fault.exe,并单步执行,输出如下:
Microsoft (R) Windows Debugger Version 6.9.0003.113 X86
Copyright (c) Microsoft Corporation. All rights reserved.
*** wait with pending attach
Symbol search path is: srv*D:\SymbolsCache*http://msdl.microsoft.com/download/symbols
Executable search path is:
ModLoad: 00400000 00427000 C:\TSource\fault.exe
ModLoad: 7c930000 7ca00000 C:\WINDOWS\system32\ntdll.dll
ModLoad: 7c800000 7c92b000 C:\WINDOWS\system32\kernel32.dll
(be0.ab4): Break instruction exception - code 80000003 (first chance)
eax=7ffdc000 ebx=00000001 ecx=00000002 edx=00000003 esi=00000004 edi=00000005
eip=7c94a3e1 esp=0039ffcc ebp=0039fff4 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=0038 gs=0000 efl=00000246
ntdll!DbgBreakPoint:
7c94a3e1 cc int 3
0:001> kb
ChildEBP RetAddr Args to Child
0039ffc8 7c96fdd8 00000005 00000004 00000001 ntdll!DbgBreakPoint
0039fff4 00000000 00000000 00000000 00000000 ntdll!DbgUiRemoteBreakin+0x36
0:001> g
(be0.acc): Integer divide-by-zero - code c0000094 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00000016 ebx=7ffdc000 ecx=00000000 edx=00000000 esi=00000000 edi=00000000
eip=0040108c esp=0012ff3c ebp=0012ff78 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010206
*** WARNING: Unable to verify checksum for C:\TSource\fault.exe
fault!main+0x7c:
0040108c f7f9 idiv eax,ecx
0:000> p
eax=00000016 ebx=7ffdc000 ecx=0012fc70 edx=00000000 esi=00000000 edi=00000000
eip=7c958554 esp=0012fc54 ebp=0012ff78 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
ntdll!KiUserExceptionDispatcher+0x4:
7c958554 8b1c24 mov ebx,dword ptr [esp] ss:0023:0012fc54=0012fc5c
0:000>
eax=00000016 ebx=0012fc5c ecx=0012fc70 edx=00000000 esi=00000000 edi=00000000
eip=7c958557 esp=0012fc54 ebp=0012ff78 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
ntdll!KiUserExceptionDispatcher+0x7:
7c958557 51 push ecx
0:000>
eax=00000016 ebx=0012fc5c ecx=0012fc70 edx=00000000 esi=00000000 edi=00000000
eip=7c958558 esp=0012fc50 ebp=0012ff78 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
ntdll!KiUserExceptionDispatcher+0x8:
7c958558 53 push ebx
0:000>
eax=00000016 ebx=0012fc5c ecx=0012fc70 edx=00000000 esi=00000000 edi=00000000
eip=7c958559 esp=0012fc4c ebp=0012ff78 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
ntdll!KiUserExceptionDispatcher+0x9:
7c958559 e8d88f0000 call ntdll!RtlDispatchException (7c961536)
0:000>
eax=00000001 ebx=0012fc5c ecx=00000000 edx=ffffffc4 esi=00000000 edi=00000000
eip=7c95855e esp=0012fc54 ebp=0012ff78 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
ntdll!KiUserExceptionDispatcher+0xe:
7c95855e 0ac0 or al,al
0:000>
eax=00000001 ebx=0012fc5c ecx=00000000 edx=ffffffc4 esi=00000000 edi=00000000
eip=7c958560 esp=0012fc54 ebp=0012ff78 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
ntdll!KiUserExceptionDispatcher+0x10:
7c958560 740c je ntdll!KiUserExceptionDispatcher+0x1e (7c95856e) [br=0]
0:000>
eax=00000001 ebx=0012fc5c ecx=00000000 edx=ffffffc4 esi=00000000 edi=00000000
eip=7c958562 esp=0012fc54 ebp=0012ff78 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
ntdll!KiUserExceptionDispatcher+0x12:
7c958562 5b pop ebx
0:000>
eax=00000001 ebx=0012fc5c ecx=00000000 edx=ffffffc4 esi=00000000 edi=00000000
eip=7c958563 esp=0012fc58 ebp=0012ff78 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
ntdll!KiUserExceptionDispatcher+0x13:
7c958563 59 pop ecx
0:000>
eax=00000001 ebx=0012fc5c ecx=0012fc70 edx=ffffffc4 esi=00000000 edi=00000000
eip=7c958564 esp=0012fc5c ebp=0012ff78 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
ntdll!KiUserExceptionDispatcher+0x14:
7c958564 6a00 push 0
0:000>
eax=00000001 ebx=0012fc5c ecx=0012fc70 edx=ffffffc4 esi=00000000 edi=00000000
eip=7c958566 esp=0012fc58 ebp=0012ff78 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
ntdll!KiUserExceptionDispatcher+0x16:
7c958566 51 push ecx
0:000>
eax=00000001 ebx=0012fc5c ecx=0012fc70 edx=ffffffc4 esi=00000000 edi=00000000
eip=7c958567 esp=0012fc54 ebp=0012ff78 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
ntdll!KiUserExceptionDispatcher+0x17:
7c958567 e823e8ffff call ntdll!NtContinue (7c956d8f)
0:000>
(be0.acc): Integer divide-by-zero - code c0000094 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00000016 ebx=7ffdc000 ecx=00000000 edx=00000000 esi=00000000 edi=00000000
eip=0040108c esp=0012ff3c ebp=0012ff78 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010206
fault!main+0x7c:
0040108c f7f9 idiv eax,ecx
0:000> x fault!nDivisor
0:000> .detach
Detached
可以看出,异常处理后,会再次试图执行触发异常的指令。而此时ecx仍然为零,从而再次触发异常,如此往复,从而得到最开始的输出结果。
不知我的分析对否。现在正在想如何修正这个例子。
|
|
|
IP 地址: 已记录
|
报告
|
|
|
|
2008-06-22, 09:21 上午
|
格蠹老雷
注册: 2005-12-19
发 贴: 1,303
|
|
|
因为编译器(VC6,与VC7/VC8)的差异,产生的代码不一样,注意《软件调试》71页中部产生的汇编代码。
这个例子只是用来演示异常处理的过程和恢复执行的可能性。事实上,由于实际的异常情况大多很复杂,所以尝试恢复执行的难度也更大,主要是难以有通用的做法。
阅读24.4.1节的SehRaw示例,你可以知道如何绕过这个问题。
因为VC6轻便灵活,编译C/C++程序足够强大,所以建议你安装一个VC6环境,这样对于有DSW项目文件的示例就可以直接用VC6来编译。
|
|
|
IP 地址: 已记录
|
报告
|
|
|
|
2008-06-25, 22:35 下午
|
skyworth
注册: 2008-06-07
发 贴: 55
|
|
|
嗯,看过了书上的相关代码,的确是那样的。
谢谢你的建议^_^。
|
|
|
IP 地址: 已记录
|
报告
|
|
|
|
高端调试 » 软件调试 » Windows内核调试 » 关于《软件调试》 3.3.3 示例
|
|
|
|
|
|