Experimental JIT fixes for linux crashing (no more xchg of esp)

This commit is contained in:
David Anderson 2005-08-16 23:09:55 +00:00
parent 98d3fb79d7
commit 85b7ac740b
4 changed files with 168 additions and 104 deletions

Binary file not shown.

View File

@ -10,7 +10,7 @@
* including commercial applications, and to alter it and redistribute it * including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions: * freely, subject to the following restrictions:
* *
* 1. The origin of this software must not be misrepresented; you must not * 1. The origin of this software must not be misreprfesented; you must not
* claim that you wrote the original software. If you use this software in * claim that you wrote the original software. If you use this software in
* a product, an acknowledgment in the product documentation would be * a product, an acknowledgment in the product documentation would be
* appreciated but is not required. * appreciated but is not required.

View File

@ -21,17 +21,26 @@
; step. ; step.
; NOTE 3: ; NOTE 3:
; During execution of the compiled code with amx_exec_jit() the x86 processor's
; stack is switched into the data section of the abstract machine. This means
; that there should always be enough memory left between HEA and STK to provide
; stack space for occurring interrupts! (see the STACKRESERVE variable)
; NOTE 4:
; Although the Pawn compiler doesn't generate the LCTRL, SCTRL and CALL.I ; Although the Pawn compiler doesn't generate the LCTRL, SCTRL and CALL.I
; instructions, I have to tell that they don't work as expected in a JIT ; instructions, I have to tell that they don't work as expected in a JIT
; compiled program, because there is no easy way of transforming AMX code ; compiled program, because there is no easy way of transforming AMX code
; addresses and JIT translated ones. This might be fixed in a future version. ; addresses and JIT translated ones. This might be fixed in a future version.
; NOTE 4:
; Stack Pointer issues (by David Anderson)
; The JIT was changed recently so it no longer uses ESP as a general purpose
; register (GRP), because it can conflict with threading/signal systems which
; rely on the stack pointer being in-tact to find thread-ids. My fix for this
; was to keep esp safe, but save the stack pointer in 'ecx'. As such, ecx is no
; longer the CIP or scratch register, it is the save point for pieces of the AMX
; structure on the x86 stack.
; This means that the optimization of the JIT has changed, as every amx stack
; push call now takes two operations instead of one (same for pop), and pushing
; addresses is 4 instructions instead of 1.
; As of this moment I don't see a better way around it, but the sacrifice for
; having pthread-safe code was deemed to be necessary.
; NOTE 5:
; NX ("No eXecute") and XD (eXecution Denied) bits ; NX ("No eXecute") and XD (eXecution Denied) bits
; (by Thiadmer Riemersma) ; (by Thiadmer Riemersma)
; ;
@ -65,7 +74,8 @@
; segment: the JIT-compiler patches P-code parameters into its own code segment ; segment: the JIT-compiler patches P-code parameters into its own code segment
; during compilation. This is handled in the support code for amx_InitJIT. ; during compilation. This is handled in the support code for amx_InitJIT.
; ;
;
; NOTE 6:
; CALLING CONVENTIONS ; CALLING CONVENTIONS
; (by Thiadmer Riemersma) ; (by Thiadmer Riemersma)
; ;
@ -77,9 +87,16 @@
; a reserved word on the assembler, I had to choose a different name for the ; a reserved word on the assembler, I had to choose a different name for the
; macro, hence STDECL.) ; macro, hence STDECL.)
; Revision History ; Revision History
; ---------------- ; ----------------
; 26 july 2005 by David "BAILOPAN" Anderson ; 16 august 2005 by David "BAILOPAN" Anderson (DA)
; Changed JIT to not swap stack pointer during execution. This
; is playing with fire, especially with pthreads and signals on linux,
; where the stack pointer is used to find the current thread id. If
; the stack pointer is altered during a thread/signal switch/interrupt
; unexpected behaviour can occur (crashes).
; 26 july 2005 by David "BAILOPAN" Anderson (DA)
; Fixed a bug where zero casetbl entries would crash the JIT. ; Fixed a bug where zero casetbl entries would crash the JIT.
; 17 february 2005 by Thiadmer Riemersms ; 17 february 2005 by Thiadmer Riemersms
; Addition of the BREAK opcode, removal of the older debugging opcode ; Addition of the BREAK opcode, removal of the older debugging opcode
@ -165,15 +182,6 @@
; ;
%define FORCERELOCATABLE %define FORCERELOCATABLE
;
; Determines how much memory should be reserved for occurring interrupts.
; (If my memory serves me right, DOS4/G(W) provides a stack of 512 bytes
; for interrupts that occur in real mode and are promoted to protected mode.)
; This value _MUST_ be greater than 64 (for AMX needs) and should be at least
; 128 (to serve interrupts).
;
%define STACKRESERVE 256
; ;
; This variable controls the generation of memory range checks at run-time. ; This variable controls the generation of memory range checks at run-time.
; You should set this to 0, only when you are sure that there are no range ; You should set this to 0, only when you are sure that there are no range
@ -186,32 +194,49 @@
%define JIT 1 %define JIT 1
%include "amxdefn.asm" %include "amxdefn.asm"
; GWMV: ;Registers used for JIT during execution:
; Nasm can't do the next as equivalence statements, since the value of ; eax - pri
; esi is not determined at compile time ; ebx - reloc frame
%define stk [esi+32] ; define some aliases to registers that will ; ecx - info params
%define alt [esi+28] ; be stored on the stack when the code is ; edx - alt
%define pri [esi+24] ; actually beeing executed ; esi - AMX stack
%define code [esi+20] ; edi - DAT
%define amx [esi+16] ; ebp - scratch
%define retval [esi+12]
%define stp [esi+8] ;DA:
%define hea [esi+4] ; These are still stored in the stack, but the stack pointer
%define frm [esi] ; FRM is NOT stored in ebp, FRM+DAT is being held ; holding them is now kept in ecx.
%define stk [ecx+32] ; define some aliases to registers that will
%define alt [ecx+28] ; be stored on the stack when the code is
%define pri [ecx+24] ; actually beeing executed
%define code [ecx+20]
%define amx [ecx+16]
%define retval [ecx+12]
%define stp [ecx+8]
%define hea [ecx+4]
%define frm [ecx] ; FRM is NOT stored in ebp, FRM+DAT is being held
; in ebx instead. ; in ebx instead.
; ;
; #define PUSH(v) ( stk-=sizeof(cell), *(cell *)(data+(int)stk)=v ) ; #define PUSH(v) ( stk-=sizeof(cell), *(cell *)(data+(int)stk)=v )
; ;
%macro _PUSH 1 %macro _PUSH 1
push dword %1 sub esi, 4
mov dword [esi], %1
%endmacro
%macro _PUSHMEM 1
sub esi, 4
mov ebp, dword %1
mov dword [esi], ebp
%endmacro %endmacro
; ;
; #define POP(v) ( v=*(cell *)(data+(int)stk), stk+=sizeof(cell) ) ; #define POP(v) ( v=*(cell *)(data+(int)stk), stk+=sizeof(cell) )
; ;
%macro _POP 1 %macro _POP 1
pop dword %1 mov %1, dword [esi]
add esi, 4
%endmacro %endmacro
@ -790,7 +815,7 @@ OP_LCTRL:
jne lctrl_5 jne lctrl_5
GO_ON j_lctrl_4, lctrl_5, 8 GO_ON j_lctrl_4, lctrl_5, 8
j_lctrl_4: j_lctrl_4:
mov eax,esp ; 4=STK mov eax,esi ; 4=STK
sub eax,edi sub eax,edi
CHECKCODESIZE j_lctrl_4 CHECKCODESIZE j_lctrl_4
lctrl_5: lctrl_5:
@ -824,7 +849,7 @@ OP_SCTRL:
j_sctrl_4: j_sctrl_4:
;mov esp,eax ; 4=STK ;mov esp,eax ; 4=STK
;add esp,edi ; relocate stack ;add esp,edi ; relocate stack
lea esp,[eax+edi] lea esi,[eax+edi]
CHECKCODESIZE j_sctrl_4 CHECKCODESIZE j_sctrl_4
sctrl_5: sctrl_5:
cmp eax,5 cmp eax,5
@ -885,14 +910,16 @@ OP_PUSH_ALT:
OP_PUSH_R_PRI: OP_PUSH_R_PRI:
;nop; ;nop;
putval j_push_r_pri+1 putval j_push_r_pri+2
GO_ON j_push_r_pri, OP_PUSH_C, 8 GO_ON j_push_r_pri, OP_PUSH_C, 8
j_push_r_pri: j_push_r_pri:
push ecx
mov ecx,12345678h mov ecx,12345678h
j_push_loop: j_push_loop:
_PUSH eax _PUSH eax
loop j_push_loop loop j_push_loop
pop ecx
;dec ecx ;dec ecx
;jnz j_push_loop ;jnz j_push_loop
CHECKCODESIZE j_push_r_pri CHECKCODESIZE j_push_r_pri
@ -900,30 +927,33 @@ OP_PUSH_R_PRI:
;good ;good
OP_PUSH_C: OP_PUSH_C:
;nop; ;nop;
putval j_push_c+1 putval j_push_c_end-4
GO_ON j_push_c, OP_PUSH, 8 GO_ON j_push_c, OP_PUSH, 8
j_push_c: j_push_c:
_PUSH 12345678h _PUSH 12345678h
j_push_c_end:
CHECKCODESIZE j_push_c CHECKCODESIZE j_push_c
OP_PUSH: OP_PUSH:
;nop; ;nop;
putval j_push+2 putval j_push_end-6
GO_ON j_push, OP_PUSH_S, 8 GO_ON j_push, OP_PUSH_S, 8
j_push: j_push:
_PUSH [edi+12345678h] _PUSHMEM [edi+12345678h]
j_push_end:
CHECKCODESIZE j_push CHECKCODESIZE j_push
;good ;good
OP_PUSH_S: OP_PUSH_S:
;nop; ;nop;
putval j_push_s+2 putval j_push_s_end-6
GO_ON j_push_s, OP_POP_PRI, 8 GO_ON j_push_s, OP_POP_PRI, 8
j_push_s: j_push_s:
_PUSH [ebx+12345678h] _PUSHMEM [ebx+12345678h]
j_push_s_end:
CHECKCODESIZE j_push_s CHECKCODESIZE j_push_s
OP_POP_PRI: OP_POP_PRI:
@ -950,8 +980,8 @@ OP_STACK:
GO_ON j_stack, OP_HEAP, 8 GO_ON j_stack, OP_HEAP, 8
j_stack: j_stack:
mov edx,esp mov edx,esi
add esp,12345678h add esi,12345678h
sub edx,edi sub edx,edi
%ifdef DORUNTIMECHECKS %ifdef DORUNTIMECHECKS
call [chk_marginstack] call [chk_marginstack]
@ -979,9 +1009,9 @@ OP_PROC:
GO_ON j_proc, OP_RET GO_ON j_proc, OP_RET
j_proc: ;[STK] = FRM, STK = STK - cell size, FRM = STK j_proc: ;[STK] = FRM, STK = STK - cell size, FRM = STK
_PUSH frm ; push old frame (for RET/RETN) _PUSHMEM frm ; push old frame (for RET/RETN)
mov frm,esp ; get new frame mov frm,esi ; get new frame
mov ebx,esp ; already relocated mov ebx,esi ; already relocated
sub frm,edi ; relocate frame sub frm,edi ; relocate frame
CHECKCODESIZE j_proc CHECKCODESIZE j_proc
@ -991,6 +1021,7 @@ OP_RET:
j_ret: j_ret:
_POP ebx ; pop frame _POP ebx ; pop frame
add esi,4 ; pop extra param
mov frm,ebx mov frm,ebx
add ebx,edi add ebx,edi
ret ret
@ -1009,11 +1040,13 @@ OP_RETN:
;good ;good
OP_CALL: OP_CALL:
;nop; ;nop;
RELOC 1 RELOC j_call_e8-j_call+1
GO_ON j_call, OP_CALL_I, 8 GO_ON j_call, OP_CALL_I, 8
j_call: j_call:
;call 12345678h ; tasm chokes on this out of a sudden ;call 12345678h ; tasm chokes on this out of a sudden
_PUSH 0
j_call_e8
db 0e8h, 0, 0, 0, 0 db 0e8h, 0, 0, 0, 0
CHECKCODESIZE j_call CHECKCODESIZE j_call
@ -1022,6 +1055,7 @@ OP_CALL_I:
GO_ON j_call_i, OP_JUMP GO_ON j_call_i, OP_JUMP
j_call_i: j_call_i:
_PUSH 0
call eax call eax
CHECKCODESIZE j_call_i CHECKCODESIZE j_call_i
@ -1172,24 +1206,30 @@ OP_SHL:
;nop; ;nop;
GO_ON j_shl, OP_SHR GO_ON j_shl, OP_SHR
j_shl: j_shl:
mov ecx,edx ; TODO: save ECX if used as special register push ecx
mov ecx,edx
shl eax,cl shl eax,cl
pop ecx
CHECKCODESIZE j_shl CHECKCODESIZE j_shl
OP_SHR: OP_SHR:
;nop; ;nop;
GO_ON j_shr, OP_SSHR GO_ON j_shr, OP_SSHR
j_shr: j_shr:
mov ecx,edx ; TODO: save ECX if used as special register push ecx
mov ecx,edx
shr eax,cl shr eax,cl
pop ecx
CHECKCODESIZE j_shr CHECKCODESIZE j_shr
OP_SSHR: OP_SSHR:
;nop; ;nop;
GO_ON j_sshr, OP_SHL_C_PRI GO_ON j_sshr, OP_SHL_C_PRI
j_sshr: j_sshr:
mov ecx,edx ; TODO: save ECX if used as special register push ecx
mov ecx,edx
sar eax,cl sar eax,cl
pop ecx
CHECKCODESIZE j_sshr CHECKCODESIZE j_sshr
OP_SHL_C_PRI: OP_SHL_C_PRI:
@ -1608,29 +1648,35 @@ OP_DEC_I:
OP_MOVS: OP_MOVS:
;nop; ;nop;
putval j_movs+1 putval j_movs+2
GO_ON j_movs, OP_CMPS, 8 GO_ON j_movs, OP_CMPS, 8
j_movs: j_movs:
mov ecx,12345678h ;TODO: save ECX if used as special register push ecx
mov ecx,12345678h
call [jit_movs] call [jit_movs]
pop ecx
CHECKCODESIZE j_movs CHECKCODESIZE j_movs
OP_CMPS: OP_CMPS:
;nop; ;nop;
putval j_cmps+1 putval j_cmps+2
GO_ON j_cmps, OP_FILL, 8 GO_ON j_cmps, OP_FILL, 8
j_cmps: j_cmps:
mov ecx,12345678h ;TODO: save ECX if used as special register push ecx
mov ecx,12345678h
call [jit_cmps] call [jit_cmps]
pop ecx
CHECKCODESIZE j_cmps CHECKCODESIZE j_cmps
OP_FILL: OP_FILL:
;nop; ;nop;
putval j_fill+1 putval j_fill+2
GO_ON j_fill, OP_HALT, 8 GO_ON j_fill, OP_HALT, 8
j_fill: j_fill:
push ecx
mov ecx,12345678h ;TODO: save ECX if used as special register mov ecx,12345678h ;TODO: save ECX if used as special register
call [jit_fill] call [jit_fill]
pop ecx
CHECKCODESIZE j_fill CHECKCODESIZE j_fill
;good ;good
@ -1879,7 +1925,7 @@ _amx_exec_jit:
push dword [eax+20]; store FRM push dword [eax+20]; store FRM
mov edx,[eax+4] ; get ALT mov edx,[eax+4] ; get ALT
mov ecx,[eax+8] ; get CIP mov ebp,[eax+8] ; get CIP
mov edi,[eax+12] ; get pointer to data segment mov edi,[eax+12] ; get pointer to data segment
mov esi,[eax+16] ; get STK !!changed, now ECX free as counter!! mov esi,[eax+16] ; get STK !!changed, now ECX free as counter!!
mov ebx,[eax+20] ; get FRM mov ebx,[eax+20] ; get FRM
@ -1887,13 +1933,13 @@ _amx_exec_jit:
add ebx,edi ; relocate frame add ebx,edi ; relocate frame
add esi,edi ; ESP will contain DAT+STK add esi,edi ; ESP will contain DAT+STK
xchg esp,esi ; switch to AMX stack
add stp,edi ; make STP absolute address for run-time checks add [esp+8],edi ; make STP absolute address for run-time checks
_POP ebp ; AMX pseudo-return address, ignored _POP ecx ; AMX pseudo-return address, ignored
mov ecx,esp ; copy stack pointer
; Call compiled code via CALL NEAR <address> ; Call compiled code via CALL NEAR <address>
call ecx call ebp
return_to_caller: return_to_caller:
cmp dword retval,0 cmp dword retval,0
@ -1906,15 +1952,17 @@ return_to_caller:
jmp _return jmp _return
_return_popstack: _return_popstack:
add esp,4 ; Correct ESP, because we just come from a mov esp,ecx ; get our old stack pointer
; runtime error checking routine.
_return: _return:
; store machine state ; store machine state
mov ecx,esp ; get STK into ECX push ecx
push ecx
mov ebp,amx ; get amx into EBP mov ebp,amx ; get amx into EBP
mov ecx,esi ; get STK into ECX
sub ecx,edi ; correct STK sub ecx,edi ; correct STK
mov [ebp+_stk],ecx ; store values in AMX structure: STK, ... mov [ebp+_stk],ecx ; store values in AMX structure: STK, ...
pop ecx ; get orig value
mov ecx,hea ; ... HEA, ... mov ecx,hea ; ... HEA, ...
mov [ebp+_hea],ecx mov [ebp+_hea],ecx
mov ecx,ebx ; ... and FRM mov ecx,ebx ; ... and FRM
@ -1924,8 +1972,8 @@ _return:
mov [ebp+_alt],edx ; ... and ALT mov [ebp+_alt],edx ; ... and ALT
; return ; return
pop ecx
sub stp,edi ; make STP relative to DAT again sub stp,edi ; make STP relative to DAT again
xchg esp,esi ; switch back to caller's stack
add esp,4*9 ; remove temporary data add esp,4*9 ; remove temporary data
@ -1946,12 +1994,8 @@ err_stacklow:
jmp _return_popstack jmp _return_popstack
_CHKMARGIN_STACK: ; some run-time check routines _CHKMARGIN_STACK: ; some run-time check routines
cmp esp,stp cmp esi,stp
lea ebp,[esp-STACKRESERVE]
jg err_stacklow jg err_stacklow
sub ebp,edi
cmp hea,ebp
jg err_stack
ret ret
err_heaplow: err_heaplow:
@ -1959,7 +2003,7 @@ err_heaplow:
jmp _return_popstack jmp _return_popstack
_CHKMARGIN_HEAP: _CHKMARGIN_HEAP:
cmp esp,stp cmp esi,stp
jg err_stacklow jg err_stacklow
cmp dword hea,0 cmp dword hea,0
jl err_heaplow jl err_heaplow
@ -1975,7 +2019,7 @@ _VERIFYADDRESS_eax: ; used in load.i, store.i & lidx
cmp eax,hea cmp eax,hea
jb veax1 jb veax1
lea ebp,[eax+edi] lea ebp,[eax+edi]
cmp ebp,esp cmp ebp,esi
jb err_memaccess jb err_memaccess
veax1: veax1:
ret ret
@ -1986,7 +2030,7 @@ _VERIFYADDRESS_edx: ; used in load.i, store.i & lidx
cmp edx,hea cmp edx,hea
jb vedx1 jb vedx1
lea ebp,[edx+edi] lea ebp,[edx+edi]
cmp ebp,esp cmp ebp,esi
jb err_memaccess jb err_memaccess
vedx1: vedx1:
ret ret
@ -2018,15 +2062,15 @@ JIT_OP_SDIV:
JIT_OP_RETN: JIT_OP_RETN:
_POP ebx ; pop frame _POP ebx ; pop frame
_POP ecx ; get return address add esi,4 ; get rid of the extra parameter from call
mov frm,ebx mov frm,ebx
_POP ebp _POP ebp
add ebx,edi add ebx,edi
add esp,ebp ; remove data from stack add esi,ebp ; remove data from stack
jmp ecx ret
JIT_OP_MOVS: ;length of block to copy is already in ECX JIT_OP_MOVS: ;length of block to copy is already in ECX
@ -2092,34 +2136,33 @@ err_divide:
jmp _return_popstack jmp _return_popstack
JIT_OP_SYSREQ: JIT_OP_SYSREQ:
mov ecx,esp ; get STK into ECX push ecx
push esi
mov ebp,amx ; get amx into EBP mov ebp,amx ; get amx into EBP
sub ecx,edi ; correct STK sub esi,edi ; correct STK
mov alt,edx ; save ALT mov alt,edx ; save ALT
mov [ebp+_stk],ecx ; store values in AMX structure: STK, mov [ebp+_stk],esi ; store values in AMX structure: STK,
mov ecx,hea ; HEA, mov esi,hea ; HEA,
mov ebx,frm ; and FRM mov ebx,frm ; and FRM
mov [ebp+_hea],ecx mov [ebp+_hea],esi
mov [ebp+_frm],ebx mov [ebp+_frm],ebx
lea ebx,pri ; 3rd param: addr. of retval lea ebx,pri ; 3rd param: addr. of retval
lea ecx,[esp+4] ; 4th param: parameter array
xchg esp,esi ; switch to caller stack ;Our original esi is still pushed!
push ecx
push ebx push ebx
push eax ; 2nd param: function number push eax ; 2nd param: function number
push ebp ; 1st param: amx push ebp ; 1st param: amx
call [ebp+_callback] call [ebp+_callback]
_DROPARGS 16 ; remove args from stack _DROPARGS 12 ; remove args from stack
xchg esp,esi ; switch back to AMX stack pop esi
pop ecx
cmp eax,AMX_ERR_NONE cmp eax,AMX_ERR_NONE
jne _return_popstack; return error code, if any jne _return_popstack
.continue:
mov eax,pri ; get retval into eax (PRI) mov eax,pri ; get retval into eax (PRI)
mov edx,alt ; restore ALT mov edx,alt ; restore ALT
mov ebx,frm ; restore FRM mov ebx,frm ; restore FRM
@ -2128,25 +2171,25 @@ JIT_OP_SYSREQ:
JIT_OP_SYSREQ_D: ; (TR) JIT_OP_SYSREQ_D: ; (TR)
mov ecx,esp ; get STK into ECX push ecx
push esi
mov ebp,amx ; get amx into EBP mov ebp,amx ; get amx into EBP
sub ecx,edi ; correct STK sub esi,edi ; correct STK
mov alt,edx ; save ALT mov alt,edx ; save ALT
mov [ebp+_stk],ecx ; store values in AMX structure: STK, mov [ebp+_stk],esi ; store values in AMX structure: STK,
mov ecx,hea ; HEA, mov esi,hea ; HEA,
mov eax,frm ; and FRM mov eax,frm ; and FRM
mov [ebp+_hea],ecx mov [ebp+_hea],esi
mov [ebp+_frm],eax ; eax & ecx are invalid by now mov [ebp+_frm],eax ; eax & ecx are invalid by now
lea edx,[esp+4] ; 2nd param: parameter array ;esi is still pushed!
xchg esp,esi ; switch to caller stack
push edx
push ebp ; 1st param: amx push ebp ; 1st param: amx
call ebx ; direct call call ebx ; direct call
_DROPARGS 8 ; remove args from stack _DROPARGS 8 ; remove args from stack
xchg esp,esi ; switch back to AMX stack
pop ecx
mov ebp,amx ; get amx into EBP mov ebp,amx ; get amx into EBP
cmp dword [ebp+_error],AMX_ERR_NONE cmp dword [ebp+_error],AMX_ERR_NONE
jne _return_popstack; return error code, if any jne _return_popstack; return error code, if any
@ -2160,25 +2203,27 @@ JIT_OP_SYSREQ_D: ; (TR)
JIT_OP_BREAK: JIT_OP_BREAK:
%ifdef DEBUGSUPPORT %ifdef DEBUGSUPPORT
mov ecx,esp ; get STK into ECX push ecx
push esi
mov ebp,amx ; get amx into EBP mov ebp,amx ; get amx into EBP
sub ecx,edi ; correct STK sub esi,edi ; correct STK
mov [ebp+_pri],eax ; store values in AMX structure: PRI, mov [ebp+_pri],eax ; store values in AMX structure: PRI,
mov [ebp+_alt],edx ; ALT, mov [ebp+_alt],edx ; ALT,
mov [ebp+_stk],ecx ; STK, mov [ebp+_stk],esi ; STK,
mov ecx,hea ; HEA, mov esi,hea ; HEA,
mov ebx,frm ; and FRM mov ebx,frm ; and FRM
mov [ebp+_hea],ecx mov [ebp+_hea],esi
mov [ebp+_frm],ebx ; EBX & ECX are invalid by now mov [ebp+_frm],ebx ; EBX & ECX are invalid by now
;??? storing CIP is not very useful, because the code changed (during JIT compile) ;??? storing CIP is not very useful, because the code changed (during JIT compile)
xchg esp,esi ; switch to caller stack
push ebp ; 1st param: amx push ebp ; 1st param: amx
call [ebp+_debug] call [ebp+_debug]
_DROPARGS 4 ; remove args from stack _DROPARGS 4 ; remove args from stack
xchg esp,esi ; switch back to AMX stack
pop esi
pop ecx
cmp eax,AMX_ERR_NONE cmp eax,AMX_ERR_NONE
jne _return_popstack; return error code, if any jne _return_popstack; return error code, if any
@ -2194,6 +2239,7 @@ JIT_OP_BREAK:
JIT_OP_SWITCH: JIT_OP_SWITCH:
pop ebp ; pop return address = table address pop ebp ; pop return address = table address
push ecx
mov ecx,[ebp] ; ECX = number of records mov ecx,[ebp] ; ECX = number of records
lea ebp,[ebp+ecx*8+8] ; set pointer _after_ LAST case lea ebp,[ebp+ecx*8+8] ; set pointer _after_ LAST case
;if there are zero cases we should just skip this -- bail ;if there are zero cases we should just skip this -- bail
@ -2205,6 +2251,7 @@ JIT_OP_SWITCH:
sub ebp,8 ; position to preceding case sub ebp,8 ; position to preceding case
loop op_switch_loop ; check next case, or fall through loop op_switch_loop ; check next case, or fall through
op_switch_jump: op_switch_jump:
pop ecx
%ifndef FORCERELOCATABLE %ifndef FORCERELOCATABLE
jmp [ebp-4] ; jump to the case instructions jmp [ebp-4] ; jump to the case instructions
%else %else

View File

@ -2895,6 +2895,22 @@ static cell AMX_NATIVE_CALL find_plugin_byfile(AMX *amx, cell *params)
return -1; return -1;
} }
static cell AMX_NATIVE_CALL int3(AMX *amx, cell *params)
{
#ifdef DEBUG
#if defined WIN32
__asm
{
int 3;
};
#else
asm("int $3");
#endif //WIN32
#endif //DEBUG
return 0;
}
AMX_NATIVE_INFO amxmod_Natives[] = { AMX_NATIVE_INFO amxmod_Natives[] = {
{ "client_cmd", client_cmd }, { "client_cmd", client_cmd },
{ "client_print", client_print }, { "client_print", client_print },
@ -3062,5 +3078,6 @@ AMX_NATIVE_INFO amxmod_Natives[] = {
{ "plugin_flags", plugin_flags}, { "plugin_flags", plugin_flags},
{ "lang_phrase", lang_phrase}, { "lang_phrase", lang_phrase},
{ "mkdir", amx_mkdir}, { "mkdir", amx_mkdir},
{ "int3", int3},
{ NULL, NULL } { NULL, NULL }
}; };