Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Loading jnidispatch on Android 15 with 16 KB page size leads to crash #1618

Closed
lisa-bella97 opened this issue Aug 13, 2024 · 14 comments
Closed

Comments

@lisa-bella97
Copy link

  1. Version of JNA and related jars
    5.14.0@aar
  2. Version and vendor of the java virtual machine
    ART, Android 15
    System.getProperty("java.vm.version") = "2.1.0"
  3. Operating system
    Android 15 with 16 KB page size
  4. System architecture (CPU type, bitness of the JVM)
    arm64-v8a
  5. Complete description of the problem
    Loading jnidispatch using System.loadLibrary("jnidispatch") is OK on Android 15 or less with 4 KB page size, but is not OK (leads to SIGSEGV crash) on Android 15 with 16 KB page size (support of this page size in Android 15 is described in docs).
    System.loadLibrary("jnidispatch") is called on Android platform in loadNativeDispatchLibrary function that is called in static block of JNA class Native, so you cannot properly use, for example, Native.load function on Android 15 with 16 KB page size.
    To test this behaviour, corresponding Android Studio emulators were used. Info about emulator:
    Emulator version: 35.1.13-11943732 (HVF 14.5.0)
    Host machine: macOS 14.5
    Api level: 35
    Type: Google APIs PlayStore Page Size 16 KB
  6. Steps to reproduce
    You can find minimal sample here. Launching this app on Android 15, 16-KB-based emulator will lead to SIGSEGV crash, full log with dump.
@pgarba
Copy link

pgarba commented Oct 10, 2024

Yes, this one is critical. Would be great if you could fix it in the upcoming release

@dbwiddis
Copy link
Contributor

Looks like there are page size assumptions in the native code that are used when compiling:

#ifndef malloc_getpagesize
# ifdef _SC_PAGESIZE /* some SVR4 systems omit an underscore */
# ifndef _SC_PAGE_SIZE
# define _SC_PAGE_SIZE _SC_PAGESIZE
# endif
# endif
# ifdef _SC_PAGE_SIZE
# define malloc_getpagesize sysconf(_SC_PAGE_SIZE)
# else
# if defined(BSD) || defined(DGUX) || defined(HAVE_GETPAGESIZE)
extern size_t getpagesize();
# define malloc_getpagesize getpagesize()
# else
# ifdef WIN32 /* use supplied emulation of getpagesize */
# define malloc_getpagesize getpagesize()
# else
# ifndef LACKS_SYS_PARAM_H
# include <sys/param.h>
# endif
# ifdef EXEC_PAGESIZE
# define malloc_getpagesize EXEC_PAGESIZE
# else
# ifdef NBPG
# ifndef CLSIZE
# define malloc_getpagesize NBPG
# else
# define malloc_getpagesize (NBPG * CLSIZE)
# endif
# else
# ifdef NBPC
# define malloc_getpagesize NBPC
# else
# ifdef PAGESIZE
# define malloc_getpagesize PAGESIZE
# else /* just guess */
# define malloc_getpagesize ((size_t)4096U)
# endif
# endif
# endif
# endif
# endif
# endif
# endif
#endif

I assume the native library version with the distribution was likely compiled on a smaller page size. Can you compile the native library on the system with the higher page size and does it resolve the problem?

@pgarba
Copy link

pgarba commented Oct 10, 2024

Based on Googles recommendations the code should be updated;

Check for code instances that reference specific page sizes

