Files
llamamod/notes/dev/mountain3-diag/cave.asm
T

286 lines
5.4 KiB
NASM

; Mountain 3 crash diagnostics (German groove.exe). nasm -f bin -DCAVE=.. -DDATA=.. -DFIX=0/1
bits 32
org CAVE
%define D(o) dword [DATA+o]
; DATA layout: 0 magic, 16 cnt_parent_ok, 20 cnt_stale_addr, 24 cnt_stale_pop, 28 cnt_free, 32 cnt_anom,
; 36 cnt_alloc, 40 stale ring idx, 44 all ring idx, 48 dummy, 52 last free ptr, 56 last alloc size, 60 tmp idx,
; 64 stale ring 32x32, 1088 anomaly record 64 bytes, 1152 dump 256 bytes (hdr-128..+128), 1408 all-ring 64x32 (2048)
; 3456 free history 64 x 16
entry_addr: jmp near push_addr
entry_pop: jmp near pop_var
entry_free: jmp near free_hook
entry_alloc: jmp near alloc_hook
push_addr:
mov eax,[esp+4]
mov ecx,[eax+0xc]
mov edx,[esp+8]
mov [DATA+60],edx
mov edx,0x11
call record_all
test ecx,ecx
jz .stale
cmp dword [ecx+0xec],0
jz .stale
inc D(16)
.ok:
mov edx,[ecx+0xf4]
mov ecx,[esp+8]
lea edx,[edx+ecx*4]
.push:
push edx
push eax
call 0x54bbd0
add esp,8
ret
.stale:
inc D(20)
mov edx,1
call record
call stale_info
call check_heap
%if FIX
mov edx,DATA+48
jmp .push
%else
test ecx,ecx
jnz .ok
mov edx,DATA+48
jmp .push
%endif
pop_var:
push esi
mov esi,[esp+8]
push esi
call 0x54bc00
add esp,4
mov ecx,[esi+0xc]
mov edx,[esp+0xc]
mov [DATA+60],edx
push eax
mov eax,esi
mov edx,0x12
call record_all
pop eax
test ecx,ecx
jz .stale
cmp dword [ecx+0xec],0
jz .stale
inc D(16)
.ok:
mov edx,[ecx+0xf4]
mov ecx,[esp+0xc]
lea edx,[edx+ecx*4]
.store:
pop esi
mov [edx],eax
ret
.stale:
inc D(24)
push eax
mov eax,esi
mov edx,2
call record
call stale_info
call check_heap
pop eax
%if FIX
mov edx,DATA+48
jmp .store
%else
test ecx,ecx
jnz .ok
mov edx,DATA+48
jmp .store
%endif
; record: eax strat, ecx parent, edx kind, [DATA+60] idx. Preserves eax, ecx.
record:
push esi
push edi
push ebx
mov esi,[DATA+40]
and esi,31
shl esi,5
lea edi,[DATA+64+esi]
jmp rec_common
record_all:
push esi
push edi
push ebx
mov esi,[DATA+44]
and esi,63
shl esi,5
lea edi,[DATA+1408+esi]
inc D(44)
dec D(40) ; compensated below
rec_common:
inc D(40)
mov [edi],eax
mov [edi+4],ecx
mov [edi+8],edx
mov ebx,[DATA+60]
mov [edi+12],ebx
mov ebx,[eax+0x18]
mov [edi+16],ebx
mov dword [edi+20],0
mov dword [edi+24],0
mov dword [edi+28],0
test ecx,ecx
jz .np
mov ebx,[ecx+0x18]
mov [edi+20],ebx
mov ebx,[ecx+0xf4]
mov [edi+24],ebx
mov ebx,[ecx+0xec]
mov [edi+28],ebx
.np:
pop ebx
pop edi
pop esi
ret
free_hook:
pushad
inc D(28)
mov eax,[esp+36]
mov [DATA+52],eax
mov esi,[DATA+28]
and esi,63
shl esi,4
mov [DATA+3456+esi],eax
mov ebx,[esp+32] ; caller
mov [DATA+3456+esi+4],ebx
mov ebx,[eax-4] ; size|used
mov [DATA+3456+esi+8],ebx
mov ebx,[eax-12] ; next
mov [DATA+3456+esi+12],ebx
call check_heap
popad
mov eax,[esp+4]
push esi
jmp 0x41ada5
alloc_hook:
pushad
inc D(36)
mov eax,[esp+36]
mov [DATA+56],eax
call check_heap
popad
mov ecx,[0x58499c]
jmp 0x41ae26
; walks the local heap; on the first inconsistency records it (code in anomaly+0)
check_heap:
pushad
mov esi,[0x58499c]
test esi,esi
jz .done
xor edi,edi
mov ecx,70000
.loop:
mov edx,1
cmp [esi+4],edi
jne .bad
mov edx,2
movzx eax,word [esi+10]
cmp eax,1
ja .bad
mov ebx,[esi]
test ebx,ebx
jz .done
mov edx,3
movzx eax,word [esi+8]
lea eax,[esi+eax*4+12]
cmp ebx,eax
jne .bad
mov edi,esi
mov esi,ebx
dec ecx
jnz .loop
.done:
popad
ret
.bad:
inc D(32)
cmp dword [DATA+32],1
jne .done
mov [DATA+1088],edx
mov [DATA+1092],esi
mov [DATA+1096],edi
mov eax,[esi]
mov [DATA+1100],eax
mov eax,[esi+4]
mov [DATA+1104],eax
mov eax,[esi+8]
mov [DATA+1108],eax
mov eax,[DATA+28]
mov [DATA+1112],eax
mov eax,[DATA+36]
mov [DATA+1116],eax
mov eax,[DATA+40]
mov [DATA+1120],eax
mov eax,[esp+32] ; return address of check_heap caller
mov [DATA+1124],eax
mov eax,[DATA+52]
mov [DATA+1128],eax
mov eax,[DATA+56]
mov [DATA+1132],eax
; dump 256 bytes from edi (previous header) if set, else esi-128
test edi,edi
jnz .src
lea edi,[esi-128]
.src:
mov esi,edi
lea edi,[DATA+1152]
mov ecx,64
rep movsd
jmp .done
; stale_info: ecx parent, [DATA+60] idx -> DATA+4480 + (n&31)*16: target, block hdr, size|used, value before
stale_info:
pushad
test ecx,ecx
jz .out
mov edi,[ecx+0xf4]
mov eax,[DATA+60]
lea edi,[edi+eax*4]
mov ebx,[DATA+40]
dec ebx
and ebx,31
shl ebx,4
lea ebx,[DATA+4480+ebx]
mov [ebx],edi
mov eax,[edi]
mov [ebx+12],eax
mov dword [ebx+4],0
mov dword [ebx+8],0
mov esi,[0x58499c]
mov ecx,70000
.l:
test esi,esi
jz .out
mov edx,[esi]
test edx,edx
jnz .h
movzx eax,word [esi+8]
lea edx,[esi+eax*4+12]
.h:
cmp edi,esi
jb .next
cmp edi,edx
jae .next
mov [ebx+4],esi
mov eax,[esi+8]
mov [ebx+8],eax
jmp .out
.next:
mov esi,[esi]
dec ecx
jnz .l
.out:
popad
ret