Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wrong padding size generated from different arch #1284

Closed
eldesh opened this issue Mar 27, 2018 · 2 comments
Closed

Wrong padding size generated from different arch #1284

eldesh opened this issue Mar 27, 2018 · 2 comments

Comments

@eldesh
Copy link

eldesh commented Mar 27, 2018

A generated code via cross compiling environment is difference from naitive generated code.

The cross compiling environment is x86_64 linux .
And a target environment is RaspberryPi(arm-unknown-linux-gnueabihf).

  • bindgen 0.35.0
  • llvm 3.9.1

Input C/C++ Header

typedef int aligned[64] __attribute__((__aligned__(8)));
typedef int array[64];

typedef struct {
  aligned buf; // 256
  int x;
} a_record_t;

typedef struct
{
  array buf;
  int x;
} b_record_t;

Bindgen Invocation

On x86_64 linux, I have generated code as gen_arm.rs, and send compiled binary to my raspberrypi.

x86_64 $ mkdir pi
x86_64 $ sshfs [email protected]:/usr pi
x86_64 $ TARGET=arm-unknown-linux-gnueabihf bindgen --output gen_arm.rs wrapper.h -- -I pi/include/clang/3.9.1/include --sysroot=/work/pi -I pi/include/arm-linux-gnueabihf
x86_64 $ rustc -C linker=armv6-rpi-linux-gnueabihf-gcc --target arm-unknown-linux-gnueabihf --test gen_arm.rs
x86_64 $ scp gen_arm [email protected]:.

On RaspberryPi, I have generated code ordinally and compile it using native rust compiler.

rpi $ bindgen --output gen_rpi.rs wrapper.h -- -I /usr/lib/clang/3.9.1/include --sysroot=/usr -I /usr/include/arm-linux-gnueabihf
rpi $ rustc --test gen_rpi.rs

Actual Results

Below is the result of the layout test which is generated on x86_64 linux environment.

rpi $ ./gen_arm
running 2 tests
test bindgen_test_layout_b_record_t ... ok
test bindgen_test_layout_a_record_t ... FAILED

failures:

---- bindgen_test_layout_a_record_t stdout ----
        thread 'bindgen_test_layout_a_record_t' panicked at 'assertion failed: `(left == right)`
  left: `260`,
 right: `264`: Size of: a_record_t', gen_arm.rs:13:5
note: Run with `RUST_BACKTRACE=1` for a backtrace.


failures:
    bindgen_test_layout_a_record_t

test result: FAILED. 1 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out

On the other hand, below is the result of the same test above.
But the test code have been generated on RaspberryPi.

rpi $ ./gen_rpi
running 2 tests
test bindgen_test_layout_b_record_t ... ok
test bindgen_test_layout_a_record_t ... ok

test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

Expected Results

What is expected of results of tests, both results are matching.

rpi $ ./gen_arm
running 2 tests
test bindgen_test_layout_b_record_t ... ok
test bindgen_test_layout_a_record_t ... ok

test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
@emilio
Copy link
Contributor

emilio commented Mar 27, 2018

Can you show the generated file generated in your raspberry PI? Wanna know what's the expected size / alignment.

There are a couple of uses of size_of::<*mut ()>() and align_of::<*mut ()> in the tree that should more than probably be replaced by actual target information.

@eldesh
Copy link
Author

eldesh commented Mar 28, 2018

generated code

This is generated code in raspberrypi and it's command.

# command
pi$ bindgen --output gen_rpi.rs wrapper.h -- -I /usr/lib/clang/3.9.1/include --sysroot=/usr -I /usr/include/arm-linux-gnueabihf
// generated code
pub type aligned = [::std::os::raw::c_int; 64usize];
pub type array = [::std::os::raw::c_int; 64usize];
#[repr(C)]
#[derive(Copy, Clone)]
pub struct a_record_t {
    pub buf: aligned,
    pub x: ::std::os::raw::c_int,
    pub __bindgen_padding_0: u32,
}
#[test]
fn bindgen_test_layout_a_record_t() {
    assert_eq!(
        ::std::mem::size_of::<a_record_t>(),
        264usize,
        concat!("Size of: ", stringify!(a_record_t))
    );
    assert_eq!(
        unsafe { &(*(::std::ptr::null::<a_record_t>())).buf as *const _ as usize },
        0usize,
        concat!(
            "Offset of field: ",
            stringify!(a_record_t),
            "::",
            stringify!(buf)
        )
    );
    assert_eq!(
        unsafe { &(*(::std::ptr::null::<a_record_t>())).x as *const _ as usize },
        256usize,
        concat!(
            "Offset of field: ",
            stringify!(a_record_t),
            "::",
            stringify!(x)
        )
    );
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct b_record_t {
    pub buf: array,
    pub x: ::std::os::raw::c_int,
}
...(snip test cases for b_record_t)...

In the generated code for the same header on my (x86_64) linux environment, there is no __bindgen_padding_0: u32 field of a_record_t type.

expected results

In the above generated code, ::std::mem::size_of::<a_record_t>() = 264usize is expected (1st case of bindgen_test_layout_a_record_t).

And the generated code on x86_64 linux expects same size (264usize) for a_record_t. (But the actual resut is 260.)

For further experiments, I wrote the below C code.

// test.c
#include <stdio.h>
typedef int aligned[64] __attribute__((__aligned__(8)));
typedef int array[64];

typedef struct
{
  aligned buf;
  int x;
} a_record_t;

typedef struct
{
  array buf;
  int x;
} b_record_t;

#define print_sizeof(ty) \
                printf("sizeof %s: %zu\n", #ty, sizeof(ty))

int main (int argc, char * argv[]) {
        print_sizeof(a_record_t);
        print_sizeof(b_record_t);
        return 0;
}

This code outputs same result to native generated rust code.

rpi $ gcc -o test test.c && ./test
sizeof a_record_t: 264
sizeof b_record_t: 260

So, I guess that cross-generating is wrong.

@eldesh eldesh changed the title wrong padding size generated from different arch Wrong padding size generated from different arch Mar 28, 2018
@emilio emilio self-assigned this Mar 31, 2018
emilio added a commit to emilio/rust-bindgen that referenced this issue Mar 31, 2018
emilio added a commit to emilio/rust-bindgen that referenced this issue Mar 31, 2018
emilio added a commit to emilio/rust-bindgen that referenced this issue Mar 31, 2018
emilio added a commit to emilio/rust-bindgen that referenced this issue Mar 31, 2018
emilio added a commit to emilio/rust-bindgen that referenced this issue Apr 3, 2018
bors-servo pushed a commit that referenced this issue Apr 3, 2018
codegen: Use target pointer size consistently for layout calculations

Assuming new enough libclang, this PR makes cross-compilation do layout calculations properly.

Fixes #1284
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants