|
| 1 | +# About |
| 2 | + |
| 3 | +This contains a non-exhaustive list of changes that we had to make to be able to build the PHP codebase for wasm32-wasi. |
| 4 | + |
| 5 | +To remove or add code for wasm32-wasi builds we are using the 'WASM_WASI' macro. |
| 6 | + |
| 7 | +# Emulated functionality |
| 8 | + |
| 9 | +We are using emulation of getpid, signals and clocks. |
| 10 | + |
| 11 | +We are not using mman emulation due to the reasons outlined [below](#mmap-support). |
| 12 | + |
| 13 | +# Excluded code |
| 14 | + |
| 15 | +This describes the most common places where we needed to exclude code because |
| 16 | +a method or constant is not available or is somehow different with WASI. |
| 17 | + |
| 18 | +## S_IFSOCK is the same as S_IFIFO |
| 19 | + |
| 20 | +WASI snapshot2 is not out yet - https://github.com/nodejs/uvwasi/issues/59. |
| 21 | + |
| 22 | +Thus there is no support for a FIFO filetype. So the two constants were |
| 23 | +defined to the same value. Because of this a switch/case on file type will fail |
| 24 | +due to duplicate case labels. |
| 25 | + |
| 26 | +We've commented out the S_IFIFO cases. |
| 27 | + |
| 28 | +## setjmp and longjmp |
| 29 | + |
| 30 | +There is no such support in WASI yet. |
| 31 | + |
| 32 | +We have taken a shortcut and just botched the exception handling in the zend |
| 33 | +engine. The program will just ignore certain exceptions at the PHP engine level |
| 34 | +(exceptions raised from within PHP scripts work). |
| 35 | + |
| 36 | +## sqlite3 support |
| 37 | + |
| 38 | +We are using sqlite 3.39.2 instead of the original 3.28.0 that goes with php 7.3.33. |
| 39 | + |
| 40 | +Additionally sqlite3 had to be modified in some ways for WASM_WASI builds: |
| 41 | + |
| 42 | + - mark fchmod, fchown as not defined |
| 43 | + - use "dotlockIoFinder" for file locking |
| 44 | + - skip sqlite3_finalize |
| 45 | + |
| 46 | +## Unsupported posix methods |
| 47 | + |
| 48 | +We have stubbed the posix methods in `ext/posix/posix.c` which are not supported for WASI. |
| 49 | + |
| 50 | +Other methods, which are direcly used without wrapping were skipped in place by stubbing |
| 51 | +the method that is calling them. |
| 52 | + |
| 53 | +## php flock |
| 54 | + |
| 55 | +File locking is also stubbed and always returns success. |
| 56 | + |
| 57 | +## mmap support |
| 58 | + |
| 59 | +**TL;DR:** |
| 60 | + |
| 61 | +We are building without MMAP support. To make it work, changes had to be made to zend_alloc.c resulting in a slower but correct behavior. |
| 62 | + |
| 63 | + |
| 64 | +**Details:** |
| 65 | + |
| 66 | +Take a look [here](https://linux.die.net/man/2/mmap) for the docs for mmap and munmap |
| 67 | + |
| 68 | +The mmap support in wasi-libc is just a rudimentary emulation (as of the wasi-sdk-16 tag). |
| 69 | + |
| 70 | + - mmap uses malloc to reserve the necessary amount of memory (always ignoring the addr hint) |
| 71 | + - mmap zeroes out bytes if MAP_ANONYMOUS is used |
| 72 | + - mmap reads file contents if mapping an fd |
| 73 | + - munmap only supports unmapping of the exact same chunk (addr + size) that was previously mapped - as it is effectively a free of the malloc-ed memory |
| 74 | + |
| 75 | +In the php code there are two places where mman.h is used |
| 76 | + |
| 77 | +1. In zend_alloc.c - for custom memory allocation |
| 78 | + |
| 79 | + - there is code that relies on partial munmap (for the sake of proper alignment at higher level). Using the emulated mmap will lead to leaks here, as munmap fails. |
| 80 | + - there is code that relies on the capability to extend a mmaped chunk - this will fail and lead to performance degradation (falling-back to reallocation) |
| 81 | + |
| 82 | +2. In plain_wrapper.c and zend_stream.c - for reading of the interpreted .php source files |
| 83 | + |
| 84 | + - the tricky thing here is the ZEND_MMAP_AHEAD needed by the zend_language_scanner. The language parser depends on having a bunch of null-terminating characters at the end of the interpreted string. The usual mmap behavior guarantees that when files are mmaped memory is reserved in pages of size `sysconf(_SC_PAGE_SIZE)`, which is padded with `\0`-s after the file contents. However, the emulated mmap does not do that (as it only malloc-s what was requested). This leads to the parser reading random stuff from memory after the mmaped file contents. |
| 85 | + |
| 86 | + |
0 commit comments