diff --git a/make/autoconf/build-aux/config.sub b/make/autoconf/build-aux/config.sub index 8f5a5cf52..34943b6ed 100644 --- a/make/autoconf/build-aux/config.sub +++ b/make/autoconf/build-aux/config.sub @@ -47,7 +47,8 @@ if echo $* | grep pc-msys >/dev/null ; then fi # Filter out everything that doesn't begin with "aarch64-" -if ! echo $* | grep '^aarch64-' >/dev/null ; then +# or that ends with "-android" +if ! echo $* | egrep "^aarch64-|-android" >/dev/null ; then . $DIR/autoconf-config.sub "$@" # autoconf-config.sub exits, so we never reach here, but just in # case we do: @@ -58,6 +59,10 @@ while test $# -gt 0 ; do case $1 in -- ) # Stop option processing shift; break ;; + *-android* ) + echo $1 + exit + ;; aarch64-* ) config=`echo $1 | sed 's/^aarch64-/arm-/'` sub_args="$sub_args $config" diff --git a/make/autoconf/flags-cflags.m4 b/make/autoconf/flags-cflags.m4 index 5eed1138f..b4319de67 100644 --- a/make/autoconf/flags-cflags.m4 +++ b/make/autoconf/flags-cflags.m4 @@ -374,7 +374,8 @@ AC_DEFUN([FLAGS_SETUP_CFLAGS_HELPER], #### OS DEFINES, these should be independent on toolchain if test "x$OPENJDK_TARGET_OS" = xlinux; then CFLAGS_OS_DEF_JVM="-DLINUX" - CFLAGS_OS_DEF_JDK="-D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE" + # CFLAGS_OS_DEF_JDK="-D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE" + CFLAGS_OS_DEF_JDK="-D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE -D__USE_BSD" elif test "x$OPENJDK_TARGET_OS" = xmacosx; then CFLAGS_OS_DEF_JVM="-D_ALLBSD_SOURCE -D_DARWIN_C_SOURCE -D_XOPEN_SOURCE" CFLAGS_OS_DEF_JDK="-D_ALLBSD_SOURCE -D_DARWIN_UNLIMITED_SELECT" diff --git a/make/autoconf/flags-ldflags.m4 b/make/autoconf/flags-ldflags.m4 index 23bb33e87..ad0ab88d0 100644 --- a/make/autoconf/flags-ldflags.m4 +++ b/make/autoconf/flags-ldflags.m4 @@ -179,7 +179,9 @@ AC_DEFUN([FLAGS_SETUP_LDFLAGS_CPU_DEP], test "x${OPENJDK_$1_CPU}" = xmips64el; then $1_CPU_LDFLAGS="${$1_CPU_LDFLAGS} -Wl,--hash-style=sysv" else - $1_CPU_LDFLAGS="${$1_CPU_LDFLAGS} -Wl,--hash-style=gnu" + # Android 5.x does not support GNU hash style + # gnu + $1_CPU_LDFLAGS="${$1_CPU_LDFLAGS} -Wl,--hash-style=sysv" fi elif test "x$TOOLCHAIN_TYPE" = xmicrosoft; then diff --git a/make/autoconf/lib-freetype.m4 b/make/autoconf/lib-freetype.m4 index 6a7109342..2d74ffc5b 100644 --- a/make/autoconf/lib-freetype.m4 +++ b/make/autoconf/lib-freetype.m4 @@ -103,7 +103,8 @@ AC_DEFUN_ONCE([LIB_SETUP_FREETYPE], FREETYPE_TO_USE=bundled if test "x$OPENJDK_TARGET_OS" != "xwindows" && \ test "x$OPENJDK_TARGET_OS" != "xmacosx" && \ - test "x$OPENJDK_TARGET_OS" != "xaix"; then + test "x$OPENJDK_TARGET_OS" != "xaix" && \ + test "x$OPENJDK_TARGET_OS" != "xandroid"; then FREETYPE_TO_USE=system fi if test "x$with_freetype" != "x" ; then diff --git a/make/autoconf/libraries.m4 b/make/autoconf/libraries.m4 index a65d91ee9..961f57db9 100644 --- a/make/autoconf/libraries.m4 +++ b/make/autoconf/libraries.m4 @@ -40,8 +40,8 @@ m4_include([lib-tests.m4]) AC_DEFUN_ONCE([LIB_DETERMINE_DEPENDENCIES], [ # Check if X11 is needed - if test "x$OPENJDK_TARGET_OS" = xwindows || test "x$OPENJDK_TARGET_OS" = xmacosx; then - # No X11 support on windows or macosx + if test "x$OPENJDK_TARGET_OS" = xwindows || test "x$OPENJDK_TARGET_OS" = xmacosx || test "x$OPENJDK_TARGET_OS" = xandroid; then + # No X11 support on windows, macosx or android NEEDS_LIB_X11=false elif test "x$ENABLE_HEADLESS_ONLY" = xtrue; then # No X11 support needed when building headless only @@ -52,8 +52,8 @@ AC_DEFUN_ONCE([LIB_DETERMINE_DEPENDENCIES], fi # Check if fontconfig is needed - if test "x$OPENJDK_TARGET_OS" = xwindows || test "x$OPENJDK_TARGET_OS" = xmacosx; then - # No fontconfig support on windows or macosx + if test "x$OPENJDK_TARGET_OS" = xwindows || test "x$OPENJDK_TARGET_OS" = xmacosx || test "x$OPENJDK_TARGET_OS" = xandroid; then + # No fontconfig support on windows, macosx or android NEEDS_LIB_FONTCONFIG=false else # All other instances need fontconfig, even if building headless only, diff --git a/make/autoconf/platform.m4 b/make/autoconf/platform.m4 index 2dd13d0d5..ea06c46a7 100644 --- a/make/autoconf/platform.m4 +++ b/make/autoconf/platform.m4 @@ -190,6 +190,10 @@ AC_DEFUN([PLATFORM_EXTRACT_VARS_FROM_OS], VAR_OS=linux VAR_OS_TYPE=unix ;; + *android*) + VAR_OS=linux + VAR_OS_TYPE=unix + ;; *darwin*) VAR_OS=macosx VAR_OS_TYPE=unix diff --git a/make/autoconf/toolchain.m4 b/make/autoconf/toolchain.m4 index 788958880..5dc9ade78 100644 --- a/make/autoconf/toolchain.m4 +++ b/make/autoconf/toolchain.m4 @@ -35,10 +35,10 @@ m4_include([toolchain_microsoft.m4]) # All valid toolchains, regardless of platform (used by help.m4) -VALID_TOOLCHAINS_all="gcc clang xlc microsoft" +VALID_TOOLCHAINS_all="clang gcc xlc microsoft" # These toolchains are valid on different platforms -VALID_TOOLCHAINS_linux="gcc clang" +VALID_TOOLCHAINS_linux="clang gcc" VALID_TOOLCHAINS_macosx="gcc clang" VALID_TOOLCHAINS_aix="xlc" VALID_TOOLCHAINS_windows="microsoft" @@ -899,8 +899,8 @@ AC_DEFUN_ONCE([TOOLCHAIN_SETUP_BUILD_COMPILERS], UTIL_REQUIRE_PROGS(BUILD_CC, clang cc gcc) UTIL_REQUIRE_PROGS(BUILD_CXX, clang++ CC g++) else - UTIL_REQUIRE_PROGS(BUILD_CC, cc gcc) - UTIL_REQUIRE_PROGS(BUILD_CXX, CC g++) + UTIL_REQUIRE_PROGS(BUILD_CC, clang cc gcc) + UTIL_REQUIRE_PROGS(BUILD_CXX, clang++ CC g++) fi UTIL_LOOKUP_PROGS(BUILD_NM, nm gcc-nm) UTIL_LOOKUP_PROGS(BUILD_AR, ar gcc-ar lib) @@ -915,11 +915,14 @@ AC_DEFUN_ONCE([TOOLCHAIN_SETUP_BUILD_COMPILERS], PATH="$OLDPATH" - TOOLCHAIN_EXTRACT_COMPILER_VERSION(BUILD_CC, [BuildC]) - TOOLCHAIN_EXTRACT_COMPILER_VERSION(BUILD_CXX, [BuildC++]) - TOOLCHAIN_PREPARE_FOR_VERSION_COMPARISONS([BUILD_], [OPENJDK_BUILD_], [build ]) - TOOLCHAIN_EXTRACT_LD_VERSION(BUILD_LD, [build linker]) - TOOLCHAIN_PREPARE_FOR_LD_VERSION_COMPARISONS([BUILD_], [OPENJDK_BUILD_]) + # xandroid + if test "x$OPENJDK_BUILD_OS" != "xlinux"; then + TOOLCHAIN_EXTRACT_COMPILER_VERSION(BUILD_CC, [BuildC]) + TOOLCHAIN_EXTRACT_COMPILER_VERSION(BUILD_CXX, [BuildC++]) + TOOLCHAIN_PREPARE_FOR_VERSION_COMPARISONS([BUILD_], [OPENJDK_BUILD_], [build ]) + TOOLCHAIN_EXTRACT_LD_VERSION(BUILD_LD, [build linker]) + TOOLCHAIN_PREPARE_FOR_LD_VERSION_COMPARISONS([BUILD_], [OPENJDK_BUILD_]) + fi else # If we are not cross compiling, use the normal target compilers for # building the build platform executables. diff --git a/make/common/JdkNativeCompilation.gmk b/make/common/JdkNativeCompilation.gmk index 6a963ac2c..349ff126b 100644 --- a/make/common/JdkNativeCompilation.gmk +++ b/make/common/JdkNativeCompilation.gmk @@ -41,6 +41,12 @@ FindSrcDirsForLib += \ $(TOPDIR)/src/$(strip $1)/$(OPENJDK_TARGET_OS_TYPE)/native/lib$(strip $2) \ $(TOPDIR)/src/$(strip $1)/share/native/lib$(strip $2))) +ifeq ($(OPENJDK_TARGET_OS), android) + FindSrcDirsForLib += \ + $(call uniq, $(wildcard \ + $(TOPDIR)/src/$(strip $1)/linux/native/lib$(strip $2))) +endif + FindSrcDirsForComponent += \ $(call uniq, $(wildcard \ $(TOPDIR)/src/$(strip $1)/$(OPENJDK_TARGET_OS)/native/$(strip $2) \ diff --git a/make/common/Modules.gmk b/make/common/Modules.gmk index 0eb0fb2dd..e0431de0b 100644 --- a/make/common/Modules.gmk +++ b/make/common/Modules.gmk @@ -83,6 +83,10 @@ GENERATED_SRC_DIRS += \ TOP_SRC_DIRS += \ $(TOPDIR)/src \ # +ifeq ($(OPENJDK_TARGET_OS), android) + SRC_SUBDIRS += linux/classes +endif + SRC_SUBDIRS += $(OPENJDK_TARGET_OS)/classes ifneq ($(OPENJDK_TARGET_OS), $(OPENJDK_TARGET_OS_TYPE)) diff --git a/make/common/Utils.gmk b/make/common/Utils.gmk index a7df32065..0eaa1ec40 100644 --- a/make/common/Utils.gmk +++ b/make/common/Utils.gmk @@ -307,6 +307,12 @@ check-jvm-variant = \ isTargetOs = \ $(strip $(if $(filter $(OPENJDK_TARGET_OS), $1), true, false)) +ifeq ($(call isTargetOs, android), true) + # PATCH: Since Android is Linux, so Linux specific things are also built for Android. + isTargetOs = \ + $(strip $(if $(filter $(OPENJDK_TARGET_OS), $1), true, $(if $(filter linux, $1), true, false))) +endif + isTargetOsType = \ $(strip $(if $(filter $(OPENJDK_TARGET_OS_TYPE), $1), true, false)) diff --git a/make/hotspot/lib/JvmMapfile.gmk b/make/hotspot/lib/JvmMapfile.gmk index 5cba93178..181e0db5c 100644 --- a/make/hotspot/lib/JvmMapfile.gmk +++ b/make/hotspot/lib/JvmMapfile.gmk @@ -52,7 +52,7 @@ endif # Create a dynamic list of symbols from the built object files. This is highly # platform dependent. -ifeq ($(call isTargetOs, linux), true) +ifeq ($(call isTargetOs, android linux), true) DUMP_SYMBOLS_CMD := $(NM) --defined-only *.o ifneq ($(FILTER_SYMBOLS_PATTERN), ) FILTER_SYMBOLS_PATTERN := $(FILTER_SYMBOLS_PATTERN)| diff --git a/make/hotspot/lib/JvmOverrideFiles.gmk b/make/hotspot/lib/JvmOverrideFiles.gmk index a9f8a0e54..c2fd95850 100644 --- a/make/hotspot/lib/JvmOverrideFiles.gmk +++ b/make/hotspot/lib/JvmOverrideFiles.gmk @@ -65,7 +65,8 @@ ifeq ($(call isTargetOs, linux), true) # endif - ifeq ($(call isTargetCpu, x86), true) + #ifeq ($(call isTargetCpu, x86), true) + ifeq (false, true) # Performance measurements show that by compiling GC related code, we could # significantly reduce the GC pause time on 32 bit Linux/Unix platforms by # compiling without the PIC flag (-fPIC on linux). diff --git a/make/modules/java.base/lib/CoreLibraries.gmk b/make/modules/java.base/lib/CoreLibraries.gmk index 1d5fede2a..37624ce84 100644 --- a/make/modules/java.base/lib/CoreLibraries.gmk +++ b/make/modules/java.base/lib/CoreLibraries.gmk @@ -112,6 +112,10 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBJAVA, \ TARGETS += $(BUILD_LIBJAVA) +ifeq ($(OPENJDK_TARGET_OS), linux) + $(BUILD_LIBJAVA): $(BUILD_LIBTINYICONV) +endif + $(BUILD_LIBJAVA): $(BUILD_LIBVERIFY) $(BUILD_LIBJAVA): $(BUILD_LIBFDLIBM) diff --git a/make/modules/java.desktop/Lib.gmk b/make/modules/java.desktop/Lib.gmk index 22b07289a..7281c96b9 100644 --- a/make/modules/java.desktop/Lib.gmk +++ b/make/modules/java.desktop/Lib.gmk @@ -76,7 +76,7 @@ ifeq ($(call isTargetOs, aix), false) $(BUILD_LIBJSOUND): $(call FindLib, java.base, java) - TARGETS += $(BUILD_LIBJSOUND) + # TARGETS += $(BUILD_LIBJSOUND) endif diff --git a/make/modules/java.desktop/lib/Awt2dLibraries.gmk b/make/modules/java.desktop/lib/Awt2dLibraries.gmk index 4d0c0c00d..0bd1b5063 100644 --- a/make/modules/java.desktop/lib/Awt2dLibraries.gmk +++ b/make/modules/java.desktop/lib/Awt2dLibraries.gmk @@ -527,7 +527,7 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBFONTMANAGER, \ LDFLAGS_unix := -L$(INSTALL_LIBRARIES_HERE), \ LDFLAGS_aix := -Wl$(COMMA)-berok, \ LIBS := $(BUILD_LIBFONTMANAGER_FONTLIB), \ - LIBS_unix := -lawt -ljava -ljvm $(LIBM) $(LIBCXX), \ + LIBS_unix := -lawt -lawt_headless -ljava -ljvm $(LIBM) $(LIBCXX), \ LIBS_macosx := -lawt_lwawt -framework CoreText -framework CoreFoundation -framework CoreGraphics, \ LIBS_windows := $(WIN_JAVA_LIB) advapi32.lib user32.lib gdi32.lib \ $(WIN_AWT_LIB), \ @@ -753,7 +753,7 @@ ifeq ($(ENABLE_HEADLESS_ONLY), false) LIBS_aix := -liconv, \ )) - TARGETS += $(BUILD_LIBSPLASHSCREEN) + # TARGETS += $(BUILD_LIBSPLASHSCREEN) ifeq ($(call isTargetOs, macosx), true) $(BUILD_LIBSPLASHSCREEN): $(call FindLib, $(MODULE), osxapp) diff --git a/make/modules/java.instrument/Lib.gmk b/make/modules/java.instrument/Lib.gmk index 3996ad213..bba075e69 100644 --- a/make/modules/java.instrument/Lib.gmk +++ b/make/modules/java.instrument/Lib.gmk @@ -36,9 +36,11 @@ endif $(eval $(call SetupJdkLibrary, BUILD_LIBINSTRUMENT, \ NAME := instrument, \ OPTIMIZATION := LOW, \ + EXTRA_SRC := java.base:libtinyiconv, \ CFLAGS := $(CFLAGS_JDKLIB) $(LIBINSTRUMENT_CFLAGS), \ CFLAGS_debug := -DJPLIS_LOGGING, \ CFLAGS_release := -DNO_JPLIS_LOGGING, \ + CXXFLAGS := $(CXXFLAGS_JDKLIB), \ DISABLED_WARNINGS_gcc := unused-function, \ EXTRA_HEADER_DIRS := java.base:libjli, \ LDFLAGS := $(LDFLAGS_JDKLIB) \ diff --git a/make/modules/jdk.hotspot.agent/Lib.gmk b/make/modules/jdk.hotspot.agent/Lib.gmk index 59b24d0e4..d35dbfd17 100644 --- a/make/modules/jdk.hotspot.agent/Lib.gmk +++ b/make/modules/jdk.hotspot.agent/Lib.gmk @@ -74,6 +74,6 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBSA, \ LIBS_windows := dbgeng.lib $(WIN_JAVA_LIB), \ )) -TARGETS += $(BUILD_LIBSA) +# TARGETS += $(BUILD_LIBSA) ################################################################################ diff --git a/make/modules/jdk.jdwp.agent/Lib.gmk b/make/modules/jdk.jdwp.agent/Lib.gmk index aef358c14..7b9e5097c 100644 --- a/make/modules/jdk.jdwp.agent/Lib.gmk +++ b/make/modules/jdk.jdwp.agent/Lib.gmk @@ -52,12 +52,14 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBJDWP, \ NAME := jdwp, \ OPTIMIZATION := LOW, \ CFLAGS := $(CFLAGS_JDKLIB) -DJDWP_LOGGING, \ + CXXFLAGS := $(CXXFLAGS_JDKLIB), \ DISABLED_WARNINGS_gcc := unused-function, \ DISABLED_WARNINGS_clang := sometimes-uninitialized format-nonliteral \ self-assign, \ EXTRA_HEADER_DIRS := \ include \ libjdwp/export, \ + EXTRA_SRC := java.base:libtinyiconv, \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ LIBS := $(JDKLIB_LIBS), \ diff --git a/make/modules/jdk.net/Lib.gmk b/make/modules/jdk.net/Lib.gmk index 3c9d1055f..e4260da69 100644 --- a/make/modules/jdk.net/Lib.gmk +++ b/make/modules/jdk.net/Lib.gmk @@ -27,7 +27,7 @@ include LibCommon.gmk ################################################################################ -ifeq ($(call isTargetOs, linux macosx), true) +ifeq ($(call isTargetOs, linux macosx android), true) $(eval $(call SetupJdkLibrary, BUILD_LIBEXTNET, \ NAME := extnet, \ diff --git a/src/hotspot/cpu/arm/icache_arm.cpp b/src/hotspot/cpu/arm/icache_arm.cpp index 61fcb8a35..93d2ad4f4 100644 --- a/src/hotspot/cpu/arm/icache_arm.cpp +++ b/src/hotspot/cpu/arm/icache_arm.cpp @@ -31,7 +31,7 @@ static int icache_flush(address addr, int lines, int magic) { - __builtin___clear_cache(addr, addr + (lines << ICache::log2_line_size)); + __builtin___clear_cache((char*) addr, (char*) (addr + (lines << ICache::log2_line_size))); return magic; } diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp index ae0c73dcb..e2c9a21f7 100644 --- a/src/hotspot/os/linux/os_linux.cpp +++ b/src/hotspot/os/linux/os_linux.cpp @@ -132,7 +132,7 @@ // for timer info max values which include all bits #define ALL_64_BITS CONST64(0xFFFFFFFFFFFFFFFF) -#ifdef MUSL_LIBC +#if defined(MUSL_LIBC) || defined(__ANDROID__) // dlvsym is not a part of POSIX // and musl libc doesn't implement it. static void *dlvsym(void *handle, @@ -182,6 +182,8 @@ static int clock_tics_per_sec = 100; // avoid this static bool suppress_primordial_thread_resolution = false; +static bool read_so_path_from_maps(const char* so_name, char* buf, int buflen); + // utility functions julong os::available_memory() { @@ -322,11 +324,11 @@ bool os::have_special_privileges() { #ifndef SYS_gettid -// i386: 224, ia64: 1105, amd64: 186, sparc: 143 +// i386 & arm: 224, ia64: 1105, amd64: 186, sparc: 143, aarch64: 178 #ifdef __ia64__ #define SYS_gettid 1105 #else - #ifdef __i386__ + #if defined(__i386__) || defined(__arm__) #define SYS_gettid 224 #else #ifdef __amd64__ @@ -334,6 +336,8 @@ bool os::have_special_privileges() { #else #ifdef __sparc__ #define SYS_gettid 143 + #elif defined(__arm64__) || defined(__aarch64__) + #define SYS_gettid 178 #else #error define gettid for the arch #endif @@ -515,6 +519,7 @@ extern "C" void breakpoint() { // detecting pthread library void os::Linux::libpthread_init() { +#ifndef __ANDROID__ // Save glibc and pthread version strings. #if !defined(_CS_GNU_LIBC_VERSION) || \ !defined(_CS_GNU_LIBPTHREAD_VERSION) @@ -539,6 +544,9 @@ void os::Linux::libpthread_init() { confstr(_CS_GNU_LIBPTHREAD_VERSION, str, n); os::Linux::set_libpthread_version(str); #endif +#else + os::Linux::set_libpthread_version("NPTL"); +#endif } ///////////////////////////////////////////////////////////////////////////// @@ -1374,7 +1382,13 @@ const char* os::dll_file_extension() { return ".so"; } // This must be hard coded because it's the system's temporary // directory not the java application's temp directory, ala java.io.tmpdir. -const char* os::get_temp_directory() { return "/tmp"; } +const char* os::get_temp_directory() { +#ifndef __ANDROID__ + return "/tmp"; +#else + return "/data/tmp"; +#endif +} static bool file_exists(const char* filename) { struct stat statbuf; @@ -1517,6 +1531,30 @@ bool os::dll_address_to_library_name(address addr, char* buf, return false; } +static bool read_so_path_from_maps(const char* so_name, char* buf, int buflen) { + FILE *fp = fopen("/proc/self/maps", "r"); + assert(fp, "Failed to open /proc/self/maps"); + if (!fp) { + return false; + } + + char maps_buffer[2048]; + while (fgets(maps_buffer, 2048, fp) != NULL) { + if (strstr(maps_buffer, so_name) == NULL) { + continue; + } + + char *so_path = strchr(maps_buffer, '/'); + so_path[strlen(so_path) - 1] = '\0'; // Cut trailing \n + jio_snprintf(buf, buflen, "%s", so_path); + fclose(fp); + return true; + } + + fclose(fp); + return false; +} + // Loads .dll/.so and // in case of error it checks if .dll/.so was built for the // same architecture as Hotspot is running on @@ -1863,6 +1901,7 @@ void * os::Linux::dll_load_in_vmthread(const char *filename, char *ebuf, } const char* os::Linux::dll_path(void* lib) { +#ifdef RTLD_DI_LINKMAP struct link_map *lmap; const char* l_path = NULL; assert(lib != NULL, "dll_path parameter must not be NULL"); @@ -1872,6 +1911,9 @@ const char* os::Linux::dll_path(void* lib) { l_path = lmap->l_name; } return l_path; +#else + return NULL; +#endif } static bool _print_ascii_file(const char* filename, outputStream* st, const char* hdr = NULL) { @@ -2538,6 +2576,19 @@ void os::jvm_path(char *buf, jint buflen) { CAST_FROM_FN_PTR(address, os::jvm_path), dli_fname, sizeof(dli_fname), NULL); assert(ret, "cannot locate libjvm"); +#ifdef __ANDROID__ + if (dli_fname[0] == '\0') { + return; + } + + if (strchr(dli_fname, '/') == NULL) { + bool ok = read_so_path_from_maps(dli_fname, buf, buflen); + assert(ok, "unable to turn relative libjvm.so path into absolute"); + return; + } + + snprintf(buf, buflen, /* "%s/lib/%s/server/%s", java_home_var, cpu_arch, */ "%s", dli_fname); +#else // !__ANDROID__ char *rp = NULL; if (ret && dli_fname[0] != '\0') { rp = os::Posix::realpath(dli_fname, buf, buflen); @@ -2603,6 +2654,7 @@ void os::jvm_path(char *buf, jint buflen) { } } } +#endif strncpy(saved_jvm_path, buf, MAXPATHLEN); saved_jvm_path[MAXPATHLEN - 1] = '\0'; @@ -2937,7 +2989,8 @@ void os::Linux::sched_getcpu_init() { } if (sched_getcpu() == -1) { - vm_exit_during_initialization("getcpu(2) system call not supported by kernel"); + // vm_exit_during_initialization + warning("getcpu(2) system call not supported by kernel"); } } @@ -3554,6 +3607,7 @@ bool os::Linux::hugetlbfs_sanity_check(bool warn, size_t page_size) { } bool os::Linux::shm_hugetlbfs_sanity_check(bool warn, size_t page_size) { +#ifndef __ANDROID__ // Try to create a large shared memory segment. int shmid = shmget(IPC_PRIVATE, page_size, SHM_HUGETLB|IPC_CREAT|SHM_R|SHM_W); if (shmid == -1) { @@ -3575,6 +3629,10 @@ bool os::Linux::shm_hugetlbfs_sanity_check(bool warn, size_t page_size) { // Managed to create a segment, now delete it. shmctl(shmid, IPC_RMID, NULL); return true; +#else + warning("UseSHM not supported on this platform"); + return false; +#endif } // From the coredump_filter documentation: @@ -3838,6 +3896,8 @@ void os::large_page_init() { #define SHM_HUGETLB 04000 #endif +#ifndef __ANDROID__ + #define shm_warning_format(format, ...) \ do { \ if (UseLargePages && \ @@ -3930,8 +3990,11 @@ static char* shmat_large_pages(int shmid, size_t bytes, size_t alignment, char* } } +#endif // !__ANDROID__ + char* os::Linux::reserve_memory_special_shm(size_t bytes, size_t alignment, char* req_addr, bool exec) { +#ifndef __ANDROID__ // "exec" is passed in but not used. Creating the shared image for // the code cache doesn't have an SHM_X executable permission to check. assert(UseLargePages && UseSHM, "only for SHM large pages"); @@ -3976,6 +4039,10 @@ char* os::Linux::reserve_memory_special_shm(size_t bytes, size_t alignment, shmctl(shmid, IPC_RMID, NULL); return addr; +#else + assert(0, "SHM not supported on this platform"); + return NULL; +#endif // !__ANDROID__ } static void warn_on_commit_special_failure(char* req_addr, size_t bytes, @@ -4111,8 +4178,13 @@ char* os::pd_reserve_memory_special(size_t bytes, size_t alignment, size_t page_ } bool os::Linux::release_memory_special_shm(char* base, size_t bytes) { +#ifndef __ANDROID__ // detaching the SHM segment will also delete it, see reserve_memory_special_shm() return shmdt(base) == 0; +#else + assert(0, "SHM not supported on this platform"); + return false; +#endif // SUPPORTS_SHM } bool os::Linux::release_memory_special_huge_tlbfs(char* base, size_t bytes) { @@ -5181,7 +5253,46 @@ bool os::is_thread_cpu_time_supported() { // Linux doesn't yet have a (official) notion of processor sets, // so just return the system wide load average. int os::loadavg(double loadavg[], int nelem) { +#ifndef __ANDROID__ return ::getloadavg(loadavg, nelem); +#else +/* + * Copyright (C) 2018 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + if (nelem < 0) return -1; + if (nelem > 3) nelem = 3; + struct sysinfo si; + if (sysinfo(&si) == -1) return -1; + for (int i = 0; i < nelem; ++i) { + loadavg[i] = static_cast(si.loads[i]) / static_cast(1 << SI_LOAD_SHIFT); + } + return nelem; +#endif } void os::pause() { diff --git a/src/hotspot/os/linux/os_perf_linux.cpp b/src/hotspot/os/linux/os_perf_linux.cpp index 7c42379a0..5b76b3f42 100644 --- a/src/hotspot/os/linux/os_perf_linux.cpp +++ b/src/hotspot/os/linux/os_perf_linux.cpp @@ -45,9 +45,312 @@ #include #include #include +#ifndef __ANDROID__ #include +#else +#include +#include +#include +#include +#include +#include +#include +#include +#endif #include +#ifdef __ANDROID__ +/* + * Copyright (C) 2015 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +__BEGIN_DECLS + +/** + * Returned by getifaddrs() and freed by freeifaddrs(). + */ +struct ifaddrs { + /** Pointer to the next element in the linked list. */ + struct ifaddrs* ifa_next; + + /** Interface name. */ + char* ifa_name; + + /** Interface flags (like `SIOCGIFFLAGS`). */ + unsigned int ifa_flags; + + /** Interface address. */ + struct sockaddr* ifa_addr; + + /** Interface netmask. */ + struct sockaddr* ifa_netmask; + + union { + /** Interface broadcast address (if IFF_BROADCAST is set). */ + struct sockaddr* ifu_broadaddr; + + /** Interface destination address (if IFF_POINTOPOINT is set). */ + struct sockaddr* ifu_dstaddr; + } ifa_ifu; + + /** Unused. */ + void* ifa_data; +}; + +/** Synonym for `ifa_ifu.ifu_broadaddr` in `struct ifaddrs`. */ +#define ifa_broadaddr ifa_ifu.ifu_broadaddr + +/** Synonym for `ifa_ifu.ifu_dstaddr` in `struct ifaddrs`. */ +#define ifa_dstaddr ifa_ifu.ifu_dstaddr + +/** + * [getifaddrs(3)](http://man7.org/linux/man-pages/man3/getifaddrs.3.html) creates a linked list + * of `struct ifaddrs`. The list must be freed by freeifaddrs(). + * + * Returns 0 and stores the list in `*__list_ptr` on success, + * and returns -1 and sets `errno` on failure. + * + * Available since API level 24. + */ +int getifaddrs(struct ifaddrs** __list_ptr); // __INTRODUCED_IN(24); + +/** + * [freeifaddrs(3)](http://man7.org/linux/man-pages/man3/freeifaddrs.3.html) frees a linked list + * of `struct ifaddrs` returned by getifaddrs(). + * + * Available since API level 24. + */ +void freeifaddrs(struct ifaddrs* __ptr); // __INTRODUCED_IN(24); + +__END_DECLS + +#define nullptr 0 + +// The public ifaddrs struct is full of pointers. Rather than track several +// different allocations, we use a maximally-sized structure with the public +// part at offset 0, and pointers into its hidden tail. +struct ifaddrs_storage { + // Must come first, so that `ifaddrs_storage` is-a `ifaddrs`. + ifaddrs ifa; + // The interface index, so we can match RTM_NEWADDR messages with + // earlier RTM_NEWLINK messages (to copy the interface flags). + int interface_index; + // Storage for the pointers in `ifa`. + sockaddr_storage addr; + sockaddr_storage netmask; + sockaddr_storage ifa_ifu; + char name[IFNAMSIZ + 1]; + // Netlink gives us the address family in the header, and the + // sockaddr_in or sockaddr_in6 bytes as the payload. We need to + // stitch the two bits together into the sockaddr that's part of + // our portable interface. + void SetAddress(int family, const void* data, size_t byteCount) { + addr.ss_family = family; + memcpy(SockaddrBytes(family, &addr), data, byteCount); + ifa.ifa_addr = reinterpret_cast(&addr); + } + void SetBroadcastAddress(int family, const void* data, size_t byteCount) { + ifa_ifu.ss_family = family; + memcpy(SockaddrBytes(family, &ifa_ifu), data, byteCount); + ifa.ifa_dstaddr = reinterpret_cast(&ifa_ifu); + } + // Netlink gives us the prefix length as a bit count. We need to turn + // that into a BSD-compatible netmask represented by a sockaddr*. + void SetNetmask(int family, size_t prefix_length) { + // ...and work out the netmask from the prefix length. + netmask.ss_family = family; + uint8_t* dst = SockaddrBytes(family, &netmask); + memset(dst, 0xff, prefix_length / 8); + if ((prefix_length % 8) != 0) { + dst[prefix_length/8] = (0xff << (8 - (prefix_length % 8))); + } + ifa.ifa_netmask = reinterpret_cast(&netmask); + } + void SetPacketAttributes(int ifindex, unsigned short hatype, unsigned char halen) { + sockaddr_ll* sll = reinterpret_cast(&addr); + sll->sll_ifindex = ifindex; + sll->sll_hatype = hatype; + sll->sll_halen = halen; + } + private: + // Returns a pointer to the first byte in the address data (which is + // stored in network byte order). + uint8_t* SockaddrBytes(int family, sockaddr_storage* ss) { + if (family == AF_INET) { + sockaddr_in* ss4 = reinterpret_cast(ss); + return reinterpret_cast(&ss4->sin_addr); + } else if (family == AF_INET6) { + sockaddr_in6* ss6 = reinterpret_cast(ss); + return reinterpret_cast(&ss6->sin6_addr); + } else if (family == AF_PACKET) { + sockaddr_ll* sll = reinterpret_cast(ss); + return reinterpret_cast(&sll->sll_addr); + } + return nullptr; + } +}; +ifaddrs_storage* new_ifaddrs_storage(ifaddrs** list) { + ifaddrs_storage *storage; + memset(storage, 0, sizeof(*storage)); + // push_front onto `list`. + storage->ifa.ifa_next = *list; + *list = reinterpret_cast(storage); + return storage; +} +#if !defined(__clang__) +// GCC gets confused by NLMSG_DATA and doesn't realize that the old-style +// cast is from a system header and should be ignored. +#pragma GCC diagnostic ignored "-Wold-style-cast" +#endif +static void __handle_netlink_response(ifaddrs** out, nlmsghdr* hdr) { + if (hdr->nlmsg_type == RTM_NEWLINK) { + ifinfomsg* ifi = reinterpret_cast(NLMSG_DATA(hdr)); + // Create a new ifaddr entry, and set the interface index and flags. + ifaddrs_storage* new_addr = new_ifaddrs_storage(out); + new_addr->interface_index = ifi->ifi_index; + new_addr->ifa.ifa_flags = ifi->ifi_flags; + // Go through the various bits of information and find the name. + rtattr* rta = IFLA_RTA(ifi); + size_t rta_len = IFLA_PAYLOAD(hdr); + while (RTA_OK(rta, rta_len)) { + if (rta->rta_type == IFLA_ADDRESS) { + if (RTA_PAYLOAD(rta) < sizeof(new_addr->addr)) { + new_addr->SetAddress(AF_PACKET, RTA_DATA(rta), RTA_PAYLOAD(rta)); + new_addr->SetPacketAttributes(ifi->ifi_index, ifi->ifi_type, RTA_PAYLOAD(rta)); + } + } else if (rta->rta_type == IFLA_BROADCAST) { + if (RTA_PAYLOAD(rta) < sizeof(new_addr->ifa_ifu)) { + new_addr->SetBroadcastAddress(AF_PACKET, RTA_DATA(rta), RTA_PAYLOAD(rta)); + new_addr->SetPacketAttributes(ifi->ifi_index, ifi->ifi_type, RTA_PAYLOAD(rta)); + } + } else if (rta->rta_type == IFLA_IFNAME) { + if (RTA_PAYLOAD(rta) < sizeof(new_addr->name)) { + memcpy(new_addr->name, RTA_DATA(rta), RTA_PAYLOAD(rta)); + new_addr->ifa.ifa_name = new_addr->name; + } + } + rta = RTA_NEXT(rta, rta_len); + } + } else if (hdr->nlmsg_type == RTM_NEWADDR) { + ifaddrmsg* msg = reinterpret_cast(NLMSG_DATA(hdr)); + // We should already know about this from an RTM_NEWLINK message. + const ifaddrs_storage* addr = reinterpret_cast(*out); + while (addr != nullptr && addr->interface_index != static_cast(msg->ifa_index)) { + addr = reinterpret_cast(addr->ifa.ifa_next); + } + // If this is an unknown interface, ignore whatever we're being told about it. + if (addr == nullptr) return; + // Create a new ifaddr entry and copy what we already know. + ifaddrs_storage* new_addr = new_ifaddrs_storage(out); + // We can just copy the name rather than look for IFA_LABEL. + strcpy(new_addr->name, addr->name); + new_addr->ifa.ifa_name = new_addr->name; + new_addr->ifa.ifa_flags = addr->ifa.ifa_flags; + new_addr->interface_index = addr->interface_index; + // Go through the various bits of information and find the address + // and any broadcast/destination address. + rtattr* rta = IFA_RTA(msg); + size_t rta_len = IFA_PAYLOAD(hdr); + while (RTA_OK(rta, rta_len)) { + if (rta->rta_type == IFA_ADDRESS) { + if (msg->ifa_family == AF_INET || msg->ifa_family == AF_INET6) { + new_addr->SetAddress(msg->ifa_family, RTA_DATA(rta), RTA_PAYLOAD(rta)); + new_addr->SetNetmask(msg->ifa_family, msg->ifa_prefixlen); + } + } else if (rta->rta_type == IFA_BROADCAST) { + if (msg->ifa_family == AF_INET || msg->ifa_family == AF_INET6) { + new_addr->SetBroadcastAddress(msg->ifa_family, RTA_DATA(rta), RTA_PAYLOAD(rta)); + } + } + rta = RTA_NEXT(rta, rta_len); + } + } +} +static bool __send_netlink_request(int fd, int type) { + struct NetlinkMessage { + nlmsghdr hdr; + rtgenmsg msg; + } request; + memset(&request, 0, sizeof(request)); + request.hdr.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST; + request.hdr.nlmsg_type = type; + request.hdr.nlmsg_len = sizeof(request); + request.msg.rtgen_family = AF_UNSPEC; // All families. + return (TEMP_FAILURE_RETRY(send(fd, &request, sizeof(request), 0)) == sizeof(request)); +} +static bool __read_netlink_responses(int fd, ifaddrs** out, char* buf, size_t buf_len) { + ssize_t bytes_read; + // Read through all the responses, handing interesting ones to __handle_netlink_response. + while ((bytes_read = TEMP_FAILURE_RETRY(recv(fd, buf, buf_len, 0))) > 0) { + nlmsghdr* hdr = reinterpret_cast(buf); + for (; NLMSG_OK(hdr, static_cast(bytes_read)); hdr = NLMSG_NEXT(hdr, bytes_read)) { + if (hdr->nlmsg_type == NLMSG_DONE) return true; + if (hdr->nlmsg_type == NLMSG_ERROR) return false; + __handle_netlink_response(out, hdr); + } + } + // We only get here if recv fails before we see a NLMSG_DONE. + return false; +} +int getifaddrs(ifaddrs** out) { + // Make cleanup easy. + *out = nullptr; + // The kernel keeps packets under 8KiB (NLMSG_GOODSIZE), + // but that's a bit too large to go on the stack. + size_t buf_len = 8192; + char* buf = NEW_C_HEAP_ARRAY(char, buf_len, mtInternal); + if (buf == nullptr) return -1; + // Open the netlink socket and ask for all the links and addresses. + int fd = socket(PF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_ROUTE); + bool okay = fd != -1 && + __send_netlink_request(fd, RTM_GETLINK) && __read_netlink_responses(fd, out, buf, buf_len) && + __send_netlink_request(fd, RTM_GETADDR) && __read_netlink_responses(fd, out, buf, buf_len); + if (!okay) { + freeifaddrs(*out); + // Ensure that callers crash if they forget to check for success. + *out = nullptr; + } + { + int saved_errno = errno; + close(fd); + FREE_C_HEAP_ARRAY(char, buf); + errno = saved_errno; + } + return okay ? 0 : -1; +} +void freeifaddrs(ifaddrs* list) { + while (list != nullptr) { + ifaddrs* current = list; + list = list->ifa_next; + free(current); + } +} +#endif + /** /proc/[number]/stat Status information about the process. This is used by ps(1). It is defined in /usr/src/linux/fs/proc/array.c. diff --git a/src/hotspot/os/posix/os_posix.cpp b/src/hotspot/os/posix/os_posix.cpp index ae058dd34..ea99a3755 100644 --- a/src/hotspot/os/posix/os_posix.cpp +++ b/src/hotspot/os/posix/os_posix.cpp @@ -65,7 +65,9 @@ #include #include #include +#ifndef __ANDROID__ #include +#endif #ifdef __APPLE__ #include @@ -418,6 +420,7 @@ void os::Posix::print_load_average(outputStream* st) { // unfortunately it does not work on macOS and Linux because the utx chain has no entry // for reboot at least on my test machines void os::Posix::print_uptime_info(outputStream* st) { +#ifndef __ANDROID__ int bootsec = -1; int currsec = time(NULL); struct utmpx* ent; @@ -432,6 +435,7 @@ void os::Posix::print_uptime_info(outputStream* st) { if (bootsec != -1) { os::print_dhm(st, "OS uptime:", (long) (currsec-bootsec)); } +#endif } static void print_rlimit(outputStream* st, const char* msg, diff --git a/src/hotspot/os_cpu/linux_aarch64/threadLS_linux_aarch64.S b/src/hotspot/os_cpu/linux_aarch64/threadLS_linux_aarch64.S index f541844b9..dd83b3723 100644 --- a/src/hotspot/os_cpu/linux_aarch64/threadLS_linux_aarch64.S +++ b/src/hotspot/os_cpu/linux_aarch64/threadLS_linux_aarch64.S @@ -19,6 +19,7 @@ // or visit www.oracle.com if you need additional information or have any // questions. +#ifndef __ANDROID__ // JavaThread::aarch64_get_thread_helper() // // Return the current thread pointer in x0. @@ -42,3 +43,4 @@ _ZN10JavaThread25aarch64_get_thread_helperEv: ret .size _ZN10JavaThread25aarch64_get_thread_helperEv, .-_ZN10JavaThread25aarch64_get_thread_helperEv +#endif diff --git a/src/hotspot/os_cpu/linux_aarch64/thread_linux_aarch64.hpp b/src/hotspot/os_cpu/linux_aarch64/thread_linux_aarch64.hpp index 5a1f273c5..88b6750db 100644 --- a/src/hotspot/os_cpu/linux_aarch64/thread_linux_aarch64.hpp +++ b/src/hotspot/os_cpu/linux_aarch64/thread_linux_aarch64.hpp @@ -47,6 +47,13 @@ private: bool pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava); public: - static Thread *aarch64_get_thread_helper(); + static Thread *aarch64_get_thread_helper() +#ifndef __ANDROID__ +; +#else + { + return Thread::current(); + } +#endif #endif // OS_CPU_LINUX_AARCH64_THREAD_LINUX_AARCH64_HPP diff --git a/src/hotspot/os_cpu/linux_arm/fpu_control.h b/src/hotspot/os_cpu/linux_arm/fpu_control.h new file mode 100644 index 000000000..745243d62 --- /dev/null +++ b/src/hotspot/os_cpu/linux_arm/fpu_control.h @@ -0,0 +1,59 @@ +/* FPU control word definitions. ARM VFP version. + Copyright (C) 2004-2019 Free Software Foundation, Inc. + This file is part of the GNU C Library. + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + . */ +#ifndef _FPU_CONTROL_H +#define _FPU_CONTROL_H +#if !(defined(_LIBC) && !defined(_LIBC_TEST)) && defined(__SOFTFP__) +#define _FPU_RESERVED 0xffffffff +#define _FPU_DEFAULT 0x00000000 +typedef unsigned int fpu_control_t; +#define _FPU_GETCW(cw) (cw) = 0 +#define _FPU_SETCW(cw) (void) (cw) +extern fpu_control_t __fpu_control; +#else +/* masking of interrupts */ +#define _FPU_MASK_IM 0x00000100 /* invalid operation */ +#define _FPU_MASK_ZM 0x00000200 /* divide by zero */ +#define _FPU_MASK_OM 0x00000400 /* overflow */ +#define _FPU_MASK_UM 0x00000800 /* underflow */ +#define _FPU_MASK_PM 0x00001000 /* inexact */ +#define _FPU_MASK_NZCV 0xf0000000 /* NZCV flags */ +#define _FPU_MASK_RM 0x00c00000 /* rounding mode */ +#define _FPU_MASK_EXCEPT 0x00001f1f /* all exception flags */ +/* Some bits in the FPSCR are not yet defined. They must be preserved when + modifying the contents. */ +#define _FPU_RESERVED 0x00086060 +#define _FPU_DEFAULT 0x00000000 +/* Default + exceptions enabled. */ +#define _FPU_IEEE (_FPU_DEFAULT | 0x00001f00) +/* Type of the control word. */ +typedef unsigned int fpu_control_t; +/* Macros for accessing the hardware control word. */ +#ifdef __SOFTFP__ +/* This is fmrx %0, fpscr. */ +# define _FPU_GETCW(cw) \ + __asm__ __volatile__ ("mrc p10, 7, %0, cr1, cr0, 0" : "=r" (cw)) +/* This is fmxr fpscr, %0. */ +# define _FPU_SETCW(cw) \ + __asm__ __volatile__ ("mcr p10, 7, %0, cr1, cr0, 0" : : "r" (cw)) +#else +# define _FPU_GETCW(cw) \ + __asm__ __volatile__ ("vmrs %0, fpscr" : "=r" (cw)) +# define _FPU_SETCW(cw) \ + __asm__ __volatile__ ("vmsr fpscr, %0" : : "r" (cw)) +#endif +/* Default control word set at startup. */ +extern fpu_control_t __fpu_control; +#endif /* __SOFTFP__ */ +#endif /* _FPU_CONTROL_H */ diff --git a/src/hotspot/os_cpu/linux_arm/linux_arm_32.S b/src/hotspot/os_cpu/linux_arm/linux_arm_32.S index c1c8fd428..626982e13 100644 --- a/src/hotspot/os_cpu/linux_arm/linux_arm_32.S +++ b/src/hotspot/os_cpu/linux_arm/linux_arm_32.S @@ -94,7 +94,7 @@ dw_f2b_loop_32: stmia to!, {r3 - r9, ip} bgt dw_f2b_loop_32 dw_f2b_loop_32_finish: - addlts r2, #32 + addslt r2, #32 beq disjoint_words_finish cmp r2, #16 blt disjoint_words_small @@ -142,7 +142,7 @@ cw_f2b_loop_32: stmia to!, {r3 - r9, ip} bgt cw_f2b_loop_32 cw_f2b_loop_32_finish: - addlts r2, #32 + addslt r2, #32 beq conjoint_words_finish cmp r2, #16 blt conjoint_words_small @@ -175,7 +175,7 @@ cw_b2f_loop_32: stmdb to!, {r3-r9,ip} bgt cw_b2f_loop_32 cw_b2f_loop_32_finish: - addlts r2, #32 + addslt r2, #32 beq conjoint_words_finish cmp r2, #16 blt cw_b2f_copy_small @@ -227,7 +227,7 @@ cs_f2b_loop_32: stmia to!, {r3 - r9, ip} bgt cs_f2b_loop_32 cs_f2b_loop_32_finish: - addlts r2, #32 + addslt r2, #32 beq conjoint_shorts_finish movs r6, r2, lsr #3 .align 3 @@ -243,11 +243,11 @@ cs_f2b_4: beq conjoint_shorts_finish cmp r2, #4 ldrh r3, [from], #2 - ldrgeh r4, [from], #2 - ldrgth r5, [from], #2 + ldrhge r4, [from], #2 + ldrhgt r5, [from], #2 strh r3, [to], #2 - strgeh r4, [to], #2 - strgth r5, [to], #2 + strhge r4, [to], #2 + strhgt r5, [to], #2 b conjoint_shorts_finish # Destination not aligned @@ -305,11 +305,11 @@ cs_f2b_4_u: beq conjoint_shorts_finish cmp r2, #4 ldrh r3, [from], #2 - ldrgeh r4, [from], #2 - ldrgth r5, [from], #2 + ldrhge r4, [from], #2 + ldrhgt r5, [from], #2 strh r3, [to], #2 - strgeh r4, [to], #2 - strgth r5, [to], #2 + strhge r4, [to], #2 + strhgt r5, [to], #2 b conjoint_shorts_finish # Src and dest overlap, copy in a descending order @@ -332,7 +332,7 @@ cs_b2f_loop_32: stmdb to!, {r3-r9,ip} bgt cs_b2f_loop_32 cs_b2f_loop_32_finish: - addlts r2, #32 + addslt r2, #32 beq conjoint_shorts_finish cmp r2, #24 blt cs_b2f_16 @@ -358,11 +358,11 @@ cs_b2f_8: cs_b2f_all_copy: cmp r2, #4 ldrh r3, [from, #-2]! - ldrgeh r4, [from, #-2]! - ldrgth r5, [from, #-2]! + ldrhge r4, [from, #-2]! + ldrhgt r5, [from, #-2]! strh r3, [to, #-2]! - strgeh r4, [to, #-2]! - strgth r5, [to, #-2]! + strhge r4, [to, #-2]! + strhgt r5, [to, #-2]! b conjoint_shorts_finish # Destination not aligned @@ -397,7 +397,7 @@ cs_b2f_16_loop_u: bgt cs_b2f_16_loop_u beq conjoint_shorts_finish cs_b2f_16_loop_u_finished: - addlts r2, #16 + addslt r2, #16 ldr r3, [from] cmp r2, #10 blt cs_b2f_2_u_loop @@ -460,7 +460,7 @@ cl_f2b_loop_32: stmia to!, {r3 - r9, ip} bgt cl_f2b_loop_32 cl_f2b_loop_32_finish: - addlts r2, #32 + addslt r2, #32 beq conjoint_longs_finish conjoint_longs_small: cmp r2, #16 @@ -493,7 +493,7 @@ cl_b2f_loop_32: stmdb to!, {r3 - r9, ip} bgt cl_b2f_loop_32 cl_b2f_loop_32_finish: - addlts r2, #32 + addslt r2, #32 beq conjoint_longs_finish cmp r2, #16 blt cl_b2f_copy_8 diff --git a/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp b/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp index 6fc0c8406..f0314a729 100644 --- a/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp +++ b/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp @@ -70,7 +70,11 @@ # include # include # include +#ifndef __ANDROID__ # include +#else +# include "fpu_control.h" //include the local header +#endif # include #define SPELL_REG_SP "sp" @@ -81,8 +85,14 @@ #endif address os::current_stack_pointer() { +#if defined(__clang__) || defined(__llvm__) + void *sp; + __asm__("mov %0, " SPELL_REG_SP : "=r"(sp)); + return (address) sp; +#else register address sp __asm__ (SPELL_REG_SP); return sp; +#endif } char* os::non_memory_address_word() { @@ -406,8 +416,8 @@ void os::setup_fpu() { #if !defined(__SOFTFP__) && defined(__VFP_FP__) // Turn on IEEE-754 compliant VFP mode __asm__ volatile ( - "mov %%r0, #0;" - "fmxr fpscr, %%r0" + "mov r0, #0;" + "fmxr fpscr, r0" : /* no output */ : /* no input */ : "r0" ); #endif diff --git a/src/hotspot/os_cpu/linux_x86/fpu_control.h b/src/hotspot/os_cpu/linux_x86/fpu_control.h new file mode 100644 index 000000000..605302c09 --- /dev/null +++ b/src/hotspot/os_cpu/linux_x86/fpu_control.h @@ -0,0 +1,109 @@ +/* FPU control word bits. x86 version. + Copyright (C) 1993-2012 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Olaf Flebbe. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#ifndef _FPU_CONTROL_H +#define _FPU_CONTROL_H 1 + +/* Note that this file sets on x86-64 only the x87 FPU, it does not + touch the SSE unit. */ + +/* Here is the dirty part. Set up your 387 through the control word + * (cw) register. + * + * 15-13 12 11-10 9-8 7-6 5 4 3 2 1 0 + * | reserved | IC | RC | PC | reserved | PM | UM | OM | ZM | DM | IM + * + * IM: Invalid operation mask + * DM: Denormalized operand mask + * ZM: Zero-divide mask + * OM: Overflow mask + * UM: Underflow mask + * PM: Precision (inexact result) mask + * + * Mask bit is 1 means no interrupt. + * + * PC: Precision control + * 11 - round to extended precision + * 10 - round to double precision + * 00 - round to single precision + * + * RC: Rounding control + * 00 - rounding to nearest + * 01 - rounding down (toward - infinity) + * 10 - rounding up (toward + infinity) + * 11 - rounding toward zero + * + * IC: Infinity control + * That is for 8087 and 80287 only. + * + * The hardware default is 0x037f which we use. + */ + +#include + +/* masking of interrupts */ +#define _FPU_MASK_IM 0x01 +#define _FPU_MASK_DM 0x02 +#define _FPU_MASK_ZM 0x04 +#define _FPU_MASK_OM 0x08 +#define _FPU_MASK_UM 0x10 +#define _FPU_MASK_PM 0x20 + +/* precision control */ +#define _FPU_EXTENDED 0x300 /* libm requires double extended precision. */ +#define _FPU_DOUBLE 0x200 +#define _FPU_SINGLE 0x0 + +/* rounding control */ +#define _FPU_RC_NEAREST 0x0 /* RECOMMENDED */ +#define _FPU_RC_DOWN 0x400 +#define _FPU_RC_UP 0x800 +#define _FPU_RC_ZERO 0xC00 + +#define _FPU_RESERVED 0xF0C0 /* Reserved bits in cw */ + + +/* The fdlibm code requires strict IEEE double precision arithmetic, + and no interrupts for exceptions, rounding to nearest. */ + +#define _FPU_DEFAULT 0x037f + +/* IEEE: same as above. */ +#define _FPU_IEEE 0x037f + +/* Type of the control word. */ +typedef unsigned int fpu_control_t __attribute__ ((__mode__ (__HI__))); + +/* Macros for accessing the hardware control word. "*&" is used to + work around a bug in older versions of GCC. __volatile__ is used + to support combination of writing the control register and reading + it back. Without __volatile__, the old value may be used for reading + back under compiler optimization. + + Note that the use of these macros is not sufficient anymore with + recent hardware nor on x86-64. Some floating point operations are + executed in the SSE/SSE2 engines which have their own control and + status register. */ +#define _FPU_GETCW(cw) __asm__ __volatile__ ("fnstcw %0" : "=m" (*&cw)) +#define _FPU_SETCW(cw) __asm__ __volatile__ ("fldcw %0" : : "m" (*&cw)) + +/* Default control word set at startup. */ +extern fpu_control_t __fpu_control; + +#endif /* fpu_control.h */ diff --git a/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp b/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp index cc71b0d27..d3a40d433 100644 --- a/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp +++ b/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp @@ -73,8 +73,10 @@ # include # include # include -#ifndef AMD64 +#if !defined(AMD64) && !defined(__ANDROID__) # include +#elif defined(__ANDROID__) +# include "fpu_control.h" #endif #ifdef AMD64 diff --git a/src/hotspot/share/utilities/elfFile.hpp b/src/hotspot/share/utilities/elfFile.hpp index 0db847238..cee0456ed 100644 --- a/src/hotspot/share/utilities/elfFile.hpp +++ b/src/hotspot/share/utilities/elfFile.hpp @@ -47,8 +47,10 @@ typedef Elf64_Phdr Elf_Phdr; typedef Elf64_Sym Elf_Sym; #if !defined(_ALLBSD_SOURCE) || defined(__APPLE__) +#ifndef ELF_ST_TYPE #define ELF_ST_TYPE ELF64_ST_TYPE #endif +#endif #else @@ -63,9 +65,11 @@ typedef Elf32_Phdr Elf_Phdr; typedef Elf32_Sym Elf_Sym; #if !defined(_ALLBSD_SOURCE) || defined(__APPLE__) +#ifndef ELF_ST_TYPE #define ELF_ST_TYPE ELF32_ST_TYPE #endif #endif +#endif #include "globalDefinitions.hpp" #include "memory/allocation.hpp" diff --git a/src/hotspot/share/utilities/globalDefinitions_gcc.hpp b/src/hotspot/share/utilities/globalDefinitions_gcc.hpp index 30cca9ee7..896690c9a 100644 --- a/src/hotspot/share/utilities/globalDefinitions_gcc.hpp +++ b/src/hotspot/share/utilities/globalDefinitions_gcc.hpp @@ -48,6 +48,10 @@ #include #include +#if defined(__ANDROID__) && !defined(ANDROID) +#define ANDROID 1 +#endif + #if defined(LINUX) || defined(_ALLBSD_SOURCE) #include #include diff --git a/src/java.base/share/native/libtinyiconv/iconv.cpp b/src/java.base/share/native/libtinyiconv/iconv.cpp new file mode 100644 index 000000000..7018b6ce2 --- /dev/null +++ b/src/java.base/share/native/libtinyiconv/iconv.cpp @@ -0,0 +1,438 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef __ANDROID__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +__BEGIN_DECLS + +/* + * These return values are specified by POSIX for multibyte conversion + * functions. + */ + +#ifdef __cplusplus +#define __MB_ERR_ILLEGAL_SEQUENCE static_cast(-1) +#define __MB_ERR_INCOMPLETE_SEQUENCE static_cast(-2) +#else +#define __MB_ERR_ILLEGAL_SEQUENCE (size_t)(-1) +#define __MB_ERR_INCOMPLETE_SEQUENCE (size_t)(-2) +#endif // __cplusplus +#define __MB_IS_ERR(rv) (rv == __MB_ERR_ILLEGAL_SEQUENCE || \ + rv == __MB_ERR_INCOMPLETE_SEQUENCE) +static inline __wur size_t mbstate_bytes_so_far(const mbstate_t* ps) { + return + (ps->__seq[2] != 0) ? 3 : + (ps->__seq[1] != 0) ? 2 : + (ps->__seq[0] != 0) ? 1 : 0; +} +static inline void mbstate_set_byte(mbstate_t* ps, int i, char byte) { + ps->__seq[i] = (uint8_t)(byte); +} +static inline __wur uint8_t mbstate_get_byte(const mbstate_t* ps, int n) { + return ps->__seq[n]; +} +static inline __wur size_t mbstate_reset_and_return_illegal(int _errno, mbstate_t* ps) { + errno = _errno; +#ifdef __cplusplus + *(reinterpret_cast(ps->__seq)) = 0; +#else + *(uint32_t*)(ps->__seq) = 0; +#endif // __cplusplus + return __MB_ERR_ILLEGAL_SEQUENCE; +} +static inline __wur size_t mbstate_reset_and_return(int _return, mbstate_t* ps) { +#ifdef __cplusplus + *(reinterpret_cast(ps->__seq)) = 0; +#else + *(uint32_t*)(ps->__seq) = 0; +#endif // __cplusplus + return _return; +} + +#ifdef __cplusplus +# define INVALID_ICONV_T reinterpret_cast(-1) +#else // !__cplusplus +# define INVALID_ICONV_T (iconv_t)(-1) +#endif // __cplusplus + +// Ideally we'd use icu4c but the API mismatch seems too great. So we just offer something +// equivalent to (but slightly easier to use for runs of text than) . If you're +// here to add more encodings, consider working on finishing the icu4c NDK wrappers instead. + +#ifdef __cplusplus + enum Encoding +#else + typedef enum +#endif // __cplusplus +{ + US_ASCII, + UTF_8, + UTF_16_LE, + UTF_16_BE, + UTF_32_LE, + UTF_32_BE, + WCHAR_T, +#ifdef __cplusplus + }; +#else + } Encoding; +#endif // __cplusplus + +#ifdef __cplusplus + enum Mode +#else + typedef enum +#endif // __cplusplus +{ + ERROR, + IGNORE, + TRANSLIT, +#ifdef __cplusplus + }; +#else + } Mode; +#endif // __cplusplus + +// This matching is strange but true. +// See http://www.unicode.org/reports/tr22/#Charset_Alias_Matching. +static bool __match_encoding(const char* lhs, const char* rhs) { + while (*lhs && *rhs) { + // Skip non-alnum in lhs; "UTF-8", "UTF_8", "UTF8", "UTF 8" are all equivalent. + // Also implement the "delete each 0 that is not preceded by a digit" rule. + for (; *lhs; ++lhs) { + if (isalnum(*lhs) && (*lhs != '0' || !isdigit(*(lhs + 1)))) break; + } + // Case doesn't matter either. + if (tolower(*lhs) != tolower(*rhs)) break; + ++lhs; + ++rhs; + } + // As a special case we treat the GNU "//" extensions as end of string. + if ((*lhs == '\0' || strstr(lhs, "//") == lhs) && *rhs == '\0') return true; + return false; +} + +static bool __parse_encoding(const char* s, Encoding* encoding, Mode* mode) { + const char* suffix = strstr(s, "//"); + if (suffix) { + if (!mode) return false; + if (strcmp(suffix, "//IGNORE") == 0) { + *mode = IGNORE; + } else if (strcmp(suffix, "//TRANSLIT") == 0) { + *mode = TRANSLIT; + } else { + return false; + } + } + if (__match_encoding(s, "utf8")) { + *encoding = UTF_8; + } else if (__match_encoding(s, "ascii") || __match_encoding(s, "usascii")) { + *encoding = US_ASCII; + } else if (__match_encoding(s, "utf16le")) { + *encoding = UTF_16_LE; + } else if (__match_encoding(s, "utf16be")) { + *encoding = UTF_16_BE; + } else if (__match_encoding(s, "utf32le")) { + *encoding = UTF_32_LE; + } else if (__match_encoding(s, "utf32be")) { + *encoding = UTF_32_BE; + } else if (__match_encoding(s, "wchart")) { + *encoding = WCHAR_T; + } else { + return false; + } + return true; +} + +struct __iconv_t { + Encoding src_encoding; + Encoding dst_encoding; + Mode mode; +/* + __iconv_t() : mode(ERROR) { + } +*/ + int Convert(char** src_buf0, size_t* src_bytes_left0, char** dst_buf0, size_t* dst_bytes_left0) { + // Reset state. + wc = 0; + memset(&ps, 0, sizeof(ps)); + replacement_count = 0; + ignored = false; + src_buf = src_buf0; + src_bytes_left = src_bytes_left0; + dst_buf = dst_buf0; + dst_bytes_left = dst_bytes_left0; + while (*src_bytes_left > 0) { + if (!GetNext() || !Convert()) return -1; + } + return Done(); + } + private: + char32_t wc; + char buf[16]; + size_t src_bytes_used; + size_t dst_bytes_used; + mbstate_t ps; + size_t replacement_count; + bool ignored; + char** src_buf; + size_t* src_bytes_left; + char** dst_buf; + size_t* dst_bytes_left; + bool GetNext() { + errno = 0; + switch (src_encoding) { + case US_ASCII: + wc = **src_buf; + src_bytes_used = 1; + if (wc > 0x7f) errno = EILSEQ; + break; + case UTF_8: + src_bytes_used = mbrtoc32(&wc, *src_buf, *src_bytes_left, &ps); + if (src_bytes_used == __MB_ERR_ILLEGAL_SEQUENCE) { + break; // EILSEQ already set. + } else if (src_bytes_used == __MB_ERR_INCOMPLETE_SEQUENCE) { + errno = EINVAL; + return false; + } + break; + case UTF_16_BE: + case UTF_16_LE: { + if (*src_bytes_left < 2) { + errno = EINVAL; + return false; + } + bool swap = (src_encoding == UTF_16_BE); + wc = In16(*src_buf, swap); + // 0xd800-0xdbff: high surrogates + // 0xdc00-0xdfff: low surrogates + if (wc >= 0xd800 && wc <= 0xdfff) { + if (wc >= 0xdc00) { // Low surrogate before high surrogate. + errno = EILSEQ; + return false; + } + if (*src_bytes_left < 4) { + errno = EINVAL; + return false; + } + uint16_t hi = wc; + uint16_t lo = In16(*src_buf + 2, swap); + wc = 0x10000 + ((hi - 0xd800) << 10) + (lo - 0xdc00); + src_bytes_used = 4; + } + break; + } + case UTF_32_BE: + case UTF_32_LE: + case WCHAR_T: + if (*src_bytes_left < 4) { + errno = EINVAL; + return false; + } + wc = In32(*src_buf, (src_encoding == UTF_32_BE)); + break; + } + if (errno == EILSEQ) { + switch (mode) { + case ERROR: + return false; + case IGNORE: + *src_buf += src_bytes_used; + *src_bytes_left -= src_bytes_used; + ignored = true; + return GetNext(); + case TRANSLIT: + wc = '?'; + ++replacement_count; + return true; + } + } + return true; + } + + bool Convert() { + errno = 0; + switch (dst_encoding) { + case US_ASCII: + buf[0] = wc; + dst_bytes_used = 1; + if (wc > 0x7f) errno = EILSEQ; + break; + case UTF_8: + dst_bytes_used = c32rtomb(buf, wc, &ps); + if (dst_bytes_used == __MB_ERR_ILLEGAL_SEQUENCE) { + break; // EILSEQ already set. + } else if (dst_bytes_used == __MB_ERR_INCOMPLETE_SEQUENCE) { + errno = EINVAL; + return false; + } + break; + case UTF_16_BE: + case UTF_16_LE: { + bool swap = (dst_encoding == UTF_16_BE); + if (wc < 0x10000) { // BMP. + Out16(buf, wc, swap); + } else { // Supplementary plane; output surrogate pair. + wc -= 0x10000; + char16_t hi = 0xd800 | (wc >> 10); + char16_t lo = 0xdc00 | (wc & 0x3ff); + Out16(buf + 0, hi, swap); + Out16(buf + 2, lo, swap); + dst_bytes_used = 4; + } + } break; + case UTF_32_BE: + case UTF_32_LE: + case WCHAR_T: + Out32(wc, (dst_encoding == UTF_32_BE)); + break; + } + if (errno == EILSEQ) { + if (mode == IGNORE) { + *src_buf += src_bytes_used; + *src_bytes_left -= src_bytes_used; + ignored = true; + return true; + } else if (mode == TRANSLIT) { + wc = '?'; + ++replacement_count; + return Convert(); + } + return false; + } + return Emit(); + } + + uint16_t In16(const char* buf, bool swap) { +#ifdef __cplusplus + const uint8_t* src = reinterpret_cast(buf); +#else // !__cplusplus + const uint8_t* src = (const uint8_t*)(buf); +#endif // __cplusplus + uint16_t wc = (src[0]) | (src[1] << 8); + if (swap) wc = __swap16(wc); + src_bytes_used = 2; + return wc; + } + + uint32_t In32(const char* buf, bool swap) { +#ifdef __cplusplus + const uint8_t* src = reinterpret_cast(buf); +#else // !__cplusplus + const uint8_t* src = (const uint8_t*)(buf); +#endif // __cplusplus + uint32_t wc = (src[0]) | (src[1] << 8) | (src[2] << 16) | (src[3] << 24); + if (swap) wc = __swap32(wc); + src_bytes_used = 4; + return wc; + } + + void Out16(char* dst, char16_t ch, bool swap) { + if (swap) ch = __swap16(ch); + dst[0] = ch; + dst[1] = ch >> 8; + dst_bytes_used = 2; + } + + void Out32(char32_t ch, bool swap) { + if (swap) ch = __swap32(ch); + buf[0] = ch; + buf[1] = ch >> 8; + buf[2] = ch >> 16; + buf[3] = ch >> 24; + dst_bytes_used = 4; + } + + bool Emit() { + if (dst_bytes_used > *dst_bytes_left) { + errno = E2BIG; + return false; + } + memcpy(*dst_buf, buf, dst_bytes_used); + *src_buf += src_bytes_used; + *src_bytes_left -= src_bytes_used; + *dst_buf += dst_bytes_used; + *dst_bytes_left -= dst_bytes_used; + return true; + } + + int Done() { + if (mode == TRANSLIT) return replacement_count; + if (ignored) { + errno = EILSEQ; + return -1; + } + return 0; + } +}; + +iconv_t iconv_open(const char* __dst_encoding, const char* __src_encoding) { + iconv_t result = iconv_t(); + result->mode = ERROR; + if (!__parse_encoding(__src_encoding, &result->src_encoding, 0 /* nullptr */) || + !__parse_encoding(__dst_encoding, &result->dst_encoding, &result->mode)) { + free(result); + errno = EINVAL; + return INVALID_ICONV_T; + } + return result; +} + +size_t iconv(iconv_t __converter, + char** __src_buf, size_t* __src_bytes_left, + char** __dst_buf, size_t* __dst_bytes_left) { + if (__converter == INVALID_ICONV_T) { + errno = EBADF; + return -1; + } + return __converter->Convert(__src_buf, __src_bytes_left, __dst_buf, __dst_bytes_left); +} + +int iconv_close(iconv_t __converter) { + if (__converter == INVALID_ICONV_T) { + errno = EBADF; + return -1; + } + free(__converter); + return 0; +} + +__END_DECLS + +#endif // __ANDROID__ diff --git a/src/java.base/unix/classes/sun/net/dns/ResolverConfigurationImpl.java b/src/java.base/unix/classes/sun/net/dns/ResolverConfigurationImpl.java index d46138f23..eadaf92a4 100644 --- a/src/java.base/unix/classes/sun/net/dns/ResolverConfigurationImpl.java +++ b/src/java.base/unix/classes/sun/net/dns/ResolverConfigurationImpl.java @@ -62,9 +62,11 @@ public class ResolverConfigurationImpl { LinkedList ll = new LinkedList<>(); + String resolvPath = System.getProperty("ext.net.resolvPath", "/etc/resolv.conf"); + try { BufferedReader in = - new BufferedReader(new FileReader("/etc/resolv.conf")); + new BufferedReader(new FileReader(resolvPath)); String line; while ((line = in.readLine()) != null) { int maxvalues = maxperkeyword; diff --git a/src/java.base/unix/native/libjava/java_props_md.c b/src/java.base/unix/native/libjava/java_props_md.c index 36a08d4c1..a0eca754b 100644 --- a/src/java.base/unix/native/libjava/java_props_md.c +++ b/src/java.base/unix/native/libjava/java_props_md.c @@ -46,6 +46,100 @@ #include "java_props_macosx.h" #endif +#ifdef __ANDROID__ +// From https://android.googlesource.com/platform/bionic/+/master/libc/bionic/langinfo.cpp +/* + * Copyright (C) 2016 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +char* nl_langinfo(nl_item item) { + const char* result = ""; + switch (item) { + case CODESET: result = (MB_CUR_MAX == 1) ? "ASCII" : "UTF-8"; break; + case D_T_FMT: result = "%F %T %z"; break; + case D_FMT: result = "%F"; break; + case T_FMT: result = "%T"; break; + case T_FMT_AMPM: result = "%I:%M:%S %p"; break; + case AM_STR: result = "AM"; break; + case PM_STR: result = "PM"; break; + case DAY_1: result = "Sunday"; break; + case DAY_2: result = "Monday"; break; + case DAY_3: result = "Tuesday"; break; + case DAY_4: result = "Wednesday"; break; + case DAY_5: result = "Thursday"; break; + case DAY_6: result = "Friday"; break; + case DAY_7: result = "Saturday"; break; + case ABDAY_1: result = "Sun"; break; + case ABDAY_2: result = "Mon"; break; + case ABDAY_3: result = "Tue"; break; + case ABDAY_4: result = "Wed"; break; + case ABDAY_5: result = "Thu"; break; + case ABDAY_6: result = "Fri"; break; + case ABDAY_7: result = "Sat"; break; + case MON_1: result = "January"; break; + case MON_2: result = "February"; break; + case MON_3: result = "March"; break; + case MON_4: result = "April"; break; + case MON_5: result = "May"; break; + case MON_6: result = "June"; break; + case MON_7: result = "July"; break; + case MON_8: result = "August"; break; + case MON_9: result = "September"; break; + case MON_10: result = "October"; break; + case MON_11: result = "November"; break; + case MON_12: result = "December"; break; + case ABMON_1: result = "Jan"; break; + case ABMON_2: result = "Feb"; break; + case ABMON_3: result = "Mar"; break; + case ABMON_4: result = "Apr"; break; + case ABMON_5: result = "May"; break; + case ABMON_6: result = "Jun"; break; + case ABMON_7: result = "Jul"; break; + case ABMON_8: result = "Aug"; break; + case ABMON_9: result = "Sep"; break; + case ABMON_10: result = "Oct"; break; + case ABMON_11: result = "Nov"; break; + case ABMON_12: result = "Dec"; break; + case ERA: result = ""; break; + case ERA_D_FMT: result = ""; break; + case ERA_D_T_FMT: result = ""; break; + case ERA_T_FMT: result = ""; break; + case ALT_DIGITS: result = ""; break; + case RADIXCHAR: result = "."; break; + case THOUSEP: result = ""; break; + case YESEXPR: result = "^[yY]"; break; + case NOEXPR: result = "^[nN]"; break; + case CRNCYSTR: result = ""; break; + default: break; + } + return (char*) result; +} +#endif + #if defined(_ALLBSD_SOURCE) #if !defined(P_tmpdir) #include diff --git a/src/java.base/unix/native/libjava/jni_util_md.c b/src/java.base/unix/native/libjava/jni_util_md.c index 460503cd7..193480e73 100644 --- a/src/java.base/unix/native/libjava/jni_util_md.c +++ b/src/java.base/unix/native/libjava/jni_util_md.c @@ -31,7 +31,7 @@ #include "jni_util.h" #include "dlfcn.h" -#if defined(LINUX) && (defined(_GNU_SOURCE) || \ +#if !defined(__ANDROID__) && defined(LINUX) && (defined(_GNU_SOURCE) || \ (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE < 200112L \ && defined(_XOPEN_SOURCE) && _XOPEN_SOURCE < 600)) extern int __xpg_strerror_r(int, char *, size_t); diff --git a/src/java.base/unix/native/libjava/posix_spawn.c b/src/java.base/unix/native/libjava/posix_spawn.c new file mode 100644 index 000000000..f9032bab4 --- /dev/null +++ b/src/java.base/unix/native/libjava/posix_spawn.c @@ -0,0 +1,147 @@ +// From https://android.googlesource.com/platform/external/dhcpcd-6.8.2/+/refs/heads/pie-dr1-release/compat/posix_spawn.c +/* + * dhcpcd - DHCP client daemon + * Copyright (c) 2006-2012 Roy Marples + * All rights reserved + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* This implementation of posix_spawn is only suitable for the needs of dhcpcd + * but it could easily be extended to other applications. */ + +#include +#include +#include +#include +#include +#include +#include + +#include "posix_spawn.h" + +#ifndef _NSIG +#ifdef _SIG_MAXSIG +#define _NSIG _SIG_MAXSIG + 1 +#else +/* Guess */ +#define _NSIG SIGPWR + 1 +#endif +#endif + +extern char **environ; + +static int +posix_spawnattr_handle(const posix_spawnattr_t *attrp) +{ + struct sigaction sa; + int i; + if (attrp->posix_attr_flags & POSIX_SPAWN_SETSIGMASK) + sigprocmask(SIG_SETMASK, &attrp->posix_attr_sigmask, NULL); + if (attrp->posix_attr_flags & POSIX_SPAWN_SETSIGDEF) { + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = SIG_DFL; + for (i = 1; i < _NSIG; i++) { + if (sigismember(&attrp->posix_attr_sigdefault, i)) { + if (sigaction(i, &sa, NULL) == -1) + return -1; + } + } + } + return 0; +} + +inline static int +is_vfork_safe(short int flags) +{ + return !(flags & (POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK)); +} + +int +posix_spawn(pid_t *pid, const char *path, + const posix_spawn_file_actions_t *file_actions, + const posix_spawnattr_t *attrp, + char *const argv[], char *const envp[]) +{ + short int flags; + pid_t p; + volatile int error; + error = 0; + flags = attrp ? attrp->posix_attr_flags : 0; + if (file_actions == NULL && is_vfork_safe(flags)) + p = vfork(); + else +#ifdef THERE_IS_NO_FORK + return ENOSYS; +#else + p = fork(); +#endif + switch (p) { + case -1: + return errno; + case 0: + if (attrp) { + error = posix_spawnattr_handle(attrp); + if (error) + _exit(127); + } + execve(path, argv, envp); + error = errno; + _exit(127); + default: + if (error != 0) + waitpid(p, NULL, WNOHANG); + else if (pid != NULL) + *pid = p; + return error; + } +} + +int +posix_spawnattr_init(posix_spawnattr_t *attr) +{ + memset(attr, 0, sizeof(*attr)); + attr->posix_attr_flags = 0; + sigprocmask(0, NULL, &attr->posix_attr_sigmask); + sigemptyset(&attr->posix_attr_sigdefault); + return 0; +} + +int +posix_spawnattr_setflags(posix_spawnattr_t *attr, short flags) +{ + attr->posix_attr_flags = flags; + return 0; +} + +int +posix_spawnattr_setsigmask(posix_spawnattr_t *attr, const sigset_t *sigmask) +{ + attr->posix_attr_sigmask = *sigmask; + return 0; +} + +int +posix_spawnattr_setsigdefault(posix_spawnattr_t *attr, const sigset_t *sigmask) +{ + attr->posix_attr_sigdefault = *sigmask; + return 0; +} diff --git a/src/java.base/unix/native/libjava/posix_spawn.h b/src/java.base/unix/native/libjava/posix_spawn.h new file mode 100644 index 000000000..388016eb3 --- /dev/null +++ b/src/java.base/unix/native/libjava/posix_spawn.h @@ -0,0 +1,53 @@ +// From https://android.googlesource.com/platform/external/dhcpcd-6.8.2/+/refs/heads/pie-dr1-release/compat/posix_spawn.h +/* + * dhcpcd - DHCP client daemon + * Copyright (c) 2006-2012 Roy Marples + * All rights reserved + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef POSIX_SPAWN_H +#define POSIX_SPAWN_H + +#include + +typedef struct { + short posix_attr_flags; +#define POSIX_SPAWN_SETSIGDEF 0x10 +#define POSIX_SPAWN_SETSIGMASK 0x20 + sigset_t posix_attr_sigmask; + sigset_t posix_attr_sigdefault; +} posix_spawnattr_t; + +typedef struct { +// int unused; +} posix_spawn_file_actions_t; + +int posix_spawn(pid_t *, const char *, + const posix_spawn_file_actions_t *, const posix_spawnattr_t *, + char *const [], char *const []); +int posix_spawnattr_init(posix_spawnattr_t *); +int posix_spawnattr_setflags(posix_spawnattr_t *, short); +int posix_spawnattr_setsigmask(posix_spawnattr_t *, const sigset_t *); +int posix_spawnattr_setsigdefault(posix_spawnattr_t *, const sigset_t *); + +#endif diff --git a/src/java.base/unix/native/libjli/java_md.c b/src/java.base/unix/native/libjli/java_md.c index 503a2457b..d6ac325c8 100644 --- a/src/java.base/unix/native/libjli/java_md.c +++ b/src/java.base/unix/native/libjli/java_md.c @@ -585,7 +585,58 @@ const char* SetExecname(char **argv) { char* exec_path = NULL; -#if defined(__linux__) +#if defined(__ANDROID__) //Since both __ANDROID__ and __linux__ are defined, we must let the preprocessor preprocess the __ANDRIOD__ part first + char *__java_home = getenv("JAVA_HOME"); + // From http://hg.openjdk.java.net/mobile/jdk9/jdk/file/17bb8a98d5e3/src/java.base/unix/native/libjli/java_md_solinux.c#l844 + /* For Android, 'self' would point to /system/bin/app_process + * since we are really executing a Dalvik program at this point. + * argv[0] points to the Dalvik application name and we set the + * path to __java_home. + */ + char buf[PATH_MAX+1]; + char *p = NULL; + if ((p = JLI_StrRChr(argv[0], '/')) != 0) { + /* may be running from command line */ + p++; + if ((JLI_StrLen(p) == 4) && JLI_StrCmp(p, "java") == 0) { + /* started as 'java'. Must be command line */ + JLI_TraceLauncher("SetExecName maybe command line = %s\n", argv[0]); + if (*argv[0] != '/') { + char *curdir = NULL; + /* get absolute path */ + getcwd(buf, PATH_MAX); + curdir = JLI_StringDup(buf); + JLI_Snprintf(buf, PATH_MAX, "%s/%s", curdir, argv[0]); + JLI_MemFree(curdir); + } else { + JLI_Snprintf(buf, PATH_MAX, "%s", argv[0]); + } + } else { + /* Not command line, see if __java_home set */ + if (__java_home != NULL) { + JLI_TraceLauncher("SetExecName not java = %s\n", __java_home); + JLI_Snprintf(buf, PATH_MAX, "%s/bin/java", __java_home); + } else { + /* Fake it as best we can or should we punt? */ + JLI_TraceLauncher("SetExecName fake it = %s\n", argv[0]); + JLI_Snprintf(buf, PATH_MAX, "/data/data/%s/storage/jvm/bin/java", + argv[0]); + } + } + } else { + /* Not started as 'java', see if __java_home set */ + if (__java_home != NULL) { + JLI_TraceLauncher("SetExecName not command line = %s\n", __java_home); + JLI_Snprintf(buf, PATH_MAX, "%s/bin/java", __java_home); + } else { + /* Fake it as best we can or should we punt? */ + JLI_TraceLauncher("SetExecName fake it 2 = %s\n", argv[0]); + JLI_Snprintf(buf, PATH_MAX, "/data/data/%s/storage/jvm/bin/java", + argv[0]); + } + } + exec_path = JLI_StringDup(buf); +#elif defined(__linux__) { const char* self = "/proc/self/exe"; char buf[PATH_MAX+1]; @@ -595,10 +646,6 @@ SetExecname(char **argv) exec_path = JLI_StringDup(buf); } } -#else /* !__linux__ */ - { - /* Not implemented */ - } #endif if (exec_path == NULL) { diff --git a/src/java.base/unix/native/libnet/net_util_md.h b/src/java.base/unix/native/libnet/net_util_md.h index 68835987b..eafd4509e 100644 --- a/src/java.base/unix/native/libnet/net_util_md.h +++ b/src/java.base/unix/native/libnet/net_util_md.h @@ -26,6 +26,9 @@ #ifndef NET_UTILS_MD_H #define NET_UTILS_MD_H +#ifdef ANDROID +#include +#endif #include #include #include diff --git a/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c b/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c index 9df8be1e6..12f9b4de3 100644 --- a/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c +++ b/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c @@ -140,6 +140,7 @@ typedef int fstatat64_func(int, const char *, struct stat64 *, int); typedef int unlinkat_func(int, const char*, int); typedef int renameat_func(int, const char*, int, const char*); typedef int futimesat_func(int, const char *, const struct timeval *); +typedef int utimensat_func(int, const char *, const struct timespec *, int flags); typedef int futimens_func(int, const struct timespec *); typedef int lutimes_func(const char *, const struct timeval *); typedef DIR* fdopendir_func(int); @@ -149,10 +150,46 @@ static fstatat64_func* my_fstatat64_func = NULL; static unlinkat_func* my_unlinkat_func = NULL; static renameat_func* my_renameat_func = NULL; static futimesat_func* my_futimesat_func = NULL; +static utimensat_func* my_utimensat_func = NULL; static futimens_func* my_futimens_func = NULL; static lutimes_func* my_lutimes_func = NULL; static fdopendir_func* my_fdopendir_func = NULL; +#ifdef __ANDROID__ +/* + * TODO: Android lacks support for the methods listed below. In it's place are + * alternatives that use existing Android functionality, but lack reentrant + * support. Determine if the following are the most suitable alternatives. + * + */ +int getgrgid_r(gid_t gid, struct group* grp, char* buf, size_t buflen, struct group** result) { + + *result = NULL; + errno = 0; + grp = getgrgid(gid); + if (grp == NULL) { + return errno; + } + // buf not used by caller (see below) + *result = grp; + return 0; +} + +int getgrnam_r(const char *name, struct group* grp, char* buf, size_t buflen, struct group** result) { + + *result = NULL; + errno = 0; + grp = getgrnam(name); + if (grp == NULL) { + return errno; + } + // buf not used by caller (see below) + *result = grp; + return 0; + +} +#endif + /** * fstatat missing from glibc on Linux. */ @@ -272,6 +309,9 @@ Java_sun_nio_fs_UnixNativeDispatcher_init(JNIEnv* env, jclass this) #ifndef _ALLBSD_SOURCE my_futimesat_func = (futimesat_func*) dlsym(RTLD_DEFAULT, "futimesat"); my_lutimes_func = (lutimes_func*) dlsym(RTLD_DEFAULT, "lutimes"); +#endif +#ifdef __ANDROID__ + my_utimensat_func = (utimensat_func*) dlsym(RTLD_DEFAULT, "utimensat"); #endif my_futimens_func = (futimens_func*) dlsym(RTLD_DEFAULT, "futimens"); #if defined(_AIX) @@ -292,7 +332,7 @@ Java_sun_nio_fs_UnixNativeDispatcher_init(JNIEnv* env, jclass this) capabilities |= sun_nio_fs_UnixNativeDispatcher_SUPPORTS_FUTIMES; capabilities |= sun_nio_fs_UnixNativeDispatcher_SUPPORTS_LUTIMES; #else - if (my_futimesat_func != NULL) + if (my_futimesat_func != NULL || my_utimensat_func != NULL) capabilities |= sun_nio_fs_UnixNativeDispatcher_SUPPORTS_FUTIMES; if (my_lutimes_func != NULL) capabilities |= sun_nio_fs_UnixNativeDispatcher_SUPPORTS_LUTIMES; @@ -304,7 +344,7 @@ Java_sun_nio_fs_UnixNativeDispatcher_init(JNIEnv* env, jclass this) if (my_openat64_func != NULL && my_fstatat64_func != NULL && my_unlinkat_func != NULL && my_renameat_func != NULL && - my_futimesat_func != NULL && my_fdopendir_func != NULL) + (my_futimesat_func != NULL || my_utimensat_func != NULL) && my_fdopendir_func != NULL) { capabilities |= sun_nio_fs_UnixNativeDispatcher_SUPPORTS_OPENAT; } @@ -689,22 +729,30 @@ Java_sun_nio_fs_UnixNativeDispatcher_futimes(JNIEnv* env, jclass this, jint file jlong accessTime, jlong modificationTime) { struct timeval times[2]; + struct timespec times2[2]; int err = 0; - times[0].tv_sec = accessTime / 1000000; + times[0].tv_sec = times2[0].tv_sec = accessTime / 1000000; times[0].tv_usec = accessTime % 1000000; - times[1].tv_sec = modificationTime / 1000000; + times[1].tv_sec = times2[1].tv_sec = modificationTime / 1000000; times[1].tv_usec = modificationTime % 1000000; + times2[0].tv_nsec = times[0].tv_usec * 1000; + times2[1].tv_nsec = times[1].tv_usec * 1000; + #ifdef _ALLBSD_SOURCE RESTARTABLE(futimes(filedes, ×[0]), err); #else - if (my_futimesat_func == NULL) { - JNU_ThrowInternalError(env, "my_futimesat_func is NULL"); + if (my_futimesat_func == NULL && my_utimensat_func == NULL) { + JNU_ThrowInternalError(env, "my_futimesat_func and my_utimensat_func are NULL"); return; } - RESTARTABLE((*my_futimesat_func)(filedes, NULL, ×[0]), err); + if (my_futimesat_func != NULL) { + RESTARTABLE((*my_futimesat_func)(filedes, NULL, ×[0]), err); + } else { + RESTARTABLE((*my_utimensat_func)(filedes, NULL, ×2[0], 0), err); + } #endif if (err == -1) { throwUnixException(env, errno); diff --git a/src/java.desktop/unix/native/libawt/awt/awt_LoadLibrary.c b/src/java.desktop/unix/native/libawt/awt/awt_LoadLibrary.c index fbd6ce9d1..94d238f8e 100644 --- a/src/java.desktop/unix/native/libawt/awt/awt_LoadLibrary.c +++ b/src/java.desktop/unix/native/libawt/awt/awt_LoadLibrary.c @@ -30,6 +30,7 @@ #include #include #include +#include #include "gdefs.h" #include @@ -98,6 +99,30 @@ JNIEXPORT jboolean JNICALL AWTIsHeadless() { #define HEADLESS_PATH "/libawt_headless.so" #endif +static bool read_so_path_from_maps(const char* so_name, char* buf) { + FILE *fp = fopen("/proc/self/maps", "r"); + + if (!fp) { + return false; + } + + char maps_buffer[2048]; + while (fgets(maps_buffer, 2048, fp) != NULL) { + if (strstr(maps_buffer, so_name) == NULL) { + continue; + } + + char *so_path = strchr(maps_buffer, '/'); + so_path[strlen(so_path) - 1] = '\0'; // Cut trailing \n + strcpy(buf,so_path); + fclose(fp); + return true; + } + + fclose(fp); + return false; +} + jint AWT_OnLoad(JavaVM *vm, void *reserved) { @@ -121,7 +146,11 @@ AWT_OnLoad(JavaVM *vm, void *reserved) #ifndef STATIC_BUILD /* Get address of this library and the directory containing it. */ dladdr((void *)AWT_OnLoad, &dlinfo); - realpath((char *)dlinfo.dli_fname, buf); + if (strrchr(dlinfo.dli_fname, '/') != NULL) { + realpath((char *)dlinfo.dli_fname, buf); + }else{ + read_so_path_from_maps(dlinfo.dli_fname,buf); + } len = strlen(buf); p = strrchr(buf, '/'); #endif diff --git a/src/java.instrument/unix/native/libinstrument/EncodingSupport_md.c b/src/java.instrument/unix/native/libinstrument/EncodingSupport_md.c index 13cca6453..796666173 100644 --- a/src/java.instrument/unix/native/libinstrument/EncodingSupport_md.c +++ b/src/java.instrument/unix/native/libinstrument/EncodingSupport_md.c @@ -64,7 +64,11 @@ utfInitialize(void) (void)setlocale(LC_ALL, ""); /* Get the codeset name */ +#ifndef __ANDROID__ codeset = (char*)nl_langinfo(CODESET); +#else + codeset = "ASCII"; // (MB_CUR_MAX == 1) ? "ASCII" : "UTF-8"; +#endif if ( codeset == NULL || codeset[0] == 0 ) { UTF_DEBUG(("NO codeset returned by nl_langinfo(CODESET)\n")); return; diff --git a/src/jdk.jdwp.agent/share/native/libjdwp/utf_util.c b/src/jdk.jdwp.agent/share/native/libjdwp/utf_util.c index 3fb38893e..20ac7b270 100644 --- a/src/jdk.jdwp.agent/share/native/libjdwp/utf_util.c +++ b/src/jdk.jdwp.agent/share/native/libjdwp/utf_util.c @@ -483,7 +483,11 @@ static int iconvConvert(conv_direction drn, char *bytes, size_t len, char *outpu // locale is not initialized, do it now if (setlocale(LC_ALL, "") != NULL) { // nl_langinfo returns ANSI_X3.4-1968 by default +#ifndef __ANDROID__ codeset = (char*)nl_langinfo(CODESET); +#else + codeset = "ASCII"; +#endif } if (codeset == NULL) {