misalignment in ellipsis?
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

misalignment in ellipsis?



Good day!

I've hit something that left me a bit mystified, to say
the least. It's probably my stupidity, but maybe you can shed
a bit of light on this:

I'm running a system compiled with your (excellent!) 2005-Q1 
tools on an ARM9 (Sharp) chip. The system itself is a fully 
blown OS with ThreadX as the kernel.

I've got a very simple program, which tests ellipsis with
mixed-sized arguments (int and float in this case):

#include <stdio.h>

int
main(int argc, char** argv)
{
	printf("%f\n", (double)1.0);
	printf("%d %f\n", 1, (double)1.0);
	printf("%d %d %f\n", 1, 2, (double)1.0);

	return 0;
}



What one would expect is a printout like:

1.000000
1 1.000000
1 2 1.000000



However, what we get is:

0.000000
1 -53.661629
1 2 0.000000


Our printf function does the following:

int	printf(const char *fmt, ...)
{
	va_list va;
	int rc;

	va_start(va, fmt);
	rc =  __le->jmp->_fmtout(NULL, stdout, (size_t)-1,fmt, va);
	va_end(va);
	return rc;
}



After some debugging with the probe I found that the
memory layout of the variable argument list (va) seemed to be
a bit awkward:

va points to 0xc04ad460.

%f
c04ad460: c04a937c 00000000 3ff00000 ...

%d %f
c04ad460: 00000001 00000000 3ff00000 c04ad4b0 ...

%d %d %f
c04ad460: 00000001 00000002 00000001 00000000 3ff00000 ...


The va_arg() inside of _fmtout() extracts:

%f:
va_arg(va, double): 0000.0000.c04a.937c

%d %f:
va_arg(va, int): 0000.0001
va_arg(va, double): c04a.d4b0.3ff0.0000 

%d %d %f:
va_arg(va, int): 0000.0001
va_arg(va, int): 0000.0002
va_arg(va, double): 0000.0000.0000.0001

which indicates that the va_arg() function (correctly?) expects
doubles to be aligned on 8 byte boundaries [absolute], however 
the compiler seems to stick them on 8byte *relative to the last
argument (or whatever)*. 

Running the program again, which causes a different
memory location and results in va being aligned on a 4 byte
boundary, produces (by accident?) the right result:

1.000000
1 1.000000
1 2 1.000000

with a memory dump of:

va points to 0xc04ad434.

%f
c04ad434: c04a9350 00000000 3ff00000 ...

%d %f
c04ad434: 00000001 00000000 3ff00000 ...

%d %d %f
c04ad434: 00000001 00000002 00000001 00000000 3ff00000 ...


so in this case the va_arg() sees the double at the right place.


---------------------------------------------------------

We are using the following definition in stdarg.h:

typedef __builtin_va_list va_list;
#define va_start(v,l)	__builtin_va_start(v,l)
#define va_end(v)	__builtin_va_end(v)
#define va_arg(v,l)	__builtin_va_arg(v,l)

---------------------------------------------------------

The compiler options are (-D[efines] & -W[arnings] omitted):
-mcpu=arm9 -ffreestanding -O3

We're only linking with libgcc.a, no other standard libraries.

GCC version is:
gcc (GCC) 3.4.3 (release) (CodeSourcery ARM Q1B 2005)

Compiler platform is MS Windows.

----------------------------------------------------------

Am I missing the plot or is there something strange going on?

Any help/feedback appreciated,
many thanks in advance!

Best regards,
Patric Keller

This email and any attachments is confidential, may be legally privileged and is intended for the use of the addressee only. If you are not the intended recipient, please note that any use, disclosure, printing or copying of this email is strictly prohibited and may be unlawful. If received in error, please delete this email and any attachments and confirm this to the sender.