github.com/ice-blockchain/go/src@v0.0.0-20240403114104-1564d284e521/runtime/cgo/gcc_android.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 <stdarg.h> 6 #include <android/log.h> 7 #include <pthread.h> 8 #include <dlfcn.h> 9 #include "libcgo.h" 10 11 void 12 fatalf(const char* format, ...) 13 { 14 va_list ap; 15 16 // Write to both stderr and logcat. 17 // 18 // When running from an .apk, /dev/stderr and /dev/stdout 19 // redirect to /dev/null. And when running a test binary 20 // via adb shell, it's easy to miss logcat. 21 22 fprintf(stderr, "runtime/cgo: "); 23 va_start(ap, format); 24 vfprintf(stderr, format, ap); 25 va_end(ap); 26 fprintf(stderr, "\n"); 27 28 va_start(ap, format); 29 __android_log_vprint(ANDROID_LOG_FATAL, "runtime/cgo", format, ap); 30 va_end(ap); 31 32 abort(); 33 } 34 35 // Truncated to a different magic value on 32-bit; that's ok. 36 #define magic1 (0x23581321345589ULL) 37 38 // From https://android.googlesource.com/platform/bionic/+/refs/heads/android10-tests-release/libc/private/bionic_asm_tls.h#69. 39 #define TLS_SLOT_APP 2 40 41 // inittls allocates a thread-local storage slot for g. 42 // 43 // It finds the first available slot using pthread_key_create and uses 44 // it as the offset value for runtime.tls_g. 45 static void 46 inittls(void **tlsg, void **tlsbase) 47 { 48 pthread_key_t k; 49 int i, err; 50 void *handle, *get_ver, *off; 51 52 // Check for Android Q where we can use the free TLS_SLOT_APP slot. 53 handle = dlopen("libc.so", RTLD_LAZY); 54 if (handle == NULL) { 55 fatalf("inittls: failed to dlopen main program"); 56 return; 57 } 58 // android_get_device_api_level is introduced in Android Q, so its mere presence 59 // is enough. 60 get_ver = dlsym(handle, "android_get_device_api_level"); 61 dlclose(handle); 62 if (get_ver != NULL) { 63 off = (void *)(TLS_SLOT_APP*sizeof(void *)); 64 // tlsg is initialized to Q's free TLS slot. Verify it while we're here. 65 if (*tlsg != off) { 66 fatalf("tlsg offset wrong, got %ld want %ld\n", *tlsg, off); 67 } 68 return; 69 } 70 71 err = pthread_key_create(&k, nil); 72 if(err != 0) { 73 fatalf("pthread_key_create failed: %d", err); 74 } 75 pthread_setspecific(k, (void*)magic1); 76 // If thread local slots are laid out as we expect, our magic word will 77 // be located at some low offset from tlsbase. However, just in case something went 78 // wrong, the search is limited to sensible offsets. PTHREAD_KEYS_MAX was the 79 // original limit, but issue 19472 made a higher limit necessary. 80 for (i=0; i<384; i++) { 81 if (*(tlsbase+i) == (void*)magic1) { 82 *tlsg = (void*)(i*sizeof(void *)); 83 pthread_setspecific(k, 0); 84 return; 85 } 86 } 87 fatalf("inittls: could not find pthread key"); 88 } 89 90 void (*x_cgo_inittls)(void **tlsg, void **tlsbase) = inittls;