https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=206810
Bug ID: 206810 Summary: 11.0-CURRENT/clang380-import for powerpc (32-bit): signal handlers given insufficient stack alignment Product: Base System Version: 11.0-CURRENT Hardware: ppc OS: Any Status: New Severity: Affects Only Me Priority: --- Component: kern Assignee: freebsd-bugs@FreeBSD.org Reporter: mar...@dsl-only.net [syslogd, nfsd, mountd, and make all get the described-below sorts of segmentation faults via similar __vfprintf use during a signal handler for the powerpc (32-bit) context identifed.] For a system based on buildworld with TARGET_ARCH=powerpc via clang 3.8.0 (and use of project/clang380-import -r294962) the following short program gets a segmentation violation for the use of handler via raise: #include <signal.h> // for signal, SIGINT, SIG_ERR, raise. #include <stdio.h> // for snprintf void handler(int sig) { char buf[32]; snprintf(buf, sizeof buf, "%d", sig); // FreeBSD's world does such things in some of its signal handlers } int main(void) { handler(0); // works fine if (signal(SIGINT, handler) != SIG_ERR) raise(SIGINT); // fails during handler return 0; } The problem actually occurs during __vfprintf (and the code it inlines), specifically for io_flush(struct io_state *iop, locale_t locale) has: return (__sprint(iop->fp, &iop->uio, locale)); The code generated that calculates &iop->uio depends on alignment by masking in the offset of 4 bytes instead of adding 4 to the address. ("li r3,4" and later "rlwimi r23,r3,0,29,29".) With the stack misalignment via the signal delivery the wrong address is calculated (the bit position already has a one). In fact it calculates the same address as its does for iop->fp (fp being the first field of *iop). For reference: #define NIOV 8 struct io_state { FILE *fp; struct __suio uio; /* output information: summary */ struct __siov iov[NIOV];/* ... and individual io vectors */ }; With the bad address propagated to #define COPY(n) (void)memcpy((void *)fp->_p, (void *)p, (size_t)(n)) (as p via __sfvwrite using COPY) the memcpy gets the segmentation fault. The signal delivery is generating a modulo-4 alignment that is not aligned for any higher power of 2. Roman Divacky reports via a list response that 16 byte alignment is expected by llvm for ppc32. While 16 is what I expect as the ABI requirement I do not have a definitive reference to the FreeBSD powerpc (32-bit) ABI criteria for this (or any) context: I can not point to the definition or a known-good secondary source to prove a violation of a rule. But I doubt that this should be considered a clang 3.8.0 defect for ppc32: it should be treated as a FreeBSD signal delivery defect instead as far as I can tell. Below I provide some gdb evidence of the good (direct handler call) vs. bad (signal based handler call) stack alignments for handler and for __vfprintf (and its inlined code) if you want to look. For __vfprintf's lots of local variables (including arrays) they all end up with unusual alignments from start from a unusual alignment. You can stop reading this description here to avoid this detail: There is no more after it. (gdb) run Starting program: /root/c_tests/a.out Breakpoint 10, 0x018006d4 in handler () (gdb) bt #0 0x018006d4 in handler () #1 0x01800760 in main () (gdb) info frame Stack level 0, frame at 0xffffdcb0: pc = 0x18006d4 in handler; saved pc = 0x1800760 called by frame at 0xffffdcd0 Arglist at 0xffffdc60, args: Locals at 0xffffdc60, Previous frame's sp is 0xffffdcb0 Saved registers: r31 at 0xffffdcac, pc at 0xffffdcb4, lr at 0xffffdcb4 vs. (gdb) cont Continuing. Breakpoint 10, 0x018006d4 in handler () (gdb) bt #0 0x018006d4 in handler () #1 <signal handler called> #2 0x00000000 in ?? () (gdb) info frame Stack level 0, frame at 0xffffd73c: pc = 0x18006d4 in handler; saved pc = 0xffffe008 called by frame at 0xffffd73c Arglist at 0xffffd6ec, args: Locals at 0xffffd6ec, Previous frame's sp is 0xffffd73c Saved registers: r31 at 0xffffd738, pc at 0xffffd740, lr at 0xffffd740 (gdb) info frame Stack level 0, frame at 0xffffdad0: pc = 0x41931590 in __vfprintf (/usr/src/lib/libc/stdio/vfprintf.c:454); saved pc = 0x4199c644 called by frame at 0xffffdc60 source language c. Arglist at 0xffffd880, args: fp=0xffffdb40, locale=0x419cba40 <__xlocale_global_locale>, fmt0=0x180085c "%d", ap=0xffffdc30 Locals at 0xffffd880, Previous frame's sp is 0xffffdad0 Saved registers: . . . vs. (gdb) info frame Stack level 0, frame at 0xffffd55c: pc = 0x41931590 in __vfprintf (/usr/src/lib/libc/stdio/vfprintf.c:454); saved pc = 0x4199c644 called by frame at 0xffffd6ec source language c. Arglist at 0xffffd30c, args: fp=0xffffd5cc, locale=0x419cba40 <__xlocale_global_locale>, fmt0=0x180085c "%d", ap=0xffffd6bc Locals at 0xffffd30c, Previous frame's sp is 0xffffd55c Saved registers: . . . -- You are receiving this mail because: You are the assignee for the bug. _______________________________________________ freebsd-bugs@freebsd.org mailing list https://lists.freebsd.org/mailman/listinfo/freebsd-bugs To unsubscribe, send any mail to "freebsd-bugs-unsubscr...@freebsd.org"