github.com/twelsh-aw/go/src@v0.0.0-20230516233729-a56fe86a7c81/runtime/cgo/gcc_darwin_arm64.c (about) 1 // Copyright 2014 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 #include <limits.h> 6 #include <pthread.h> 7 #include <signal.h> 8 #include <string.h> /* for strerror */ 9 #include <sys/param.h> 10 #include <unistd.h> 11 #include <stdlib.h> 12 13 #include "libcgo.h" 14 #include "libcgo_unix.h" 15 16 #include <TargetConditionals.h> 17 18 #if TARGET_OS_IPHONE 19 #include <CoreFoundation/CFBundle.h> 20 #include <CoreFoundation/CFString.h> 21 #endif 22 23 static void *threadentry(void*); 24 static void (*setg_gcc)(void*); 25 26 void 27 _cgo_sys_thread_start(ThreadStart *ts) 28 { 29 pthread_attr_t attr; 30 sigset_t ign, oset; 31 pthread_t p; 32 size_t size; 33 int err; 34 35 //fprintf(stderr, "runtime/cgo: _cgo_sys_thread_start: fn=%p, g=%p\n", ts->fn, ts->g); // debug 36 sigfillset(&ign); 37 pthread_sigmask(SIG_SETMASK, &ign, &oset); 38 39 size = pthread_get_stacksize_np(pthread_self()); 40 pthread_attr_init(&attr); 41 pthread_attr_setstacksize(&attr, size); 42 // Leave stacklo=0 and set stackhi=size; mstart will do the rest. 43 ts->g->stackhi = size; 44 err = _cgo_try_pthread_create(&p, &attr, threadentry, ts); 45 46 pthread_sigmask(SIG_SETMASK, &oset, nil); 47 48 if (err != 0) { 49 fprintf(stderr, "runtime/cgo: pthread_create failed: %s\n", strerror(err)); 50 abort(); 51 } 52 } 53 54 extern void crosscall1(void (*fn)(void), void (*setg_gcc)(void*), void *g); 55 static void* 56 threadentry(void *v) 57 { 58 ThreadStart ts; 59 60 ts = *(ThreadStart*)v; 61 free(v); 62 63 #if TARGET_OS_IPHONE 64 darwin_arm_init_thread_exception_port(); 65 #endif 66 67 crosscall1(ts.fn, setg_gcc, (void*)ts.g); 68 return nil; 69 } 70 71 #if TARGET_OS_IPHONE 72 73 // init_working_dir sets the current working directory to the app root. 74 // By default ios/arm64 processes start in "/". 75 static void 76 init_working_dir() 77 { 78 CFBundleRef bundle = CFBundleGetMainBundle(); 79 if (bundle == NULL) { 80 fprintf(stderr, "runtime/cgo: no main bundle\n"); 81 return; 82 } 83 CFURLRef url_ref = CFBundleCopyResourceURL(bundle, CFSTR("Info"), CFSTR("plist"), NULL); 84 if (url_ref == NULL) { 85 // No Info.plist found. It can happen on Corellium virtual devices. 86 return; 87 } 88 CFStringRef url_str_ref = CFURLGetString(url_ref); 89 char buf[MAXPATHLEN]; 90 Boolean res = CFStringGetCString(url_str_ref, buf, sizeof(buf), kCFStringEncodingUTF8); 91 CFRelease(url_ref); 92 if (!res) { 93 fprintf(stderr, "runtime/cgo: cannot get URL string\n"); 94 return; 95 } 96 97 // url is of the form "file:///path/to/Info.plist". 98 // strip it down to the working directory "/path/to". 99 int url_len = strlen(buf); 100 if (url_len < sizeof("file://")+sizeof("/Info.plist")) { 101 fprintf(stderr, "runtime/cgo: bad URL: %s\n", buf); 102 return; 103 } 104 buf[url_len-sizeof("/Info.plist")+1] = 0; 105 char *dir = &buf[0] + sizeof("file://")-1; 106 107 if (chdir(dir) != 0) { 108 fprintf(stderr, "runtime/cgo: chdir(%s) failed\n", dir); 109 } 110 111 // The test harness in go_ios_exec passes the relative working directory 112 // in the GoExecWrapperWorkingDirectory property of the app bundle. 113 CFStringRef wd_ref = CFBundleGetValueForInfoDictionaryKey(bundle, CFSTR("GoExecWrapperWorkingDirectory")); 114 if (wd_ref != NULL) { 115 if (!CFStringGetCString(wd_ref, buf, sizeof(buf), kCFStringEncodingUTF8)) { 116 fprintf(stderr, "runtime/cgo: cannot get GoExecWrapperWorkingDirectory string\n"); 117 return; 118 } 119 if (chdir(buf) != 0) { 120 fprintf(stderr, "runtime/cgo: chdir(%s) failed\n", buf); 121 } 122 } 123 } 124 125 #endif // TARGET_OS_IPHONE 126 127 void 128 x_cgo_init(G *g, void (*setg)(void*)) 129 { 130 size_t size; 131 132 //fprintf(stderr, "x_cgo_init = %p\n", &x_cgo_init); // aid debugging in presence of ASLR 133 setg_gcc = setg; 134 size = pthread_get_stacksize_np(pthread_self()); 135 g->stacklo = (uintptr)&size - size + 4096; 136 137 #if TARGET_OS_IPHONE 138 darwin_arm_init_mach_exception_handler(); 139 darwin_arm_init_thread_exception_port(); 140 init_working_dir(); 141 #endif 142 }