public inbox for libffi-discuss@sourceware.org
 help / color / mirror / Atom feed
From: "Kaz Kylheku (libffi)" <382-725-6798@kylheku.com>
To: Cheng Jin <jincheng@ca.ibm.com>
Cc: libffi-discuss@sourceware.org
Subject: Re: Incorrect data detected in the nested float struct with x86/libffi on Linux/64bit
Date: Wed, 09 Jun 2021 19:05:24 -0700	[thread overview]
Message-ID: <cb87f420e998ab562dac048fb6dbc957@mail.kylheku.com> (raw)
In-Reply-To: <OF5D0877D1.6ACE238D-ON002586EF.0055990B-852586EF.005BA901@ibm.com>

On 2021-06-09 09:41, Cheng Jin via Libffi-discuss wrote:
> Hi,
> 
> We found that the nested struct [[float, float], float] works good with
> x86/libffi (at https://github.com/libffi/libffi/tree/master/src/x86)
> on Linux/64bit (verified on Ubuntu 19) while a variant of it like
> [float,[float,float]] was messed up at the 3rd element when invoking
> ffi_call() in the following test:

In the libffi that comes with Ubuntu 18.04 Server, x84-64, your test
case aborts in ffi_call.

I built a similar test case in which I put your function into a shared
lib, and used a libffi-based programming language to call it. Same
thing: abort in ffi_call.

There is some problem in that version of libffi; it doesn't like small
structures. If I add padding to the structure, then there is no abort.

My version of the function looks like this:

float_t testNestedFloatStruct(float_t arg1, stru_Nested_F arg2)
{
   float_t floatSum = arg1 + arg2.elem1 + arg2.elem2.elem1 + 
arg2.elem2.elem2;
   puts("called");
   printf("arg1 = %f, arg2 = { %f, { %f, %f } }\n", arg1, arg2.elem1,
          arg2.elem2.elem1, arg2.elem2.elem2);
   return floatSum;
}

On the FFI side, if I add a uint64's worth of padding to the structure,
the ffi_call proceeds without abort, and the result is like this:

arg1 = 1.000000, arg2 = { 0.000000, { 0.000000, 
-52784298695107543040.000000 } }
-5.27842986951075e19

The second line is the caller printing the return value. As you can
see, complete rubbish.

If I take out the padding and change everything to double (my float_f
typedef lets me do that easily), it looks like this:

arg1 = 1.000000, arg2 = { 2.000000, { 3.000000, 4.000000 } }
10.0

That's the expected behavior; the all-float case should look the same.

Basically with the padding, although the call works, it's using the 
wrong
calling conventions. I think this small structure is supposed to be 
passed
in registers.

If I step over the ffi_prep_cif call to see what args were passed to it
and how the sizes and alignment were set, all looks good:

ffi_make_call_desc (ntotal=<optimized out>, nfixed=<optimized out>,
     rettype=0x7ffff7f97780, argtypes=<optimized out>, name_in=<optimized 
out>)
     at ffi.c:4831
4831      if (ffis != FFI_OK)
(gdb) p args[0]
$5 = (ffi_type *) 0x758c80 <ffi_type_float>
(gdb) p args[1]
$6 = (ffi_type *) 0xc38220
(gdb) p (*args[1])
$7 = {size = 12, alignment = 4, type = 13, elements = 0xc38240}
(gdb) p (*args[1]).elements[0]
$8 = (struct _ffi_type *) 0x758c80 <ffi_type_float>
(gdb) p (*args[1]).elements[1]
$9 = (struct _ffi_type *) 0xb92160
(gdb) p (*(*args[1]).elements[1])
$10 = {size = 8, alignment = 4, type = 13, elements = 0xb92180}
(gdb) p (*(*args[1]).elements[1]).elements[0]
$11 = (struct _ffi_type *) 0x758c80 <ffi_type_float>
(gdb) p (*(*args[1]).elements[1]).elements[1]
$12 = (struct _ffi_type *) 0x758c80 <ffi_type_float>
(gdb) p (*(*args[1]).elements[1]).elements[2]
$13 = (struct _ffi_type *) 0x0
(gdb) p (*args[1]).elements[2]
$14 = (struct _ffi_type *) 0x0


Both elements arrays have two elements and a null terminator. Two floats
at the leaves, and a float + struct at the first level.

  parent reply	other threads:[~2021-06-10  2:05 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-06-09 16:41 Cheng Jin
2021-06-09 16:50 ` Anthony Green
2021-06-09 17:53   ` Cheng Jin
2021-06-15 18:02   ` Jakub Jelinek
2021-06-15 19:02     ` Jakub Jelinek
2021-06-15 19:29       ` Anthony Green
2021-06-09 23:48 ` Kaz Kylheku (libffi)
2021-06-10  0:21   ` Cheng Jin
2021-06-10  2:05 ` Kaz Kylheku (libffi) [this message]
2021-06-10  2:39   ` Cheng Jin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=cb87f420e998ab562dac048fb6dbc957@mail.kylheku.com \
    --to=382-725-6798@kylheku.com \
    --cc=jincheng@ca.ibm.com \
    --cc=libffi-discuss@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).