aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgrischka <grischka>2010-10-19 13:15:06 +0200
committergrischka <grischka>2010-10-19 13:15:06 +0200
commit9228842fa75190665241bf1d3bb3f8f74d2ffdbb (patch)
tree6845dc58312bc8a51c33749466273b1039ebaaca
parent036d94112d4f0db6eb82b79bbfd0c9ef2328df34 (diff)
downloadtinycc-9228842fa75190665241bf1d3bb3f8f74d2ffdbb.tar.gz
tinycc-9228842fa75190665241bf1d3bb3f8f74d2ffdbb.tar.bz2
win32: register SEH in startup code (i386 only)
Needed to handle signal() etc. with msvcrt
-rw-r--r--win32/include/_mingw.h2
-rw-r--r--win32/lib/chkstk.S122
-rw-r--r--win32/lib/crt1.c3
-rw-r--r--win32/lib/wincrt1.c1
4 files changed, 126 insertions, 2 deletions
diff --git a/win32/include/_mingw.h b/win32/include/_mingw.h
index 7a1891c..e8e9561 100644
--- a/win32/include/_mingw.h
+++ b/win32/include/_mingw.h
@@ -70,11 +70,13 @@
#define __x86_64 1
#define USE_MINGW_SETJMP_TWO_ARGS
#define mingw_getsp tinyc_getbp
+#define __TRY__
#else
#define __stdcall __attribute__((__stdcall__))
#define _X86_ 1
#define WIN32 1
#define _USE_32BIT_TIME_T
+#define __TRY__ void __try__(void**), *_sehrec[6]; __try__(_sehrec);
#endif
/* in stddef.h */
diff --git a/win32/lib/chkstk.S b/win32/lib/chkstk.S
index a757b16..5791aaa 100644
--- a/win32/lib/chkstk.S
+++ b/win32/lib/chkstk.S
@@ -75,3 +75,125 @@ t1:
/* ---------------------------------------------- */
#endif
/* ---------------------------------------------- */
+
+
+/* ---------------------------------------------- */
+#ifndef TCC_TARGET_X86_64
+/* ---------------------------------------------- */
+
+/*
+ int _except_handler3(
+ PEXCEPTION_RECORD exception_record,
+ PEXCEPTION_REGISTRATION registration,
+ PCONTEXT context,
+ PEXCEPTION_REGISTRATION dispatcher
+ );
+
+ int __cdecl _XcptFilter(
+ unsigned long xcptnum,
+ PEXCEPTION_POINTERS pxcptinfoptrs
+ );
+
+ struct _sehrec {
+ void *esp; // 0
+ void *exception_pointers; // 1
+ void *prev; // 2
+ void *handler; // 3
+ void *scopetable; // 4
+ int trylevel; // 5
+ void *ebp // 6
+ };
+
+ // this is what the assembler code below means:
+ __try
+ {
+ // ...
+ }
+ __except (_XcptFilter(GetExceptionCode(), GetExceptionInformation()))
+ {
+ exit(GetExceptionCode());
+ }
+*/
+
+.globl _exception_info
+_exception_info:
+ mov 1*4-24(%ebp),%eax
+ ret
+
+.globl _exception_code
+_exception_code:
+ call _exception_info
+ mov (%eax),%eax
+ mov (%eax),%eax
+ ret
+
+seh_filter:
+ call _exception_info
+ push %eax
+ call _exception_code
+ push %eax
+ call _XcptFilter
+ add $ 8,%esp
+ ret
+
+seh_except:
+ mov 0*4-24(%ebp),%esp
+ call _exception_code
+ push %eax
+ call _exit
+
+// msvcrt wants scopetables aligned and in read-only segment (using .text)
+.align 4
+seh_scopetable:
+ .long -1
+ .long seh_filter
+ .long seh_except
+
+seh_handler:
+ jmp _except_handler3
+
+.globl __try__
+__try__:
+ push %ebp
+ mov 8(%esp),%ebp
+
+// void *esp;
+ lea 12(%esp),%eax
+ mov %eax,0*4(%ebp)
+
+// void *exception_pointers;
+ xor %eax,%eax
+ mov %eax,1*4(%ebp)
+
+// void *prev;
+ mov %fs:0,%eax
+ mov %eax,2*4(%ebp)
+
+// void *handler;
+ mov $ seh_handler,%eax
+ mov %eax,3*4(%ebp)
+
+// void *scopetable;
+ mov $ seh_scopetable,%eax
+ mov %eax,4*4(%ebp)
+
+// int trylevel;
+ xor %eax,%eax
+ mov %eax,5*4(%ebp)
+
+// register new SEH
+ lea 2*4(%ebp),%eax
+ mov %eax,%fs:0
+
+ pop %ebp
+ ret
+
+/* ---------------------------------------------- */
+#else
+/* ---------------------------------------------- */
+
+/* SEH on x86-64 not implemented */
+
+/* ---------------------------------------------- */
+#endif
+/* ---------------------------------------------- */
diff --git a/win32/lib/crt1.c b/win32/lib/crt1.c
index 2e18c2b..3e1d17f 100644
--- a/win32/lib/crt1.c
+++ b/win32/lib/crt1.c
@@ -15,11 +15,11 @@ typedef struct
} _startupinfo;
void __getmainargs(int *pargc, char ***pargv, char ***penv, int globb, _startupinfo*);
-
int main(int argc, char **argv, char **env);
int _start(void)
{
+ __TRY__
int argc; char **argv; char **env; int ret;
_startupinfo start_info = {0};
@@ -32,4 +32,3 @@ int _start(void)
}
// =============================================
-
diff --git a/win32/lib/wincrt1.c b/win32/lib/wincrt1.c
index 212f9d4..0466da9 100644
--- a/win32/lib/wincrt1.c
+++ b/win32/lib/wincrt1.c
@@ -10,6 +10,7 @@ void _controlfp(unsigned a, unsigned b);
int _winstart(void)
{
+ __TRY__
char *szCmd;
STARTUPINFO startinfo;
int fShow;