This is the mail archive of the libffi-discuss@sourceware.org mailing list for the libffi project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

PPC bug when handling double


Hi,

I am not very familiar with libffi but I believe I may have stumbled upon a bug.

If you build the attached test code, you will get two test programs -
namely, ex1 and ex2. The only difference between the two is
'-D__USE_F6__' , which passes the last parameter of test_func1() as a
float instead of a double. I have tried these test programs on both
X86 and PPC (32-bit in both cases) using libffi 3.2.1. I did not use
any special configure flags when I built libffi 3.2.1 for both
platforms.

This is what I get on X86:

$ ./ex1
args_idx = 12
tst_func1 : 0xa 0xb 11.100000 12.1 13.100000 14.1 15.100000 16.1
17.100000 18.1 19.100000 20.100000
rc = 1 - success? Y
$ ./ex2
args_idx = 12
tst_func1 : 0xa 0xb 11.100000 12.1 13.100000 14.1 15.100000 16.1
17.100000 18.1 19.100000 20.1
rc = 1 - success? Y

That looks fine. The last parameter is always 20.1.

If I run the same code on PPC I get:

$ uname -a
Linux tstsrv 3.0.101-0.47.52-ppc64 #1 SMP Thu Mar 26 10:55:49 UTC 2015
(0e3c7c8) ppc64 ppc64 ppc64 GNU/Linux
$ file  ./ppc/libffi_3.2.1/lib/libffi.so.6.0.4
./ppc/libffi_3.2.1/lib/libffi.so.6.0.4: ELF 32-bit MSB shared object,
PowerPC or cisco 4500, version 1 (SYSV), dynamically linked, not
stripped
$ gcc -dumpversion
4.3

$ ./ex1
args_idx = 12
tst_func1 : 0xa 0xb 11.100000 12.1 13.100000 14.1 15.100000 16.1
17.100000 18.1 19.100000 20.100000
rc = 1 - success? Y
$ ./ex2
args_idx = 12
tst_func1 : 0xa 0xb 11.100000 12.1 13.100000 14.1 15.100000 16.1
17.100000 18.1 19.100000 -2.35344e-185
rc = 0 - success? N

You can see above that the last parameter printed by tst_func1() is
incorrect in the case of ex2 (i.e., when passed as a double).

Any idea?

Thanks in advance
#include <stdint.h>
#include <stdio.h>
#include <ffi.h>
#include "trg.h"

#define NUM_TST_ARGS  12
#define FFI_FN(f) ((void (*)(void))f)

