Skip to contentSkip to conversation

linux-user/flatload: fix initial stack pointer alignment

PATCH In review Max Filippov 2 participants 2 messages Oct 24, 2018

lore
Share & tools
lore
#0 lore raw

PATCH v2 1/1 linux-user/flatload: fix initial stack pointer alignment

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

---
Changes v1->v2:
- make sp adjustment unconditional

 linux-user/flatload.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
linux-user/flatload.c +3 -3
index 2eefe55e5000..0122ab3afe65 100644
@@ -771,10 +771,10 @@ 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);
+    sp -= (sp - stack_len) & 15;
     sp = loader_build_argptr(bprm->envc, bprm->argc, sp, p,
                              flat_argvp_envp_on_stack());
 
Signature · 1 line
2.11.0
Reviewed-by on v2 1/1
#1 lore raw
Quoted 29 lines · Max Filippov

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

---
Changes v1->v2:
- make sp adjustment unconditional

 linux-user/flatload.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
linux-user/flatload.c +0 -0
index 2eefe55e5000..0122ab3afe65 100644
@@ -771,10 +771,10 @@ 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;

linux-user/flatload.c int load_flt_binary(struct linux_binprm *bprm, struct image_info *info) · line 780

Quoted 10 lines
linux-user/flatload.c +3 -3
-    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);
+    sp -= (sp - stack_len) & 15;
     sp = loader_build_argptr(bprm->envc, bprm->argc, sp, p,
                              flat_argvp_envp_on_stack());