jextract: offset not multiple of alignment, causing ExceptionInInitializerError
Sebastian Stenzel
sebastian.stenzel at gmail.com
Fri Jan 15 08:31:17 UTC 2021
I had another look at the original header file (macOS: usr/include/sys/fcntl.h). Turns out, this struct is surrounded by a pack(4), which should explain this behaviour:
#pragma pack(4)
struct log2phys {
unsigned int l2p_flags; /* unused so far */
off_t l2p_contigbytes; /* F_LOG2PHYS: unused so far */
/* F_LOG2PHYS_EXT: IN: number of bytes to be queried */
/* OUT: number of contiguous bytes at this position */
off_t l2p_devoffset; /* F_LOG2PHYS: OUT: bytes into device */
/* F_LOG2PHYS_EXT: IN: bytes into file */
/* OUT: bytes into device */
};
#pragma pack()
Question is: Is jextract _expected_ to be aware of this?
> On 14. Jan 2021, at 23:01, Maurizio Cimadamore <maurizio.cimadamore at oracle.com> wrote:
>
> That layout looks odd/wrong.
>
> It seems like there might be some padding missing. Note that you have a 64 bit field that is not 64 bit aligned - so accessing it might be slower. I believe in most compilers 32 bit of padding would be inserted.
>
> Or, if this is really the way the struct is laid out, jextract should have relaxed the alignment requirements for "l2p_contigbytes". As it stands, the jextract layout seems bogus. If you have access to the code, I'd suggest adding:
>
> C_LONG_LONG.withName("l2p_contigbytes").withAlignmentBits(32)
>
> This should allow you to initialize correctly.
>
> Maurizio
>
> On 14/01/2021 21:34, Sebastian Stenzel wrote:
>> Hey,
>>
>> Today I noticed a strange problem related to the MemoryLayout generated by jextract for the following struct:
>>
>> ```
>> struct log2phys {
>> u_int32_t l2p_flags;
>> off_t l2p_contigbytes;
>> off_t l2p_devoffset;
>> };
>> ```
>>
>> The generated layout looks like this:
>>
>> ```
>> static final MemoryLayout log2phys$struct$LAYOUT_ = MemoryLayout.ofStruct(
>> C_INT.withName("l2p_flags"),
>> C_LONG_LONG.withName("l2p_contigbytes"),
>> C_LONG_LONG.withName("l2p_devoffset")
>> ).withName("log2phys");
>> ```
>>
>> During runtime, when the class was loaded and the VarHandle for "l2p_contigbytes" was created, I got the following exception:
>>
>> Exception in thread "main" java.lang.ExceptionInInitializerError
>> at com.example.fuse_h$fuse_operations.$LAYOUT(fuse_h.java:14808)
>> at com.example.fuse_h$fuse_operations.allocate(fuse_h.java:16294)
>> ...
>> Caused by: java.lang.UnsupportedOperationException: Invalid alignment requirements for layout b64(l2p_contigbytes)[abi/kind=LONG_LONG,layout/name=l2p_contigbytes]
>> at jdk.incubator.foreign/jdk.internal.foreign.LayoutPath.checkAlignment(LayoutPath.java:273)
>> at jdk.incubator.foreign/jdk.internal.foreign.LayoutPath.dereferenceHandle(LayoutPath.java:159)
>> at jdk.incubator.foreign/jdk.incubator.foreign.MemoryLayout.lambda$varHandle$2(MemoryLayout.java:488)
>> at jdk.incubator.foreign/jdk.incubator.foreign.MemoryLayout.computePathOp(MemoryLayout.java:538)
>> at jdk.incubator.foreign/jdk.incubator.foreign.MemoryLayout.varHandle(MemoryLayout.java:488)
>> at com.example.fuse_h_constants_1.<clinit>(fuse_h_constants_1.java:1921)
>> ... 5 more
>>
>> I set a breakpoint at LayoutPath.checkAlignment and can tell that "l2p_contigbytes" has an offset of 32 bit (sounds reasonable) but an alignment of 64 bit. I have no idea, what all this means, but apparently it is invalid.
>>
>> I were able to avoid this error in my test project, but I thought I'd better report this in case there is something wrong, as I can see nothing special about aforementioned struct.
>>
>> Let me know if I can provide any further information!
>>
>> Sebastian
More information about the panama-dev
mailing list