Use of $v10 register (was Re: klibc: [s390x] SIGSEGV in mksh testcase funsub-2)
retitle 943425 klibc: [s390x] setjmp/longjmp do not save/restore all registers in use
# because this affects a release architecture
severity 943425 serious
thanks
Recapping for the benefit of d-s390@l.d.o:
> The code in question (where it crashes) is thus:
> 1607 */
> 1608 valsub(t, NULL);
> 1609 subst_exstat = exstat & 0xFF;
> 1610 /* rewind the tempfile and restore regular stdout */
> 1611 lseek(shf_fileno(shf), (off_t)0, SEEK_SET);
> The crash occurs in line 1611 because shf (a local variable) is nil.
>
> The really interesting part, though, is in line 1608, a call to valsub():
[…]
> 2104 if (!kshsetjmp(e->jbuf))
> 2105 execute(t, XXCOM | XERROK, NULL);
[…]
kshsetjmp(x) is sigsetjmp(x,0) (though klibc ignores the 0).
execute() calls siglongjmp().
> - it appears as if the combination of sigsetjmp/siglongjmp does not restore
> all callee-saved variables correctly on s390x; comparing with glibc shows
> that the wrong FPU registers seem to be saved but mksh does not use the
> FPU anyway
>
> Setting breakpoints to lines 1608 (valsub call) and 1609:
[…]
> 1608 valsub(t, NULL);
> (gdb) print shf
> $5 = (struct shf *) 0x3fffdfe5de8
> (gdb) print &shf
> Address requested for identifier "shf" which is in register $v10
> (gdb) print $v10
> $6 = {v4_float = {1.43352833e-42, -4.22639375e+37, 0, 0}, v2_double = {2.1729070589754877e-311, 0}, v16_int8 = {
> 0, 0, 3, -1, -3, -2, 93, -24, 0, 0, 0, 0, 0, 0, 0, 0}, v8_int16 = {0, 1023, -514, 24040, 0, 0, 0, 0},
> v4_int32 = {1023, -33661464, 0, 0}, v2_int64 = {4398012849640, 0}, uint128 = 81129017470195127308370827018240}
>
> 0x3FFFDFE5DE8 is 4398012849640 which is in v2_int64, found.
[…]
> Breakpoint 2, comsub (fn=14, cp=0x0, xp=<synthetic pointer>) at ../../eval.c:1609
> 1609 subst_exstat = exstat & 0xFF;
[…]
> (gdb) print $v10
> $7 = {v4_float = {0, 0, 0, 0}, v2_double = {0, 0}, v16_int8 = {0 <repeats 16 times>}, v8_int16 = {0, 0, 0, 0,
> 0, 0, 0, 0}, v4_int32 = {0, 0, 0, 0}, v2_int64 = {0, 0}, uint128 = 0}
------------------------------------------------------------------
So, setjmp/longjmp in klibc save f1/f3/f5/f7 (as shown on Wikipedia
https://en.wikipedia.org/wiki/Calling_convention#IBM_System/360_and_successors
“the z/Architecture ABI,[11] used in Linux” a page down), while
glibc’s save f8–f15 instead.
https://share.confex.com/share/124/webprogram/Handout/Session16897/SHARE_Seattle_2015_SIMD.pdf
shows that the vector registers overlap and extend the FPU registers.
(gdb) info float
[…]
f10 2.172907066248134e-311 (raw 0x000003fffdfe9768)
(gdb) print shf
$2 = (struct shf *) 0x3fffdfe9768
The real questions here are:
• is register v10 (vector extension) even supposed to be used?
• klibc does not really support the FPU anyway
• the half of v10 that equals f10 just HAPPENS to be saved by
glibc, but what if the upper half, that is outside of the FPU,
is used?
• where *is* the s390x̲ ABI documented anyway? syscall(2) has the
kernel side only
Building with -mno-vx does not seem to help, %f* are still in
the .s files generated by gcc.
So I assume klibc should save registers f8–15 on s390x but what
happened to f1/f3/f5/f7?
Thanks,
//mirabilos
--
[17:15:07] Lukas Degener: Kleines Asterix-Latinum für Softwaretechniker:
veni, vidi, fixi(t) ;-)
Reply to: