EmbeddedRelated.com
Forums

Struct alignment problem (GCC)

Started by "ICLI, Bekir (EXT)" April 8, 2008
Chris DeLise wrote:
>
> The network folks understand this, but there is a lot of legacy code
> that doesn't use these techniques. I think part of the problem is that
> ARM architecture doesn't gracefully cope with unaligned data in the way
> CISC machines do with reduced performance.

This is the key point that a lot of "desktop" programmers don't get.

They have matured with PC technology where unaligned accesses of
data just take extra clock cycles, and where compilers generally
packed structure slements by default to save space.

They often don't understand that misaligned accesses are simply not
allowed on ARM (or Blackfin) devices - in fact just about any modern
micro that has some DSP aspirations has this "flaw" from their
point of view.

Even more surprising to them is that they compiler may not even
order their structure elements in the order they are defined!

Of course, us embedded old timers just grin when their carefully
crafted structures that mimic machine registers or network data
packets don't work as expected :-)

Ralph

PS. I love these types of threads as opposed to the "help me do
my homework" or "we need free drivers" messages

Ralph,

> Even more surprising to them is that they compiler may not even
> order their structure elements in the order they are defined!

Actually, that is specifically precluded by the ISO standard: members *must*
be allocated in ascending address order.

--
Paul Curtis, Rowley Associates Ltd http://www.rowley.co.uk
CrossWorks for ARM, MSP430, AVR, MAXQ, and now Cortex-M3 processors

Paul Curtis wrote:
> Ralph,
>
>> Even more surprising to them is that they compiler may not even
>> order their structure elements in the order they are defined!
>
> Actually, that is specifically precluded by the ISO standard: members *must*
> be allocated in ascending address order.

You are, of course, correct. I was thinking of compiler directives
that allow structure members to be shuffled around to minimize
"wasted" space...

Thanks for pointing that out, and I'll keep it in my back pocket
for those often heated "why is the compiler doing THIS?" discussions.

Ralph

> Nah, the only truly portable solution is not to use
> any sort of packed
> attribute. ;)
>
That's right!

Moreover there are cases where packed/alligned
attributes do not work as expected. For example I
wasn't able to make the following structure in 4 bytes
under gcc:

typedef union
{
struct {unsigned char low; unsigned char hi;};
unsigned short as_short;
} short_reg;

struct{
short_reg a ;
short_reg b ;
} test ;
I was using this with other compilers without
problems, but with gcc - no luck and I think I have
tried all...

__________________________________________________

Just to make matters more interesting. I don't know which version of
GCC you are using, but I tried this:

//---------------------------------
struct hilo {unsigned char lo; unsigned char hi;};
typedef union
{
struct hilo highlow;
unsigned short as_short;
} short_reg;

struct {
short_reg a ;
short_reg b ;
} test ;

void main()
{
volatile int i;

test.a.highlow.hi=5;
test.a.highlow.lo;

i=test.a.highlow.hi*test.a.highlow.lo;

i=sizeof(test);

i=test.b.highlow.hi*2;
};
//---------------------------------

With CodeSourcery's command line compiler GCC 4.2.1, and the
sizeof(test) gives me 4.

John

--- In A..., Miroslav Kostadinov wrote:
> > Nah, the only truly portable solution is not to use
> > any sort of packed
> > attribute. ;)
> >
> That's right!
>
> Moreover there are cases where packed/alligned
> attributes do not work as expected. For example I
> wasn't able to make the following structure in 4 bytes
> under gcc:
>
> typedef union
> {
> struct {unsigned char low; unsigned char hi;};
> unsigned short as_short;
> } short_reg;
>
> struct{
> short_reg a ;
> short_reg b ;
> } test ;
> I was using this with other compilers without
> problems, but with gcc - no luck and I think I have
> tried all...
>
> __________________________________________________

John,

it's: arm-elf-gcc (GCC) 4.2.2 but I have noticed this
problem with earlier versions.

I guess you may have some "magic" command line
option... Here is my log:
Compiling C: app/main.c

arm-elf-gcc -c -mthumb -mcpu=arm7tdmi -gdwarf-2 -Os
-fomit-frame-pointer -fverbose-asm -I. -Wall
-Wcast-align -Wimplicit -Wstrict-prototypes
-Wpointer-arith -Wswitch -Wredundant-decls
-Wreturn-type -Wshadow -Wunused
-Wa,-adhlns=out/app/main.lst -Wnested-externs
-funsigned-char -std=gnu99 -MD -MP -MF
out/app/main.o.dep app/main.c -o out/app/main.o

--- John wrote:

> Just to make matters more interesting. I don't know
> which version of
> GCC you are using, but I tried this:
>
> //---------------------------------
> struct hilo {unsigned char lo; unsigned char hi;};
> typedef union
> {
> struct hilo highlow;
> unsigned short as_short;
> } short_reg;
>
> struct {
> short_reg a ;
> short_reg b ;
> } test ;
>
> void main()
> {
> volatile int i;
>
> test.a.highlow.hi=5;
> test.a.highlow.lo;
>
> i=test.a.highlow.hi*test.a.highlow.lo;
>
> i=sizeof(test);
>
> i=test.b.highlow.hi*2;
> };
> //---------------------------------
>
> With CodeSourcery's command line compiler GCC 4.2.1,
> and the
> sizeof(test) gives me 4.
>
> John
>
> --- In A..., Miroslav Kostadinov
> wrote:
> >
> >
> > > Nah, the only truly portable solution is not to
> use
> > > any sort of packed
> > > attribute. ;)
> > >
> >
> >
> > That's right!
> >
> > Moreover there are cases where packed/alligned
> > attributes do not work as expected. For example I
> > wasn't able to make the following structure in 4
> bytes
> > under gcc:
> >
> > typedef union
> > {
> > struct {unsigned char low; unsigned char hi;};
> > unsigned short as_short;
> > } short_reg;
> >
> > struct{
> > short_reg a ;
> > short_reg b ;
> > } test ;
> >
> >
> > I was using this with other compilers without
> > problems, but with gcc - no luck and I think I
> have
> > tried all...
> >
> > __________________________________________________
> >
>

__________________________________________________

arm-none-eabi-gcc -S testunion.c

Intermixing the resultant C and assembly code:
-------------
struct hilo {unsigned char lo; unsigned char hi;};

typedef union
{
struct hilo highlow;
unsigned short as_short;
} short_reg;

struct {
short_reg a ;
short_reg b ;
} test ;

