RayeR
CZ, 04.09.2012, 18:53 |
GCC 4.7.0 breaks __attribute__((packed)) behavior on... (Developers) |
Hi,
maybe some of you are using mingw32 and/or writing portable code for 32/64bit systems so it may save your time on hunting bugs. I just recompiled my KMD under new mingw32 4.7.0 and got a crash. After night tracking I found that the problem is in size of structure:
typedef struct { // 48-bit adresa GDT/IDT
Word limit; // size limit of GDT [Bytes-1]
DWord base; // linear base address of the GDT in physical memory
} __attribute__((packed)) GDTR;
You may think that __attribute__((packed)) save your ass and will be always 6 Bytes. Forget, not now, world is going mad and packing behaves differently.
To fix it, it's needed to add -mno-ms-bitfields gcc option since version 4.7.0.
But not at all systems. DJGPP 4.7.1 doesn't need it. But mingw32 and 64-bit linux gcc yes. More at https://lists.gnu.org/archive/html/qemu-devel/2012-07/msg02240.html --- DOS gives me freedom to unlimited HW access. |
Rugxulo
Usono, 04.09.2012, 23:16
@ RayeR
|
GCC 4.7.0 breaks __attribute__((packed)) behavior on... |
Hi,
(N.B. I know almost nothing, so keep in mind I only barely heard about this stuff.)
> maybe some of you are using mingw32 and/or writing portable code for
> 32/64bit systems so it may save your time on hunting bugs.
C actually doesn't "demand" portable code, nor does GCC. It's within the guidelines of the C language (from Rationale?) to actually write "fast but non-portable code" if needed. (Not everything has to be "strictly conformant", and there are many environmental dependencies that people often overlook, e.g. file name length, temp dirs [if any], size of various things, etc). Portability is often way more complex than just language syntax.
> I just
> recompiled my KMD under new mingw32 4.7.0 and got a crash. After night
> tracking I found that the problem is in size of structure:
>
> __attribute__((packed))
That is not really portable. So you're basically upset that one GCC supports it a certain way while another doesn't. (IIRC, e.g. Bellard's TCC only accepted such a thing on individual struct members, not the overall struct. Not sure what other compilers accept, most seem to accept some form of #pragma pack , but #pragma options are inherently non-standard).
> You may think that __attribute__((packed)) save your ass and will be always
> 6 Bytes.
Needing exact size is rare (network packets??), or at least more rare than otherwise. Most structs (and things like long double) are aligned for better speed. (Some architectures actually demand alignment of all code. x86 only mostly demands it for SSE. I think GCC now assumes or makes sure the stack is 16-byte aligned now, definitely for x86-64, maybe even x86, because of that.)
> Forget, not now, world is going mad and packing behaves
> differently.
> To fix it, it's needed to add -mno-ms-bitfields gcc option since version
> 4.7.0.
> But not at all systems. DJGPP 4.7.1 doesn't need it. But mingw32 and 64-bit
> linux gcc yes.
Earlier today, I just happened to read (for literally no reason beyond curiosity) about (ActiveState) Perl and XS modules and needing a compiler. I have no interest in Windows programming, but I was looking up random stuff about makefiles. Anyways, apparently MinGW and MSVC (since both use MSVCRT) can build compatible code (e.g. XS modules) if you use the (now default) ms-bitfields part. So that's probably GCC's upstream motivation, if I had to take a guess.
You may also want to take a look at C11 (-std=c11 for GCC 4.7.1) alignof, alignas, max_align_t, aligned_alloc (stdalign.h). I'm not 100% aware of the syntax, but it's somewhat restricted, i.e. you can't necessarily decrease an object's alignment (and I'm not sure most object formats let you willy nilly change overall alignment anyways, e.g. DJGPP COFF). |
RayeR
CZ, 05.09.2012, 03:46
@ Rugxulo
|
GCC 4.7.0 breaks __attribute__((packed)) behavior on... |
I don't want/have time for long philosophic discussion about portable code, different C compilers, why need packed structures, etc...
I just giving a warning, that new gcc since ver 4.7.0 changed default bahavior of attribute packed (-mms-bitfields become default) that may affect older SW when recompiling. I see it as very serious change. I understand this was done for some reasons of compatability with M$ and/or 64bit stuff but I don't agree with this way. Attribute packed should be left to always pack the structure to minimum size without padding (otherwise I would't use this attribute at all) and they could introduce some new attribute ms_packed... --- DOS gives me freedom to unlimited HW access. |
Rugxulo
Usono, 05.09.2012, 11:26
@ RayeR
|
GCC 4.7.0 breaks __attribute__((packed)) behavior on... |
> I don't want/have time for long philosophic discussion about portable code,
> different C compilers, why need packed structures, etc...
I know, me neither, just saying, things are more complicated than they seem. It's not necessarily clear cut. Maybe it's a bug, maybe not, dunno.
> I just giving a warning, that new gcc since ver 4.7.0 changed default
> bahavior of attribute packed (-mms-bitfields become default) that may
> affect older SW when recompiling. I see it as very serious change.
It was (partially) mentioned:
http://gcc.gnu.org/gcc-4.7/changes.html
"IA-32/x86-64
Windows mingw targets are using the -mms-bitfields option by default."
> I understand this was done for some reasons of compatability with M$ and/or
> 64bit stuff but I don't agree with this way.
But if they left it incompatible with MSVC, other people would complain. You can't please everybody, something had to change. (Though, again, this may indeed be a bug where "packed" should always be minimal, but I vaguely doubt it.)
> Attribute packed should be
> left to always pack the structure to minimum size without padding
> (otherwise I would't use this attribute at all) and they could introduce
> some new attribute ms_packed...
Just for reference, I found a few interesting tidbits in the manual (gcc.info):
= http://gcc.gnu.org/onlinedocs/gcc-4.7.1/gcc/Warning-Options.html#Warning-Options
= http://gcc.gnu.org/onlinedocs/gcc-4.7.1/gcc/Variable-Attributes.html#Variable-Attributes
= http://gcc.gnu.org/onlinedocs/gcc-4.7.1/gcc/Struct...king-Pragmas.html#Structure_002dPacking-Pragmas
= http://gcc.gnu.org/onlinedocs/gcc-4.7.1/gcc/Compatibility.html#Compatibility
"-Wpadded
Warn if padding is included in a structure, either to align an element of the structure or to align the whole structure. Sometimes when this happens it is possible to rearrange the fields of the structure to reduce the padding and so make the structure smaller." (does this warn you at all in this specific instance??)
"Note: The 4.1, 4.2 and 4.3 series of GCC ignore the packed attribute on bit-fields of type char. This has been fixed in GCC 4.4 but the change can lead to differences in the structure layout. See the documentation of -Wpacked-bitfield-compat for more information." (so a bug isn't impossible)
"6.36.5 i386 Variable Attributes
Two attributes are currently defined for i386 configurations: ms_struct and gcc_struct
ms_struct
gcc_struct
If packed is used on a structure, or if bit-fields are used it may be that the Microsoft ABI packs them differently than GCC would normally pack them. Particularly when moving packed data between functions compiled with GCC and the native Microsoft compiler (either via function call or as data in a file), it may be necessary to access either format."
"Some targets, e.g. i386 and powerpc, support the ms_struct #pragma which lays out a structure as the documented __attribute__ ((ms_struct)).
#pragma ms_struct on turns on the layout for structures declared.
#pragma ms_struct off turns off the layout for structures declared.
#pragma ms_struct reset goes back to the default layout."
So, you may? want to do something like this (untested):
#if (__GNUC__ == 4) && (__GNUC_MINOR__ >= 7) && defined(__MINGW32__)
#pragma ms_struct off
#endif
|
RayeR
CZ, 05.09.2012, 19:09 (edited by RayeR, 05.09.2012, 19:22)
@ Rugxulo
|
GCC 4.7.0 breaks __attribute__((packed)) behavior on... |
> > I understand this was done for some reasons of compatability with M$
> and/or
> > 64bit stuff but I don't agree with this way.
>
> But if they left it incompatible with MSVC, other people would complain.
> You can't please everybody, something had to change. (Though, again, this
> may indeed be a bug where "packed" should always be minimal, but I vaguely
> doubt it.)
But the problem is in time sequence. From the beginning the mingw used -mno-ms-bitfields as default and when somebody needed to be compatible with MS code he suppressed this by -mms-bitfields in makefile. And it worked for about 10 years. But most of GNU libs was compiled by default with -mno-ms-bitfields. Now they change it and it affect all existing sources, makefiles and precompiled libs. This is the most problem I see.
> "-Wpadded
I tried Wpadded and it's silent :\
> Two attributes are currently defined for i386 configurations: ms_struct and
> gcc_struct
Yeah, interesting. I tried
__attribute__ ((gcc_struct, __packed__))
together and this enforced real packing. Thanks. So in my code I can add gcc_struct everywhere needed but still need to modify makefiles of older libs. Since what gcc version was gcc_struct supported? Will older gccs safely ignore it?
EDIT:
gcc_struct
Found in versions: 3.4
So it exist quite a long time... --- DOS gives me freedom to unlimited HW access. |