Add Cosmopolitan Libc Platform (#2598)

This PR adds the Cosmopolitan Libc platform enabling compatibility with multiple
x86_64 operating systems with the same binary. The platform is similar to the
Linux platform, but for now only x86_64 with interpreter modes are supported.

The only major change to the core is `posix.c/convert_errno()` was rewritten to use
a switch statement. With Cosmopolitan errno values depend on the currently
running operating system, and so they are non-constant and cannot be used in array
designators. However, the `cosmocc` compiler allows non-constant case labels in
switch statements, enabling the new version.

And updated wamr-test-suites script to add `-j <platform>` option. The spec tests
can be ran via `CC=cosmocc ./test_wamr.sh -j cosmopolitan -t classic-interp`
or `CC=cosmocc ./test_wamr.sh -j cosmopolitan -t fast-interp`.
This commit is contained in:
Gavin Hayes
2023-10-04 09:55:37 -04:00
committed by GitHub
parent 8987432f36
commit d8ee771e28
11 changed files with 512 additions and 94 deletions

View File

@ -60,98 +60,99 @@ static_assert(sizeof(struct iovec) == sizeof(__wasi_ciovec_t),
static __wasi_errno_t
convert_errno(int error)
{
static const __wasi_errno_t errors[] = {
#define X(v) [v] = __WASI_##v
X(E2BIG),
X(EACCES),
X(EADDRINUSE),
X(EADDRNOTAVAIL),
X(EAFNOSUPPORT),
X(EAGAIN),
X(EALREADY),
X(EBADF),
X(EBADMSG),
X(EBUSY),
X(ECANCELED),
X(ECHILD),
X(ECONNABORTED),
X(ECONNREFUSED),
X(ECONNRESET),
X(EDEADLK),
X(EDESTADDRREQ),
X(EDOM),
X(EDQUOT),
X(EEXIST),
X(EFAULT),
X(EFBIG),
X(EHOSTUNREACH),
X(EIDRM),
X(EILSEQ),
X(EINPROGRESS),
X(EINTR),
X(EINVAL),
X(EIO),
X(EISCONN),
X(EISDIR),
X(ELOOP),
X(EMFILE),
X(EMLINK),
X(EMSGSIZE),
X(EMULTIHOP),
X(ENAMETOOLONG),
X(ENETDOWN),
X(ENETRESET),
X(ENETUNREACH),
X(ENFILE),
X(ENOBUFS),
X(ENODEV),
X(ENOENT),
X(ENOEXEC),
X(ENOLCK),
X(ENOLINK),
X(ENOMEM),
X(ENOMSG),
X(ENOPROTOOPT),
X(ENOSPC),
X(ENOSYS),
__wasi_errno_t code = __WASI_ENOSYS;
#define X(v) \
case v: \
code = __WASI_##v; \
break;
switch (error) {
X(E2BIG)
X(EACCES)
X(EADDRINUSE)
X(EADDRNOTAVAIL)
X(EAFNOSUPPORT)
X(EAGAIN)
X(EALREADY)
X(EBADF)
X(EBADMSG)
X(EBUSY)
X(ECANCELED)
X(ECHILD)
X(ECONNABORTED)
X(ECONNREFUSED)
X(ECONNRESET)
X(EDEADLK)
X(EDESTADDRREQ)
X(EDOM)
X(EDQUOT)
X(EEXIST)
X(EFAULT)
X(EFBIG)
X(EHOSTUNREACH)
X(EIDRM)
X(EILSEQ)
X(EINPROGRESS)
X(EINTR)
X(EINVAL)
X(EIO)
X(EISCONN)
X(EISDIR)
X(ELOOP)
X(EMFILE)
X(EMLINK)
X(EMSGSIZE)
X(EMULTIHOP)
X(ENAMETOOLONG)
X(ENETDOWN)
X(ENETRESET)
X(ENETUNREACH)
X(ENFILE)
X(ENOBUFS)
X(ENODEV)
X(ENOENT)
X(ENOEXEC)
X(ENOLCK)
X(ENOLINK)
X(ENOMEM)
X(ENOMSG)
X(ENOPROTOOPT)
X(ENOSPC)
X(ENOSYS)
#ifdef ENOTCAPABLE
X(ENOTCAPABLE),
X(ENOTCAPABLE)
#endif
X(ENOTCONN),
X(ENOTDIR),
X(ENOTEMPTY),
X(ENOTRECOVERABLE),
X(ENOTSOCK),
X(ENOTSUP),
X(ENOTTY),
X(ENXIO),
X(EOVERFLOW),
X(EOWNERDEAD),
X(EPERM),
X(EPIPE),
X(EPROTO),
X(EPROTONOSUPPORT),
X(EPROTOTYPE),
X(ERANGE),
X(EROFS),
X(ESPIPE),
X(ESRCH),
X(ESTALE),
X(ETIMEDOUT),
X(ETXTBSY),
X(EXDEV),
X(ENOTCONN)
X(ENOTDIR)
X(ENOTEMPTY)
X(ENOTRECOVERABLE)
X(ENOTSOCK)
X(ENOTSUP)
X(ENOTTY)
X(ENXIO)
X(EOVERFLOW)
X(EOWNERDEAD)
X(EPERM)
X(EPIPE)
X(EPROTO)
X(EPROTONOSUPPORT)
X(EPROTOTYPE)
X(ERANGE)
X(EROFS)
X(ESPIPE)
X(ESRCH)
X(ESTALE)
X(ETIMEDOUT)
X(ETXTBSY)
X(EXDEV)
default:
if (error == EOPNOTSUPP)
code = __WASI_ENOTSUP;
else if (code == EWOULDBLOCK)
code = __WASI_EAGAIN;
break;
}
#undef X
#if EOPNOTSUPP != ENOTSUP
[EOPNOTSUPP] = __WASI_ENOTSUP,
#endif
#if EWOULDBLOCK != EAGAIN
[EWOULDBLOCK] = __WASI_EAGAIN,
#endif
};
if (error < 0 || (size_t)error >= sizeof(errors) / sizeof(errors[0])
|| errors[error] == 0)
return __WASI_ENOSYS;
return errors[error];
return code;
}
static bool

View File

@ -65,7 +65,7 @@
#endif
#endif
#if !defined(__APPLE__) && !defined(ESP_PLATFORM)
#if !defined(__APPLE__) && !defined(ESP_PLATFORM) && !defined(__COSMOPOLITAN__)
#define CONFIG_HAS_POSIX_FALLOCATE 1
#else
#define CONFIG_HAS_POSIX_FALLOCATE 0
@ -83,7 +83,8 @@
#define CONFIG_HAS_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP 0
#endif
#if !defined(__APPLE__) && !defined(BH_PLATFORM_LINUX_SGX)
#if !defined(__APPLE__) && !defined(BH_PLATFORM_LINUX_SGX) \
&& !defined(__COSMOPOLITAN__)
#define CONFIG_HAS_PTHREAD_CONDATTR_SETCLOCK 1
#else
#define CONFIG_HAS_PTHREAD_CONDATTR_SETCLOCK 0

View File

@ -799,7 +799,7 @@ os_socket_set_ip_add_membership(bh_socket_t socket,
{
assert(imr_multiaddr);
if (is_ipv6) {
#ifdef IPPROTO_IPV6
#if defined(IPPROTO_IPV6) && !defined(BH_PLATFORM_COSMOPOLITAN)
struct ipv6_mreq mreq;
for (int i = 0; i < 8; i++) {
((uint16_t *)mreq.ipv6mr_multiaddr.s6_addr)[i] =
@ -837,7 +837,7 @@ os_socket_set_ip_drop_membership(bh_socket_t socket,
{
assert(imr_multiaddr);
if (is_ipv6) {
#ifdef IPPROTO_IPV6
#if defined(IPPROTO_IPV6) && !defined(BH_PLATFORM_COSMOPOLITAN)
struct ipv6_mreq mreq;
for (int i = 0; i < 8; i++) {
((uint16_t *)mreq.ipv6mr_multiaddr.s6_addr)[i] =

View File

@ -0,0 +1,43 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include "platform_api_vmcore.h"
int
bh_platform_init()
{
return 0;
}
void
bh_platform_destroy()
{}
int
os_printf(const char *format, ...)
{
int ret = 0;
va_list ap;
va_start(ap, format);
#ifndef BH_VPRINTF
ret += vprintf(format, ap);
#else
ret += BH_VPRINTF(format, ap);
#endif
va_end(ap);
return ret;
}
int
os_vprintf(const char *format, va_list ap)
{
#ifndef BH_VPRINTF
return vprintf(format, ap);
#else
return BH_VPRINTF(format, ap);
#endif
}

View File

@ -0,0 +1,122 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* Copyright (C) 2023 Dylibso. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#ifndef _PLATFORM_INTERNAL_H
#define _PLATFORM_INTERNAL_H
#include <inttypes.h>
#include <stdbool.h>
#include <assert.h>
#include <time.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <stdarg.h>
#include <ctype.h>
#include <pthread.h>
#include <signal.h>
#include <semaphore.h>
#include <limits.h>
#include <dirent.h>
#include <fcntl.h>
#include <unistd.h>
#include <poll.h>
#include <sched.h>
#include <errno.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/time.h>
#include <sys/uio.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/resource.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifndef BH_PLATFORM_COSMOPOLITAN
#define BH_PLATFORM_COSMOPOLITAN
#endif
/* Stack size of applet threads's native part. */
#define BH_APPLET_PRESERVED_STACK_SIZE (32 * 1024)
/* Default thread priority */
#define BH_THREAD_DEFAULT_PRIORITY 0
typedef pthread_t korp_tid;
typedef pthread_mutex_t korp_mutex;
typedef pthread_cond_t korp_cond;
typedef pthread_t korp_thread;
typedef sem_t korp_sem;
#define OS_THREAD_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
#define os_thread_local_attribute __thread
#define bh_socket_t int
#if WASM_DISABLE_WRITE_GS_BASE == 0
#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64)
#define os_writegsbase(base_addr) \
do { \
uint64 __gs_value = (uint64)(uintptr_t)base_addr; \
asm volatile("wrgsbase %0" ::"r"(__gs_value) : "memory"); \
} while (0)
#if 0
/* _writegsbase_u64 also works, but need to add -mfsgsbase flag for gcc */
#include <immintrin.h>
#define os_writegsbase(base_addr) \
_writegsbase_u64(((uint64)(uintptr_t)base_addr))
#endif
#endif
#endif
#if WASM_DISABLE_HW_BOUND_CHECK == 0
#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) \
|| defined(BUILD_TARGET_AARCH64) || defined(BUILD_TARGET_RISCV64_LP64D) \
|| defined(BUILD_TARGET_RISCV64_LP64)
#include <setjmp.h>
#define OS_ENABLE_HW_BOUND_CHECK
typedef jmp_buf korp_jmpbuf;
#define os_setjmp setjmp
#define os_longjmp longjmp
#define os_alloca alloca
#define os_getpagesize getpagesize
typedef void (*os_signal_handler)(void *sig_addr);
int
os_thread_signal_init(os_signal_handler handler);
void
os_thread_signal_destroy();
bool
os_thread_signal_inited();
void
os_signal_unmask();
void
os_sigreturn();
#endif /* end of BUILD_TARGET_X86_64/AMD_64/AARCH64/RISCV64 */
#endif /* end of WASM_DISABLE_HW_BOUND_CHECK */
#ifdef __cplusplus
}
#endif
#endif /* end of _PLATFORM_INTERNAL_H */

View File

@ -0,0 +1,19 @@
# Copyright (C) 2019 Intel Corporation. All rights reserved.
# Copyright (C) 2023 Dylibso. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
set (PLATFORM_SHARED_DIR ${CMAKE_CURRENT_LIST_DIR})
add_definitions(-DBH_PLATFORM_COSMOPOLITAN)
include_directories(${PLATFORM_SHARED_DIR})
include_directories(${PLATFORM_SHARED_DIR}/../include)
include (${CMAKE_CURRENT_LIST_DIR}/../common/posix/platform_api_posix.cmake)
file (GLOB_RECURSE source_all ${PLATFORM_SHARED_DIR}/*.c)
set (PLATFORM_SHARED_SOURCE ${source_all} ${PLATFORM_COMMON_POSIX_SOURCE})
file (GLOB header ${PLATFORM_SHARED_DIR}/../include/*.h)
LIST (APPEND RUNTIME_LIB_HEADER_LIST ${header})