mirror of
https://github.com/LuaJIT/LuaJIT.git
synced 2025-02-07 23:24:09 +00:00
Add support for WIN64 exception handling to external unwinder.
Modify unwinding to always return _ff or _c unwind type. Generate PE object .pdata/.xdata sections for x64 interpreter. Can drop r12-r15 saves in Windows/x64 interpreter now.
This commit is contained in:
parent
b3e3bad0ff
commit
c31ac26fb9
@ -90,6 +90,7 @@ typedef struct PEsymaux {
|
|||||||
#define PEOBJ_ARCH_TARGET 0x8664
|
#define PEOBJ_ARCH_TARGET 0x8664
|
||||||
#define PEOBJ_RELOC_REL32 0x04 /* MS: REL32, GNU: DISP32. */
|
#define PEOBJ_RELOC_REL32 0x04 /* MS: REL32, GNU: DISP32. */
|
||||||
#define PEOBJ_RELOC_DIR32 0x02
|
#define PEOBJ_RELOC_DIR32 0x02
|
||||||
|
#define PEOBJ_RELOC_ADDR32NB 0x03
|
||||||
#define PEOBJ_SYM_PREFIX ""
|
#define PEOBJ_SYM_PREFIX ""
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -98,7 +99,10 @@ enum {
|
|||||||
PEOBJ_SECT_ABS = -2,
|
PEOBJ_SECT_ABS = -2,
|
||||||
PEOBJ_SECT_UNDEF = -1,
|
PEOBJ_SECT_UNDEF = -1,
|
||||||
PEOBJ_SECT_TEXT,
|
PEOBJ_SECT_TEXT,
|
||||||
/* TODO: add .pdata/.xdata for x64. */
|
#if LJ_TARGET_X64
|
||||||
|
PEOBJ_SECT_PDATA,
|
||||||
|
PEOBJ_SECT_XDATA,
|
||||||
|
#endif
|
||||||
PEOBJ_SECT_RDATA,
|
PEOBJ_SECT_RDATA,
|
||||||
PEOBJ_SECT_RDATA_Z,
|
PEOBJ_SECT_RDATA_Z,
|
||||||
PEOBJ_NSECTIONS
|
PEOBJ_NSECTIONS
|
||||||
@ -196,6 +200,24 @@ void emit_peobj(BuildCtx *ctx)
|
|||||||
/* Flags: 60 = read+execute, 50 = align16, 20 = code. */
|
/* Flags: 60 = read+execute, 50 = align16, 20 = code. */
|
||||||
pesect[PEOBJ_SECT_TEXT].flags = 0x60500020;
|
pesect[PEOBJ_SECT_TEXT].flags = 0x60500020;
|
||||||
|
|
||||||
|
#if LJ_TARGET_X64
|
||||||
|
memcpy(pesect[PEOBJ_SECT_PDATA].name, ".pdata", sizeof(".pdata")-1);
|
||||||
|
pesect[PEOBJ_SECT_PDATA].ofs = sofs;
|
||||||
|
sofs += (pesect[PEOBJ_SECT_PDATA].size = 3*4);
|
||||||
|
pesect[PEOBJ_SECT_PDATA].relocofs = sofs;
|
||||||
|
sofs += (pesect[PEOBJ_SECT_PDATA].nreloc = 3) * PEOBJ_RELOC_SIZE;
|
||||||
|
/* Flags: 40 = read, 30 = align4, 40 = initialized data. */
|
||||||
|
pesect[PEOBJ_SECT_PDATA].flags = 0x40300040;
|
||||||
|
|
||||||
|
memcpy(pesect[PEOBJ_SECT_XDATA].name, ".xdata", sizeof(".xdata")-1);
|
||||||
|
pesect[PEOBJ_SECT_XDATA].ofs = sofs;
|
||||||
|
sofs += (pesect[PEOBJ_SECT_XDATA].size = 8*2+4); /* See below. */
|
||||||
|
pesect[PEOBJ_SECT_XDATA].relocofs = sofs;
|
||||||
|
sofs += (pesect[PEOBJ_SECT_XDATA].nreloc = 1) * PEOBJ_RELOC_SIZE;
|
||||||
|
/* Flags: 40 = read, 30 = align4, 40 = initialized data. */
|
||||||
|
pesect[PEOBJ_SECT_XDATA].flags = 0x40300040;
|
||||||
|
#endif
|
||||||
|
|
||||||
memcpy(pesect[PEOBJ_SECT_RDATA].name, ".rdata", sizeof(".rdata")-1);
|
memcpy(pesect[PEOBJ_SECT_RDATA].name, ".rdata", sizeof(".rdata")-1);
|
||||||
pesect[PEOBJ_SECT_RDATA].ofs = sofs;
|
pesect[PEOBJ_SECT_RDATA].ofs = sofs;
|
||||||
sofs += (pesect[PEOBJ_SECT_RDATA].size = ctx->npc*sizeof(uint16_t));
|
sofs += (pesect[PEOBJ_SECT_RDATA].size = ctx->npc*sizeof(uint16_t));
|
||||||
@ -228,6 +250,9 @@ void emit_peobj(BuildCtx *ctx)
|
|||||||
#if !LJ_HASJIT
|
#if !LJ_HASJIT
|
||||||
pehdr.nsyms -= 7;
|
pehdr.nsyms -= 7;
|
||||||
#endif
|
#endif
|
||||||
|
#if LJ_TARGET_X64
|
||||||
|
pehdr.nsyms += 1; /* Symbol for lj_err_unwind_win64. */
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Write PE object header and all sections. */
|
/* Write PE object header and all sections. */
|
||||||
owrite(ctx, &pehdr, sizeof(PEheader));
|
owrite(ctx, &pehdr, sizeof(PEheader));
|
||||||
@ -243,6 +268,41 @@ void emit_peobj(BuildCtx *ctx)
|
|||||||
owrite(ctx, &reloc, PEOBJ_RELOC_SIZE);
|
owrite(ctx, &reloc, PEOBJ_RELOC_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if LJ_TARGET_X64
|
||||||
|
{ /* Write .pdata section. */
|
||||||
|
uint32_t pdata[3]; /* Start of .text, end of .text and .xdata. */
|
||||||
|
PEreloc reloc;
|
||||||
|
pdata[0] = 0; pdata[1] = (uint32_t)ctx->codesz; pdata[2] = 0;
|
||||||
|
owrite(ctx, &pdata, sizeof(pdata));
|
||||||
|
reloc.vaddr = 0; reloc.symidx = 1+2+relocsyms+2+2+1;
|
||||||
|
reloc.type = PEOBJ_RELOC_ADDR32NB;
|
||||||
|
owrite(ctx, &reloc, PEOBJ_RELOC_SIZE);
|
||||||
|
reloc.vaddr = 4; reloc.symidx = 1+2+relocsyms+2+2+1;
|
||||||
|
reloc.type = PEOBJ_RELOC_ADDR32NB;
|
||||||
|
owrite(ctx, &reloc, PEOBJ_RELOC_SIZE);
|
||||||
|
reloc.vaddr = 8; reloc.symidx = 1+2+relocsyms+2;
|
||||||
|
reloc.type = PEOBJ_RELOC_ADDR32NB;
|
||||||
|
owrite(ctx, &reloc, PEOBJ_RELOC_SIZE);
|
||||||
|
}
|
||||||
|
{ /* Write .xdata section. */
|
||||||
|
uint16_t xdata[8+2];
|
||||||
|
PEreloc reloc;
|
||||||
|
xdata[0] = 0x01|0x08|0x10; /* Ver. 1, uhander/ehandler, prolog size 0. */
|
||||||
|
xdata[1] = 5; /* Number of unwind codes, no frame pointer. */
|
||||||
|
xdata[2] = 0x4200; /* Stack offset 4*8+8 = aword*5. */
|
||||||
|
xdata[3] = 0x3000; /* Push rbx. */
|
||||||
|
xdata[4] = 0x6000; /* Push rsi. */
|
||||||
|
xdata[5] = 0x7000; /* Push rdi. */
|
||||||
|
xdata[6] = 0x5000; /* Push rbp. */
|
||||||
|
xdata[7] = 0; /* Alignment. */
|
||||||
|
xdata[8] = xdata[9] = 0; /* Relocated address of exception handler. */
|
||||||
|
owrite(ctx, &xdata, sizeof(xdata));
|
||||||
|
reloc.vaddr = sizeof(xdata)-4; reloc.symidx = 1+2+relocsyms+2+2;
|
||||||
|
reloc.type = PEOBJ_RELOC_ADDR32NB;
|
||||||
|
owrite(ctx, &reloc, PEOBJ_RELOC_SIZE);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Write .rdata section. */
|
/* Write .rdata section. */
|
||||||
for (i = 0; i < ctx->npc; i++) {
|
for (i = 0; i < ctx->npc; i++) {
|
||||||
uint16_t pcofs = (uint16_t)ctx->sym_ofs[i];
|
uint16_t pcofs = (uint16_t)ctx->sym_ofs[i];
|
||||||
@ -279,6 +339,14 @@ void emit_peobj(BuildCtx *ctx)
|
|||||||
emit_peobj_sym(ctx, name, 0,
|
emit_peobj_sym(ctx, name, 0,
|
||||||
PEOBJ_SECT_UNDEF, PEOBJ_TYPE_FUNC, PEOBJ_SCL_EXTERN);
|
PEOBJ_SECT_UNDEF, PEOBJ_TYPE_FUNC, PEOBJ_SCL_EXTERN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if LJ_TARGET_X64
|
||||||
|
emit_peobj_sym_sect(ctx, pesect, PEOBJ_SECT_PDATA);
|
||||||
|
emit_peobj_sym_sect(ctx, pesect, PEOBJ_SECT_XDATA);
|
||||||
|
emit_peobj_sym(ctx, PEOBJ_SYM_PREFIX "lj_err_unwind_win64", 0,
|
||||||
|
PEOBJ_SECT_UNDEF, PEOBJ_TYPE_FUNC, PEOBJ_SCL_EXTERN);
|
||||||
|
#endif
|
||||||
|
|
||||||
emit_peobj_sym(ctx, PEOBJ_SYM_PREFIX LABEL_ASM_BEGIN, 0,
|
emit_peobj_sym(ctx, PEOBJ_SYM_PREFIX LABEL_ASM_BEGIN, 0,
|
||||||
PEOBJ_SECT_TEXT, PEOBJ_TYPE_NULL, PEOBJ_SCL_EXTERN);
|
PEOBJ_SECT_TEXT, PEOBJ_TYPE_NULL, PEOBJ_SCL_EXTERN);
|
||||||
for (i = nzsym; i < ctx->nsym; i++) {
|
for (i = nzsym; i < ctx->nsym; i++) {
|
||||||
|
@ -168,28 +168,22 @@
|
|||||||
|.define CFRAME_SPACE, aword*5 // Delta for rsp (see <--).
|
|.define CFRAME_SPACE, aword*5 // Delta for rsp (see <--).
|
||||||
|.macro saveregs
|
|.macro saveregs
|
||||||
| push rbp; push rdi; push rsi; push rbx
|
| push rbp; push rdi; push rsi; push rbx
|
||||||
| push r15; push r14; push r13; push r12
|
|
||||||
| sub rsp, CFRAME_SPACE
|
| sub rsp, CFRAME_SPACE
|
||||||
|.endmacro
|
|.endmacro
|
||||||
|.macro restoreregs
|
|.macro restoreregs
|
||||||
| add rsp, CFRAME_SPACE
|
| add rsp, CFRAME_SPACE
|
||||||
| pop r12; pop r13; pop r14; pop r15
|
|
||||||
| pop rbx; pop rsi; pop rdi; pop rbp
|
| pop rbx; pop rsi; pop rdi; pop rbp
|
||||||
|.endmacro
|
|.endmacro
|
||||||
|
|
|
|
||||||
|.define SAVE_CFRAME, aword [rsp+aword*17]
|
|.define SAVE_CFRAME, aword [rsp+aword*13]
|
||||||
|.define SAVE_PC, dword [rsp+dword*33]
|
|.define SAVE_PC, dword [rsp+dword*25]
|
||||||
|.define SAVE_L, dword [rsp+dword*32]
|
|.define SAVE_L, dword [rsp+dword*24]
|
||||||
|.define SAVE_ERRF, dword [rsp+dword*31]
|
|.define SAVE_ERRF, dword [rsp+dword*23]
|
||||||
|.define SAVE_NRES, dword [rsp+dword*30]
|
|.define SAVE_NRES, dword [rsp+dword*22]
|
||||||
|.define TMP2, dword [rsp+dword*29]
|
|.define TMP2, dword [rsp+dword*21]
|
||||||
|.define TMP1, dword [rsp+dword*28]
|
|.define TMP1, dword [rsp+dword*20]
|
||||||
|//----- 16 byte aligned, ^^^ 32 byte register save area, owned by interpreter
|
|//----- 16 byte aligned, ^^^ 32 byte register save area, owned by interpreter
|
||||||
|.define SAVE_RET, aword [rsp+aword*13] //<-- rsp entering interpreter.
|
|.define SAVE_RET, aword [rsp+aword*9] //<-- rsp entering interpreter.
|
||||||
|.define SAVE_R8, aword [rsp+aword*12]
|
|
||||||
|.define SAVE_R7, aword [rsp+aword*11]
|
|
||||||
|.define SAVE_R6, aword [rsp+aword*10]
|
|
||||||
|.define SAVE_R5, aword [rsp+aword*9]
|
|
||||||
|.define SAVE_R4, aword [rsp+aword*8]
|
|.define SAVE_R4, aword [rsp+aword*8]
|
||||||
|.define SAVE_R3, aword [rsp+aword*7]
|
|.define SAVE_R3, aword [rsp+aword*7]
|
||||||
|.define SAVE_R2, aword [rsp+aword*6]
|
|.define SAVE_R2, aword [rsp+aword*6]
|
||||||
@ -202,7 +196,7 @@
|
|||||||
|//----- 16 byte aligned, ^^^ 32 byte register save area, owned by callee
|
|//----- 16 byte aligned, ^^^ 32 byte register save area, owned by callee
|
||||||
|
|
|
|
||||||
|// TMPQ overlaps TMP1/TMP2. MULTRES overlaps TMP2 (and TMPQ).
|
|// TMPQ overlaps TMP1/TMP2. MULTRES overlaps TMP2 (and TMPQ).
|
||||||
|.define TMPQ, qword [rsp+aword*14]
|
|.define TMPQ, qword [rsp+aword*10]
|
||||||
|.define MULTRES, TMP2
|
|.define MULTRES, TMP2
|
||||||
|.define TMPa, ARG5
|
|.define TMPa, ARG5
|
||||||
|.define ARG5d, dword [rsp+aword*4]
|
|.define ARG5d, dword [rsp+aword*4]
|
||||||
@ -861,10 +855,12 @@ static void build_subroutines(BuildCtx *ctx, int cmov, int sse)
|
|||||||
| mov dword [RA+RD*8-4], LJ_TNIL // Ensure one valid arg.
|
| mov dword [RA+RD*8-4], LJ_TNIL // Ensure one valid arg.
|
||||||
| mov RC, RA // ... in [RC]
|
| mov RC, RA // ... in [RC]
|
||||||
| mov PC, [RB-12] // Restore PC from [cont|PC].
|
| mov PC, [RB-12] // Restore PC from [cont|PC].
|
||||||
| mov RA, dword [RB-16]
|
|
||||||
|.if X64
|
|.if X64
|
||||||
|
| movsxd RAa, dword [RB-16] // May be negative on WIN64 with debug.
|
||||||
| lea KBASEa, qword [=>0]
|
| lea KBASEa, qword [=>0]
|
||||||
| add RAa, KBASEa
|
| add RAa, KBASEa
|
||||||
|
|.else
|
||||||
|
| mov RA, dword [RB-16]
|
||||||
|.endif
|
|.endif
|
||||||
| mov LFUNC:KBASE, [BASE-8]
|
| mov LFUNC:KBASE, [BASE-8]
|
||||||
| mov PROTO:KBASE, LFUNC:KBASE->pt
|
| mov PROTO:KBASE, LFUNC:KBASE->pt
|
||||||
@ -1854,7 +1850,7 @@ static void build_subroutines(BuildCtx *ctx, int cmov, int sse)
|
|||||||
|.ffunc coroutine_yield
|
|.ffunc coroutine_yield
|
||||||
| mov L:RB, SAVE_L
|
| mov L:RB, SAVE_L
|
||||||
| mov [RA-4], PC
|
| mov [RA-4], PC
|
||||||
| test aword L:RB->cframe, CFRAME_CANYIELD
|
| test aword L:RB->cframe, CFRAME_RESUME
|
||||||
| jz ->fff_fallback
|
| jz ->fff_fallback
|
||||||
| mov L:RB->base, RA
|
| mov L:RB->base, RA
|
||||||
| lea RC, [RA+NARGS:RC*8-8]
|
| lea RC, [RA+NARGS:RC*8-8]
|
||||||
|
@ -1177,7 +1177,7 @@ static void build_subroutines(BuildCtx *ctx, int cmov, int sse)
|
|||||||
dasm_put(Dst, 3443, Dt1(->top), Dt1(->base), Dt8(->upvalue[0].gcr), Dt1(->cframe), Dt1(->status), LUA_YIELD, Dt1(->top), Dt1(->base));
|
dasm_put(Dst, 3443, Dt1(->top), Dt1(->base), Dt8(->upvalue[0].gcr), Dt1(->cframe), Dt1(->status), LUA_YIELD, Dt1(->top), Dt1(->base));
|
||||||
dasm_put(Dst, 3523, Dt1(->maxstack), Dt1(->top), Dt1(->base), Dt1(->top), DISPATCH_GL(vmstate), ~LJ_VMST_INTERP, Dt1(->base));
|
dasm_put(Dst, 3523, Dt1(->maxstack), Dt1(->top), Dt1(->base), Dt1(->top), DISPATCH_GL(vmstate), ~LJ_VMST_INTERP, Dt1(->base));
|
||||||
dasm_put(Dst, 3631, LUA_YIELD, Dt1(->base), Dt1(->top), Dt1(->top), Dt1(->maxstack), FRAME_TYPE);
|
dasm_put(Dst, 3631, LUA_YIELD, Dt1(->base), Dt1(->top), Dt1(->top), Dt1(->maxstack), FRAME_TYPE);
|
||||||
dasm_put(Dst, 3727, Dt1(->top), Dt1(->base), Dt1(->cframe), CFRAME_CANYIELD, Dt1(->base), Dt1(->top), Dt1(->cframe), LUA_YIELD, Dt1(->status));
|
dasm_put(Dst, 3727, Dt1(->top), Dt1(->base), Dt1(->cframe), CFRAME_RESUME, Dt1(->base), Dt1(->top), Dt1(->cframe), LUA_YIELD, Dt1(->status));
|
||||||
if (sse) {
|
if (sse) {
|
||||||
dasm_put(Dst, 3813, 1+1, LJ_TISNUM);
|
dasm_put(Dst, 3813, 1+1, LJ_TISNUM);
|
||||||
} else {
|
} else {
|
||||||
|
98
src/lj_err.c
98
src/lj_err.c
@ -493,7 +493,7 @@ static void *err_unwind(lua_State *L, void *stopcf, int errcode)
|
|||||||
L->cframe = NULL;
|
L->cframe = NULL;
|
||||||
L->status = cast_byte(errcode);
|
L->status = cast_byte(errcode);
|
||||||
}
|
}
|
||||||
return cframe_raw(cf);
|
return cf;
|
||||||
}
|
}
|
||||||
if (errcode) {
|
if (errcode) {
|
||||||
L->cframe = cframe_prev(cf);
|
L->cframe = cframe_prev(cf);
|
||||||
@ -514,9 +514,8 @@ static void *err_unwind(lua_State *L, void *stopcf, int errcode)
|
|||||||
L->cframe = cf;
|
L->cframe = cf;
|
||||||
L->base = frame_prevd(frame) + 1;
|
L->base = frame_prevd(frame) + 1;
|
||||||
unwindstack(L, L->base);
|
unwindstack(L, L->base);
|
||||||
return NULL; /* Call special handler. */
|
|
||||||
}
|
}
|
||||||
return cf;
|
return (void *)((intptr_t)cf | CFRAME_UNWIND_FF);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* No C frame. */
|
/* No C frame. */
|
||||||
@ -528,7 +527,7 @@ static void *err_unwind(lua_State *L, void *stopcf, int errcode)
|
|||||||
G(L)->panic(L);
|
G(L)->panic(L);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
return L; /* Anything not-NULL will do. */
|
return L; /* Anything non-NULL will do. */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -- External frame unwinding -------------------------------------------- */
|
/* -- External frame unwinding -------------------------------------------- */
|
||||||
@ -574,12 +573,12 @@ LJ_FUNCA int lj_err_unwind_dwarf(int version, _Unwind_Action actions,
|
|||||||
errcode = LUA_ERRRUN;
|
errcode = LUA_ERRRUN;
|
||||||
}
|
}
|
||||||
#if LJ_UNWIND_EXT
|
#if LJ_UNWIND_EXT
|
||||||
if (err_unwind(L, cf, errcode)) {
|
cf = err_unwind(L, cf, errcode);
|
||||||
|
if (cf) {
|
||||||
_Unwind_SetGR(ctx, 0, errcode);
|
_Unwind_SetGR(ctx, 0, errcode);
|
||||||
_Unwind_SetIP(ctx, (_Unwind_Ptr)lj_vm_unwind_c_eh);
|
_Unwind_SetIP(ctx, (_Unwind_Ptr)(cframe_unwind_ff(cf) ?
|
||||||
return _URC_INSTALL_CONTEXT;
|
lj_vm_unwind_ff_eh :
|
||||||
} else if ((actions & _UA_HANDLER_FRAME)) {
|
lj_vm_unwind_c_eh));
|
||||||
_Unwind_SetIP(ctx, (_Unwind_Ptr)lj_vm_unwind_ff_eh);
|
|
||||||
return _URC_INSTALL_CONTEXT;
|
return _URC_INSTALL_CONTEXT;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
@ -607,20 +606,89 @@ static void err_raise_ext(int errcode)
|
|||||||
|
|
||||||
#elif defined(_WIN64)
|
#elif defined(_WIN64)
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Someone in Redmond owes me several days of my life. A lot of this is
|
||||||
|
** undocumented or just plain wrong on MSDN. Some of it can be gathered
|
||||||
|
** from 3rd party docs or must be found by trial-and-error. They really
|
||||||
|
** don't want you to write your own language-specific exception handler
|
||||||
|
** or to interact gracefully with MSVC. :-(
|
||||||
|
**
|
||||||
|
** Apparently MSVC doesn't call C++ destructors for foreign exceptions
|
||||||
|
** unless you compile your C++ code with /EHa. Unfortunately this means
|
||||||
|
** catch (...) also catches things like access violations. The use of
|
||||||
|
** _set_se_translator doesn't really help, because it requires /EHa, too.
|
||||||
|
*/
|
||||||
|
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
#define LJ_EXCODE ((DWORD)0x024c4a00)
|
/* Taken from: http://www.nynaeve.net/?p=99 */
|
||||||
|
typedef struct UndocumentedDispatcherContext {
|
||||||
|
ULONG64 ControlPc;
|
||||||
|
ULONG64 ImageBase;
|
||||||
|
PRUNTIME_FUNCTION FunctionEntry;
|
||||||
|
ULONG64 EstablisherFrame;
|
||||||
|
ULONG64 TargetIp;
|
||||||
|
PCONTEXT ContextRecord;
|
||||||
|
PEXCEPTION_ROUTINE LanguageHandler;
|
||||||
|
PVOID HandlerData;
|
||||||
|
PUNWIND_HISTORY_TABLE HistoryTable;
|
||||||
|
ULONG ScopeIndex;
|
||||||
|
ULONG Fill0;
|
||||||
|
} UndocumentedDispatcherContext;
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
/* Another wild guess. */
|
||||||
|
extern __DestructExceptionObject(EXCEPTION_RECORD *rec, int nothrow);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define LJ_MSVC_EXCODE ((DWORD)0xe06d7363)
|
||||||
|
|
||||||
|
#define LJ_EXCODE ((DWORD)0xe24c4a00)
|
||||||
#define LJ_EXCODE_MAKE(c) (LJ_EXCODE | (DWORD)(c))
|
#define LJ_EXCODE_MAKE(c) (LJ_EXCODE | (DWORD)(c))
|
||||||
#define LJ_EXCODE_CHECK(cl) (((cl) ^ LJ_EXCODE) <= 0xff)
|
#define LJ_EXCODE_CHECK(cl) (((cl) ^ LJ_EXCODE) <= 0xff)
|
||||||
#define LJ_EXCODE_ERRCODE(cl) (cast_int((cl) & 0xff))
|
#define LJ_EXCODE_ERRCODE(cl) (cast_int((cl) & 0xff))
|
||||||
|
|
||||||
/* NYI: Win64 exception handler for interpreter frame. */
|
/* Win64 exception handler for interpreter frame. */
|
||||||
|
LJ_FUNCA EXCEPTION_DISPOSITION lj_err_unwind_win64(EXCEPTION_RECORD *rec,
|
||||||
|
void *cf, CONTEXT *ctx, UndocumentedDispatcherContext *dispatch)
|
||||||
|
{
|
||||||
|
lua_State *L = cframe_L(cf);
|
||||||
|
if ((rec->ExceptionFlags & 6)) { /* EH_UNWINDING|EH_EXIT_UNWIND */
|
||||||
|
err_unwind(L, cf, 1); /* Unwind internal frames. */
|
||||||
|
} else {
|
||||||
|
void *cf2 = err_unwind(L, cf, 0);
|
||||||
|
if (cf2) { /* We catch it, so start unwinding the upper frames. */
|
||||||
|
int errcode;
|
||||||
|
if (LJ_EXCODE_CHECK(rec->ExceptionCode)) {
|
||||||
|
errcode = LJ_EXCODE_ERRCODE(rec->ExceptionCode);
|
||||||
|
} else if (rec->ExceptionCode == LJ_MSVC_EXCODE) {
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
__DestructExceptionObject(rec, 1);
|
||||||
|
#endif
|
||||||
|
setstrV(L, L->top++, lj_err_str(L, LJ_ERR_ERRCPP));
|
||||||
|
errcode = LUA_ERRRUN;
|
||||||
|
} else { /* Don't catch access violations etc. */
|
||||||
|
return ExceptionContinueSearch;
|
||||||
|
}
|
||||||
|
/* Unwind the stack and call all handlers for all lower C frames
|
||||||
|
** (including ourselves) again with EH_UNWINDING set. Then set
|
||||||
|
** rsp = cf, rax = errcode and jump to the specified target.
|
||||||
|
*/
|
||||||
|
RtlUnwindEx(cf, (void *)(cframe_unwind_ff(cf2) ?
|
||||||
|
lj_vm_unwind_ff_eh :
|
||||||
|
lj_vm_unwind_c_eh),
|
||||||
|
rec, (void *)errcode, ctx, dispatch->HistoryTable);
|
||||||
|
/* RtlUnwindEx should never return. */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ExceptionContinueSearch;
|
||||||
|
}
|
||||||
|
|
||||||
/* Raise Windows exception. */
|
/* Raise Windows exception. */
|
||||||
static void err_raise_ext(int errcode)
|
static void err_raise_ext(int errcode)
|
||||||
{
|
{
|
||||||
RaiseException(LJ_EXCODE_MAKE(errcode), 0, 0, NULL);
|
RaiseException(LJ_EXCODE_MAKE(errcode), 1 /* EH_NONCONTINUABLE */, 0, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@ -650,10 +718,10 @@ LJ_NOINLINE void lj_err_throw(lua_State *L, int errcode)
|
|||||||
#else
|
#else
|
||||||
{
|
{
|
||||||
void *cf = err_unwind(L, NULL, errcode);
|
void *cf = err_unwind(L, NULL, errcode);
|
||||||
if (cf)
|
if (cframe_unwind_ff(cf))
|
||||||
lj_vm_unwind_c(cf, errcode);
|
lj_vm_unwind_ff(cframe_raw(cf));
|
||||||
else
|
else
|
||||||
lj_vm_unwind_ff(cframe_raw(L->cframe));
|
lj_vm_unwind_c(cframe_raw(cf), errcode);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
|
@ -67,13 +67,13 @@ enum {
|
|||||||
#define CFRAME_SIZE (12*4)
|
#define CFRAME_SIZE (12*4)
|
||||||
#elif LJ_TARGET_X64
|
#elif LJ_TARGET_X64
|
||||||
#if _WIN64
|
#if _WIN64
|
||||||
#define CFRAME_OFS_PREV (17*8)
|
#define CFRAME_OFS_PREV (13*8)
|
||||||
#define CFRAME_OFS_PC (33*4)
|
#define CFRAME_OFS_PC (25*4)
|
||||||
#define CFRAME_OFS_L (32*4)
|
#define CFRAME_OFS_L (24*4)
|
||||||
#define CFRAME_OFS_ERRF (31*4)
|
#define CFRAME_OFS_ERRF (23*4)
|
||||||
#define CFRAME_OFS_NRES (30*4)
|
#define CFRAME_OFS_NRES (22*4)
|
||||||
#define CFRAME_OFS_MULTRES (29*4)
|
#define CFRAME_OFS_MULTRES (21*4)
|
||||||
#define CFRAME_SIZE (14*8)
|
#define CFRAME_SIZE (10*8)
|
||||||
#else
|
#else
|
||||||
#define CFRAME_OFS_PREV (4*8)
|
#define CFRAME_OFS_PREV (4*8)
|
||||||
#define CFRAME_OFS_PC (5*4)
|
#define CFRAME_OFS_PC (5*4)
|
||||||
@ -88,8 +88,8 @@ enum {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define CFRAME_RESUME 1
|
#define CFRAME_RESUME 1
|
||||||
#define CFRAME_CANYIELD ((intptr_t)(CFRAME_RESUME))
|
#define CFRAME_UNWIND_FF 2 /* Only used in unwinder. */
|
||||||
#define CFRAME_RAWMASK (~CFRAME_CANYIELD)
|
#define CFRAME_RAWMASK (~(intptr_t)(CFRAME_RESUME|CFRAME_UNWIND_FF))
|
||||||
|
|
||||||
#define cframe_errfunc(cf) (*(int32_t *)(((char *)(cf))+CFRAME_OFS_ERRF))
|
#define cframe_errfunc(cf) (*(int32_t *)(((char *)(cf))+CFRAME_OFS_ERRF))
|
||||||
#define cframe_nres(cf) (*(int32_t *)(((char *)(cf))+CFRAME_OFS_NRES))
|
#define cframe_nres(cf) (*(int32_t *)(((char *)(cf))+CFRAME_OFS_NRES))
|
||||||
@ -101,7 +101,8 @@ enum {
|
|||||||
(mref(*(MRef *)(((char *)(cf))+CFRAME_OFS_PC), const BCIns))
|
(mref(*(MRef *)(((char *)(cf))+CFRAME_OFS_PC), const BCIns))
|
||||||
#define setcframe_pc(cf, pc) \
|
#define setcframe_pc(cf, pc) \
|
||||||
(setmref(*(MRef *)(((char *)(cf))+CFRAME_OFS_PC), (pc)))
|
(setmref(*(MRef *)(((char *)(cf))+CFRAME_OFS_PC), (pc)))
|
||||||
#define cframe_canyield(cf) ((intptr_t)(cf) & CFRAME_CANYIELD)
|
#define cframe_canyield(cf) ((intptr_t)(cf) & CFRAME_RESUME)
|
||||||
|
#define cframe_unwind_ff(cf) ((intptr_t)(cf) & CFRAME_UNWIND_FF)
|
||||||
#define cframe_raw(cf) ((void *)((intptr_t)(cf) & CFRAME_RAWMASK))
|
#define cframe_raw(cf) ((void *)((intptr_t)(cf) & CFRAME_RAWMASK))
|
||||||
#define cframe_Lpc(L) cframe_pc(cframe_raw(L->cframe))
|
#define cframe_Lpc(L) cframe_pc(cframe_raw(L->cframe))
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user