mirror of
https://github.com/alliedmodders/amxmodx.git
synced 2024-12-26 06:45: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
|
* 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.
|
||||||
|
@ -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
|
||||||
|
@ -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 }
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user