rust-bindgen icon indicating copy to clipboard operation
rust-bindgen copied to clipboard

Bitfield type generates a `packed` and `aligned` structure

Open s1341 opened this issue 2 years ago • 1 comments

Input C/C++ Header

struct _GumChainedPtr64Rebase
{
  guint64 target   : 36,
          high8    :  8,
          reserved :  7,
          next     : 12,
          bind     :  1;
};

Bindgen Invocation


    let bindings = bindgen::Builder::default().use_core();

    #[cfg(feature = "auto-download")]
    let bindings = bindings.clang_arg(format!("-I{include_dir}"));

    #[cfg(not(feature = "auto-download"))]
    let bindings = if std::env::var("DOCS_RS").is_ok() {
        bindings.clang_arg("-Iinclude")
    } else {
        bindings
    };

    let bindings = bindings
        .header_contents("gum.h", "#include \"frida-gum.h\"")
        .header("event_sink.h")
        .header("invocation_listener.h")
        .header("probe_listener.h")
        .header("stalker_observer.h")
        .header("stalker_params.h")
        .parse_callbacks(Box::new(bindgen::CargoCallbacks))
        .generate_comments(false)
        .layout_tests(false)
        .generate()
        .unwrap();

Actual Results

#[repr(C, packed(4))]
#[repr(align(4))]
#[derive(Debug, Copy, Clone)]
pub struct _GumChainedPtr64Rebase {
    pub _bitfield_align_1: [u64; 0],
    pub _bitfield_1: __BindgenBitfieldUnit<[u8; 8usize]>,
}
impl _GumChainedPtr64Rebase {
    #[inline]
    pub fn target(&self) -> guint64 {
        unsafe { ::core::mem::transmute(self._bitfield_1.get(0usize, 36u8) as u64) }
    }
    #[inline]
    pub fn set_target(&mut self, val: guint64) {
        unsafe {
            let val: u64 = ::core::mem::transmute(val);
            self._bitfield_1.set(0usize, 36u8, val as u64)
        }
    }
    #[inline]
    pub fn high8(&self) -> guint64 {
        unsafe { ::core::mem::transmute(self._bitfield_1.get(36usize, 8u8) as u64) }
    }
    #[inline]
    pub fn set_high8(&mut self, val: guint64) {
        unsafe {
            let val: u64 = ::core::mem::transmute(val);
            self._bitfield_1.set(36usize, 8u8, val as u64)
        }
    }
    #[inline]
    pub fn reserved(&self) -> guint64 {
        unsafe { ::core::mem::transmute(self._bitfield_1.get(44usize, 7u8) as u64) }
    }
    #[inline]
    pub fn set_reserved(&mut self, val: guint64) {
        unsafe {
            let val: u64 = ::core::mem::transmute(val);
            self._bitfield_1.set(44usize, 7u8, val as u64)
        }
    }
    #[inline]
    pub fn next(&self) -> guint64 {
        unsafe { ::core::mem::transmute(self._bitfield_1.get(51usize, 12u8) as u64) }
    }
    #[inline]
    pub fn set_next(&mut self, val: guint64) {
        unsafe {
            let val: u64 = ::core::mem::transmute(val);
            self._bitfield_1.set(51usize, 12u8, val as u64)
        }
    }
    #[inline]
    pub fn bind(&self) -> guint64 {
        unsafe { ::core::mem::transmute(self._bitfield_1.get(63usize, 1u8) as u64) }
    }
    #[inline]
    pub fn set_bind(&mut self, val: guint64) {
        unsafe {
            let val: u64 = ::core::mem::transmute(val);
            self._bitfield_1.set(63usize, 1u8, val as u64)
        }
    }
    #[inline]
    pub fn new_bitfield_1(
        target: guint64,
        high8: guint64,
        reserved: guint64,
        next: guint64,
        bind: guint64,
    ) -> __BindgenBitfieldUnit<[u8; 8usize]> {
        let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 8usize]> = Default::default();
        __bindgen_bitfield_unit.set(0usize, 36u8, {
            let target: u64 = unsafe { ::core::mem::transmute(target) };
            target as u64
        });
        __bindgen_bitfield_unit.set(36usize, 8u8, {
            let high8: u64 = unsafe { ::core::mem::transmute(high8) };
            high8 as u64
        });
        __bindgen_bitfield_unit.set(44usize, 7u8, {
            let reserved: u64 = unsafe { ::core::mem::transmute(reserved) };
            reserved as u64
        });
        __bindgen_bitfield_unit.set(51usize, 12u8, {
            let next: u64 = unsafe { ::core::mem::transmute(next) };
            next as u64
        });
        __bindgen_bitfield_unit.set(63usize, 1u8, {
            let bind: u64 = unsafe { ::core::mem::transmute(bind) };
            bind as u64
        });
        __bindgen_bitfield_unit
    }
}

and/or

error[E0587]: type has conflicting packed and align representation hints
     --> /home/runner/work/frida-rust/frida-rust/target/i686-unknown-linux-gnu/debug/build/frida-gum-sys-6002c29d0e45c6ce/out/bindings.rs:19668:1
      |
19668 | pub struct _GumChainedPtr64Rebase {
      | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Expected Results

A struct with either packed(x) or aligned(x) should be generated.

s1341 avatar Nov 27 '23 07:11 s1341

By the way, this issue seems to be present only on i686-unknown-linux-gnu, and not when compiling for 64bit.

s1341 avatar Dec 06 '23 06:12 s1341