mirror of
https://github.com/alliedmodders/amxmodx.git
synced 2024-12-25 06:15:37 +03:00
Experimental JIT fixes for linux crashing (no more xchg of esp)
This commit is contained in:
parent
98d3fb79d7
commit
85b7ac740b
Binary file not shown.
@ -10,7 +10,7 @@
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* 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
|
||||
* a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
|
@ -21,17 +21,26 @@
|
||||
; step.
|
||||
|
||||
; 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
|
||||
; 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
|
||||
; 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
|
||||
; (by Thiadmer Riemersma)
|
||||
;
|
||||
@ -65,7 +74,8 @@
|
||||
; 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.
|
||||
;
|
||||
;
|
||||
|
||||
; NOTE 6:
|
||||
; CALLING CONVENTIONS
|
||||
; (by Thiadmer Riemersma)
|
||||
;
|
||||
@ -77,9 +87,16 @@
|
||||
; a reserved word on the assembler, I had to choose a different name for the
|
||||
; macro, hence STDECL.)
|
||||
|
||||
|
||||
; 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.
|
||||
; 17 february 2005 by Thiadmer Riemersms
|
||||
; Addition of the BREAK opcode, removal of the older debugging opcode
|
||||
@ -165,15 +182,6 @@
|
||||
;
|
||||
%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.
|
||||
; You should set this to 0, only when you are sure that there are no range
|
||||
@ -186,32 +194,49 @@
|
||||
%define JIT 1
|
||||
%include "amxdefn.asm"
|
||||
|
||||
; GWMV:
|
||||
; Nasm can't do the next as equivalence statements, since the value of
|
||||
; esi is not determined at compile time
|
||||
%define stk [esi+32] ; define some aliases to registers that will
|
||||
%define alt [esi+28] ; be stored on the stack when the code is
|
||||
%define pri [esi+24] ; actually beeing executed
|
||||
%define code [esi+20]
|
||||
%define amx [esi+16]
|
||||
%define retval [esi+12]
|
||||
%define stp [esi+8]
|
||||
%define hea [esi+4]
|
||||
%define frm [esi] ; FRM is NOT stored in ebp, FRM+DAT is being held
|
||||
;Registers used for JIT during execution:
|
||||
; eax - pri
|
||||
; ebx - reloc frame
|
||||
; ecx - info params
|
||||
; edx - alt
|
||||
; esi - AMX stack
|
||||
; edi - DAT
|
||||
; ebp - scratch
|
||||
|
||||
;DA:
|
||||
; These are still stored in the stack, but the stack pointer
|
||||
; 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.
|
||||
|
||||
;
|
||||
; #define PUSH(v) ( stk-=sizeof(cell), *(cell *)(data+(int)stk)=v )
|
||||
;
|
||||
%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
|
||||
|
||||
;
|
||||
; #define POP(v) ( v=*(cell *)(data+(int)stk), stk+=sizeof(cell) )
|
||||
;
|
||||
%macro _POP 1
|
||||
pop dword %1
|
||||
mov %1, dword [esi]
|
||||
add esi, 4
|
||||
%endmacro
|
||||
|
||||
|
||||
@ -790,7 +815,7 @@ OP_LCTRL:
|
||||
jne lctrl_5
|
||||
GO_ON j_lctrl_4, lctrl_5, 8
|
||||
j_lctrl_4:
|
||||
mov eax,esp ; 4=STK
|
||||
mov eax,esi ; 4=STK
|
||||
sub eax,edi
|
||||
CHECKCODESIZE j_lctrl_4
|
||||
lctrl_5:
|
||||
@ -824,7 +849,7 @@ OP_SCTRL:
|
||||
j_sctrl_4:
|
||||
;mov esp,eax ; 4=STK
|
||||
;add esp,edi ; relocate stack
|
||||
lea esp,[eax+edi]
|
||||
lea esi,[eax+edi]
|
||||
CHECKCODESIZE j_sctrl_4
|
||||
sctrl_5:
|
||||
cmp eax,5
|
||||
@ -885,14 +910,16 @@ OP_PUSH_ALT:
|
||||
|
||||
OP_PUSH_R_PRI:
|
||||
;nop;
|
||||
putval j_push_r_pri+1
|
||||
putval j_push_r_pri+2
|
||||
GO_ON j_push_r_pri, OP_PUSH_C, 8
|
||||
|
||||
j_push_r_pri:
|
||||
push ecx
|
||||
mov ecx,12345678h
|
||||
j_push_loop:
|
||||
_PUSH eax
|
||||
loop j_push_loop
|
||||
pop ecx
|
||||
;dec ecx
|
||||
;jnz j_push_loop
|
||||
CHECKCODESIZE j_push_r_pri
|
||||
@ -900,30 +927,33 @@ OP_PUSH_R_PRI:
|
||||
;good
|
||||
OP_PUSH_C:
|
||||
;nop;
|
||||
putval j_push_c+1
|
||||
putval j_push_c_end-4
|
||||
GO_ON j_push_c, OP_PUSH, 8
|
||||
|
||||
j_push_c:
|
||||
_PUSH 12345678h
|
||||
j_push_c_end:
|
||||
CHECKCODESIZE j_push_c
|
||||
|
||||
OP_PUSH:
|
||||
;nop;
|
||||
putval j_push+2
|
||||
putval j_push_end-6
|
||||
GO_ON j_push, OP_PUSH_S, 8
|
||||
|
||||
j_push:
|
||||
_PUSH [edi+12345678h]
|
||||
_PUSHMEM [edi+12345678h]
|
||||
j_push_end:
|
||||
CHECKCODESIZE j_push
|
||||
|
||||
;good
|
||||
OP_PUSH_S:
|
||||
;nop;
|
||||
putval j_push_s+2
|
||||
putval j_push_s_end-6
|
||||
GO_ON j_push_s, OP_POP_PRI, 8
|
||||
|
||||
j_push_s:
|
||||
_PUSH [ebx+12345678h]
|
||||
_PUSHMEM [ebx+12345678h]
|
||||
j_push_s_end:
|
||||
CHECKCODESIZE j_push_s
|
||||
|
||||
OP_POP_PRI:
|
||||
@ -950,8 +980,8 @@ OP_STACK:
|
||||
GO_ON j_stack, OP_HEAP, 8
|
||||
|
||||
j_stack:
|
||||
mov edx,esp
|
||||
add esp,12345678h
|
||||
mov edx,esi
|
||||
add esi,12345678h
|
||||
sub edx,edi
|
||||
%ifdef DORUNTIMECHECKS
|
||||
call [chk_marginstack]
|
||||
@ -979,9 +1009,9 @@ OP_PROC:
|
||||
GO_ON j_proc, OP_RET
|
||||
|
||||
j_proc: ;[STK] = FRM, STK = STK - cell size, FRM = STK
|
||||
_PUSH frm ; push old frame (for RET/RETN)
|
||||
mov frm,esp ; get new frame
|
||||
mov ebx,esp ; already relocated
|
||||
_PUSHMEM frm ; push old frame (for RET/RETN)
|
||||
mov frm,esi ; get new frame
|
||||
mov ebx,esi ; already relocated
|
||||
sub frm,edi ; relocate frame
|
||||
CHECKCODESIZE j_proc
|
||||
|
||||
@ -991,6 +1021,7 @@ OP_RET:
|
||||
|
||||
j_ret:
|
||||
_POP ebx ; pop frame
|
||||
add esi,4 ; pop extra param
|
||||
mov frm,ebx
|
||||
add ebx,edi
|
||||
ret
|
||||
@ -1009,11 +1040,13 @@ OP_RETN:
|
||||
;good
|
||||
OP_CALL:
|
||||
;nop;
|
||||
RELOC 1
|
||||
RELOC j_call_e8-j_call+1
|
||||
GO_ON j_call, OP_CALL_I, 8
|
||||
|
||||
j_call:
|
||||
;call 12345678h ; tasm chokes on this out of a sudden
|
||||
_PUSH 0
|
||||
j_call_e8
|
||||
db 0e8h, 0, 0, 0, 0
|
||||
CHECKCODESIZE j_call
|
||||
|
||||
@ -1022,6 +1055,7 @@ OP_CALL_I:
|
||||
GO_ON j_call_i, OP_JUMP
|
||||
|
||||
j_call_i:
|
||||
_PUSH 0
|
||||
call eax
|
||||
CHECKCODESIZE j_call_i
|
||||
|
||||
@ -1172,24 +1206,30 @@ OP_SHL:
|
||||
;nop;
|
||||
GO_ON j_shl, OP_SHR
|
||||
j_shl:
|
||||
mov ecx,edx ; TODO: save ECX if used as special register
|
||||
push ecx
|
||||
mov ecx,edx
|
||||
shl eax,cl
|
||||
pop ecx
|
||||
CHECKCODESIZE j_shl
|
||||
|
||||
OP_SHR:
|
||||
;nop;
|
||||
GO_ON j_shr, OP_SSHR
|
||||
j_shr:
|
||||
mov ecx,edx ; TODO: save ECX if used as special register
|
||||
push ecx
|
||||
mov ecx,edx
|
||||
shr eax,cl
|
||||
pop ecx
|
||||
CHECKCODESIZE j_shr
|
||||
|
||||
OP_SSHR:
|
||||
;nop;
|
||||
GO_ON j_sshr, OP_SHL_C_PRI
|
||||
j_sshr:
|
||||
mov ecx,edx ; TODO: save ECX if used as special register
|
||||
push ecx
|
||||
mov ecx,edx
|
||||
sar eax,cl
|
||||
pop ecx
|
||||
CHECKCODESIZE j_sshr
|
||||
|
||||
OP_SHL_C_PRI:
|
||||
@ -1608,29 +1648,35 @@ OP_DEC_I:
|
||||
|
||||
OP_MOVS:
|
||||
;nop;
|
||||
putval j_movs+1
|
||||
putval j_movs+2
|
||||
GO_ON j_movs, OP_CMPS, 8
|
||||
j_movs:
|
||||
mov ecx,12345678h ;TODO: save ECX if used as special register
|
||||
push ecx
|
||||
mov ecx,12345678h
|
||||
call [jit_movs]
|
||||
pop ecx
|
||||
CHECKCODESIZE j_movs
|
||||
|
||||
OP_CMPS:
|
||||
;nop;
|
||||
putval j_cmps+1
|
||||
putval j_cmps+2
|
||||
GO_ON j_cmps, OP_FILL, 8
|
||||
j_cmps:
|
||||
mov ecx,12345678h ;TODO: save ECX if used as special register
|
||||
push ecx
|
||||
mov ecx,12345678h
|
||||
call [jit_cmps]
|
||||
pop ecx
|
||||
CHECKCODESIZE j_cmps
|
||||
|
||||
OP_FILL:
|
||||
;nop;
|
||||
putval j_fill+1
|
||||
putval j_fill+2
|
||||
GO_ON j_fill, OP_HALT, 8
|
||||
j_fill:
|
||||
push ecx
|
||||
mov ecx,12345678h ;TODO: save ECX if used as special register
|
||||
call [jit_fill]
|
||||
pop ecx
|
||||
CHECKCODESIZE j_fill
|
||||
|
||||
;good
|
||||
@ -1879,7 +1925,7 @@ _amx_exec_jit:
|
||||
push dword [eax+20]; store FRM
|
||||
|
||||
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 esi,[eax+16] ; get STK !!changed, now ECX free as counter!!
|
||||
mov ebx,[eax+20] ; get FRM
|
||||
@ -1887,13 +1933,13 @@ _amx_exec_jit:
|
||||
add ebx,edi ; relocate frame
|
||||
|
||||
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 ecx
|
||||
call ebp
|
||||
|
||||
return_to_caller:
|
||||
cmp dword retval,0
|
||||
@ -1906,15 +1952,17 @@ return_to_caller:
|
||||
jmp _return
|
||||
|
||||
_return_popstack:
|
||||
add esp,4 ; Correct ESP, because we just come from a
|
||||
; runtime error checking routine.
|
||||
mov esp,ecx ; get our old stack pointer
|
||||
_return:
|
||||
; store machine state
|
||||
mov ecx,esp ; get STK into ECX
|
||||
push ecx
|
||||
push ecx
|
||||
mov ebp,amx ; get amx into EBP
|
||||
mov ecx,esi ; get STK into ECX
|
||||
|
||||
sub ecx,edi ; correct STK
|
||||
mov [ebp+_stk],ecx ; store values in AMX structure: STK, ...
|
||||
pop ecx ; get orig value
|
||||
mov ecx,hea ; ... HEA, ...
|
||||
mov [ebp+_hea],ecx
|
||||
mov ecx,ebx ; ... and FRM
|
||||
@ -1924,8 +1972,8 @@ _return:
|
||||
mov [ebp+_alt],edx ; ... and ALT
|
||||
|
||||
; return
|
||||
pop ecx
|
||||
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
|
||||
|
||||
@ -1946,12 +1994,8 @@ err_stacklow:
|
||||
jmp _return_popstack
|
||||
|
||||
_CHKMARGIN_STACK: ; some run-time check routines
|
||||
cmp esp,stp
|
||||
lea ebp,[esp-STACKRESERVE]
|
||||
cmp esi,stp
|
||||
jg err_stacklow
|
||||
sub ebp,edi
|
||||
cmp hea,ebp
|
||||
jg err_stack
|
||||
ret
|
||||
|
||||
err_heaplow:
|
||||
@ -1959,7 +2003,7 @@ err_heaplow:
|
||||
jmp _return_popstack
|
||||
|
||||
_CHKMARGIN_HEAP:
|
||||
cmp esp,stp
|
||||
cmp esi,stp
|
||||
jg err_stacklow
|
||||
cmp dword hea,0
|
||||
jl err_heaplow
|
||||
@ -1975,7 +2019,7 @@ _VERIFYADDRESS_eax: ; used in load.i, store.i & lidx
|
||||
cmp eax,hea
|
||||
jb veax1
|
||||
lea ebp,[eax+edi]
|
||||
cmp ebp,esp
|
||||
cmp ebp,esi
|
||||
jb err_memaccess
|
||||
veax1:
|
||||
ret
|
||||
@ -1986,7 +2030,7 @@ _VERIFYADDRESS_edx: ; used in load.i, store.i & lidx
|
||||
cmp edx,hea
|
||||
jb vedx1
|
||||
lea ebp,[edx+edi]
|
||||
cmp ebp,esp
|
||||
cmp ebp,esi
|
||||
jb err_memaccess
|
||||
vedx1:
|
||||
ret
|
||||
@ -2018,15 +2062,15 @@ JIT_OP_SDIV:
|
||||
|
||||
JIT_OP_RETN:
|
||||
_POP ebx ; pop frame
|
||||
_POP ecx ; get return address
|
||||
add esi,4 ; get rid of the extra parameter from call
|
||||
|
||||
mov frm,ebx
|
||||
_POP ebp
|
||||
|
||||
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
|
||||
@ -2092,34 +2136,33 @@ err_divide:
|
||||
jmp _return_popstack
|
||||
|
||||
JIT_OP_SYSREQ:
|
||||
mov ecx,esp ; get STK into ECX
|
||||
push ecx
|
||||
push esi
|
||||
mov ebp,amx ; get amx into EBP
|
||||
|
||||
sub ecx,edi ; correct STK
|
||||
sub esi,edi ; correct STK
|
||||
mov alt,edx ; save ALT
|
||||
|
||||
mov [ebp+_stk],ecx ; store values in AMX structure: STK,
|
||||
mov ecx,hea ; HEA,
|
||||
mov [ebp+_stk],esi ; store values in AMX structure: STK,
|
||||
mov esi,hea ; HEA,
|
||||
mov ebx,frm ; and FRM
|
||||
mov [ebp+_hea],ecx
|
||||
mov [ebp+_hea],esi
|
||||
mov [ebp+_frm],ebx
|
||||
|
||||
lea ebx,pri ; 3rd param: addr. of retval
|
||||
lea ecx,[esp+4] ; 4th param: parameter array
|
||||
|
||||
xchg esp,esi ; switch to caller stack
|
||||
|
||||
push ecx
|
||||
;Our original esi is still pushed!
|
||||
push ebx
|
||||
push eax ; 2nd param: function number
|
||||
push ebp ; 1st param: amx
|
||||
call [ebp+_callback]
|
||||
_DROPARGS 16 ; remove args from stack
|
||||
|
||||
xchg esp,esi ; switch back to AMX stack
|
||||
_DROPARGS 12 ; remove args from stack
|
||||
|
||||
pop esi
|
||||
pop ecx
|
||||
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 edx,alt ; restore ALT
|
||||
mov ebx,frm ; restore FRM
|
||||
@ -2128,25 +2171,25 @@ JIT_OP_SYSREQ:
|
||||
|
||||
|
||||
JIT_OP_SYSREQ_D: ; (TR)
|
||||
mov ecx,esp ; get STK into ECX
|
||||
push ecx
|
||||
push esi
|
||||
mov ebp,amx ; get amx into EBP
|
||||
|
||||
sub ecx,edi ; correct STK
|
||||
sub esi,edi ; correct STK
|
||||
mov alt,edx ; save ALT
|
||||
|
||||
mov [ebp+_stk],ecx ; store values in AMX structure: STK,
|
||||
mov ecx,hea ; HEA,
|
||||
mov [ebp+_stk],esi ; store values in AMX structure: STK,
|
||||
mov esi,hea ; HEA,
|
||||
mov eax,frm ; and FRM
|
||||
mov [ebp+_hea],ecx
|
||||
mov [ebp+_hea],esi
|
||||
mov [ebp+_frm],eax ; eax & ecx are invalid by now
|
||||
|
||||
lea edx,[esp+4] ; 2nd param: parameter array
|
||||
xchg esp,esi ; switch to caller stack
|
||||
push edx
|
||||
;esi is still pushed!
|
||||
push ebp ; 1st param: amx
|
||||
call ebx ; direct call
|
||||
_DROPARGS 8 ; remove args from stack
|
||||
xchg esp,esi ; switch back to AMX stack
|
||||
|
||||
pop ecx
|
||||
mov ebp,amx ; get amx into EBP
|
||||
cmp dword [ebp+_error],AMX_ERR_NONE
|
||||
jne _return_popstack; return error code, if any
|
||||
@ -2160,25 +2203,27 @@ JIT_OP_SYSREQ_D: ; (TR)
|
||||
|
||||
JIT_OP_BREAK:
|
||||
%ifdef DEBUGSUPPORT
|
||||
mov ecx,esp ; get STK into ECX
|
||||
push ecx
|
||||
push esi
|
||||
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+_alt],edx ; ALT,
|
||||
mov [ebp+_stk],ecx ; STK,
|
||||
mov ecx,hea ; HEA,
|
||||
mov [ebp+_stk],esi ; STK,
|
||||
mov esi,hea ; HEA,
|
||||
mov ebx,frm ; and FRM
|
||||
mov [ebp+_hea],ecx
|
||||
mov [ebp+_hea],esi
|
||||
mov [ebp+_frm],ebx ; EBX & ECX are invalid by now
|
||||
;??? 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
|
||||
call [ebp+_debug]
|
||||
_DROPARGS 4 ; remove args from stack
|
||||
xchg esp,esi ; switch back to AMX stack
|
||||
|
||||
pop esi
|
||||
pop ecx
|
||||
cmp eax,AMX_ERR_NONE
|
||||
jne _return_popstack; return error code, if any
|
||||
|
||||
@ -2194,6 +2239,7 @@ JIT_OP_BREAK:
|
||||
|
||||
JIT_OP_SWITCH:
|
||||
pop ebp ; pop return address = table address
|
||||
push ecx
|
||||
mov ecx,[ebp] ; ECX = number of records
|
||||
lea ebp,[ebp+ecx*8+8] ; set pointer _after_ LAST case
|
||||
;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
|
||||
loop op_switch_loop ; check next case, or fall through
|
||||
op_switch_jump:
|
||||
pop ecx
|
||||
%ifndef FORCERELOCATABLE
|
||||
jmp [ebp-4] ; jump to the case instructions
|
||||
%else
|
||||
|
@ -2895,6 +2895,22 @@ static cell AMX_NATIVE_CALL find_plugin_byfile(AMX *amx, cell *params)
|
||||
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[] = {
|
||||
{ "client_cmd", client_cmd },
|
||||
{ "client_print", client_print },
|
||||
@ -3062,5 +3078,6 @@ AMX_NATIVE_INFO amxmod_Natives[] = {
|
||||
{ "plugin_flags", plugin_flags},
|
||||
{ "lang_phrase", lang_phrase},
|
||||
{ "mkdir", amx_mkdir},
|
||||
{ "int3", int3},
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user