mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-08-01 23:40:28 +00:00
Release Cosmopolitan v3.8.0
This change switches c++ exception handling from sjlj to standard dwarf. It's needed because clang for aarch64 doesn't support sjlj. It turns out that libunwind had a bare-metal configuration that made this easy to do. This change gets the new experimental cosmocc -mclang flag in a state of working so well that it can now be used to build all of llamafile and it goes 3x faster in terms of build latency, without trading away any perf. The int_fast16_t and int_fast32_t types are now always defined as 32-bit in the interest of having more abi consistency between cosmocc -mgcc and -mclang mode.
This commit is contained in:
parent
5b9862907c
commit
c9152b6f14
188 changed files with 199063 additions and 636 deletions
8
third_party/libunwind/AddressSpace.hpp
vendored
8
third_party/libunwind/AddressSpace.hpp
vendored
|
@ -94,12 +94,12 @@ namespace libunwind {
|
|||
// __eh_frame_hdr_start = SIZEOF(.eh_frame_hdr) > 0 ? ADDR(.eh_frame_hdr) : 0;
|
||||
// __eh_frame_hdr_end = SIZEOF(.eh_frame_hdr) > 0 ? . : 0;
|
||||
|
||||
extern char __eh_frame_start;
|
||||
extern char __eh_frame_end;
|
||||
extern char __eh_frame_start __attribute__((__weak__)); // [jart]
|
||||
extern char __eh_frame_end __attribute__((__weak__)); // [jart]
|
||||
|
||||
#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
|
||||
extern char __eh_frame_hdr_start;
|
||||
extern char __eh_frame_hdr_end;
|
||||
extern char __eh_frame_hdr_start __attribute__((__weak__)); // [jart]
|
||||
extern char __eh_frame_hdr_end __attribute__((__weak__)); // [jart]
|
||||
#endif
|
||||
|
||||
#elif defined(_LIBUNWIND_ARM_EHABI) && defined(_LIBUNWIND_IS_BAREMETAL)
|
||||
|
|
31
third_party/libunwind/BUILD.mk
vendored
31
third_party/libunwind/BUILD.mk
vendored
|
@ -20,6 +20,7 @@ THIRD_PARTY_LIBUNWIND_A_HDRS = \
|
|||
third_party/libunwind/include/__libunwind_config.h \
|
||||
third_party/libunwind/include/libunwind.h \
|
||||
third_party/libunwind/include/unwind.h \
|
||||
third_party/libunwind/assembly.h \
|
||||
third_party/libunwind/config.h \
|
||||
third_party/libunwind/cet_unwind.h \
|
||||
third_party/libunwind/dwarf2.h \
|
||||
|
@ -35,18 +36,23 @@ THIRD_PARTY_LIBUNWIND_A_SRCS_CC = \
|
|||
third_party/libunwind/libunwind.cc
|
||||
|
||||
THIRD_PARTY_LIBUNWIND_A_SRCS_C = \
|
||||
third_party/libunwind/Unwind-sjlj.c \
|
||||
third_party/libunwind/UnwindLevel1-gcc-ext.c \
|
||||
third_party/libunwind/UnwindLevel1.c \
|
||||
third_party/libunwind/gcc_personality_v0.c
|
||||
|
||||
THIRD_PARTY_LIBUNWIND_A_SRCS_S = \
|
||||
third_party/libunwind/UnwindRegistersRestore.S \
|
||||
third_party/libunwind/UnwindRegistersSave.S \
|
||||
|
||||
THIRD_PARTY_LIBUNWIND_A_SRCS = \
|
||||
$(THIRD_PARTY_LIBUNWIND_A_SRCS_C) \
|
||||
$(THIRD_PARTY_LIBUNWIND_A_SRCS_CC)
|
||||
$(THIRD_PARTY_LIBUNWIND_A_SRCS_CC) \
|
||||
$(THIRD_PARTY_LIBUNWIND_A_SRCS_S) \
|
||||
|
||||
THIRD_PARTY_LIBUNWIND_A_OBJS = \
|
||||
$(THIRD_PARTY_LIBUNWIND_A_SRCS_C:%.c=o/$(MODE)/%.o) \
|
||||
$(THIRD_PARTY_LIBUNWIND_A_SRCS_CC:%.cc=o/$(MODE)/%.o)
|
||||
$(THIRD_PARTY_LIBUNWIND_A_SRCS_CC:%.cc=o/$(MODE)/%.o) \
|
||||
$(THIRD_PARTY_LIBUNWIND_A_SRCS_S:%.S=o/$(MODE)/%.o) \
|
||||
|
||||
THIRD_PARTY_LIBUNWIND_A_CHECKS = \
|
||||
$(THIRD_PARTY_LIBUNWIND_A).pkg \
|
||||
|
@ -55,7 +61,9 @@ THIRD_PARTY_LIBUNWIND_A_CHECKS = \
|
|||
THIRD_PARTY_LIBUNWIND_A_DIRECTDEPS = \
|
||||
LIBC_CALLS \
|
||||
LIBC_INTRIN \
|
||||
LIBC_STDIO
|
||||
LIBC_STDIO \
|
||||
LIBC_MEM \
|
||||
LIBC_THREAD \
|
||||
|
||||
THIRD_PARTY_LIBUNWIND_A_DEPS := \
|
||||
$(call uniq,$(foreach x,$(THIRD_PARTY_LIBUNWIND_A_DIRECTDEPS),$($(x))))
|
||||
|
@ -75,7 +83,20 @@ $(THIRD_PARTY_LIBUNWIND_A_OBJS): private \
|
|||
-fno-sanitize=all \
|
||||
-ffunction-sections \
|
||||
-fdata-sections \
|
||||
-D_LIBUNWIND_USE_DLADDR=0
|
||||
-D_LIBUNWIND_USE_DLADDR=0 \
|
||||
-D_LIBUNWIND_IS_BAREMETAL=1 \
|
||||
|
||||
# avoid cyclic dependency on libcxxabi
|
||||
o/$(MODE)/third_party/libunwind/libunwind.o: \
|
||||
COPTS += \
|
||||
-fno-rtti \
|
||||
|
||||
o/$(MODE)/third_party/libunwind/UnwindRegistersRestore.o: third_party/libunwind/UnwindRegistersRestore.S
|
||||
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
|
||||
o/$(MODE)/third_party/libunwind/UnwindRegistersSave.o: third_party/libunwind/UnwindRegistersSave.S
|
||||
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
|
||||
|
||||
$(THIRD_PARTY_LIBUNWIND_A_OBJS): third_party/libunwind/BUILD.mk
|
||||
|
||||
THIRD_PARTY_LIBUNWIND_LIBS = $(foreach x,$(THIRD_PARTY_LIBUNWIND_ARTIFACTS),$($(x)))
|
||||
THIRD_PARTY_LIBUNWIND_SRCS = $(foreach x,$(THIRD_PARTY_LIBUNWIND_ARTIFACTS),$($(x)_SRCS))
|
||||
|
|
530
third_party/libunwind/Unwind-sjlj.c
vendored
530
third_party/libunwind/Unwind-sjlj.c
vendored
|
@ -1,530 +0,0 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//
|
||||
// Implements setjump-longjump based C++ exceptions
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "third_party/libunwind/include/unwind.h"
|
||||
|
||||
#include "libc/isystem/inttypes.h"
|
||||
#include "libc/isystem/stdint.h"
|
||||
#include "libc/isystem/stdbool.h"
|
||||
#include "libc/isystem/stdlib.h"
|
||||
|
||||
#include "third_party/libunwind/config.h"
|
||||
|
||||
/// With SJLJ based exceptions, any function that has a catch clause or needs to
|
||||
/// do any clean up when an exception propagates through it, needs to call
|
||||
/// \c _Unwind_SjLj_Register at the start of the function and
|
||||
/// \c _Unwind_SjLj_Unregister at the end. The register function is called with
|
||||
/// the address of a block of memory in the function's stack frame. The runtime
|
||||
/// keeps a linked list (stack) of these blocks - one per thread. The calling
|
||||
/// function also sets the personality and lsda fields of the block.
|
||||
|
||||
#if defined(_LIBUNWIND_BUILD_SJLJ_APIS)
|
||||
|
||||
typedef uintptr_t _Unwind_Word __attribute__((__mode__(__unwind_word__)));
|
||||
|
||||
struct _Unwind_FunctionContext {
|
||||
// next function in stack of handlers
|
||||
struct _Unwind_FunctionContext *prev;
|
||||
|
||||
#if defined(__ve__)
|
||||
// VE requires to store 64 bit pointers in the buffer for SjLj exception.
|
||||
// We expand the size of values defined here. This size must be matched
|
||||
// to the size returned by TargetMachine::getSjLjDataSize().
|
||||
|
||||
// set by calling function before registering to be the landing pad
|
||||
uint64_t resumeLocation;
|
||||
|
||||
// set by personality handler to be parameters passed to landing pad function
|
||||
uint64_t resumeParameters[4];
|
||||
#else
|
||||
// set by calling function before registering to be the landing pad
|
||||
uint32_t resumeLocation;
|
||||
|
||||
// set by personality handler to be parameters passed to landing pad function
|
||||
_Unwind_Word resumeParameters[4];
|
||||
#endif
|
||||
|
||||
// set by calling function before registering
|
||||
_Unwind_Personality_Fn personality; // arm offset=24
|
||||
uintptr_t lsda; // arm offset=28
|
||||
|
||||
// variable length array, contains registers to restore
|
||||
// 0 = r7, 1 = pc, 2 = sp
|
||||
void *jbuf[];
|
||||
};
|
||||
|
||||
#if defined(_LIBUNWIND_HAS_NO_THREADS)
|
||||
# define _LIBUNWIND_THREAD_LOCAL
|
||||
#else
|
||||
# if __STDC_VERSION__ >= 201112L
|
||||
# define _LIBUNWIND_THREAD_LOCAL _Thread_local
|
||||
# elif defined(_MSC_VER)
|
||||
# define _LIBUNWIND_THREAD_LOCAL __declspec(thread)
|
||||
# elif defined(__GNUC__) || defined(__clang__)
|
||||
# define _LIBUNWIND_THREAD_LOCAL __thread
|
||||
# else
|
||||
# error Unable to create thread local storage
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
#if !defined(FOR_DYLD)
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#include <System/pthread_machdep.h>
|
||||
#else
|
||||
static _LIBUNWIND_THREAD_LOCAL struct _Unwind_FunctionContext *stack = NULL;
|
||||
#endif
|
||||
|
||||
static struct _Unwind_FunctionContext *__Unwind_SjLj_GetTopOfFunctionStack() {
|
||||
#if defined(__APPLE__)
|
||||
return _pthread_getspecific_direct(__PTK_LIBC_DYLD_Unwind_SjLj_Key);
|
||||
#else
|
||||
return stack;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
__Unwind_SjLj_SetTopOfFunctionStack(struct _Unwind_FunctionContext *fc) {
|
||||
#if defined(__APPLE__)
|
||||
_pthread_setspecific_direct(__PTK_LIBC_DYLD_Unwind_SjLj_Key, fc);
|
||||
#else
|
||||
stack = fc;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/// Called at start of each function that catches exceptions
|
||||
_LIBUNWIND_EXPORT void
|
||||
_Unwind_SjLj_Register(struct _Unwind_FunctionContext *fc) {
|
||||
fc->prev = __Unwind_SjLj_GetTopOfFunctionStack();
|
||||
__Unwind_SjLj_SetTopOfFunctionStack(fc);
|
||||
}
|
||||
|
||||
|
||||
/// Called at end of each function that catches exceptions
|
||||
_LIBUNWIND_EXPORT void
|
||||
_Unwind_SjLj_Unregister(struct _Unwind_FunctionContext *fc) {
|
||||
__Unwind_SjLj_SetTopOfFunctionStack(fc->prev);
|
||||
}
|
||||
|
||||
|
||||
static _Unwind_Reason_Code
|
||||
unwind_phase1(struct _Unwind_Exception *exception_object) {
|
||||
_Unwind_FunctionContext_t c = __Unwind_SjLj_GetTopOfFunctionStack();
|
||||
_LIBUNWIND_TRACE_UNWINDING("unwind_phase1: initial function-context=%p",
|
||||
(void *)c);
|
||||
|
||||
// walk each frame looking for a place to stop
|
||||
for (bool handlerNotFound = true; handlerNotFound; c = c->prev) {
|
||||
|
||||
// check for no more frames
|
||||
if (c == NULL) {
|
||||
_LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): reached "
|
||||
"bottom => _URC_END_OF_STACK",
|
||||
(void *)exception_object);
|
||||
return _URC_END_OF_STACK;
|
||||
}
|
||||
|
||||
_LIBUNWIND_TRACE_UNWINDING("unwind_phase1: function-context=%p", (void *)c);
|
||||
// if there is a personality routine, ask it if it will want to stop at this
|
||||
// frame
|
||||
if (c->personality != NULL) {
|
||||
_LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): calling "
|
||||
"personality function %p",
|
||||
(void *)exception_object,
|
||||
(void *)c->personality);
|
||||
_Unwind_Reason_Code personalityResult = (*c->personality)(
|
||||
1, _UA_SEARCH_PHASE, exception_object->exception_class,
|
||||
exception_object, (struct _Unwind_Context *)c);
|
||||
switch (personalityResult) {
|
||||
case _URC_HANDLER_FOUND:
|
||||
// found a catch clause or locals that need destructing in this frame
|
||||
// stop search and remember function context
|
||||
handlerNotFound = false;
|
||||
exception_object->private_2 = (uintptr_t) c;
|
||||
_LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): "
|
||||
"_URC_HANDLER_FOUND",
|
||||
(void *)exception_object);
|
||||
return _URC_NO_REASON;
|
||||
|
||||
case _URC_CONTINUE_UNWIND:
|
||||
_LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): "
|
||||
"_URC_CONTINUE_UNWIND",
|
||||
(void *)exception_object);
|
||||
// continue unwinding
|
||||
break;
|
||||
|
||||
default:
|
||||
// something went wrong
|
||||
_LIBUNWIND_TRACE_UNWINDING(
|
||||
"unwind_phase1(ex_ojb=%p): _URC_FATAL_PHASE1_ERROR",
|
||||
(void *)exception_object);
|
||||
return _URC_FATAL_PHASE1_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
return _URC_NO_REASON;
|
||||
}
|
||||
|
||||
|
||||
static _Unwind_Reason_Code
|
||||
unwind_phase2(struct _Unwind_Exception *exception_object) {
|
||||
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p)",
|
||||
(void *)exception_object);
|
||||
|
||||
// walk each frame until we reach where search phase said to stop
|
||||
_Unwind_FunctionContext_t c = __Unwind_SjLj_GetTopOfFunctionStack();
|
||||
while (true) {
|
||||
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2s(ex_ojb=%p): context=%p",
|
||||
(void *)exception_object, (void *)c);
|
||||
|
||||
// check for no more frames
|
||||
if (c == NULL) {
|
||||
_LIBUNWIND_TRACE_UNWINDING(
|
||||
"unwind_phase2(ex_ojb=%p): __unw_step() reached "
|
||||
"bottom => _URC_END_OF_STACK",
|
||||
(void *)exception_object);
|
||||
return _URC_END_OF_STACK;
|
||||
}
|
||||
|
||||
// if there is a personality routine, tell it we are unwinding
|
||||
if (c->personality != NULL) {
|
||||
_Unwind_Action action = _UA_CLEANUP_PHASE;
|
||||
if ((uintptr_t) c == exception_object->private_2)
|
||||
action = (_Unwind_Action)(
|
||||
_UA_CLEANUP_PHASE |
|
||||
_UA_HANDLER_FRAME); // tell personality this was the frame it marked
|
||||
// in phase 1
|
||||
_Unwind_Reason_Code personalityResult =
|
||||
(*c->personality)(1, action, exception_object->exception_class,
|
||||
exception_object, (struct _Unwind_Context *)c);
|
||||
switch (personalityResult) {
|
||||
case _URC_CONTINUE_UNWIND:
|
||||
// continue unwinding
|
||||
_LIBUNWIND_TRACE_UNWINDING(
|
||||
"unwind_phase2(ex_ojb=%p): _URC_CONTINUE_UNWIND",
|
||||
(void *)exception_object);
|
||||
if ((uintptr_t) c == exception_object->private_2) {
|
||||
// phase 1 said we would stop at this frame, but we did not...
|
||||
_LIBUNWIND_ABORT("during phase1 personality function said it would "
|
||||
"stop here, but now if phase2 it did not stop here");
|
||||
}
|
||||
break;
|
||||
case _URC_INSTALL_CONTEXT:
|
||||
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): "
|
||||
"_URC_INSTALL_CONTEXT, will resume at "
|
||||
"landing pad %p",
|
||||
(void *)exception_object, c->jbuf[1]);
|
||||
// personality routine says to transfer control to landing pad
|
||||
// we may get control back if landing pad calls _Unwind_Resume()
|
||||
__Unwind_SjLj_SetTopOfFunctionStack(c);
|
||||
__builtin_longjmp(c->jbuf, 1);
|
||||
// __unw_resume() only returns if there was an error
|
||||
return _URC_FATAL_PHASE2_ERROR;
|
||||
default:
|
||||
// something went wrong
|
||||
_LIBUNWIND_DEBUG_LOG("personality function returned unknown result %d",
|
||||
personalityResult);
|
||||
return _URC_FATAL_PHASE2_ERROR;
|
||||
}
|
||||
}
|
||||
c = c->prev;
|
||||
}
|
||||
|
||||
// clean up phase did not resume at the frame that the search phase said it
|
||||
// would
|
||||
return _URC_FATAL_PHASE2_ERROR;
|
||||
}
|
||||
|
||||
|
||||
static _Unwind_Reason_Code
|
||||
unwind_phase2_forced(struct _Unwind_Exception *exception_object,
|
||||
_Unwind_Stop_Fn stop, void *stop_parameter) {
|
||||
// walk each frame until we reach where search phase said to stop
|
||||
_Unwind_FunctionContext_t c = __Unwind_SjLj_GetTopOfFunctionStack();
|
||||
while (true) {
|
||||
|
||||
// get next frame (skip over first which is _Unwind_RaiseException)
|
||||
if (c == NULL) {
|
||||
_LIBUNWIND_TRACE_UNWINDING(
|
||||
"unwind_phase2(ex_ojb=%p): __unw_step() reached "
|
||||
"bottom => _URC_END_OF_STACK",
|
||||
(void *)exception_object);
|
||||
return _URC_END_OF_STACK;
|
||||
}
|
||||
|
||||
// call stop function at each frame
|
||||
_Unwind_Action action =
|
||||
(_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE);
|
||||
_Unwind_Reason_Code stopResult =
|
||||
(*stop)(1, action, exception_object->exception_class, exception_object,
|
||||
(struct _Unwind_Context *)c, stop_parameter);
|
||||
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
|
||||
"stop function returned %d",
|
||||
(void *)exception_object, stopResult);
|
||||
if (stopResult != _URC_NO_REASON) {
|
||||
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
|
||||
"stopped by stop function",
|
||||
(void *)exception_object);
|
||||
return _URC_FATAL_PHASE2_ERROR;
|
||||
}
|
||||
|
||||
// if there is a personality routine, tell it we are unwinding
|
||||
if (c->personality != NULL) {
|
||||
_Unwind_Personality_Fn p = (_Unwind_Personality_Fn)c->personality;
|
||||
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
|
||||
"calling personality function %p",
|
||||
(void *)exception_object, (void *)p);
|
||||
_Unwind_Reason_Code personalityResult =
|
||||
(*p)(1, action, exception_object->exception_class, exception_object,
|
||||
(struct _Unwind_Context *)c);
|
||||
switch (personalityResult) {
|
||||
case _URC_CONTINUE_UNWIND:
|
||||
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
|
||||
"personality returned _URC_CONTINUE_UNWIND",
|
||||
(void *)exception_object);
|
||||
// destructors called, continue unwinding
|
||||
break;
|
||||
case _URC_INSTALL_CONTEXT:
|
||||
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
|
||||
"personality returned _URC_INSTALL_CONTEXT",
|
||||
(void *)exception_object);
|
||||
// we may get control back if landing pad calls _Unwind_Resume()
|
||||
__Unwind_SjLj_SetTopOfFunctionStack(c);
|
||||
__builtin_longjmp(c->jbuf, 1);
|
||||
break;
|
||||
default:
|
||||
// something went wrong
|
||||
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
|
||||
"personality returned %d, "
|
||||
"_URC_FATAL_PHASE2_ERROR",
|
||||
(void *)exception_object, personalityResult);
|
||||
return _URC_FATAL_PHASE2_ERROR;
|
||||
}
|
||||
}
|
||||
c = c->prev;
|
||||
}
|
||||
|
||||
// call stop function one last time and tell it we've reached the end of the
|
||||
// stack
|
||||
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): calling stop "
|
||||
"function with _UA_END_OF_STACK",
|
||||
(void *)exception_object);
|
||||
_Unwind_Action lastAction =
|
||||
(_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE | _UA_END_OF_STACK);
|
||||
(*stop)(1, lastAction, exception_object->exception_class, exception_object,
|
||||
(struct _Unwind_Context *)c, stop_parameter);
|
||||
|
||||
// clean up phase did not resume at the frame that the search phase said it
|
||||
// would
|
||||
return _URC_FATAL_PHASE2_ERROR;
|
||||
}
|
||||
|
||||
|
||||
/// Called by __cxa_throw. Only returns if there is a fatal error
|
||||
_LIBUNWIND_EXPORT _Unwind_Reason_Code
|
||||
_Unwind_SjLj_RaiseException(struct _Unwind_Exception *exception_object) {
|
||||
_LIBUNWIND_TRACE_API("_Unwind_SjLj_RaiseException(ex_obj=%p)",
|
||||
(void *)exception_object);
|
||||
|
||||
// mark that this is a non-forced unwind, so _Unwind_Resume() can do the right
|
||||
// thing
|
||||
exception_object->private_1 = 0;
|
||||
exception_object->private_2 = 0;
|
||||
|
||||
// phase 1: the search phase
|
||||
_Unwind_Reason_Code phase1 = unwind_phase1(exception_object);
|
||||
if (phase1 != _URC_NO_REASON)
|
||||
return phase1;
|
||||
|
||||
// phase 2: the clean up phase
|
||||
return unwind_phase2(exception_object);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// When _Unwind_RaiseException() is in phase2, it hands control
|
||||
/// to the personality function at each frame. The personality
|
||||
/// may force a jump to a landing pad in that function, the landing
|
||||
/// pad code may then call _Unwind_Resume() to continue with the
|
||||
/// unwinding. Note: the call to _Unwind_Resume() is from compiler
|
||||
/// generated user code. All other _Unwind_* routines are called
|
||||
/// by the C++ runtime __cxa_* routines.
|
||||
///
|
||||
/// Re-throwing an exception is implemented by having the code call
|
||||
/// __cxa_rethrow() which in turn calls _Unwind_Resume_or_Rethrow()
|
||||
_LIBUNWIND_EXPORT void
|
||||
_Unwind_SjLj_Resume(struct _Unwind_Exception *exception_object) {
|
||||
_LIBUNWIND_TRACE_API("_Unwind_SjLj_Resume(ex_obj=%p)",
|
||||
(void *)exception_object);
|
||||
|
||||
if (exception_object->private_1 != 0)
|
||||
unwind_phase2_forced(exception_object,
|
||||
(_Unwind_Stop_Fn) exception_object->private_1,
|
||||
(void *)exception_object->private_2);
|
||||
else
|
||||
unwind_phase2(exception_object);
|
||||
|
||||
// clients assume _Unwind_Resume() does not return, so all we can do is abort.
|
||||
_LIBUNWIND_ABORT("_Unwind_SjLj_Resume() can't return");
|
||||
}
|
||||
|
||||
|
||||
/// Called by __cxa_rethrow().
|
||||
_LIBUNWIND_EXPORT _Unwind_Reason_Code
|
||||
_Unwind_SjLj_Resume_or_Rethrow(struct _Unwind_Exception *exception_object) {
|
||||
_LIBUNWIND_TRACE_API("__Unwind_SjLj_Resume_or_Rethrow(ex_obj=%p), "
|
||||
"private_1=%" PRIuPTR,
|
||||
(void *)exception_object, exception_object->private_1);
|
||||
// If this is non-forced and a stopping place was found, then this is a
|
||||
// re-throw.
|
||||
// Call _Unwind_RaiseException() as if this was a new exception.
|
||||
if (exception_object->private_1 == 0) {
|
||||
return _Unwind_SjLj_RaiseException(exception_object);
|
||||
// should return if there is no catch clause, so that __cxa_rethrow can call
|
||||
// std::terminate()
|
||||
}
|
||||
|
||||
// Call through to _Unwind_Resume() which distinguishes between forced and
|
||||
// regular exceptions.
|
||||
_Unwind_SjLj_Resume(exception_object);
|
||||
_LIBUNWIND_ABORT("__Unwind_SjLj_Resume_or_Rethrow() called "
|
||||
"_Unwind_SjLj_Resume() which unexpectedly returned");
|
||||
}
|
||||
|
||||
|
||||
/// Called by personality handler during phase 2 to get LSDA for current frame.
|
||||
_LIBUNWIND_EXPORT uintptr_t
|
||||
_Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) {
|
||||
_Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
|
||||
_LIBUNWIND_TRACE_API("_Unwind_GetLanguageSpecificData(context=%p) "
|
||||
"=> 0x%" PRIuPTR,
|
||||
(void *)context, ufc->lsda);
|
||||
return ufc->lsda;
|
||||
}
|
||||
|
||||
|
||||
/// Called by personality handler during phase 2 to get register values.
|
||||
_LIBUNWIND_EXPORT uintptr_t _Unwind_GetGR(struct _Unwind_Context *context,
|
||||
int index) {
|
||||
_LIBUNWIND_TRACE_API("_Unwind_GetGR(context=%p, reg=%d)", (void *)context,
|
||||
index);
|
||||
_Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
|
||||
return ufc->resumeParameters[index];
|
||||
}
|
||||
|
||||
|
||||
/// Called by personality handler during phase 2 to alter register values.
|
||||
_LIBUNWIND_EXPORT void _Unwind_SetGR(struct _Unwind_Context *context, int index,
|
||||
uintptr_t new_value) {
|
||||
_LIBUNWIND_TRACE_API("_Unwind_SetGR(context=%p, reg=%d, value=0x%" PRIuPTR
|
||||
")",
|
||||
(void *)context, index, new_value);
|
||||
_Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
|
||||
ufc->resumeParameters[index] = new_value;
|
||||
}
|
||||
|
||||
|
||||
/// Called by personality handler during phase 2 to get instruction pointer.
|
||||
_LIBUNWIND_EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) {
|
||||
_Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
|
||||
_LIBUNWIND_TRACE_API("_Unwind_GetIP(context=%p) => 0x%" PRIu32,
|
||||
(void *)context, ufc->resumeLocation + 1);
|
||||
return ufc->resumeLocation + 1;
|
||||
}
|
||||
|
||||
|
||||
/// Called by personality handler during phase 2 to get instruction pointer.
|
||||
/// ipBefore is a boolean that says if IP is already adjusted to be the call
|
||||
/// site address. Normally IP is the return address.
|
||||
_LIBUNWIND_EXPORT uintptr_t _Unwind_GetIPInfo(struct _Unwind_Context *context,
|
||||
int *ipBefore) {
|
||||
_Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
|
||||
*ipBefore = 0;
|
||||
_LIBUNWIND_TRACE_API("_Unwind_GetIPInfo(context=%p, %p) => 0x%" PRIu32,
|
||||
(void *)context, (void *)ipBefore,
|
||||
ufc->resumeLocation + 1);
|
||||
return ufc->resumeLocation + 1;
|
||||
}
|
||||
|
||||
|
||||
/// Called by personality handler during phase 2 to alter instruction pointer.
|
||||
_LIBUNWIND_EXPORT void _Unwind_SetIP(struct _Unwind_Context *context,
|
||||
uintptr_t new_value) {
|
||||
_LIBUNWIND_TRACE_API("_Unwind_SetIP(context=%p, value=0x%" PRIuPTR ")",
|
||||
(void *)context, new_value);
|
||||
_Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
|
||||
ufc->resumeLocation = new_value - 1;
|
||||
}
|
||||
|
||||
|
||||
/// Called by personality handler during phase 2 to find the start of the
|
||||
/// function.
|
||||
_LIBUNWIND_EXPORT uintptr_t
|
||||
_Unwind_GetRegionStart(struct _Unwind_Context *context) {
|
||||
// Not supported or needed for sjlj based unwinding
|
||||
(void)context;
|
||||
_LIBUNWIND_TRACE_API("_Unwind_GetRegionStart(context=%p)", (void *)context);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/// Called by personality handler during phase 2 if a foreign exception
|
||||
/// is caught.
|
||||
_LIBUNWIND_EXPORT void
|
||||
_Unwind_DeleteException(struct _Unwind_Exception *exception_object) {
|
||||
_LIBUNWIND_TRACE_API("_Unwind_DeleteException(ex_obj=%p)",
|
||||
(void *)exception_object);
|
||||
if (exception_object->exception_cleanup != NULL)
|
||||
(*exception_object->exception_cleanup)(_URC_FOREIGN_EXCEPTION_CAUGHT,
|
||||
exception_object);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// Called by personality handler during phase 2 to get base address for data
|
||||
/// relative encodings.
|
||||
_LIBUNWIND_EXPORT uintptr_t
|
||||
_Unwind_GetDataRelBase(struct _Unwind_Context *context) {
|
||||
// Not supported or needed for sjlj based unwinding
|
||||
(void)context;
|
||||
_LIBUNWIND_TRACE_API("_Unwind_GetDataRelBase(context=%p)", (void *)context);
|
||||
_LIBUNWIND_ABORT("_Unwind_GetDataRelBase() not implemented");
|
||||
}
|
||||
|
||||
|
||||
/// Called by personality handler during phase 2 to get base address for text
|
||||
/// relative encodings.
|
||||
_LIBUNWIND_EXPORT uintptr_t
|
||||
_Unwind_GetTextRelBase(struct _Unwind_Context *context) {
|
||||
// Not supported or needed for sjlj based unwinding
|
||||
(void)context;
|
||||
_LIBUNWIND_TRACE_API("_Unwind_GetTextRelBase(context=%p)", (void *)context);
|
||||
_LIBUNWIND_ABORT("_Unwind_GetTextRelBase() not implemented");
|
||||
}
|
||||
|
||||
|
||||
/// Called by personality handler to get "Call Frame Area" for current frame.
|
||||
_LIBUNWIND_EXPORT uintptr_t _Unwind_GetCFA(struct _Unwind_Context *context) {
|
||||
_LIBUNWIND_TRACE_API("_Unwind_GetCFA(context=%p)", (void *)context);
|
||||
if (context != NULL) {
|
||||
_Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
|
||||
// Setjmp/longjmp based exceptions don't have a true CFA.
|
||||
// Instead, the SP in the jmpbuf is the closest approximation.
|
||||
return (uintptr_t) ufc->jbuf[2];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // defined(_LIBUNWIND_BUILD_SJLJ_APIS)
|
1256
third_party/libunwind/UnwindRegistersRestore.S
vendored
Normal file
1256
third_party/libunwind/UnwindRegistersRestore.S
vendored
Normal file
File diff suppressed because it is too large
Load diff
1186
third_party/libunwind/UnwindRegistersSave.S
vendored
Normal file
1186
third_party/libunwind/UnwindRegistersSave.S
vendored
Normal file
File diff suppressed because it is too large
Load diff
303
third_party/libunwind/assembly.h
vendored
Normal file
303
third_party/libunwind/assembly.h
vendored
Normal file
|
@ -0,0 +1,303 @@
|
|||
/* ===-- assembly.h - libUnwind assembler support macros -------------------===
|
||||
*
|
||||
* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
* See https://llvm.org/LICENSE.txt for license information.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*
|
||||
* This file defines macros for use in libUnwind assembler source.
|
||||
* This file is not part of the interface of this library.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*/
|
||||
|
||||
#ifndef UNWIND_ASSEMBLY_H
|
||||
#define UNWIND_ASSEMBLY_H
|
||||
|
||||
#if defined(__linux__) && defined(__CET__)
|
||||
#include <cet.h>
|
||||
#define _LIBUNWIND_CET_ENDBR _CET_ENDBR
|
||||
#else
|
||||
#define _LIBUNWIND_CET_ENDBR
|
||||
#endif
|
||||
|
||||
#if defined(__powerpc64__)
|
||||
#define SEPARATOR ;
|
||||
#define PPC64_OFFS_SRR0 0
|
||||
#define PPC64_OFFS_CR 272
|
||||
#define PPC64_OFFS_XER 280
|
||||
#define PPC64_OFFS_LR 288
|
||||
#define PPC64_OFFS_CTR 296
|
||||
#define PPC64_OFFS_VRSAVE 304
|
||||
#define PPC64_OFFS_FP 312
|
||||
#define PPC64_OFFS_V 824
|
||||
#elif defined(__APPLE__) && defined(__aarch64__)
|
||||
#define SEPARATOR %%
|
||||
#elif defined(__riscv)
|
||||
# define RISCV_ISIZE (__riscv_xlen / 8)
|
||||
# define RISCV_FOFFSET (RISCV_ISIZE * 32)
|
||||
# if defined(__riscv_flen)
|
||||
# define RISCV_FSIZE (__riscv_flen / 8)
|
||||
# endif
|
||||
|
||||
# if __riscv_xlen == 64
|
||||
# define ILOAD ld
|
||||
# define ISTORE sd
|
||||
# elif __riscv_xlen == 32
|
||||
# define ILOAD lw
|
||||
# define ISTORE sw
|
||||
# else
|
||||
# error "Unsupported __riscv_xlen"
|
||||
# endif
|
||||
|
||||
# if defined(__riscv_flen)
|
||||
# if __riscv_flen == 64
|
||||
# define FLOAD fld
|
||||
# define FSTORE fsd
|
||||
# elif __riscv_flen == 32
|
||||
# define FLOAD flw
|
||||
# define FSTORE fsw
|
||||
# else
|
||||
# error "Unsupported __riscv_flen"
|
||||
# endif
|
||||
# endif
|
||||
# define SEPARATOR ;
|
||||
#else
|
||||
#define SEPARATOR ;
|
||||
#endif
|
||||
|
||||
#if defined(__powerpc64__) && (!defined(_CALL_ELF) || _CALL_ELF == 1) && \
|
||||
!defined(_AIX)
|
||||
#define PPC64_OPD1 .section .opd,"aw",@progbits SEPARATOR
|
||||
#define PPC64_OPD2 SEPARATOR \
|
||||
.p2align 3 SEPARATOR \
|
||||
.quad .Lfunc_begin0 SEPARATOR \
|
||||
.quad .TOC.@tocbase SEPARATOR \
|
||||
.quad 0 SEPARATOR \
|
||||
.text SEPARATOR \
|
||||
.Lfunc_begin0:
|
||||
#else
|
||||
#define PPC64_OPD1
|
||||
#define PPC64_OPD2
|
||||
#endif
|
||||
|
||||
#if defined(__aarch64__)
|
||||
#if defined(__ARM_FEATURE_GCS_DEFAULT) && defined(__ARM_FEATURE_BTI_DEFAULT)
|
||||
// Set BTI, PAC, and GCS gnu property bits
|
||||
#define GNU_PROPERTY 7
|
||||
// We indirectly branch to __libunwind_Registers_arm64_jumpto from
|
||||
// __unw_phase2_resume, so we need to use bti jc.
|
||||
#define AARCH64_BTI bti jc
|
||||
#elif defined(__ARM_FEATURE_GCS_DEFAULT)
|
||||
// Set GCS gnu property bit
|
||||
#define GNU_PROPERTY 4
|
||||
#elif defined(__ARM_FEATURE_BTI_DEFAULT)
|
||||
// Set BTI and PAC gnu property bits
|
||||
#define GNU_PROPERTY 3
|
||||
#define AARCH64_BTI bti c
|
||||
#endif
|
||||
#ifdef GNU_PROPERTY
|
||||
.pushsection ".note.gnu.property", "a" SEPARATOR \
|
||||
.balign 8 SEPARATOR \
|
||||
.long 4 SEPARATOR \
|
||||
.long 0x10 SEPARATOR \
|
||||
.long 0x5 SEPARATOR \
|
||||
.asciz "GNU" SEPARATOR \
|
||||
.long 0xc0000000 SEPARATOR /* GNU_PROPERTY_AARCH64_FEATURE_1_AND */ \
|
||||
.long 4 SEPARATOR \
|
||||
.long GNU_PROPERTY SEPARATOR \
|
||||
.long 0 SEPARATOR \
|
||||
.popsection SEPARATOR
|
||||
#endif
|
||||
#endif
|
||||
#if !defined(AARCH64_BTI)
|
||||
#define AARCH64_BTI
|
||||
#endif
|
||||
|
||||
#if !defined(__aarch64__)
|
||||
#ifdef __ARM_FEATURE_PAC_DEFAULT
|
||||
.eabi_attribute Tag_PAC_extension, 2
|
||||
.eabi_attribute Tag_PACRET_use, 1
|
||||
#endif
|
||||
#ifdef __ARM_FEATURE_BTI_DEFAULT
|
||||
.eabi_attribute Tag_BTI_extension, 1
|
||||
.eabi_attribute Tag_BTI_use, 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define GLUE2(a, b) a ## b
|
||||
#define GLUE(a, b) GLUE2(a, b)
|
||||
#define SYMBOL_NAME(name) GLUE(__USER_LABEL_PREFIX__, name)
|
||||
|
||||
#if defined(__APPLE__)
|
||||
|
||||
#define SYMBOL_IS_FUNC(name)
|
||||
#define HIDDEN_SYMBOL(name) .private_extern name
|
||||
#if defined(_LIBUNWIND_HIDE_SYMBOLS)
|
||||
#define EXPORT_SYMBOL(name) HIDDEN_SYMBOL(name)
|
||||
#else
|
||||
#define EXPORT_SYMBOL(name)
|
||||
#endif
|
||||
#define WEAK_ALIAS(name, aliasname) \
|
||||
.globl SYMBOL_NAME(aliasname) SEPARATOR \
|
||||
EXPORT_SYMBOL(SYMBOL_NAME(aliasname)) SEPARATOR \
|
||||
SYMBOL_NAME(aliasname) = SYMBOL_NAME(name)
|
||||
|
||||
#define NO_EXEC_STACK_DIRECTIVE
|
||||
|
||||
#elif defined(__ELF__)
|
||||
|
||||
#if defined(__arm__)
|
||||
#define SYMBOL_IS_FUNC(name) .type name,%function
|
||||
#else
|
||||
#define SYMBOL_IS_FUNC(name) .type name,@function
|
||||
#endif
|
||||
#define HIDDEN_SYMBOL(name) .hidden name
|
||||
#if defined(_LIBUNWIND_HIDE_SYMBOLS)
|
||||
#define EXPORT_SYMBOL(name) HIDDEN_SYMBOL(name)
|
||||
#else
|
||||
#define EXPORT_SYMBOL(name)
|
||||
#endif
|
||||
#define WEAK_SYMBOL(name) .weak name
|
||||
|
||||
#if defined(__hexagon__)
|
||||
#define WEAK_ALIAS(name, aliasname) \
|
||||
EXPORT_SYMBOL(SYMBOL_NAME(aliasname)) SEPARATOR \
|
||||
WEAK_SYMBOL(SYMBOL_NAME(aliasname)) SEPARATOR \
|
||||
.equiv SYMBOL_NAME(aliasname), SYMBOL_NAME(name)
|
||||
#else
|
||||
#define WEAK_ALIAS(name, aliasname) \
|
||||
EXPORT_SYMBOL(SYMBOL_NAME(aliasname)) SEPARATOR \
|
||||
WEAK_SYMBOL(SYMBOL_NAME(aliasname)) SEPARATOR \
|
||||
SYMBOL_NAME(aliasname) = SYMBOL_NAME(name)
|
||||
#endif
|
||||
|
||||
#if defined(__GNU__) || defined(__FreeBSD__) || defined(__Fuchsia__) || \
|
||||
defined(__linux__)
|
||||
#define NO_EXEC_STACK_DIRECTIVE .section .note.GNU-stack,"",%progbits
|
||||
#else
|
||||
#define NO_EXEC_STACK_DIRECTIVE
|
||||
#endif
|
||||
|
||||
#elif defined(_WIN32)
|
||||
|
||||
#define SYMBOL_IS_FUNC(name) \
|
||||
.def name SEPARATOR \
|
||||
.scl 2 SEPARATOR \
|
||||
.type 32 SEPARATOR \
|
||||
.endef
|
||||
#define EXPORT_SYMBOL2(name) \
|
||||
.section .drectve,"yn" SEPARATOR \
|
||||
.ascii "-export:", #name, "\0" SEPARATOR \
|
||||
.text
|
||||
#if defined(_LIBUNWIND_HIDE_SYMBOLS)
|
||||
#define EXPORT_SYMBOL(name)
|
||||
#else
|
||||
#define EXPORT_SYMBOL(name) EXPORT_SYMBOL2(name)
|
||||
#endif
|
||||
#define HIDDEN_SYMBOL(name)
|
||||
|
||||
#if defined(__MINGW32__)
|
||||
#define WEAK_ALIAS(name, aliasname) \
|
||||
.globl SYMBOL_NAME(aliasname) SEPARATOR \
|
||||
EXPORT_SYMBOL(aliasname) SEPARATOR \
|
||||
SYMBOL_NAME(aliasname) = SYMBOL_NAME(name)
|
||||
#else
|
||||
#define WEAK_ALIAS3(name, aliasname) \
|
||||
.section .drectve,"yn" SEPARATOR \
|
||||
.ascii "-alternatename:", #aliasname, "=", #name, "\0" SEPARATOR \
|
||||
.text
|
||||
#define WEAK_ALIAS2(name, aliasname) \
|
||||
WEAK_ALIAS3(name, aliasname)
|
||||
#define WEAK_ALIAS(name, aliasname) \
|
||||
EXPORT_SYMBOL(SYMBOL_NAME(aliasname)) SEPARATOR \
|
||||
WEAK_ALIAS2(SYMBOL_NAME(name), SYMBOL_NAME(aliasname))
|
||||
#endif
|
||||
|
||||
#define NO_EXEC_STACK_DIRECTIVE
|
||||
|
||||
#elif defined(__sparc__)
|
||||
|
||||
#elif defined(_AIX)
|
||||
|
||||
#if defined(__powerpc64__)
|
||||
#define VBYTE_LEN 8
|
||||
#define CSECT_ALIGN 3
|
||||
#else
|
||||
#define VBYTE_LEN 4
|
||||
#define CSECT_ALIGN 2
|
||||
#endif
|
||||
|
||||
// clang-format off
|
||||
#define DEFINE_LIBUNWIND_FUNCTION_AND_WEAK_ALIAS(name, aliasname) \
|
||||
.csect .text[PR], 2 SEPARATOR \
|
||||
.csect .name[PR], 2 SEPARATOR \
|
||||
.globl name[DS] SEPARATOR \
|
||||
.globl .name[PR] SEPARATOR \
|
||||
.align 4 SEPARATOR \
|
||||
.csect name[DS], CSECT_ALIGN SEPARATOR \
|
||||
aliasname: \
|
||||
.vbyte VBYTE_LEN, .name[PR] SEPARATOR \
|
||||
.vbyte VBYTE_LEN, TOC[TC0] SEPARATOR \
|
||||
.vbyte VBYTE_LEN, 0 SEPARATOR \
|
||||
.weak aliasname SEPARATOR \
|
||||
.weak .aliasname SEPARATOR \
|
||||
.csect .name[PR], 2 SEPARATOR \
|
||||
.aliasname: \
|
||||
|
||||
#define WEAK_ALIAS(name, aliasname)
|
||||
#define NO_EXEC_STACK_DIRECTIVE
|
||||
|
||||
// clang-format on
|
||||
#else
|
||||
|
||||
#error Unsupported target
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(_AIX)
|
||||
// clang-format off
|
||||
#define DEFINE_LIBUNWIND_FUNCTION(name) \
|
||||
.globl name[DS] SEPARATOR \
|
||||
.globl .name SEPARATOR \
|
||||
.align 4 SEPARATOR \
|
||||
.csect name[DS], CSECT_ALIGN SEPARATOR \
|
||||
.vbyte VBYTE_LEN, .name SEPARATOR \
|
||||
.vbyte VBYTE_LEN, TOC[TC0] SEPARATOR \
|
||||
.vbyte VBYTE_LEN, 0 SEPARATOR \
|
||||
.csect .text[PR], 2 SEPARATOR \
|
||||
.name:
|
||||
// clang-format on
|
||||
#else
|
||||
#define DEFINE_LIBUNWIND_FUNCTION(name) \
|
||||
.globl SYMBOL_NAME(name) SEPARATOR \
|
||||
HIDDEN_SYMBOL(SYMBOL_NAME(name)) SEPARATOR \
|
||||
SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \
|
||||
PPC64_OPD1 \
|
||||
SYMBOL_NAME(name): \
|
||||
PPC64_OPD2 \
|
||||
AARCH64_BTI
|
||||
#endif
|
||||
|
||||
#if defined(__arm__)
|
||||
#if !defined(__ARM_ARCH)
|
||||
#define __ARM_ARCH 4
|
||||
#endif
|
||||
|
||||
#if defined(__ARM_ARCH_4T__) || __ARM_ARCH >= 5
|
||||
#define ARM_HAS_BX
|
||||
#endif
|
||||
|
||||
#ifdef ARM_HAS_BX
|
||||
#define JMP(r) bx r
|
||||
#else
|
||||
#define JMP(r) mov pc, r
|
||||
#endif
|
||||
#endif /* __arm__ */
|
||||
|
||||
#if defined(__powerpc__)
|
||||
#define PPC_LEFT_SHIFT(index) << (index)
|
||||
#endif
|
||||
|
||||
#endif /* UNWIND_ASSEMBLY_H */
|
2
third_party/libunwind/libunwind.cc
vendored
2
third_party/libunwind/libunwind.cc
vendored
|
@ -321,7 +321,7 @@ void __unw_remove_dynamic_fde(unw_word_t fde) {
|
|||
void __unw_add_dynamic_eh_frame_section(unw_word_t eh_frame_start) {
|
||||
// The eh_frame section start serves as the mh_group
|
||||
unw_word_t mh_group = eh_frame_start;
|
||||
CFI_Parser<LocalAddressSpace>::CIE_Info cieInfo;
|
||||
CFI_Parser<LocalAddressSpace>::CIE_Info cieInfo = {};
|
||||
CFI_Parser<LocalAddressSpace>::FDE_Info fdeInfo;
|
||||
auto p = (LocalAddressSpace::pint_t)eh_frame_start;
|
||||
while (true) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue