summaryrefslogtreecommitdiff
path: root/mcon.c
diff options
context:
space:
mode:
Diffstat (limited to 'mcon.c')
-rw-r--r--mcon.c382
1 files changed, 379 insertions, 3 deletions
diff --git a/mcon.c b/mcon.c
index add8c69..594c6a6 100644
--- a/mcon.c
+++ b/mcon.c
@@ -7,6 +7,7 @@
#define NEW_HEADERS
#define G_POWER
#define FLUSH_PORT_BUFFER
+#define STACK_OVERFLOW_EXCEPTION_HANDLER
#ifdef MACHO
# define NEWLINE_CHAR '\r'
@@ -45,6 +46,170 @@ extern void sprintf (char *,...);
#ifndef NEW_HEADERS
# include <OSEvents.h>
#endif
+#ifdef STACK_OVERFLOW_EXCEPTION_HANDLER
+# ifdef MACHO
+# include <mach/mach.h>
+# else
+# include <Files.h>
+# include <Folders.h>
+# include <CFBundle.h>
+# include <CFNumber.h>
+# include <CFURL.h>
+# define SIGBUS 10
+# define SIGSEGV 11
+# define SIG_DFL (void (*)())0
+# define SIG_IGN (void (*)())1
+ struct sigaction {
+ void (*sa_handler)();
+ unsigned int sa_mask;
+ int sa_flags;
+ };
+ struct sigaltstack {
+ char *ss_sp;
+ int ss_size;
+ int ss_flags;
+ };
+ struct sigcontext {
+ int sc_onstack;
+ int sc_mask;
+ int sc_ir;
+ int sc_psw;
+ int sc_sp;
+ void *sc_regs;
+ };
+ struct vm_region_basic_info {
+ int protection;
+ int max_protection;
+ unsigned int inheritance;
+ int shared;
+ int reserved;
+ int offset;
+ int behavior;
+ unsigned short user_wired_count;
+ };
+
+ static CFBundleRef systemBundle=NULL;
+
+ static int initSystemBundle (void)
+ {
+ FSRefParam fileRefParam;
+ FSRef fileRef;
+ OSErr error;
+ CFURLRef url;
+
+ {
+ int i;
+ char *p;
+
+ p=(char*)&fileRefParam;
+ for (i=0; i<sizeof (fileRefParam); ++i)
+ p[i]=0;
+
+ p=(char*)&fileRef;
+ for (i=0; i<sizeof (fileRef); ++i)
+ p[i]=0;
+ }
+
+ fileRefParam.ioNamePtr = "\pSystem.framework";;
+ fileRefParam.newRef = &fileRef;
+
+ error = FindFolder (kSystemDomain,kFrameworksFolderType,false,&fileRefParam.ioVRefNum,&fileRefParam.ioDirID);
+ if (error!=noErr)
+ return 0;
+
+ error = PBMakeFSRefSync (&fileRefParam);
+ if (error!=noErr)
+ return 0;
+
+ url = CFURLCreateFromFSRef (NULL/*kCFAllocatorDefault*/,&fileRef);
+ if (url==NULL)
+ return 0;
+
+ systemBundle = CFBundleCreate(NULL/*kCFAllocatorDefault*/, url);
+ if (systemBundle==NULL)
+ return 0;
+
+ CFRelease (url);
+
+ return 1;
+ }
+
+ static int (*sigaction_p) (int,void *,void *)=NULL;
+
+ static int sigaction (int a1,void *a2,void *a3)
+ {
+ if (sigaction_p==NULL){
+ if (systemBundle==NULL)
+ initSystemBundle();
+ sigaction_p = (int(*)(int,void*,void*)) CFBundleGetFunctionPointerForName (systemBundle,CFSTR ("sigaction"));
+ if (sigaction_p==NULL)
+ return -1;
+ }
+
+ return call_function_3 (a1,a2,a3,sigaction_p);
+ }
+
+ static int (*sigaltstack_p) (void *,void *);
+
+ int sigaltstack (void *a1,void *a2)
+ {
+ if (sigaltstack_p==NULL){
+ if (systemBundle==NULL)
+ initSystemBundle();
+ sigaltstack_p = (int(*)(void*,void*)) CFBundleGetFunctionPointerForName (systemBundle,CFSTR ("sigaltstack"));
+ if (sigaltstack_p==NULL)
+ return -1;
+ }
+
+ return call_function_2 (a1,a2,sigaltstack_p);
+ }
+
+ static int (*mach_task_self_p) (void)=NULL;
+
+ int mach_task_self (void)
+ {
+ if (mach_task_self_p==NULL){
+ if (systemBundle==NULL)
+ initSystemBundle();
+ mach_task_self_p = (int(*)(void)) CFBundleGetFunctionPointerForName (systemBundle,CFSTR ("mach_task_self"));
+ if (mach_task_self_p==NULL)
+ return -1;
+ }
+
+ return call_function_0 (mach_task_self_p);
+ }
+
+ static int (*vm_region_p) (int,void*,void *,int,void *,void *,void *);
+
+ int vm_region (int a1,void *a2,void *a3,int a4,void *a5,void *a6,void *a7)
+ {
+ if (vm_region_p==NULL){
+ if (systemBundle==NULL)
+ initSystemBundle();
+ vm_region_p = (int(*)(int,void*,void *,int,void *,void *,void *)) CFBundleGetFunctionPointerForName (systemBundle,CFSTR ("vm_region"));
+ if (vm_region_p==NULL)
+ return -1;
+ }
+
+ return call_function_7 (a1,a2,a3,a4,a5,a6,a7,vm_region_p);
+ }
+
+ static int (*vm_protect_p) (int,int,int,int,int);
+
+ int vm_protect (int a1,int a2,int a3,int a4,int a5)
+ {
+ if (vm_protect_p==NULL){
+ if (systemBundle==NULL)
+ initSystemBundle();
+ vm_protect_p = (int(*)(int,int,int,int,int)) CFBundleGetFunctionPointerForName (systemBundle,CFSTR ("vm_protect"));
+ if (vm_protect_p==NULL)
+ return -1;
+ }
+
+ return call_function_5 (a1,a2,a3,a4,a5,vm_protect_p);
+ }
+# endif
+#endif
#ifdef MACOSX
# undef GetWindowPort
@@ -1424,6 +1589,214 @@ extern void my_pointer_glue (void (*function) (void));
int execution_aborted;
+#ifdef STACK_OVERFLOW_EXCEPTION_HANDLER
+int *a_stack_guard_page,*b_stack_guard_page;
+
+void *allocate_a_stack (int size)
+{
+ int alloc_size;
+ char *p,*end_p;
+
+ alloc_size=(size+4096+4095) & -4096;
+
+# ifdef MACHO
+ p=malloc (alloc_size);
+# else
+ p=NewPtr (alloc_size);
+# endif
+ if (p==NULL)
+ return NULL;
+
+ end_p=(char*)(((int)p+size+4095) & -4096);
+
+ vm_protect (mach_task_self(),(int)end_p,4096,0,0);
+
+ a_stack_guard_page=(int*)end_p;
+
+ return (void*)((int)end_p-size);
+}
+
+extern int *halt_sp;
+extern void stack_overflow (void);
+
+struct sigaction old_BUS_sa,old_SEGV_sa;
+
+static void clean_exception_handler (int sig,void *sip,struct sigcontext *scp)
+{
+ struct sigaction *old_sa_p;
+ unsigned int instruction;
+ int *registers,a;
+
+ instruction=*(unsigned int*)(scp->sc_ir);
+ registers = &((int *)scp->sc_regs)[2];
+
+ switch (instruction>>26){
+ case 36: /* stw */ case 37: /* stwu */
+ case 38: /* stb */ case 39: /* stbu */
+ case 44: /* sth */ case 45: /* sthu */
+ case 47: /* stmw */
+ case 54: /* stfd */ case 55: /* stfdu */
+ {
+ int reg_a,a_aligned_4k;
+
+ reg_a=(instruction>>16) & 31;
+ a=(short)instruction;
+ if (reg_a)
+ a+=registers[reg_a];
+
+ a_aligned_4k = (int)a & -4096;
+
+ if (a_aligned_4k==(int)b_stack_guard_page || a_aligned_4k==(int)a_stack_guard_page){
+ scp->sc_ir = (int)&stack_overflow;
+ registers[1]=(int)halt_sp;
+ return;
+ }
+ }
+ }
+
+ old_sa_p = sig==SIGBUS ? &old_BUS_sa : &old_SEGV_sa;
+
+ if (old_sa_p->sa_handler==SIG_DFL || old_sa_p->sa_handler==SIG_IGN)
+ sigaction (sig,old_sa_p,NULL);
+ else
+# ifdef MACHO
+ old_sa_p->sa_handler (sig,sip,scp);
+# else
+ call_function_3 (sig,sip,scp,old_sa_p->sa_handler);
+# endif
+}
+
+# ifndef MACHO
+extern int *get_TOC (void);
+# endif
+
+static void install_clean_exception_handler (void)
+{
+ {
+ struct vm_region_basic_info vm_region_info;
+# ifdef MACHO
+ vm_address_t vm_address,previous_address;
+ mach_msg_type_number_t info_count;
+ memory_object_name_t object_name;
+ vm_size_t vm_size;
+# else
+ int vm_address,previous_address;
+ int info_count;
+ int object_name;
+ int vm_size;
+ int *stack_top;
+# endif
+ int r,var_on_stack;
+
+ vm_address=(int)&var_on_stack;
+
+ info_count=sizeof (vm_region_info);
+# ifdef MACHO
+ r=vm_region (mach_task_self(),&vm_address,&vm_size,VM_REGION_BASIC_INFO,(vm_region_info_t)&vm_region_info,&info_count,&object_name);
+# else
+ r=vm_region (mach_task_self(),&vm_address,&vm_size,10,(void*)&vm_region_info,&info_count,&object_name);
+# endif
+ if (r!=0)
+ return;
+
+#ifndef MACHO
+ stack_top=(int*)(vm_address+vm_size);
+#endif
+
+ do {
+ previous_address=vm_address;
+ vm_address=vm_address-1;
+
+ info_count=sizeof (vm_region_info);
+# ifdef MACHO
+ r=vm_region (mach_task_self(),&vm_address,&vm_size,VM_REGION_BASIC_INFO,(vm_region_info_t)&vm_region_info,&info_count,&object_name);
+# else
+ r=vm_region (mach_task_self(),&vm_address,&vm_size,10,(void*)&vm_region_info,&info_count,&object_name);
+# endif
+ } while (vm_address!=previous_address && r==0);
+
+ b_stack_guard_page=(int*)((int)previous_address-4096);
+
+#ifndef MACHO
+ {
+ int stack_size_aligned_4k;
+
+ stack_size_aligned_4k = (stack_size+4095) & -4096;
+ if ((unsigned int)b_stack_guard_page < (unsigned int)((int)stack_top-stack_size_aligned_4k-4096)){
+ b_stack_guard_page=(int*)((int)stack_top-stack_size_aligned_4k-4096);
+ vm_protect (mach_task_self(),(int)b_stack_guard_page,4096,0,0);
+ }
+ }
+#endif
+ }
+
+ {
+ struct sigaltstack sa_stack;
+ void *signal_stack;
+ struct sigaction sa;
+
+# ifdef MACHO
+ signal_stack=(int*)malloc (MINSIGSTKSZ);
+# else
+ signal_stack=(int*)NewPtr (8192);
+# endif
+ if (signal_stack!=NULL){
+# ifndef MACHO
+ int *handler_trampoline;
+# endif
+
+ sa_stack.ss_sp=signal_stack;
+# ifdef MACHO
+ sa_stack.ss_size=MINSIGSTKSZ;
+# else
+ sa_stack.ss_size=8192;
+# endif
+ sa_stack.ss_flags=0;
+
+ sigaltstack (&sa_stack,NULL);
+
+# ifdef MACHO
+ sa.sa_handler=&clean_exception_handler;
+ sigemptyset (&sa.sa_mask);
+ sa.sa_flags=SA_ONSTACK;//SA_SIGINFO;
+# else
+ handler_trampoline = (int*) NewPtr (24);
+ if (handler_trampoline!=NULL){
+ int *handler_address,*toc_register;
+
+ handler_address=*(int**)&clean_exception_handler;
+ toc_register=get_TOC();
+
+# define i_dai_i(i,rd,ra,si)((i<<26)|((rd)<<21)|((ra)<<16)|((unsigned short)(si)))
+# define addis_i(rd,ra,si) i_dai_i (15,rd,ra,si)
+# define addi_i(rd,ra,si) i_dai_i (14,rd,ra,si)
+# define lis_i(rd,si) addis_i (rd,0,si)
+# define bctr_i() ((19<<26)|(20<<21)|(528<<1))
+# define mtspr_i(spr,rs) ((31<<26)|((rs)<<21)|(spr<<16)|(467<<1))
+# define mtctr_i(rs) mtspr_i (9,rs)
+
+ handler_trampoline[0]=lis_i (6,((int)handler_address-(short)handler_address)>>16);
+ handler_trampoline[1]=addi_i (6,6,(short)handler_address);
+ handler_trampoline[2]=mtctr_i (6);
+ handler_trampoline[3]=lis_i (2,((int)toc_register-(short)toc_register)>>16);
+ handler_trampoline[4]=addi_i (2,2,(short)toc_register);
+ handler_trampoline[5]=bctr_i();
+
+ __icbi (handler_trampoline,0);
+ __icbi (handler_trampoline,20);
+
+ sa.sa_handler=(void(*)())handler_trampoline;
+ sa.sa_mask=0;
+ sa.sa_flags=1;
+ }
+# endif
+ sigaction (SIGSEGV,&sa,&old_SEGV_sa);
+ sigaction (SIGBUS,&sa,&old_BUS_sa);
+ }
+ }
+}
+#endif
+
int main (void)
{
Handle stack_handle,font_handle;
@@ -1452,6 +1825,10 @@ int main (void)
heap_size=(stack_p[2]+7) & ~7;
flags=stack_p[3];
+#ifdef STACK_OVERFLOW_EXCEPTION_HANDLER
+ install_clean_exception_handler();
+#endif
+
#ifdef SIMULATE
n_processors=stack_p[1];
if (n_processors<1)
@@ -1484,6 +1861,7 @@ int main (void)
#endif
font_id=-1;
+
font_handle=GetResource ('Font',128);
if (font_handle!=NULL){
@@ -1503,8 +1881,6 @@ int main (void)
if (!init_terminal())
return 1;
-/* srand (TickCount()); */
-
#ifdef G_POWER
wait_next_event_available=1;
#else
@@ -1587,7 +1963,7 @@ int main (void)
return 0;
}
-#ifdef TIME_PROFILE
+#if defined (TIME_PROFILE) || defined (MACHO)
void create_profile_file_name (unsigned char *profile_file_name)
{
unsigned char *cur_ap_name,*end_profile_file_name;