diff mbox series

linux-user/flatload: fix initial stack pointer alignment

Message ID 20181024023831.2529-1-jcmvbkbc@gmail.com
State New
Headers show
Series linux-user/flatload: fix initial stack pointer alignment | expand

Commit Message

Max Filippov Oct. 24, 2018, 2:38 a.m. UTC
Stack pointer alignment code incorrectly adds stack_size to sp instead
of subtracting it. It also does not take flat_argvp_envp_on_stack() into
account when calculating stack_size. This results in initial stack
pointer misalignment with certain set of command line arguments and
environment variables and correct alignment for the same binary with a
different set of arguments. This misalignment causes failures in the
following tests in the testsuite of gcc built for xtensa uclinux:

  gcc.dg/torture/vshuf-v64qi.c
  gcc.dg/torture/vshuf-v8sf.c
  gcc.dg/torture/vshuf-v8si.c

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 linux-user/flatload.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

Comments

Laurent Vivier Oct. 24, 2018, 11:35 a.m. UTC | #1
On 24/10/2018 03:38, Max Filippov wrote:
> Stack pointer alignment code incorrectly adds stack_size to sp instead
> of subtracting it. It also does not take flat_argvp_envp_on_stack() into
> account when calculating stack_size. This results in initial stack
> pointer misalignment with certain set of command line arguments and
> environment variables and correct alignment for the same binary with a
> different set of arguments. This misalignment causes failures in the
> following tests in the testsuite of gcc built for xtensa uclinux:
> 
>   gcc.dg/torture/vshuf-v64qi.c
>   gcc.dg/torture/vshuf-v8sf.c
>   gcc.dg/torture/vshuf-v8si.c
> 
> Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
> ---
>  linux-user/flatload.c | 8 +++++---
>  1 file changed, 5 insertions(+), 3 deletions(-)
> 
> diff --git a/linux-user/flatload.c b/linux-user/flatload.c
> index 2eefe55e5000..1893966b5b30 100644
> --- a/linux-user/flatload.c
> +++ b/linux-user/flatload.c
> @@ -771,10 +771,12 @@ int load_flt_binary(struct linux_binprm *bprm, struct image_info *info)
>      /* Enforce final stack alignment of 16 bytes.  This is sufficient
>         for all current targets, and excess alignment is harmless.  */
>      stack_len = bprm->envc + bprm->argc + 2;
> -    stack_len += 3;	/* argc, arvg, argp */
> +    stack_len += flat_argvp_envp_on_stack() ? 2 : 0; /* arvg, argp */
> +    stack_len += 1; /* argc */>      stack_len *= sizeof(abi_ulong);
> -    if ((sp + stack_len) & 15)
> -        sp -= 16 - ((sp + stack_len) & 15);
> +    if ((sp - stack_len) & 15) {
> +        sp -= ((sp - stack_len) & 15);
> +    }

If I understand correctly the purpose, I think it could be clearer like:

    sp = (sp - stack_len) & ~15;

Thanks,
Laurent
Max Filippov Oct. 24, 2018, 5:19 p.m. UTC | #2
On Wed, Oct 24, 2018 at 4:35 AM Laurent Vivier <laurent@vivier.eu> wrote:
> > diff --git a/linux-user/flatload.c b/linux-user/flatload.c
> > index 2eefe55e5000..1893966b5b30 100644
> > --- a/linux-user/flatload.c
> > +++ b/linux-user/flatload.c

> > -        sp -= 16 - ((sp + stack_len) & 15);
> > +    if ((sp - stack_len) & 15) {
> > +        sp -= ((sp - stack_len) & 15);
> > +    }
>
> If I understand correctly the purpose, I think it could be clearer like:
>
>     sp = (sp - stack_len) & ~15;

Yes, you're right. I'll send v2.
Max Filippov Oct. 24, 2018, 6:30 p.m. UTC | #3
On Wed, Oct 24, 2018 at 10:19 AM Max Filippov <jcmvbkbc@gmail.com> wrote:
>
> On Wed, Oct 24, 2018 at 4:35 AM Laurent Vivier <laurent@vivier.eu> wrote:
> > > diff --git a/linux-user/flatload.c b/linux-user/flatload.c
> > > index 2eefe55e5000..1893966b5b30 100644
> > > --- a/linux-user/flatload.c
> > > +++ b/linux-user/flatload.c
>
> > > -        sp -= 16 - ((sp + stack_len) & 15);
> > > +    if ((sp - stack_len) & 15) {
> > > +        sp -= ((sp - stack_len) & 15);
> > > +    }
> >
> > If I understand correctly the purpose, I think it could be clearer like:
> >
> >     sp = (sp - stack_len) & ~15;
>
> Yes, you're right. I'll send v2.

Well, not exactly. The sp is not moved down stack_len + alignment bytes,
only the alignment bytes. I'll send v2 anyway.
diff mbox series

Patch

diff --git a/linux-user/flatload.c b/linux-user/flatload.c
index 2eefe55e5000..1893966b5b30 100644
--- a/linux-user/flatload.c
+++ b/linux-user/flatload.c
@@ -771,10 +771,12 @@  int load_flt_binary(struct linux_binprm *bprm, struct image_info *info)
     /* Enforce final stack alignment of 16 bytes.  This is sufficient
        for all current targets, and excess alignment is harmless.  */
     stack_len = bprm->envc + bprm->argc + 2;
-    stack_len += 3;	/* argc, arvg, argp */
+    stack_len += flat_argvp_envp_on_stack() ? 2 : 0; /* arvg, argp */
+    stack_len += 1; /* argc */
     stack_len *= sizeof(abi_ulong);
-    if ((sp + stack_len) & 15)
-        sp -= 16 - ((sp + stack_len) & 15);
+    if ((sp - stack_len) & 15) {
+        sp -= ((sp - stack_len) & 15);
+    }
     sp = loader_build_argptr(bprm->envc, bprm->argc, sp, p,
                              flat_argvp_envp_on_stack());