Skip to content

Commit f799304

Browse files
rjernstalbertzaharovits
authored andcommitted
Force resolution of fstat64 symbol with JNA (#110807)
When JNA loads libraries it creates a proxy object for the library. Unfortunately it doesn't actually inspect any of the methods, those get bound lazily at runtime when the method is called through the proxy. For fstat64 we need to know at load time whether the symbol exists, so that we can fallback to an alternate function if it doesn't. This commit looks up the NativeLibrary object from JNA for libc and checks if fstat64 exists during load time.
1 parent 0420300 commit f799304

File tree

1 file changed

+10
-1
lines changed

1 file changed

+10
-1
lines changed

libs/native/jna/src/main/java/org/elasticsearch/nativeaccess/jna/JnaPosixCLibrary.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import com.sun.jna.Library;
1212
import com.sun.jna.Memory;
1313
import com.sun.jna.Native;
14+
import com.sun.jna.NativeLibrary;
1415
import com.sun.jna.NativeLong;
1516
import com.sun.jna.Pointer;
1617
import com.sun.jna.Structure;
@@ -143,9 +144,17 @@ private interface FXStatFunction extends Library {
143144
this.functions = Native.load("c", NativeFunctions.class);
144145
FStat64Function fstat64;
145146
try {
147+
// JNA lazily finds symbols, so even though we try to bind two different functions below, if fstat64
148+
// isn't found, we won't know until runtime when calling the function. To force resolution of the
149+
// symbol we get a function object directly from the native library. We don't use it, we just want to
150+
// see if it will throw UnsatisfiedLinkError
151+
NativeLibrary.getInstance("c").getFunction("fstat64");
146152
fstat64 = Native.load("c", FStat64Function.class);
147153
} catch (UnsatisfiedLinkError e) {
148-
// TODO: explain
154+
// fstat has a long history in linux from the 32-bit architecture days. On some modern linux systems,
155+
// fstat64 doesn't exist as a symbol in glibc. Instead, the compiler replaces fstat64 calls with
156+
// the internal __fxstat method. Here we fall back to __fxstat, and staticall bind the special
157+
// "version" argument so that the call site looks the same as that of fstat64
149158
var fxstat = Native.load("c", FXStatFunction.class);
150159
int version = System.getProperty("os.arch").equals("aarch64") ? 0 : 1;
151160
fstat64 = (fd, stat) -> fxstat.__fxstat(version, fd, stat);

0 commit comments

Comments
 (0)