Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit fafdeef

Browse files
ereslibreassambar
andcommitted
Add support for building to the wasm32-wasi target
This change performs initial adaptations allowing the PHP interpreter to be compiled for the wasm32-wasi target. Challenges found: - `setjmp`/`longjmp` not available in this platform: can be worked around by using Asyncify; this is work in progress to be presented at a later stage. - Processes: WebAssembly has no concept of processes, so many process-related operations had to be emulated, or are no-ops. `getpid` and clocks are emulated. Signal handling has minimal emulation. `uid`, `gid`, and related concepts that do not map well to a WebAssembly sandbox are also removed. - `mmap` implementation is a minimal emulation that allows to allocate memory or map file contents to it. - Filesystem: many filesystem operations cannot be mapped to WASI, and so these operations are no-ops. - `S_IFSOCK` matches `S_IFIFO` in current `wasi-libc`; removed the `S_IFIFO` case, because `clang` will fail building due to a duplicated constant in `switch` statements. - File locks are also stubbed and always return success. - Networking: given the WebAssembly sandbox and capability-based security, it is not possible to open a socket as of today. Although the host is able to open a socket and forward a file descriptor, leaving the `accept()` syscall to the WebAssembly module, we have removed networking syscalls at this time. The only binary that builds with this change is `php-cgi` at this time. It's possible to adapt the change so that `php` builds and is able to run scripts and programs in the filesystem in a CLI fashion. However, starting a PHP server to listen on a socket using the CLI is a more contrived situation, given it's not possible to open a listening socket from within the sandbox; however it would be possible to create the socket on the host side, and forward the file descriptor to the module. Co-Authored-By: Asen Alexandrov <alexandrov@vmware.com>
1 parent 48db342 commit fafdeef

36 files changed

+358
-32
lines changed

‎Zend/zend.c‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -834,7 +834,9 @@ static void executor_globals_ctor(zend_executor_globals *executor_globals) /* {{
834834
#endif
835835
executor_globals->saved_fpu_cw_ptr = NULL;
836836
executor_globals->active = 0;
837+
#ifndef __wasi__
837838
executor_globals->bailout = NULL;
839+
#endif // __wasi__
838840
executor_globals->error_handling = EH_NORMAL;
839841
executor_globals->exception_class = NULL;
840842
executor_globals->exception = NULL;
@@ -1223,6 +1225,7 @@ ZEND_COLD void zenderror(const char *error) /* {{{ */
12231225
ZEND_API ZEND_COLD ZEND_NORETURN void _zend_bailout(const char *filename, uint32_t lineno) /* {{{ */
12241226
{
12251227

1228+
#ifndef __wasi__
12261229
if (!EG(bailout)) {
12271230
zend_output_debug_string(1, "%s(%d) : Bailed out without a bailout address!", filename, lineno);
12281231
exit(-1);
@@ -1233,6 +1236,7 @@ ZEND_API ZEND_COLD ZEND_NORETURN void _zend_bailout(const char *filename, uint32
12331236
CG(in_compilation) = 0;
12341237
EG(current_execute_data) = NULL;
12351238
LONGJMP(*EG(bailout), FAILURE);
1239+
#endif // __wasi__
12361240
}
12371241
/* }}} */
12381242

‎Zend/zend.h‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,7 @@ typedef size_t (*zend_write_func_t)(const char *str, size_t str_length);
256256

257257
#define zend_bailout() _zend_bailout(__FILE__, __LINE__)
258258

259+
#ifndef __wasi__
259260
#define zend_try \
260261
{ \
261262
JMP_BUF *__orig_bailout = EG(bailout); \
@@ -272,6 +273,19 @@ typedef size_t (*zend_write_func_t)(const char *str, size_t str_length);
272273
}
273274
#define zend_first_try EG(bailout)=NULL; zend_try
274275

276+
#else // __wasi__
277+
#define zend_try \
278+
{ \
279+
if (1) {
280+
#define zend_catch \
281+
} else {
282+
#define zend_end_try() \
283+
} \
284+
}
285+
#define zend_first_try zend_try
286+
#endif // __wasi__
287+
288+
275289
BEGIN_EXTERN_C()
276290
void zend_startup(zend_utility_functions *utility_functions);
277291
void zend_shutdown(void);

‎Zend/zend_alloc.c‎

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@
8080
#include <fcntl.h>
8181
#include <errno.h>
8282

83-
#ifndef_WIN32
83+
#if !defined(_WIN32) &&HAVE_MMAP
8484
# include <sys/mman.h>
8585
# ifndef MAP_ANON
8686
# ifdef MAP_ANONYMOUS
@@ -445,6 +445,8 @@ static void zend_mm_munmap(void *addr, size_t size)
445445
#endif
446446
}
447447
}
448+
#elif ! HAVE_MMAP
449+
free(addr);
448450
#else
449451
if (munmap(addr, size) != 0) {
450452
#if ZEND_MM_ERROR
@@ -472,6 +474,8 @@ static void *zend_mm_mmap_fixed(void *addr, size_t size)
472474
}
473475
ZEND_ASSERT(ptr == addr);
474476
return ptr;
477+
#elif ! HAVE_MMAP
478+
return NULL;
475479
#else
476480
int flags = MAP_PRIVATE | MAP_ANON;
477481
#if defined(MAP_EXCL)
@@ -508,6 +512,10 @@ static void *zend_mm_mmap(size_t size)
508512
return NULL;
509513
}
510514
return ptr;
515+
#elif ! HAVE_MMAP
516+
void* ptr = malloc(size);
517+
memset(ptr, 0, size);
518+
return ptr;
511519
#else
512520
void *ptr;
513521

@@ -717,6 +725,11 @@ static zend_always_inline void zend_mm_hugepage(void* ptr, size_t size)
717725

718726
static void *zend_mm_chunk_alloc_int(size_t size, size_t alignment)
719727
{
728+
#if ! HAVE_MMAP
729+
void* ptr = aligned_alloc(alignment, size);
730+
memset(ptr, 0, size);
731+
return ptr;
732+
#else
720733
void *ptr = zend_mm_mmap(size);
721734

722735
if (ptr == NULL) {
@@ -767,6 +780,7 @@ static void *zend_mm_chunk_alloc_int(size_t size, size_t alignment)
767780
#endif
768781
return ptr;
769782
}
783+
#endif
770784
}
771785

772786
static void *zend_mm_chunk_alloc(zend_mm_heap *heap, size_t size, size_t alignment)
@@ -2932,7 +2946,7 @@ ZEND_API void start_memory_manager(void)
29322946
#else
29332947
alloc_globals_ctor(&alloc_globals);
29342948
#endif
2935-
#ifndef_WIN32
2949+
#if !defined(_WIN32) &&HAVE_MMAP
29362950
# if defined(_SC_PAGESIZE)
29372951
REAL_PAGE_SIZE = sysconf(_SC_PAGESIZE);
29382952
# elif defined(_SC_PAGE_SIZE)

‎Zend/zend_fibers.c‎

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
# include <ucontext.h>
4040
#endif
4141