void main()
{
volatile int i;

test.a.highlow.hi=5;
ldr r2, .L3
mov r3, #5
strb r3, [r2, #1]

test.a.highlow.lo;
ldr r2, .L3
mov r3, #10
strb r3, [r2, #0]

i=test.a.highlow.hi*test.a.highlow.lo;
ldr r3, .L3
ldrb r3, [r3, #1] @ zero_extendqisi2
mov r2, r3
ldr r3, .L3
ldrb r3, [r3, #0] @ zero_extendqisi2
mul r3, r2, r3
str r3, [fp, #-8]

i=sizeof(test);
mov r3, #4
str r3, [fp, #-8]

i=test.b.highlow.hi*2;
ldr r3, .L3
ldrb r3, [r3, #3] @ zero_extendqisi2
mov r3, r3, asl #1
str r3, [fp, #-8]
};
-------------
Again, looks right to me.

John

--- In A..., Miroslav Kostadinov wrote:
>
> John,
>
> it's: arm-elf-gcc (GCC) 4.2.2 but I have noticed this
> problem with earlier versions.
>
> I guess you may have some "magic" command line
> option... Here is my log:
> Compiling C: app/main.c
>
> arm-elf-gcc -c -mthumb -mcpu=arm7tdmi -gdwarf-2 -Os
> -fomit-frame-pointer -fverbose-asm -I. -Wall
> -Wcast-align -Wimplicit -Wstrict-prototypes
> -Wpointer-arith -Wswitch -Wredundant-decls
> -Wreturn-type -Wshadow -Wunused
> -Wa,-adhlns=out/app/main.lst -Wnested-externs
> -funsigned-char -std=gnu99 -MD -MP -MF
> out/app/main.o.dep app/main.c -o out/app/main.o
>
> --- John wrote:
>
> > Just to make matters more interesting. I don't know
> > which version of
> > GCC you are using, but I tried this:
> >
> > //---------------------------------
> > struct hilo {unsigned char lo; unsigned char hi;};
> > typedef union
> > {
> > struct hilo highlow;
> > unsigned short as_short;
> > } short_reg;
> >
> > struct {
> > short_reg a ;
> > short_reg b ;
> > } test ;
> >
> > void main()
> > {
> > volatile int i;
> >
> > test.a.highlow.hi=5;
> > test.a.highlow.lo;
> >
> > i=test.a.highlow.hi*test.a.highlow.lo;
> >
> > i=sizeof(test);
> >
> > i=test.b.highlow.hi*2;
> > };
> > //---------------------------------
> >
> > With CodeSourcery's command line compiler GCC 4.2.1,
> > and the
> > sizeof(test) gives me 4.
> >
> > John
> >
> > --- In A..., Miroslav Kostadinov
> > wrote:
> > >
> > >
> > > > Nah, the only truly portable solution is not to
> > use
> > > > any sort of packed
> > > > attribute. ;)
> > > >
> > >
> > >
> > > That's right!
> > >
> > > Moreover there are cases where packed/alligned
> > > attributes do not work as expected. For example I
> > > wasn't able to make the following structure in 4
> > bytes
> > > under gcc:
> > >
> > > typedef union
> > > {
> > > struct {unsigned char low; unsigned char hi;};
> > > unsigned short as_short;
> > > } short_reg;
> > >
> > > struct{
> > > short_reg a ;
> > > short_reg b ;
> > > } test ;
> > >
> > >
> > > I was using this with other compilers without
> > > problems, but with gcc - no luck and I think I
> > have
> > > tried all...
> > >
> > > __________________________________________________
> > >
> > >
> >
> >
> >
> __________________________________________________

I just copy & paste your code in a new file named
testunion.c

And then I write in the command prompt:

arm-elf-gcc -S testunion.c

The resulting testunion.s file is:
.file "testunion.c"
.text
.align 2
.global main
.type main, %function
main:
@ args = 0, pretend = 0, frame = 4
@ frame_needed = 1, uses_anonymous_args = 0
mov ip, sp
stmfd sp!, {fp, ip, lr, pc}
sub fp, ip, #4
sub sp, sp, #4
ldr r2, .L3
mov r3, #5
strb r3, [r2, #1]
ldr r2, .L3
mov r3, #10
strb r3, [r2, #0]
ldr r3, .L3
ldrb r3, [r3, #1] @ zero_extendqisi2
mov r2, r3
ldr r3, .L3
ldrb r3, [r3, #0] @ zero_extendqisi2
mul r3, r2, r3
str r3, [fp, #-16]
mov r3, #8
str r3, [fp, #-16]
ldr r3, .L3
ldrb r3, [r3, #5] @ zero_extendqisi2
mov r3, r3, asl #1
str r3, [fp, #-16]
ldmfd sp, {r3, fp, sp, pc}
.L4:
.align 2
.L3:
.word test
.size main, .-main
.comm test,8,4
.ident "GCC: (GNU) 4.2.2"

I think we get almost "the same" result except for the
fact that the size is not the same ;-)

Cheers,
Miro

--- John wrote:

> arm-none-eabi-gcc -S testunion.c
>
> Intermixing the resultant C and assembly code:
> -------------
> struct hilo {unsigned char lo; unsigned char hi;};
>
> typedef union
> {
> struct hilo highlow;
> unsigned short as_short;
> } short_reg;
>
> struct {
> short_reg a ;
> short_reg b ;
> } test ;
>
> void main()
> {
> volatile int i;
>
> test.a.highlow.hi=5;
> ldr r2, .L3
> mov r3, #5
> strb r3, [r2, #1]
>
> test.a.highlow.lo;
> ldr r2, .L3
> mov r3, #10
> strb r3, [r2, #0]
>
> i=test.a.highlow.hi*test.a.highlow.lo;
> ldr r3, .L3
> ldrb r3, [r3, #1] @ zero_extendqisi2
> mov r2, r3
> ldr r3, .L3
> ldrb r3, [r3, #0] @ zero_extendqisi2
> mul r3, r2, r3
> str r3, [fp, #-8]
>
> i=sizeof(test);
> mov r3, #4
> str r3, [fp, #-8]
>
> i=test.b.highlow.hi*2;
> ldr r3, .L3
> ldrb r3, [r3, #3] @ zero_extendqisi2
> mov r3, r3, asl #1
> str r3, [fp, #-8]
> };
> -------------
> Again, looks right to me.
>
> John
>
> --- In A..., Miroslav Kostadinov
> wrote:
> >
> > John,
> >
> > it's: arm-elf-gcc (GCC) 4.2.2 but I have noticed
> this
> > problem with earlier versions.
> >
> > I guess you may have some "magic" command line
> > option... Here is my log:
> >
> >
> > Compiling C: app/main.c
> >
> > arm-elf-gcc -c -mthumb -mcpu=arm7tdmi -gdwarf-2
> -Os
> > -fomit-frame-pointer -fverbose-asm -I. -Wall
> > -Wcast-align -Wimplicit -Wstrict-prototypes
> > -Wpointer-arith -Wswitch -Wredundant-decls
> > -Wreturn-type -Wshadow -Wunused
> > -Wa,-adhlns=out/app/main.lst -Wnested-externs
> > -funsigned-char -std=gnu99 -MD -MP -MF
> > out/app/main.o.dep app/main.c -o out/app/main.o
> >
> >
> >
> > --- John wrote:
> >
> > > Just to make matters more interesting. I don't
> know
> > > which version of
> > > GCC you are using, but I tried this:
> > >
> > > //---------------------------------
> > > struct hilo {unsigned char lo; unsigned char
> hi;};
> > > typedef union
> > > {
> > > struct hilo highlow;
> > > unsigned short as_short;
> > > } short_reg;
> > >
> > > struct {
> > > short_reg a ;
> > > short_reg b ;
> > > } test ;
> > >
> > > void main()
> > > {
> > > volatile int i;
> > >
> > > test.a.highlow.hi=5;
> > > test.a.highlow.lo;
> > >
> > > i=test.a.highlow.hi*test.a.highlow.lo;
> > >
> > > i=sizeof(test);
> > >
> > > i=test.b.highlow.hi*2;
> > > };
> > > //---------------------------------
> > >
> > > With CodeSourcery's command line compiler GCC
> 4.2.1,
> > > and the
> > > sizeof(test) gives me 4.
> > >
> > > John
> > >
> > > --- In A..., Miroslav
> Kostadinov
> > > wrote:
> > > >
> > > >
> > > > > Nah, the only truly portable solution is not
> to
> > > use
> > > > > any sort of packed
> > > > > attribute. ;)
> > > > >
> > > >
> > > >
> > > > That's right!
> > > >
> > > > Moreover there are cases where packed/alligned
> > > > attributes do not work as expected. For
> example I
> > > > wasn't able to make the following structure in
> 4
> > > bytes
> > > > under gcc:
> > > >
> > > > typedef union
> > > > {
> > > > struct {unsigned char low; unsigned char
> hi;};
> > > > unsigned short as_short;
> > > > } short_reg;
> > > >
> > > > struct{
> > > > short_reg a ;
> > > > short_reg b ;
> > > > } test ;
> > > >
> > > >
> > > > I was using this with other compilers without
> > > > problems, but with gcc - no luck and I think I
> > > have
> > > > tried all...
> > > >
> > > >
> __________________________________________________
> > > >
> > > >
> > >
> > >
> > >
> >
> >
> > __________________________________________________
> >
>

__________________________________________________

Hi all,

I've checked the history for my old question about using the "packed" attribute of gcc, and decided to follow it.
Here is my problem: We have a huge code in our project that is inherited from old projects and is written for a specific hardware.
And this code uses almost all the structs as packed. I have turned on the alignment error checks in MMU and am getting misaligned attempts almost all over the code.
My question is, is there any way to tell the compiler that he should handle all the code related to the packed structs only with byte-wise accesses ?? (no matter if it is byte, word, or double word access is)

PS: As you see, I am in such a desperate situation that I'd prefer functionality over performance in the first place, because the code is completely unknown to us and it'd take months to understand and manipulate it..

Regards,
Bekir

________________________________

Von: A... [mailto:A...] Im Auftrag von ICLI, Bekir (EXT)
Gesendet: Dienstag, 8. April 2008 09:48
An: A...
Betreff: [AT91SAM] Struct alignment problem (GCC)

Hi all,

I am generating my code with GNU-ARM..
I have searched and found that the solution to this struct mis-alignment problem is:
__attribute__((__packed__))

Is there any compiler option, that would do the same for all structs I define?
Or do I have to write this attribute to all of them?
I found in gcc.pdf

-fpack-struct
Pack all structure members together without holes.
Warning: the '-fpack-struct' switch causes GCC to generate code that is
not binary compatible with code generated without that switch. Additionally,
it makes the code suboptimal. Use it to conform to a non-default application
binary interface.
After compiling my code with this option, it did not work, which, I guess, confirms the warning.
I am not even sure if this is the correct compiler option.

Any help would be greatly appreciated..

Mit freundlichem Gru/ Best regards
Bekir ICLI
ICLI, Bekir (EXT) schrieb:

> My question is, is there any way to tell the compiler that he should
> handle all the code related to the packed structs only with byte-wise
> accesses ?? (no matter if it is byte, word, or double word access is)

Maybe this option helps (size in bits!)
-mstructure-size-boundary=8
--
42Bastian

Note: SPAM-only account, direct mail to bs42@...