;
; GRDB
;
; Copyright(c) LADsoft
;
; David Lindauer, camille@bluegrass.net
;
;
; swift.asm
;
; function: swift (relatively) tracing to find the end of a procedure
;
	.model small
	.code
	.386

include eexec.inc

traceon	db	0	;is swift tracing enabled
int3trace db	0	;are we in the middle of a full-speed run to int3
image	db	0	;image at place int 3 is found
oldcs	dw	0	;position of int 3
oldip	dw	0
oldsp	dw	0	;save so we can detect int 3 that we didn't
oldss	dw	0	; put there during swift trace...

	public	swiftrace,traceon,untrace
	assume	ds:nothing, es:dgroup
untrace	proc
	test	[int3trace],1	;
	jz	nounload2	;
	push	ax		; registers picked because this used in
	mov	es,[oldcs]	; break interrupt too!!!!
	mov	bp,[oldip]
	mov	al,[image]	;
	mov	es:[bp],al	;
	mov	[int3trace],0	;
	pop	ax
nounload2:
	mov	[traceon],0
	ret
untrace	endp
swiftrace PROC
	test	[traceon],0ffh
	jz	notrace
	add	sp,2		; bump past ret
	pusha			; get user CS:IP
	mov	bp,sp
	push	fs
	push	es
	push	dgroup
	pop	es
	mov	fs,[bp + 16 + 2]
	mov	bx,[bp + 16]	; unload int 3 call again
	test	[int3trace],1	;
	jz	nounload	;
	mov	fs,[oldcs]
	mov	bx,[oldip]
	cmp	sp,[oldsp]	; this is a hack in case we run into an int 3
	jnz	noupdate	; during a subroutine run
	mov	ax,ss
	cmp	ax,[oldss]
	jnz	noupdate
	mov	[bp+16],bx	; point back where int 3 was
noupdate:
	mov	al,[image]	;
	mov	fs:[bx],al	;
	mov	[int3trace],0	;
nounload:
	mov	al,fs:[bx]
	cmp	al,0cch
	jz	found3
	
	call	WadePrefix	; wade through prefixes
	cmp	al,9dh		; ehcek for popf
	jnz	notpopf
	or	word ptr [bp + 4 + 2 + 16],100h	; make sure popf will trace
	jmp	stx
notpopf:
	cmp	al,0c2h		; now check for rets
	jz	retx
	cmp	al,0c3h
	jz	retx
	cmp	al,0cbh
	jz	retx
	cmp	al,0cah
	jz	retx
	cmp	al,0cfh		; we WILL check iret here
	jnz	tracex		; none of those, check for call/int/string stepping
	or	word ptr [bp + 4 + 6 + 16],100h ; be sure iret will trace
retx:
       	mov	[traceon],0	; else kill trace flag and trace past ret/iret
tracex:	
	or	word ptr [bp + 4+16],100h	; set trace flag
	call	callcheck	; see if call.int
	jz	setcall		; yep, set a break there
	call    cmpstring	; see if is string instruction
	mov	ax,1		; else one byte
	jz	short setcall	; yes, set an int 3 instruction in place
stx:
	pop	es
	pop	fs
	popa
	iret
setcall:        
	add	bx,ax
	mov	al,fs:[bx]
	mov	[image],al
	mov	byte ptr fs:[bx],0cch
	inc	[int3trace]
	mov	[oldcs],fs
	mov	[oldip],bx
	mov	[oldss],ss
	mov	[oldsp],sp
	and	word ptr [bp + 4 +16],0FEFFH	; no trace here
	jmp	stx
found3:
	mov	[traceon],0
	pop	es
	pop	fs
	popa
notrace:
	ret
swiftrace ENDP
	end