Tarantool development patches archive
 help / color / mirror / Atom feed
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 --]

  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-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-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-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