10,21 → 10,21 |
|
; diamond, 2006 |
sys_debug_services: |
cmp eax, 9 |
ja @f |
jmp dword [sys_debug_services_table+eax*4] |
@@: ret |
cmp eax, 9 |
ja @f |
jmp dword [sys_debug_services_table+eax*4] |
@@: ret |
sys_debug_services_table: |
dd debug_set_event_data |
dd debug_getcontext |
dd debug_setcontext |
dd debug_detach |
dd debug_suspend |
dd debug_resume |
dd debug_read_process_memory |
dd debug_write_process_memory |
dd debug_terminate |
dd debug_set_drx |
dd debug_set_event_data |
dd debug_getcontext |
dd debug_setcontext |
dd debug_detach |
dd debug_suspend |
dd debug_resume |
dd debug_read_process_memory |
dd debug_write_process_memory |
dd debug_terminate |
dd debug_set_drx |
|
debug_set_event_data: |
; in: ebx = pointer |
31,7 → 31,7 |
; destroys eax |
mov eax, [current_slot] |
mov [eax+APPDATA.dbg_event_mem], ebx |
ret |
ret |
|
get_debuggee_slot: |
; in: ebx=PID |
38,43 → 38,43 |
; out: CF=1 if error |
; CF=0 and eax=slot*0x20 if ok |
; out: interrupts disabled |
cli |
mov eax, ebx |
call pid_to_slot |
test eax, eax |
jz .ret_bad |
shl eax, 5 |
push ebx |
cli |
mov eax, ebx |
call pid_to_slot |
test eax, eax |
jz .ret_bad |
shl eax, 5 |
push ebx |
mov ebx, [CURRENT_TASK] |
cmp [SLOT_BASE+eax*8+APPDATA.debugger_slot], ebx |
pop ebx |
jnz .ret_bad |
; clc ; automatically |
ret |
pop ebx |
jnz .ret_bad |
; clc ; automatically |
ret |
.ret_bad: |
stc |
ret |
stc |
ret |
|
debug_detach: |
; in: ebx=pid |
; destroys eax,ebx |
call get_debuggee_slot |
jc .ret |
call get_debuggee_slot |
jc .ret |
and dword [eax*8+SLOT_BASE+APPDATA.debugger_slot], 0 |
call do_resume |
call do_resume |
.ret: |
sti |
ret |
sti |
ret |
|
debug_terminate: |
; in: ebx=pid |
call get_debuggee_slot |
jc debug_detach.ret |
mov ecx, eax |
shr ecx, 5 |
push 2 |
pop ebx |
jmp sys_system |
call get_debuggee_slot |
jc debug_detach.ret |
mov ecx, eax |
shr ecx, 5 |
push 2 |
pop ebx |
jmp sys_system |
|
debug_suspend: |
; in: ebx=pid |
85,30 → 85,30 |
shl eax, 5 |
jz .ret |
mov bl, [CURRENT_TASK+eax+TASKDATA.state] ; process state |
test bl, bl |
jz .1 |
cmp bl, 5 |
jnz .ret |
mov bl, 2 |
test bl, bl |
jz .1 |
cmp bl, 5 |
jnz .ret |
mov bl, 2 |
.2: mov [CURRENT_TASK+eax+TASKDATA.state], bl |
.ret: |
sti |
ret |
sti |
ret |
.1: |
inc ebx |
jmp .2 |
inc ebx |
jmp .2 |
|
do_resume: |
mov bl, [CURRENT_TASK+eax+TASKDATA.state] |
cmp bl, 1 |
jz .1 |
cmp bl, 2 |
jnz .ret |
mov bl, 5 |
cmp bl, 1 |
jz .1 |
cmp bl, 2 |
jnz .ret |
mov bl, 5 |
.2: mov [CURRENT_TASK+eax+TASKDATA.state], bl |
.ret: ret |
.1: dec ebx |
jmp .2 |
.ret: ret |
.1: dec ebx |
jmp .2 |
|
debug_resume: |
; in: ebx=pid |
119,8 → 119,8 |
shl eax, 5 |
jz .ret |
call do_resume |
.ret: sti |
ret |
.ret: sti |
ret |
|
debug_getcontext: |
; in: |
128,16 → 128,16 |
; ecx=sizeof(CONTEXT) |
; edx->CONTEXT |
; destroys eax,ecx,edx,esi,edi |
cmp ecx, 28h |
jnz .ret |
push ebx |
mov ebx, edx |
call check_region |
pop ebx |
dec eax |
jnz .ret |
call get_debuggee_slot |
jc .ret |
cmp ecx, 28h |
jnz .ret |
push ebx |
mov ebx, edx |
call check_region |
pop ebx |
dec eax |
jnz .ret |
call get_debuggee_slot |
jc .ret |
mov eax, [eax*8+SLOT_BASE+APPDATA.pl0_stack] |
lea esi, [eax+RING0_STACK_SIZE] |
mov edi, edx |
147,30 → 147,30 |
; top of ring0 stack: ring3 stack ptr (ss+esp), iret data (cs+eip+eflags), pushad |
sub esi, 8+12+20h |
lodsd ;edi |
mov [edi+24h], eax |
mov [edi+24h], eax |
lodsd ;esi |
mov [edi+20h], eax |
mov [edi+20h], eax |
lodsd ; ebp |
mov [edi+1Ch], eax |
mov [edi+1Ch], eax |
lodsd ;esp |
lodsd ;ebx |
mov [edi+14h], eax |
mov [edi+14h], eax |
lodsd ;edx |
mov [edi+10h], eax |
mov [edi+10h], eax |
lodsd ;ecx |
mov [edi+0Ch], eax |
mov [edi+0Ch], eax |
lodsd ;eax |
mov [edi+8], eax |
mov [edi+8], eax |
lodsd ;eip |
mov [edi], eax |
mov [edi], eax |
lodsd ;cs |
lodsd ;eflags |
mov [edi+4], eax |
mov [edi+4], eax |
lodsd ;esp |
mov [edi+18h], eax |
mov [edi+18h], eax |
.ret: |
sti |
ret |
sti |
ret |
|
debug_setcontext: |
; in: |
178,16 → 178,16 |
; ecx=sizeof(CONTEXT) |
; edx->CONTEXT |
; destroys eax,ecx,edx,esi,edi |
cmp ecx, 28h |
jnz .ret |
push ebx |
mov ebx, edx |
call check_region |
pop ebx |
dec eax |
jnz .ret |
call get_debuggee_slot |
jc .stiret |
cmp ecx, 28h |
jnz .ret |
push ebx |
mov ebx, edx |
call check_region |
pop ebx |
dec eax |
jnz .ret |
call get_debuggee_slot |
jc .stiret |
mov eax, [eax*8+SLOT_BASE+APPDATA.pl0_stack] |
lea edi, [eax+RING0_STACK_SIZE] |
mov esi, edx |
194,104 → 194,104 |
.ring0: |
sub edi, 8+12+20h |
mov eax, [esi+24h] ;edi |
stosd |
stosd |
mov eax, [esi+20h] ;esi |
stosd |
stosd |
mov eax, [esi+1Ch] ;ebp |
stosd |
stosd |
scasd |
mov eax, [esi+14h] ;ebx |
stosd |
stosd |
mov eax, [esi+10h] ;edx |
stosd |
stosd |
mov eax, [esi+0Ch] ;ecx |
stosd |
stosd |
mov eax, [esi+8] ;eax |
stosd |
stosd |
mov eax, [esi] ;eip |
stosd |
scasd |
stosd |
scasd |
mov eax, [esi+4] ;eflags |
stosd |
stosd |
mov eax, [esi+18h] ;esp |
stosd |
stosd |
.stiret: |
sti |
sti |
.ret: |
ret |
ret |
|
debug_set_drx: |
call get_debuggee_slot |
jc .errret |
mov ebp, eax |
call get_debuggee_slot |
jc .errret |
mov ebp, eax |
lea eax, [eax*8+SLOT_BASE+APPDATA.dbg_regs] |
; [eax]=dr0, [eax+4]=dr1, [eax+8]=dr2, [eax+C]=dr3 |
; [eax+10]=dr7 |
cmp edx, OS_BASE |
jae .errret |
cmp cl, 3 |
ja .errret |
mov ebx, dr7 |
shr ebx, cl |
shr ebx, cl |
test ebx, 2 ; bit 1+2*index = G0..G3, global break enable |
jnz .errret2 |
test ch, ch |
jns .new |
cmp cl, 3 |
ja .errret |
mov ebx, dr7 |
shr ebx, cl |
shr ebx, cl |
test ebx, 2 ; bit 1+2*index = G0..G3, global break enable |
jnz .errret2 |
test ch, ch |
jns .new |
; clear breakpoint |
movzx ecx, cl |
add ecx, ecx |
and dword [eax+ecx*2], 0 ; clear DR<i> |
btr dword [eax+10h], ecx ; clear L<i> bit |
test byte [eax+10h], 55h |
jnz .okret |
movzx ecx, cl |
add ecx, ecx |
and dword [eax+ecx*2], 0 ; clear DR<i> |
btr dword [eax+10h], ecx ; clear L<i> bit |
test byte [eax+10h], 55h |
jnz .okret |
; imul eax, ebp, tss_step/32 |
; and byte [eax + tss_data + TSS._trap], not 1 |
and [ebp*8 + SLOT_BASE+APPDATA.dbg_state], not 1 |
.okret: |
and dword [esp+36], 0 |
sti |
ret |
and dword [esp+36], 0 |
sti |
ret |
.errret: |
sti |
mov dword [esp+36], 1 |
ret |
sti |
mov dword [esp+36], 1 |
ret |
.errret2: |
sti |
mov dword [esp+36], 2 |
ret |
sti |
mov dword [esp+36], 2 |
ret |
.new: |
; add new breakpoint |
; cl=index; ch=flags; edx=address |
test ch, 0xF0 |
jnz .errret |
mov bl, ch |
and bl, 3 |
cmp bl, 2 |
jz .errret |
mov bl, ch |
shr bl, 2 |
cmp bl, 2 |
jz .errret |
test dl, bl |
jnz .errret |
or byte [eax+10h+1], 3 ; set GE and LE flags |
movzx ebx, ch |
movzx ecx, cl |
add ecx, ecx |
bts dword [eax+10h], ecx ; set L<i> flag |
add ecx, ecx |
mov [eax+ecx], edx ; set DR<i> |
shl ebx, cl |
mov edx, 0xF |
shl edx, cl |
not edx |
and [eax+10h+2], dx |
or [eax+10h+2], bx ; set R/W and LEN fields |
test ch, 0xF0 |
jnz .errret |
mov bl, ch |
and bl, 3 |
cmp bl, 2 |
jz .errret |
mov bl, ch |
shr bl, 2 |
cmp bl, 2 |
jz .errret |
test dl, bl |
jnz .errret |
or byte [eax+10h+1], 3 ; set GE and LE flags |
movzx ebx, ch |
movzx ecx, cl |
add ecx, ecx |
bts dword [eax+10h], ecx ; set L<i> flag |
add ecx, ecx |
mov [eax+ecx], edx ; set DR<i> |
shl ebx, cl |
mov edx, 0xF |
shl edx, cl |
not edx |
and [eax+10h+2], dx |
or [eax+10h+2], bx ; set R/W and LEN fields |
; imul eax, ebp, tss_step/32 |
; or byte [eax + tss_data + TSS._trap], 1 |
or [ebp*8 + SLOT_BASE+APPDATA.dbg_state], 1 |
jmp .okret |
jmp .okret |
|
debug_read_process_memory: |
; in: |
301,23 → 301,23 |
; edx=address in debuggee |
; out: [esp+36]=sizeof(read) |
; destroys all |
push ebx |
mov ebx, esi |
call check_region |
pop ebx |
dec eax |
jnz .err |
call get_debuggee_slot |
jc .err |
shr eax, 5 |
mov ebx, esi |
call read_process_memory |
sti |
mov dword [esp+36], eax |
ret |
push ebx |
mov ebx, esi |
call check_region |
pop ebx |
dec eax |
jnz .err |
call get_debuggee_slot |
jc .err |
shr eax, 5 |
mov ebx, esi |
call read_process_memory |
sti |
mov dword [esp+36], eax |
ret |
.err: |
or dword [esp+36], -1 |
ret |
or dword [esp+36], -1 |
ret |
|
debug_write_process_memory: |
; in: |
327,20 → 327,20 |
; edx=address in debuggee |
; out: [esp+36]=sizeof(write) |
; destroys all |
push ebx |
mov ebx, esi |
call check_region |
pop ebx |
dec eax |
jnz debug_read_process_memory.err |
call get_debuggee_slot |
jc debug_read_process_memory.err |
shr eax, 5 |
mov ebx, esi |
call write_process_memory |
sti |
mov [esp+36], eax |
ret |
push ebx |
mov ebx, esi |
call check_region |
pop ebx |
dec eax |
jnz debug_read_process_memory.err |
call get_debuggee_slot |
jc debug_read_process_memory.err |
shr eax, 5 |
mov ebx, esi |
call write_process_memory |
sti |
mov [esp+36], eax |
ret |
|
debugger_notify: |
; in: eax=debugger slot |
349,127 → 349,68 |
; interrupts must be disabled! |
; destroys all general registers |
; interrupts remain disabled |
xchg ebp, eax |
mov edi, [timer_ticks] |
add edi, 500 ; 5 sec timeout |
xchg ebp, eax |
mov edi, [timer_ticks] |
add edi, 500 ; 5 sec timeout |
.1: |
mov eax, ebp |
shl eax, 8 |
mov eax, ebp |
shl eax, 8 |
mov edx, [SLOT_BASE+eax+APPDATA.dbg_event_mem] |
test edx, edx |
jz .ret |
test edx, edx |
jz .ret |
; read buffer header |
push ecx |
push eax |
push eax |
mov eax, ebp |
mov ebx, esp |
mov ecx, 8 |
call read_process_memory |
cmp eax, ecx |
jz @f |
add esp, 12 |
jmp .ret |
push ecx |
push eax |
push eax |
mov eax, ebp |
mov ebx, esp |
mov ecx, 8 |
call read_process_memory |
cmp eax, ecx |
jz @f |
add esp, 12 |
jmp .ret |
@@: |
cmp dword [ebx], 0 |
jg @f |
cmp dword [ebx], 0 |
jg @f |
.2: |
pop ecx |
pop ecx |
pop ecx |
pop ecx |
pop ecx |
pop ecx |
cmp dword [CURRENT_TASK], 1 |
jnz .notos |
cmp [timer_ticks], edi |
jae .ret |
jnz .notos |
cmp [timer_ticks], edi |
jae .ret |
.notos: |
sti |
call change_task |
cli |
jmp .1 |
sti |
call change_task |
cli |
jmp .1 |
@@: |
mov ecx, [ebx+8] |
add ecx, [ebx+4] |
cmp ecx, [ebx] |
ja .2 |
mov ecx, [ebx+8] |
add ecx, [ebx+4] |
cmp ecx, [ebx] |
ja .2 |
; advance buffer position |
push ecx |
mov ecx, 4 |
sub ebx, ecx |
mov eax, ebp |
add edx, ecx |
call write_process_memory |
pop eax |
push ecx |
mov ecx, 4 |
sub ebx, ecx |
mov eax, ebp |
add edx, ecx |
call write_process_memory |
pop eax |
; write message |
mov eax, ebp |
add edx, ecx |
add edx, [ebx+8] |
add ebx, 20 |
pop ecx |
pop ecx |
pop ecx |
call write_process_memory |
mov eax, ebp |
add edx, ecx |
add edx, [ebx+8] |
add ebx, 20 |
pop ecx |
pop ecx |
pop ecx |
call write_process_memory |
; new debug event |
mov eax, ebp |
shl eax, 8 |
mov eax, ebp |
shl eax, 8 |
or byte [SLOT_BASE+eax+APPDATA.event_mask+1], 1 ; set flag 100h |
.ret: |
ret |
|
debug_exc: |
test byte [esp+8+2], 2 |
jnz v86_debug_exc |
; int 1 = #DB |
save_ring3_context |
cld |
mov ax, app_data ;os_data |
mov ds, ax |
mov es, ax |
mov eax, dr6 |
push eax |
xor eax, eax |
mov dr6, eax |
; test if debugging |
cli |
mov eax, [current_slot] |
mov eax, [eax+APPDATA.debugger_slot] |
test eax, eax |
jnz .debug |
sti |
; not debuggee => say error and terminate |
add esp, 0x20+4 |
mov [error_interrupt], 1 |
call show_error_parameters |
mov edx, [TASK_BASE] |
mov byte [edx+TASKDATA.state], 4 |
jmp change_task |
.debug: |
; we are debugged process, notify debugger and suspend ourself |
; eax=debugger PID |
pop edx |
mov ebx, dr7 |
mov cl, not 1 |
.l1: |
test bl, 1 |
jnz @f |
and dl, cl |
@@: |
shr ebx, 2 |
add cl, cl |
inc ecx |
cmp cl, not 10h |
jnz .l1 |
push edx ; DR6 image |
mov ecx, [TASK_BASE] |
push dword [ecx+TASKDATA.pid] ; PID |
push 12 |
pop ecx |
push 3 ; 3 = debug exception |
call debugger_notify |
pop ecx |
pop ecx |
pop ecx |
mov edx, [TASK_BASE] |
mov byte [edx+TASKDATA.state], 1 ; suspended |
call change_task |
restore_ring3_context |
iretd |
ret |