123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965 |
- /*
- * Copyright (c) 2023, Ali Mohammad Pur <mpfard@serenityos.org>
- *
- * SPDX-License-Identifier: BSD-2-Clause
- */
- #pragma once
- #include <AK/DistinctNumeric.h>
- #include <AK/Endian.h>
- #include <AK/Function.h>
- #include <AK/LexicalPath.h>
- #include <AK/RedBlackTree.h>
- #include <AK/String.h>
- #include <AK/Vector.h>
- #include <LibWasm/AbstractMachine/AbstractMachine.h>
- #include <LibWasm/Forward.h>
- namespace Wasm::Wasi::ABI {
- // NOTE: The "real" ABI used in the wild is described by [api.h from libc-bottom-half](https://github.com/WebAssembly/wasi-libc/blob/2c2fc9a2fddd0927a66f1c142e65c8dab6f5c5d7/libc-bottom-half/headers/public/wasi/api.h)
- // This is *not* the same ABI as the one described in the WASI spec, nor is it the same ABI as api.h on wasi-libc/master.
- // The highlights of the ABI are:
- // - (most) structs are passed as pointers to heap.
- // - arrays are fat pointers splat across two arguments
- // - return object locations are also passed as arguments, the number of arguments depends on the return type itself:
- // - ArgsSizes / EnvironSizes / the return type of sock_recv use two arguments
- // - everything else is passed like a normal struct
- template<auto impl>
- struct InvocationOf {
- HostFunction operator()(Implementation&, StringView name);
- };
- template<typename T, size_t N>
- void serialize(T const&, Array<Bytes, N>);
- template<typename T, size_t N>
- T deserialize(Array<ReadonlyBytes, N> const&);
- template<typename T>
- struct ToCompatibleValue {
- using Type = void;
- };
- template<typename T>
- struct CompatibleValue {
- typename ToCompatibleValue<T>::Type value;
- Wasm::Value to_wasm_value() const;
- };
- template<typename T>
- CompatibleValue<T> to_compatible_value(Wasm::Value const&);
- template<typename T>
- T deserialize(CompatibleValue<T> const&);
- }
- namespace Wasm::Wasi {
- // NOTE: This is a copy of LittleEndian from Endian.h,
- // we can't use those because they have a packed attribute, and depend on it;
- // but we want proper alignment on these types.
- template<typename T>
- class alignas(T) LittleEndian {
- public:
- constexpr LittleEndian() = default;
- constexpr LittleEndian(T value)
- : m_value(AK::convert_between_host_and_little_endian(value))
- {
- }
- constexpr operator T() const { return AK::convert_between_host_and_little_endian(m_value); }
- constexpr T value() const { return AK::convert_between_host_and_little_endian(m_value); }
- LittleEndian& operator+=(T other)
- {
- m_value = AK::convert_between_host_and_little_endian(AK::convert_between_host_and_little_endian(m_value) + other);
- return *this;
- }
- // This returns the internal representation. In this case, that is the value stored in little endian format.
- constexpr Bytes bytes() { return Bytes { &m_value, sizeof(m_value) }; }
- constexpr ReadonlyBytes bytes() const { return ReadonlyBytes { &m_value, sizeof(m_value) }; }
- void serialize_into(Array<Bytes, 1> bytes) const;
- static LittleEndian read_from(Array<ReadonlyBytes, 1> const& bytes);
- private:
- T m_value { 0 };
- };
- using Size = LittleEndian<u32>;
- using FileSize = LittleEndian<u64>;
- using Timestamp = LittleEndian<u64>;
- namespace Detail {
- template<typename>
- struct __Pointer_tag;
- template<typename>
- struct __ConstPointer_tag;
- }
- // NOTE: Might need to be updated if WASI ever supports memory64.
- using UnderlyingPointerType = u32;
- template<typename T>
- using Pointer = DistinctNumeric<LittleEndian<UnderlyingPointerType>, Detail::__Pointer_tag<T>, AK::DistinctNumericFeature::Comparison>;
- template<typename T>
- using ConstPointer = DistinctNumeric<LittleEndian<UnderlyingPointerType>, Detail::__ConstPointer_tag<T>, AK::DistinctNumericFeature::Comparison>;
- // https://github.com/WebAssembly/wasi-libc/blob/2c2fc9a2fddd0927a66f1c142e65c8dab6f5c5d7/libc-bottom-half/headers/public/wasi/api.h#L70
- enum class ClockID : u32 {
- Realtime,
- Monotonic,
- ProcessCPUTimeID,
- ThreadCPUTimeID,
- };
- // https://github.com/WebAssembly/wasi-libc/blob/2c2fc9a2fddd0927a66f1c142e65c8dab6f5c5d7/libc-bottom-half/headers/public/wasi/api.h#L105
- enum class Errno : u16 {
- Success,
- TooBig,
- Access,
- AddressInUse,
- AddressNotAvailable,
- AFNotSupported,
- Again,
- Already,
- BadF,
- BadMessage,
- Busy,
- Canceled,
- Child,
- ConnectionAborted,
- ConnectionRefused,
- ConnectionReset,
- Deadlock,
- DestinationAddressRequired,
- Domain,
- DQuot, // Reserved, Unused.
- Exist,
- Fault,
- FBig,
- HostUnreachable,
- IdentifierRemoved,
- IllegalSequence,
- InProgress,
- Interrupted,
- Invalid,
- IO,
- IsConnected,
- IsDirectory,
- Loop,
- MFile,
- MLink,
- MessageSize,
- MultiHop, // Reserved, Unused.
- NameTooLong,
- NetworkDown,
- NetworkReset,
- NetworkUnreachable,
- NFile,
- NoBufferSpace,
- NoDevice,
- NoEntry,
- NoExec,
- NoLock,
- NoLink,
- NoMemory,
- NoMessage,
- NoProtocolOption,
- NoSpace,
- NoSys,
- NotConnected,
- NotDirectory,
- NotEmpty,
- NotRecoverable,
- NotSocket,
- NotSupported,
- NoTTY,
- NXIO,
- Overflow,
- OwnerDead,
- Permission,
- Pipe,
- Protocol,
- ProtocolNotSupported,
- ProtocolType,
- Range,
- ReadOnlyFS,
- SPipe,
- SRCH,
- Stale,
- TimedOut,
- TextBusy,
- XDev,
- NotCapable,
- };
- // https://github.com/WebAssembly/wasi-libc/blob/2c2fc9a2fddd0927a66f1c142e65c8dab6f5c5d7/libc-bottom-half/headers/public/wasi/api.h#L498
- struct Rights {
- using CompatibleType = u64;
- struct Bits {
- bool fd_datasync : 1;
- bool fd_read : 1;
- bool fd_seek : 1;
- bool fd_fdstat_set_flags : 1;
- bool fd_sync : 1;
- bool fd_tell : 1;
- bool fd_write : 1;
- bool fd_advise : 1;
- bool fd_allocate : 1;
- bool path_create_directory : 1;
- bool path_create_file : 1;
- bool path_link_source : 1;
- bool path_link_target : 1;
- bool path_open : 1;
- bool fd_readdir : 1;
- bool path_readlink : 1;
- bool path_rename_source : 1;
- bool path_rename_target : 1;
- bool path_filestat_get : 1;
- bool path_filestat_set_size : 1;
- bool path_filestat_set_times : 1;
- bool fd_filestat_get : 1;
- bool fd_filestat_set_size : 1;
- bool fd_filestat_set_times : 1;
- bool path_symlink : 1;
- bool path_remove_directory : 1;
- bool path_unlink_file : 1;
- bool poll_fd_readwrite : 1;
- bool sock_shutdown : 1;
- bool sock_accept : 1;
- u8 _unused1 : 2;
- u32 _unused2 : 32;
- };
- static_assert(sizeof(Bits) == sizeof(CompatibleType));
- union {
- Bits bits;
- LittleEndian<CompatibleType> data;
- };
- void serialize_into(Array<Bytes, 1> bytes) const;
- static Rights read_from(Array<ReadonlyBytes, 1> const& bytes);
- };
- // https://github.com/WebAssembly/wasi-libc/blob/2c2fc9a2fddd0927a66f1c142e65c8dab6f5c5d7/libc-bottom-half/headers/public/wasi/api.h#L663
- using FD = DistinctNumeric<LittleEndian<u32>, struct __FD_tag, AK::DistinctNumericFeature::Comparison>;
- // https://github.com/WebAssembly/wasi-libc/blob/2c2fc9a2fddd0927a66f1c142e65c8dab6f5c5d7/libc-bottom-half/headers/public/wasi/api.h#L671
- struct IOVec {
- Pointer<u8> buf;
- Size buf_len;
- static IOVec read_from(Array<ReadonlyBytes, 1> const& bytes);
- };
- // https://github.com/WebAssembly/wasi-libc/blob/2c2fc9a2fddd0927a66f1c142e65c8dab6f5c5d7/libc-bottom-half/headers/public/wasi/api.h#L692
- struct CIOVec {
- ConstPointer<u8> buf;
- Size buf_len;
- static CIOVec read_from(Array<ReadonlyBytes, 1> const& bytes);
- };
- // https://github.com/WebAssembly/wasi-libc/blob/2c2fc9a2fddd0927a66f1c142e65c8dab6f5c5d7/libc-bottom-half/headers/public/wasi/api.h#L713
- using FileDelta = LittleEndian<i64>;
- // https://github.com/WebAssembly/wasi-libc/blob/2c2fc9a2fddd0927a66f1c142e65c8dab6f5c5d7/libc-bottom-half/headers/public/wasi/api.h#L721
- enum class Whence : u8 {
- Set,
- Cur,
- End,
- };
- // https://github.com/WebAssembly/wasi-libc/blob/2c2fc9a2fddd0927a66f1c142e65c8dab6f5c5d7/libc-bottom-half/headers/public/wasi/api.h#L746
- using DirCookie = LittleEndian<u64>;
- // https://github.com/WebAssembly/wasi-libc/blob/2c2fc9a2fddd0927a66f1c142e65c8dab6f5c5d7/libc-bottom-half/headers/public/wasi/api.h#L754
- using DirNameLen = LittleEndian<u32>;
- // https://github.com/WebAssembly/wasi-libc/blob/2c2fc9a2fddd0927a66f1c142e65c8dab6f5c5d7/libc-bottom-half/headers/public/wasi/api.h#L762
- using INode = LittleEndian<u64>;
- // https://github.com/WebAssembly/wasi-libc/blob/2c2fc9a2fddd0927a66f1c142e65c8dab6f5c5d7/libc-bottom-half/headers/public/wasi/api.h#L770
- enum class FileType : u8 {
- Unknown,
- BlockDevice,
- CharacterDevice,
- Directory,
- RegularFile,
- SocketDGram,
- SocketStream,
- SymbolicLink,
- };
- // https://github.com/WebAssembly/wasi-libc/blob/2c2fc9a2fddd0927a66f1c142e65c8dab6f5c5d7/libc-bottom-half/headers/public/wasi/api.h#L818
- struct DirEnt {
- DirCookie d_next;
- INode d_ino;
- DirNameLen d_namlen;
- FileType d_type;
- u8 _padding[3] { 0 }; // Not part of the API, but the struct is required to be 24 bytes - even though it has no explicit padding.
- };
- static_assert(sizeof(DirEnt) == 24);
- // https://github.com/WebAssembly/wasi-libc/blob/2c2fc9a2fddd0927a66f1c142e65c8dab6f5c5d7/libc-bottom-half/headers/public/wasi/api.h#L851
- enum class Advice : u8 {
- Normal,
- Sequential,
- Random,
- WillNeed,
- DontNeed,
- NoReuse,
- };
- // https://github.com/WebAssembly/wasi-libc/blob/2c2fc9a2fddd0927a66f1c142e65c8dab6f5c5d7/libc-bottom-half/headers/public/wasi/api.h#L889
- struct FDFlags {
- using CompatibleType = u16;
- struct Bits {
- bool append : 1;
- bool dsync : 1;
- bool nonblock : 1;
- bool rsync : 1;
- bool sync : 1;
- u8 _unused1 : 3;
- u8 _unused2 : 8;
- };
- static_assert(sizeof(Bits) == sizeof(CompatibleType));
- union {
- Bits bits;
- LittleEndian<CompatibleType> data;
- };
- void serialize_into(Array<Bytes, 1> bytes) const;
- static FDFlags read_from(Array<ReadonlyBytes, 1> const& bytes);
- };
- // https://github.com/WebAssembly/wasi-libc/blob/2c2fc9a2fddd0927a66f1c142e65c8dab6f5c5d7/libc-bottom-half/headers/public/wasi/api.h#L924
- struct FDStat {
- FileType fs_filetype;
- u8 _padding1 { 0 }; // Not part of the API.
- FDFlags fs_flags;
- u8 _padding2[4] { 0 }; // Not part of the API.
- Rights fs_rights_base;
- Rights fs_rights_inheriting;
- void serialize_into(Array<Bytes, 1> bytes) const;
- };
- static_assert(sizeof(FDStat) == 24);
- // https://github.com/WebAssembly/wasi-libc/blob/2c2fc9a2fddd0927a66f1c142e65c8dab6f5c5d7/libc-bottom-half/headers/public/wasi/api.h#L959
- using Device = LittleEndian<u64>;
- // https://github.com/WebAssembly/wasi-libc/blob/2c2fc9a2fddd0927a66f1c142e65c8dab6f5c5d7/libc-bottom-half/headers/public/wasi/api.h#L967
- struct FSTFlags {
- using CompatibleType = u16;
- struct Bits {
- bool atim : 1;
- bool atim_now : 1;
- bool mtim : 1;
- bool mtim_now : 1;
- u8 _unused1 : 4;
- u8 _unused2 : 8;
- };
- static_assert(sizeof(Bits) == sizeof(CompatibleType));
- union {
- Bits bits;
- LittleEndian<CompatibleType> data;
- };
- void serialize_into(Array<Bytes, 1> bytes) const;
- static FSTFlags read_from(Array<ReadonlyBytes, 1> const& bytes);
- };
- static_assert(sizeof(FSTFlags) == 2);
- // https://github.com/WebAssembly/wasi-libc/blob/2c2fc9a2fddd0927a66f1c142e65c8dab6f5c5d7/libc-bottom-half/headers/public/wasi/api.h#L995
- struct LookupFlags {
- using CompatibleType = u32;
- struct Bits {
- bool symlink_follow : 1;
- u8 _unused1 : 7;
- u8 _unused2 : 8;
- u16 _unused3 : 16;
- };
- static_assert(sizeof(Bits) == sizeof(CompatibleType));
- union {
- Bits bits;
- LittleEndian<CompatibleType> data;
- };
- void serialize_into(Array<Bytes, 1> bytes) const;
- static LookupFlags read_from(Array<ReadonlyBytes, 1> const& bytes);
- };
- static_assert(sizeof(LookupFlags) == 4);
- // https://github.com/WebAssembly/wasi-libc/blob/2c2fc9a2fddd0927a66f1c142e65c8dab6f5c5d7/libc-bottom-half/headers/public/wasi/api.h#L1008
- struct OFlags {
- using CompatibleType = u16;
- struct Bits {
- bool creat : 1;
- bool directory : 1;
- bool excl : 1;
- bool trunc : 1;
- u8 _unused1 : 4;
- u8 _unused2 : 8;
- };
- static_assert(sizeof(Bits) == sizeof(CompatibleType));
- union {
- Bits bits;
- LittleEndian<CompatibleType> data;
- };
- static OFlags read_from(Array<ReadonlyBytes, 1> const& bytes);
- };
- static_assert(sizeof(OFlags) == 2);
- // https://github.com/WebAssembly/wasi-libc/blob/2c2fc9a2fddd0927a66f1c142e65c8dab6f5c5d7/libc-bottom-half/headers/public/wasi/api.h#L1036
- using LinkCount = LittleEndian<u64>;
- // https://github.com/WebAssembly/wasi-libc/blob/2c2fc9a2fddd0927a66f1c142e65c8dab6f5c5d7/libc-bottom-half/headers/public/wasi/api.h#L1044
- struct FileStat {
- Device dev;
- INode ino;
- FileType filetype;
- u8 _padding1[7] { 0 }; // Not part of the API.
- LinkCount nlink;
- FileSize size;
- Timestamp atim;
- Timestamp mtim;
- Timestamp ctim;
- void serialize_into(Array<Bytes, 1> bytes) const;
- };
- static_assert(sizeof(FileStat) == 64);
- // https://github.com/WebAssembly/wasi-libc/blob/2c2fc9a2fddd0927a66f1c142e65c8dab6f5c5d7/libc-bottom-half/headers/public/wasi/api.h#L1102
- using UserData = LittleEndian<u64>;
- // https://github.com/WebAssembly/wasi-libc/blob/2c2fc9a2fddd0927a66f1c142e65c8dab6f5c5d7/libc-bottom-half/headers/public/wasi/api.h#L1110
- enum class EventType : u8 {
- Clock,
- FDRead,
- FDWrite,
- };
- // https://github.com/WebAssembly/wasi-libc/blob/2c2fc9a2fddd0927a66f1c142e65c8dab6f5c5d7/libc-bottom-half/headers/public/wasi/api.h#L1137
- struct EventRWFlags {
- using CompatibleType = u16;
- struct Bits {
- bool fd_readwrite_hangup : 1;
- u8 _unused1 : 7;
- u8 _unused2 : 8;
- };
- static_assert(sizeof(Bits) == sizeof(CompatibleType));
- union {
- Bits bits;
- LittleEndian<CompatibleType> data;
- };
- void serialize_into(Array<Bytes, 1> bytes) const;
- static EventRWFlags read_from(Array<ReadonlyBytes, 1> const& bytes);
- };
- // https://github.com/WebAssembly/wasi-libc/blob/2c2fc9a2fddd0927a66f1c142e65c8dab6f5c5d7/libc-bottom-half/headers/public/wasi/api.h#L1151
- struct EventFDReadWrite {
- FileSize nbytes;
- u8 _padding[4] { 0 }; // Not part of the API.
- EventRWFlags flags;
- void serialize_into(Array<Bytes, 1> bytes) const;
- static EventFDReadWrite read_from(Array<ReadonlyBytes, 1> const& bytes);
- };
- static_assert(sizeof(EventFDReadWrite) == 16);
- // https://github.com/WebAssembly/wasi-libc/blob/2c2fc9a2fddd0927a66f1c142e65c8dab6f5c5d7/libc-bottom-half/headers/public/wasi/api.h#L1186
- struct Event {
- UserData userdata;
- Errno errno_;
- EventType type;
- u8 _padding[5] { 0 }; // Not part of the API.
- EventFDReadWrite fd_readwrite;
- void serialize_into(Array<Bytes, 1> bytes) const;
- static Event read_from(Array<ReadonlyBytes, 1> const& bytes);
- };
- static_assert(sizeof(Event) == 32);
- // https://github.com/WebAssembly/wasi-libc/blob/2c2fc9a2fddd0927a66f1c142e65c8dab6f5c5d7/libc-bottom-half/headers/public/wasi/api.h#L1220
- struct SubClockFlags {
- using CompatibleType = u16;
- struct Bits {
- bool subscription_clock_abstime : 1;
- u8 _unused1 : 7;
- u8 _unused2 : 8;
- };
- static_assert(sizeof(Bits) == sizeof(CompatibleType));
- union {
- Bits bits;
- LittleEndian<CompatibleType> data;
- };
- void serialize_into(Array<Bytes, 1> bytes) const;
- static SubClockFlags read_from(Array<ReadonlyBytes, 1> const& bytes);
- };
- // https://github.com/WebAssembly/wasi-libc/blob/2c2fc9a2fddd0927a66f1c142e65c8dab6f5c5d7/libc-bottom-half/headers/public/wasi/api.h#L1237
- struct SubscriptionClock {
- ClockID id;
- u8 _padding1[4] { 0 }; // Not part of the API.
- Timestamp timeout;
- Timestamp precision;
- SubClockFlags flags;
- u8 _padding2[4] { 0 }; // Not part of the API.
- void serialize_into(Array<Bytes, 1> bytes) const;
- static SubscriptionClock read_from(Array<ReadonlyBytes, 1> const& bytes);
- };
- static_assert(sizeof(SubscriptionClock) == 32);
- // https://github.com/WebAssembly/wasi-libc/blob/2c2fc9a2fddd0927a66f1c142e65c8dab6f5c5d7/libc-bottom-half/headers/public/wasi/api.h#L1272
- struct SubscriptionFDReadWrite {
- FD file_descriptor;
- void serialize_into(Array<Bytes, 1> bytes) const;
- static SubscriptionFDReadWrite read_from(Array<ReadonlyBytes, 1> const& bytes);
- };
- // https://github.com/WebAssembly/wasi-libc/blob/2c2fc9a2fddd0927a66f1c142e65c8dab6f5c5d7/libc-bottom-half/headers/public/wasi/api.h#L1287
- union SubscriptionU {
- SubscriptionClock clock;
- SubscriptionFDReadWrite fd_read;
- SubscriptionFDReadWrite fd_write;
- };
- // https://github.com/WebAssembly/wasi-libc/blob/2c2fc9a2fddd0927a66f1c142e65c8dab6f5c5d7/libc-bottom-half/headers/public/wasi/api.h#L1306
- struct Subscription {
- UserData userdata;
- EventType type;
- u8 _padding[7] { 0 }; // Not part of the API.
- SubscriptionU u;
- void serialize_into(Array<Bytes, 1> bytes) const;
- static Subscription read_from(Array<ReadonlyBytes, 1> const& bytes);
- };
- static_assert(sizeof(Subscription) == 48);
- // https://github.com/WebAssembly/wasi-libc/blob/2c2fc9a2fddd0927a66f1c142e65c8dab6f5c5d7/libc-bottom-half/headers/public/wasi/api.h#L1334
- using ExitCode = LittleEndian<u32>;
- // https://github.com/WebAssembly/wasi-libc/blob/2c2fc9a2fddd0927a66f1c142e65c8dab6f5c5d7/libc-bottom-half/headers/public/wasi/api.h#L1342
- enum class Signal : u8 {
- None,
- HUP,
- INT,
- QUIT,
- ILL,
- TRAP,
- ABRT,
- BUS,
- FPE,
- KILL,
- USR1,
- SEGV,
- USR2,
- PIPE,
- ALRM,
- TERM,
- CHLD,
- CONT,
- STOP,
- TSTP,
- TTIN,
- TTOU,
- URG,
- XCPU,
- XFSZ,
- VTALRM,
- PROF,
- WINCH,
- POLL,
- PWR,
- SYS,
- };
- // https://github.com/WebAssembly/wasi-libc/blob/2c2fc9a2fddd0927a66f1c142e65c8dab6f5c5d7/libc-bottom-half/headers/public/wasi/api.h#L1536
- struct RIFlags {
- using CompatibleType = u16;
- struct Bits {
- bool recv_peek : 1;
- bool recv_waitall : 1;
- u8 _unused1 : 6;
- u8 _unused2 : 8;
- };
- static_assert(sizeof(Bits) == sizeof(CompatibleType));
- union {
- Bits bits;
- LittleEndian<CompatibleType> data;
- };
- static RIFlags read_from(Array<ReadonlyBytes, 1> const& bytes);
- };
- // https://github.com/WebAssembly/wasi-libc/blob/2c2fc9a2fddd0927a66f1c142e65c8dab6f5c5d7/libc-bottom-half/headers/public/wasi/api.h#L1554
- struct ROFlags {
- using CompatibleType = u16;
- struct Bits {
- bool recv_data_truncated : 1;
- u8 _unused1 : 7;
- u8 _unused2 : 8;
- };
- static_assert(sizeof(Bits) == sizeof(CompatibleType));
- union {
- Bits bits;
- LittleEndian<CompatibleType> data;
- };
- void serialize_into(Array<Bytes, 1> bytes) const;
- };
- // https://github.com/WebAssembly/wasi-libc/blob/2c2fc9a2fddd0927a66f1c142e65c8dab6f5c5d7/libc-bottom-half/headers/public/wasi/api.h#L1568
- using SIFlags = LittleEndian<u16>;
- // https://github.com/WebAssembly/wasi-libc/blob/2c2fc9a2fddd0927a66f1c142e65c8dab6f5c5d7/libc-bottom-half/headers/public/wasi/api.h#L1576
- struct SDFlags {
- using CompatibleType = u8;
- struct Bits {
- bool rd : 1;
- bool wr : 1;
- u8 _unused : 6;
- };
- static_assert(sizeof(Bits) == sizeof(CompatibleType));
- union {
- Bits bits;
- LittleEndian<CompatibleType> data;
- };
- void serialize_into(Array<Bytes, 1> bytes) const;
- static SDFlags read_from(Array<ReadonlyBytes, 1> const& bytes);
- };
- // https://github.com/WebAssembly/wasi-libc/blob/2c2fc9a2fddd0927a66f1c142e65c8dab6f5c5d7/libc-bottom-half/headers/public/wasi/api.h#L1594
- enum class PreOpenType : u8 {
- Dir,
- };
- // https://github.com/WebAssembly/wasi-libc/blob/2c2fc9a2fddd0927a66f1c142e65c8dab6f5c5d7/libc-bottom-half/headers/public/wasi/api.h#L1607
- struct PreStatDir {
- Size pr_name_len;
- void serialize_into(Array<Bytes, 1> bytes) const;
- static PreStatDir read_from(Array<ReadonlyBytes, 1> const& bytes);
- };
- // https://github.com/WebAssembly/wasi-libc/blob/2c2fc9a2fddd0927a66f1c142e65c8dab6f5c5d7/libc-bottom-half/headers/public/wasi/api.h#L1636
- struct PreStat {
- PreOpenType type;
- u8 _padding[3] { 0 }; // Not part of the API.
- union {
- PreStatDir dir;
- };
- void serialize_into(Array<Bytes, 1> bytes) const;
- };
- static_assert(sizeof(PreStat) == 8);
- // https://github.com/WebAssembly/wasi-libc/blob/2c2fc9a2fddd0927a66f1c142e65c8dab6f5c5d7/libc-bottom-half/headers/public/wasi/api.h#L1676
- struct ArgsSizes {
- Size count;
- Size size;
- using SerializationComponents = TypeList<Size, Size>;
- void serialize_into(Array<Bytes, 2> bytes) const;
- };
- // https://github.com/WebAssembly/wasi-libc/blob/2c2fc9a2fddd0927a66f1c142e65c8dab6f5c5d7/libc-bottom-half/headers/public/wasi/api.h#L1708
- struct EnvironSizes {
- Size count;
- Size size;
- using SerializationComponents = TypeList<Size, Size>;
- void serialize_into(Array<Bytes, 2> bytes) const;
- };
- // https://github.com/WebAssembly/wasi-libc/blob/2c2fc9a2fddd0927a66f1c142e65c8dab6f5c5d7/libc-bottom-half/headers/public/wasi/api.h#L2664
- struct SockRecvResult {
- Size size;
- ROFlags roflags;
- u8 _padding[2] { 0 }; // Not part of the API.
- using SerializationComponents = TypeList<Size, ROFlags>;
- void serialize_into(Array<Bytes, 2> bytes) const;
- };
- static_assert(sizeof(SockRecvResult) == 8);
- template<typename TResult, typename Tag = u32>
- struct Result {
- Result(TResult&& result)
- : bits {}
- , tag(0)
- {
- new (&bits) TResult(move(result));
- }
- Result(Errno&& error)
- : bits {}
- , tag(1)
- {
- new (&bits) Errno(error);
- }
- Optional<TResult&> result() const
- {
- if (tag == 0)
- return *bit_cast<TResult*>(&bits[0]);
- return {};
- }
- Optional<Errno&> error() const
- {
- if (tag == 1)
- return *bit_cast<Errno*>(&bits[0]);
- return {};
- }
- bool is_error() const { return tag == 1; }
- template<size_t N>
- Errno serialize_into(Array<Bytes, N>&& spans) const
- {
- if (tag == 1)
- return error().value();
- ABI::serialize(*result(), move(spans));
- return Errno::Success;
- }
- private:
- alignas(max(alignof(TResult), alignof(Errno))) u8 bits[max(sizeof(TResult), sizeof(Errno))];
- LittleEndian<Tag> tag;
- };
- template<typename Tag>
- struct Result<void, Tag> {
- Result()
- : error_bits {}
- , tag(0)
- {
- }
- Result(Errno&& error)
- : error_bits {}
- , tag(1)
- {
- new (&error_bits) Errno(error);
- }
- Optional<Empty> result() const
- {
- if (tag == 0)
- return { Empty {} };
- return {};
- }
- Optional<Errno&> error() const
- {
- if (tag == 1)
- return *bit_cast<Errno*>(&error_bits[0]);
- return {};
- }
- bool is_error() const { return tag == 1; }
- private:
- alignas(Errno) u8 error_bits[sizeof(Errno)];
- LittleEndian<Tag> tag;
- };
- struct Implementation {
- struct MappedPath {
- LexicalPath host_path;
- LexicalPath mapped_path;
- mutable Optional<int> opened_fd {};
- };
- struct Details {
- Function<Vector<AK::String>()> provide_arguments;
- Function<Vector<AK::String>()> provide_environment;
- Function<Vector<MappedPath>()> provide_preopened_directories;
- };
- explicit Implementation(Details&& details)
- : provide_arguments(move(details.provide_arguments))
- , provide_environment(move(details.provide_environment))
- , provide_preopened_directories(move(details.provide_preopened_directories))
- {
- // Map all of std{in,out,err} by default.
- m_fd_map.insert(0, 0);
- m_fd_map.insert(1, 1);
- m_fd_map.insert(2, 2);
- }
- ErrorOr<HostFunction> function_by_name(StringView);
- private:
- template<auto impl>
- HostFunction invocation_of(StringView name) { return ABI::InvocationOf<impl> {}(*this, name); }
- ErrorOr<Result<void>> impl$args_get(Configuration&, Pointer<Pointer<u8>> argv, Pointer<u8> argv_buf);
- ErrorOr<Result<ArgsSizes>> impl$args_sizes_get(Configuration&);
- ErrorOr<Result<void>> impl$environ_get(Configuration&, Pointer<Pointer<u8>> environ, Pointer<u8> environ_buf);
- ErrorOr<Result<EnvironSizes>> impl$environ_sizes_get(Configuration&);
- ErrorOr<Result<Timestamp>> impl$clock_res_get(Configuration&, ClockID id);
- ErrorOr<Result<Timestamp>> impl$clock_time_get(Configuration&, ClockID id, Timestamp precision);
- ErrorOr<Result<void>> impl$fd_advise(Configuration&, FD, FileSize offset, FileSize len, Advice);
- ErrorOr<Result<void>> impl$fd_allocate(Configuration&, FD, FileSize offset, FileSize len);
- ErrorOr<Result<void>> impl$fd_close(Configuration&, FD);
- ErrorOr<Result<void>> impl$fd_datasync(Configuration&, FD);
- ErrorOr<Result<FDStat>> impl$fd_fdstat_get(Configuration&, FD);
- ErrorOr<Result<void>> impl$fd_fdstat_set_flags(Configuration&, FD, FDFlags);
- ErrorOr<Result<void>> impl$fd_fdstat_set_rights(Configuration&, FD, Rights fs_rights_base, Rights fs_rights_inheriting);
- ErrorOr<Result<FileStat>> impl$fd_filestat_get(Configuration&, FD);
- ErrorOr<Result<void>> impl$fd_filestat_set_size(Configuration&, FD, FileSize);
- ErrorOr<Result<void>> impl$fd_filestat_set_times(Configuration&, FD, Timestamp atim, Timestamp mtim, FSTFlags);
- ErrorOr<Result<Size>> impl$fd_pread(Configuration&, FD, Pointer<IOVec> iovs, Size iovs_len, FileSize offset);
- ErrorOr<Result<PreStat>> impl$fd_prestat_get(Configuration&, FD);
- ErrorOr<Result<void>> impl$fd_prestat_dir_name(Configuration&, FD, Pointer<u8> path, Size path_len);
- ErrorOr<Result<Size>> impl$fd_pwrite(Configuration&, FD, Pointer<CIOVec> iovs, Size iovs_len, FileSize offset);
- ErrorOr<Result<Size>> impl$fd_read(Configuration&, FD, Pointer<IOVec> iovs, Size iovs_len);
- ErrorOr<Result<Size>> impl$fd_readdir(Configuration&, FD, Pointer<u8> buf, Size buf_len, DirCookie cookie);
- ErrorOr<Result<void>> impl$fd_renumber(Configuration&, FD from, FD to);
- ErrorOr<Result<FileSize>> impl$fd_seek(Configuration&, FD, FileDelta offset, Whence whence);
- ErrorOr<Result<void>> impl$fd_sync(Configuration&, FD);
- ErrorOr<Result<FileSize>> impl$fd_tell(Configuration&, FD);
- ErrorOr<Result<Size>> impl$fd_write(Configuration&, FD, Pointer<CIOVec> iovs, Size iovs_len);
- ErrorOr<Result<void>> impl$path_create_directory(Configuration&, FD, Pointer<u8> path, Size path_len);
- ErrorOr<Result<FileStat>> impl$path_filestat_get(Configuration&, FD, LookupFlags, ConstPointer<u8> path, Size path_len);
- ErrorOr<Result<void>> impl$path_filestat_set_times(Configuration&, FD, LookupFlags, Pointer<u8> path, Size path_len, Timestamp atim, Timestamp mtim, FSTFlags);
- ErrorOr<Result<void>> impl$path_link(Configuration&, FD, LookupFlags, Pointer<u8> old_path, Size old_path_len, FD, Pointer<u8> new_path, Size new_path_len);
- ErrorOr<Result<FD>> impl$path_open(Configuration&, FD, LookupFlags, Pointer<u8> path, Size path_len, OFlags, Rights fs_rights_base, Rights fs_rights_inheriting, FDFlags fd_flags);
- ErrorOr<Result<Size>> impl$path_readlink(Configuration&, FD, LookupFlags, Pointer<u8> path, Size path_len, Pointer<u8> buf, Size buf_len);
- ErrorOr<Result<void>> impl$path_remove_directory(Configuration&, FD, Pointer<u8> path, Size path_len);
- ErrorOr<Result<void>> impl$path_rename(Configuration&, FD, Pointer<u8> old_path, Size old_path_len, FD, Pointer<u8> new_path, Size new_path_len);
- ErrorOr<Result<void>> impl$path_symlink(Configuration&, Pointer<u8> old_path, Size old_path_len, FD, Pointer<u8> new_path, Size new_path_len);
- ErrorOr<Result<void>> impl$path_unlink_file(Configuration&, FD, Pointer<u8> path, Size path_len);
- ErrorOr<Result<Size>> impl$poll_oneoff(Configuration&, ConstPointer<Subscription> in, Pointer<Event> out, Size nsubscriptions);
- ErrorOr<Result<void>> impl$proc_exit(Configuration&, ExitCode); // Note: noreturn.
- ErrorOr<Result<void>> impl$proc_raise(Configuration&, Signal);
- ErrorOr<Result<void>> impl$sched_yield(Configuration&);
- ErrorOr<Result<void>> impl$random_get(Configuration&, Pointer<u8> buf, Size buf_len);
- ErrorOr<Result<FD>> impl$sock_accept(Configuration&, FD fd, FDFlags fd_flags);
- ErrorOr<Result<SockRecvResult>> impl$sock_recv(Configuration&, FD fd, Pointer<IOVec> ri_data, Size ri_data_len, RIFlags ri_flags);
- ErrorOr<Result<Size>> impl$sock_send(Configuration&, FD fd, Pointer<CIOVec> si_data, Size ri_data_len, SIFlags si_flags);
- ErrorOr<Result<void>> impl$sock_shutdown(Configuration&, FD fd, SDFlags how);
- Vector<AK::String> const& arguments() const;
- Vector<AK::String> const& environment() const;
- Vector<MappedPath> const& preopened_directories() const;
- using PreopenedDirectoryDescriptor = DistinctNumeric<LittleEndian<size_t>, struct PreopenedDirectoryDescriptor_tag, AK::DistinctNumericFeature::Comparison, AK::DistinctNumericFeature::CastToUnderlying, AK::DistinctNumericFeature::Increment>;
- using UnmappedDescriptor = DistinctNumeric<LittleEndian<size_t>, struct UnmappedDescriptor_tag, AK::DistinctNumericFeature::Comparison, AK::DistinctNumericFeature::CastToUnderlying>;
- using MappedDescriptor = Variant<u32, PreopenedDirectoryDescriptor>;
- using Descriptor = Variant<u32, PreopenedDirectoryDescriptor, UnmappedDescriptor>;
- Descriptor map_fd(FD);
- public:
- Function<Vector<AK::String>()> provide_arguments;
- Function<Vector<AK::String>()> provide_environment;
- Function<Vector<MappedPath>()> provide_preopened_directories;
- private:
- struct Cache {
- Optional<Vector<AK::String>> cached_arguments;
- Optional<Vector<AK::String>> cached_environment;
- Optional<Vector<MappedPath>> cached_preopened_directories;
- };
- mutable Cache cache {};
- RedBlackTree<u32, MappedDescriptor> m_fd_map;
- size_t m_first_unmapped_preopened_directory_index { 0 };
- };
- #undef IMPL
- }
- namespace Wasm::Wasi::ABI {
- template<typename T, typename... Args>
- struct ToCompatibleValue<DistinctNumeric<T, Args...>> {
- using Type = typename ToCompatibleValue<T>::Type;
- };
- template<typename T>
- struct ToCompatibleValue<LittleEndian<T>> {
- using Type = MakeSigned<T>;
- };
- template<typename T>
- requires(requires { declval<typename T::CompatibleType>(); })
- struct ToCompatibleValue<T> {
- using Type = MakeSigned<typename T::CompatibleType>;
- };
- template<Integral T>
- struct ToCompatibleValue<T> {
- using Type = MakeSigned<T>;
- };
- template<Enum T>
- struct ToCompatibleValue<T> {
- using Type = MakeSigned<UnderlyingType<T>>;
- };
- }
- template<typename T>
- struct AK::Formatter<Wasm::Wasi::LittleEndian<T>> : AK::Formatter<T> {
- ErrorOr<void> format(FormatBuilder& builder, Wasm::Wasi::LittleEndian<T> value)
- {
- return Formatter<T>::format(builder, value.operator T());
- }
- };
|