mirror of
https://github.com/fluencelabs/asmble
synced 2025-07-02 16:01:36 +00:00
Compare commits
6 Commits
split_fix
...
wasi_stage
Author | SHA1 | Date | |
---|---|---|---|
42bd748d95 | |||
f583e6f0c9 | |||
c3bdffc2a2 | |||
2144c74a66 | |||
4c5af2e998 | |||
d707a03b3f |
@ -21,7 +21,7 @@ buildscript {
|
||||
allprojects {
|
||||
apply plugin: 'java'
|
||||
group 'com.github.cretz.asmble'
|
||||
version '0.4.11-fl'
|
||||
version '0.4.11-fl_experiment_29'
|
||||
|
||||
// skips building and running for the specified examples
|
||||
ext.skipExamples = ['c-simple', 'go-simple', 'rust-regex']
|
||||
@ -309,9 +309,9 @@ def publishSettings(project, projectName, projectDescription) {
|
||||
}
|
||||
|
||||
bintray {
|
||||
if(!hasProperty("bintrayUser") || !hasProperty("bintrayKey")) {
|
||||
return
|
||||
}
|
||||
// if(!hasProperty("bintrayUser") || !hasProperty("bintrayKey")) {
|
||||
// return
|
||||
// }
|
||||
|
||||
user = bintrayUser
|
||||
key = bintrayKey
|
||||
|
@ -36,5 +36,7 @@ public abstract class MemoryBuffer {
|
||||
public abstract short getShort(int index);
|
||||
public abstract float getFloat(int index);
|
||||
public abstract double getDouble(int index);
|
||||
public abstract byte get();
|
||||
public abstract void get(byte[] arr, int offset, int length);
|
||||
public abstract MemoryBuffer get(byte[] arr);
|
||||
}
|
||||
|
@ -3,6 +3,9 @@ package asmble.cli
|
||||
import asmble.ast.Script
|
||||
import asmble.compile.jvm.*
|
||||
import asmble.run.jvm.*
|
||||
import asmble.run.jvm.native_modules.LoggerModule
|
||||
import asmble.run.jvm.native_modules.EnvModule
|
||||
import asmble.run.jvm.native_modules.wasi.WASIModule
|
||||
import java.io.File
|
||||
import java.io.PrintWriter
|
||||
import java.util.*
|
||||
@ -86,6 +89,24 @@ abstract class ScriptCommand<T> : Command<T>() {
|
||||
}
|
||||
}
|
||||
|
||||
PrintWriter(System.out, true).println("asmble is running");
|
||||
|
||||
// TODO: this hack should be refactored in future with rewritting the part of Asmble core code
|
||||
// check that there is only one main module
|
||||
if(context.modules.size == 1 && args.memoryBuilder != null) {
|
||||
PrintWriter(System.out, true).println("WASI module loaded");
|
||||
val capacity = Math.multiplyExact(args.defaultMaxMemPages, Mem.PAGE_SIZE)
|
||||
val moduleMem = args.memoryBuilder.build(capacity)
|
||||
context.moduleMem = moduleMem
|
||||
|
||||
// add the WASI Wasm module for support a subset of WASI syscalls
|
||||
// WASI is enabled only for one module mode
|
||||
context = context.withModuleRegistered(
|
||||
"wasi_unstable",
|
||||
Module.Native(WASIModule(moduleMem, arrayOf("/Users/")))
|
||||
)
|
||||
}
|
||||
|
||||
// Do registrations
|
||||
context = args.registrations.fold(context) { ctx, (moduleName, className) ->
|
||||
ctx.withModuleRegistered(moduleName,
|
||||
@ -95,15 +116,14 @@ abstract class ScriptCommand<T> : Command<T>() {
|
||||
if (args.specTestRegister) context = context.withHarnessRegistered()
|
||||
|
||||
if (args.enableLogger) {
|
||||
// add logger Wasm module for logging
|
||||
context =
|
||||
context.withModuleRegistered(
|
||||
// add the logger Wasm module for logging
|
||||
context = context.withModuleRegistered(
|
||||
"logger",
|
||||
Module.Native(LoggerModule(PrintWriter(System.out)))
|
||||
)
|
||||
}
|
||||
|
||||
// add env Wasm module for gas metering
|
||||
// add the env Wasm module for gas metering
|
||||
context =
|
||||
context.withModuleRegistered(
|
||||
"env",
|
||||
|
@ -108,6 +108,14 @@ open class MemoryByteBuffer(val bb: ByteBuffer) : MemoryBuffer() {
|
||||
return bb.getDouble(index)
|
||||
}
|
||||
|
||||
override fun get(): Byte {
|
||||
return bb.get();
|
||||
}
|
||||
|
||||
override fun get(arr: ByteArray, offset: Int, length: Int) {
|
||||
bb.get(arr, offset, length);
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other)
|
||||
return true
|
||||
|
@ -77,6 +77,7 @@ interface Module {
|
||||
// If there is a memory import, we have to get the one with the mem class as the first
|
||||
val memImport = mod.imports.find { it.kind is Node.Import.Kind.Memory }
|
||||
val builder = ctx.memoryBuilder
|
||||
val moduleMem = ctx.moduleMem
|
||||
|
||||
val memLimit = if (memImport != null) {
|
||||
constructor = cls.declaredConstructors.find { it.parameterTypes.firstOrNull()?.ref == mem.memType }
|
||||
@ -91,6 +92,11 @@ interface Module {
|
||||
throw RunErr.ImportMemoryCapacityTooLarge(it * Mem.PAGE_SIZE, memCap)
|
||||
}
|
||||
memLimit
|
||||
} else if (moduleMem != null) {
|
||||
constructor = cls.declaredConstructors.find { it.parameterTypes.firstOrNull()?.ref == mem.memType }
|
||||
|
||||
constructorParams += moduleMem
|
||||
ctx.defaultMaxMemPages * Mem.PAGE_SIZE
|
||||
} else if (builder != null) {
|
||||
constructor = cls.declaredConstructors.find { it.parameterTypes.firstOrNull()?.ref == mem.memType }
|
||||
|
||||
|
@ -6,6 +6,7 @@ import asmble.ast.Script
|
||||
import asmble.compile.jvm.*
|
||||
import asmble.io.AstToSExpr
|
||||
import asmble.io.SExprToStr
|
||||
import asmble.run.jvm.native_modules.TestHarness
|
||||
import asmble.util.Logger
|
||||
import asmble.util.toRawIntBits
|
||||
import asmble.util.toRawLongBits
|
||||
@ -44,7 +45,8 @@ data class ScriptContext(
|
||||
val exceptionTranslator: ExceptionTranslator = ExceptionTranslator,
|
||||
val defaultMaxMemPages: Int = 1,
|
||||
val includeBinaryInCompiledClass: Boolean = false,
|
||||
val memoryBuilder: MemoryBufferBuilder? = null
|
||||
val memoryBuilder: MemoryBufferBuilder? = null,
|
||||
var moduleMem: MemoryBuffer? = null
|
||||
) : Logger by logger {
|
||||
|
||||
fun withHarnessRegistered(out: PrintWriter = PrintWriter(System.out, true)) =
|
||||
|
@ -1,4 +1,4 @@
|
||||
package asmble.run.jvm
|
||||
package asmble.run.jvm.native_modules
|
||||
|
||||
/**
|
||||
* Used to tack the state of the environment module.
|
||||
@ -46,11 +46,17 @@ open class EnvModule(private val gasLimit: Long) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns environment module state.
|
||||
* Used from WasmVm to determine spent gas and executed instruction counter after each invocation.
|
||||
* Returns spent gas.
|
||||
*/
|
||||
fun getState(): EnvState {
|
||||
return state;
|
||||
fun getSpentGas(): Long {
|
||||
return state.spentGas;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns executed instruction counter.
|
||||
*/
|
||||
fun getEIC(): Long {
|
||||
return state.EIC;
|
||||
}
|
||||
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package asmble.run.jvm
|
||||
package asmble.run.jvm.native_modules
|
||||
|
||||
import asmble.compile.jvm.Mem
|
||||
import java.io.PrintWriter
|
@ -1,7 +1,5 @@
|
||||
package asmble.run.jvm
|
||||
package asmble.run.jvm.native_modules
|
||||
|
||||
import asmble.annotation.WasmExport
|
||||
import asmble.annotation.WasmExternalKind
|
||||
import asmble.compile.jvm.Mem
|
||||
import asmble.compile.jvm.MemoryBuffer
|
||||
import asmble.compile.jvm.MemoryByteBuffer
|
@ -0,0 +1,402 @@
|
||||
package asmble.run.jvm.native_modules.wasi
|
||||
|
||||
import asmble.ast.Script
|
||||
import asmble.compile.jvm.MemoryBuffer
|
||||
import asmble.run.jvm.ScriptAssertionError
|
||||
import java.io.File
|
||||
import java.io.PrintWriter
|
||||
import java.lang.Integer.min
|
||||
import java.util.*
|
||||
import kotlin.collections.HashMap
|
||||
|
||||
/**
|
||||
* Module used for support WASI, contains the realization of several WASI imports
|
||||
* for operating with file system. Should be registered as 'wasi_unstable'.
|
||||
*/
|
||||
open class WASIModule(private val mem: MemoryBuffer, private val preopenedDirNames: Array<String>) {
|
||||
/*
|
||||
+ (import "wasi_unstable" "fd_prestat_get" (func $__wasi_fd_prestat_get (type 2)))
|
||||
+ (import "wasi_unstable" "fd_prestat_dir_name" (func $__wasi_fd_prestat_dir_name (type 1)))
|
||||
+ (import "wasi_unstable" "environ_sizes_get" (func $__wasi_environ_sizes_get (type 2)))
|
||||
+ (import "wasi_unstable" "environ_get" (func $__wasi_environ_get (type 2)))
|
||||
+ (import "wasi_unstable" "args_sizes_get" (func $__wasi_args_sizes_get (type 2)))
|
||||
+ (import "wasi_unstable" "args_get" (func $__wasi_args_get (type 2)))
|
||||
(import "wasi_unstable" "fd_close" (func $fd_close (type 3)))
|
||||
(import "wasi_unstable" "fd_write" (func $fd_write (type 9)))
|
||||
(import "wasi_unstable" "fd_read" (func $fd_read (type 9)))
|
||||
(import "wasi_unstable" "path_open" (func $path_open (type 10)))
|
||||
+ (import "wasi_unstable" "proc_exit" (func $__wasi_proc_exit (type 0)))
|
||||
(import "wasi_unstable" "fd_fdstat_get" (func $__wasi_fd_fdstat_get (type 2)))
|
||||
*/
|
||||
|
||||
private val writer = PrintWriter(System.out, true);
|
||||
|
||||
// this error code will be returned by all non-implemented methods
|
||||
private val wasiErrorCode: Int = __WASI_EACCES
|
||||
|
||||
private val stdin: Int = 0
|
||||
private val stdout: Int = 1
|
||||
private val stderr: Int = 2
|
||||
|
||||
private var nextPreopenedDirId = 0;
|
||||
private val preopenedDirs = HashMap<Int, String>()
|
||||
|
||||
// mapping between file descriptors and opened file
|
||||
private val openedFiles = HashMap<Int, File>()
|
||||
private val openedFilesOffset = HashMap<Int, Int>()
|
||||
private val openedFileNames = HashMap<String, Int>()
|
||||
|
||||
/**
|
||||
* [Wasm function]
|
||||
* Gets metadata about a preopened file descriptor.
|
||||
*
|
||||
* @param fd the preopened file descriptor to query
|
||||
* @param buf_ptr where the metadata will be written
|
||||
* @return WASI code of result
|
||||
*/
|
||||
fun fd_prestat_get(
|
||||
fd: Int,
|
||||
buf_ptr: Int
|
||||
): Int {
|
||||
writer.println("fd_prestat_get: $fd, $buf_ptr");
|
||||
writer.flush();
|
||||
|
||||
if (nextPreopenedDirId >= preopenedDirNames.size) {
|
||||
return __WASI_EBADF;
|
||||
}
|
||||
|
||||
// dir type
|
||||
mem.putInt(buf_ptr, 0);
|
||||
|
||||
// dir length
|
||||
|
||||
writer.println("fd_prestat_get: returning ${preopenedDirNames[nextPreopenedDirId].length} as the string length");
|
||||
writer.flush();
|
||||
|
||||
mem.putInt(buf_ptr + 4, preopenedDirNames[nextPreopenedDirId].length);
|
||||
preopenedDirs[fd] = preopenedDirNames[nextPreopenedDirId];
|
||||
|
||||
++nextPreopenedDirId;
|
||||
|
||||
return __WASI_ESUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* [Wasm function]
|
||||
* Gets state of preopened file descriptors.
|
||||
*
|
||||
* @param fd the preopened file descriptor to query
|
||||
* @param path where the metadata will be written
|
||||
* @param path_len the length of metadata
|
||||
* @return WASI code of result
|
||||
*/
|
||||
fun fd_prestat_dir_name(
|
||||
fd: Int,
|
||||
path: Int,
|
||||
path_len: Int
|
||||
): Int {
|
||||
writer.println("fd_prestat_dir_name: $fd, $path, $path_len");
|
||||
writer.flush();
|
||||
|
||||
val memView = mem.duplicate();
|
||||
memView.position(path);
|
||||
|
||||
if(preopenedDirs.containsKey(fd) ) {
|
||||
writer.println("fd_prestat_dir_name: return string ${preopenedDirs[fd]}");
|
||||
writer.flush();
|
||||
memView.put(preopenedDirs[fd]!!.toByteArray(), 0, path_len);
|
||||
} else {
|
||||
// TODO: handle error
|
||||
memView.put(path, 0);
|
||||
}
|
||||
|
||||
return __WASI_ESUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* [Wasm function]
|
||||
* Gets metadata of a file descriptor.
|
||||
*
|
||||
* @param fd the file descriptor whose metadata will be accessed
|
||||
* @param buf the location where the metadata will be written
|
||||
* @return WASI code of result
|
||||
*/
|
||||
fun fd_fdstat_get(
|
||||
fd: Int,
|
||||
path: Int
|
||||
): Int {
|
||||
writer.println("fd_fdstat_get: $fd, $path");
|
||||
writer.flush();
|
||||
|
||||
if(preopenedDirs.containsKey(fd)) {
|
||||
mem.put(path, __WASI_FILETYPE_DIRECTORY.toByte());
|
||||
mem.putShort(path + 2, __WASI_FILETYPE_DIRECTORY.toShort());
|
||||
// all rights
|
||||
mem.putLong(path + 8, Long.MAX_VALUE);
|
||||
mem.putLong(path + 16, Long.MAX_VALUE);
|
||||
}
|
||||
|
||||
return __WASI_ESUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* [Wasm function]
|
||||
* Opens file located at the given path.
|
||||
*
|
||||
* @param dirfd the descriptor corresponding to the directory that the file is in
|
||||
* @param dirflags flags specifying how the path will be resolved
|
||||
* @param path_offset the path of the file or directory to be open
|
||||
* @param path_len the lenght of the path string
|
||||
* @param o_flags how the file will be open
|
||||
* @param fs_rights_base the rights of the created file descriptor
|
||||
* @param fs_rightsinheriting the rights of file descriptors derived from the created file descriptor
|
||||
* @param fs_flags the flags of the file descriptor
|
||||
* @param fd the new file descriptor
|
||||
* @return WASI code of result
|
||||
*/
|
||||
fun path_open(
|
||||
dirfd: __wasi_fd_t,
|
||||
dirflags: __wasi_lookupflags_t,
|
||||
path_offset: Int,
|
||||
path_len: Int,
|
||||
o_flags: __wasi_oflags_t,
|
||||
fs_rights_base: __wasi_rights_t,
|
||||
fs_rightsinheriting: __wasi_rights_t,
|
||||
fs_flags: __wasi_fdflags_t,
|
||||
fd: __wasi_fd_t
|
||||
): Int {
|
||||
// path_open: 3, 1, 1114408, 43, 9, 264749053, 264749053, 0, 1048400
|
||||
writer.println("path_open: $dirfd, $dirflags, $path_offset, $path_len, $o_flags, $fs_rights_base, $fs_rightsinheriting, $fs_flags, $fd");
|
||||
writer.flush();
|
||||
|
||||
if( (dirflags and __WASI_LOOKUP_SYMLINK_FOLLOW) != 0) {
|
||||
// TODO
|
||||
writer.println("path_open: will follow debug links");
|
||||
writer.flush();
|
||||
}
|
||||
|
||||
val pathToOpen = preopenedDirs[dirfd]!! + readUTF8String(mem, path_offset, path_len);
|
||||
|
||||
writer.println("path_open: $pathToOpen");
|
||||
writer.flush();
|
||||
|
||||
var newFd = 2 + nextPreopenedDirId + 10;
|
||||
if(openedFileNames.containsKey(pathToOpen)) {
|
||||
newFd = openedFileNames[pathToOpen]!!;
|
||||
} else {
|
||||
if(o_flags and __WASI_O_CREAT == 0) {
|
||||
return __WASI_EINVAL;
|
||||
}
|
||||
|
||||
if(o_flags and __WASI_O_DIRECTORY != 0) {
|
||||
return __WASI_ENOTDIR;
|
||||
}
|
||||
|
||||
val file = File(pathToOpen);
|
||||
if(file.exists() && (o_flags and __WASI_O_EXCL != 0)) {
|
||||
return __WASI_EINVAL;
|
||||
}
|
||||
file.createNewFile();
|
||||
|
||||
openedFileNames[pathToOpen] = newFd;
|
||||
openedFilesOffset[newFd] = 0;
|
||||
openedFiles[newFd] = File(pathToOpen);
|
||||
}
|
||||
|
||||
mem.putInt(fd, newFd);
|
||||
|
||||
return __WASI_ESUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* [Wasm function]
|
||||
* Reads data from file descriptor.
|
||||
*
|
||||
* @param fd a file descriptor from which data will be read
|
||||
* @param iovs vectors where data will be stored
|
||||
* @param iovs_len the length of data in `iovs`
|
||||
* @param nread number of bytes read
|
||||
*/
|
||||
fun fd_read(
|
||||
fd: __wasi_fd_t,
|
||||
iovs: Int,
|
||||
iovs_len: Int,
|
||||
nread: Int
|
||||
): Int {
|
||||
|
||||
writer.println("fd_read: $fd, $iovs, $iovs_len, $nread");
|
||||
writer.flush();
|
||||
|
||||
// check that is isn't standart i/o descriptor
|
||||
if(fd <= 2) {
|
||||
// return 0 bytes written if we try to read from the stdin
|
||||
mem.putInt(nread, 0);
|
||||
return __WASI_ESUCCESS;
|
||||
}
|
||||
|
||||
val data_ptr = mem.getInt(iovs);
|
||||
val data_len = mem.getInt(iovs + 4);
|
||||
val readBytes = openedFiles[fd]!!.readBytes();
|
||||
|
||||
val offset = if(openedFilesOffset.containsKey(fd)) {
|
||||
openedFilesOffset[fd]!!
|
||||
} else {
|
||||
0
|
||||
}
|
||||
|
||||
val readBytesCount = min(data_len, readBytes.size - offset);
|
||||
val tmpMem = ByteArray(readBytesCount);
|
||||
writer.println("fd_read: $data_ptr $data_len $readBytesCount");
|
||||
writer.flush();
|
||||
|
||||
System.arraycopy(readBytes, offset, tmpMem, 0, readBytesCount);
|
||||
|
||||
writer.println("fd_read: $data_ptr $data_len $readBytes $tmpMem");
|
||||
writer.flush();
|
||||
|
||||
openedFilesOffset[fd] = offset + readBytesCount;
|
||||
|
||||
val memView = mem.duplicate();
|
||||
memView.position(data_ptr);
|
||||
memView.put(tmpMem, 0, readBytesCount);
|
||||
mem.putInt(nread, readBytesCount);
|
||||
|
||||
return __WASI_ESUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* [Wasm function]
|
||||
* Writes data to the file descriptor.
|
||||
*
|
||||
* @param fd a file descriptor (opened with writing) to write to
|
||||
* @param iovs a list of vectors to read data from
|
||||
* @param iovs_len the length of data in `iovs`
|
||||
* @param nwritten the number of bytes written
|
||||
*/
|
||||
fun fd_write(
|
||||
fd: __wasi_fd_t,
|
||||
iovs: Int,
|
||||
iovs_len: Int,
|
||||
nwritten: Int
|
||||
): Int {
|
||||
|
||||
val data_ptr = mem.getInt(iovs);
|
||||
val data_len = mem.getInt(iovs + 4);
|
||||
|
||||
val str = readUTF8String(mem, data_ptr, data_len);
|
||||
|
||||
writer.println("fd_write: $fd, $iovs, $iovs_len, $nwritten, $str");
|
||||
writer.flush();
|
||||
|
||||
// check that is isn't standart i/o descriptor
|
||||
if(fd > 2) {
|
||||
openedFiles[fd]!!.writeText(str);
|
||||
}
|
||||
|
||||
mem.putInt(nwritten, data_len);
|
||||
return __WASI_ESUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* [Wasm function]
|
||||
* Close an open file descriptor
|
||||
*
|
||||
* @param fd a file descriptor mapping to an open file to close
|
||||
*/
|
||||
fun fd_close(
|
||||
fd: __wasi_fd_t
|
||||
): Int {
|
||||
writer.println("fd_close: $fd");
|
||||
writer.flush();
|
||||
|
||||
openedFiles.remove(fd);
|
||||
openedFilesOffset.remove(fd);
|
||||
|
||||
return __WASI_ESUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* [Wasm function]
|
||||
* Returns a command-line arguments size.
|
||||
*
|
||||
* @param argc the number of arguments
|
||||
* @param argv_buf_size the size of the argument string data
|
||||
*/
|
||||
fun args_sizes_get(
|
||||
argc: Int,
|
||||
argv_buf_size: Int
|
||||
): Int {
|
||||
writer.println("args_sizes_get: $argc, $argv_buf_size");
|
||||
writer.flush();
|
||||
|
||||
mem.putInt(argc, 0);
|
||||
mem.putInt(argv_buf_size, 0);
|
||||
|
||||
return __WASI_ESUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* [Wasm function]
|
||||
* Reads a command-line arguments.
|
||||
*
|
||||
* @param argv a pointer to a buffer to write the argument pointers
|
||||
* @param argv_buf a pointer to a buffer to write the argument string data
|
||||
*/
|
||||
fun args_get(
|
||||
argv: Int,
|
||||
argv_buf: Int
|
||||
): Int {
|
||||
writer.println("args_get: $argv, $argv_buf");
|
||||
writer.flush();
|
||||
|
||||
return __WASI_ESUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* [Wasm function]
|
||||
* Returns a command-line arguments size.
|
||||
*
|
||||
* @param environ_count the number of environment variables
|
||||
* @param environ_buf_size the size of the environment variable string data
|
||||
*/
|
||||
fun environ_sizes_get(
|
||||
environ_count: Int,
|
||||
environ_buf_size: Int
|
||||
): Int {
|
||||
writer.println("environ_sizes_get: $environ_count, $environ_buf_size");
|
||||
writer.flush();
|
||||
|
||||
mem.putInt(environ_count, 0);
|
||||
mem.putInt(environ_buf_size, 0);
|
||||
|
||||
return __WASI_ESUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* [Wasm function]
|
||||
* Reads a command-line arguments.
|
||||
*/
|
||||
fun environ_get(
|
||||
environ: Int,
|
||||
environ_buf: Int
|
||||
): Int {
|
||||
writer.println("environ_get: $environ, $environ_buf");
|
||||
writer.flush();
|
||||
|
||||
return wasiErrorCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* [Wasm function]
|
||||
* Reads a command-line arguments.
|
||||
*
|
||||
* @param code the exit code
|
||||
*/
|
||||
fun proc_exit(code: Int){
|
||||
writer.println("proc_exit: $code");
|
||||
writer.flush();
|
||||
|
||||
throw ScriptAssertionError(Script.Cmd.Assertion.Trap(Script.Cmd.Action.Get("", ""), "trap"), "proc_exit")
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package asmble.run.jvm.native_modules.wasi
|
||||
|
||||
import java.io.File
|
||||
|
||||
/**
|
||||
* Module used for support WASI, contains the realization of several WASI imports
|
||||
* for operating with file system. Should be registered as 'wasi_unstable'.
|
||||
*/
|
||||
data class WASIState (
|
||||
// mapping between file descriptors and opened file
|
||||
val openFiles: HashMap<Int, File> = HashMap<Int, File>()
|
||||
)
|
@ -0,0 +1,154 @@
|
||||
package asmble.run.jvm.native_modules.wasi
|
||||
|
||||
typealias __wasi_fd_t = Int;
|
||||
val __WASI_STDIN_FILENO: __wasi_fd_t = 0;
|
||||
val __WASI_STDOUT_FILENO: __wasi_fd_t = 1;
|
||||
val __WASI_STDERR_FILENO: __wasi_fd_t = 2;
|
||||
|
||||
typealias __wasi_lookupflags_t = Int;
|
||||
val __WASI_LOOKUP_SYMLINK_FOLLOW: __wasi_lookupflags_t = 1;
|
||||
|
||||
typealias __wasi_oflags_t = Int;//Short;
|
||||
val __WASI_O_CREAT: __wasi_oflags_t = 1;
|
||||
val __WASI_O_DIRECTORY: __wasi_oflags_t = 2;
|
||||
val __WASI_O_EXCL: __wasi_oflags_t = 4;
|
||||
val __WASI_O_TRUNC: __wasi_oflags_t = 8;
|
||||
|
||||
val __WASI_ESUCCESS = 0
|
||||
val __WASI_E2BIG = 1
|
||||
val __WASI_EACCES = 2
|
||||
val __WASI_EADDRINUSE = 3
|
||||
val __WASI_EADDRNOTAVAIL = 4
|
||||
val __WASI_EAFNOSUPPORT = 5
|
||||
val __WASI_EAGAIN = 6
|
||||
val __WASI_EALREADY = 7
|
||||
val __WASI_EBADF = 8
|
||||
val __WASI_EBADMSG = 9
|
||||
val __WASI_EBUSY = 10
|
||||
val __WASI_ECANCELED = 11
|
||||
val __WASI_ECHILD = 12
|
||||
val __WASI_ECONNABORTED = 13
|
||||
val __WASI_ECONNREFUSED = 14
|
||||
val __WASI_ECONNRESET = 15
|
||||
val __WASI_EDEADLK = 16
|
||||
val __WASI_EDESTADDRREQ = 17
|
||||
val __WASI_EDOM = 18
|
||||
val __WASI_EDQUOT = 19
|
||||
val __WASI_EEXIST = 20
|
||||
val __WASI_EFAULT = 21
|
||||
val __WASI_EFBIG = 22
|
||||
val __WASI_EHOSTUNREACH = 23
|
||||
val __WASI_EIDRM = 24
|
||||
val __WASI_EILSEQ = 25
|
||||
val __WASI_EINPROGRESS = 26
|
||||
val __WASI_EINTR = 27
|
||||
val __WASI_EINVAL = 28
|
||||
val __WASI_EIO = 29
|
||||
val __WASI_EISCONN = 30
|
||||
val __WASI_EISDIR = 31
|
||||
val __WASI_ELOOP = 32
|
||||
val __WASI_EMFILE = 33
|
||||
val __WASI_EMLINK = 34
|
||||
val __WASI_EMSGSIZE = 35
|
||||
val __WASI_EMULTIHOP = 36
|
||||
val __WASI_ENAMETOOLONG = 37
|
||||
val __WASI_ENETDOWN = 38
|
||||
val __WASI_ENETRESET = 39
|
||||
val __WASI_ENETUNREACH = 40
|
||||
val __WASI_ENFILE = 41
|
||||
val __WASI_ENOBUFS = 42
|
||||
val __WASI_ENODEV = 43
|
||||
val __WASI_ENOENT = 44
|
||||
val __WASI_ENOEXEC = 45
|
||||
val __WASI_ENOLCK = 46
|
||||
val __WASI_ENOLINK = 47
|
||||
val __WASI_ENOMEM = 48
|
||||
val __WASI_ENOMSG = 49
|
||||
val __WASI_ENOPROTOOPT = 50
|
||||
val __WASI_ENOSPC = 51
|
||||
val __WASI_ENOSYS = 52
|
||||
val __WASI_ENOTCONN = 53
|
||||
val __WASI_ENOTDIR = 54
|
||||
val __WASI_ENOTEMPTY = 55
|
||||
val __WASI_ENOTRECOVERABLE = 56
|
||||
val __WASI_ENOTSOCK = 57
|
||||
val __WASI_ENOTSUP = 58
|
||||
val __WASI_ENOTTY = 59
|
||||
val __WASI_ENXIO = 60
|
||||
val __WASI_EOVERFLOW = 61
|
||||
val __WASI_EOWNERDEAD = 62
|
||||
val __WASI_EPERM = 63
|
||||
val __WASI_EPIPE = 64
|
||||
val __WASI_EPROTO = 65
|
||||
val __WASI_EPROTONOSUPPORT = 66
|
||||
val __WASI_EPROTOTYPE = 67
|
||||
val __WASI_ERANGE = 68
|
||||
val __WASI_EROFS = 69
|
||||
val __WASI_ESPIPE = 70
|
||||
val __WASI_ESRCH = 71
|
||||
val __WASI_ESTALE = 72
|
||||
val __WASI_ETIMEDOUT = 73
|
||||
val __WASI_ETXTBSY = 74
|
||||
val __WASI_EXDEV = 75
|
||||
val __WASI_ENOTCAPABLE = 76
|
||||
|
||||
typealias __wasi_filetype_t = Int;//Byte;
|
||||
val __WASI_FILETYPE_UNKNOWN: __wasi_filetype_t = 0;
|
||||
val __WASI_FILETYPE_BLOCK_DEVICE: __wasi_filetype_t = 1;
|
||||
val __WASI_FILETYPE_CHARACTER_DEVICE: __wasi_filetype_t = 2;
|
||||
val __WASI_FILETYPE_DIRECTORY: __wasi_filetype_t = 3;
|
||||
val __WASI_FILETYPE_REGULAR_FILE: __wasi_filetype_t = 4;
|
||||
val __WASI_FILETYPE_SOCKET_DGRAM: __wasi_filetype_t = 5;
|
||||
val __WASI_FILETYPE_SOCKET_STREAM: __wasi_filetype_t = 6;
|
||||
val __WASI_FILETYPE_SYMBOLIC_LINK: __wasi_filetype_t = 7;
|
||||
|
||||
typealias __wasi_fstflags_t = Int;//Short;
|
||||
val __WASI_FILESTAT_SET_ATIM: __wasi_fstflags_t = 1;
|
||||
val __WASI_FILESTAT_SET_ATIM_NOW: __wasi_fstflags_t = 2;
|
||||
val __WASI_FILESTAT_SET_MTIM: __wasi_fstflags_t = 4;
|
||||
val __WASI_FILESTAT_SET_MTIM_NOW: __wasi_fstflags_t = 8;
|
||||
|
||||
typealias __wasi_fdflags_t = Int;//Short;
|
||||
val __WASI_FDFLAG_APPEND: __wasi_fdflags_t = 1;
|
||||
val __WASI_FDFLAG_DSYNC: __wasi_fdflags_t = 2;
|
||||
val __WASI_FDFLAG_NONBLOCK: __wasi_fdflags_t = 4;
|
||||
val __WASI_FDFLAG_RSYNC: __wasi_fdflags_t = 8;
|
||||
val __WASI_FDFLAG_SYNC: __wasi_fdflags_t = 16;
|
||||
|
||||
typealias __wasi_rights_t = Long;
|
||||
val __WASI_RIGHT_FD_DATASYNC: __wasi_rights_t = 1;
|
||||
val __WASI_RIGHT_FD_READ: __wasi_rights_t = 2;
|
||||
val __WASI_RIGHT_FD_SEEK: __wasi_rights_t = 4;
|
||||
val __WASI_RIGHT_FD_FDSTAT_SET_FLAGS: __wasi_rights_t = 8;
|
||||
val __WASI_RIGHT_FD_SYNC: __wasi_rights_t = 16;
|
||||
val __WASI_RIGHT_FD_TELL: __wasi_rights_t = 32;
|
||||
val __WASI_RIGHT_FD_WRITE: __wasi_rights_t = 64;
|
||||
val __WASI_RIGHT_FD_ADVISE: __wasi_rights_t = 128;
|
||||
val __WASI_RIGHT_FD_ALLOCATE: __wasi_rights_t = 256;
|
||||
val __WASI_RIGHT_PATH_CREATE_DIRECTORY: __wasi_rights_t = 512;
|
||||
val __WASI_RIGHT_PATH_CREATE_FILE: __wasi_rights_t = 1024;
|
||||
val __WASI_RIGHT_PATH_LINK_SOURCE: __wasi_rights_t = 2048;
|
||||
val __WASI_RIGHT_PATH_LINK_TARGET: __wasi_rights_t = 4096;
|
||||
val __WASI_RIGHT_PATH_OPEN: __wasi_rights_t = 8192;
|
||||
val __WASI_RIGHT_FD_READDIR: __wasi_rights_t = 16384;
|
||||
val __WASI_RIGHT_PATH_READLINK: __wasi_rights_t = 32768;
|
||||
val __WASI_RIGHT_PATH_RENAME_SOURCE: __wasi_rights_t = 65536;
|
||||
val __WASI_RIGHT_PATH_RENAME_TARGET: __wasi_rights_t = 131072;
|
||||
val __WASI_RIGHT_PATH_FILESTAT_GET: __wasi_rights_t = 262144;
|
||||
val __WASI_RIGHT_PATH_FILESTAT_SET_SIZE: __wasi_rights_t = 524288;
|
||||
val __WASI_RIGHT_PATH_FILESTAT_SET_TIMES: __wasi_rights_t = 1048576;
|
||||
val __WASI_RIGHT_FD_FILESTAT_GET: __wasi_rights_t = 2097152;
|
||||
val __WASI_RIGHT_FD_FILESTAT_SET_SIZE: __wasi_rights_t = 4194304;
|
||||
val __WASI_RIGHT_FD_FILESTAT_SET_TIMES: __wasi_rights_t = 8388608;
|
||||
val __WASI_RIGHT_PATH_SYMLINK: __wasi_rights_t = 16777216;
|
||||
val __WASI_RIGHT_PATH_UNLINK_FILE: __wasi_rights_t = 33554432;
|
||||
val __WASI_RIGHT_PATH_REMOVE_DIRECTORY: __wasi_rights_t = 67108864;
|
||||
val __WASI_RIGHT_POLL_FD_READWRITE: __wasi_rights_t = 134217728;
|
||||
val __WASI_RIGHT_SOCK_SHUTDOWN: __wasi_rights_t = 268435456;
|
||||
|
||||
data class __wasi_fdstat_t (
|
||||
var fs_filetype: __wasi_filetype_t,
|
||||
var fs_flags: __wasi_fdflags_t,
|
||||
var fs_rights_base: __wasi_rights_t,
|
||||
var fs_rights_inheriting: __wasi_rights_t
|
||||
)
|
@ -0,0 +1,17 @@
|
||||
package asmble.run.jvm.native_modules.wasi
|
||||
|
||||
import asmble.compile.jvm.MemoryBuffer
|
||||
import java.io.PrintWriter
|
||||
import java.nio.charset.Charset
|
||||
import kotlin.ByteArray
|
||||
|
||||
fun readUTF8String(mem: MemoryBuffer, offset: Int, length: Int): String {
|
||||
// TODO: too many copying
|
||||
val duplicatedMem = mem.duplicate();
|
||||
duplicatedMem.position(offset);
|
||||
|
||||
val arr = ByteArray(length);
|
||||
duplicatedMem.get(arr, 0, length);
|
||||
|
||||
return String(arr, 0, length, Charset.forName("UTF-8"));
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
package asmble.run.jvm
|
||||
|
||||
import asmble.TestBase
|
||||
import asmble.run.jvm.native_modules.LoggerModule
|
||||
import org.junit.Test
|
||||
import java.io.PrintWriter
|
||||
import java.io.StringWriter
|
||||
|
Reference in New Issue
Block a user