Sunday, August 08, 2021

Re: lang/ruby and powerpc* __builtin_setjmp

On 08/08 12:45, George Koehler wrote:
> Hello Jeremy, ports list,
>
> lang/ruby uses __builtin_setjmp and __builtin_longjmp, but these are
> broken in clang-11 on powerpc and powerpc64. I want to avoid these
> builtins and use _setjmp(3) on powerpc*, see diff below.
>
> The symptoms of the broken __builtin_setjmp are easy to miss. Our
> ruby packages for powerpc (macppc), linked by ld.bfd, seem to have
> no symptoms. If I change the linker to ld.lld, then "make build" has
> a chance to crash SIGSEGV. In lang/ruby/2.7, the crash often happened
> near the end of rdoc generation. I produced a similar SIGSEGV by
> sending SIGALRM to the Ruby code "trap(:ALRM){exit}; sleep".
>
> Yesterday (Fri), I found the problem in ruby-2.7.4/eval.c where
> rb_longjmp() uses EC_JUMP_TAG to __builtin_longjmp. In the powerpc
> ABI, each .c file has a different TOC pointer in register r30. The
> broken builtin jumps from eval.c to another .c without changing r30,
> so some code runs with the wrong r30. SIGSEGV happens if r30 + addend
> points outside of the global offset table. This depends on the
> linker; ld.lld might use larger addends than ld.bfd.
>
> In the powerpc64 ABI, every .c file in libruby should use the same
> TOC pointer, so the previous problem shouldn't happen; but something
> else must be wrong, because __builtin_setjmp causes a crash when I
> pass a wrong option, like "ruby -e" with no -e code:
>
> $ ruby27 -e
> ruby27: [BUG] Segmentation fault at 0x0000000000000018
> ruby 2.7.4p191 (2021-07-07 revision a21a3b7d23) [powerpc64-openbsd]
> ...
>
> Avoiding __builtin_setjmp prevents the crash:
>
> $ ruby27 -e
> Traceback (most recent call last):
> ruby27: no code specified for -e (RuntimeError)
>
> I long knew of this powerpc64 crash, but didn't know the cause until
> today (Sat). Jeremy, you asked me for a backtrace, but I never
> provided one. (I don't know how to backtrace through shlibs with
> devel/gdb on powerpc64.) I forgot about the crash, because I normally
> pass correct options to ruby.
>
> Upstream ruby disables __builtin_setjmp in powerpc64 Linux;
> see WRKSRC/configure.ac "# __builtin longjmp in ppc64* Linux".
>
> I have not checked with upstream llvm/clang. I neither reported a
> bug for __builtin_setjmp, nor checked whether a later version of clang
> fixes the builtin. The code for these builtins is in or near
> /usr/src/gnu/llvm/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
>
> If we disable the builtins on more archs, we might benefit from the
> xor cookie (https://u22788749.ct.sendgrid.net/ls/click?upn=yGPgKxLt0dQzFpcLvHl2PFJWR3gvLEq8GplkUr5AtZw-2B6jOCYjkAQ63Xe0VXRkaSQfX-2FVACakuwm-2F0cS3wfJrYGt7Jzb7yMlo-2FRu7kFF4bM-3Dmke-_7a8z5HXKglTa4iEppNBl7pmmyiLmNe-2BkBcvOJjbwgwTfAz6nt7aOI7zjjKB-2BE4pNq-2BetAn6OyM8pPXvRRgmEbfE7grlC3u3qrtEZs2VSJ4vNebB8MdG6zOxuUlB4MXyRPA4RVz5OzUqG51d9jpc-2FdxFZU1nHPnNlWJP6e8pxJavUPmAq7-2B9vd3CRR99NEzQ36GiMrun6c5AvAbWFg5Cg5w-3D-3D
> I didn't think to disable the builtins on not powerpc*.
>
> Is this diff ok to commit?

George,

Thank you for you detailed analysis of the problem and the proposed fix.

There have been multiple issues reported to upstream Ruby due to
builtin setjmp/longjmp on clang and on PowerPC. We might also hit
this issue on sparc64 if we switch to clang by default.

I wasn't aware the builtin setjmp/longjmp didn't use the xor cookie. I
think we would want to use the xor cookie on all arches, and therefore
it would better to disable builtin setjmp/longjmp by default on all
arches.

OK jeremy@ to commit. I'll do some testing with builtin setjmp/longjmp
disabled on amd64. If that works, we can switch to doing that by
default. If any regressions are noticed, we still have time to switch
back to only disabling the builtins on powerpc*.

Thanks,
Jeremy

>
> --George
>
> Index: Makefile.inc
> ===================================================================
> RCS file: /cvs/ports/lang/ruby/Makefile.inc,v
> retrieving revision 1.24
> diff -u -p -r1.24 Makefile.inc
> --- Makefile.inc 20 Mar 2020 16:44:24 -0000 1.24
> +++ Makefile.inc 7 Aug 2021 15:55:24 -0000
> @@ -38,6 +38,13 @@ CONFIGURE_ARGS += --enable-shared \
> --without-bundled-libffi \
> --disable-option-checking
>
> +.if ${MACHINE_ARCH} == "powerpc" || ${MACHINE_ARCH} == "powerpc64"
> +# clang-11's __builtin_setjmp is broken, has chance of SIGSEGV during
> +# "make build" on powerpc with ld.lld, or when passing a wrong option
> +# (like "ruby -e" with no -e code) on powerpc64.
> +CONFIGURE_ARGS += --with-setjmp-type=_setjmp
> +.endif
> +
> CONFIGURE_ENV += LIBruby${BINREV}_VERSION=${LIBruby${BINREV}_VERSION} \
> PREFIX="${PREFIX}" \
> CPPFLAGS="-DOPENSSL_NO_STATIC_ENGINE -I${LOCALBASE}/include" \
> Index: 2.6/Makefile
> ===================================================================
> RCS file: /cvs/ports/lang/ruby/2.6/Makefile,v
> retrieving revision 1.15
> diff -u -p -r1.15 Makefile
> --- 2.6/Makefile 9 Jul 2021 17:05:46 -0000 1.15
> +++ 2.6/Makefile 7 Aug 2021 15:55:24 -0000
> @@ -1,6 +1,7 @@
> # $OpenBSD: Makefile,v 1.15 2021/07/09 17:05:46 jeremy Exp $
>
> VERSION = 2.6.8
> +REVISION-main = 0
> DISTNAME = ruby-${VERSION}
> SHARED_LIBS = ruby26 0.0
> NEXTVER = 2.7
> Index: 2.7/Makefile
> ===================================================================
> RCS file: /cvs/ports/lang/ruby/2.7/Makefile,v
> retrieving revision 1.12
> diff -u -p -r1.12 Makefile
> --- 2.7/Makefile 9 Jul 2021 17:05:03 -0000 1.12
> +++ 2.7/Makefile 7 Aug 2021 15:55:24 -0000
> @@ -1,6 +1,7 @@
> # $OpenBSD: Makefile,v 1.12 2021/07/09 17:05:03 jeremy Exp $
>
> VERSION = 2.7.4
> +REVISION-main = 0
> DISTNAME = ruby-${VERSION}
> SHARED_LIBS = ruby27 0.0
> NEXTVER = 2.8
> Index: 3.0/Makefile
> ===================================================================
> RCS file: /cvs/ports/lang/ruby/3.0/Makefile,v
> retrieving revision 1.4
> diff -u -p -r1.4 Makefile
> --- 3.0/Makefile 9 Jul 2021 17:04:32 -0000 1.4
> +++ 3.0/Makefile 7 Aug 2021 15:55:24 -0000
> @@ -1,6 +1,7 @@
> # $OpenBSD: Makefile,v 1.4 2021/07/09 17:04:32 jeremy Exp $
>
> VERSION = 3.0.2
> +REVISION-main = 0
> DISTNAME = ruby-${VERSION}
> SHARED_LIBS = ruby30 0.0
> NEXTVER = 3.1

No comments:

Post a Comment