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