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) ;-)