EmbeddedRelated.com
Forums
The 2024 Embedded Online Conference

Struct alignment problem (GCC)

Started by "ICLI, Bekir (EXT)" April 8, 2008
Just be aware that if you use an option that affects the
structure packing, then your code is not binary compatible
with code that has been compiled without such an option.
i.e. you might have to recompile newlib with the same
option.

Regards
Anton Erasmus
On Mon, 21 Jul 2008 10:02:30 +0200
42Bastian wrote:
>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@...
>
>
Hi,

Thanks for the answers..
I checked in GCC's "Using the GNU Compiler Collection" what "-ms.s.b=8" does.
There says:
" The size of all structures and unions will be rounded up to a multiple of the
number of bits set by this option. Permissible values are 8 and 32. The default
value varies for different toolchains. For the COFF targeted toolchain the default
value is 8. Specifying the larger number can produce faster, more efficient
code, but can also increase the size of the program. The two values are potentially
incompatible. Code compiled with one value cannot necessarily expect
to work with code or libraries compiled with the other value, if they exchange
information using structures or unions."

But my structs have no component smaller than a char, which is already 8 bits.
That means, giving this option should have no effect, am I right?

My problem is with the way the struct accesses are handled. I want to be able to tell the compiler to generate such a code that all write operations performed with these structs to be byte-per-byte.
PS: I have seen that the compiler uses for the 2byte write operations (of the byte-packed structs) always byte-wise access. Coming from that, I thought it'd be possible to tell him, do this for 4 byte acesses as well.

Best regards,
Bekir

-----Ursprgliche Nachricht-----
Von: A... [mailto:A...] Im Auftrag von Anton James Erasmus
Gesendet: Montag, 21. Juli 2008 10:51
An: A...
Betreff: Re: [AT91SAM] Struct alignment problem (GCC)

Just be aware that if you use an option that affects the
structure packing, then your code is not binary compatible
with code that has been compiled without such an option.
i.e. you might have to recompile newlib with the same
option.

Regards
Anton Erasmus
On Mon, 21 Jul 2008 10:02:30 +0200
42Bastian wrote:
>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@...
>
>
> But my structs have no component smaller than a char, which is already 8 bits.
> That means, giving this option should have no effect, am I right?

I used this option for TCP/IP where the IP header is misaligned due to
the 14 bytes of the ethernet-header.
It helped, gcc accesses long words byte by byte, until I rewrote the stack.

I'd say: Give it a try.

--
42Bastian

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

I already did, but I can see in the resulting assembly code the 4byte accesses.

-----Ursprgliche Nachricht-----
Von: A... [mailto:A...] Im Auftrag von 42Bastian
Gesendet: Montag, 21. Juli 2008 11:34
An: A...
Betreff: Re: AW: [AT91SAM] Struct alignment problem (GCC)
> But my structs have no component smaller than a char, which is already 8 bits.
> That means, giving this option should have no effect, am I right?

I used this option for TCP/IP where the IP header is misaligned due to
the 14 bytes of the ethernet-header.
It helped, gcc accesses long words byte by byte, until I rewrote the stack.

I'd say: Give it a try.

--
42Bastian

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

ICLI, Bekir (EXT) schrieb:
> I already did, but I can see in the resulting assembly code the 4byte accesses.

Strange. I did a small test:
struct test {
int a;
int b;
int d;
} __attribute__((packed));

int a(struct test *p){
return p->a+p->d;
}

