Skip to content

FFI: wrong argument passing order on linux x86_64 C ABI #25594

Closed
@chyh1990

Description

@chyh1990

On linux x86_64, FFI passes arguments in wrong order if the function has more than 6 arguments, with struct (passed by value) mixed.

Reproduce

bug.c

#include <stdio.h>

struct Rect {
        int l;
        int t;
        int r;
        int b;
};

void bug(int a, int b, int c, int d,
        int e, struct Rect f, int g, int h) {
        fprintf(stderr, "%d %d %d %d %d\n",
                a, b, c, d, e);
        fprintf(stderr, "%d %d %d %d\n",
                f.l, f.t, f.r, f.b);
        fprintf(stderr, "%d %d\n", g, h);
}

bug.rs

#[repr(C)]
struct Rect {
    l: i32,
    t: i32,
    r: i32,
    b: i32,
}

#[link(name = "bug")]
extern "C" {
    fn bug(a: i32, b: i32, c: i32, d: i32,
           e: i32, f: Rect, g: i32, h: i32);
}

fn main() {
    let r = Rect {
        l: 10,
        t: 20,
        r: 30,
        b: 40
    };
    unsafe { bug(1, 2, 3, 4, 5, r, 6, 7); }
}
gcc -fPIC -o libbug.so -shared bug.c
rustc -L. bug.rs
./bug

Rust version

rustc 1.0.0 (a59de37e9 2015-05-13) (built 2015-05-14)
binary: rustc
commit-hash: a59de37e99060162a2674e3ff45409ac73595c0e
commit-date: 2015-05-13
build-date: 2015-05-14
host: x86_64-unknown-linux-gnu
release: 1.0.0

Expected output:
1 2 3 4 5
10 20 30 40
6 7

Actual output:
1 2 3 4 5
30 40 6 32740
10 7

Reason

Only 6 arguments can be passed by registers (see http://www.x86-64.org/documentation/abi.pdf).
In the above example, a, b, c, d, e, g should be passed in registers, f & h should be passed on stack.

But Rust FFI mistakenly passes a, b, c, d, e and lower 8bytes of f in registers. This is wrong
according to abi.pdf, page 20:

If there are no registers available for any eightbyte of an argument, the whole
argument is passed on the stack. If registers have already been assigned for some
eightbytes of such an argument, the assignments get reverted.

Metadata

Metadata

Assignees

Labels

A-codegenArea: Code generation

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions