; 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