Skip to content

Commit 017aef1

Browse files
committed
Merge branch 'v2.1' into v2.1-agentzh
2 parents c99736f + 35b09e6 commit 017aef1

File tree

9 files changed

+179
-31
lines changed

9 files changed

+179
-31
lines changed

doc/extensions.html

+11-14
Original file line numberDiff line numberDiff line change
@@ -365,25 +365,30 @@ <h2 id="exceptions">C++ Exception Interoperability</h2>
365365
</tr>
366366
<tr class="odd separate">
367367
<td class="excplatform">POSIX/x64, DWARF2 unwinding</td>
368-
<td class="exccompiler">GCC 4.3+</td>
368+
<td class="exccompiler">GCC 4.3+, Clang</td>
369369
<td class="excinterop"><b style="color: #00a000;">Full</b></td>
370370
</tr>
371371
<tr class="even">
372+
<td class="excplatform">ARM <tt>-DLUAJIT_UNWIND_EXTERNAL</tt></td>
373+
<td class="exccompiler">GCC, Clang</td>
374+
<td class="excinterop"><b style="color: #00a000;">Full</b></td>
375+
</tr>
376+
<tr class="odd">
372377
<td class="excplatform">Other platforms, DWARF2 unwinding</td>
373-
<td class="exccompiler">GCC</td>
378+
<td class="exccompiler">GCC, Clang</td>
374379
<td class="excinterop"><b style="color: #c06000;">Limited</b></td>
375380
</tr>
376-
<tr class="odd">
381+
<tr class="even">
377382
<td class="excplatform">Windows/x64</td>
378383
<td class="exccompiler">MSVC or WinSDK</td>
379384
<td class="excinterop"><b style="color: #00a000;">Full</b></td>
380385
</tr>
381-
<tr class="even">
386+
<tr class="odd">
382387
<td class="excplatform">Windows/x86</td>
383388
<td class="exccompiler">Any</td>
384-
<td class="excinterop"><b style="color: #a00000;">No</b></td>
389+
<td class="excinterop"><b style="color: #00a000;">Full</b></td>
385390
</tr>
386-
<tr class="odd">
391+
<tr class="even">
387392
<td class="excplatform">Other platforms</td>
388393
<td class="exccompiler">Other compilers</td>
389394
<td class="excinterop"><b style="color: #a00000;">No</b></td>
@@ -432,14 +437,6 @@ <h2 id="exceptions">C++ Exception Interoperability</h2>
432437
<li>Lua errors <b>cannot</b> be caught on the C++ side.</li>
433438
<li>Throwing Lua errors across C++ frames will <b>not</b> call
434439
C++ destructors.</li>
435-
<li>Additionally, on Windows/x86 with SEH-based C++&nbsp;exceptions:
436-
it's <b>not</b> safe to throw a Lua error across any frames containing
437-
a C++ function with any try/catch construct or using variables with
438-
(implicit) destructors. This also applies to any functions which may be
439-
inlined in such a function. It doesn't matter whether <tt>lua_error()</tt>
440-
is called inside or outside of a try/catch or whether any object actually
441-
needs to be destroyed: the SEH chain is corrupted and this will eventually
442-
lead to the termination of the process.</li>
443440
</ul>
444441
<br class="flush">
445442
</div>

