1- # Libcore-Syscall
1+ # Libcore-Syscall / Libcore-ElfLoader
22
3- Libcore-Syscall is a Java library for Android that allows you to make any Linux system calls directly from Java code.
3+ Libcore-Syscall is a Java library for Android that allows you to make any Linux system calls or load any ELF shared objects directly from Java code.
44
55## Features
66
77- Support Android 5.0 - 15
88- Support any system calls (as long as they are permitted by the seccomp filter)
9+ - Support loading any ELF shared objects (lib* .so) directly from memory
910- Implemented in 100% pure Java 1.8
1011- No shared libraries (lib* .so) are shipped with the library
1112- No ` System.loadLibrary ` or ` System.load ` is used
13+ - No temporary files are created on the disk (does not require a writable path/mount point)
1214- Small, no dependencies
1315
1416## Usage
@@ -18,10 +20,63 @@ The library provides the following classes:
1820- MemoryAccess/MemoryAllocator: Allocate and read/write native memory.
1921- NativeAccess: Register JNI methods, or call native functions (such as ` dlopen ` , ` dlsym ` , etc.) directly.
2022- Syscall: Make any Linux system calls.
23+ - DlExtLibraryLoader: Load any ELF shared objects (lib* .so) directly from memory.
2124
22- ## Example
25+ ## Examples
2326
24- Here is an example of how to use the library. It calls the ` uname ` system call to get the system information.
27+ Here are some examples of possible use cases.
28+
29+ ### Load ELF Shared Object from Memory
30+
31+ Here is an example of how to load an ELF shared object directly from memory.
32+ It loads the ` libmmkv.so ` shared object and calls the ` MMKV.initialize ` method.
33+
34+ See [ TestNativeLoader.java] ( demo-app/src/main/java/com/example/test/app/TestNativeLoader.java ) for the complete example.
35+
36+ <details >
37+
38+ ``` java
39+ import com.tencent.mmkv.MMKV ;
40+
41+ import dev.tmpfs.libcoresyscall.core.NativeAccess ;
42+ import dev.tmpfs.libcoresyscall.elfloader.DlExtLibraryLoader ;
43+
44+ public static long initializeMMKV(@NonNull Context ctx) {
45+ String soname = " libmmkv.so" ;
46+ // get the ELF data from somewhere
47+ byte [] elfData = getElfData(soname);
48+
49+ // load the ELF shared object from byte array
50+ // if it fails, it throws an UnsatisfiedLinkError
51+ long sHandle = DlExtLibraryLoader . dlopenExtFromMemory(elfData, soname, DlExtLibraryLoader . RTLD_NOW , 0 , 0 );
52+
53+ // since dlopen from memory is not a standard function, ART does not know it
54+ // we need to call JNI_OnLoad manually, as if the shared object is loaded by System.loadLibrary
55+ long jniOnLoad = DlExtLibraryLoader . dlsym(sHandle, " JNI_OnLoad" );
56+ if (jniOnLoad != 0 ) {
57+ long javaVm = NativeAccess . getJavaVM();
58+ long ret = NativeAccess . callPointerFunction(jniOnLoad, javaVm, 0 );
59+ if (ret < 0 ) {
60+ throw new RuntimeException (" JNI_OnLoad failed: " + ret);
61+ }
62+ } else {
63+ // should not happen, MMKV uses JNI_OnLoad to register native methods
64+ throw new IllegalStateException (" JNI_OnLoad not found" );
65+ }
66+ // initialize MMKV, since we have already loaded the libmmkv.so from memory
67+ // MMKV does not need to load the libmmkv.so shared object again
68+ MMKV . initialize(ctx, libName - > {
69+ // no-op
70+ });
71+ return sHandle;
72+ }
73+ ```
74+
75+ </details >
76+
77+ ### Make System Calls
78+
79+ Here is an example of how to make syscalls with the library. It calls the ` uname ` system call to get the system information.
2580
2681See [ TestMainActivity.java] ( demo-app/src/main/java/com/example/test/app/TestMainActivity.java ) for the complete example.
2782
@@ -94,11 +149,6 @@ To build the demo app:
94149./gradlew :demo-app:assembleDebug
95150```
96151
97- ## The Future
98-
99- - A symbol resolver that can resolve symbols in loaded native libraries.
100- - Loading arbitrary shared libraries (lib* .so) with 100% pure Java code in memory without writing it to the disk.
101-
102152## Credits
103153
104154- [ pine] ( https://github.com/canyie/pine )
0 commit comments