From 2f1de39dd3b22030237158862103756945c364a3 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Thu, 16 Sep 2004 20:08:11 +0000 Subject: [PATCH] JIT's OP_CALL now supports a debug hook --- amxmodx/JIT/jits.asm | 87 ++++++++++++++++++++++++++++++++++++++----- amxmodx/JIT/jits.o | Bin 26526 -> 27214 bytes 2 files changed, 78 insertions(+), 9 deletions(-) diff --git a/amxmodx/JIT/jits.asm b/amxmodx/JIT/jits.asm index 673502f8..dd1aa4e1 100755 --- a/amxmodx/JIT/jits.asm +++ b/amxmodx/JIT/jits.asm @@ -42,6 +42,12 @@ ; Revision History ;------------------ +; 16 September 2004 by David "BAILOPAN" Anderson +; Implemented a compile time toggleable debug hook on OP_CALL and OP_RET. +; NOTE: JIT has not had debug hooks since 1999. +; 8 September 2004 by David "BAILOPAN" Anderson +; Changed OP_LINE call to be compile-time toggle-able between compiling +; line ops or not. ; 29 June 2004 by G.W.M. Vissers ; Translated the thing into NASM. The actual generation of the code is ; put into the data section because the code modifies itself whereas the @@ -147,8 +153,14 @@ _dbgcode: resd 1 _dbgaddr: resd 1 _dbgparam: resd 1 _dbgname: resd 1 -_usertags: resd 4 ; 4 = AMX_USERNUM (#define'd in amx.h) -_userdata: resd 4 ; 4 = AMX_USERNUM (#define'd in amx.h) +_usertags1: resd 1 ; 4 = AMX_USERNUM (#define'd in amx.h) +_usertags2: resd 1 ; 4 = AMX_USERNUM (#define'd in amx.h) +_usertags3: resd 1 ; 4 = AMX_USERNUM (#define'd in amx.h) +_usertags4: resd 1 ; 4 = AMX_USERNUM (#define'd in amx.h) +_userdata1: resd 1 ; 4 = AMX_USERNUM (#define'd in amx.h) +_userdata2: resd 1 ; 4 = AMX_USERNUM (#define'd in amx.h) +_userdata3: resd 1 ; 4 = AMX_USERNUM (#define'd in amx.h) +_userdata4: resd 1 ; 4 = AMX_USERNUM (#define'd in amx.h) _error: resd 1 _pri: resd 1 _alt: resd 1 @@ -1049,13 +1061,64 @@ OP_RETN: ;good OP_CALL: ;nop; - RELOC 1 - GO_ON j_call, OP_CALL_I, 8 + ;save registers + push eax + push ebp + ;get .amx flags + mov ebp,[amxhead] + mov eax,[ebp+_h_flags] + ;check to see if the flag has line ops + and eax,AMX_FLAG_DEBUG + cmp eax,AMX_FLAG_DEBUG + ;restore registers + pop ebp + pop eax + ;if so, skip down to debug compiler + jmp _go_jit_debug - j_call: - ;call 12345678h ; tasm chokes on this out of a sudden - db 0e8h, 0, 0, 0, 0 - CHECKCODESIZE j_call +_go_jit_nodebug: + RELOC 1 + GO_ON j_call_nodebug, _j_call_go_on, 8 + j_call_nodebug: + call 12345678h + CHECKCODESIZE j_call_nodebug + +_j_call_go_on: + jmp _opcall_end + +_go_jit_debug: + ;thanks to Julien "dJeyL" Laurent for code relocation explanation + RELOC _go_jit_reloc-j_call+1 + GO_ON j_call, OP_CALL_I, 8 + j_call: + ; save some registers + push ebp + push eax + push edx + ; get AMX + mov ebp,amx + ; get debug call pointer + mov eax,[ebp+_userdata2] + ; check to see if it's valid + mov edx, dword 0 + cmp eax,edx + je _go_jit_skip_call + xchg esp,esi ;switch to caller stack + push 2 ;param mode=2, push + push ebp ;param amx + call eax ;indirect call + add esp, 8 ;restore stack + xchg esp,esi ;return to AMX stack + mov ebp,amx ;restore AMX [necessary?] + _go_jit_skip_call: + ;restore original registers + pop edx + pop eax + pop ebp + _go_jit_reloc: + call 12345678h + CHECKCODESIZE j_call +_opcall_end: OP_CALL_I: ;nop; @@ -2223,7 +2286,6 @@ JIT_OP_LINE: pop eax jmp ecx ; jump back - JIT_OP_SWITCH: pop ebp ; pop return address = table address mov ecx,[ebp] ; ECX = number of records @@ -2241,6 +2303,12 @@ JIT_OP_SWITCH: jmp ebp %endif +JIT_DEBUG: + push eax + pop eax + ret + + ; The caller of asm_runJIT() can determine the maximum size of the compiled ; code by multiplying the result of this function by the number of opcodes in @@ -2288,6 +2356,7 @@ jit_sysreq DD JIT_OP_SYSREQ jit_sysreq_d DD JIT_OP_SYSREQ_D jit_line DD JIT_OP_LINE jit_switch DD JIT_OP_SWITCH +jit_debug DD JIT_DEBUG ; ; The table for the browser/relocator function. diff --git a/amxmodx/JIT/jits.o b/amxmodx/JIT/jits.o index 1ea925ccf0073bcb2c06198fcb4aa8e765882af9..8b1a6bb616f7a4e5b2975e019e8191ae6ac211bc 100755 GIT binary patch literal 27214 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 CPi;8> literal 26526 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