42-
#ifndefZEND_WIN32
42+
#if !defined(ZEND_WIN32) &&HAVE_MMAP
4343
# include <unistd.h>
4444
# include <sys/mman.h>
4545
# include <limits.h>
@@ -108,7 +108,9 @@ typedef struct _zend_fiber_vm_state {
108108
zend_execute_data *current_execute_data;
109109
int error_reporting;
110110
uint32_t jit_trace_num;
111+
#ifndef __wasi__
111112
JMP_BUF *bailout;
113+
#endif // __wasi__
112114
zend_fiber *active_fiber;
113115
#ifdef ZEND_CHECK_STACK_LIMIT
114116
void *stack_base;
@@ -125,7 +127,9 @@ static zend_always_inline void zend_fiber_capture_vm_state(zend_fiber_vm_state *
125127
state->current_execute_data = EG(current_execute_data);
126128
state->error_reporting = EG(error_reporting);
127129
state->jit_trace_num = EG(jit_trace_num);
130+
#ifndef __wasi__
128131
state->bailout = EG(bailout);
132+
#endif // __wasi__
129133
state->active_fiber = EG(active_fiber);
130134
#ifdef ZEND_CHECK_STACK_LIMIT
131135
state->stack_base = EG(stack_base);
@@ -142,7 +146,9 @@ static zend_always_inline void zend_fiber_restore_vm_state(zend_fiber_vm_state *
142146
EG(current_execute_data) = state->current_execute_data;
143147
EG(error_reporting) = state->error_reporting;
144148
EG(jit_trace_num) = state->jit_trace_num;
149+
#ifndef __wasi__
145150
EG(bailout) = state->bailout;
151+
#endif // __wasi__
146152
EG(active_fiber) = state->active_fiber;
147153
#ifdef ZEND_CHECK_STACK_LIMIT
148154
EG(stack_base) = state->stack_base;
@@ -236,6 +242,8 @@ static zend_fiber_stack *zend_fiber_stack_allocate(size_t size)
236242
return NULL;
237243
}
238244
# endif
245+
#elif defined __wasi__
246+
pointer = malloc(alloc_size);
239247
#else
240248
pointer = mmap(NULL, alloc_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
241249

@@ -302,6 +310,8 @@ static void zend_fiber_stack_free(zend_fiber_stack *stack)
302310

303311
#ifdef ZEND_WIN32
304312
VirtualFree(pointer, 0, MEM_RELEASE);
313+
#elif defined __wasi__
314+
free(pointer);
305315
#else
306316
munmap(pointer, stack->size + ZEND_FIBER_GUARD_PAGES * page_size);
307317
#endif
@@ -415,7 +425,7 @@ ZEND_API bool zend_fiber_init_context(zend_fiber_context *context, void *kind, z
415425
makecontext(handle, (void (*)(void)) zend_fiber_trampoline, 0);
416426

417427
context->handle = handle;
418-
#else
428+
#elif !defined(__wasi__)
419429
// Stack grows down, calculate the top of the stack. make_fcontext then shifts pointer to lower 16-byte boundary.
420430
void *stack = (void *) ((uintptr_t) context->stack->pointer + context->stack->size);
421431

@@ -428,6 +438,8 @@ ZEND_API bool zend_fiber_init_context(zend_fiber_context *context, void *kind, z
428438

429439
context->handle = make_fcontext(stack, context->stack->size, zend_fiber_trampoline);
430440
ZEND_ASSERT(context->handle != NULL && "make_fcontext() never returns NULL");
441+
#else
442+
return false;
431443
#endif
432444

433445
context->kind = kind;
@@ -502,16 +514,18 @@ ZEND_API void zend_fiber_switch_context(zend_fiber_transfer *transfer)
502514

503515
/* Copy transfer struct because it might live on the other fiber's stack that will eventually be destroyed. */
504516
*transfer = *transfer_data;
505-
#else
517+
#elif !defined(__wasi__)
506518
boost_context_data data = jump_fcontext(to->handle, transfer);
507519

508520
/* Copy transfer struct because it might live on the other fiber's stack that will eventually be destroyed. */
509521
*transfer = *data.transfer;
522+
#else
523+
return;
510524
#endif
511525

512526
to = transfer->context;
513527

514-
#ifndefZEND_FIBER_UCONTEXT
528+
#if !defined(ZEND_FIBER_UCONTEXT) && !defined(__wasi__)
515529
/* Get the context that resumed us and update its handle to allow for symmetric coroutines. */
516530
to->handle = data.handle;
517531
#endif

‎Zend/zend_globals.h‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@
2121
#define ZEND_GLOBALS_H
2222

2323

24+
#ifndef __wasi__
2425
#include <setjmp.h>
26+
#endif
2527

2628
#include "zend_globals_macros.h"
2729

@@ -162,7 +164,9 @@ struct _zend_executor_globals {
162164

163165
HashTable included_files; /* files already included */
164166

167+
#ifndef __wasi__
165168
JMP_BUF *bailout;
169+
#endif
166170

167171
int error_reporting;
168172
int exit_status;

‎Zend/zend_types.h‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1453,5 +1453,15 @@ static zend_always_inline uint32_t zval_delref_p(zval* pz) {
14531453
#define ZVAL_COPY_OR_DUP_PROP(z, v) \
14541454
do { ZVAL_COPY_OR_DUP(z, v); Z_PROP_FLAG_P(z) = Z_PROP_FLAG_P(v); } while (0)
14551455

1456+
#ifdef __wasi__
1457+
#define LOG_EMERG 0 /* system is unusable */
1458+
#define LOG_ALERT 1 /* action must be taken immediately */
1459+
#define LOG_CRIT 2 /* critical conditions */
1460+
#define LOG_ERR 3 /* error conditions */
1461+
#define LOG_WARNING 4 /* warning conditions */
1462+
#define LOG_NOTICE 5 /* normal but significant condition */
1463+
#define LOG_INFO 6 /* informational */
1464+
#define LOG_DEBUG 7 /* debug-level messages */
1465+
#endif // __wasi__
14561466

14571467
#endif /* ZEND_TYPES_H */

‎Zend/zend_virtual_cwd.c‎

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1400,6 +1400,8 @@ CWD_API int virtual_chmod(const char *filename, mode_t mode) /* {{{ */
14001400
}
14011401
ret = php_win32_ioutil_chmod(new_state.cwd, mode);
14021402
}
1403+
#elif defined __wasi__
1404+
ret = 0;
14031405
#else
14041406
ret = chmod(new_state.cwd, mode);
14051407
#endif
@@ -1428,7 +1430,11 @@ CWD_API int virtual_chown(const char *filename, uid_t owner, gid_t group, int li
14281430
ret = -1;
14291431
#endif
14301432
} else {
1433+
#ifndef __wasi__
14311434
ret = chown(new_state.cwd, owner, group);
1435+
#else
1436+
ret = 0;
1437+
#endif // __wasi__
14321438
}
14331439

14341440
CWD_STATE_FREE_ERR(&new_state);
@@ -1706,8 +1712,11 @@ CWD_API FILE *virtual_popen(const char *command, const char *type) /* {{{ */
17061712
*ptr++ = ' ';
17071713

17081714
memcpy(ptr, command, command_length+1);
1715+
#ifndef __wasi__
17091716
retval = popen(command_line, type);
1710-
1717+
#else
1718+
retval = 0;
1719+
#endif // __wasi__
17111720
efree(command_line);
17121721
return retval;
17131722
}

‎configure.ac‎

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,9 @@ label2:
199199
fi
200200
PHP_SUBST(RE2C_FLAGS)
201201

202+
dnl Check if __wasi__ is defined by the compiler
203+
AC_CHECK_DECLS([__wasi__])
204+
202205
dnl Platform-specific compile settings.
203206
dnl ----------------------------------------------------------------------------
204207

@@ -1334,11 +1337,13 @@ else
13341337
if test "$fiber_os" = 'mac'; then
13351338
AC_DEFINE([_XOPEN_SOURCE], 1, [ ])
13361339
fi
1337-
AC_CHECK_HEADER(ucontext.h, [
1338-
AC_DEFINE([ZEND_FIBER_UCONTEXT], 1, [ ])
1339-
], [
1340-
AC_MSG_ERROR([fibers not available on this platform])
1341-
])
1340+
if test "$ac_cv_have_decl___wasi__" != "yes"; then
1341+
AC_CHECK_HEADER(ucontext.h, [
1342+
AC_DEFINE([ZEND_FIBER_UCONTEXT], 1, [ ])
1343+
], [
1344+
AC_MSG_ERROR([fibers not available on this platform])
1345+
])
1346+
fi
13421347
fi
13431348

13441349
LIBZEND_BASIC_CHECKS

‎ext/fileinfo/libmagic/fsmagic.c‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ file_fsmagic(struct magic_set *ms, const char *fn, zend_stat_t *sb)
167167
# endif
168168
#endif
169169

170+
#ifndef __wasi__
170171
#ifdef S_IFIFO
171172
case S_IFIFO:
172173
if((ms->flags & MAGIC_DEVICES) != 0)
@@ -179,6 +180,7 @@ file_fsmagic(struct magic_set *ms, const char *fn, zend_stat_t *sb)
179180
return -1;
180181
break;
181182
#endif
183+
#endif // __wasi__
182184
#ifdef S_IFDOOR
183185
case S_IFDOOR:
184186
if (mime) {

‎ext/pdo_sqlite/sqlite_statement.c‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@ static int pdo_sqlite_stmt_dtor(pdo_stmt_t *stmt)
3232
pdo_sqlite_stmt *S = (pdo_sqlite_stmt*)stmt->driver_data;
3333

3434
if (S->stmt) {
35+
#ifndef __wasi__
3536
sqlite3_finalize(S->stmt);
37+
#endif
3638
S->stmt = NULL;
3739
}
3840
efree(S);

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /