[-- Attachment #1: Type: text/plain, Size: 3671 bytes --] Hi Everyone, I'm building Guile 3.0.5 on OS X 11.2.3. It looks like Guile is having some trouble: libtool: link: /usr/bin/clang -std=gnu11 -I/usr/local/include -D_THREAD_SAFE -Wall -Wmissing-prototypes -Wpointer-arith -fno-strict-aliasing -fwrapv -fvisibility=hidden -I/usr/local/include -g2 -O2 -fno-common -arch arm64 -fPIC -pthread -I/usr/local/include -D_THREAD_SAFE -Wl,-rpath -Wl,@loader_path/../lib -Wl,-rpath -Wl,/usr/local/lib -o .libs/guile guile-guile.o -L/usr/local/lib ./.libs/libguile-3.0.dylib /usr/local/lib/libgc.dylib /usr/local/lib/libffi.dylib /usr/local/lib/libintl.dylib /usr/local/lib/libunistring.dylib /usr/local/lib/libiconv.dylib /usr/local/lib/libgmp.dylib /usr/local/lib/libltdl.dylib -ldl -lpthread -pthread cat alist.doc array-handle.doc array-map.doc arrays.doc async.doc atomic.doc backtrace.doc boolean.doc bitvectors.doc bytevectors.doc chars.doc control.doc continuations.doc debug.doc deprecated.doc deprecation.doc dynl.doc dynwind.doc eq.doc error.doc eval.doc evalext.doc exceptions.doc expand.doc extensions.doc fdes-finalizers.doc feature.doc filesys.doc fluids.doc foreign.doc fports.doc gc-malloc.doc gc.doc gettext.doc generalized-arrays.doc generalized-vectors.doc goops.doc gsubr.doc guardians.doc hash.doc hashtab.doc hooks.doc i18n.doc init.doc ioext.doc keywords.doc list.doc load.doc macros.doc mallocs.doc memoize.doc modules.doc numbers.doc objprop.doc options.doc pairs.doc ports.doc print.doc procprop.doc procs.doc promises.doc r6rs-ports.doc random.doc rdelim.doc read.doc rw.doc scmsigs.doc script.doc simpos.doc smob.doc sort.doc srcprop.doc srfi-1.doc srfi-4.doc srfi-13.doc srfi-14.doc srfi-60.doc stackchk.doc stacks.doc stime.doc strings.doc strorder.doc strports.doc struct.doc symbols.doc syntax.doc threads.doc throw.doc unicode.doc uniform.doc values.doc variable.doc vectors.doc version.doc vports.doc weak-set.doc weak-table.doc weak-vector.doc dynl.doc posix.doc net_db.doc socket.doc regex-posix.doc | GUILE_AUTO_COMPILE=0 ../meta/build-env guild snarf-check-and-output-texi > guile-procedures.texi || { rm guile-procedures.texi; false; } allocating JIT code buffer failed: Permission denied jit.c:5804: fatal: assertion failed /bin/sh: line 1: 58915 Broken pipe: 13 cat alist.doc array-handle.doc array-map.doc arrays.doc async.doc atomic.doc backtrace.doc boolean.doc bitvectors.doc bytevectors.doc chars.doc control.doc continuations.doc debug.doc deprecated.doc deprecation.doc dynl.doc dynwind.doc eq.doc error.doc eval.doc evalext.doc exceptions.doc expand.doc extensions.doc fdes-finalizers.doc feature.doc filesys.doc fluids.doc foreign.doc fports.doc gc-malloc.doc gc.doc gettext.doc generalized-arrays.doc generalized-vectors.doc goops.doc gsubr.doc guardians.doc hash.doc hashtab.doc hooks.doc i18n.doc init.doc ioext.doc keywords.doc list.doc load.doc macros.doc mallocs.doc memoize.doc modules.doc numbers.doc objprop.doc options.doc pairs.doc ports.doc print.doc procprop.doc procs.doc promises.doc r6rs-ports.doc random.doc rdelim.doc read.doc rw.doc scmsigs.doc script.doc simpos.doc smob.doc sort.doc srcprop.doc srfi-1.doc srfi-4.doc srfi-13.doc srfi-14.doc srfi-60.doc stackchk.doc stacks.doc stime.doc strings.doc strorder.doc strports.doc struct.doc symbols.doc syntax.doc threads.doc throw.doc unicode.doc uniform.doc values.doc variable.doc vectors.doc version.doc vports.doc weak-set.doc weak-table.doc weak-vector.doc dynl.doc posix.doc net_db.doc socket.doc regex-posix.doc 58916 Abort trap: 6 | GUILE_AUTO_COMPILE=0 ../meta/build-env guild snarf-check-and-output-texi > guile-procedures.texi gmake[3]: *** [guile-procedures.texi] Error 1 [-- Attachment #2: guile3-config.log.zip --] [-- Type: application/zip, Size: 112505 bytes --]
I'm looking at OS X's man page on mmap. The EACCES does not seem to fit one of the stated reasons in the man page. Also see https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/mmap.2.html. I have two theories, both of which are guesses. Neither seems to be very good. First, this may be related to W^X pages on OS X. Second, the size is 0 but the wrong error code is returned. For the second case, size=0 should result in EINVAL. I don't know what size is so this is probably a bad guess. I'm not sure how to get this under a debugger. Here's a test of the first theory: % cat mmap-test.c #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <sys/mman.h> int main(int argc, char* argv[]) { size_t len = 10; int prot = PROT_EXEC | PROT_READ | PROT_WRITE; int flags = MAP_PRIVATE | MAP_ANONYMOUS; void *p = mmap (NULL, len, prot, flags, -1, 0); int err = errno; if (p) { printf("p is good\n"); munmap(p, len); } else { printf("p is bad (%d)\n", err); } return 0; } % clang -Wall mmap-test.c -o mmap-test.exe % ./mmap-test.exe p is good Here's a test of the second theory with len = 0: % ./mmap-test.exe p is good I'm out of ideas... ========================= This is the relevant part of libguile/jit.c: 1330 static struct code_arena * 1331 allocate_code_arena (size_t size, struct code_arena *prev) 1332 { 1333 struct code_arena *ret = malloc (sizeof (struct code_arena)); 1334 1335 if (!ret) return NULL; 1336 1337 memset (ret, 0, sizeof (*ret)); 1338 ret->used = 0; 1339 ret->size = size; 1340 ret->prev = prev; 1341 ret->base = mmap (NULL, ret->size, 1342 PROT_EXEC | PROT_READ | PROT_WRITE, 1343 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 1344 1345 if (ret->base == MAP_FAILED) 1346 { 1347 perror ("allocating JIT code buffer failed"); 1348 free (ret); 1349 return NULL; 1350 } 1351 1352 INFO ("allocated code arena, %p-%p\n", ret->base, ret->base + ret->size); 1353 1354 return ret; 1355 }
Dammit, check for the proper return value... % cat mmap-test.c #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <sys/mman.h> int main(int argc, char* argv[]) { size_t len = 10; int prot = PROT_EXEC | PROT_READ | PROT_WRITE; int flags = MAP_PRIVATE | MAP_ANONYMOUS; void *p = mmap (NULL, len, prot, flags, -1, 0); int err = errno; if (p != (void*) -1) { printf("p is good\n"); munmap(p, len); } else { printf("p is bad (%d)\n", err); } return 0; } % clang -Wall mmap-test.c -o mmap-test.exe % ./mmap-test.exe p is bad (13) That is the permission denied. Next, avoid W+X: % cat mmap-test.c #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <sys/mman.h> int main(int argc, char* argv[]) { size_t len = 10; int prot = /*PROT_EXEC |*/ PROT_READ | PROT_WRITE; int flags = MAP_PRIVATE | MAP_ANONYMOUS; void *p = mmap (NULL, len, prot, flags, -1, 0); int err = errno; if (p != (void*) -1) { printf("p is good\n"); munmap(p, len); } else { printf("p is bad (%d)\n", err); } return 0; } It looks like W^X is the culprit. Jeff
This looks like the Apple article of interest: https://developer.apple.com/documentation/apple-silicon/porting-just-in-time-compilers-to-apple-silicon. According to the article, the page should be mapped with MAP_JIT. Before instructions are written, pthread_jit_write_protect_np should be called. After writing the jitted code, call pthread_jit_write_protect_np again and call sys_icache_invalidate. It looks like the OpenJDK folks are also experiencing similar issues. Jeff
The GUILE_ENABLE_JIT m4 macro should _not_enable JIT on the Apple silicon. That's going to take a real port. This may help in detecting the M1 as long as build==host. apple_silicon=`sysctl machdep.cpu.brand_string 2>/dev/null | grep -i -c "Apple M1"` If a cross-compile is happening, then TARGET_OSX and MAP_JIT macros may help. Jeff