static int test1(void) {
	uint32_t sValues[2 * NUM_TST_ARGS];
	size_t sValues_idx = 0;

	ffi_cif cif;
	ffi_type *args[NUM_TST_ARGS];
	size_t args_idx = 0;
	void *values[NUM_TST_ARGS];
	int rc = -1;
	
	/* Initialize the argument info vectors */
	args[args_idx] = &ffi_type_pointer;
	sValues[sValues_idx] = (uint32_t) 0xa;
	values[args_idx] = &(sValues[sValues_idx]);
	++args_idx;
	++sValues_idx;

	args[args_idx] = &ffi_type_pointer;
	sValues[sValues_idx] = (uint32_t) 0xb;
	values[args_idx] = &(sValues[sValues_idx]);
	++args_idx;
	++sValues_idx;

	args[args_idx] = &ffi_type_float;
	{
		const float tf = 11.1;
		const uint32_t * const tp = (uint32_t *) &tf;
		sValues[sValues_idx] = *tp;
	}
	values[args_idx] = &(sValues[sValues_idx]);
	++args_idx;
	++sValues_idx;

	args[args_idx] = &ffi_type_double;
	{
		const double tf = 12.1;
		const uint32_t * const tp = (uint32_t *) &tf;
		sValues[sValues_idx] = *tp;
		++sValues_idx;
		sValues[sValues_idx] = *(tp + 1);
	}
	values[args_idx] = &(sValues[sValues_idx - 1]);
	++args_idx;
	++sValues_idx;

	args[args_idx] = &ffi_type_float;
	{
		const float tf = 13.1;
		const uint32_t * const tp = (uint32_t *) &tf;
		sValues[sValues_idx] = *tp;
	}
	values[args_idx] = &(sValues[sValues_idx]);
	++args_idx;
	++sValues_idx;

	args[args_idx] = &ffi_type_double;
	{
		const double tf = 14.1;
		const uint32_t * const tp = (uint32_t *) &tf;
		sValues[sValues_idx] = *tp;
		++sValues_idx;
		sValues[sValues_idx] = *(tp + 1);
	}
	values[args_idx] = &(sValues[sValues_idx - 1]);
	++args_idx;
	++sValues_idx;

	args[args_idx] = &ffi_type_float;
	{
		const float tf = 15.1;
		const uint32_t * const tp = (uint32_t *) &tf;
		sValues[sValues_idx] = *tp;
	}
	values[args_idx] = &(sValues[sValues_idx]);
	++args_idx;
	++sValues_idx;

	args[args_idx] = &ffi_type_double;
	{
		const double tf = 16.1;
		const uint32_t * const tp = (uint32_t *) &tf;
		sValues[sValues_idx] = *tp;
		++sValues_idx;
		sValues[sValues_idx] = *(tp + 1);
	}
	values[args_idx] = &(sValues[sValues_idx - 1]);
	++args_idx;
	++sValues_idx;

	args[args_idx] = &ffi_type_float;
	{
		const float tf = 17.1;
		const uint32_t * const tp = (uint32_t *) &tf;
		sValues[sValues_idx] = *tp;
	}
	values[args_idx] = &(sValues[sValues_idx]);
	++args_idx;
	++sValues_idx;

	args[args_idx] = &ffi_type_double;
	{
		const double tf = 18.1;
		const uint32_t * const tp = (uint32_t *) &tf;
		sValues[sValues_idx] = *tp;
		++sValues_idx;
		sValues[sValues_idx] = *(tp + 1);
	}
	values[args_idx] = &(sValues[sValues_idx - 1]);
	++args_idx;
	++sValues_idx;

	args[args_idx] = &ffi_type_float;
	{
		const float tf = 19.1;
		const uint32_t * const tp = (uint32_t *) &tf;
		sValues[sValues_idx] = *tp;
	}
	values[args_idx] = &(sValues[sValues_idx]);
	++args_idx;
	++sValues_idx;

#ifdef __USE_F6__
	args[args_idx] = &ffi_type_float;
	{
		const float tf = 20.1;
		const uint32_t * const tp = (uint32_t *) &tf;
		sValues[sValues_idx] = *tp;
	}
	values[args_idx] = &(sValues[sValues_idx]);
	++args_idx;
	++sValues_idx;
#else /* __USE_F6__ */
	args[args_idx] = &ffi_type_double;
	{
		const double tf = 20.1;
		const uint32_t * const tp = (uint32_t *) &tf;
		sValues[sValues_idx] = *tp;
		++sValues_idx;
		sValues[sValues_idx] = *(tp + 1);
	}
	values[args_idx] = &(sValues[sValues_idx - 1]);
	++args_idx;
	++sValues_idx;
#endif /* __USE_F6__ */

	printf("args_idx = %d\n", args_idx);

	/* Initialize the cif and issue ffi call */
	if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, NUM_TST_ARGS, &ffi_type_uint, args) == FFI_OK) {
		ffi_call(&cif, FFI_FN(tst_func1), &rc, values);
		printf("rc = %d - success? %c\n", rc, (1 == rc) ? 'Y' : 'N');
	}

	return rc;
}

int main() {
	return test1();
}

Attachment: Makefile
Description: Binary data

#include <stdio.h>

int tst_func1(const char * p1, const char * p2, float f1, double d1, float f2, double d2, 
#ifdef __USE_F6__
	float f3, double d3, float f4, double d4, float f5, float f6)
#else /* __USE_F6__ */
	float f3, double d3, float f4, double d4, float f5, double d5)
#endif /* __USE_F6__ */
{
	const int success =
		((const char *) 0xa        == p1) &&
		((const char *) 0xb        == p2) &&
		((float) 11.1              == f1) &&
		((double) 12.1             == d1) &&
		((float) 13.1              == f2) &&
		((double) 14.1             == d2) &&
		((float) 15.1              == f3) &&
		((double) 16.1             == d3) &&
		((float) 17.1              == f4) &&
		((double) 18.1             == d4) &&
		((float) 19.1              == f5) &&
#ifdef __USE_F6__
		((float) 20.1              == f6);
#else /* __USE_F6__ */
		((double) 20.1             == d5);
#endif /* __USE_F6__ */

#ifdef __USE_F6__
	printf("%s : %p %p %f %g %f %g %f %g %f %g %f %f\n",
#else /* __USE_F6__ */
	printf("%s : %p %p %f %g %f %g %f %g %f %g %f %g\n",
#endif /* __USE_F6__ */
		__func__,
		p1,
		p2,
		f1,
		d1,
		f2,
		d2,
		f3,
		d3,
		f4,
		d4,
		f5,
#ifdef __USE_F6__
		f6);
#else /* __USE_F6__ */
		d5);
#endif /* __USE_F6__ */

	return success;
}

#ifndef __TRG_H__
#define __TRG_H__

int tst_func1(const char * p1, const char * p2, float f1, double d1, float f2, double d2, 
#ifdef __USE_F6__
	float f3, double d3, float f4, double d4, float f5, float f6);
#else /* __USE_F6__ */
	float f3, double d3, float f4, double d4, float f5, double d5);
#endif /* __USE_F6__ */

#endif /* __TRG_H__ */


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]