linux-user/flatload: fix initial stack pointer alignment
PATCH 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
--- linux-user/flatload.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
linux-user/flatload.c +5 -3
@@ -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 ());
Signature · 1 line
2.11.0
Quoted 23 lines · Max Filippov
Stack pointer alignment code incorrectly adds
stack_sizeto sp instead of subtracting it. It also does not takeflat_argvp_envp_on_stack()into account when calculatingstack_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.cSigned-off-by Max Filippov <[email protected]>--- linux-user/flatload.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)linux-user/flatload.c +0
-0@@ -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
linux-user/flatload.c int load_flt_binary(struct linux_binprm *bprm, struct image_info *info) · line 778
Quoted 10 lines
linux-user/flatload.c +5
-3for 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
Quoted 5 lines · Laurent Vivier
Quoted 4 lines
linux-user/flatload.c +0
-0
Quoted 8 lines
linux-user/flatload.c int load_flt_binary(struct linux_binprm *bprm, struct image_info *info) · line 779
Quoted 4 lines
linux-user/flatload.c +3
-1- 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.
Signature · 2 lines
Thanks. -- Max
Quoted 12 lines · Max Filippov
Quoted 10 lines · Laurent Vivier
Quoted 9 lines
linux-user/flatload.c +3
-1- sp -=16 - ((sp + stack_len) &15 ); +if ((sp - stack_len) &15 ) { + sp -= ((sp - stack_len) &15 ); + }
Quoted 5 lines
Quoted 3 lines
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.
Signature · 2 lines
Thanks. -- Max