From: sergos via Tarantool-patches <tarantool-patches@dev.tarantool.org>
To: Maksim Kokryashkin <max.kokryashkin@gmail.com>
Cc: tarantool-patches@dev.tarantool.org
Subject: Re: [Tarantool-patches] [PATCH luajit v4 1/8] Cleanup and enable external unwinding for more platforms.
Date: Mon, 5 Dec 2022 19:01:48 +0300 [thread overview]
Message-ID: <122D5C22-F75B-4468-97AF-D69BCB93EA3E@tarantool.org> (raw)
In-Reply-To: <20221028092638.11506-2-max.kokryashkin@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 26392 bytes --]
Hi!
Thanks for the patch, LGTM as part of original [PATCH luajit 1/6] Cleanup and enable external unwinding for more platforms.
Sergos.
> On 28 Oct 2022, at 12:26, Maksim Kokryashkin <max.kokryashkin@gmail.com> wrote:
>
> (cherry picked from commit e131936133c58de4426c595db2341caf5a1665b5)
>
> This commit enables external unwinding on all platforms, that
> create unwind tables by default. Corresponding check is added
> to the build routine.
>
> Also, GC64 mode is now enabled on MacOS by default, as
> non-GC64 mode is forbidden.
>
> Maxim Kokryashkin:
> * added the description for the patch
>
> Needed for tarantool/tarantool#6096
> Part of tarantool/tarantool#7230
> ---
> .github/workflows/macos-x86_64.yml | 20 +-
> CMakeLists.txt | 3 +
> cmake/SetTargetFlags.cmake | 22 +-
> doc/extensions.html | 22 +-
> src/Makefile.original | 11 +-
> src/lj_arch.h | 27 ++-
> src/lj_err.c | 321 +++++++++++++++--------------
> 7 files changed, 214 insertions(+), 212 deletions(-)
>
> diff --git a/.github/workflows/macos-x86_64.yml b/.github/workflows/macos-x86_64.yml
> index 840806e3..dafd1796 100644
> --- a/.github/workflows/macos-x86_64.yml
> +++ b/.github/workflows/macos-x86_64.yml
> @@ -35,7 +35,7 @@ jobs:
> fail-fast: false
> matrix:
> BUILDTYPE: [Debug, Release]
> - GC64: [ON, OFF]
> + GC64: ON
> include:
> - BUILDTYPE: Debug
> CMAKEFLAGS: -DCMAKE_BUILD_TYPE=Debug -DLUA_USE_ASSERT=ON -DLUA_USE_APICHECK=ON
> @@ -69,15 +69,6 @@ jobs:
> - name: test
> run: cmake --build . --parallel --target test
>
> - test-tarantool-debug-wo-GC64:
> - name: Tarantool Debug GC64:OFF
> - needs: test-luajit
> - uses: tarantool/tarantool/.github/workflows/luajit-integration.yml@master
> - with:
> - GC64: OFF
> - buildtype: Debug
> - host: macos-11
> - revision: ${{ github.sha }}
> test-tarantool-debug-w-GC64:
> name: Tarantool Debug GC64:ON
> needs: test-luajit
> @@ -87,15 +78,6 @@ jobs:
> buildtype: Debug
> host: macos-11
> revision: ${{ github.sha }}
> - test-tarantool-release-wo-GC64:
> - name: Tarantool Release GC64:OFF
> - needs: test-luajit
> - uses: tarantool/tarantool/.github/workflows/luajit-integration.yml@master
> - with:
> - GC64: OFF
> - buildtype: RelWithDebInfo
> - host: macos-11
> - revision: ${{ github.sha }}
> test-tarantool-release-w-GC64:
> name: Tarantool Release GC64:ON
> needs: test-luajit
> diff --git a/CMakeLists.txt b/CMakeLists.txt
> index 8b49f9d7..c4f3ef62 100644
> --- a/CMakeLists.txt
> +++ b/CMakeLists.txt
> @@ -176,6 +176,9 @@ endif()
>
> # Enable GC64 mode for x64.
> option(LUAJIT_ENABLE_GC64 "GC64 mode for x64" OFF)
> +if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
> + set(LUAJIT_ENABLE_GC64 ON)
> +endif()
> if(LUAJIT_ENABLE_GC64)
> AppendFlags(TARGET_C_FLAGS -DLUAJIT_ENABLE_GC64)
> endif()
> diff --git a/cmake/SetTargetFlags.cmake b/cmake/SetTargetFlags.cmake
> index b544d2ac..36896aff 100644
> --- a/cmake/SetTargetFlags.cmake
> +++ b/cmake/SetTargetFlags.cmake
> @@ -15,6 +15,22 @@ endif()
> LuaJITTestArch(TESTARCH "${TARGET_C_FLAGS}")
> LuaJITArch(LUAJIT_ARCH "${TESTARCH}")
>
> +string(FIND ${TARGET_C_FLAGS} "LJ_NO_UNWIND 1" UNWIND_POS)
> +if(UNWIND_POS EQUAL -1)
> + execute_process(
> + COMMAND bash -c "exec 2>/dev/null; echo 'extern void b(void);int a(void){b();return 0;}' | ${CMAKE_C_COMPILER} -c -x c - -o tmpunwind.o && grep -qa -e eh_frame -e __unwind_info tmpunwind.o && echo E; rm -f tmpunwind.o"
> + WORKING_DIRECTORY ${LUAJIT_SOURCE_DIR}
> + OUTPUT_VARIABLE TESTUNWIND
> + RESULT_VARIABLE TESTUNWIND_RC
> + )
> + if(TESTUNWIND_RC EQUAL 0)
> + string(FIND "${TESTUNWIND}" "E" UNW_TEST_POS)
> + if(NOT UNW_TEST_POS EQUAL -1)
> + AppendFlags(TARGET_C_FLAGS -DLUAJIT_UNWIND_EXTERNAL)
> + endif()
> + endif()
> +endif()
> +
> # Target-specific compiler options.
> #
> # x86/x64 only: For GCC 4.2 or higher and if you don't intend to
> @@ -25,12 +41,6 @@ if(LUAJIT_ARCH STREQUAL "x86")
> endif()
>
> if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
> - if(LUAJIT_ARCH STREQUAL "x64")
> - # XXX: Set -pagezero_size to hint <mmap> when allocating 32
> - # bit memory on OSX/x64, otherwise the lower 4GB are blocked.
> - AppendFlags(TARGET_BIN_FLAGS -pagezero_size 10000 -image_base 100000000)
> - AppendFlags(TARGET_SHARED_FLAGS -image_base 7fff04c4a000)
> - endif()
> AppendFlags(TARGET_SHARED_FLAGS -single_module -undefined dynamic_lookup)
> else() # Linux and FreeBSD.
> AppendFlags(TARGET_BIN_FLAGS -Wl,-E)
> diff --git a/doc/extensions.html b/doc/extensions.html
> index e0f136e2..777e9928 100644
> --- a/doc/extensions.html
> +++ b/doc/extensions.html
> @@ -395,29 +395,19 @@ the toolchain used to compile LuaJIT:
> <td class="excinterop">Interoperability</td>
> </tr>
> <tr class="odd separate">
> -<td class="excplatform">POSIX/x64, DWARF2 unwinding</td>
> -<td class="exccompiler">GCC 4.3+, Clang</td>
> +<td class="excplatform">External frame unwinding</td>
> +<td class="exccompiler">GCC, Clang, MSVC</td>
> <td class="excinterop"><b style="color: #00a000;">Full</b></td>
> </tr>
> <tr class="even">
> -<td class="excplatform">ARM <tt>-DLUAJIT_UNWIND_EXTERNAL</tt></td>
> -<td class="exccompiler">GCC, Clang</td>
> -<td class="excinterop"><b style="color: #00a000;">Full</b></td>
> -</tr>
> -<tr class="odd">
> -<td class="excplatform">Other platforms, DWARF2 unwinding</td>
> +<td class="excplatform">Internal frame unwinding + DWARF2</td>
> <td class="exccompiler">GCC, Clang</td>
> <td class="excinterop"><b style="color: #c06000;">Limited</b></td>
> </tr>
> -<tr class="even">
> -<td class="excplatform">Windows/x64</td>
> -<td class="exccompiler">MSVC or WinSDK</td>
> -<td class="excinterop"><b style="color: #00a000;">Full</b></td>
> -</tr>
> <tr class="odd">
> -<td class="excplatform">Windows/x86</td>
> -<td class="exccompiler">Any</td>
> -<td class="excinterop"><b style="color: #00a000;">Full</b></td>
> +<td class="excplatform">Windows 64 bit</td>
> +<td class="exccompiler">non-MSVC</td>
> +<td class="excinterop"><b style="color: #c06000;">Limited</b></td>
> </tr>
> <tr class="even">
> <td class="excplatform">Other platforms</td>
> diff --git a/src/Makefile.original b/src/Makefile.original
> index dd1c6a76..c9609700 100644
> --- a/src/Makefile.original
> +++ b/src/Makefile.original
> @@ -320,6 +320,13 @@ else
> ifeq (,$(shell $(TARGET_CC) -o /dev/null -c -x c /dev/null -fno-stack-protector 2>/dev/null || echo 1))
> TARGET_XCFLAGS+= -fno-stack-protector
> endif
> +ifeq (,$(findstring LJ_NO_UNWIND 1,$(TARGET_TESTARCH)))
> + # Find out whether the target toolchain always generates unwind tables.
> + TARGET_TESTUNWIND=$(shell exec 2>/dev/null; echo 'extern void b(void);int a(void){b();return 0;}' | $(TARGET_CC) -c -x c - -o tmpunwind.o && grep -qa -e eh_frame -e __unwind_info tmpunwind.o && echo E; rm -f tmpunwind.o)
> + ifneq (,$(findstring E,$(TARGET_TESTUNWIND)))
> + TARGET_XCFLAGS+= -DLUAJIT_UNWIND_EXTERNAL
> + endif
> +endif
> ifeq (Darwin,$(TARGET_SYS))
> ifeq (,$(MACOSX_DEPLOYMENT_TARGET))
> export MACOSX_DEPLOYMENT_TARGET=10.4
> @@ -328,10 +335,6 @@ ifeq (Darwin,$(TARGET_SYS))
> TARGET_XSHLDFLAGS= -dynamiclib -single_module -undefined dynamic_lookup -fPIC
> TARGET_DYNXLDOPTS=
> TARGET_XSHLDFLAGS+= -install_name $(TARGET_DYLIBPATH) -compatibility_version $(MAJVER).$(MINVER) -current_version $(MAJVER).$(MINVER).$(RELVER)
> - ifeq (x64,$(TARGET_LJARCH))
> - TARGET_XLDFLAGS+= -pagezero_size 10000 -image_base 100000000
> - TARGET_XSHLDFLAGS+= -image_base 7fff04c4a000
> - endif
> else
> ifeq (iOS,$(TARGET_SYS))
> TARGET_STRIP+= -x
> diff --git a/src/lj_arch.h b/src/lj_arch.h
> index 40129d9e..730be5bf 100644
> --- a/src/lj_arch.h
> +++ b/src/lj_arch.h
> @@ -152,11 +152,6 @@
> #define LJ_ARCH_NAME "x86"
> #define LJ_ARCH_BITS 32
> #define LJ_ARCH_ENDIAN LUAJIT_LE
> -#if LJ_TARGET_WINDOWS || LJ_TARGET_CYGWIN
> -#define LJ_ABI_WIN 1
> -#else
> -#define LJ_ABI_WIN 0
> -#endif
> #define LJ_TARGET_X86 1
> #define LJ_TARGET_X86ORX64 1
> #define LJ_TARGET_EHRETREG 0
> @@ -170,11 +165,6 @@
> #define LJ_ARCH_NAME "x64"
> #define LJ_ARCH_BITS 64
> #define LJ_ARCH_ENDIAN LUAJIT_LE
> -#if LJ_TARGET_WINDOWS || LJ_TARGET_CYGWIN
> -#define LJ_ABI_WIN 1
> -#else
> -#define LJ_ABI_WIN 0
> -#endif
> #define LJ_TARGET_X64 1
> #define LJ_TARGET_X86ORX64 1
> #define LJ_TARGET_EHRETREG 0
> @@ -185,6 +175,8 @@
> #define LJ_ARCH_NUMMODE LJ_NUMMODE_SINGLE_DUAL
> #ifdef LUAJIT_ENABLE_GC64
> #define LJ_TARGET_GC64 1
> +#elif LJ_TARGET_OSX
> +#error "macOS requires GC64 -- don't disable it"
> #endif
>
> #elif LUAJIT_TARGET == LUAJIT_ARCH_ARM
> @@ -566,15 +558,22 @@
> #define LJ_NO_SYSTEM 1
> #endif
>
> -#if !defined(LUAJIT_NO_UNWIND) && __GNU_COMPACT_EH__
> -/* NYI: no support for compact unwind specification, yet. */
> -#define LUAJIT_NO_UNWIND 1
> +#if LJ_TARGET_WINDOWS || LJ_TARGET_CYGWIN
> +#define LJ_ABI_WIN 1
> +#else
> +#define LJ_ABI_WIN 0
> #endif
>
> -#if defined(LUAJIT_NO_UNWIND) || defined(__symbian__) || LJ_TARGET_IOS || LJ_TARGET_PS3 || LJ_TARGET_PS4
> +#if defined(LUAJIT_NO_UNWIND) || __GNU_COMPACT_EH__ || defined(__symbian__) || LJ_TARGET_IOS || LJ_TARGET_PS3 || LJ_TARGET_PS4
> #define LJ_NO_UNWIND 1
> #endif
>
> +#if !LJ_NO_UNWIND && !defined(LUAJIT_UNWIND_INTERNAL) && (LJ_ABI_WIN || (defined(LUAJIT_UNWIND_EXTERNAL) && (defined(__GNUC__) || defined(__clang__))))
> +#define LJ_UNWIND_EXT 1
> +#else
> +#define LJ_UNWIND_EXT 0
> +#endif
> +
> /* Compatibility with Lua 5.1 vs. 5.2. */
> #ifdef LUAJIT_ENABLE_LUA52COMPAT
> #define LJ_52 1
> diff --git a/src/lj_err.c b/src/lj_err.c
> index c310daf6..298e5434 100644
> --- a/src/lj_err.c
> +++ b/src/lj_err.c
> @@ -29,12 +29,18 @@
> ** Pros and Cons:
> **
> ** - EXT requires unwind tables for *all* functions on the C stack between
> -** the pcall/catch and the error/throw. This is the default on x64,
> -** but needs to be manually enabled on x86/PPC for non-C++ code.
> +** the pcall/catch and the error/throw. C modules used by Lua code can
> +** throw errors, so these need to have unwind tables, too. Transitively
> +** this applies to all system libraries used by C modules -- at least
> +** when they have callbacks which may throw an error.
> **
> -** - INT is faster when actually throwing errors (but this happens rarely).
> +** - INT is faster when actually throwing errors, but this happens rarely.
> ** Setting up error handlers is zero-cost in any case.
> **
> +** - INT needs to save *all* callee-saved registers when entering the
> +** interpreter. EXT only needs to save those actually used inside the
> +** interpreter. JIT-compiled code may need to save some more.
> +**
> ** - EXT provides full interoperability with C++ exceptions. You can throw
> ** Lua errors or C++ exceptions through a mix of Lua frames and C++ frames.
> ** C++ destructors are called as needed. C++ exceptions caught by pcall
> @@ -46,27 +52,33 @@
> ** the wrapper function feature. Lua errors thrown through C++ frames
> ** cannot be caught by C++ code and C++ destructors are not run.
> **
> -** EXT is the default on x64 systems and on Windows, INT is the default on all
> -** other systems.
> +** EXT is the default on all systems where the toolchain produces unwind
> +** tables by default (*). This is hard-coded and/or detected in src/Makefile.
> +** You can thwart the detection with: TARGET_XCFLAGS=-DLUAJIT_UNWIND_INTERNAL
> +**
> +** INT is the default on all other systems.
> +**
> +** EXT can be manually enabled for toolchains that are able to produce
> +** conforming unwind tables:
> +** "TARGET_XCFLAGS=-funwind-tables -DLUAJIT_UNWIND_EXTERNAL"
> +** As explained above, *all* C code used directly or indirectly by LuaJIT
> +** must be compiled with -funwind-tables (or -fexceptions). C++ code must
> +** *not* be compiled with -fno-exceptions.
> +**
> +** If you're unsure whether error handling inside the VM works correctly,
> +** try running this and check whether it prints "OK":
> **
> -** EXT can be manually enabled on POSIX systems using GCC and DWARF2 stack
> -** unwinding with -DLUAJIT_UNWIND_EXTERNAL. *All* C code must be compiled
> -** with -funwind-tables (or -fexceptions). This includes LuaJIT itself (set
> -** TARGET_CFLAGS), all of your C/Lua binding code, all loadable C modules
> -** and all C libraries that have callbacks which may be used to call back
> -** into Lua. C++ code must *not* be compiled with -fno-exceptions.
> +** luajit -e "print(select(2, load('OK')):match('OK'))"
> **
> -** EXT is mandatory on WIN64 since the calling convention has an abundance
> -** of callee-saved registers (rbx, rbp, rsi, rdi, r12-r15, xmm6-xmm15).
> -** The POSIX/x64 interpreter only saves r12/r13 for INT (e.g. PS4).
> +** (*) Originally, toolchains only generated unwind tables for C++ code. For
> +** interoperability reasons, this can be manually enabled for plain C code,
> +** too (with -funwind-tables). With the introduction of the x64 architecture,
> +** the corresponding POSIX and Windows ABIs mandated unwind tables for all
> +** code. Over the following years most desktop and server platforms have
> +** enabled unwind tables by default on all architectures. OTOH mobile and
> +** embedded platforms do not consistently mandate unwind tables.
> */
>
> -#if defined(__GNUC__) && (LJ_TARGET_X64 || defined(LUAJIT_UNWIND_EXTERNAL)) && !LJ_NO_UNWIND
> -#define LJ_UNWIND_EXT 1
> -#elif LJ_TARGET_WINDOWS
> -#define LJ_UNWIND_EXT 1
> -#endif
> -
> /* -- Error messages ------------------------------------------------------ */
>
> /* Error message strings. */
> @@ -183,7 +195,125 @@ static void *err_unwind(lua_State *L, void *stopcf, int errcode)
>
> /* -- External frame unwinding -------------------------------------------- */
>
> -#if defined(__GNUC__) && !LJ_NO_UNWIND && !LJ_ABI_WIN
> +#if LJ_ABI_WIN
> +
> +/*
> +** 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
> +#include <windows.h>
> +
> +#if LJ_TARGET_X86
> +typedef void *UndocumentedDispatcherContext; /* Unused on x86. */
> +#else
> +/* Taken from: http://www.nynaeve.net/?p=99 */
> +typedef struct UndocumentedDispatcherContext {
> + ULONG64 ControlPc;
> + ULONG64 ImageBase;
> + PRUNTIME_FUNCTION FunctionEntry;
> + ULONG64 EstablisherFrame;
> + ULONG64 TargetIp;
> + PCONTEXT ContextRecord;
> + void (*LanguageHandler)(void);
> + PVOID HandlerData;
> + PUNWIND_HISTORY_TABLE HistoryTable;
> + ULONG ScopeIndex;
> + ULONG Fill0;
> +} UndocumentedDispatcherContext;
> +#endif
> +
> +/* Another wild guess. */
> +extern void __DestructExceptionObject(EXCEPTION_RECORD *rec, int nothrow);
> +
> +#if LJ_TARGET_X64 && defined(MINGW_SDK_INIT)
> +/* Workaround for broken MinGW64 declaration. */
> +VOID RtlUnwindEx_FIXED(PVOID,PVOID,PVOID,PVOID,PVOID,PVOID) asm("RtlUnwindEx");
> +#define RtlUnwindEx RtlUnwindEx_FIXED
> +#endif
> +
> +#define LJ_MSVC_EXCODE ((DWORD)0xe06d7363)
> +#define LJ_GCC_EXCODE ((DWORD)0x20474343)
> +
> +#define LJ_EXCODE ((DWORD)0xe24c4a00)
> +#define LJ_EXCODE_MAKE(c) (LJ_EXCODE | (DWORD)(c))
> +#define LJ_EXCODE_CHECK(cl) (((cl) ^ LJ_EXCODE) <= 0xff)
> +#define LJ_EXCODE_ERRCODE(cl) ((int)((cl) & 0xff))
> +
> +/* Windows exception handler for interpreter frame. */
> +LJ_FUNCA int lj_err_unwind_win(EXCEPTION_RECORD *rec,
> + void *f, CONTEXT *ctx, UndocumentedDispatcherContext *dispatch)
> +{
> +#if LJ_TARGET_X86
> + void *cf = (char *)f - CFRAME_OFS_SEH;
> +#else
> + void *cf = f;
> +#endif
> + lua_State *L = cframe_L(cf);
> + int errcode = LJ_EXCODE_CHECK(rec->ExceptionCode) ?
> + LJ_EXCODE_ERRCODE(rec->ExceptionCode) : LUA_ERRRUN;
> + if ((rec->ExceptionFlags & 6)) { /* EH_UNWINDING|EH_EXIT_UNWIND */
> + /* Unwind internal frames. */
> + err_unwind(L, cf, errcode);
> + } else {
> + void *cf2 = err_unwind(L, cf, 0);
> + if (cf2) { /* We catch it, so start unwinding the upper frames. */
> + if (rec->ExceptionCode == LJ_MSVC_EXCODE ||
> + rec->ExceptionCode == LJ_GCC_EXCODE) {
> +#if !LJ_TARGET_CYGWIN
> + __DestructExceptionObject(rec, 1);
> +#endif
> + setstrV(L, L->top++, lj_err_str(L, LJ_ERR_ERRCPP));
> + } else if (!LJ_EXCODE_CHECK(rec->ExceptionCode)) {
> + /* Don't catch access violations etc. */
> + return 1; /* ExceptionContinueSearch */
> + }
> +#if LJ_TARGET_X86
> + UNUSED(ctx);
> + UNUSED(dispatch);
> + /* Call all handlers for all lower C frames (including ourselves) again
> + ** with EH_UNWINDING set. Then call the specified function, passing cf
> + ** and errcode.
> + */
> + lj_vm_rtlunwind(cf, (void *)rec,
> + (cframe_unwind_ff(cf2) && errcode != LUA_YIELD) ?
> + (void *)lj_vm_unwind_ff : (void *)lj_vm_unwind_c, errcode);
> + /* lj_vm_rtlunwind does not return. */
> +#else
> + /* Unwind the stack and call all handlers for all lower C frames
> + ** (including ourselves) again with EH_UNWINDING set. Then set
> + ** stack pointer = cf, result = errcode and jump to the specified target.
> + */
> + RtlUnwindEx(cf, (void *)((cframe_unwind_ff(cf2) && errcode != LUA_YIELD) ?
> + lj_vm_unwind_ff_eh :
> + lj_vm_unwind_c_eh),
> + rec, (void *)(uintptr_t)errcode, ctx, dispatch->HistoryTable);
> + /* RtlUnwindEx should never return. */
> +#endif
> + }
> + }
> + return 1; /* ExceptionContinueSearch */
> +}
> +
> +/* Raise Windows exception. */
> +static void err_raise_ext(global_State *g, int errcode)
> +{
> +#if LJ_HASJIT
> + setmref(g->jit_base, NULL);
> +#endif
> + RaiseException(LJ_EXCODE_MAKE(errcode), 1 /* EH_NONCONTINUABLE */, 0, NULL);
> +}
> +
> +#elif !LJ_NO_UNWIND && (defined(__GNUC__) || defined(__clang__))
>
> /*
> ** We have to use our own definitions instead of the mandatory (!) unwind.h,
> @@ -232,7 +362,6 @@ LJ_FUNCA int lj_err_unwind_dwarf(int version, int actions,
> lua_State *L;
> if (version != 1)
> return _URC_FATAL_PHASE1_ERROR;
> - UNUSED(uexclass);
> cf = (void *)_Unwind_GetCFA(ctx);
> L = cframe_L(cf);
> if ((actions & _UA_SEARCH_PHASE)) {
> @@ -280,6 +409,9 @@ LJ_FUNCA int lj_err_unwind_dwarf(int version, int actions,
> ** it on non-x64 because the interpreter restores all callee-saved regs.
> */
> lj_err_throw(L, errcode);
> +#if LJ_TARGET_X64
> +#error "Broken build system -- only use the provided Makefiles!"
> +#endif
> #endif
> }
> return _URC_CONTINUE_UNWIND;
> @@ -292,14 +424,6 @@ static _Unwind_Exception static_uex;
> #else
> static __thread _Unwind_Exception static_uex;
> #endif
> -
> -/* Raise DWARF2 exception. */
> -static void err_raise_ext(int errcode)
> -{
> - static_uex.exclass = LJ_UEXCLASS_MAKE(errcode);
> - static_uex.excleanup = NULL;
> - _Unwind_RaiseException(&static_uex);
> -}
> #endif
>
> #else /* LJ_TARGET_ARM */
> @@ -373,132 +497,22 @@ LJ_FUNCA int lj_err_unwind_arm(int state, _Unwind_Control_Block *ucb,
>
> #if LJ_UNWIND_EXT
> static __thread _Unwind_Control_Block static_uex;
> +#endif
> +#endif /* LJ_TARGET_ARM */
>
> -static void err_raise_ext(int errcode)
> +#if LJ_UNWIND_EXT
> +/* Raise external exception. */
> +static void err_raise_ext(global_State *g, int errcode)
> {
> +#if LJ_HASJIT
> + setmref(g->jit_base, NULL);
> +#endif
> memset(&static_uex, 0, sizeof(static_uex));
> static_uex.exclass = LJ_UEXCLASS_MAKE(errcode);
> _Unwind_RaiseException(&static_uex);
> }
> #endif
>
> -#endif /* LJ_TARGET_ARM */
> -
> -#elif LJ_ABI_WIN
> -
> -/*
> -** 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
> -#include <windows.h>
> -
> -#if LJ_TARGET_X64
> -/* Taken from: http://www.nynaeve.net/?p=99 */
> -typedef struct UndocumentedDispatcherContext {
> - ULONG64 ControlPc;
> - ULONG64 ImageBase;
> - PRUNTIME_FUNCTION FunctionEntry;
> - ULONG64 EstablisherFrame;
> - ULONG64 TargetIp;
> - PCONTEXT ContextRecord;
> - void (*LanguageHandler)(void);
> - PVOID HandlerData;
> - PUNWIND_HISTORY_TABLE HistoryTable;
> - ULONG ScopeIndex;
> - ULONG Fill0;
> -} UndocumentedDispatcherContext;
> -#else
> -typedef void *UndocumentedDispatcherContext;
> -#endif
> -
> -/* Another wild guess. */
> -extern void __DestructExceptionObject(EXCEPTION_RECORD *rec, int nothrow);
> -
> -#if LJ_TARGET_X64 && defined(MINGW_SDK_INIT)
> -/* Workaround for broken MinGW64 declaration. */
> -VOID RtlUnwindEx_FIXED(PVOID,PVOID,PVOID,PVOID,PVOID,PVOID) asm("RtlUnwindEx");
> -#define RtlUnwindEx RtlUnwindEx_FIXED
> -#endif
> -
> -#define LJ_MSVC_EXCODE ((DWORD)0xe06d7363)
> -#define LJ_GCC_EXCODE ((DWORD)0x20474343)
> -
> -#define LJ_EXCODE ((DWORD)0xe24c4a00)
> -#define LJ_EXCODE_MAKE(c) (LJ_EXCODE | (DWORD)(c))
> -#define LJ_EXCODE_CHECK(cl) (((cl) ^ LJ_EXCODE) <= 0xff)
> -#define LJ_EXCODE_ERRCODE(cl) ((int)((cl) & 0xff))
> -
> -/* Windows exception handler for interpreter frame. */
> -LJ_FUNCA int lj_err_unwind_win(EXCEPTION_RECORD *rec,
> - void *f, CONTEXT *ctx, UndocumentedDispatcherContext *dispatch)
> -{
> -#if LJ_TARGET_X64
> - void *cf = f;
> -#else
> - void *cf = (char *)f - CFRAME_OFS_SEH;
> -#endif
> - lua_State *L = cframe_L(cf);
> - int errcode = LJ_EXCODE_CHECK(rec->ExceptionCode) ?
> - LJ_EXCODE_ERRCODE(rec->ExceptionCode) : LUA_ERRRUN;
> - if ((rec->ExceptionFlags & 6)) { /* EH_UNWINDING|EH_EXIT_UNWIND */
> - /* Unwind internal frames. */
> - err_unwind(L, cf, errcode);
> - } else {
> - void *cf2 = err_unwind(L, cf, 0);
> - if (cf2) { /* We catch it, so start unwinding the upper frames. */
> - if (rec->ExceptionCode == LJ_MSVC_EXCODE ||
> - rec->ExceptionCode == LJ_GCC_EXCODE) {
> -#if LJ_TARGET_WINDOWS
> - __DestructExceptionObject(rec, 1);
> -#endif
> - setstrV(L, L->top++, lj_err_str(L, LJ_ERR_ERRCPP));
> - } else if (!LJ_EXCODE_CHECK(rec->ExceptionCode)) {
> - /* Don't catch access violations etc. */
> - return 1; /* ExceptionContinueSearch */
> - }
> -#if LJ_TARGET_X64
> - /* 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) && errcode != LUA_YIELD) ?
> - lj_vm_unwind_ff_eh :
> - lj_vm_unwind_c_eh),
> - rec, (void *)(uintptr_t)errcode, ctx, dispatch->HistoryTable);
> - /* RtlUnwindEx should never return. */
> -#else
> - UNUSED(ctx);
> - UNUSED(dispatch);
> - /* Call all handlers for all lower C frames (including ourselves) again
> - ** with EH_UNWINDING set. Then call the specified function, passing cf
> - ** and errcode.
> - */
> - lj_vm_rtlunwind(cf, (void *)rec,
> - (cframe_unwind_ff(cf2) && errcode != LUA_YIELD) ?
> - (void *)lj_vm_unwind_ff : (void *)lj_vm_unwind_c, errcode);
> - /* lj_vm_rtlunwind does not return. */
> -#endif
> - }
> - }
> - return 1; /* ExceptionContinueSearch */
> -}
> -
> -/* Raise Windows exception. */
> -static void err_raise_ext(int errcode)
> -{
> - RaiseException(LJ_EXCODE_MAKE(errcode), 1 /* EH_NONCONTINUABLE */, 0, NULL);
> -}
> -
> #endif
>
> /* -- Error handling ------------------------------------------------------ */
> @@ -508,22 +522,23 @@ LJ_NOINLINE void LJ_FASTCALL lj_err_throw(lua_State *L, int errcode)
> {
> global_State *g = G(L);
> lj_trace_abort(g);
> - setmref(g->jit_base, NULL);
> L->status = LUA_OK;
> #if LJ_UNWIND_EXT
> - err_raise_ext(errcode);
> + err_raise_ext(g, errcode);
> /*
> ** A return from this function signals a corrupt C stack that cannot be
> ** unwound. We have no choice but to call the panic function and exit.
> **
> ** Usually this is caused by a C function without unwind information.
> - ** This should never happen on x64, but may happen if you've manually
> - ** enabled LUAJIT_UNWIND_EXTERNAL and forgot to recompile *every*
> - ** non-C++ file with -funwind-tables.
> + ** This may happen if you've manually enabled LUAJIT_UNWIND_EXTERNAL
> + ** and forgot to recompile *every* non-C++ file with -funwind-tables.
> */
> if (G(L)->panic)
> G(L)->panic(L);
> #else
> +#if LJ_HASJIT
> + setmref(g->jit_base, NULL);
> +#endif
> {
> void *cf = err_unwind(L, NULL, errcode);
> if (cframe_unwind_ff(cf))
> --
> 2.37.0 (Apple Git-136)
>
[-- Attachment #2: Type: text/html, Size: 38079 bytes --]
next prev parent reply other threads:[~2022-12-05 16:02 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <20221028092638.11506-1-max.kokryashkin@gmail.com>
[not found] ` <20221028092638.11506-6-max.kokryashkin@gmail.com>
2022-11-24 11:41 ` [Tarantool-patches] [PATCH luajit v4 5/8] OSX/ARM64: Disable unwind info Sergey Kaplun via Tarantool-patches
2022-11-30 13:05 ` Maxim Kokryashkin via Tarantool-patches
2022-12-05 21:43 ` sergos via Tarantool-patches
[not found] ` <20221028092638.11506-7-max.kokryashkin@gmail.com>
2022-11-24 11:49 ` [Tarantool-patches] [PATCH luajit v4 6/8] BSD: Fix build with BSD grep Sergey Kaplun via Tarantool-patches
2022-11-30 13:05 ` Maxim Kokryashkin via Tarantool-patches
2022-12-05 21:46 ` sergos via Tarantool-patches
[not found] ` <20221028092638.11506-8-max.kokryashkin@gmail.com>
2022-11-24 11:56 ` [Tarantool-patches] [PATCH luajit v4 7/8] Fix build with busybox grep Sergey Kaplun via Tarantool-patches
2022-11-30 13:06 ` Maxim Kokryashkin via Tarantool-patches
2022-12-05 21:51 ` sergos via Tarantool-patches
[not found] ` <20221028092638.11506-2-max.kokryashkin@gmail.com>
2022-12-05 16:01 ` sergos via Tarantool-patches [this message]
[not found] ` <20221028092638.11506-3-max.kokryashkin@gmail.com>
2022-12-05 16:06 ` [Tarantool-patches] [PATCH luajit v4 2/8] OSX: Fix build by hardcoding external frame unwinding sergos via Tarantool-patches
[not found] ` <20221028092638.11506-4-max.kokryashkin@gmail.com>
2022-12-05 16:11 ` [Tarantool-patches] [PATCH luajit v4 3/8] OSX/ARM64: Disable external unwinding for now sergos via Tarantool-patches
[not found] ` <20221028092638.11506-5-max.kokryashkin@gmail.com>
2022-11-24 11:37 ` [Tarantool-patches] [PATCH luajit v4 4/8] ARM64: Reorder interpreter stack frame and fix unwinding Sergey Kaplun via Tarantool-patches
2022-11-30 13:04 ` Maxim Kokryashkin via Tarantool-patches
2022-12-05 21:42 ` sergos via Tarantool-patches
[not found] ` <20221028092638.11506-9-max.kokryashkin@gmail.com>
2022-11-24 13:10 ` [Tarantool-patches] [PATCH luajit v4 8/8] OSX/ARM64: Fix external unwinding Sergey Kaplun via Tarantool-patches
2022-11-30 13:21 ` Maxim Kokryashkin via Tarantool-patches
2022-12-01 8:52 ` Sergey Kaplun via Tarantool-patches
2022-12-01 12:28 ` Sergey Kaplun via Tarantool-patches
2022-12-06 5:58 ` sergos via Tarantool-patches
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=122D5C22-F75B-4468-97AF-D69BCB93EA3E@tarantool.org \
--to=tarantool-patches@dev.tarantool.org \
--cc=max.kokryashkin@gmail.com \
--cc=sergos@tarantool.org \
--subject='Re: [Tarantool-patches] [PATCH luajit v4 1/8] Cleanup and enable external unwinding for more platforms.' \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox