From owner-freebsd-bugs@FreeBSD.ORG Thu Apr 4 15:16:08 2013 Return-Path: Delivered-To: freebsd-bugs@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by hub.freebsd.org (Postfix) with ESMTP id AEECCA40; Thu, 4 Apr 2013 15:16:08 +0000 (UTC) (envelope-from brde@optusnet.com.au) Received: from mail04.syd.optusnet.com.au (mail04.syd.optusnet.com.au [211.29.132.185]) by mx1.freebsd.org (Postfix) with ESMTP id 4F23F967; Thu, 4 Apr 2013 15:16:08 +0000 (UTC) Received: from c211-30-173-106.carlnfd1.nsw.optusnet.com.au (c211-30-173-106.carlnfd1.nsw.optusnet.com.au [211.30.173.106]) by mail04.syd.optusnet.com.au (8.13.1/8.13.1) with ESMTP id r34FG2Uf024396 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Fri, 5 Apr 2013 02:16:03 +1100 Date: Fri, 5 Apr 2013 02:16:02 +1100 (EST) From: Bruce Evans X-X-Sender: bde@besplex.bde.org To: Bruce Evans Subject: Re: misc/177624: Swapcontext can get compiled incorrectly In-Reply-To: <20130404232206.S1025@besplex.bde.org> Message-ID: <20130405011027.Y1350@besplex.bde.org> References: <201304040232.r342WFTC020054@red.freebsd.org> <20130404232206.S1025@besplex.bde.org> MIME-Version: 1.0 Content-Type: MULTIPART/MIXED; BOUNDARY="0-1588918552-1365088562=:1350" X-Optus-CM-Score: 0 X-Optus-CM-Analysis: v=2.0 cv=HfxM1V48 c=1 sm=1 a=HSHldBqzbsoA:10 a=PO7r1zJSAAAA:8 a=JzwRw_2MAAAA:8 a=cK7K0dqV01sA:10 a=7JrwyhdqLwUuy0H6cxwA:9 a=45ClL6m2LaAA:10 a=TEtd8y5WR3g2ypngnwZWYw==:117 Cc: freebsd-gnats-submit@freebsd.org, freebsd-bugs@freebsd.org, Brian Demsky X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 04 Apr 2013 15:16:08 -0000 This message is in MIME format. The first part should be readable text, while the remaining parts are likely unreadable without MIME-aware tools. --0-1588918552-1365088562=:1350 Content-Type: TEXT/PLAIN; charset=X-UNKNOWN; format=flowed Content-Transfer-Encoding: QUOTED-PRINTABLE On Fri, 5 Apr 2013, Bruce Evans wrote: > On Thu, 4 Apr 2013, Brian Demsky wrote: > >>> Description: >> Here is the code for swap context: >>=20 >> int >> swapcontext(ucontext_t *oucp, const ucontext_t *ucp) >> { >> int ret; >>=20 >> if ((oucp =3D=3D NULL) || (ucp =3D=3D NULL)) { >> errno =3D EINVAL; >> return (-1); >> } >> oucp->uc_flags &=3D ~UCF_SWAPPED; >> ret =3D getcontext(oucp); >> if ((ret =3D=3D 0) && !(oucp->uc_flags & UCF_SWAPPED)) { >> oucp->uc_flags |=3D UCF_SWAPPED; >> ret =3D setcontext(ucp); >> } >> return (ret); >> } > >> On the OS X port of libc in Mac OSX 10.7.5, this gets compiled as: > >> ... >> 0x00007fff901e870b : pop %rbx >> 0x00007fff901e870c : pop %r14 >> 0x00007fff901e870e : jmpq 0x7fff90262855 >>=20 >> The problem is that rbx is callee saved by compiled version of swapconte= xt=20 >> and then reused before getcontext is called. Getcontext then stores the= =20 >> wrong value for rbx and setcontext later restores the wrong value for rb= x.=20 >> If the caller had any value in rbx, it has been trashed at this point. > > Later you wrote: > >> The analysis is a little wrong about the problem. Ultimately, the tail= =20 >> call to set context trashes the copies of bx and r14 on the stack=85. > > The bug seems to be in setcontext(). It must preserve the callee-saved > registers, not restore them. This would happen automatically if more > were written in C. But setcontext() can't be written entirely in C, > since it must save all callee-saved registers including ones not used > and therefore not normally saved by any C function that it might be in, > and possibly also including callee-saved registers for nonstandard or > non-C ABIs. In FreeBSD, it is apparently always a syscall. This is more than a little wrong. When setcontext() succeeds, it doesn't return here. Then it acts like longjmp() and must restore all the callee-saved to whatever they were when getcontext() was called. Otherwise, it must not clobber any callee-saved registers (then it differs from longjmp(). longjmp() just can't fail). Now I don't see any bug here. If the saved state is returned to, then it is as if getcontext() returned, and the intermediately-saved %rbx is correct (we will restore the orginal %rbx if we return). If setcontext() fails, then it should preserve all callee-saved registers. In the tail-call case, we have already restored the orginal %rbx and the failing setcontext() should preserve that. Bruce --0-1588918552-1365088562=:1350--