public inbox for cygwin-cvs@sourceware.org
help / color / mirror / Atom feed
* [newlib-cygwin] Cygwin: drop i686 exception handling
@ 2022-05-17 12:12 Corinna Vinschen
0 siblings, 0 replies; only message in thread
From: Corinna Vinschen @ 2022-05-17 12:12 UTC (permalink / raw)
To: cygwin-cvs
https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=93bea9f5387921ec40f35c0c45ff240a433db603
commit 93bea9f5387921ec40f35c0c45ff240a433db603
Author: Corinna Vinschen <corinna@vinschen.de>
Date: Tue May 17 14:12:32 2022 +0200
Cygwin: drop i686 exception handling
Leave x86_64 CPU-specific code and #error out when trying to build
for another target. Access special registers CPU-agnostic.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
Diff:
---
winsup/cygwin/cygtls.h | 72 +--------
winsup/cygwin/exception.h | 121 ---------------
winsup/cygwin/exceptions.cc | 363 +++++++++-----------------------------------
3 files changed, 72 insertions(+), 484 deletions(-)
diff --git a/winsup/cygwin/cygtls.h b/winsup/cygwin/cygtls.h
index c4702e88a..bfd358268 100644
--- a/winsup/cygwin/cygtls.h
+++ b/winsup/cygwin/cygtls.h
@@ -276,7 +276,6 @@ private:
extern _cygtls *_main_tls;
extern _cygtls *_sig_tls;
-#ifdef __x86_64__
class san
{
san *_clemente;
@@ -305,53 +304,9 @@ public:
earlier in the function, so this call serves as a register barrier. */
void leave () __attribute__ ((returns_twice));
};
-#else
-class san
-{
- san *_clemente;
- jmp_buf _context;
- uint32_t _c_cnt;
- uint32_t _w_cnt;
-public:
- int setup () __attribute__ ((always_inline))
- {
- _clemente = _my_tls.andreas;
- _my_tls.andreas = this;
- _c_cnt = _my_tls.locals.pathbufs.c_cnt;
- _w_cnt = _my_tls.locals.pathbufs.w_cnt;
- return __sjfault (_context);
- }
- void leave () __attribute__ ((always_inline))
- {
- /* Restore tls_pathbuf counters in case of error. */
- _my_tls.locals.pathbufs.c_cnt = _c_cnt;
- _my_tls.locals.pathbufs.w_cnt = _w_cnt;
- __ljfault (_context, 1);
- }
- void reset () __attribute__ ((always_inline))
- {
- _my_tls.andreas = _clemente;
- }
-};
-class myfault
-{
- san sebastian;
-public:
- ~myfault () __attribute__ ((always_inline)) { sebastian.reset (); }
- inline int faulted () __attribute__ ((always_inline))
- {
- return sebastian.setup ();
- }
-};
-#endif
-
-/* Exception handling macros. These are required because SEH differs a lot
- between 32 and 64 bit. Essentially, on 64 bit, we have to create compile
- time SEH tables which define the handler and try/except labels, while on
- 32 bit we can simply set up an SJLJ handler within the myfault class. */
+/* Exception handling macros. This is a handmade SEH try/except. */
#define __mem_barrier __asm__ __volatile__ ("" ::: "memory")
-#ifdef __x86_64__
#define __try \
{ \
__label__ __l_try, __l_except, __l_endtry; \
@@ -387,31 +342,6 @@ public:
__mem_barrier; \
}
-#else /* !__x86_64__ */
-#define __try \
- { \
- __label__ __l_endtry; \
- myfault efault; \
- if (!efault.faulted ()) \
- {
-
-#define __leave \
- goto __l_endtry
-
-#define __except(__errno) \
- goto __l_endtry; \
- } \
- { \
- if (__errno) \
- set_errno (__errno);
-
-#define __endtry \
- } \
- __l_endtry: \
- __mem_barrier; \
- }
-#endif /* __x86_64__ */
-
class wait_signal_arrived
{
public:
diff --git a/winsup/cygwin/exception.h b/winsup/cygwin/exception.h
index ffff7464b..13159d17b 100644
--- a/winsup/cygwin/exception.h
+++ b/winsup/cygwin/exception.h
@@ -6,125 +6,6 @@ details. */
#pragma once
-#ifdef __i386__
-/* Documentation on the innards of 32 bit Windows exception handling (i.e.
- from the perspective of a compiler implementor) apparently doesn't exist.
- However, the following came from Onno Hovers <onno@stack.urc.tue.nl>
-
-The first pointer to the chain of handlers is in the thread environment block
-at FS:[0]. This chain has the following format:
-
-typedef struct __EXCEPTION_FRAME
-{
- struct __EXCEPTION_FRAME *Prev; /-* pointer to the previous frame *-/
- PEXCEPTION_HANDLER Handler; /-* handler function *-/
-}
-
-You register an exception handler in your compiler with this simple ASM
-sequence:
- PUSH _MyExceptionHandler
- PUSH FS:[0]
- MOV FS:[0],ESP
-An exception frame MUST be on the stack! The frame may have more fields and
-both Visual C++ and Borland C++ use more fields for themselves.
-
-When an exception occurs the system calls all handlers starting with the
-handler at FS:0, and then the previous etc. until one handler returns
-ExceptionContinueExecution, which is 0. If a handler does not want to handle
-the exception it should just return ExceptionContinueSearch, which is 1.
-
-The handler has the following parameters:
-ehandler (
- PEXCEPTION_RECORD erecord,
- PEXCEPTION_FRAME myframe,
- PCONTEXT context, /-* context before and after *-/
- PVOID dispatch) /-* something *-/
-
-When a handler wants to handle the exception, it has some alternatives:
-
--one is to do do something about the exception condition, like emulating
-an invalid instruction, mapping memory where there was a page fault, etc.
-If the handler wants to have the context of the thread that causes the
-exception changed, it should make that change in the context passed to the
-handler.
-
--the second alternative is to call all exception handlers again, indicating
-that you want them to clean up. This way all the __finally blocks get
-executed. After doing that you change the context passed to the handler so
-the code starts executing in the except block. For this purpose you could
-call RtlUnwind. This (undocumented) function calls all exception handlers
-up to but not including the exception frame passed to it. If NULL is passed
-as exception frame RtlUnwind calls all exception handlers and then exits the
-process. The parameters to RtlUnwind are:
-
-RtlUnwind (
- PEXCEPTION_FRAME endframe,
- PVOID unusedEip,
- PEXCEPTION_RECORD erecord,
- DWORD returnEax)
-
-You should set unusedEip to the address where RtlUnwind should return like
-this:
- PUSH 0
- PUSH OFFSET ReturnUnwind
- PUSH 0
- PUSH 0
- CALL RtlUnwind
-ReturnUnwind:
- .....
-
-If no EXCEPTION_RECORD is passed, RtlUnwind makes a default exception
-record. In any case, the ExceptionFlags part of this record has the
-EH_UNWINDING (=2), flag set. (and EH_EXIT_UNWIND (=4), when NULL is passed as the end
-frame.).
-
-The handler for a exception as well as a for unwinds may be executed in the
-thread causing the exception, but may also be executed in another (special
-exception) thread. So it is not wise to make any assumptions about that!
-
-As an alternative you may consider the SetUnhandledExceptionFilter API
-to install your own exception filter. This one is documented.
-*/
-
-/* The January 1994 MSJ has an article entitled "Clearer, More Comprehensive
- Error Processing with Win32 Structured Exception Handling". It goes into
- a teensy bit of detail of the innards of exception handling (i.e. what we
- have to do). */
-
-typedef EXCEPTION_DISPOSITION (exception_handler) (EXCEPTION_RECORD *,
- struct _exception_list *,
- CONTEXT *,
- void *);
-
-typedef struct _exception_list
-{
- struct _exception_list *prev;
- exception_handler *handler;
-} exception_list;
-
-extern exception_list *_except_list asm ("%fs:0");
-typedef void *PDISPATCHER_CONTEXT;
-
-class exception
-{
- exception_list el;
- exception_list *save;
- static EXCEPTION_DISPOSITION handle (EXCEPTION_RECORD *, exception_list *,
- CONTEXT *, PDISPATCHER_CONTEXT);
-public:
- exception () __attribute__ ((always_inline))
- {
- /* Install SEH handler. */
- save = _except_list;
- el.handler = handle;
- el.prev = _except_list;
- _except_list = ⪙
- };
- ~exception () __attribute__ ((always_inline)) { _except_list = save; }
-};
-
-#else /* !__i386__ */
-
#define exception_list void
typedef struct _DISPATCHER_CONTEXT *PDISPATCHER_CONTEXT;
@@ -159,8 +40,6 @@ public:
LONG CALLBACK myfault_altstack_handler (EXCEPTION_POINTERS *);
-#endif /* __i386__ */
-
class cygwin_exception
{
PUINT_PTR framep;
diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc
index f6c390241..2fecd52ec 100644
--- a/winsup/cygwin/exceptions.cc
+++ b/winsup/cygwin/exceptions.cc
@@ -30,15 +30,21 @@ details. */
#include "posix_timer.h"
#include "gcc_seh.h"
-/* Definitions for code simplification */
+/* Define macros for CPU-agnostic register access. The _CX_foo
+ macros are for access into CONTEXT, the _MC_foo ones for access into
+ mcontext. The idea is to access the registers in terms of their job,
+ not in terms of their name on the given target. */
#ifdef __x86_64__
-# define _GR(reg) R ## reg
-# define _AFMT "%011X"
-# define _ADDR DWORD64
+#define _CX_instPtr Rip
+#define _CX_stackPtr Rsp
+#define _CX_framePtr Rbp
+/* For special register access inside mcontext. */
+#define _MC_retReg rax
+#define _MC_instPtr rip
+#define _MC_stackPtr rsp
+#define _MC_uclinkReg rbx /* MUST be callee-saved reg */
#else
-# define _GR(reg) E ## reg
-# define _AFMT "%08x"
-# define _ADDR DWORD
+#error unimplemented for this target
#endif
#define CALL_HANDLER_RETRY_OUTER 10
@@ -204,20 +210,12 @@ cygwin_exception::dump_exception ()
small_printf ("rbp=%016X rsp=%016X\r\n", ctx->Rbp, ctx->Rsp);
small_printf ("program=%W, pid %u, thread %s\r\n",
myself->progname, myself->pid, mythreadname ());
-#else
- if (exception_name)
- small_printf ("Exception: %s at eip=%08x\r\n", exception_name, ctx->Eip);
- else
- small_printf ("Signal %d at eip=%08x\r\n", e->ExceptionCode, ctx->Eip);
- small_printf ("eax=%08x ebx=%08x ecx=%08x edx=%08x esi=%08x edi=%08x\r\n",
- ctx->Eax, ctx->Ebx, ctx->Ecx, ctx->Edx, ctx->Esi, ctx->Edi);
- small_printf ("ebp=%08x esp=%08x program=%W, pid %u, thread %s\r\n",
- ctx->Ebp, ctx->Esp, myself->progname, myself->pid,
- mythreadname ());
-#endif
small_printf ("cs=%04x ds=%04x es=%04x fs=%04x gs=%04x ss=%04x\r\n",
ctx->SegCs, ctx->SegDs, ctx->SegEs, ctx->SegFs,
ctx->SegGs, ctx->SegSs);
+#else
+#error unimplemented for this target
+#endif
}
/* A class for manipulating the stack. */
@@ -227,11 +225,9 @@ class stack_info
char *next_offset () {return *((char **) sf.AddrFrame.Offset);}
bool needargs;
PUINT_PTR dummy_frame;
-#ifdef __x86_64__
CONTEXT c;
UNWIND_HISTORY_TABLE hist;
__tlsstack_t *sigstackptr;
-#endif
public:
STACKFRAME sf; /* For storing the stack information */
void init (PUINT_PTR, bool, PCONTEXT); /* Called the first time that stack info is needed */
@@ -250,7 +246,6 @@ static NO_COPY stack_info thestack;
void
stack_info::init (PUINT_PTR framep, bool wantargs, PCONTEXT ctx)
{
-#ifdef __x86_64__
memset (&hist, 0, sizeof hist);
if (ctx)
memcpy (&c, ctx, sizeof c);
@@ -260,7 +255,6 @@ stack_info::init (PUINT_PTR framep, bool wantargs, PCONTEXT ctx)
c.ContextFlags = CONTEXT_ALL;
}
sigstackptr = _my_tls.stackptr;
-#endif
memset (&sf, 0, sizeof (sf));
if (ctx)
sf.AddrFrame.Offset = (UINT_PTR) framep;
@@ -277,7 +271,6 @@ stack_info::init (PUINT_PTR framep, bool wantargs, PCONTEXT ctx)
extern "C" void _cygwin_exit_return ();
-#ifdef __x86_64__
static inline void
__unwind_single_frame (PCONTEXT ctx)
{
@@ -287,19 +280,16 @@ __unwind_single_frame (PCONTEXT ctx)
DWORD64 establisher;
PVOID hdl;
- f = RtlLookupFunctionEntry (ctx->Rip, &imagebase, &hist);
+ f = RtlLookupFunctionEntry (ctx->_CX_instPtr, &imagebase, &hist);
if (f)
- RtlVirtualUnwind (0, imagebase, ctx->Rip, f, ctx, &hdl, &establisher,
- NULL);
+ RtlVirtualUnwind (0, imagebase, ctx->_CX_instPtr, f, ctx, &hdl,
+ &establisher, NULL);
else
{
- ctx->Rip = *(ULONG_PTR *) ctx->Rsp;
- ctx->Rsp += 8;
+ ctx->_CX_instPtr = *(ULONG_PTR *) ctx->_CX_stackPtr;
+ ctx->_CX_stackPtr += 8;
}
}
-#else
-#define __unwind_single_frame(ctx)
-#endif
/* Walk the stack.
@@ -308,57 +298,30 @@ __unwind_single_frame (PCONTEXT ctx)
int
stack_info::walk ()
{
-#ifdef __x86_64__
- if (!c.Rip)
+ if (!c._CX_instPtr)
return 0;
- sf.AddrPC.Offset = c.Rip;
- sf.AddrStack.Offset = c.Rsp;
- sf.AddrFrame.Offset = c.Rbp;
+ sf.AddrPC.Offset = c._CX_instPtr;
+ sf.AddrStack.Offset = c._CX_stackPtr;
+ sf.AddrFrame.Offset = c._CX_framePtr;
- if ((c.Rip >= (DWORD64)&_sigbe) && (c.Rip < (DWORD64)&_sigdelayed_end))
+ if ((c._CX_instPtr >= (DWORD64)&_sigbe)
+ && (c._CX_instPtr < (DWORD64)&_sigdelayed_end))
{
/* _sigbe and sigdelayed don't have SEH unwinding data, so virtually
unwind the tls sigstack */
- c.Rip = sigstackptr[-1];
+ c._CX_instPtr = sigstackptr[-1];
sigstackptr--;
return 1;
}
__unwind_single_frame (&c);
- if (needargs && c.Rip)
+ if (needargs && c._CX_instPtr)
{
- PULONG_PTR p = (PULONG_PTR) c.Rsp;
+ PULONG_PTR p = (PULONG_PTR) c._CX_stackPtr;
for (unsigned i = 0; i < NPARAMS; ++i)
sf.Params[i] = p[i + 1];
}
return 1;
-#else
- char **framep;
-
- if ((void (*) ()) sf.AddrPC.Offset == _cygwin_exit_return)
- return 0; /* stack frames are exhausted */
-
- if (((framep = (char **) next_offset ()) == NULL)
- || (framep >= (char **) cygwin_hmodule))
- return 0;
-
- sf.AddrFrame.Offset = (_ADDR) framep;
- sf.AddrPC.Offset = sf.AddrReturn.Offset;
-
- /* The return address always follows the stack pointer */
- sf.AddrReturn.Offset = (_ADDR) *++framep;
-
- if (needargs)
- {
- unsigned nparams = NPARAMS;
-
- /* The arguments follow the return address */
- sf.Params[0] = (_ADDR) *++framep;
- for (unsigned i = 1; i < nparams; i++)
- sf.Params[i] = (_ADDR) *++framep;
- }
- return 1;
-#endif
}
void
@@ -379,17 +342,13 @@ cygwin_exception::dumpstack ()
int i;
thestack.init (framep, 1, ctx); /* Initialize from the input CONTEXT */
-#ifdef __x86_64__
small_printf ("Stack trace:\r\nFrame Function Args\r\n");
-#else
- small_printf ("Stack trace:\r\nFrame Function Args\r\n");
-#endif
for (i = 0; i < DUMPSTACK_FRAME_LIMIT && thestack++; i++)
{
- small_printf (_AFMT " " _AFMT, thestack.sf.AddrFrame.Offset,
+ small_printf ("%011X %011X", thestack.sf.AddrFrame.Offset,
thestack.sf.AddrPC.Offset);
for (unsigned j = 0; j < NPARAMS; j++)
- small_printf ("%s" _AFMT, j == 0 ? " (" : ", ",
+ small_printf ("%s%011X", j == 0 ? " (" : ", ",
thestack.sf.Params[j]);
small_printf (")\r\n");
}
@@ -413,8 +372,8 @@ _cygtls::inside_kernel (CONTEXT *cx)
return true;
memset (&m, 0, sizeof m);
- if (!VirtualQuery ((LPCVOID) cx->_GR(ip), &m, sizeof m))
- sigproc_printf ("couldn't get memory info, pc %p, %E", cx->_GR(ip));
+ if (!VirtualQuery ((LPCVOID) cx->_CX_instPtr, &m, sizeof m))
+ sigproc_printf ("couldn't get memory info, pc %p, %E", cx->_CX_instPtr);
size_t size = (windows_system_directory_length + 6) * sizeof (WCHAR);
PWCHAR checkdir = (PWCHAR) alloca (size);
@@ -439,7 +398,7 @@ _cygtls::inside_kernel (CONTEXT *cx)
res = wcsncasecmp (windows_system_directory, checkdir,
windows_system_directory_length) == 0;
}
- sigproc_printf ("pc %p, h %p, inside_kernel %d", cx->_GR(ip), h, res);
+ sigproc_printf ("pc %p, h %p, inside_kernel %d", cx->_CX_instPtr, h, res);
# undef h
return res;
}
@@ -451,7 +410,7 @@ cygwin_stackdump ()
CONTEXT c;
c.ContextFlags = CONTEXT_FULL;
RtlCaptureContext (&c);
- cygwin_exception exc ((PUINT_PTR) c._GR(bp), &c);
+ cygwin_exception exc ((PUINT_PTR) c._CX_framePtr, &c);
exc.dumpstack ();
}
@@ -548,35 +507,6 @@ try_to_debug ()
return dbg;
}
-#ifdef __x86_64__
-/* Don't unwind the stack on x86_64. It's not necessary to do that from the
- exception handler. */
-#define rtl_unwind(el,er)
-#else
-static void __reg3 rtl_unwind (exception_list *, PEXCEPTION_RECORD)
- __attribute__ ((noinline, regparm (3)));
-
-void __reg3
-rtl_unwind (exception_list *frame, PEXCEPTION_RECORD e)
-{
- __asm__ ("\n\
- pushl %%ebx \n\
- pushl %%edi \n\
- pushl %%esi \n\
- pushl $0 \n\
- pushl %1 \n\
- pushl $1f \n\
- pushl %0 \n\
- call _RtlUnwind@16 \n\
-1: \n\
- popl %%esi \n\
- popl %%edi \n\
- popl %%ebx \n\
-": : "r" (frame), "r" (e));
-}
-#endif /* __x86_64 */
-
-#ifdef __x86_64__
/* myfault exception handler. */
EXCEPTION_DISPOSITION
exception::myfault (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT *in,
@@ -610,16 +540,14 @@ myfault_altstack_handler (EXCEPTION_POINTERS *exc)
/* Unwind the stack manually and call RtlRestoreContext. This
is necessary because RtlUnwindEx checks the stack for validity,
which, as outlined above, fails for the alternate stack. */
- while (c->Rsp < me.andreas->frame)
+ while (c->_CX_stackPtr < me.andreas->frame)
__unwind_single_frame (c);
- c->Rip = me.andreas->ret;
+ c->_CX_instPtr = me.andreas->ret;
RtlRestoreContext (c, NULL);
}
return EXCEPTION_CONTINUE_SEARCH;
}
-#endif
-
/* Main exception handler. */
EXCEPTION_DISPOSITION
exception::handle (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT *in,
@@ -628,11 +556,6 @@ exception::handle (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT *in,
static int NO_COPY debugging = 0;
_cygtls& me = _my_tls;
-#ifdef __i386__
- if (me.andreas)
- me.andreas->leave (); /* Return from a "san" caught fault */
-#endif
-
if (debugging && ++debugging < 500000)
{
SetThreadPriority (hMainThread, THREAD_PRIORITY_NORMAL);
@@ -759,7 +682,6 @@ exception::handle (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT *in,
handling. */
return ExceptionContinueExecution;
-#ifdef __x86_64__
case STATUS_GCC_THROW:
case STATUS_GCC_UNWIND:
case STATUS_GCC_FORCED:
@@ -767,7 +689,6 @@ exception::handle (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT *in,
_Unwind_RaiseException(), GCC expects us to continue all the
(continuable) GCC exceptions that reach us. */
return ExceptionContinueExecution;
-#endif
default:
/* If we don't recognize the exception, we have to assume that
@@ -777,40 +698,21 @@ exception::handle (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT *in,
}
debug_printf ("In cygwin_except_handler exception %y at %p sp %p",
- e->ExceptionCode, in->_GR(ip), in->_GR(sp));
+ e->ExceptionCode, in->_CX_instPtr, in->_CX_stackPtr);
debug_printf ("In cygwin_except_handler signal %d at %p",
- si.si_signo, in->_GR(ip));
+ si.si_signo, in->_CX_instPtr);
-#ifdef __x86_64__
- PUINT_PTR framep = (PUINT_PTR) in->Rbp;
- /* Sometimes, when a stack is screwed up, Rbp tends to be NULL. In that
- case, base the stacktrace on Rsp. In most cases, it allows to generate
- useful stack trace. */
+ PUINT_PTR framep = (PUINT_PTR) in->_CX_framePtr;
+ /* Sometimes, when a stack is screwed up, the frame pointer tends to be NULL.
+ In that case, base the stacktrace on the stack pointer. In most cases,
+ it allows to generate useful stack trace. */
if (!framep)
- framep = (PUINT_PTR) in->Rsp;
-#else
- PUINT_PTR framep = (PUINT_PTR) in->_GR(sp);
- for (PUINT_PTR bpend = (PUINT_PTR) __builtin_frame_address (0);
- framep > bpend;
- framep--)
- if (*framep == in->SegCs && framep[-1] == in->_GR(ip))
- {
- framep -= 2;
- break;
- }
-
- /* Temporarily replace windows top level SEH with our own handler.
- We don't want any Windows magic kicking in. This top level frame
- will be removed automatically after our exception handler returns. */
- _except_list->handler = handle;
-#endif
+ framep = (PUINT_PTR) in->_CX_stackPtr;
if (exit_state >= ES_SIGNAL_EXIT
&& (NTSTATUS) e->ExceptionCode != STATUS_CONTROL_C_EXIT)
api_fatal ("Exception during process exit");
- else if (!try_to_debug ())
- rtl_unwind (frame, e);
- else
+ else if (try_to_debug ())
{
debugging = 1;
return ExceptionContinueExecution;
@@ -823,7 +725,7 @@ exception::handle (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT *in,
be the address of the faulting instruction. Other signals are apparently
undefined so we just set those to the faulting instruction too. */
si.si_addr = (si.si_signo == SIGSEGV || si.si_signo == SIGBUS)
- ? (void *) e->ExceptionInformation[1] : (void *) in->_GR(ip);
+ ? (void *) e->ExceptionInformation[1] : (void *) in->_CX_instPtr;
me.incyg++;
sig_send (NULL, si, &me); /* Signal myself */
if ((NTSTATUS) e->ExceptionCode == STATUS_STACK_OVERFLOW)
@@ -928,7 +830,7 @@ _cygtls::interrupt_now (CONTEXT *cx, siginfo_t& si, void *handler,
interrupted = false;
else
{
- _ADDR &ip = cx->_GR(ip);
+ DWORD64 &ip = cx->_CX_instPtr;
push (ip);
interrupt_setup (si, handler, siga);
ip = pop ();
@@ -1364,13 +1266,8 @@ signal_exit (int sig, siginfo_t *si, void *)
{
CONTEXT c;
c.ContextFlags = CONTEXT_FULL;
-#ifdef __x86_64__
RtlCaptureContext (&c);
cygwin_exception exc ((PUINT_PTR) __builtin_frame_address (0), &c);
-#else
- GetThreadContext (GetCurrentThread (), &c);
- cygwin_exception exc ((PUINT_PTR) __builtin_frame_address (0), &c);
-#endif
exc.dumpstack ();
}
break;
@@ -1691,7 +1588,7 @@ _cygtls::call_signal_handler ()
{
/* Software-generated signal. We're fetching the current
context, unwind to the caller and in case we're called
- from sigdelayed, fix rip/eip accordingly. */
+ from sigdelayed, fix the instruction pointer accordingly. */
context.uc_mcontext.ctxflags = CONTEXT_FULL;
RtlCaptureContext ((PCONTEXT) &context.uc_mcontext);
__unwind_single_frame ((PCONTEXT) &context.uc_mcontext);
@@ -1700,7 +1597,7 @@ _cygtls::call_signal_handler ()
#ifdef __x86_64__
context.uc_mcontext.rip = retaddr ();
#else
- context.uc_mcontext.eip = retaddr ();
+#error unimplemented for this target
#endif
}
}
@@ -1808,39 +1705,7 @@ _cygtls::call_signal_handler ()
[WRAPPER] "o" (altstack_wrapper)
: "memory");
#else
- /* Clobbered regs: ecx, edx, ebp, esp */
- __asm__ ("\n\
- movl %[NEW_SP], %%eax # Load alt stack into eax \n\
- subl $32, %%eax # Make room on alt stack for \n\
- # clobbered regs and args to \n\
- # signal handler \n\
- movl %%ecx, 16(%%eax) # Save clobbered regs \n\
- movl %%edx, 20(%%eax) \n\
- movl %%ebp, 24(%%eax) \n\
- movl %%esp, 28(%%eax) \n\
- movl %[SIG], %%ecx # thissig to 1st arg slot \n\
- movl %%ecx, (%%eax) \n\
- leal %[SI], %%ecx # &thissi to 2nd arg slot \n\
- movl %%ecx, 4(%%eax) \n\
- movl %[CTX], %%ecx # thiscontext to 3rd arg slot\n\
- movl %%ecx, 8(%%eax) \n\
- movl %[FUNC], %%ecx # thisfunc to 4th arg slot \n\
- movl %%ecx, 12(%%eax) \n\
- leal %[WRAPPER], %%ecx # thisfunc to ecx \n\
- movl %%eax, %%esp # Move alt stack into esp \n\
- call *%%ecx # Call thisfunc \n\
- movl %%esp, %%eax # Restore clobbered regs \n\
- movl 28(%%eax), %%esp \n\
- movl 24(%%eax), %%ebp \n\
- movl 20(%%eax), %%edx \n\
- movl 16(%%eax), %%eax \n"
- : : [NEW_SP] "o" (new_sp),
- [SIG] "o" (thissig),
- [SI] "o" (thissi),
- [CTX] "o" (thiscontext),
- [FUNC] "o" (thisfunc),
- [WRAPPER] "o" (altstack_wrapper)
- : "memory");
+#error unimplemented for this target
#endif
}
else
@@ -1885,11 +1750,7 @@ _cygtls::signal_debugger (siginfo_t& si)
if (GetThreadContext (th, &c))
{
if (incyg)
-#ifdef __x86_64__
- c.Rip = retaddr ();
-#else
- c.Eip = retaddr ();
-#endif
+ c._CX_instPtr = retaddr ();
memcpy (&context.uc_mcontext, &c, sizeof (CONTEXT));
/* Enough space for 32/64 bit addresses */
char sigmsg[2 * sizeof (_CYGWIN_SIGNAL_STRING
@@ -1908,20 +1769,12 @@ setcontext (const ucontext_t *ucp)
PCONTEXT ctx = (PCONTEXT) &ucp->uc_mcontext;
set_signal_mask (_my_tls.sigmask, ucp->uc_sigmask);
_my_tls.incyg = true;
-#ifdef __x86_64__
- /* Apparently a call to NtContinue works on 64 bit as well, but using
- RtlRestoreContext is the blessed way. */
RtlRestoreContext (ctx, NULL);
-#else
- NtContinue (ctx, FALSE);
-#endif
/* If we got here, something was wrong. */
set_errno (EINVAL);
return -1;
}
-#ifdef __x86_64__
-
extern "C" int
getcontext (ucontext_t *ucp)
{
@@ -1929,14 +1782,13 @@ getcontext (ucontext_t *ucp)
ctx->ContextFlags = CONTEXT_FULL;
RtlCaptureContext (ctx);
__unwind_single_frame (ctx);
- /* Successful getcontext is supposed to return 0. If we don't set rax to 0
- here, there's a chance that code like this:
+ /* Successful getcontext is supposed to return 0. If we don't set the
+ return register to 0 here, there's a chance that code like this:
if (getcontext (&ctx) != 0)
- assumes that getcontext failed after calling setcontext (&ctx).
- Same goes for eax on 32 bit, see assembler implementation below. */
- ucp->uc_mcontext.rax = 0;
+ assumes that getcontext failed after calling setcontext (&ctx). */
+ ucp->uc_mcontext._MC_retReg = 0;
ucp->uc_sigmask = ucp->uc_mcontext.oldmask = _my_tls.sigmask;
/* Do not touch any other member of ucontext_t. */
return 0;
@@ -1950,14 +1802,16 @@ swapcontext (ucontext_t *oucp, const ucontext_t *ucp)
RtlCaptureContext (ctx);
__unwind_single_frame (ctx);
/* See comment in getcontext. */
- oucp->uc_mcontext.rax = 0;
+ oucp->uc_mcontext._MC_retReg = 0;
oucp->uc_sigmask = oucp->uc_mcontext.oldmask = _my_tls.sigmask;
return setcontext (ucp);
}
/* Trampoline function to set the context to uc_link. The pointer to the
- address of uc_link is stored in the callee-saved register $rbx. If uc_link
- is NULL, call exit. */
+ address of uc_link is stored in a callee-saved register, referenced by
+ _MC_uclinkReg from the C code. If uc_link is NULL, call exit. */
+#ifdef __x86_64__
+/* _MC_uclinkReg == %rbx */
__asm__ (" \n\
.global __cont_link_context \n\
.seh_proc __cont_link_context \n\
@@ -1979,77 +1833,7 @@ __cont_link_context: \n\
");
#else
-
-/* On 32 bit it's crucial to call RtlCaptureContext in a way which makes sure
- the callee-saved registers, especially $ebx, are not changed by the calling
- function. If so, makecontext/__cont_link_context would be broken.
-
- Amazing, but true: While on 64 bit RtlCaptureContext returns the exact
- context of its own caller, as expected, on 32 bit RtlCaptureContext returns
- the context of the callers caller. So while we have to unwind another frame
- on 64 bit, we can skip this step on 32 bit.
-
- Both functions are split into the first half in assembler, and the second
- half in C to allow easy access to _my_tls. */
-
-extern "C" int
-__getcontext (ucontext_t *ucp)
-{
- ucp->uc_mcontext.eax = 0;
- ucp->uc_sigmask = ucp->uc_mcontext.oldmask = _my_tls.sigmask;
- return 0;
-}
-
-__asm__ (" \n\
- .global _getcontext \n\
-_getcontext: \n\
- pushl %ebp \n\
- movl %esp, %ebp \n\
- movl 8(%esp), %eax \n\
- pushl %eax \n\
- call _RtlCaptureContext@4 \n\
- popl %ebp \n\
- jmp ___getcontext \n\
- nop \n\
- ");
-
-extern "C" int
-__swapcontext (ucontext_t *oucp, const ucontext_t *ucp)
-{
- oucp->uc_mcontext.eax = 0;
- oucp->uc_sigmask = oucp->uc_mcontext.oldmask = _my_tls.sigmask;
- return setcontext (ucp);
-}
-
-__asm__ (" \n\
- .global _swapcontext \n\
-_swapcontext: \n\
- pushl %ebp \n\
- movl %esp, %ebp \n\
- movl 8(%esp), %eax \n\
- pushl %eax \n\
- call _RtlCaptureContext@4 \n\
- popl %ebp \n\
- jmp ___swapcontext \n\
- nop \n\
- ");
-
-/* Trampoline function to set the context to uc_link. The pointer to the
- address of uc_link is stored in the callee-saved register $ebx. If uc_link
- is NULL, call exit. */
-__asm__ (" \n\
- .global ___cont_link_context \n\
-___cont_link_context: \n\
- movl %ebx, %esp \n\
- movl (%esp), %eax \n\
- testl %eax, %eax \n\
- je 1f \n\
- call _setcontext \n\
- movl $0xff, (%esp) \n\
-1: \n\
- call _cygwin_exit \n\
- nop \n\
- ");
+#error unimplemented for this target
#endif
/* makecontext is modelled after GLibc's makecontext. The stack from uc_stack
@@ -2079,7 +1863,7 @@ makecontext (ucontext_t *ucp, void (*func) (void), int argc, ...)
sp[0] = (uintptr_t) __cont_link_context;
/* Fetch arguments and store them on the stack.
- x86_64 only:
+ x86_64:
- Store first four args in the AMD64 ABI arg registers.
@@ -2114,23 +1898,18 @@ makecontext (ucontext_t *ucp, void (*func) (void), int argc, ...)
break;
}
#else
- sp[i + 1] = va_arg (ap, uintptr_t);
+#error unimplemented for this target
#endif
va_end (ap);
/* Store pointer to uc_link at the top of the stack. */
sp[argc + 1] = (uintptr_t) ucp->uc_link;
/* Last but not least set the register in the context at ucp so that a
subsequent setcontext or swapcontext picks up the right values:
- - Set rip/eip to the target function.
- - Set rsp/esp to the just computed stack pointer value.
- - Set rbx/ebx to the address of the pointer to uc_link. */
-#ifdef __x86_64__
- ucp->uc_mcontext.rip = (uint64_t) func;
- ucp->uc_mcontext.rsp = (uint64_t) sp;
- ucp->uc_mcontext.rbx = (uint64_t) (sp + argc + 1);
-#else
- ucp->uc_mcontext.eip = (uint32_t) func;
- ucp->uc_mcontext.esp = (uint32_t) sp;
- ucp->uc_mcontext.ebx = (uint32_t) (sp + argc + 1);
-#endif
+ - Set instruction pointer to the target function.
+ - Set stack pointer to the just computed stack pointer value.
+ - Set Cygwin-specific uclink register to the address of the pointer
+ to uc_link. */
+ ucp->uc_mcontext._MC_instPtr = (uint64_t) func;
+ ucp->uc_mcontext._MC_stackPtr = (uint64_t) sp;
+ ucp->uc_mcontext._MC_uclinkReg = (uint64_t) (sp + argc + 1);
}
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2022-05-17 12:12 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-05-17 12:12 [newlib-cygwin] Cygwin: drop i686 exception handling Corinna Vinschen
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).