Compiled with: arm-thumb-elf-gcc -O -S
I get:
.file "t.c"
.text
.align 2
.global a
.type a, %function
a:
@ args = 0, pretend = 0, frame = 0
@ frame_needed = 0, uses_anonymous_args = 0
@ link register save eliminated.
@ lr needed for prologue
mov r3, r0
ldrb r1, [r0, #0] @ zero_extendqisi2
ldrb r2, [r0, #1] @ zero_extendqisi2
orr r1, r1, r2, asl #8
ldrb r2, [r0, #2] @ zero_extendqisi2
orr r1, r1, r2, asl #16
ldrb r2, [r0, #3] @ zero_extendqisi2
orr r1, r1, r2, asl #24
ldrb r0, [r0, #8] @ zero_extendqisi2
ldrb r2, [r3, #9] @ zero_extendqisi2
orr r0, r0, r2, asl #8
ldrb r2, [r3, #10] @ zero_extendqisi2
orr r0, r0, r2, asl #16
ldrb r3, [r3, #11] @ zero_extendqisi2
orr r0, r0, r3, asl #24
add r0, r1, r0
mov pc, lr
.size a, .-a
.ident "GCC: (GNU) 3.4.4"

--
42Bastian

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

ICLI, Bekir (EXT) wrote:
> Hi all,

> 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)

Hmmmm, there are really two answers to this problem. The first has
already been suggested, and that is to force all structure members
to be aligned on word boundaries, but of course this does
not actually pack anything, and makes your structures bigger.

The way you have asked the question, I might assume that
some of the structures are being transmitted to the target
machine.

In this case, the only way around the problem is to write a library
that does the native to wire protocol pack/unpack operation for
you, and you'll have to design adescription string for every
structure.

I ran into this exact problem when porting code from an HC16 where
misaligned accesses were OK, to a Blackfin, where everything had to be
aligned on the correct boundary size.

Good luck!

Ralph

Hi all,

I have another question related to this argument here.

Here is the declaration:

struct l2_apb apb;
struct l2_apb * l2_apb_ptr;

l2_apb is a struct which is defined with __attribute__(packed)

If I say:

l2_apb_ptr = &apb;

l2_apb_ptr->prev_blk_ptr = l_status;

where l_status (and prev_blk_ptr) are 2 byte variables, he handles it
with two byte-wise accesses (strb).

If I say:

apb.prev_blk_ptr = l_status;

He handles it with one word-wise access (strh). Which means, any time
when I work with a pointer to this struct, he handles all the accesses
byte-wise.
Can I have somehow any control over this behavior? Better asked, would
it be somehow possible to access to this variable word-wise with a
pointer?

Best Regards,
Bekir

________________________________

Von: A... [mailto:A...] Im Auftrag
von Ralph Hempel
Gesendet: Montag, 21. Juli 2008 14:31
An: A...
Betreff: Re: [AT91SAM] Struct alignment problem (GCC)

ICLI, Bekir (EXT) wrote:
> Hi all,

> 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)

Hmmmm, there are really two answers to this problem. The first has
already been suggested, and that is to force all structure members
to be aligned on word boundaries, but of course this does
not actually pack anything, and makes your structures bigger.

The way you have asked the question, I might assume that
some of the structures are being transmitted to the target
machine.

In this case, the only way around the problem is to write a library
that does the native to wire protocol pack/unpack operation for
you, and you'll have to design adescription string for every
structure.

I ran into this exact problem when porting code from an HC16 where
misaligned accesses were OK, to a Blackfin, where everything had to be
aligned on the correct boundary size.

Good luck!

Ralph
Have you tried using:

__attribute__ ((aligned (2)))

rather than (packed)?

--- In A..., "ICLI, Bekir (EXT)"
wrote:
>
> Hi all,
>
> I have another question related to this argument here.
>
> Here is the declaration:
>
> struct l2_apb apb;
> struct l2_apb * l2_apb_ptr;
>
> l2_apb is a struct which is defined with __attribute__(packed)
>
> If I say:
>
> l2_apb_ptr = &apb;
>
> l2_apb_ptr->prev_blk_ptr = l_status;
>
> where l_status (and prev_blk_ptr) are 2 byte variables, he handles it
> with two byte-wise accesses (strb).
>
> If I say:
>
> apb.prev_blk_ptr = l_status;
>
> He handles it with one word-wise access (strh). Which means, any time
> when I work with a pointer to this struct, he handles all the accesses
> byte-wise.
> Can I have somehow any control over this behavior? Better asked, would
> it be somehow possible to access to this variable word-wise with a
> pointer?
>
> Best Regards,
> Bekir
>
> ________________________________
>
> Von: A... [mailto:A...] Im Auftrag
> von Ralph Hempel
> Gesendet: Montag, 21. Juli 2008 14:31
> An: A...
> Betreff: Re: [AT91SAM] Struct alignment problem (GCC)
>
> ICLI, Bekir (EXT) wrote:
> > Hi all,
>
> > 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)
>
> Hmmmm, there are really two answers to this problem. The first has
> already been suggested, and that is to force all structure members
> to be aligned on word boundaries, but of course this does
> not actually pack anything, and makes your structures bigger.
>
> The way you have asked the question, I might assume that
> some of the structures are being transmitted to the target
> machine.
>
> In this case, the only way around the problem is to write a library
> that does the native to wire protocol pack/unpack operation for
> you, and you'll have to design adescription string for every
> structure.
>
> I ran into this exact problem when porting code from an HC16 where
> misaligned accesses were OK, to a Blackfin, where everything had to be
> aligned on the correct boundary size.
>
> Good luck!
>
> Ralph
>

ICLI, Bekir (EXT) wrote:
> Hi all,
>
> I have another question related to this argument here.
>
> Here is the declaration:
>
> struct l2_apb apb;
> struct l2_apb * l2_apb_ptr;
> l2_apb is a struct which is defined with __attribute__(packed)

First, avoid using lower case ell like this, it makes the
variable hard to read. (is that a 1 or an l?)

> If I say:
>
> l2_apb_ptr = &apb;
>
> l2_apb_ptr->prev_blk_ptr = l_status;
>
> where l_status (and prev_blk_ptr) are 2 byte variables, he handles it
> with two byte-wise accesses (strb).
>
> If I say:
>
> apb.prev_blk_ptr = l_status;
>
> He handles it with one word-wise access (strh). Which means, any time
> when I work with a pointer to this struct, he handles all the accesses
> byte-wise.
> Can I have somehow any control over this behavior? Better asked, would
> it be somehow possible to access to this variable word-wise with a pointer?

The answer is, it depends.

Actually you might need to answer another question first, which
is why are you trying to optimize this little bit of code? Is your
CPU or memory utilization so high that you're trying to save
instruction space and CPU cycles at the this level?

On to the answer you wanted :-)

When you define a structure as packed, the elements are jammed together
with no space, which is what you want. Note well that there may still
be endianness issues if you are shipping this struct off the CPU!

Individual instances of the structure are, however, aligned on natural
memory boundaries, which are 32 bits on the ARM. Depending on where
prev_blk_ptr is in the struct, the compiler might know that it can
safely do a word copy of l_status IF YOU ARE ADRESSING AN INDIVIDUAL
STRUCTURE INSTANCE.

Sorry for uppercasing, but that's an important point.

Once you access through a pointer, the compiler has no way of knowing
if the structure was aligned on a 32 bit boundary, because you might
have an l2_apb structure that is itself embedded in a packed structure.

So using the pointer access forces the compiler to use bye access
because it's simply safer.

To avoid this behaviour, don't pack your structures. It allows the
most efficient access to your structures.

And follow my advice from a previous message in this thread which
is to write a crack/uncrack library for the structures that you're
passing off the CPU :-)

Yes, I know it's a lot of work, but it will save you a lot of
debugging time later.

Ralph

The 2024 Embedded Online Conference