Hi Ports, Armin,

This diff makes PyPy build on OpenBSD once more, and in doing so updates
to the latest version.

I only started out to mark PyPy wxneeded, but it led to an odd situation
with PyPy:

 * The bootstrap tarball no longer works, since the contained binary is
   not marked wxneeded, so we have to make a new bootstrap using
   CPython.

 * However, the build system itself (under CPython) is not W^X compliant
   either. 

The diff makes the PyPy build work under CPython without requiring
CPython itself to be marked wxneeded (although I see another thread
where people are discussing marking CPython anyway). It also marks the
PyPy binary wxneeded. Since we have to have a new bootstrap, I figured I
may aswell update PyPy to the latest version too.

Armin, this is a minimal distribution patch that I am going to use for
now until we can figure out this rmmap refactoring. It simply duplicates 
alloc_hinted thus avoiding the NonConstant problem. I'm still working on
the correct refactoring separately.

People, note that this does not make the PyPy JIT W^X compatible.
Although I hope we can be there eventually, apparently this will not be
a trivial task (it's going to be hard to know all the places where we
need to flip the page protection flags, and when we get it wrong and get
a crash, it's going to be hard to know where the crash came from).

Anyway, this is the first step. OK anyone?

Bootstrap tarball is here (please could you host this Stuart?):
http://theunixzoo.co.uk/random/pypy-bootstrap-amd64-5.3.1.tar.xz


Index: Makefile
===================================================================
RCS file: /cvs/ports/lang/pypy/Makefile,v
retrieving revision 1.24
diff -u -p -r1.24 Makefile
--- Makefile    13 Jun 2016 08:44:17 -0000      1.24
+++ Makefile    11 Aug 2016 20:19:10 -0000
@@ -18,7 +18,7 @@ COMMENT =             fast implementation of the Py
 # You can use the no_bootstrap FLAVOR to make a new bootstrap. This uses
 # CPython to build PyPy instead. Note this is slower.
 
-V =                    5.3.0
+V =                    5.3.1
 BOOTSTRAP_V =          ${V}
 DISTNAME =             pypy2-v${V}-src
 PKGNAME =              pypy-${V}
@@ -95,7 +95,8 @@ do-build:
          pypy --jit loop_longevity=300 \
          ../../rpython/bin/rpython --source --opt=jit
 .endif
-       cd ${WRKDIR}/usession/testing_1 && ${SETENV} ${MAKE_ENV} ${MAKE_PROGRAM}
+       cd ${WRKDIR}/usession/testing_1 && ${SETENV} ${MAKE_ENV} \
+               ${MAKE_PROGRAM} LDFLAGS_LINK="-Wl,-z,wxneeded -pthread"
 
 PYPY_INST_LIB_DIR = ${PREFIX}/pypy/lib
 PYPY_LD_LIBRARY_PATH = LD_LIBRARY_PATH=${PYPY_INST_LIB_DIR}
Index: distinfo
===================================================================
RCS file: /cvs/ports/lang/pypy/distinfo,v
retrieving revision 1.16
diff -u -p -r1.16 distinfo
--- distinfo    13 Jun 2016 08:44:17 -0000      1.16
+++ distinfo    11 Aug 2016 20:19:10 -0000
@@ -1,4 +1,4 @@
-SHA256 (pypy/pypy-bootstrap-amd64-5.3.0.tar.xz) = 
edy2uGOHyc3D9NndGeSZ86szEvpiJmFSQdAC/wtLBpg=
-SHA256 (pypy/pypy2-v5.3.0-src.tar.bz2) = 
QULrj0A4ELyIpJEXkrtaUC4VLflYBuM+aQUMgozRYNU=
-SIZE (pypy/pypy-bootstrap-amd64-5.3.0.tar.xz) = 21976516
-SIZE (pypy/pypy2-v5.3.0-src.tar.bz2) = 17361429
+SHA256 (pypy/pypy-bootstrap-amd64-5.3.1.tar.xz) = 
J8lRGufV48uBbJu302zRSAf3RdXxjEokruugShyOJ0U=
+SHA256 (pypy/pypy2-v5.3.1-src.tar.bz2) = 
MaUrq1hKvzoPDe/Rv5opEx2rCN9DiF5+7d/H3Jtxg24=
+SIZE (pypy/pypy-bootstrap-amd64-5.3.1.tar.xz) = 22269372
+SIZE (pypy/pypy2-v5.3.1-src.tar.bz2) = 17361760
Index: patches/patch-rpython_jit_backend_x86_detect_feature_py
===================================================================
RCS file: patches/patch-rpython_jit_backend_x86_detect_feature_py
diff -N patches/patch-rpython_jit_backend_x86_detect_feature_py
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ patches/patch-rpython_jit_backend_x86_detect_feature_py     11 Aug 2016 
20:19:10 -0000
@@ -0,0 +1,30 @@
+$OpenBSD$
+
+Make the CPython bootstrap W^X compatible.
+
+--- rpython/jit/backend/x86/detect_feature.py.orig     Tue Jun 14 08:46:04 2016
++++ rpython/jit/backend/x86/detect_feature.py  Thu Aug 11 08:49:22 2016
+@@ -1,17 +1,20 @@
+ import sys
+ import struct
+ from rpython.rtyper.lltypesystem import lltype, rffi
+-from rpython.rlib.rmmap import alloc, free
++from rpython.rlib.rmmap import alloc, free, set_pages_executable
+ 
++CPU_INFO_SZ = 4096
++
+ def cpu_info(instr):
+-    data = alloc(4096)
++    data = alloc(CPU_INFO_SZ, no_exec=True)
+     pos = 0
+     for c in instr:
+         data[pos] = c
+         pos += 1
+     fnptr = rffi.cast(lltype.Ptr(lltype.FuncType([], lltype.Signed)), data)
++    set_pages_executable(data, CPU_INFO_SZ)
+     code = fnptr()
+-    free(data, 4096)
++    free(data, CPU_INFO_SZ)
+     return code
+ 
+ def detect_sse2():
Index: patches/patch-rpython_rlib_rmmap_py
===================================================================
RCS file: patches/patch-rpython_rlib_rmmap_py
diff -N patches/patch-rpython_rlib_rmmap_py
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ patches/patch-rpython_rlib_rmmap_py 11 Aug 2016 20:19:10 -0000
@@ -0,0 +1,113 @@
+$OpenBSD$
+
+Make the CPython bootstrap W^X compatible.
+
+--- rpython/rlib/rmmap.py.orig Tue Jun 14 08:46:04 2016
++++ rpython/rlib/rmmap.py      Thu Aug 11 08:49:22 2016
+@@ -155,6 +155,9 @@ if _POSIX:
+         c_mremap, _ = external('mremap',
+                                [PTR, size_t, size_t, rffi.ULONG], PTR)
+ 
++    c_mprotect, _ = external('mprotect',
++                             [PTR, size_t, rffi.INT], rffi.INT)
++
+     # this one is always safe
+     _pagesize = rffi_platform.getintegerfunctionresult('getpagesize',
+                                                        includes=includes)
+@@ -694,11 +697,29 @@ if _POSIX:
+     def alloc_hinted(hintp, map_size):
+         flags = MAP_PRIVATE | MAP_ANONYMOUS
+         prot = PROT_EXEC | PROT_READ | PROT_WRITE
++
+         if we_are_translated():
+             flags = NonConstant(flags)
+             prot = NonConstant(prot)
+         return c_mmap_safe(hintp, map_size, prot, flags, -1, 0)
+ 
++    def alloc_hinted_noexec(hintp, map_size):
++        """Same as alloc_hinted, but allocates pages non-executable.
++        Duplicated because of constancy constraints on prot."""
++
++        flags = MAP_PRIVATE | MAP_ANONYMOUS
++        prot = PROT_READ | PROT_WRITE
++
++        if we_are_translated():
++            flags = NonConstant(flags)
++            prot = NonConstant(prot)
++        return c_mmap_safe(hintp, map_size, prot, flags, -1, 0)
++
++    def set_pages_executable(addr, size):
++        rv = c_mprotect(addr, size, PROT_EXEC)
++        if rv < 0:
++            debug.fatalerror_notb("set_pages_executable failed")
++
+     def clear_large_memory_chunk_aligned(addr, map_size):
+         addr = rffi.cast(PTR, addr)
+         flags = MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS
+@@ -714,10 +735,10 @@ if _POSIX:
+         pos = -0x4fff0000   # for reproducible results
+     hint = Hint()
+ 
+-    def alloc(map_size):
++    def alloc(map_size, no_exec=False):
+         """Allocate memory.  This is intended to be used by the JIT,
+-        so the memory has the executable bit set and gets allocated
+-        internally in case of a sandboxed process.
++        so the memory has the executable bit set (unless no_exec=True)
++        and gets allocated internally in case of a sandboxed process.
+         """
+         from errno import ENOMEM
+         from rpython.rlib import debug
+@@ -730,11 +751,17 @@ if _POSIX:
+             if res == rffi.cast(PTR, 0):
+                 raise MemoryError
+             return res
+-        res = alloc_hinted(rffi.cast(PTR, hint.pos), map_size)
++        if no_exec:
++            res = alloc_hinted_noexec(rffi.cast(PTR, hint.pos), map_size)
++        else:
++            res = alloc_hinted(rffi.cast(PTR, hint.pos), map_size)
+         if res == rffi.cast(PTR, -1):
+             # some systems (some versions of OS/X?) complain if they
+             # are passed a non-zero address.  Try again.
+-            res = alloc_hinted(rffi.cast(PTR, 0), map_size)
++            if no_exec:
++                res = alloc_hinted_noexec(rffi.cast(PTR, 0), map_size)
++            else:
++                res = alloc_hinted(rffi.cast(PTR, 0), map_size)
+             if res == rffi.cast(PTR, -1):
+                 # ENOMEM simply raises MemoryError, but other errors are fatal
+                 if rposix.get_saved_errno() != ENOMEM:
+@@ -748,7 +775,7 @@ if _POSIX:
+         else:
+             hint.pos += map_size
+         return res
+-    alloc._annenforceargs_ = (int,)
++    alloc._annenforceargs_ = (int, bool)
+ 
+     if _CYGWIN:
+         free = c_free_safe
+@@ -886,11 +913,13 @@ elif _MS_WINDOWS:
+     hint = Hint()
+     # XXX this has no effect on windows
+ 
+-    def alloc(map_size):
++    def alloc(map_size, no_exec=False):
+         """Allocate memory.  This is intended to be used by the JIT,
+         so the memory has the executable bit set.
+         XXX implement me: it should get allocated internally in
+         case of a sandboxed process
++
++        XXX no_exec ignored on windows.
+         """
+         null = lltype.nullptr(rffi.VOIDP.TO)
+         res = VirtualAlloc_safe(null, map_size, MEM_COMMIT | MEM_RESERVE,
+@@ -902,7 +931,7 @@ elif _MS_WINDOWS:
+         lltype.free(arg, flavor='raw')
+         # ignore errors, just try
+         return res
+-    alloc._annenforceargs_ = (int,)
++    alloc._annenforceargs_ = (int, bool)
+ 
+     def free(ptr, map_size):
+         VirtualFree_safe(ptr, 0, MEM_RELEASE)
Index: patches/patch-rpython_rlib_rvmprof_src_vmprof_config_h
===================================================================
RCS file: patches/patch-rpython_rlib_rvmprof_src_vmprof_config_h
diff -N patches/patch-rpython_rlib_rvmprof_src_vmprof_config_h
--- patches/patch-rpython_rlib_rvmprof_src_vmprof_config_h      13 Jun 2016 
08:44:17 -0000      1.2
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,18 +0,0 @@
-$OpenBSD: patch-rpython_rlib_rvmprof_src_vmprof_config_h,v 1.2 2016/06/13 
08:44:17 edd Exp $
---- rpython/rlib/rvmprof/src/vmprof_config.h.orig      Sun Jun  5 16:45:04 2016
-+++ rpython/rlib/rvmprof/src/vmprof_config.h   Sun Jun  5 16:47:15 2016
-@@ -1,10 +1,14 @@
-+#if !defined(__OpenBSD__)
- #define HAVE_SYS_UCONTEXT_H
-+#endif
- #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
-   #ifdef __i386__
-     #define PC_FROM_UCONTEXT uc_mcontext.mc_eip
-   #else
-     #define PC_FROM_UCONTEXT uc_mcontext.mc_rip
-   #endif
-+#elif defined(__OpenBSD__)
-+#define PC_FROM_UCONTEXT sc_rip
- #elif defined( __APPLE__)
-   #if ((ULONG_MAX) == (UINT_MAX))
-     #define PC_FROM_UCONTEXT uc_mcontext->__ss.__eip
Index: patches/patch-rpython_rlib_rvmprof_src_vmprof_getpc_h
===================================================================
RCS file: patches/patch-rpython_rlib_rvmprof_src_vmprof_getpc_h
diff -N patches/patch-rpython_rlib_rvmprof_src_vmprof_getpc_h
--- patches/patch-rpython_rlib_rvmprof_src_vmprof_getpc_h       13 Jun 2016 
08:44:17 -0000      1.2
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,12 +0,0 @@
-$OpenBSD: patch-rpython_rlib_rvmprof_src_vmprof_getpc_h,v 1.2 2016/06/13 
08:44:17 edd Exp $
---- rpython/rlib/rvmprof/src/vmprof_getpc.h.orig       Sun Apr 24 05:08:33 2016
-+++ rpython/rlib/rvmprof/src/vmprof_getpc.h    Sun Jun  5 16:43:26 2016
-@@ -65,6 +65,8 @@
- #elif defined(HAVE_CYGWIN_SIGNAL_H)
- #include <cygwin/signal.h>
- typedef ucontext ucontext_t;
-+#elif defined(__OpenBSD__)
-+#include <signal.h>
- #endif
- 
- 

-- 
Best Regards
Edd Barrett

http://www.theunixzoo.co.uk

Reply via email to