...

Text file src/runtime/cgo/gcc_darwin_arm64.c

Documentation: runtime/cgo

     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
    23static void *threadentry(void*);
    24static void (*setg_gcc)(void*);
    25
    26void
    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	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
    43	// Leave stacklo=0 and set stackhi=size; mstart will do the rest.
    44	ts->g->stackhi = size;
    45	err = _cgo_try_pthread_create(&p, &attr, threadentry, ts);
    46
    47	pthread_sigmask(SIG_SETMASK, &oset, nil);
    48
    49	if (err != 0) {
    50		fprintf(stderr, "runtime/cgo: pthread_create failed: %s\n", strerror(err));
    51		abort();
    52	}
    53}
    54
    55extern void crosscall1(void (*fn)(void), void (*setg_gcc)(void*), void *g);
    56static void*
    57threadentry(void *v)
    58{
    59	ThreadStart ts;
    60
    61	ts = *(ThreadStart*)v;
    62	free(v);
    63
    64#if TARGET_OS_IPHONE
    65	darwin_arm_init_thread_exception_port();
    66#endif
    67
    68	crosscall1(ts.fn, setg_gcc, (void*)ts.g);
    69	return nil;
    70}
    71
    72#if TARGET_OS_IPHONE
    73
    74// init_working_dir sets the current working directory to the app root.
    75// By default ios/arm64 processes start in "/".
    76static void
    77init_working_dir()
    78{
    79	CFBundleRef bundle;
    80	CFURLRef url_ref;
    81	CFStringRef url_str_ref;
    82	char buf[MAXPATHLEN];
    83	Boolean res;
    84	int url_len;
    85	char *dir;
    86	CFStringRef wd_ref;
    87
    88	bundle = CFBundleGetMainBundle();
    89	if (bundle == NULL) {
    90		fprintf(stderr, "runtime/cgo: no main bundle\n");
    91		return;
    92	}
    93	url_ref = CFBundleCopyResourceURL(bundle, CFSTR("Info"), CFSTR("plist"), NULL);
    94	if (url_ref == NULL) {
    95		// No Info.plist found. It can happen on Corellium virtual devices.
    96		return;
    97	}
    98	url_str_ref = CFURLGetString(url_ref);
    99	res = CFStringGetCString(url_str_ref, buf, sizeof(buf), kCFStringEncodingUTF8);
   100	CFRelease(url_ref);
   101	if (!res) {
   102		fprintf(stderr, "runtime/cgo: cannot get URL string\n");
   103		return;
   104	}
   105
   106	// url is of the form "file:///path/to/Info.plist".
   107	// strip it down to the working directory "/path/to".
   108	url_len = strlen(buf);
   109	if (url_len < sizeof("file://")+sizeof("/Info.plist")) {
   110		fprintf(stderr, "runtime/cgo: bad URL: %s\n", buf);
   111		return;
   112	}
   113	buf[url_len-sizeof("/Info.plist")+1] = 0;
   114	dir = &buf[0] + sizeof("file://")-1;
   115
   116	if (chdir(dir) != 0) {
   117		fprintf(stderr, "runtime/cgo: chdir(%s) failed\n", dir);
   118	}
   119
   120	// The test harness in go_ios_exec passes the relative working directory
   121	// in the GoExecWrapperWorkingDirectory property of the app bundle.
   122	wd_ref = CFBundleGetValueForInfoDictionaryKey(bundle, CFSTR("GoExecWrapperWorkingDirectory"));
   123	if (wd_ref != NULL) {
   124		if (!CFStringGetCString(wd_ref, buf, sizeof(buf), kCFStringEncodingUTF8)) {
   125			fprintf(stderr, "runtime/cgo: cannot get GoExecWrapperWorkingDirectory string\n");
   126			return;
   127		}
   128		if (chdir(buf) != 0) {
   129			fprintf(stderr, "runtime/cgo: chdir(%s) failed\n", buf);
   130		}
   131	}
   132}
   133
   134#endif // TARGET_OS_IPHONE
   135
   136void
   137x_cgo_init(G *g, void (*setg)(void*))
   138{
   139	//fprintf(stderr, "x_cgo_init = %p\n", &x_cgo_init); // aid debugging in presence of ASLR
   140	setg_gcc = setg;
   141	_cgo_set_stacklo(g, NULL);
   142
   143#if TARGET_OS_IPHONE
   144	darwin_arm_init_mach_exception_handler();
   145	darwin_arm_init_thread_exception_port();
   146	init_working_dir();
   147#endif
   148}

View as plain text