You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Bindgen can't translate #pragma pack(n) into #[repr(packed = "n")] #537
Thanks for the bug report! I'm not super familiar with #pragma pack -- is it standard? Or at least widely used? If not, we might want to consider whether implementing support is worth the pay off, and what ongoing maintenance costs might be.
If we did support this, I think we would want to use #[repr(C, packed)], not just #[repr(C)].
#pragma pack is understood by GCC and Visual Studio, and I think Borland too. I don't know about clang.
Or at least widely used?
I hope not! Abusing structs for serialisation purposes doesn't seem to be a good idea, and can cause problems. Unfortunately, I know of least one library which does this extensively.
whether implementing support is worth the pay off
bindgen is currently generating structs which have the wrong layout; this could also lead to some fairly strange behaviour. I think there are a number of ways you could go here:
When bindgen sees #pragma pack(*) it aborts.
When bindgen sees #pragma pack(*) it spits out a warning and stops generating bindings until it sees #pragma pack() (which resets things to normal).
bindgen generates compatible structs. In this case, I think a warning is still in order, since repr(packed) can lead to undefined behaviour in rust.
I'm having a similar issue on macOS 10.12.4. When generating the bindings for a header which includes "fcntl.h", the following struct is encountered:
#pragma pack(4)
structlog2phys {
unsigned intl2p_flags; /* unused so far */off_tl2p_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_tl2p_devoffset; /* F_LOG2PHYS: OUT: bytes into device *//* F_LOG2PHYS_EXT: IN: bytes into file *//* OUT: bytes into device */
};
#pragma pack()
For #pragma pack(n) where n > 1, it detects that something is off and makes the type opaque. This is the best that we can do since Rust doesn't have #[repr(packed = "n")] yet.
changed the title [-]Bindgen doesn't know about `#pragma pack(...)`[/-][+]Bindgen can't translate `#pragma pack(n)` into `#[repr(packed = "n")]`[/+]on Nov 1, 2017
It would be great if bindgen could start mapping #pragma pack(N) and the packed C attributes to #[repr(packed(N))] behind some sort of opt-in feature - the produced bindings are necessarily going to require nightly Rust until repr(packed) is stabilized.
Given that getting struct packing wrong is essentially undefined behavior, I'd wish that once the PR is merged it can be quickly stabilized.
Activity
fitzgen commentedon Feb 22, 2017
Thanks for the bug report! I'm not super familiar with
#pragma pack-- is it standard? Or at least widely used? If not, we might want to consider whether implementing support is worth the pay off, and what ongoing maintenance costs might be.If we did support this, I think we would want to use
#[repr(C, packed)], not just#[repr(C)].asayers commentedon Feb 22, 2017
#pragma packis understood by GCC and Visual Studio, and I think Borland too. I don't know about clang.I hope not! Abusing structs for serialisation purposes doesn't seem to be a good idea, and can cause problems. Unfortunately, I know of least one library which does this extensively.
bindgen is currently generating structs which have the wrong layout; this could also lead to some fairly strange behaviour. I think there are a number of ways you could go here:
#pragma pack(*)it aborts.#pragma pack(*)it spits out a warning and stops generating bindings until it sees#pragma pack()(which resets things to normal).repr(packed)can lead to undefined behaviour in rust.Ah yes, you're right.
emilio commentedon Feb 22, 2017
I don't think we can even see
#pragma packedfrom libclang?I guess we can try to guess if we see the alignment is 1 and the relevant fields are packed when looking at their offsets, but...
radupopescu commentedon Apr 11, 2017
Hello,
I'm having a similar issue on macOS 10.12.4. When generating the bindings for a header which includes "fcntl.h", the following struct is encountered:
Rust-bindgen generates the following code:
Some of these assertions are failing:
::std::mem::size_of::<log2phys>()is 24 bytes, not 20.::std::mem::align_of::<log2phys>()is 8 bytes, not 4.unsafe { & ( * ( 0 as * const log2phys ) ) . l2p_contigbytes as * const _ as usize }is 8 bytes not 4.unsafe { & ( * ( 0 as * const log2phys ) ) . l2p_devoffset as * const _ as usize }is 16 bytes not 12.I don't know how helpful this is, but please let me know if I can supply more information.
Thanks for making bindgen!
mark-buer commentedon May 30, 2017
I'm running into this same issue for osx/ios.
Some of the system provided headers use
packquite heavily.Running:
Gives the count of
#pragma packper header (with more than 1 occurrence):And there are many more headers with a single
#pragma packoccurrence (not listed here to avoid excessive noise).fitzgen commentedon Oct 11, 2017
AFAICT, @emilo is right, and
libclangdoesn't even give us access to#pragma pack.For this header
we get this
libclangAST (note theUnexposedAttr):fitzgen commentedon Oct 11, 2017
Another version of this issue:
LegNeato commentedon Oct 19, 2017
Hmmm, reading http://llvm.org/viewvc/llvm-project?view=revision&revision=191345 (and the patch in http://lists.llvm.org/pipermail/cfe-commits/Week-of-Mon-20130923/089367.html) I would assume that
packedshould indeed be exposed by libclang?It appears
clang-sysat least has the constant: https://github.com/KyleMayes/clang-sys/blob/da6280de7ef5f5e7dde7e63ea00fb6df26eda601/src/lib.rs#L446emilio commentedon Oct 19, 2017
Detect `#pragma pack(...)` and make `pack(n)` where `n > 1` opaque
fitzgen commentedon Nov 1, 2017
I have a band-aid in #1136
It should make
#pragma packed(1)work.For
#pragma pack(n)wheren > 1, it detects that something is off and makes the type opaque. This is the best that we can do since Rust doesn't have#[repr(packed = "n")]yet.[-]Bindgen doesn't know about #pragma pack(1)[/-][+]Bindgen doesn't know about `#pragma pack(...)`[/+][-]Bindgen doesn't know about `#pragma pack(...)`[/-][+]Bindgen can't translate `#pragma pack(n)` into `#[repr(packed = "n")]`[/+]Detect `#pragma pack(...)` and make `pack(n)` where `n > 1` opaque
Auto merge of #1136 - fitzgen:pragma-pack-bandaid, r=emilio
gnzlbg commentedon Feb 26, 2018
The PR for
packedis there rust-lang/rust#48528It would be great if
bindgencould start mapping#pragma pack(N)and thepackedC attributes to#[repr(packed(N))]behind some sort of opt-in feature - the produced bindings are necessarily going to require nightly Rust untilrepr(packed)is stabilized.Given that getting struct packing wrong is essentially undefined behavior, I'd wish that once the PR is merged it can be quickly stabilized.
gnzlbg commentedon Apr 13, 2018
@fitzgen
repr(packed(N))just landed this week, would it be possible for bindgen to use it instead of making the struct opaque?fitzgen commentedon Apr 16, 2018
We can start doing that when the rust target = nightly now. I don't have time to write a PR myself, but I could review one.
Support #[repr(packed(N))] on Rust 1.33+
Support #[repr(packed(N))] on Rust 1.33+
Support #[repr(packed(N))] on Rust 1.33+