Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Strange memory layout with Option<unsafe fn ...> within a struct

I'm using JNI definitions from here. I create a JNINativeInterface_ with most members initialized to None. I then run native code which uses the RegisterNatives field of the aforementioned struct. I initialized RegisterNatives and surrounding fields as such:

SetDoubleArrayRegion: unsafe { transmute(0xdeadbeaf as u64) },
RegisterNatives: Some(register_natives),
UnregisterNatives: unsafe { transmute(0xdeadbeaf as u64) },

register_natives is defined like so(this matches the library type exactly):

unsafe extern "system" fn register_natives(env: *mut sys::JNIEnv,
                                           clazz: jclass,
                                           methods: *const JNINativeMethod,
                                           nMethods: jint) -> jint {
    unimplemented!()
}

The native code that uses the struct segfaults(and seems to get a null ptr instead of register_natives).

The relevant part of the struct looks like so under GDB:

0x7ffcf5f4a5b8: 0x0 0x0 0x0 0x0
0x7ffcf5f4a5c8: 0xdeadbeaf  0x0 0x43fd9950  0x55ea
0x7ffcf5f4a5d8: 0xdeadbeaf  0x0 0x0 0x0
0x7ffcf5f4a5e8: 0x0 0x0 0x0 0x0

I'm confused as to exactly what I am looking at since I was expecting 0xdeadbeaf , followed by a 64 bit pointer, followed by 0xdeadbeaf, but as you can see that is not what I get. Am I wrong about my assumptions as to how option will be represented behind the scenes? Why does bindgen/the aformentioned library seem to thing that Option will lead to a compatible interface?

like image 479
PiRocks Avatar asked Nov 21 '25 21:11

PiRocks


1 Answers

[...] I was expecting 0xdeadbeaf, followed by a 64 bit pointer, followed by 0xdeadbeaf, but as you can see that is not what I get.

We must not be seeing the same thing, because I do see that.

0x7ffcf5f4a5c8: 0xdeadbeaf  0x0 0x43fd9950  0x55ea
0x7ffcf5f4a5d8: 0xdeadbeaf  0x0 0x0 0x0

Each hex number is a 32-bit integer, so you have to take two of them to make a 64-bit integer. The first is 0x00000000deadbeaf, the second is 0x000055ea43fd9950 (your register_natives function, presumably) and the third is 0x00000000deadbeaf again. (It's also "obvious" from the addresses: a 64-bit integer takes 8 bytes, so it takes two to take 0x10 bytes. Therefore, there are two 64-bit integer per line.)

The reason the program segfaults may be because letting a panic unwind through foreign code is undefined behavior. Try changing your register_natives function to something that doesn't panic.

like image 99
Francis Gagné Avatar answered Nov 23 '25 11:11

Francis Gagné



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!