Hi Jan,
Jan Rinze wrote:
> Hi all,
>
> I am a bit worried and confused about this patch:
>
>
This patch made the way we align and size structs and bitfields match
the way MSFT does with
their tools. That is part of the ABI we must match. I'll give you an
example where this was failing before the
patch.
Take an dll built with ex MSVC, with contents like this:
struct my_struct
{
size_t size_of_my_struct; /* This technique is very common in Win32
world. It is mostly used to check the version
of my_struct being used */
char v1_field;
/* char v2_field; Field would be added in v2 of the dll.*/
};
/* only showing v1 of the dll. */
__declspec(dllexport) BOOL my_funct(struct my_struct* s)
{
if (s->size_of_my_struct != sizeof (struct my_struct))
{
return FALSE;
}
/* do actual work. */
return TRUE;
}
And then called by an app built with mingw32ce, would never work
correctly, since the sizeofs
wouldn't match.
Or imagine compiling a dll with a MSFT compiler that takes a foo4
pointer as a parameter in one of its exported functions.
Then imagine you built an app in cegcc or mingw32ce, that uses that dll.
Accessing the y member on the app and on the dll would access different
offsets! Bang!
Or this:
In a MSVC compiled dll:
struct small
{
char a;
};
__declspec(dllexport) struct small* alloc_small(void)
{
return malloc (sizeof (struct small)); /* mallocs 1 byte. */
}
In a mingw32ce app using the above dll:
__declspec(dllimport) struct small* alloc_small(void);
int main()
{
struct small* sm = alloc_small();
memset (sm, 0, sizeof (struct small)); /* clears 4 bytes, outch! */
}
> Op di 31-10-2006, om 00:59 schreef Pedro Alves:
>
>> Hi all,
>>
>> I am commiting this patch that cleans up gcc's support of Windows CE for
>> arm.
>>
>> This patch fixes some major bugs/annoyances we had:
>>
>> - __declspec(dllexport/dllimport) was so broken that it was hurting.
>> We weren't passing -export= in .drectve properly,
>> so the linker would default to exporting everything. If you used .def
>> files, this would go unnoticed.
>>
>> - We had some major violations of WinCE's ABI:
>>
>> Currently this test gives wrong results:
>> struct abi_check_doubles { char a; double d; };
>> struct foo0 { char x; };
>> struct foo1 { char x;char :0; char y; };
>> struct foo2 { char x; int :0; int :0; int :0; int :0; char y; };
>> struct foo3 { char x; char :1; char y; };
>> struct foo4 { char x; int :1; char y; };
>>
>> int main()
>> {
>> printf ("Size of foo0 is %d, should be 1\n", sizeof (struct foo0));
>> printf ("Size of foo1 is %d, should be 2\n", sizeof (struct foo1));
>> printf ("Size of foo2 is %d, should be 2\n", sizeof (struct foo2));
>> printf ("Size of foo3 is %d, should be 3\n", sizeof (struct foo3));
>> printf ("Size of foo4 is %d, should be 12\n", sizeof (struct foo4));
>> return 0;
>> }
>>
>> The right results where taken from compiling the test case with MSVC.
>> Note that this is a simplified test case.
>> If you where experiencing weird crashes before while calling/interfacing
>> MSVC/eVC compiled code,
>> including the system dlls, this may very well be the reason.
>>
>> This patch also brings gcc support very close to what should be
>> submitted upstream.
>>
>
> compiling the above on an ARM-Linux box yields:
>
> $> ./test
> Size of foo0 is 4, should be 1
> Size of foo1 is 4, should be 2
> Size of foo2 is 8, should be 2
> Size of foo3 is 4, should be 3
> Size of foo4 is 4, should be 12
>
> This is with
>
> $> gcc --version
> gcc (GCC) 3.4.3
> Copyright (C) 2004 Free Software Foundation, Inc.
> This is free software; see the source for copying conditions. There is
> NO
> warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
> PURPOSE.
>
> We should note that this can break a lot of other stuff. We had rather
> be using the __packed__ attributed here.
>
>
But WinCE is not arm-linux. Arm-linux uses it's own ABI (or ABIs for the
matter, AAPCS, EABI, EEABI-linux, etc.)
We must follow the ABI WinCE uses. For instance, All linux ABIs let
small structs be passed in registers, while
WinCE mandates that *all* structs be passed through the stack.
> struct abi_check_doubles { char a; double d; };
> struct __attribute__((__packed__)) foo0 { char x; };
> struct __attribute__((__packed__)) foo1 { char x;char :0; char y; };
> struct __attribute__((__packed__)) foo2 { char x; int :0; int :0; int
> :0; int :0; char y; };
> struct __attribute__((__packed__)) foo3 { char x; char :1; char y; };
> struct __attribute__((__packed__)) foo4 { char x; int :1; char y; };
>
>
> int main()
> {
> printf ("Size of foo0 is %d, should be 1\n", sizeof (struct foo0));
> printf ("Size of foo1 is %d, should be 2\n", sizeof (struct foo1));
> printf ("Size of foo2 is %d, should be 2\n", sizeof (struct foo2));
> printf ("Size of foo3 is %d, should be 3\n", sizeof (struct foo3));
> printf ("Size of foo4 is %d, should be 12\n", sizeof (struct foo4));
> return 0;
> }
>
> Will yield:
>
> ./test
> Size of foo0 is 1, should be 1
> Size of foo1 is 2, should be 2
> Size of foo2 is 2, should be 2
> Size of foo3 is 3, should be 3
> Size of foo4 is 3, should be 12
>
> Where the foo4 is 3 in my opinion is fully correct.. 12 is pretty large
> for 2 chars and 1 bit...
>
>
Again it is the WinCE's ABI. Not my fault. :) Notice that the difference
between foo3 and foo4 is the type of
the bitfield. On windows targets, the type matters. So on those cases
you get:
struct foo3
{
char x; /* 1 == sizeof (char) */
char :1; /* 1 == sizeof (char) */
char y; /* 1 == sizeof (char) */
};
struct foo4
{
char x; /* 1 == sizeof (char) */
/* 3 == pad to align the next field, which has a 4 byte
natural alignment. */
int :1; /* 4 == sizeof (int) */
char y; /* 1 == sizeof (char) */
/* 3 == pad to align the struct size to the maximum
alignment of all the members, which is 4 (int) */
};
On the other cases, a special rule about zero sized bitfields enter the
game.
> The compiler can do this behaviour on all structs when we have
> -fpack-struct when invoking gcc. The manual of gcc however warns about
> the behaviour and the resulting binary incompatibilities.
>
>
When you use -fpack-struct, you are effectively changing the ABI
(Aplication Binary Interface).
You must never match two different ABI's in the same program, hence the
warning.
In embedded apps where you have control over everything, you can get
away with -fpack-struct,
but only if you compile everything with it, else, you have the same ABI
mismatch problems.
> I am not sure about the behaviour of eVC in this respect but the packing
> of integers on an ARM processor is pretty much going to slowdown memory
> access by a factor of at least four! (each byte is read separately when
> unaligned memory access is done.)
>
>
That's a bit of a simplification :) Optimization also has it's saying here.
> I will need to do some more checking on this in respect to eVC.
>
>
I tested this on MSVC 2005, and I would be very surprised if eVC gave
different results,
but I would be very interested in confirming this.
You can get a lot more info on this by googling for "-ms-bitfields" option.
Here is a link the patch that introduced support for it in gcc,
if you are interested.
http://gcc.gnu.org/ml/gcc-patches/1999-06n/msg00702.html
Hope this helps,
Cheers,
Pedro Alves
-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
Cegcc-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/cegcc-devel