From d77bba0a9ff855143ad5f8f2d5fa9822ed1be63e Mon Sep 17 00:00:00 2001 From: David Crawshaw Date: Fri, 17 Apr 2015 08:05:20 -0400 Subject: [PATCH] app: call main.main on app startup There is some cleanup to be done in this package now, but I'm deferring it until later in the cycle. We should probably also change the semantics slightly: main should be called for all-Go apps (that is, apps that use NativeActivity), but it would be more consistent with buildmode=c-shared and c-archive if we did not call main for Go shared libraries being included in Java android apps. Change-Id: I13ca797a478edb22b0c602c1ee6e616fe4fea1e6 Reviewed-on: https://go-review.googlesource.com/9016 Reviewed-by: Hyang-Ah Hana Kim --- app/android.c | 32 ++++---------------------------- app/android.go | 11 +++++++++++ app/internal/callfn/callfn.go | 16 ++++++++++++++++ app/internal/callfn/callfn_arm.s | 11 +++++++++++ 4 files changed, 42 insertions(+), 28 deletions(-) create mode 100644 app/internal/callfn/callfn.go create mode 100644 app/internal/callfn/callfn_arm.s diff --git a/app/android.c b/app/android.c index 1e4785c..dca0aaa 100644 --- a/app/android.c +++ b/app/android.c @@ -19,9 +19,6 @@ #define LOG_INFO(...) __android_log_print(ANDROID_LOG_INFO, "Go", __VA_ARGS__) #define LOG_FATAL(...) __android_log_print(ANDROID_LOG_FATAL, "Go", __VA_ARGS__) -// Defined in the Go runtime. -static int (*_rt0_arm_linux1)(int argc, char** argv); - jint JNI_OnLoad(JavaVM* vm, void* reserved) { current_vm = vm; current_ctx = NULL; @@ -122,32 +119,11 @@ static const char* getenv_raw(const char *name) { static void* init_go_runtime(void* unused) { init_from_context(); - - _rt0_arm_linux1 = (int (*)(int, char**))dlsym(RTLD_DEFAULT, "_rt0_arm_linux1"); - if (_rt0_arm_linux1 == NULL) { - LOG_FATAL("missing _rt0_arm_linux1"); + uintptr_t mainPC = (uintptr_t)dlsym(RTLD_DEFAULT, "main.main"); + if (!mainPC) { + LOG_FATAL("missing main.main"); } - - // Defensively heap-allocate argv0, for setenv. - char* argv0 = strdup("gojni"); - - // Build argv, including the ELF auxiliary vector. - struct { - char* argv[2]; - const char* envp[4]; - uint32_t auxv[64]; - } x; - x.argv[0] = argv0; - x.argv[1] = NULL; - x.envp[0] = getenv_raw("TMPDIR="); - x.envp[1] = getenv_raw("PATH="); - x.envp[2] = getenv_raw("LD_LIBRARY_PATH="); - x.envp[3] = NULL; - - build_auxv(x.auxv, sizeof(x.auxv)/sizeof(uint32_t)); - int32_t argc = 1; - _rt0_arm_linux1(argc, x.argv); - return NULL; + callMain(mainPC); } static void wait_go_runtime() { diff --git a/app/android.go b/app/android.go index e7f1987..30a5a90 100644 --- a/app/android.go +++ b/app/android.go @@ -69,9 +69,20 @@ import ( "runtime" "unsafe" + "golang.org/x/mobile/app/internal/callfn" "golang.org/x/mobile/geom" ) +//export callMain +func callMain(mainPC uintptr) { + for _, name := range []string{"TMPDIR", "PATH", "LD_LIBRARY_PATH"} { + n := C.CString(name) + os.Setenv(name, C.GoString(C.getenv(n))) + C.free(unsafe.Pointer(n)) + } + callfn.CallFn(mainPC) +} + //export onCreate func onCreate(activity *C.ANativeActivity) { C.asset_manager = activity.assetManager diff --git a/app/internal/callfn/callfn.go b/app/internal/callfn/callfn.go new file mode 100644 index 0000000..ed4cac3 --- /dev/null +++ b/app/internal/callfn/callfn.go @@ -0,0 +1,16 @@ +// Copyright 2015 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. + +// +build android,arm + +// Package callfn provides an android entry point. +// +// It is a separate package from app because it contains Go assembly, +// which does not compile in a package using cgo. +package callfn + +// CallFn calls a zero-argument function by its program counter. +// It is only intended for calling main.main. Using it for +// anything else will not end well. +func CallFn(fn uintptr) diff --git a/app/internal/callfn/callfn_arm.s b/app/internal/callfn/callfn_arm.s new file mode 100644 index 0000000..d71f748 --- /dev/null +++ b/app/internal/callfn/callfn_arm.s @@ -0,0 +1,11 @@ +// Copyright 2015 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 "textflag.h" +#include "funcdata.h" + +TEXT ·CallFn(SB),$0-4 + MOVW fn+0(FP), R0 + BL (R0) + RET