src/host/buildvm.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ static const char *sym_decorate(BuildCtx *ctx,
110110
if (p) {
111111
#if LJ_TARGET_X86ORX64
112112
if (!LJ_64 && (ctx->mode == BUILD_coffasm || ctx->mode == BUILD_peobj))
113-
name[0] = '@';
113+
name[0] = name[1] == 'R' ? '_' : '@'; /* Just for _RtlUnwind@16. */
114114
else
115115
*p = '\0';
116116
#elif LJ_TARGET_PPC && !LJ_TARGET_CONSOLE

src/host/buildvm_peobj.c

+26-2
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@ enum {
109109
#if LJ_TARGET_X64
110110
PEOBJ_SECT_PDATA,
111111
PEOBJ_SECT_XDATA,
112+
#elif LJ_TARGET_X86
113+
PEOBJ_SECT_SXDATA,
112114
#endif
113115
PEOBJ_SECT_RDATA_Z,
114116
PEOBJ_NSECTIONS
@@ -208,6 +210,13 @@ void emit_peobj(BuildCtx *ctx)
208210
sofs += (pesect[PEOBJ_SECT_XDATA].nreloc = 1) * PEOBJ_RELOC_SIZE;
209211
/* Flags: 40 = read, 30 = align4, 40 = initialized data. */
210212
pesect[PEOBJ_SECT_XDATA].flags = 0x40300040;
213+
#elif LJ_TARGET_X86
214+
memcpy(pesect[PEOBJ_SECT_SXDATA].name, ".sxdata", sizeof(".sxdata")-1);
215+
pesect[PEOBJ_SECT_SXDATA].ofs = sofs;
216+
sofs += (pesect[PEOBJ_SECT_SXDATA].size = 4);
217+
pesect[PEOBJ_SECT_SXDATA].relocofs = sofs;
218+
/* Flags: 40 = read, 30 = align4, 02 = lnk_info, 40 = initialized data. */
219+
pesect[PEOBJ_SECT_SXDATA].flags = 0x40300240;
211220
#endif
212221

213222
memcpy(pesect[PEOBJ_SECT_RDATA_Z].name, ".rdata$Z", sizeof(".rdata$Z")-1);
@@ -232,7 +241,7 @@ void emit_peobj(BuildCtx *ctx)
232241
nrsym = ctx->nrelocsym;
233242
pehdr.nsyms = 1+PEOBJ_NSECTIONS*2 + 1+ctx->nsym + nrsym;
234243
#if LJ_TARGET_X64
235-
pehdr.nsyms += 1; /* Symbol for lj_err_unwind_win64. */
244+
pehdr.nsyms += 1; /* Symbol for lj_err_unwind_win. */
236245
#endif
237246

238247
/* Write PE object header and all sections. */
@@ -312,6 +321,19 @@ void emit_peobj(BuildCtx *ctx)
312321
reloc.type = PEOBJ_RELOC_ADDR32NB;
313322
owrite(ctx, &reloc, PEOBJ_RELOC_SIZE);
314323
}
324+
#elif LJ_TARGET_X86
325+
/* Write .sxdata section. */
326+
for (i = 0; i < nrsym; i++) {
327+
if (!strcmp(ctx->relocsym[i], "_lj_err_unwind_win")) {
328+
uint32_t symidx = 1+2+i;
329+
owrite(ctx, &symidx, 4);
330+
break;
331+
}
332+
}
333+
if (i == nrsym) {
334+
fprintf(stderr, "Error: extern lj_err_unwind_win not used\n");
335+
exit(1);
336+
}
315337
#endif
316338

317339
/* Write .rdata$Z section. */
@@ -333,8 +355,10 @@ void emit_peobj(BuildCtx *ctx)
333355
#if LJ_TARGET_X64
334356
emit_peobj_sym_sect(ctx, pesect, PEOBJ_SECT_PDATA);
335357
emit_peobj_sym_sect(ctx, pesect, PEOBJ_SECT_XDATA);
336-
emit_peobj_sym(ctx, "lj_err_unwind_win64", 0,
358+
emit_peobj_sym(ctx, "lj_err_unwind_win", 0,
337359
PEOBJ_SECT_UNDEF, PEOBJ_TYPE_FUNC, PEOBJ_SCL_EXTERN);
360+
#elif LJ_TARGET_X86
361+
emit_peobj_sym_sect(ctx, pesect, PEOBJ_SECT_SXDATA);
338362
#endif
339363

340364
emit_peobj_sym(ctx, ctx->beginsym, 0,

src/lj_asm_x86.h

+3-3
Original file line numberDiff line numberDiff line change
@@ -2680,9 +2680,9 @@ static uint32_t asm_x86_inslen(const uint8_t* p)
26802680
case 4: result -= (prefixes & 2); /* fallthrough */
26812681
case 5: return result + (x & 15);
26822682
case 6: /* Group 3. */
2683-
if (p[1] & 0x38) return result + 2;
2684-
if ((prefixes & 2) && (x == 0x66)) return result + 4;
2685-
return result + (x & 15);
2683+
if (p[1] & 0x38) x = 2;
2684+
else if ((prefixes & 2) && (x == 0x66)) x = 4;
2685+
goto mrm;
26862686
case 7: /* VEX c4/c5. */
26872687
if (LJ_32 && p[1] < 0xc0) {
26882688
x = 2;

src/lj_err.c

+30-8
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@
4646
** the wrapper function feature. Lua errors thrown through C++ frames
4747
** cannot be caught by C++ code and C++ destructors are not run.
4848
**
49-
** EXT is the default on x64 systems, INT is the default on all other systems.
49+
** EXT is the default on x64 systems and on Windows, INT is the default on all
50+
** other systems.
5051
**
5152
** EXT can be manually enabled on POSIX systems using GCC and DWARF2 stack
5253
** unwinding with -DLUAJIT_UNWIND_EXTERNAL. *All* C code must be compiled
@@ -55,15 +56,14 @@
5556
** and all C libraries that have callbacks which may be used to call back
5657
** into Lua. C++ code must *not* be compiled with -fno-exceptions.
5758
**
58-
** EXT cannot be enabled on WIN32 since system exceptions use code-driven SEH.
5959
** EXT is mandatory on WIN64 since the calling convention has an abundance
6060
** of callee-saved registers (rbx, rbp, rsi, rdi, r12-r15, xmm6-xmm15).
6161
** The POSIX/x64 interpreter only saves r12/r13 for INT (e.g. PS4).
6262
*/
6363

6464
#if defined(__GNUC__) && (LJ_TARGET_X64 || defined(LUAJIT_UNWIND_EXTERNAL)) && !LJ_NO_UNWIND
6565
#define LJ_UNWIND_EXT 1
66-
#elif LJ_TARGET_X64 && LJ_TARGET_WINDOWS
66+
#elif LJ_TARGET_WINDOWS
6767
#define LJ_UNWIND_EXT 1
6868
#endif
6969

@@ -384,7 +384,7 @@ static void err_raise_ext(int errcode)
384384

385385
#endif /* LJ_TARGET_ARM */
386386

387-
#elif LJ_TARGET_X64 && LJ_ABI_WIN
387+
#elif LJ_ABI_WIN
388388

389389
/*
390390
** Someone in Redmond owes me several days of my life. A lot of this is
@@ -402,6 +402,7 @@ static void err_raise_ext(int errcode)
402402
#define WIN32_LEAN_AND_MEAN
403403
#include <windows.h>
404404

405+
#if LJ_TARGET_X64
405406
/* Taken from: http://www.nynaeve.net/?p=99 */
406407
typedef struct UndocumentedDispatcherContext {
407408
ULONG64 ControlPc;
@@ -416,11 +417,14 @@ typedef struct UndocumentedDispatcherContext {
416417
ULONG ScopeIndex;
417418
ULONG Fill0;
418419
} UndocumentedDispatcherContext;
420+
#else
421+
typedef void *UndocumentedDispatcherContext;
422+
#endif
419423

420424
/* Another wild guess. */
421425
extern void __DestructExceptionObject(EXCEPTION_RECORD *rec, int nothrow);
422426

423-
#ifdef MINGW_SDK_INIT
427+
#if LJ_TARGET_X64 && defined(MINGW_SDK_INIT)
424428
/* Workaround for broken MinGW64 declaration. */
425429
VOID RtlUnwindEx_FIXED(PVOID,PVOID,PVOID,PVOID,PVOID,PVOID) asm("RtlUnwindEx");
426430
#define RtlUnwindEx RtlUnwindEx_FIXED
@@ -434,10 +438,15 @@ VOID RtlUnwindEx_FIXED(PVOID,PVOID,PVOID,PVOID,PVOID,PVOID) asm("RtlUnwindEx");
434438
#define LJ_EXCODE_CHECK(cl) (((cl) ^ LJ_EXCODE) <= 0xff)
435439
#define LJ_EXCODE_ERRCODE(cl) ((int)((cl) & 0xff))
436440

437-
/* Win64 exception handler for interpreter frame. */
438-
LJ_FUNCA EXCEPTION_DISPOSITION lj_err_unwind_win64(EXCEPTION_RECORD *rec,
439-
void *cf, CONTEXT *ctx, UndocumentedDispatcherContext *dispatch)
441+
/* Windows exception handler for interpreter frame. */
442+
LJ_FUNCA EXCEPTION_DISPOSITION lj_err_unwind_win(EXCEPTION_RECORD *rec,
443+
void *f, CONTEXT *ctx, UndocumentedDispatcherContext *dispatch)
440444
{
445+
#if LJ_TARGET_X64
446+
void *cf = f;
447+
#else
448+
void *cf = (char *)f - CFRAME_OFS_SEH;
449+
#endif
441450
lua_State *L = cframe_L(cf);
442451
int errcode = LJ_EXCODE_CHECK(rec->ExceptionCode) ?
443452
LJ_EXCODE_ERRCODE(rec->ExceptionCode) : LUA_ERRRUN;
@@ -457,6 +466,7 @@ LJ_FUNCA EXCEPTION_DISPOSITION lj_err_unwind_win64(EXCEPTION_RECORD *rec,
457466
/* Don't catch access violations etc. */
458467
return ExceptionContinueSearch;
459468
}
469+
#if LJ_TARGET_X64
460470
/* Unwind the stack and call all handlers for all lower C frames
461471
** (including ourselves) again with EH_UNWINDING set. Then set
462472
** rsp = cf, rax = errcode and jump to the specified target.
@@ -466,6 +476,18 @@ LJ_FUNCA EXCEPTION_DISPOSITION lj_err_unwind_win64(EXCEPTION_RECORD *rec,
466476
lj_vm_unwind_c_eh),
467477
rec, (void *)(uintptr_t)errcode, ctx, dispatch->HistoryTable);
468478
/* RtlUnwindEx should never return. */
479+
#else
480+
UNUSED(ctx);
481+
UNUSED(dispatch);
482+
/* Call all handlers for all lower C frames (including ourselves) again
483+
** with EH_UNWINDING set. Then call the specified function, passing cf
484+
** and errcode.
485+
*/
486+
lj_vm_rtlunwind(cf, (void *)rec,
487+
(cframe_unwind_ff(cf2) && errcode != LUA_YIELD) ?
488+
(void *)lj_vm_unwind_ff : (void *)lj_vm_unwind_c, errcode);
489+
/* lj_vm_rtlunwind does not return. */
490+
#endif
469491
}
470492
}
471493
return ExceptionContinueSearch;

src/lj_frame.h

+12
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,17 @@ enum { LJ_CONT_TAILCALL, LJ_CONT_FFI_CALLBACK }; /* Special continuations. */
116116

117117
/* These definitions must match with the arch-specific *.dasc files. */
118118
#if LJ_TARGET_X86
119+
#if LJ_ABI_WIN
120+
#define CFRAME_OFS_ERRF (19*4)
121+
#define CFRAME_OFS_NRES (18*4)
122+
#define CFRAME_OFS_PREV (17*4)
123+
#define CFRAME_OFS_L (16*4)
124+
#define CFRAME_OFS_SEH (9*4)
125+
#define CFRAME_OFS_PC (6*4)
126+
#define CFRAME_OFS_MULTRES (5*4)
127+
#define CFRAME_SIZE (16*4)
128+
#define CFRAME_SHIFT_MULTRES 0
129+
#else
119130
#define CFRAME_OFS_ERRF (15*4)
120131
#define CFRAME_OFS_NRES (14*4)
121132
#define CFRAME_OFS_PREV (13*4)
@@ -124,6 +135,7 @@ enum { LJ_CONT_TAILCALL, LJ_CONT_FFI_CALLBACK }; /* Special continuations. */
124135
#define CFRAME_OFS_MULTRES (5*4)
125136
#define CFRAME_SIZE (12*4)
126137
#define CFRAME_SHIFT_MULTRES 0
138+
#endif
127139
#elif LJ_TARGET_X64
128140
#if LJ_ABI_WIN
129141
#define CFRAME_OFS_PREV (13*8)

src/lj_gdbjit.c

+18
Original file line numberDiff line numberDiff line change
@@ -719,6 +719,20 @@ static void gdbjit_buildobj(GDBJITctx *ctx)
719719

720720
/* -- Interface to GDB JIT API -------------------------------------------- */
721721

722+
static int gdbjit_lock;
723+
724+
static void gdbjit_lock_acquire()
725+
{
726+
while (__sync_lock_test_and_set(&gdbjit_lock, 1)) {
727+
/* Just spin; futexes or pthreads aren't worth the portability cost. */
728+
}
729+
}
730+
731+
static void gdbjit_lock_release()
732+
{
733+
__sync_lock_release(&gdbjit_lock);
734+
}
735+
722736
/* Add new entry to GDB JIT symbol chain. */
723737
static void gdbjit_newentry(lua_State *L, GDBJITctx *ctx)
724738
{
@@ -730,6 +744,7 @@ static void gdbjit_newentry(lua_State *L, GDBJITctx *ctx)
730744
ctx->T->gdbjit_entry = (void *)eo;
731745
/* Link new entry to chain and register it. */
732746
eo->entry.prev_entry = NULL;
747+
gdbjit_lock_acquire();
733748
eo->entry.next_entry = __jit_debug_descriptor.first_entry;
734749
if (eo->entry.next_entry)
735750
eo->entry.next_entry->prev_entry = &eo->entry;
@@ -739,6 +754,7 @@ static void gdbjit_newentry(lua_State *L, GDBJITctx *ctx)
739754
__jit_debug_descriptor.relevant_entry = &eo->entry;
740755
__jit_debug_descriptor.action_flag = GDBJIT_REGISTER;
741756
__jit_debug_register_code();
757+
gdbjit_lock_release();
742758
}
743759

744760
/* Add debug info for newly compiled trace and notify GDB. */
@@ -770,6 +786,7 @@ void lj_gdbjit_deltrace(jit_State *J, GCtrace *T)
770786
{
771787
GDBJITentryobj *eo = (GDBJITentryobj *)T->gdbjit_entry;
772788
if (eo) {
789+
gdbjit_lock_acquire();
773790
if (eo->entry.prev_entry)
774791
eo->entry.prev_entry->next_entry = eo->entry.next_entry;
775792
else
@@ -779,6 +796,7 @@ void lj_gdbjit_deltrace(jit_State *J, GCtrace *T)
779796
__jit_debug_descriptor.relevant_entry = &eo->entry;
780797
__jit_debug_descriptor.action_flag = GDBJIT_UNREGISTER;
781798
__jit_debug_register_code();
799+
gdbjit_lock_release();
782800
lj_mem_free(J2G(J), eo, eo->sz);
783801
}
784802
}

src/lj_vm.h

+4
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ LJ_ASMF int lj_vm_cpcall(lua_State *L, lua_CFunction func, void *ud,
1717
LJ_ASMF int lj_vm_resume(lua_State *L, TValue *base, int nres1, ptrdiff_t ef);
1818
LJ_ASMF_NORET void LJ_FASTCALL lj_vm_unwind_c(void *cframe, int errcode);
1919
LJ_ASMF_NORET void LJ_FASTCALL lj_vm_unwind_ff(void *cframe);
20+
#if LJ_ABI_WIN && LJ_TARGET_X86
21+
LJ_ASMF_NORET void LJ_FASTCALL lj_vm_rtlunwind(void *cframe, void *excptrec,
22+
void *unwinder, int errcode);
23+
#endif
2024
LJ_ASMF void lj_vm_unwind_c_eh(void);
2125
LJ_ASMF void lj_vm_unwind_ff_eh(void);
2226
#if LJ_TARGET_X86ORX64

0 commit comments

Comments
 (0)