[Bug 206810] 11.0-CURRENT/clang380-import for powerpc (32-bit): signal handlers given insufficient stack alignment
bugzilla-noreply at freebsd.org
bugzilla-noreply at freebsd.org
Mon Feb 1 00:36:28 UTC 2016
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 at FreeBSD.org
Reporter: markmi at 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.
More information about the freebsd-bugs
mailing list