Even if your app is 16 KB-aligned, your app can encounter errors if places in your code assume that a device is using a specific page size. To avoid this, complete the following steps:

    Remove any hard-coded dependencies that reference the [PAGE_SIZE](https://cs.android.com/android/platform/superproject/main/+/main:bionic/libc/include/bits/page_size.h;l=34-39) constant or instances in your code logic that assume that a device's page size is 4 KB (4096).

    Use [getpagesize()](https://cs.android.com/android/platform/superproject/main/+/main:bionic/libc/bionic/getpagesize.cpp;l=32) or [sysconf(_SC_PAGESIZE)](https://cs.android.com/android/platform/superproject/main/+/main:bionic/libc/bionic/sysconf.cpp;l=151) instead.

@matthiasblaesing
Copy link
Member

@pgarba could you please test if this helps:

matthias@enterprise:~/src/jnalib$ git diff                                                                                                                                                                                                                 
diff --git a/native/Makefile b/native/Makefile
index 9bafc4c032..3dafe4bdb1 100644
--- a/native/Makefile
+++ b/native/Makefile
@@ -175,7 +175,7 @@ CPP=$(PREFIX)cpp
 LD=$(CC)
 RANLIB=$(PREFIX)ranlib
 STRIP=$(PREFIX)strip -x
-CDEFINES=-DFFI_STATIC_BUILD -DNO_JAWT -DNO_WEAK_GLOBALS -DFFI_MMAP_EXEC_WRIT=1 -DFFI_MMAP_EXEC_SELINUX=0
+CDEFINES=-DFFI_STATIC_BUILD -DNO_JAWT -DNO_WEAK_GLOBALS -DFFI_MMAP_EXEC_WRIT=1 -DFFI_MMAP_EXEC_SELINUX=0 -Dmalloc_getpagesize='getpagesize()'
 COPT+=-fpic -ffunction-sections -funwind-tables -fno-short-enums
 JAVA_INCLUDES=
 CINCLUDES+=-I"$(NDK_PLATFORM)/arch-$(AARCH)/usr/include" # -I/usr/include
matthias@enterprise:~/src/jnalib$

The idea follows @dbwiddis observation where the hardcoded pagesize is used.

@mugz3m
Copy link

mugz3m commented Oct 25, 2024

Hi,

I'm facing the same problem and tried to fix JNA by making the changes suggested by @matthiasblaesing, but unfortunately, it didn’t help. After making the changes, I built jna.aar, added it to @lisa-bella97's app, and encountered the same crash again: https://gist.github.com/mugz3m/634707842dfa4a2f4b3a245714140dbe.

Could it be that I built the library incorrectly? I followed the Build Environment wiki and created artifacts by simply invoking ant native dist.

@Thomyrock
Copy link

Hello,
It seems that the cause of the issue is actually the 16KB ELF alignment. I built JNA with the following patch and tried it on @lisa-bella97's app, which now appears to be working fine:

diff --git a/native/Makefile b/native/Makefile
index 49240421e..bb89169a2 100644
--- a/native/Makefile
+++ b/native/Makefile
@@ -181,7 +181,7 @@ COPT+=-fpic -ffunction-sections -funwind-tables -fno-short-enums
 JAVA_INCLUDES=
 CINCLUDES+=-I"$(NDK_PLATFORM)/arch-$(AARCH)/usr/include" # -I/usr/include
 LIBS=-nostdlib -L"$(NDK_PLATFORM)/arch-$(AARCH)$(ALIBDIR)/" -lgcc -lc -ldl -lm
-LDFLAGS+=-Wl,-shared,-Bsymbolic -Wl,--build-id=sha1
+LDFLAGS+=-Wl,-shared,-Bsymbolic -Wl,--build-id=sha1 -Wl,-z,max-page-size=16384
 FFI_ENV=CPP="$(CPP)" CC="$(CC)" CFLAGS="$(COPT) $(CDEBUG) $(CINCLUDES)" CPPFLAGS="$(CDEFINES) $(CINCLUDES)" LIBS="$(LIBS)" RANLIB="$(RANLIB)"
 FFI_CONFIG=--enable-static --disable-shared --with-pic=yes --host=$(HOST)
 endif

@rvandermeulen
Copy link

Are there plans to ship a 5.16.0 release with this change so apps depending on JNA can complete their own 16KB page size migrations?

@matthiasblaesing
Copy link
Member

@Thomyrock this indeed makes sense. Do you want to create a PR with this change (and an entry to the CHANGES.md or shall I go ahead?

@Thomyrock
Copy link

Should be fixed by #1642

@rvandermeulen
Copy link

Thanks! Is there an ETA on when the next release will ship with that fix?

@matthiasblaesing
Copy link
Member

Fair question. I'll see if I manage to get a release out tomorrow.

@matthiasblaesing
Copy link
Member

matthiasblaesing commented Dec 22, 2024

Release is out. https://groups.google.com/g/jna-users/c/HOlDzhEes-U

@rvandermeulen
Copy link

rvandermeulen commented Dec 22, 2024 via email

@matthiasblaesing
Copy link
Member

For anyone not aware yet, in #1647 there is a claim, that the change introduced by #1640 were not enough. On x86-64 16kB pages seem to work in emulator, but it is claimed, that the build fails on aarch64 with 16kB pages.

Anyone interested is invited to have a look at the problem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants