Doubts about va_list alignment

Asked by Uwe Bonnes

Hello,

the ethernut project
svn checkout svn://svn.code.sf.net/p/ethernut/code/trunk ethernut-code
implements its own printf routines to be portable with compilers and architectures. With the launchpad toolchain we observe unexpected behaviour an AT91 and Cortex-M processors when pulling 64-bit units from the va_list, like

               double _double = va_arg(ap, double);

by either replacing above sequence with
                double _double
                uint32_t *l = (uint32_t *)&_double;

                if (*(uint32_t*)&ap & 4) {
                    l[0]= va_arg(ap, uint32_t);
                    l[1]= va_arg(ap, uint32_t);
                }
                else {
                    l[0]= va_arg(ap, uint32_t);
                    l[0]= va_arg(ap, uint32_t);
                    l[1]= va_arg(ap, uint32_t);
                }

or using a subroutine call like
double va_args_double(va_list *ap) {
    return va_arg(*ap, double);
}
...
            _double = va_args_double(&ap);
...

we can fix the issue. Looking at the assembler output for _double = va_arg(ap, double) we can see that ap is expected to be placed on a 8-byte boundary. If by chance ap is placed on odd 4 byte boundary things go astray.

Is this a problem with our setup of includes and compiler options or a general arm-gcc problem?

Question information

Language:
English Edit question
Status:
Solved
For:
GNU Arm Embedded Toolchain Edit question
Assignee:
No assignee Edit question
Solved by:
Uwe Bonnes
Solved:
Last query:
Last reply:
Revision history for this message
Joey Ye (jinyun-ye) said :
#1

Uwe, does the wrong program fault or just run with incorrect result?

Joey
On Sep 17, 2013 10:21 PM, "Uwe Bonnes" <email address hidden>
wrote:

> New question #235875 on GCC ARM Embedded:
> https://answers.launchpad.net/gcc-arm-embedded/+question/235875
>
> Hello,
>
> the ethernut project
> svn checkout svn://svn.code.sf.net/p/ethernut/code/trunk ethernut-code
> implements its own printf routines to be portable with compilers and
> architectures. With the launchpad toolchain we observe unexpected behaviour
> an AT91 and Cortex-M processors when pulling 64-bit units from the va_list,
> like
>
> double _double = va_arg(ap, double);
>
> by either replacing above sequence with
> double _double
> uint32_t *l = (uint32_t *)&_double;
>
> if (*(uint32_t*)&ap & 4) {
> l[0]= va_arg(ap, uint32_t);
> l[1]= va_arg(ap, uint32_t);
> }
> else {
> l[0]= va_arg(ap, uint32_t);
> l[0]= va_arg(ap, uint32_t);
> l[1]= va_arg(ap, uint32_t);
> }
>
> or using a subroutine call like
> double va_args_double(va_list *ap) {
> return va_arg(*ap, double);
> }
> ...
> _double = va_args_double(&ap);
> ...
>
> we can fix the issue. Looking at the assembler output for _double =
> va_arg(ap, double) we can see that ap is expected to be placed on a 8-byte
> boundary. If by chance ap is placed on odd 4 byte boundary things go astray.
>
> Is this a problem with our setup of includes and compiler options or a
> general arm-gcc problem?
>
>
>
> --
> You received this question notification because you are an answer
> contact for GCC ARM Embedded.
>

Revision history for this message
Uwe Bonnes (bon) said :
#2

It just runs with the wronmg arguments.

Revision history for this message
Uwe Bonnes (bon) said :
#3

Examinations show that our Linker scripts didn't align the stack to 8-byte boundaries. Probably this is the cause, but I could prove in our code so long. Will try with more patience this weekend. Let's keep the case open, I will come back!

Revision history for this message
Joey Ye (jinyun-ye) said :
#4

Uwe,

Any update so far? It won't work correctly if stack isn't aligned to 8 byte according to AAPCS.

- Joey

Revision history for this message
Uwe Bonnes (bon) said :
#5

With right alignment, things work as expected. Thanks for the patience!