7

I am emulating code from an embedded system (stm32, Keil µVision 5, MDK-ARM) on a PC (mingw32, 32bit arch). The alignment of the ARM compiler does not match my desktop mingw build:

// ARM Code (ARM compiler uses __packed)
typedef __packed struct _file
{
    uint8_t var1;
    uint16_t var2;
} FILE;

// PC mingw gcc code trying to emulate layout above.
typedef struct __attribute__((packed, aligned(1))) _file
{
    uint8_t var1;
    uint16_t var2;
} FILE;


In the source I do the following: file.var1 = 0x22; file.var2 = 0xAA55; which is then written to memory. When I read the memory on the embedded system it shows 0x22, 0x55, 0xAA. On the Windows machine it reads 0x22, 0xFF, 0x55, 0xAA, with padding at the 2nd byte. How can I correct this behaviour?

artless noise
  • 21,212
  • 6
  • 68
  • 105
clambake
  • 772
  • 4
  • 15
  • 3
    OT: I'd suggest using a different name than `FILE`, that name is defined by the standard library and it's possible that any standard header you include in the Windows environment will also include `stdio.h`, even if the embedded environment doesn't have it – M.M Jun 03 '14 at 23:56
  • 3
    haha yes, you are right but this is not the code I am actually using. To demonstrate the behaviour I changed the names and trimmed it down. – clambake Jun 04 '14 at 05:20
  • you are misunderstanding and misusing the language is the problem. implementation defined features are just that. No reason to expect them to work that way beyond that one implementation that one day/version... – old_timer Feb 06 '19 at 18:13

4 Answers4

6

I fixed it by myself -> Compiling with -mno-ms-bitfields helps! The code above is indeed correct. It is necessary to tell mingw to use gcc's bitfield organisation instead of the microsoft style. Though the code can be uncompileable with microsoft compilers then, I do not care at this point.

clambake
  • 772
  • 4
  • 15
  • Alright? There are no bitfields in the code, but perhaps the compiler is being prepared for some. – unwind Jun 03 '14 at 13:19
  • I guess it is a problem in the mingw implementation. – clambake Jun 03 '14 at 13:25
  • 1
    This [old gcc post](https://lists.fedoraproject.org/pipermail/mingw/2008-November/000083.html) explains what it is doing. The question is not very clear. It sounded like you are porting PC code to an ARM; not the other way around. Normally, *cygwin* wants to be compatible with the Windows way. Ie, your code is expected to do Windows things with DLLs, etc and not try to *emulate* an ARM. I think I would look into XEN, etc to actually emulate this slow ARM CPU. – artless noise Jun 03 '14 at 22:52
  • 1
    Ie, the [`gcc_struct`](https://gcc.gnu.org/onlinedocs/gcc-4.9.0/gcc/Variable-Attributes.html) is probably the better option. See section **6.36.5 i386 Variable Attributes**. If you call actual Windows code, you may need the other one. – artless noise Jun 03 '14 at 22:56
  • 1
    I can't find documentation on `-mno-ms-bitfields` anywhere in GCC doc. Any URL link to that ? – LAL May 23 '19 at 21:39
  • The gcc struct link above is to an older version of the documentation referring to "i386". The current version, referring to "x86", can be found [here](https://gcc.gnu.org/onlinedocs/gcc/x86-Variable-Attributes.html). Checking [this list](https://gcc.gnu.org/onlinedocs/gcc/Variable-Attributes.html) of architectures with specific attributes, there's no separate entry for x86-64, so the information probably applies to 64-bit as well as 32-bit Windows/processor setups. – AJM Feb 09 '22 at 13:48
  • 1
    @LAL The gcc docs have information on `-mno-ms-bitfields` and `-mms-bitfields` [here](https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html#x86-Options). – AJM Feb 09 '22 at 13:50
2

attribute packed is broken on mingw32 compilers. Another option is to use pragma pack:

#pragma pack(1)
typedef struct _file
{
  uint8_t var1;
  uint16_t var2;
} FILE;
AJM
  • 1,317
  • 2
  • 15
  • 30
0

According to the GCC manual's examples, the attribute should go after the struct's fields, i.e.:

// PC Code
typedef struct
{
    uint8_t var1;
    uint16_t var2;
} __attribute__((packed, aligned(1))) FILE;

I also dropped the pointless struct tag (_file).

The above has a sizeof value of 3 when I tested it quickly.

unwind
  • 391,730
  • 64
  • 469
  • 606
  • `warning: 'packed' attribute ignored [-Wattributes] } FILE __attribute__((packed, aligned(1)));` Hmmmm.. – clambake Jun 03 '14 at 13:09
  • @artlessnoise What is not a `typedef`? The OP's code shows two `typedef`s, right? – unwind Jun 04 '14 at 07:28
  • @unwind Actually, according to [the GCC manual's page on attribute syntax](https://gcc.gnu.org/onlinedocs/gcc/Attribute-Syntax.html) both placements of `attribute` are valid: *"An attribute specifier list may appear as part of a struct, union or enum specifier. It may go either immediately after the struct, union or enum keyword, or after the closing brace. The former syntax is preferred."* – AJM Feb 09 '22 at 13:05
  • Plus, the link to GCC type attribute documentation in your answer is now outdated. [The current version](https://gcc.gnu.org/onlinedocs/gcc/Common-Type-Attributes.html) places `attribute` after `struct` in the examples, instead of after `}`. – AJM Feb 09 '22 at 13:09
0

Simply add gcc_struct attribute to tell mingw which struct packing alghorithm to use: attribute((gcc_struct,packed));

  • 1
    Hi and welcome to Stack Overflow. Thank you for your answer. Would you mind explaining more completely how to use this attribute and where to apply it? – Shaun Ramsey Mar 04 '23 at 07:51