From 52493b4db79f620c2a4b7f0b8ba9bb686c95abba Mon Sep 17 00:00:00 2001 From: Mathias-Boulay Date: Fri, 14 Jun 2024 21:23:08 +0200 Subject: [PATCH] build: split patches into smaller sections Now I should probably make sure they are applied sequentially --- buildjdk.sh | 4 +- patches/jdk17u_android.diff | 2524 ----------------- .../android/10_use_x86_fpu_control.diff | 134 + .../11_skip_ELF_ST_TYPE_redefinition.diff | 27 + .../android/12_fix_ANDROID_defined.diff | 17 + .../jre_17/android/13_add_libtinyconv.diff | 444 +++ .../android/14_add_custom_resolv.conf.diff | 20 + .../jre_17/android/15_add_nl_langinfo.diff | 107 + .../jre_17/android/16_fix_jni_util_md.diff | 14 + .../jre_17/android/17_add_dhcp_daemon.diff | 155 + .../jre_17/android/18_add_posix_spawn.diff | 59 + patches/jre_17/android/19_fix_java_home.diff | 78 + patches/jre_17/android/1_fix_toolchain.diff | 361 +++ .../android/20_include_network_util.diff | 15 + .../android/21_fix_UnixNativeDispatcher.diff | 127 + patches/jre_17/android/22_fix_awt_path.diff | 57 + .../jre_17/android/23_use_android_offset.diff | 18 + patches/jre_17/android/24_fix_utf_util.diff | 18 + .../jre_17/android/25_fix_redefinition.diff | 13 + patches/jre_17/android/2_fix_os_linux.diff | 284 ++ .../jre_17/android/3_fix_os_perf_linux.diff | 317 +++ patches/jre_17/android/4_fix_os_posix.diff | 32 + .../jre_17/android/5_fix_thread_pointer.diff | 19 + .../jre_17/android/6_fix_thread_helper.diff | 21 + .../android/7_add_arm32_fpu_control.diff | 65 + .../jre_17/android/8_fix_arm32_assembly.diff | 126 + .../android/9_use_arm32_fpu_control.diff | 44 + patches/{ => jre_17/ios}/jdk17u_ios.diff | 0 28 files changed, 2574 insertions(+), 2526 deletions(-) delete mode 100644 patches/jdk17u_android.diff create mode 100644 patches/jre_17/android/10_use_x86_fpu_control.diff create mode 100644 patches/jre_17/android/11_skip_ELF_ST_TYPE_redefinition.diff create mode 100644 patches/jre_17/android/12_fix_ANDROID_defined.diff create mode 100644 patches/jre_17/android/13_add_libtinyconv.diff create mode 100644 patches/jre_17/android/14_add_custom_resolv.conf.diff create mode 100644 patches/jre_17/android/15_add_nl_langinfo.diff create mode 100644 patches/jre_17/android/16_fix_jni_util_md.diff create mode 100644 patches/jre_17/android/17_add_dhcp_daemon.diff create mode 100644 patches/jre_17/android/18_add_posix_spawn.diff create mode 100644 patches/jre_17/android/19_fix_java_home.diff create mode 100644 patches/jre_17/android/1_fix_toolchain.diff create mode 100644 patches/jre_17/android/20_include_network_util.diff create mode 100644 patches/jre_17/android/21_fix_UnixNativeDispatcher.diff create mode 100644 patches/jre_17/android/22_fix_awt_path.diff create mode 100644 patches/jre_17/android/23_use_android_offset.diff create mode 100644 patches/jre_17/android/24_fix_utf_util.diff create mode 100644 patches/jre_17/android/25_fix_redefinition.diff create mode 100644 patches/jre_17/android/2_fix_os_linux.diff create mode 100644 patches/jre_17/android/3_fix_os_perf_linux.diff create mode 100644 patches/jre_17/android/4_fix_os_posix.diff create mode 100644 patches/jre_17/android/5_fix_thread_pointer.diff create mode 100644 patches/jre_17/android/6_fix_thread_helper.diff create mode 100644 patches/jre_17/android/7_add_arm32_fpu_control.diff create mode 100644 patches/jre_17/android/8_fix_arm32_assembly.diff create mode 100644 patches/jre_17/android/9_use_arm32_fpu_control.diff rename patches/{ => jre_17/ios}/jdk17u_ios.diff (100%) diff --git a/buildjdk.sh b/buildjdk.sh index d1f194d..0a6794e 100755 --- a/buildjdk.sh +++ b/buildjdk.sh @@ -80,9 +80,9 @@ cd openjdk # Apply patches git reset --hard if [[ "$BUILD_IOS" != "1" ]]; then - git apply --reject --whitespace=fix ../patches/jdk17u_android.diff || echo "git apply failed (Android patch set)" + find ../patches/jre_17/android -name "*.diff" -print0 | xargs -0 -I {} sh -c 'echo "Applying {}" && git apply {} && || echo "git apply failed (Android patch set)"' else - git apply --reject --whitespace=fix ../patches/jdk17u_ios.diff || echo "git apply failed (iOS patch set)" + find ../patches/jre_17/ios -name "*.diff" -print0 | xargs -0 -I {} sh -c 'echo "Applying {}" && git apply {} && || echo "git apply failed (iOs patch set)"' # Hack: exclude building macOS stuff desktop_mac=src/java.desktop/macosx diff --git a/patches/jdk17u_android.diff b/patches/jdk17u_android.diff deleted file mode 100644 index 1f98c3f..0000000 --- a/patches/jdk17u_android.diff +++ /dev/null @@ -1,2524 +0,0 @@ -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 windows), true) -+ifeq ($(call isTargetOs, linux macosx windows 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 -+} - - // check if addr is inside libjvm.so - bool os::address_is_in_vm(address addr) { -@@ -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,13 +150,48 @@ 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; - #if defined(__linux__) - static statx_func* my_statx_func = NULL; - #endif -+#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) { -diff --git a/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c b/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c -index be578a0bb..ce5e8b400 100644 ---- a/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c -+++ b/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c -@@ -80,5 +80,5 @@ - // not relying on included headers. - --#ifndef __GLIBC__ -+#if !defined(__GLIBC__) && !defined(__ANDROID__) - // Alpine doesn't know these types, define them - typedef unsigned int __uint32_t; diff --git a/patches/jre_17/android/10_use_x86_fpu_control.diff b/patches/jre_17/android/10_use_x86_fpu_control.diff new file mode 100644 index 0000000..3404b39 --- /dev/null +++ b/patches/jre_17/android/10_use_x86_fpu_control.diff @@ -0,0 +1,134 @@ +// + +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/patches/jre_17/android/11_skip_ELF_ST_TYPE_redefinition.diff b/patches/jre_17/android/11_skip_ELF_ST_TYPE_redefinition.diff new file mode 100644 index 0000000..c3c4144 --- /dev/null +++ b/patches/jre_17/android/11_skip_ELF_ST_TYPE_redefinition.diff @@ -0,0 +1,27 @@ +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/patches/jre_17/android/12_fix_ANDROID_defined.diff b/patches/jre_17/android/12_fix_ANDROID_defined.diff new file mode 100644 index 0000000..8d332a6 --- /dev/null +++ b/patches/jre_17/android/12_fix_ANDROID_defined.diff @@ -0,0 +1,17 @@ +// Ensure `ANDROID` is defined + +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/patches/jre_17/android/13_add_libtinyconv.diff b/patches/jre_17/android/13_add_libtinyconv.diff new file mode 100644 index 0000000..6868d7a --- /dev/null +++ b/patches/jre_17/android/13_add_libtinyconv.diff @@ -0,0 +1,444 @@ +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/patches/jre_17/android/14_add_custom_resolv.conf.diff b/patches/jre_17/android/14_add_custom_resolv.conf.diff new file mode 100644 index 0000000..17a1055 --- /dev/null +++ b/patches/jre_17/android/14_add_custom_resolv.conf.diff @@ -0,0 +1,20 @@ + +// Allow passing a custom resolv.conf path + +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/patches/jre_17/android/15_add_nl_langinfo.diff b/patches/jre_17/android/15_add_nl_langinfo.diff new file mode 100644 index 0000000..c2fa36a --- /dev/null +++ b/patches/jre_17/android/15_add_nl_langinfo.diff @@ -0,0 +1,107 @@ +// Add nl_langinfo implementation to use later down the line + +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/patches/jre_17/android/16_fix_jni_util_md.diff b/patches/jre_17/android/16_fix_jni_util_md.diff new file mode 100644 index 0000000..3ef81ec --- /dev/null +++ b/patches/jre_17/android/16_fix_jni_util_md.diff @@ -0,0 +1,14 @@ +// Take into account __ANDROID__ definition +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/patches/jre_17/android/17_add_dhcp_daemon.diff b/patches/jre_17/android/17_add_dhcp_daemon.diff new file mode 100644 index 0000000..a909da4 --- /dev/null +++ b/patches/jre_17/android/17_add_dhcp_daemon.diff @@ -0,0 +1,155 @@ +// Add dhcp client demon + +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/patches/jre_17/android/18_add_posix_spawn.diff b/patches/jre_17/android/18_add_posix_spawn.diff new file mode 100644 index 0000000..f42fa05 --- /dev/null +++ b/patches/jre_17/android/18_add_posix_spawn.diff @@ -0,0 +1,59 @@ +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/patches/jre_17/android/19_fix_java_home.diff b/patches/jre_17/android/19_fix_java_home.diff new file mode 100644 index 0000000..3c3943d --- /dev/null +++ b/patches/jre_17/android/19_fix_java_home.diff @@ -0,0 +1,78 @@ + +// Fix java home + +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/patches/jre_17/android/1_fix_toolchain.diff b/patches/jre_17/android/1_fix_toolchain.diff new file mode 100644 index 0000000..a3bec2c --- /dev/null +++ b/patches/jre_17/android/1_fix_toolchain.diff @@ -0,0 +1,361 @@ +// This patch does a few things: +// - allow clang as an accepted compiler +// - allow android as an accepted target +// - forces the use of the PIC flag +// - Surely other things +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 windows), true) ++ifeq ($(call isTargetOs, linux macosx windows 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/patches/jre_17/android/20_include_network_util.diff b/patches/jre_17/android/20_include_network_util.diff new file mode 100644 index 0000000..f778577 --- /dev/null +++ b/patches/jre_17/android/20_include_network_util.diff @@ -0,0 +1,15 @@ +// include additional library for android +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/patches/jre_17/android/21_fix_UnixNativeDispatcher.diff b/patches/jre_17/android/21_fix_UnixNativeDispatcher.diff new file mode 100644 index 0000000..1c9be26 --- /dev/null +++ b/patches/jre_17/android/21_fix_UnixNativeDispatcher.diff @@ -0,0 +1,127 @@ +// Stub `getgrgid_r` and `getgrnam_r`, load android specific functions + +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,13 +150,48 @@ 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; + #if defined(__linux__) + static statx_func* my_statx_func = NULL; + #endif ++#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/patches/jre_17/android/22_fix_awt_path.diff b/patches/jre_17/android/22_fix_awt_path.diff new file mode 100644 index 0000000..a1e2141 --- /dev/null +++ b/patches/jre_17/android/22_fix_awt_path.diff @@ -0,0 +1,57 @@ +// Fix awt library path +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/patches/jre_17/android/23_use_android_offset.diff b/patches/jre_17/android/23_use_android_offset.diff new file mode 100644 index 0000000..21a36cf --- /dev/null +++ b/patches/jre_17/android/23_use_android_offset.diff @@ -0,0 +1,18 @@ +// Use android specific codeset that was introduced previously by a patch + +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/patches/jre_17/android/24_fix_utf_util.diff b/patches/jre_17/android/24_fix_utf_util.diff new file mode 100644 index 0000000..57b5dc0 --- /dev/null +++ b/patches/jre_17/android/24_fix_utf_util.diff @@ -0,0 +1,18 @@ +// Fallback on ASCII only for android + +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) { diff --git a/patches/jre_17/android/25_fix_redefinition.diff b/patches/jre_17/android/25_fix_redefinition.diff new file mode 100644 index 0000000..02b4de1 --- /dev/null +++ b/patches/jre_17/android/25_fix_redefinition.diff @@ -0,0 +1,13 @@ +// Fix redefinition from ndk r25 clang + +diff --git a/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c b/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c +index be578a0bb..ce5e8b400 100644 +--- a/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c ++++ b/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c +@@ -80,5 +80,5 @@ + // not relying on included headers. + +-#ifndef __GLIBC__ ++#if !defined(__GLIBC__) && !defined(__ANDROID__) + // Alpine doesn't know these types, define them + typedef unsigned int __uint32_t; diff --git a/patches/jre_17/android/2_fix_os_linux.diff b/patches/jre_17/android/2_fix_os_linux.diff new file mode 100644 index 0000000..647f1d1 --- /dev/null +++ b/patches/jre_17/android/2_fix_os_linux.diff @@ -0,0 +1,284 @@ +// This diff does a few things: +// does a few typecast to make the compiler happy +// define android specific iss +// use the custom /tmp path +// implement `read_so_path_from_maps` to customize file path as absolute one +// Stub `getcpu(2)` and `SHM` and `getloadavg` + +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 ++} + + // check if addr is inside libjvm.so + bool os::address_is_in_vm(address addr) { +@@ -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/patches/jre_17/android/3_fix_os_perf_linux.diff b/patches/jre_17/android/3_fix_os_perf_linux.diff new file mode 100644 index 0000000..da5257b --- /dev/null +++ b/patches/jre_17/android/3_fix_os_perf_linux.diff @@ -0,0 +1,317 @@ +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/patches/jre_17/android/4_fix_os_posix.diff b/patches/jre_17/android/4_fix_os_posix.diff new file mode 100644 index 0000000..aceeeec --- /dev/null +++ b/patches/jre_17/android/4_fix_os_posix.diff @@ -0,0 +1,32 @@ +// Stubs the uptime with an android version + +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/patches/jre_17/android/5_fix_thread_pointer.diff b/patches/jre_17/android/5_fix_thread_pointer.diff new file mode 100644 index 0000000..d37f261 --- /dev/null +++ b/patches/jre_17/android/5_fix_thread_pointer.diff @@ -0,0 +1,19 @@ +// Fixes the return pointer on android + +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/patches/jre_17/android/6_fix_thread_helper.diff b/patches/jre_17/android/6_fix_thread_helper.diff new file mode 100644 index 0000000..64ba312 --- /dev/null +++ b/patches/jre_17/android/6_fix_thread_helper.diff @@ -0,0 +1,21 @@ +// Implement the thread helper function on android + +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/patches/jre_17/android/7_add_arm32_fpu_control.diff b/patches/jre_17/android/7_add_arm32_fpu_control.diff new file mode 100644 index 0000000..c8d9642 --- /dev/null +++ b/patches/jre_17/android/7_add_arm32_fpu_control.diff @@ -0,0 +1,65 @@ +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/patches/jre_17/android/8_fix_arm32_assembly.diff b/patches/jre_17/android/8_fix_arm32_assembly.diff new file mode 100644 index 0000000..456d57c --- /dev/null +++ b/patches/jre_17/android/8_fix_arm32_assembly.diff @@ -0,0 +1,126 @@ +// Fixes the assembly to be more strict + +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/patches/jre_17/android/9_use_arm32_fpu_control.diff b/patches/jre_17/android/9_use_arm32_fpu_control.diff new file mode 100644 index 0000000..a95a714 --- /dev/null +++ b/patches/jre_17/android/9_use_arm32_fpu_control.diff @@ -0,0 +1,44 @@ +// Make use if the FPU constrol file introduced in a previous patch + +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/patches/jdk17u_ios.diff b/patches/jre_17/ios/jdk17u_ios.diff similarity index 100% rename from patches/jdk17u_ios.diff rename to patches/jre_17/ios/jdk17u_ios.diff