2500 lines
88 KiB
Diff

diff --git a/make/autoconf/flags-cflags.m4 b/make/autoconf/flags-cflags.m4
index 1fdd0143a..705b3e1f9 100644
--- a/make/autoconf/flags-cflags.m4
+++ b/make/autoconf/flags-cflags.m4
@@ -409,7 +409,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 2aca285d3..494262487 100644
--- a/make/autoconf/flags-ldflags.m4
+++ b/make/autoconf/flags-ldflags.m4
@@ -173,7 +173,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 a50ce5731..eb9545984 100644
--- a/make/autoconf/libraries.m4
+++ b/make/autoconf/libraries.m4
@@ -42,8 +42,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
else
# All other instances need X11, even if building headless only, libawt still
@@ -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 babb24a9b..bcf1e9b41 100644
--- a/make/autoconf/platform.m4
+++ b/make/autoconf/platform.m4
@@ -202,6 +202,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 adb4e182d..e2ee96798 100644
--- a/make/autoconf/toolchain.m4
+++ b/make/autoconf/toolchain.m4
@@ -903,11 +903,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 00e73f7dd..70accf224 100644
--- a/make/common/Utils.gmk
+++ b/make/common/Utils.gmk
@@ -346,6 +346,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 d80b804a2..fd2a8ed15 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 *$(OBJ_SUFFIX)
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 377018cdb..c1c624896 100644
--- a/make/hotspot/lib/JvmOverrideFiles.gmk
+++ b/make/hotspot/lib/JvmOverrideFiles.gmk
@@ -62,7 +62,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 186eff3d6..ca76357b0 100644
--- a/make/modules/java.base/lib/CoreLibraries.gmk
+++ b/make/modules/java.base/lib/CoreLibraries.gmk
@@ -117,6 +117,10 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBJAVA, \
TARGETS += $(BUILD_LIBJAVA)
+ifeq ($(OPENJDK_TARGET_OS), linux)
+ $(BUILD_LIBJAVA): $(BUILD_LIBTINYICONV)
+endif
+
$(BUILD_LIBJAVA): $(BUILD_LIBVERIFY)
diff --git a/make/modules/java.desktop/Lib.gmk b/make/modules/java.desktop/Lib.gmk
index be1ac3f1f..4dd31c4b1 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 96576bb8d..13dd8e3e5 100644
--- a/make/modules/java.desktop/lib/Awt2dLibraries.gmk
+++ b/make/modules/java.desktop/lib/Awt2dLibraries.gmk
@@ -538,7 +538,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), \
@@ -777,7 +777,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 ae985b315..c93425263 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), \
EXTRA_HEADER_DIRS := java.base:libjli, \
LDFLAGS := $(LDFLAGS_JDKLIB) \
$(call SET_SHARED_LIBRARY_ORIGIN) \
diff --git a/make/modules/jdk.hotspot.agent/Lib.gmk b/make/modules/jdk.hotspot.agent/Lib.gmk
index 478d199e5..9477a96c9 100644
--- a/make/modules/jdk.hotspot.agent/Lib.gmk
+++ b/make/modules/jdk.hotspot.agent/Lib.gmk
@@ -76,6 +76,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 b5ea40803..f92adb8d3 100644
--- a/make/modules/jdk.jdwp.agent/Lib.gmk
+++ b/make/modules/jdk.jdwp.agent/Lib.gmk
@@ -52,6 +52,7 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBJDWP, \
NAME := jdwp, \
OPTIMIZATION := LOW, \
CFLAGS := $(CFLAGS_JDKLIB) -DJDWP_LOGGING, \
+ CXXFLAGS := $(CXXFLAGS_JDKLIB), \
DISABLED_WARNINGS_gcc_SDE.c := unused-function, \
DISABLED_WARNINGS_clang_error_messages.c := format-nonliteral, \
DISABLED_WARNINGS_clang_EventRequestImpl.c := self-assign, \
@@ -60,6 +61,7 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBJDWP, \
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 2a43e81b3..ccb0afff5 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 aix), true)
+ifeq ($(call isTargetOs, linux macosx windows aix 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 42680218d..403d8905b 100644
--- a/src/hotspot/os/linux/os_linux.cpp
+++ b/src/hotspot/os/linux/os_linux.cpp
@@ -135,7 +135,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,
@@ -214,6 +214,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::Linux::available_memory_in_container() {
@@ -336,11 +338,11 @@ bool os::Linux::get_tick_information(CPUPerfTicks* pticks, int which_logical_cpu
}
#ifndef SYS_gettid
-// i386: 224, ia64: 1105, amd64: 186, sparc: 143
+// i386 & arm: 224, ia64: 1105, amd64: 186, sparc: 143
#ifdef __ia64__
#define SYS_gettid 1105
#else
- #ifdef __i386__
+ #if defined(__i386__) || defined(__arm__)
#define SYS_gettid 224
#else
#ifdef __amd64__
@@ -348,6 +350,8 @@ bool os::Linux::get_tick_information(CPUPerfTicks* pticks, int which_logical_cpu
#else
#ifdef __sparc__
#define SYS_gettid 143
+ #elif defined(__arm64__) || defined(__aarch64__)
+ #define SYS_gettid 178
#else
#error define gettid for the arch
#endif
@@ -535,6 +539,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)
@@ -559,6 +564,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
}
/////////////////////////////////////////////////////////////////////////////
@@ -1348,7 +1356,13 @@ int os::current_process_id() {
// 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) {
@@ -1420,6 +1434,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;
+}
+
// Remember the stack's state. The Linux dynamic linker will change
// the stack to 'executable' at most once, so we must safepoint only once.
bool os::Linux::_stack_is_executable = false;
@@ -1753,6 +1791,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 = nullptr;
assert(lib != nullptr, "dll_path parameter must not be null");
@@ -1762,6 +1801,9 @@ const char* os::Linux::dll_path(void* lib) {
l_path = lmap->l_name;
}
return l_path;
+#else
+ return NULL;
+#endif
}
static unsigned count_newlines(const char* s) {
@@ -2475,6 +2517,20 @@ void os::jvm_path(char *buf, jint buflen) {
CAST_FROM_FN_PTR(address, os::jvm_path),
dli_fname, sizeof(dli_fname), nullptr);
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 = nullptr;
if (ret && dli_fname[0] != '\0') {
rp = os::Posix::realpath(dli_fname, buf, buflen);
@@ -2540,6 +2596,7 @@ void os::jvm_path(char *buf, jint buflen) {
}
}
}
+#endif
strncpy(saved_jvm_path, buf, MAXPATHLEN);
saved_jvm_path[MAXPATHLEN - 1] = '\0';
@@ -2855,7 +2912,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");
}
}
@@ -3475,6 +3533,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) {
@@ -3496,6 +3555,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, nullptr);
return true;
+#else
+ warning("UseSHM not supported on this platform");
+ return false;
+#endif
}
// From the coredump_filter documentation:
@@ -3759,6 +3822,8 @@ void os::large_page_init() {
#define SHM_HUGETLB 04000
#endif
+#ifndef __ANDROID__
+
#define shm_warning_format(format, ...) \
do { \
if (UseLargePages && \
@@ -3851,8 +3916,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");
@@ -3897,6 +3965,10 @@ char* os::Linux::reserve_memory_special_shm(size_t bytes, size_t alignment,
shmctl(shmid, IPC_RMID, nullptr);
return addr;
+#else
+ assert(0, "SHM not supported on this platform");
+ return NULL;
+#endif // !__ANDROID__
}
static void log_on_commit_special_failure(char* req_addr, size_t bytes,
@@ -4023,8 +4095,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) {
@@ -5101,7 +5178,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) {
- return ::getloadavg(loadavg, 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<double>(si.loads[i]) / static_cast<double>(1 << SI_LOAD_SHIFT);
+ }
+ return nelem;
+#endif
}
// Get the default path to the core file
diff --git a/src/hotspot/os/linux/os_perf_linux.cpp b/src/hotspot/os/linux/os_perf_linux.cpp
index ff416d47e..fca2f6aa4 100644
--- a/src/hotspot/os/linux/os_perf_linux.cpp
+++ b/src/hotspot/os/linux/os_perf_linux.cpp
@@ -45,9 +45,312 @@
#include <dlfcn.h>
#include <pthread.h>
#include <limits.h>
+#ifndef __ANDROID__
#include <ifaddrs.h>
+#else
+#include <sys/cdefs.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <linux/if_packet.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#include <net/if.h>
+#include <stdint.h>
+#endif
#include <fcntl.h>
+#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<sockaddr*>(&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<sockaddr*>(&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<sockaddr*>(&netmask);
+ }
+ void SetPacketAttributes(int ifindex, unsigned short hatype, unsigned char halen) {
+ sockaddr_ll* sll = reinterpret_cast<sockaddr_ll*>(&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<sockaddr_in*>(ss);
+ return reinterpret_cast<uint8_t*>(&ss4->sin_addr);
+ } else if (family == AF_INET6) {
+ sockaddr_in6* ss6 = reinterpret_cast<sockaddr_in6*>(ss);
+ return reinterpret_cast<uint8_t*>(&ss6->sin6_addr);
+ } else if (family == AF_PACKET) {
+ sockaddr_ll* sll = reinterpret_cast<sockaddr_ll*>(ss);
+ return reinterpret_cast<uint8_t*>(&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<ifaddrs*>(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<ifinfomsg*>(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<ifaddrmsg*>(NLMSG_DATA(hdr));
+ // We should already know about this from an RTM_NEWLINK message.
+ const ifaddrs_storage* addr = reinterpret_cast<const ifaddrs_storage*>(*out);
+ while (addr != nullptr && addr->interface_index != static_cast<int>(msg->ifa_index)) {
+ addr = reinterpret_cast<const ifaddrs_storage*>(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<nlmsghdr*>(buf);
+ for (; NLMSG_OK(hdr, static_cast<size_t>(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 cf0f48974..04a5930b5 100644
--- a/src/hotspot/os/posix/os_posix.cpp
+++ b/src/hotspot/os/posix/os_posix.cpp
@@ -74,7 +74,9 @@
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>
+#ifndef __ANDROID__
#include <utmpx.h>
+#endif
#ifdef __APPLE__
#include <crt_externs.h>
@@ -453,6 +455,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(nullptr);
struct utmpx* ent;
@@ -467,6 +470,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,
@@ -1921,11 +1925,31 @@ int os::fork_and_exec(const char* cmd) {
const char* argv[4] = {"sh", "-c", cmd, nullptr};
pid_t pid = -1;
char** env = os::get_environ();
+#ifndef __ANDROID__
// Note: cast is needed because posix_spawn() requires - for compatibility with ancient
// C-code - a non-const argv/envp pointer array. But it is fine to hand in literal
// strings and just cast the constness away. See also ProcessImpl_md.c.
int rc = ::posix_spawn(&pid, "/bin/sh", nullptr, nullptr, (char**) argv, env);
if (rc == 0) {
+#else
+ pid = ::fork();
+
+ if (pid < 0) {
+ // fork failed
+ return -1;
+
+ } else if (pid == 0) {
+ // child process
+
+ ::execve("/bin/sh", (char* const*)argv, env);
+
+ // execve failed
+ ::_exit(-1);
+
+ } else {
+ // copied from J2SE ..._waitForProcessExit() in UNIXProcess_md.c; we don't
+ // care about the actual exit code, for now.
+#endif
int status;
// Wait for the child process to exit. This returns immediately if
// the child has already exited. */
@@ -1950,9 +1974,11 @@ int os::fork_and_exec(const char* cmd) {
// Unknown exit code; pass it through
return status;
}
+#ifndef __ANDROID__
} else {
// Don't log, we are inside error handling
return -1;
+#endif
}
}
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 ac60d6aa9..0645f0e00 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.
@@ -44,3 +45,4 @@ _ZN10JavaThread25aarch64_get_thread_helperEv:
ret
.size _ZN10JavaThread25aarch64_get_thread_helperEv, .-_ZN10JavaThread25aarch64_get_thread_helperEv
+#endif
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
+ <http://www.gnu.org/licenses/>. */
+#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 eb560d8f0..be8da136b 100644
--- a/src/hotspot/os_cpu/linux_arm/linux_arm_32.S
+++ b/src/hotspot/os_cpu/linux_arm/linux_arm_32.S
@@ -88,7 +88,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
@@ -136,7 +136,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
@@ -169,7 +169,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
@@ -221,7 +221,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
@@ -237,11 +237,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
@@ -299,11 +299,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
@@ -326,7 +326,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
@@ -352,11 +352,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
@@ -391,7 +391,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
@@ -454,7 +454,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
@@ -487,7 +487,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 d4c9bb304..3123efef2 100644
--- a/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp
+++ b/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp
@@ -72,7 +72,11 @@
# include <pwd.h>
# include <poll.h>
# include <ucontext.h>
+#ifndef __ANDROID__
# include <fpu_control.h>
+#else
+# include "fpu_control.h" //include the local header
+#endif
# include <asm/ptrace.h>
#define SPELL_REG_SP "sp"
@@ -90,8 +94,14 @@ enum {
#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() {
@@ -415,8 +425,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
+ <http://www.gnu.org/licenses/>. */
+
+#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 <features.h>
+
+/* 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 90c7d3c93..0a10fba48 100644
--- a/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp
+++ b/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp
@@ -74,8 +74,10 @@
# include <pwd.h>
# include <poll.h>
# include <ucontext.h>
-#ifndef AMD64
+#if !defined(AMD64) && !defined(__ANDROID__)
# include <fpu_control.h>
+#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 32ce08821..7103f3736 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
@@ -62,7 +64,7 @@ typedef Elf32_Shdr Elf_Shdr;
typedef Elf32_Phdr Elf_Phdr;
typedef Elf32_Sym Elf_Sym;
-#if !defined(_ALLBSD_SOURCE) || defined(__APPLE__)
+#if (!defined(_ALLBSD_SOURCE) || defined(__APPLE__)) && !defined(ELF_ST_TYPE)
#define ELF_ST_TYPE ELF32_ST_TYPE
#endif
#endif
diff --git a/src/hotspot/share/utilities/globalDefinitions_gcc.hpp b/src/hotspot/share/utilities/globalDefinitions_gcc.hpp
index 3da670ef4..89f2d944a 100644
--- a/src/hotspot/share/utilities/globalDefinitions_gcc.hpp
+++ b/src/hotspot/share/utilities/globalDefinitions_gcc.hpp
@@ -48,6 +48,10 @@
#include <limits.h>
#include <errno.h>
+#if defined(__ANDROID__) && !defined(ANDROID)
+#define ANDROID 1
+#endif
+
#if defined(LINUX) || defined(_ALLBSD_SOURCE)
#include <inttypes.h>
#include <signal.h>
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 <ctype.h>
+#include <endian.h>
+#include <errno.h>
+#include <iconv.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <uchar.h>
+#include <wchar.h>
+
+__BEGIN_DECLS
+
+/*
+ * These return values are specified by POSIX for multibyte conversion
+ * functions.
+ */
+
+#ifdef __cplusplus
+#define __MB_ERR_ILLEGAL_SEQUENCE static_cast<size_t>(-1)
+#define __MB_ERR_INCOMPLETE_SEQUENCE static_cast<size_t>(-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<uint32_t*>(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<uint32_t*>(ps->__seq)) = 0;
+#else
+ *(uint32_t*)(ps->__seq) = 0;
+#endif // __cplusplus
+ return _return;
+}
+
+#ifdef __cplusplus
+# define INVALID_ICONV_T reinterpret_cast<iconv_t>(-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) <uchar.h>. 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<const uint8_t*>(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<const uint8_t*>(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 6074d323f..8b337d6e3 100644
--- a/src/java.base/unix/classes/sun/net/dns/ResolverConfigurationImpl.java
+++ b/src/java.base/unix/classes/sun/net/dns/ResolverConfigurationImpl.java
@@ -63,8 +63,9 @@ public final class ResolverConfigurationImpl
ArrayList<String> ll = new ArrayList<>();
try {
+ String resolvPath = System.getProperty("ext.net.resolvPath", "/etc/resolv.conf");
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 230de04c0..8e858b736 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 <paths.h>
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 <roy@marples.name>
+ * 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 <sys/types.h>
+#include <sys/wait.h>
+#include <errno.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#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 <roy@marples.name>
+ * 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 <signal.h>
+
+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 21ef40688..b8c2520d2 100644
--- a/src/java.base/unix/native/libjli/java_md.c
+++ b/src/java.base/unix/native/libjli/java_md.c
@@ -584,7 +584,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];
@@ -594,10 +645,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 902cf9673..3b8acd66b 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 <netinet/in.h>
+#endif
#include <netdb.h>
#include <poll.h>
#include <sys/socket.h>
diff --git a/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c b/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c
index 9371bc001..ab7dd0fc0 100644
--- a/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c
+++ b/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c
@@ -140,6 +140,7 @@ typedef int fstatat64_func(int, const char *, struct stat64 *, int);
typedef int unlinkat_func(int, const char*, int);
typedef int renameat_func(int, const char*, int, const char*);
typedef int futimesat_func(int, const char *, const struct timeval *);
+typedef int utimensat_func(int, const char *, const struct timespec *, int flags);
typedef int futimens_func(int, const struct timespec *);
typedef int lutimes_func(const char *, const struct timeval *);
typedef DIR* fdopendir_func(int);
@@ -149,10 +150,46 @@ static fstatat64_func* my_fstatat64_func = NULL;
static unlinkat_func* my_unlinkat_func = NULL;
static renameat_func* my_renameat_func = NULL;
static futimesat_func* my_futimesat_func = NULL;
+static utimensat_func* my_utimensat_func = NULL;
static futimens_func* my_futimens_func = NULL;
static lutimes_func* my_lutimes_func = NULL;
static fdopendir_func* my_fdopendir_func = NULL;
+#ifdef __ANDROID__
+/*
+ * TODO: Android lacks support for the methods listed below. In it's place are
+ * alternatives that use existing Android functionality, but lack reentrant
+ * support. Determine if the following are the most suitable alternatives.
+ *
+ */
+int getgrgid_r(gid_t gid, struct group* grp, char* buf, size_t buflen, struct group** result) {
+
+ *result = NULL;
+ errno = 0;
+ grp = getgrgid(gid);
+ if (grp == NULL) {
+ return errno;
+ }
+ // buf not used by caller (see below)
+ *result = grp;
+ return 0;
+}
+
+int getgrnam_r(const char *name, struct group* grp, char* buf, size_t buflen, struct group** result) {
+
+ *result = NULL;
+ errno = 0;
+ grp = getgrnam(name);
+ if (grp == NULL) {
+ return errno;
+ }
+ // buf not used by caller (see below)
+ *result = grp;
+ return 0;
+
+}
+#endif
+
/**
* fstatat missing from glibc on Linux.
*/
@@ -272,6 +309,9 @@ Java_sun_nio_fs_UnixNativeDispatcher_init(JNIEnv* env, jclass this)
#ifndef _ALLBSD_SOURCE
my_futimesat_func = (futimesat_func*) dlsym(RTLD_DEFAULT, "futimesat");
my_lutimes_func = (lutimes_func*) dlsym(RTLD_DEFAULT, "lutimes");
+#endif
+#ifdef __ANDROID__
+ my_utimensat_func = (utimensat_func*) dlsym(RTLD_DEFAULT, "utimensat");
#endif
my_futimens_func = (futimens_func*) dlsym(RTLD_DEFAULT, "futimens");
#if defined(_AIX)
@@ -292,7 +332,7 @@ Java_sun_nio_fs_UnixNativeDispatcher_init(JNIEnv* env, jclass this)
capabilities |= sun_nio_fs_UnixNativeDispatcher_SUPPORTS_FUTIMES;
capabilities |= sun_nio_fs_UnixNativeDispatcher_SUPPORTS_LUTIMES;
#else
- if (my_futimesat_func != NULL)
+ if (my_futimesat_func != NULL || my_utimensat_func != NULL)
capabilities |= sun_nio_fs_UnixNativeDispatcher_SUPPORTS_FUTIMES;
if (my_lutimes_func != NULL)
capabilities |= sun_nio_fs_UnixNativeDispatcher_SUPPORTS_LUTIMES;
@@ -304,7 +344,7 @@ Java_sun_nio_fs_UnixNativeDispatcher_init(JNIEnv* env, jclass this)
if (my_openat64_func != NULL && my_fstatat64_func != NULL &&
my_unlinkat_func != NULL && my_renameat_func != NULL &&
- my_futimesat_func != NULL && my_fdopendir_func != NULL)
+ (my_futimesat_func != NULL || my_utimensat_func != NULL) && my_fdopendir_func != NULL)
{
capabilities |= sun_nio_fs_UnixNativeDispatcher_SUPPORTS_OPENAT;
}
@@ -675,22 +715,30 @@ Java_sun_nio_fs_UnixNativeDispatcher_futimes0(JNIEnv* env, jclass this, jint fil
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, &times[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, &times[0]), err);
+ if (my_futimesat_func != NULL) {
+ RESTARTABLE((*my_futimesat_func)(filedes, NULL, &times[0]), err);
+ } else {
+ RESTARTABLE((*my_utimensat_func)(filedes, NULL, &times2[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 b2dedca35..c01ccfb8d 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 <jni.h>
#include <jni_util.h>
#include <jvm.h>
+#include <stdbool.h>
#include "gdefs.h"
#include <sys/param.h>
@@ -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)
{
@@ -119,7 +144,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 490eea9a5..27ee1c23e 100644
--- a/src/java.instrument/unix/native/libinstrument/EncodingSupport_md.c
+++ b/src/java.instrument/unix/native/libinstrument/EncodingSupport_md.c
@@ -65,7 +65,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 f5573930d..b64e30046 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/hotspot/os_cpu/linux_aarch64/javaThread_linux_aarch64.hpp b/src/hotspot/os_cpu/linux_aarch64/javaThread_linux_aarch64.hpp
index c6e012ecf..d4f956756 100644
--- a/src/hotspot/os_cpu/linux_aarch64/javaThread_linux_aarch64.hpp
+++ b/src/hotspot/os_cpu/linux_aarch64/javaThread_linux_aarch64.hpp
@@ -47,6 +47,8 @@ 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() {
+ return Thread::current();
+ }
#endif // OS_CPU_LINUX_AARCH64_JAVATHREAD_LINUX_AARCH64_HPP