#include #include #include #include #include #include #include #include #include #define STUB_ABORT(function) \ int __unsup_##function(void) __asm__(#function) __attribute__((noreturn)); \ int __unsup_##function(void) \ { \ printf("STUB: abort: %s() called\n", #function); \ abort(); \ } /* * Warnings are deliberately disabled here to reduce unnecessary verbosity under * normal operation. To enable, replace "called = 1" with "called = 0" and * rebuild. */ #define STUB_WARN_ONCE(type, function, ret) \ type __unsup_##function(void) __asm__(#function); \ type __unsup_##function(void) \ { \ static int called = 1; \ if (!called) {\ printf("STUB: %s() called\n", #function); \ called = 1; \ } \ errno = ENOSYS; \ return ret; \ } #define STUB_IGNORE(type, function, ret) \ type __unsup_##function(void) __asm__(#function); \ type __unsup_##function(void) \ { \ errno = ENOSYS; \ return ret; \ } /* stdio.h */ STUB_WARN_ONCE(int, fflush, 0); STUB_ABORT(rename); STUB_ABORT(sscanf); /* Used only for parsing OCAMLRUNPARAM, never called */ /* * The following stubs are not required by the OCaml runtime, but are * needed to build the freestanding version of GMP used by Mirage. */ STUB_WARN_ONCE(int, fread, 0); STUB_WARN_ONCE(int, getc, EOF); STUB_WARN_ONCE(int, ungetc, EOF); STUB_WARN_ONCE(int, fwrite, 0); STUB_WARN_ONCE(int, fputc, EOF); STUB_WARN_ONCE(int, fputs, EOF); STUB_WARN_ONCE(int, putc, EOF); STUB_WARN_ONCE(int, ferror, 1); STUB_WARN_ONCE(int, fopen, 1); STUB_WARN_ONCE(int, fclose, 1); /* stdlib.h */ STUB_WARN_ONCE(char *, getenv, NULL); STUB_WARN_ONCE(char *, secure_getenv, NULL); STUB_ABORT(system); /* unistd.h */ STUB_WARN_ONCE(int, chdir, -1); STUB_ABORT(close); STUB_ABORT(getcwd); STUB_WARN_ONCE(pid_t, getpid, 2); STUB_WARN_ONCE(pid_t, getppid, 1); STUB_IGNORE(int, isatty, 0); STUB_IGNORE(off_t, lseek, -1); STUB_ABORT(read); STUB_IGNORE(int, readlink, -1); STUB_ABORT(unlink); STUB_ABORT(rmdir); STUB_ABORT(ftruncate); STUB_ABORT(execv); /* dirent.h */ STUB_WARN_ONCE(int, closedir, -1); STUB_WARN_ONCE(void *, opendir, NULL); STUB_WARN_ONCE(struct dirent *, readdir, NULL); /* fcntl.h */ STUB_ABORT(fcntl); STUB_WARN_ONCE(int, open, -1); /* signal.h */ STUB_IGNORE(int, setjmp, 0); STUB_ABORT(signal); /* * The following stubs are not required by the OCaml runtime, but are * needed to build the freestanding version of GMP used by Mirage. */ STUB_ABORT(raise); /* string.h */ STUB_ABORT(strerror); /* sys/stat.h */ STUB_WARN_ONCE(int, stat, -1); STUB_ABORT(mkdir); /* pthread.h */ STUB_IGNORE(int, pthread_join, 0); STUB_IGNORE(int, pthread_create, EAGAIN); STUB_IGNORE(int, pthread_attr_init, 0); STUB_ABORT(pthread_cleanup_push); STUB_ABORT(pthread_cleanup_pop); /* above that line, for OCaml 5, those are only required (i guess) for the configure step */ STUB_IGNORE(int, pthread_mutex_lock, 0); STUB_IGNORE(int, pthread_mutex_trylock, 0); STUB_IGNORE(int, pthread_mutex_unlock, 0); STUB_IGNORE(int, pthread_mutex_destroy, 0); STUB_IGNORE(int, pthread_mutex_init, 0); STUB_IGNORE(int, pthread_mutexattr_init, 0); STUB_IGNORE(int, pthread_mutexattr_destroy, 0); STUB_IGNORE(int, pthread_mutexattr_settype, 0); STUB_IGNORE(int, pthread_sigmask, 0); STUB_IGNORE(int, pthread_equal, 1); STUB_IGNORE(int, pthread_condattr_init, 0); /* pthread_condattr_destroy: not used by Ocaml 5 (pthread_condattr_init is only used in ocaml/runtime/platform.c with a function local variable as argument) */ STUB_IGNORE(int, pthread_cond_init, 0); STUB_IGNORE(int, pthread_cond_destroy, 0); /* it's possible to create a [Stdlib.Condition.t] but an execution path exists * where we don't really use it. However, OCaml will try to destroy this * [Stdlib.Condition.t] and we must ignore such execution path which is still * safe for unikernels (with one core). The real issue with [pthread_cond_*] is * when we would like to suspend the execution with [pthread_cond_wait] but * [pthread_cond_init] and [pthread_cond_destroy] are safe to just ignore. */ STUB_ABORT(pthread_cond_wait); STUB_ABORT(pthread_cond_signal); STUB_IGNORE(int, pthread_cond_broadcast, 0); STUB_ABORT(pthread_self); STUB_ABORT(pthread_detach); STUB_IGNORE(int, sigfillset, 0); STUB_ABORT(sigwait); STUB_ABORT(usleep);