wardite 0.5.1 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Steepfile +1 -0
- data/exe/wardite +11 -5
- data/lib/wardite/instruction.rb +7 -9
- data/lib/wardite/load.rb +14 -9
- data/lib/wardite/revisitor.rb +1 -1
- data/lib/wardite/value.rb +6 -22
- data/lib/wardite/version.rb +1 -1
- data/lib/wardite/wasi/consts.rb +129 -0
- data/lib/wardite/wasi.rb +268 -7
- data/lib/wardite/wasm_module.rb +53 -0
- data/lib/wardite.rb +68 -40
- data/misc/proposals/rubykaigi2025.md +46 -0
- data/misc/slides/fib.c +4 -0
- data/misc/slides/fib.html +13 -0
- data/misc/slides/image-1.png +0 -0
- data/misc/slides/image-2.png +0 -0
- data/misc/slides/image.png +0 -0
- data/misc/slides/tokyo12.html +614 -0
- data/misc/slides/tokyo12.md +624 -0
- data/sig/fcntl.rbs +7 -0
- data/sig/generated/wardite/load.rbs +2 -2
- data/sig/generated/wardite/value.rbs +3 -10
- data/sig/generated/wardite/wasi/consts.rbs +137 -0
- data/sig/generated/wardite/wasi.rbs +62 -5
- data/sig/generated/wardite/wasm_module.rbs +42 -0
- data/sig/generated/wardite.rbs +24 -9
- metadata +15 -3
- data/examples/add.wasm +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bbf27d475ac9dac6a9c0f6284bf379858dfef4ee52f3a2d609f41e0a87110b46
|
4
|
+
data.tar.gz: 69d508dc6674117a0c94e8308b357e49a05952f17ac949470c53e8a3267442c2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9d1b5d0ed4b626ab9c34fd0aabedca56b48afa4e9629557e0fcc8d0c7a2e05ad57d674d630c4f4b1599ec1babf70082d2a21041890f6081d4fbe18b8e57c0789
|
7
|
+
data.tar.gz: ae55bd53d03c27a6626e320223389655adcfb67033d99bf9715171eb9bb90c718fab3eacefb2e8d9dd367f7c6d5c986f2bc956741da261d821ce102362b0898e
|
data/Steepfile
CHANGED
data/exe/wardite
CHANGED
@@ -1,16 +1,22 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
3
|
require "wardite"
|
4
|
-
|
5
4
|
path = ARGV[0]
|
6
|
-
method = ARGV[1]
|
7
|
-
args = ARGV[2..-1] || []
|
8
5
|
|
9
6
|
f = File.open(path)
|
10
7
|
instance = Wardite::BinaryLoader::load_from_buffer(f);
|
11
|
-
if
|
12
|
-
|
8
|
+
if instance.runtime.respond_to?(:_start) # assumed WASI
|
9
|
+
argv = ARGV[1..-1] || []
|
10
|
+
instance.wasi.argv = ["wardite"] + argv
|
11
|
+
Bundler.with_original_env do
|
12
|
+
# instance.store.memories[0].grow(128)
|
13
|
+
instance.runtime._start
|
14
|
+
end
|
13
15
|
else
|
16
|
+
path = ARGV[0]
|
17
|
+
method = ARGV[1]
|
18
|
+
args = ARGV[2..-1] || []
|
19
|
+
|
14
20
|
args = args.map do|a|
|
15
21
|
if a.include? "."
|
16
22
|
a.to_f
|
data/lib/wardite/instruction.rb
CHANGED
@@ -46,16 +46,15 @@ module Wardite
|
|
46
46
|
|
47
47
|
# @rbs @@table: Hash[Integer, Symbol] | nil
|
48
48
|
@@table = nil
|
49
|
-
# @rbs @@
|
49
|
+
# @rbs @@fc_table: Hash[Integer, Symbol] | nil
|
50
50
|
@@fc_table = nil
|
51
51
|
|
52
52
|
# @rbs return: Hash[Integer, Symbol]
|
53
53
|
def self.table
|
54
54
|
return @@table if @@table != nil
|
55
|
-
@@table = {}
|
56
|
-
|
57
|
-
|
58
|
-
end
|
55
|
+
@@table = {} #: Hash[Integer, Symbol] | nil
|
56
|
+
SYMS.each_with_index do |sym, i|
|
57
|
+
@@table[i] = sym
|
59
58
|
end
|
60
59
|
@@table
|
61
60
|
end
|
@@ -63,10 +62,9 @@ module Wardite
|
|
63
62
|
# @rbs return: Hash[Integer, Symbol]
|
64
63
|
def self.fc_table
|
65
64
|
return @@fc_table if @@fc_table != nil
|
66
|
-
@@fc_table = {}
|
67
|
-
|
68
|
-
|
69
|
-
end
|
65
|
+
@@fc_table = {} #: Hash[Integer, Symbol] | nil
|
66
|
+
FC_SYMS.each_with_index do |sym, i|
|
67
|
+
@@fc_table[i] = sym
|
70
68
|
end
|
71
69
|
@@fc_table
|
72
70
|
end
|
data/lib/wardite/load.rb
CHANGED
@@ -250,7 +250,7 @@ module Wardite
|
|
250
250
|
# @rbs self.@buf: File|StringIO
|
251
251
|
|
252
252
|
# @rbs buf: File|StringIO
|
253
|
-
# @rbs import_object: Hash[Symbol,
|
253
|
+
# @rbs import_object: Hash[Symbol, wasmModuleSrc]
|
254
254
|
# @rbs enable_wasi: boolish
|
255
255
|
# @rbs return: Instance
|
256
256
|
def self.load_from_buffer(buf, import_object: {}, enable_wasi: true)
|
@@ -259,14 +259,19 @@ module Wardite
|
|
259
259
|
version = preamble
|
260
260
|
sections_ = sections
|
261
261
|
|
262
|
+
wasi_env = nil
|
262
263
|
if enable_wasi
|
264
|
+
require "wardite/wasi"
|
263
265
|
wasi_env = Wardite::WasiSnapshotPreview1.new
|
264
|
-
import_object[:wasi_snapshot_preview1] = wasi_env
|
266
|
+
import_object[:wasi_snapshot_preview1] = wasi_env
|
265
267
|
end
|
266
268
|
|
267
269
|
return Instance.new(import_object) do |i|
|
268
270
|
i.version = version
|
269
271
|
i.sections = sections_
|
272
|
+
if enable_wasi
|
273
|
+
i.wasi = wasi_env
|
274
|
+
end
|
270
275
|
end
|
271
276
|
end
|
272
277
|
|
@@ -358,7 +363,7 @@ module Wardite
|
|
358
363
|
end
|
359
364
|
|
360
365
|
arglen = fetch_uleb128(sbuf)
|
361
|
-
arg = []
|
366
|
+
arg = [] #: Array[Symbol]
|
362
367
|
arglen.times do
|
363
368
|
case ty = assert_read(sbuf, 1)&.ord
|
364
369
|
when 0x7f
|
@@ -376,7 +381,7 @@ module Wardite
|
|
376
381
|
dest.defined_types << arg
|
377
382
|
|
378
383
|
retlen = fetch_uleb128(sbuf)
|
379
|
-
ret = []
|
384
|
+
ret = [] #: Array[Symbol]
|
380
385
|
retlen.times do
|
381
386
|
case ty = assert_read(sbuf, 1)&.ord
|
382
387
|
when 0x7f
|
@@ -482,7 +487,7 @@ module Wardite
|
|
482
487
|
offset = decode_expr(ops)
|
483
488
|
dest.table_offsets << offset
|
484
489
|
|
485
|
-
elms = []
|
490
|
+
elms = [] #: Array[Integer]
|
486
491
|
elen = fetch_uleb128(sbuf)
|
487
492
|
elen.times do |i|
|
488
493
|
index = fetch_uleb128(sbuf)
|
@@ -585,8 +590,8 @@ module Wardite
|
|
585
590
|
$stderr.puts "warning: instruction not ended with inst end(0x0b): 0x0#{last_code.ord}"
|
586
591
|
end
|
587
592
|
cbuf = StringIO.new(code)
|
588
|
-
locals_count = []
|
589
|
-
locals_type = []
|
593
|
+
locals_count = [] #: Array[Integer]
|
594
|
+
locals_type = [] #: Array[Symbol]
|
590
595
|
locals_len = fetch_uleb128(cbuf)
|
591
596
|
locals_len.times do
|
592
597
|
type_count = fetch_uleb128(cbuf)
|
@@ -610,7 +615,7 @@ module Wardite
|
|
610
615
|
# @rbs buf: StringIO
|
611
616
|
# @rbs return: Array[::Wardite::Op]
|
612
617
|
def self.code_body(buf)
|
613
|
-
dest = []
|
618
|
+
dest = [] #: Array[Op]
|
614
619
|
while c = buf.read(1)
|
615
620
|
namespace, code = resolve_code(c, buf)
|
616
621
|
operand_types = Op.operand_of(code)
|
@@ -855,7 +860,7 @@ module Wardite
|
|
855
860
|
# @rbs code: Integer
|
856
861
|
# @rbs return: nil
|
857
862
|
def self.unimplemented_skip_section(code)
|
858
|
-
$stderr.puts "warning: unimplemented section: 0x0#{code}"
|
863
|
+
$stderr.puts "warning: unimplemented section: 0x0#{code}" if ENV['WARN_UNIMPLEMENTED_SECTION']
|
859
864
|
size = fetch_uleb128(@buf)
|
860
865
|
@buf.read(size)
|
861
866
|
nil
|
data/lib/wardite/revisitor.rb
CHANGED
data/lib/wardite/value.rb
CHANGED
@@ -8,20 +8,12 @@ module Wardite
|
|
8
8
|
# @rbs value: Integer
|
9
9
|
# @rbs return: I32
|
10
10
|
def I32(value)
|
11
|
-
|
12
|
-
# $stderr.puts "trace: negative i32 value #{value} is passed, convert to unsigned"
|
13
|
-
value = as_u32(value)
|
14
|
-
end
|
15
|
-
I32.new.tap{|i| i.value = value & I32::I32_MAX }
|
11
|
+
I32.new(value & I32::I32_MAX)
|
16
12
|
end
|
17
13
|
|
18
14
|
# @rbs value: Integer
|
19
15
|
# @rbs return: I64
|
20
16
|
def I64(value)
|
21
|
-
if value < 0
|
22
|
-
# $stderr.puts "trace: negative i64 value #{value} is passed, convert to unsigned"
|
23
|
-
value = as_u64(value)
|
24
|
-
end
|
25
17
|
I64.new.tap{|i| i.value = value & I64::I64_MAX }
|
26
18
|
end
|
27
19
|
|
@@ -36,19 +28,6 @@ module Wardite
|
|
36
28
|
def F64(value)
|
37
29
|
F64.new.tap{|i| i.value = value }
|
38
30
|
end
|
39
|
-
|
40
|
-
private
|
41
|
-
# @rbs value: Integer
|
42
|
-
# @rbs return: Integer
|
43
|
-
def as_u32(value)
|
44
|
-
((-value) ^ I32::I32_MAX) + 1
|
45
|
-
end
|
46
|
-
|
47
|
-
# @rbs value: Integer
|
48
|
-
# @rbs return: Integer
|
49
|
-
def as_u64(value)
|
50
|
-
((-value) ^ I64::I64_MAX) + 1
|
51
|
-
end
|
52
31
|
end
|
53
32
|
|
54
33
|
extend ValueHelper
|
@@ -61,6 +40,11 @@ module Wardite
|
|
61
40
|
# when we want to access signed value, it'd be done via #value_s
|
62
41
|
attr_accessor :value #: Integer
|
63
42
|
|
43
|
+
# @rbs value: Integer
|
44
|
+
def initialize(value=0)
|
45
|
+
@value = value
|
46
|
+
end
|
47
|
+
|
64
48
|
# @rbs str: String
|
65
49
|
# @rbs size: Integer|nil
|
66
50
|
# @rbs signed: bool
|
data/lib/wardite/version.rb
CHANGED
@@ -0,0 +1,129 @@
|
|
1
|
+
# rbs_inline: enabled
|
2
|
+
|
3
|
+
module Wardite
|
4
|
+
module Wasi
|
5
|
+
EACCES = 2
|
6
|
+
EAGAIN = 6
|
7
|
+
EBADF = 8
|
8
|
+
EEXIST = 20
|
9
|
+
EFAULT = 21
|
10
|
+
EINTR = 27
|
11
|
+
EINVAL = 28
|
12
|
+
EIO = 29
|
13
|
+
EISDIR = 31
|
14
|
+
ELOOP = 32
|
15
|
+
ENAMETOOLONG = 37
|
16
|
+
ENOENT = 44
|
17
|
+
ENOSYS = 52
|
18
|
+
ENOTDIR = 54
|
19
|
+
ERANGE = 68
|
20
|
+
ENOTEMPTY = 55
|
21
|
+
ENOTSOCK = 57
|
22
|
+
ENOTSUP = 58
|
23
|
+
EPERM = 63
|
24
|
+
EROFS = 69
|
25
|
+
|
26
|
+
FILETYPE_UNKNOWN = 0
|
27
|
+
FILETYPE_BLOCK_DEVICE = 1 #: Integer
|
28
|
+
FILETYPE_CHARACTER_DEVICE = 2 #: Integer
|
29
|
+
FILETYPE_DIRECTORY = 3 #: Integer
|
30
|
+
FILETYPE_REGULAR_FILE = 4 #: Integer
|
31
|
+
FILETYPE_SOCKET_DGRAM = 5 #: Integer
|
32
|
+
FILETYPE_SOCKET_STREAM = 6 #: Integer
|
33
|
+
FILETYPE_SYMBOLIC_LINK = 7 #: Integer
|
34
|
+
|
35
|
+
FD_APPEND = 1 << 0 #: Integer
|
36
|
+
FD_DSYNC = 1 << 1 #: Integer
|
37
|
+
FD_NONBLOCK = 1 << 2 #: Integer
|
38
|
+
FD_RSYNC = 1 << 3 #: Integer
|
39
|
+
FD_SYNC = 1 << 4 #: Integer
|
40
|
+
|
41
|
+
RIGHT_FD_DATASYNC = 1 << 0
|
42
|
+
RIGHT_FD_READ = 1 << 1
|
43
|
+
RIGHT_FD_SEEK = 1 << 2
|
44
|
+
RIGHT_FDSTAT_SET_FLAGS = 1 << 3
|
45
|
+
RIGHT_FD_SYNC = 1 << 4
|
46
|
+
RIGHT_FD_TELL = 1 << 5
|
47
|
+
RIGHT_FD_WRITE = 1 << 6
|
48
|
+
RIGHT_FD_ADVISE = 1 << 7
|
49
|
+
RIGHT_FD_ALLOCATE = 1 << 8
|
50
|
+
RIGHT_PATH_CREATE_DIRECTORY = 1 << 9
|
51
|
+
RIGHT_PATH_CREATE_FILE = 1 << 10
|
52
|
+
RIGHT_PATH_LINK_SOURCE = 1 << 11
|
53
|
+
RIGHT_PATH_LINK_TARGET = 1 << 12
|
54
|
+
RIGHT_PATH_OPEN = 1 << 13
|
55
|
+
RIGHT_FD_READDIR = 1 << 14
|
56
|
+
RIGHT_PATH_READLINK = 1 << 15
|
57
|
+
RIGHT_PATH_RENAME_SOURCE = 1 << 16
|
58
|
+
RIGHT_PATH_RENAME_TARGET = 1 << 17
|
59
|
+
RIGHT_PATH_FILESTAT_GET = 1 << 18
|
60
|
+
RIGHT_PATH_FILESTAT_SET_SIZE = 1 << 19
|
61
|
+
RIGHT_PATH_FILESTAT_SET_TIMES = 1 << 20
|
62
|
+
RIGHT_FD_FILESTAT_GET = 1 << 21
|
63
|
+
RIGHT_FD_FILESTAT_SET_SIZE = 1 << 22
|
64
|
+
RIGHT_FD_FILESTAT_SET_TIMES = 1 << 23
|
65
|
+
RIGHT_PATH_SYMLINK = 1 << 24
|
66
|
+
RIGHT_PATH_REMOVE_DIRECTORY = 1 << 25
|
67
|
+
RIGHT_PATH_UNLINK_FILE = 1 << 26
|
68
|
+
RIGHT_POLL_FD_READWRITE = 1 << 27
|
69
|
+
RIGHT_SOCK_SHUTDOWN = 1 << 28
|
70
|
+
|
71
|
+
RIGHT_FILE_RIGHT_BASE = RIGHT_FD_DATASYNC |
|
72
|
+
RIGHT_FD_READ |
|
73
|
+
RIGHT_FD_SEEK |
|
74
|
+
RIGHT_FDSTAT_SET_FLAGS |
|
75
|
+
RIGHT_FD_SYNC |
|
76
|
+
RIGHT_FD_TELL |
|
77
|
+
RIGHT_FD_WRITE |
|
78
|
+
RIGHT_FD_ADVISE |
|
79
|
+
RIGHT_FD_ALLOCATE |
|
80
|
+
RIGHT_FD_FILESTAT_GET |
|
81
|
+
RIGHT_FD_FILESTAT_SET_SIZE |
|
82
|
+
RIGHT_FD_FILESTAT_SET_TIMES |
|
83
|
+
RIGHT_POLL_FD_READWRITE
|
84
|
+
|
85
|
+
RIGHT_DIR_RIGHT_BASE = RIGHT_FD_DATASYNC |
|
86
|
+
RIGHT_FDSTAT_SET_FLAGS |
|
87
|
+
RIGHT_FD_SYNC |
|
88
|
+
RIGHT_PATH_CREATE_DIRECTORY |
|
89
|
+
RIGHT_PATH_CREATE_FILE |
|
90
|
+
RIGHT_PATH_LINK_SOURCE |
|
91
|
+
RIGHT_PATH_LINK_TARGET |
|
92
|
+
RIGHT_PATH_OPEN |
|
93
|
+
RIGHT_FD_READDIR |
|
94
|
+
RIGHT_PATH_READLINK |
|
95
|
+
RIGHT_PATH_RENAME_SOURCE |
|
96
|
+
RIGHT_PATH_RENAME_TARGET |
|
97
|
+
RIGHT_PATH_FILESTAT_GET |
|
98
|
+
RIGHT_PATH_FILESTAT_SET_SIZE |
|
99
|
+
RIGHT_PATH_FILESTAT_SET_TIMES |
|
100
|
+
RIGHT_FD_FILESTAT_GET |
|
101
|
+
RIGHT_FD_FILESTAT_SET_TIMES |
|
102
|
+
RIGHT_PATH_SYMLINK |
|
103
|
+
RIGHT_PATH_REMOVE_DIRECTORY |
|
104
|
+
RIGHT_PATH_UNLINK_FILE
|
105
|
+
|
106
|
+
# @rbs mode_str: String
|
107
|
+
# @rbs return: Integer
|
108
|
+
def self.to_ftype(mode_str)
|
109
|
+
case mode_str
|
110
|
+
when "file"
|
111
|
+
FILETYPE_REGULAR_FILE
|
112
|
+
when "directory"
|
113
|
+
FILETYPE_DIRECTORY
|
114
|
+
when "characterSpecial"
|
115
|
+
FILETYPE_CHARACTER_DEVICE
|
116
|
+
when "blockSpecial"
|
117
|
+
FILETYPE_BLOCK_DEVICE
|
118
|
+
when "fifo"
|
119
|
+
FILETYPE_UNKNOWN
|
120
|
+
when "link"
|
121
|
+
FILETYPE_SYMBOLIC_LINK
|
122
|
+
when "socket"
|
123
|
+
FILETYPE_SOCKET_STREAM # TODO: check UDP
|
124
|
+
else
|
125
|
+
FILETYPE_UNKNOWN
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
data/lib/wardite/wasi.rb
CHANGED
@@ -1,16 +1,161 @@
|
|
1
1
|
# rbs_inline: enabled
|
2
|
+
|
3
|
+
require "wardite/wasm_module"
|
4
|
+
require "wardite/wasi/consts"
|
5
|
+
require "securerandom"
|
6
|
+
require "fcntl"
|
7
|
+
|
2
8
|
module Wardite
|
3
9
|
class WasiSnapshotPreview1
|
4
10
|
include ValueHelper
|
11
|
+
include WasmModule
|
5
12
|
|
6
|
-
attr_accessor :fd_table #: Array[IO]
|
13
|
+
attr_accessor :fd_table #: Array[(IO|File)]
|
14
|
+
attr_accessor :argv #: Array[String]
|
7
15
|
|
8
|
-
|
16
|
+
# @rbs argv: Array[String]
|
17
|
+
# @rbs return: void
|
18
|
+
def initialize(argv: [])
|
9
19
|
@fd_table = [
|
10
20
|
STDIN,
|
11
21
|
STDOUT,
|
12
22
|
STDERR,
|
13
23
|
]
|
24
|
+
@argv = argv
|
25
|
+
end
|
26
|
+
|
27
|
+
# @rbs store: Store
|
28
|
+
# @rbs args: Array[wasmValue]
|
29
|
+
# @rbs return: Object
|
30
|
+
def args_get(store, args)
|
31
|
+
arg_offsets_p = args[0].value
|
32
|
+
arg_data_buf_p = args[1].value
|
33
|
+
if !arg_data_buf_p.is_a?(Integer)
|
34
|
+
raise ArgumentError, "invalid type of args: #{args.inspect}"
|
35
|
+
end
|
36
|
+
|
37
|
+
arg_offsets = [] #: Array[Integer]
|
38
|
+
arg_data_slice = [] #: Array[String]
|
39
|
+
current_offset = arg_data_buf_p
|
40
|
+
@argv.each do |arg|
|
41
|
+
arg_offsets << current_offset
|
42
|
+
arg_data_slice << arg
|
43
|
+
current_offset += arg.size + 1
|
44
|
+
end
|
45
|
+
arg_data = arg_data_slice.join("\0") + "\0"
|
46
|
+
|
47
|
+
memory = store.memories[0]
|
48
|
+
memory.data[arg_data_buf_p...(arg_data_buf_p + arg_data.size)] = arg_data
|
49
|
+
|
50
|
+
arg_offsets.each_with_index do |offset, i|
|
51
|
+
data_begin = arg_offsets_p + i * 4
|
52
|
+
memory.data[data_begin...(data_begin + 4)] = [offset].pack("I!")
|
53
|
+
end
|
54
|
+
|
55
|
+
0
|
56
|
+
end
|
57
|
+
|
58
|
+
# @rbs store: Store
|
59
|
+
# @rbs args: Array[wasmValue]
|
60
|
+
# @rbs return: Object
|
61
|
+
def args_sizes_get(store, args)
|
62
|
+
argc_p = args[0].value
|
63
|
+
arglen_p = args[1].value
|
64
|
+
argc = @argv.length
|
65
|
+
arglen = @argv.map{|arg| arg.size + 1}.sum
|
66
|
+
|
67
|
+
memory = store.memories[0]
|
68
|
+
memory.data[argc_p...(argc_p+4)] = [argc].pack("I!")
|
69
|
+
memory.data[arglen_p...(arglen_p+4)] = [arglen].pack("I!")
|
70
|
+
0
|
71
|
+
end
|
72
|
+
|
73
|
+
# @rbs store: Store
|
74
|
+
# @rbs args: Array[wasmValue]
|
75
|
+
# @rbs return: Object
|
76
|
+
def environ_sizes_get(store, args)
|
77
|
+
envc_p = args[0].value
|
78
|
+
envlen_p = args[1].value
|
79
|
+
envc = ENV.length
|
80
|
+
envlen = ENV.map{|k,v| k.size + v.size + 1}.sum
|
81
|
+
|
82
|
+
memory = store.memories[0]
|
83
|
+
memory.data[envc_p...(envc_p+4)] = [envc].pack("I!")
|
84
|
+
memory.data[envlen_p...(envlen_p+4)] = [envlen].pack("I!")
|
85
|
+
0
|
86
|
+
end
|
87
|
+
|
88
|
+
# @rbs store: Store
|
89
|
+
# @rbs args: Array[wasmValue]
|
90
|
+
# @rbs return: Object
|
91
|
+
def environ_get(store, args)
|
92
|
+
environ_offsets_p = args[0].value
|
93
|
+
environ_data_buf_p = args[1].value
|
94
|
+
if !environ_data_buf_p.is_a?(Integer)
|
95
|
+
raise ArgumentError, "invalid type of args: #{args.inspect}"
|
96
|
+
end
|
97
|
+
|
98
|
+
environ_offsets = [] #: Array[Integer]
|
99
|
+
environ_data_slice = [] #: Array[String]
|
100
|
+
current_offset = environ_data_buf_p
|
101
|
+
ENV.each do |k, v|
|
102
|
+
environ_offsets << current_offset
|
103
|
+
environ_data_slice << "#{k}=#{v}"
|
104
|
+
current_offset += "#{k}=#{v}".size + 1
|
105
|
+
end
|
106
|
+
environ_data = environ_data_slice.join("\0") + "\0"
|
107
|
+
|
108
|
+
memory = store.memories[0]
|
109
|
+
memory.data[environ_data_buf_p...(environ_data_buf_p + environ_data.size)] = environ_data
|
110
|
+
|
111
|
+
environ_offsets.each_with_index do |offset, i|
|
112
|
+
data_begin = environ_offsets_p + i * 4
|
113
|
+
memory.data[data_begin...(data_begin + 4)] = [offset].pack("I!")
|
114
|
+
end
|
115
|
+
|
116
|
+
0
|
117
|
+
end
|
118
|
+
|
119
|
+
# @rbs store: Store
|
120
|
+
# @rbs args: Array[wasmValue]
|
121
|
+
# @rbs return: Object
|
122
|
+
def clock_time_get(store, args)
|
123
|
+
clock_id = args[0].value
|
124
|
+
# we dont use precision...
|
125
|
+
_precision = args[1].value
|
126
|
+
timebuf64 = args[2].value
|
127
|
+
if clock_id != 0 # - CLOCKID_REALTIME
|
128
|
+
# raise NotImplementedError, "CLOCKID_REALTIME is an only supported id"
|
129
|
+
return -255
|
130
|
+
end
|
131
|
+
# timestamp in nanoseconds
|
132
|
+
now = Time.now.to_i * 1_000_000
|
133
|
+
|
134
|
+
memory = store.memories[0]
|
135
|
+
now_packed = [now].pack("Q!")
|
136
|
+
memory.data[timebuf64...(timebuf64+8)] = now_packed
|
137
|
+
0
|
138
|
+
end
|
139
|
+
|
140
|
+
# @rbs store: Store
|
141
|
+
# @rbs args: Array[wasmValue]
|
142
|
+
# @rbs return: Object
|
143
|
+
def fd_prestat_get(store, args)
|
144
|
+
fd = args[0].value.to_i
|
145
|
+
prestat_offset = args[1].value.to_i
|
146
|
+
if fd >= @fd_table.size
|
147
|
+
return Wasi::EBADF
|
148
|
+
end
|
149
|
+
file = @fd_table[fd]
|
150
|
+
if !file.is_a?(File)
|
151
|
+
return Wasi::EBADF
|
152
|
+
end
|
153
|
+
name = file.path
|
154
|
+
memory = store.memories[0]
|
155
|
+
# Zero-value 8-bit tag, and 3-byte zero-value padding
|
156
|
+
memory.data[prestat_offset...(prestat_offset+4)] = [0].pack("I!")
|
157
|
+
memory.data[(prestat_offset+4)...(prestat_offset+8)] = [name.size].pack("I!")
|
158
|
+
0
|
14
159
|
end
|
15
160
|
|
16
161
|
# @rbs store: Store
|
@@ -29,6 +174,7 @@ module Wardite
|
|
29
174
|
raise Wardite::ArgumentError, "args too short"
|
30
175
|
end
|
31
176
|
file = self.fd_table[fd]
|
177
|
+
return Wasi::EBADF if !file
|
32
178
|
memory = store.memories[0]
|
33
179
|
nwritten = 0
|
34
180
|
iovs_len.times do
|
@@ -45,11 +191,126 @@ module Wardite
|
|
45
191
|
0
|
46
192
|
end
|
47
193
|
|
48
|
-
# @rbs
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
194
|
+
# @rbs store: Store
|
195
|
+
# @rbs args: Array[wasmValue]
|
196
|
+
# @rbs return: Object
|
197
|
+
def fd_read(store, args)
|
198
|
+
iargs = args.map do |elm|
|
199
|
+
if elm.is_a?(I32)
|
200
|
+
elm.value
|
201
|
+
else
|
202
|
+
raise Wardite::ArgumentError, "invalid type of args: #{args.inspect}"
|
203
|
+
end
|
204
|
+
end #: Array[Integer]
|
205
|
+
fd, iovs, iovs_len, rp = *iargs
|
206
|
+
if !fd || !iovs || !iovs_len || !rp
|
207
|
+
raise Wardite::ArgumentError, "args too short"
|
208
|
+
end
|
209
|
+
file = self.fd_table[fd]
|
210
|
+
return Wasi::EBADF if !file
|
211
|
+
memory = store.memories[0]
|
212
|
+
nread = 0
|
213
|
+
|
214
|
+
iovs_len.times do
|
215
|
+
start = unpack_le_int(memory.data[iovs...(iovs+4)])
|
216
|
+
iovs += 4
|
217
|
+
slen = unpack_le_int(memory.data[iovs...(iovs+4)])
|
218
|
+
iovs += 4
|
219
|
+
buf = file.read(slen)
|
220
|
+
if !buf
|
221
|
+
return Wasi::EFAULT
|
222
|
+
end
|
223
|
+
memory.data[start...(start+slen)] = buf
|
224
|
+
nread += slen
|
225
|
+
end
|
226
|
+
|
227
|
+
memory.data[rp...(rp+4)] = [nread].pack("I!")
|
228
|
+
0
|
229
|
+
end
|
230
|
+
|
231
|
+
# @rbs store: Store
|
232
|
+
# @rbs args: Array[wasmValue]
|
233
|
+
# @rbs return: Object
|
234
|
+
def fd_fdstat_get(store, args)
|
235
|
+
fd = args[0].value.to_i
|
236
|
+
fdstat_offset = args[1].value.to_i
|
237
|
+
if fd >= @fd_table.size
|
238
|
+
return Wasi::EBADF
|
239
|
+
end
|
240
|
+
file = @fd_table[fd]
|
241
|
+
fdflags = 0
|
242
|
+
if file.is_a?(IO)
|
243
|
+
fdflags |= Wasi::FD_APPEND
|
244
|
+
else
|
245
|
+
if (Fcntl::O_APPEND & file.fcntl(Fcntl::F_GETFL, 0)) != 0
|
246
|
+
fdflags |= Wasi::FD_APPEND
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
if (Fcntl::O_NONBLOCK & file.fcntl(Fcntl::F_GETFL, 0)) != 0
|
251
|
+
fdflags |= Wasi::FD_NONBLOCK
|
252
|
+
end
|
253
|
+
|
254
|
+
stat = file.stat #: File::Stat
|
255
|
+
ftype = Wasi.to_ftype(stat.ftype)
|
256
|
+
|
257
|
+
fs_right_base = 0
|
258
|
+
fs_right_inheriting = 0
|
259
|
+
|
260
|
+
case ftype
|
261
|
+
when Wasi::FILETYPE_DIRECTORY
|
262
|
+
fs_right_base = Wasi::RIGHT_DIR_RIGHT_BASE
|
263
|
+
fs_right_inheriting = Wasi::RIGHT_FILE_RIGHT_BASE | Wasi::RIGHT_DIR_RIGHT_BASE
|
264
|
+
when Wasi::FILETYPE_CHARACTER_DEVICE
|
265
|
+
fs_right_base = Wasi::RIGHT_FILE_RIGHT_BASE & \
|
266
|
+
(~Wasi::RIGHT_FD_SEEK) & (~Wasi::RIGHT_FD_TELL)
|
267
|
+
else
|
268
|
+
fs_right_base = Wasi::RIGHT_FILE_RIGHT_BASE
|
269
|
+
end
|
270
|
+
|
271
|
+
memory = store.memories[0]
|
272
|
+
|
273
|
+
binformat = [fdflags, ftype, 0, 0, 0, 0, fs_right_base, fs_right_inheriting]
|
274
|
+
.pack("SSC4QQ")
|
275
|
+
memory.data[fdstat_offset...(fdstat_offset+binformat.size)] = binformat
|
276
|
+
0
|
277
|
+
end
|
278
|
+
|
279
|
+
# @rbs store: Store
|
280
|
+
# @rbs args: Array[wasmValue]
|
281
|
+
# @rbs return: Object
|
282
|
+
def fd_filestat_get(store, args)
|
283
|
+
fd = args[0].value.to_i
|
284
|
+
filestat_offset = args[1].value.to_i
|
285
|
+
if fd >= @fd_table.size
|
286
|
+
return Wasi::EBADF
|
287
|
+
end
|
288
|
+
file = @fd_table[fd]
|
289
|
+
stat = file.stat #: File::Stat
|
290
|
+
memory = store.memories[0]
|
291
|
+
binformat = [stat.dev, stat.ino, Wasi.to_ftype(stat.ftype), stat.nlink, stat.size, stat.atime.to_i, stat.mtime.to_i, stat.ctime.to_i].pack("Q8")
|
292
|
+
memory.data[filestat_offset...(filestat_offset+binformat.size)] = binformat
|
293
|
+
0
|
294
|
+
end
|
295
|
+
|
296
|
+
# @rbs store: Store
|
297
|
+
# @rbs args: Array[wasmValue]
|
298
|
+
# @rbs return: Object
|
299
|
+
def proc_exit(store, args)
|
300
|
+
exit_code = args[0].value
|
301
|
+
exit(exit_code)
|
302
|
+
end
|
303
|
+
|
304
|
+
# @rbs store: Store
|
305
|
+
# @rbs args: Array[wasmValue]
|
306
|
+
# @rbs return: Object
|
307
|
+
def random_get(store, args)
|
308
|
+
buf = args[0].value.to_i
|
309
|
+
buflen = args[1].value.to_i
|
310
|
+
randoms = SecureRandom.random_bytes(buflen) #: String
|
311
|
+
memory = store.memories[0]
|
312
|
+
memory.data[buf...(buf+buflen)] = randoms
|
313
|
+
0
|
53
314
|
end
|
54
315
|
|
55
316
|
private
|