From patchwork Thu Sep 16 14:03:20 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: Fix libffi x86-64 < 8 bytes last stack argument issue (PR libffi/45677) Date: Thu, 16 Sep 2010 04:03:20 -0000 From: Jakub Jelinek X-Patchwork-Id: 64977 Message-Id: <20100916140320.GR1269@tyan-ft48-01.lab.bos.redhat.com> To: Anthony Green , Tom Tromey Cc: gcc-patches@gcc.gnu.org Hi! GCC assumes the callee owns the whole stack slot word instead of just the first 8/16/32 bits of it when the last argument is 8/16/32 bit. unix64.S puts a saved copy of flags right after the last byte of the arguments block, so when it was not a multiple of 8 bytes, GCC could happily clobber the saved copy of flags after it. Fixed thusly, tested on x86_64-linux, ok to commit? 2010-09-16 Jakub Jelinek PR libffi/45677 * src/x86/ffi64.c (ffi_prep_cif_machdep): Ensure cif->bytes is a multiple of 8. * testsuite/libffi.call/many2.c: New test. Jakub --- libffi/src/x86/ffi64.c.jj 2010-08-11 21:08:14.000000000 +0200 +++ libffi/src/x86/ffi64.c 2010-09-16 15:34:57.000000000 +0200 @@ -378,7 +378,7 @@ ffi_prep_cif_machdep (ffi_cif *cif) if (align < 8) align = 8; - bytes = ALIGN(bytes, align); + bytes = ALIGN (bytes, align); bytes += cif->arg_types[i]->size; } else @@ -390,7 +390,7 @@ ffi_prep_cif_machdep (ffi_cif *cif) if (ssecount) flags |= 1 << 11; cif->flags = flags; - cif->bytes = bytes; + cif->bytes = ALIGN (bytes, 8); return FFI_OK; } --- libffi/testsuite/libffi.call/many2.c.jj 2010-09-16 15:01:08.000000000 +0200 +++ libffi/testsuite/libffi.call/many2.c 2010-09-16 15:28:57.000000000 +0200 @@ -0,0 +1,54 @@ +/* Area: ffi_call + Purpose: Check uint8_t arguments. + Limitations: none. + PR: PR45677. + Originator: Dan Witte 20100916 */ + +/* { dg-do run } */ + +#include "ffitest.h" + +#define NARGS 7 + +typedef unsigned char u8; + +__attribute__((noinline)) uint8_t +foo (uint8_t a, uint8_t b, uint8_t c, uint8_t d, + uint8_t e, uint8_t f, uint8_t g) +{ + return a + b + c + d + e + f + g; +} + +uint8_t +bar (uint8_t a, uint8_t b, uint8_t c, uint8_t d, + uint8_t e, uint8_t f, uint8_t g) +{ + return foo (a, b, c, d, e, f, g); +} + +int +main (void) +{ + ffi_type *ffitypes[NARGS]; + int i; + ffi_cif cif; + ffi_arg result = 0; + uint8_t args[NARGS]; + void *argptrs[NARGS]; + + for (i = 0; i < NARGS; ++i) + ffitypes[i] = &ffi_type_uint8; + + CHECK (ffi_prep_cif (&cif, FFI_DEFAULT_ABI, NARGS, + &ffi_type_uint8, ffitypes) == FFI_OK); + + for (i = 0; i < NARGS; ++i) + { + args[i] = i; + argptrs[i] = &args[i]; + } + ffi_call (&cif, FFI_FN (bar), &result, argptrs); + + CHECK (result == 21); + return 0; +}