From: Shenghou Ma Date: Sat, 11 Apr 2015 02:16:11 +0000 (-0400) Subject: runtime/cgo: darwin/arm64 support X-Git-Tag: go1.5beta1~1081 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=828de09f8bfb64fc7d3eee728e7292055fd25364;p=gostls13.git runtime/cgo: darwin/arm64 support Fixes #10116. Change-Id: I3b3f80791a1db4c2b7318f81a115972cd2237f05 Signed-off-by: Shenghou Ma Reviewed-on: https://go-review.googlesource.com/8784 Reviewed-by: David Crawshaw --- diff --git a/src/runtime/cgo/cgo.go b/src/runtime/cgo/cgo.go index 510a817c32..846801cfa8 100644 --- a/src/runtime/cgo/cgo.go +++ b/src/runtime/cgo/cgo.go @@ -11,8 +11,9 @@ package cgo /* -#cgo darwin,!arm LDFLAGS: -lpthread +#cgo darwin,!arm,!arm64 LDFLAGS: -lpthread #cgo darwin,arm LDFLAGS: -framework CoreFoundation +#cgo darwin,arm64 LDFLAGS: -framework CoreFoundation #cgo dragonfly LDFLAGS: -lpthread #cgo freebsd LDFLAGS: -lpthread #cgo android LDFLAGS: -llog diff --git a/src/runtime/cgo/gcc_arm64.S b/src/runtime/cgo/gcc_arm64.S index be4600f37d..7677ec1d48 100644 --- a/src/runtime/cgo/gcc_arm64.S +++ b/src/runtime/cgo/gcc_arm64.S @@ -11,6 +11,10 @@ #define EXT(s) s #endif +// Apple's ld64 wants 4-byte alignment for ARM code sections. +// .align in both Apple as and GNU as treat n as aligning to 2**n bytes. +.align 2 + /* * void crosscall1(void (*fn)(void), void (*setg_gcc)(void *g), void *g) * diff --git a/src/runtime/cgo/gcc_darwin_arm64.c b/src/runtime/cgo/gcc_darwin_arm64.c new file mode 100644 index 0000000000..daf3d34922 --- /dev/null +++ b/src/runtime/cgo/gcc_darwin_arm64.c @@ -0,0 +1,152 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include +#include +#include +#include /* for strerror */ +#include +#include +#include + +#include "libcgo.h" + +#include +#include + +#define magic (0xc476c475c47957UL) + +// inittls allocates a thread-local storage slot for g. +// +// It finds the first available slot using pthread_key_create and uses +// it as the offset value for runtime.tlsg. +static void +inittls(void **tlsg, void **tlsbase) +{ + pthread_key_t k; + int i, err; + + err = pthread_key_create(&k, nil); + if(err != 0) { + fprintf(stderr, "runtime/cgo: pthread_key_create failed: %d\n", err); + abort(); + } + //fprintf(stderr, "runtime/cgo: k = %d, tlsbase = %p\n", (int)k, tlsbase); // debug + pthread_setspecific(k, (void*)magic); + // The first key should be at 257. + for (i=0; ifn, ts->g); // debug + sigfillset(&ign); + pthread_sigmask(SIG_SETMASK, &ign, &oset); + + pthread_attr_init(&attr); + size = 0; + pthread_attr_getstacksize(&attr, &size); + // Leave stacklo=0 and set stackhi=size; mstack will do the rest. + ts->g->stackhi = size; + err = pthread_create(&p, &attr, threadentry, ts); + + pthread_sigmask(SIG_SETMASK, &oset, nil); + + if (err != 0) { + fprintf(stderr, "runtime/cgo: pthread_create failed: %s\n", strerror(err)); + abort(); + } +} + +extern void crosscall1(void (*fn)(void), void (*setg_gcc)(void*), void *g); +static void* +threadentry(void *v) +{ + ThreadStart ts; + + ts = *(ThreadStart*)v; + free(v); + + crosscall1(ts.fn, setg_gcc, (void*)ts.g); + return nil; +} + +// init_working_dir sets the current working directory to the app root. +// By default darwin/arm processes start in "/". +static void +init_working_dir() +{ + CFBundleRef bundle = CFBundleGetMainBundle(); + if (bundle == NULL) { + fprintf(stderr, "runtime/cgo: no main bundle\n"); + return; + } + CFURLRef url_ref = CFBundleCopyResourceURL(bundle, CFSTR("Info"), CFSTR("plist"), NULL); + if (url_ref == NULL) { + fprintf(stderr, "runtime/cgo: no Info.plist URL\n"); + return; + } + CFStringRef url_str_ref = CFURLGetString(url_ref); + char url[MAXPATHLEN]; + if (!CFStringGetCString(url_str_ref, url, sizeof(url), kCFStringEncodingUTF8)) { + fprintf(stderr, "runtime/cgo: cannot get URL string\n"); + return; + } + + // url is of the form "file:///path/to/Info.plist". + // strip it down to the working directory "/path/to". + int url_len = strlen(url); + if (url_len < sizeof("file://")+sizeof("/Info.plist")) { + fprintf(stderr, "runtime/cgo: bad URL: %s\n", url); + return; + } + url[url_len-sizeof("/Info.plist")+1] = 0; + char *dir = &url[0] + sizeof("file://")-1; + + if (chdir(dir) != 0) { + fprintf(stderr, "runtime/cgo: chdir(%s) failed\n", dir); + } + + // No-op to set a breakpoint on, immediately after the real chdir. + // Gives the test harness in go_darwin_arm_exec (which uses lldb) a + // chance to move the working directory. + getwd(dir); +} + +void +x_cgo_init(G *g, void (*setg)(void*), void **tlsg, void **tlsbase) +{ + pthread_attr_t attr; + size_t size; + + //fprintf(stderr, "x_cgo_init = %p\n", &x_cgo_init); // aid debugging in presence of ASLR + setg_gcc = setg; + pthread_attr_init(&attr); + pthread_attr_getstacksize(&attr, &size); + g->stacklo = (uintptr)&attr - size + 4096; + pthread_attr_destroy(&attr); + + // yes, tlsbase from mrs might not be correctly aligned. + inittls(tlsg, (void**)((uintptr)tlsbase & ~7)); + + init_working_dir(); +}