rust-bindgen
rust-bindgen copied to clipboard
Incorrect field offset when C struct is __attribute__((packed, aligned(8)))
Input C/C++ Header
struct foo
{
int a;
long b;
} __attribute__((packed, aligned(8)));
Bindgen Invocation
let bindings = bindgen::Builder::default()
.header("wrapper.h")
.parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
.generate()
.expect("Unable to generate bindings");
Actual Results
$ RUST_BACKTRACE=1 cargo test
Finished `test` profile [unoptimized + debuginfo] target(s) in 0.02s
Running unittests src/lib.rs (target/debug/deps/bindgen-8ef8fba8e13f0c4e)
running 1 test
test bindings::bindgen_test_layout_foo ... FAILED
failures:
---- bindings::bindgen_test_layout_foo stdout ----
thread 'bindings::bindgen_test_layout_foo' panicked at /home/kumcmill/bindgen/target/debug/build/bindgen-7cb8e559bd3e3745/out/bindings.rs:28:5:
assertion `left == right` failed: Offset of field: foo::b
left: 8
right: 4
stack backtrace:
0: rust_begin_unwind
at /rustc/051478957371ee0084a7c0913941d2a8c4757bb9/library/std/src/panicking.rs:652:5
1: core::panicking::panic_fmt
at /rustc/051478957371ee0084a7c0913941d2a8c4757bb9/library/core/src/panicking.rs:72:14
2: core::panicking::assert_failed_inner
at /rustc/051478957371ee0084a7c0913941d2a8c4757bb9/library/core/src/panicking.rs:403:23
3: core::panicking::assert_failed
at /rustc/051478957371ee0084a7c0913941d2a8c4757bb9/library/core/src/panicking.rs:363:5
4: bindgen::bindings::bindgen_test_layout_foo
at ./target/debug/build/bindgen-7cb8e559bd3e3745/out/bindings.rs:28:5
5: bindgen::bindings::bindgen_test_layout_foo::{{closure}}
at ./target/debug/build/bindgen-7cb8e559bd3e3745/out/bindings.rs:10:29
6: core::ops::function::FnOnce::call_once
at /rustc/051478957371ee0084a7c0913941d2a8c4757bb9/library/core/src/ops/function.rs:250:5
7: core::ops::function::FnOnce::call_once
at /rustc/051478957371ee0084a7c0913941d2a8c4757bb9/library/core/src/ops/function.rs:250:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
failures:
bindings::bindgen_test_layout_foo
test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.08s
and/or
/* automatically generated by rust-bindgen 0.69.4 */
#[repr(C, packed(8))]
#[derive(Debug, Copy, Clone)]
pub struct foo {
pub a: ::std::os::raw::c_int,
pub b: ::std::os::raw::c_long,
}
#[test]
fn bindgen_test_layout_foo() {
const UNINIT: ::std::mem::MaybeUninit<foo> = ::std::mem::MaybeUninit::uninit();
let ptr = UNINIT.as_ptr();
assert_eq!(
::std::mem::size_of::<foo>(),
16usize,
concat!("Size of: ", stringify!(foo))
);
assert_eq!(
::std::mem::align_of::<foo>(),
8usize,
concat!("Alignment of ", stringify!(foo))
);
assert_eq!(
unsafe { ::std::ptr::addr_of!((*ptr).a) as usize - ptr as usize },
0usize,
concat!("Offset of field: ", stringify!(foo), "::", stringify!(a))
);
assert_eq!(
unsafe { ::std::ptr::addr_of!((*ptr).b) as usize - ptr as usize },
4usize,
concat!("Offset of field: ", stringify!(foo), "::", stringify!(b))
);
}
Expected Results
A data structure with two fields. The first field at offset 0 and the second field at offset 4.
I initially filed this issue against rust-lang/rust (#128373). It turned out to be a duplicate of E0587 error on packed and aligned structures from C.
The suggestion from rust-lang/rust in #127373 was to file this against bindgen with the recommendation to handle this case by generating a packed inner struct wrapped in an align(8) outer struct.
Sounds like a duplicate of https://github.com/rust-lang/rust-bindgen/issues/2101