in plugins/experimental/wasm/lib/src/exports.cc [671:718]
Word writevImpl(Word fd, Word iovs, Word iovs_len, Word *nwritten_ptr) {
auto *context = contextOrEffectiveContext();
// Read syscall args.
uint64_t log_level;
switch (fd) {
case 1 /* stdout */:
log_level = 2; // LogLevel::info
break;
case 2 /* stderr */:
log_level = 4; // LogLevel::error
break;
default:
return 8; // __WASI_EBADF
}
std::string s;
for (size_t i = 0; i < iovs_len; i++) {
auto memslice =
context->wasmVm()->getMemory(iovs + i * 2 * sizeof(uint32_t), 2 * sizeof(uint32_t));
if (!memslice) {
return 21; // __WASI_EFAULT
}
const auto *iovec = reinterpret_cast<const uint32_t *>(memslice.value().data());
if (iovec[1] != 0U /* buf_len */) {
const auto buf = wasmtoh(iovec[0], context->wasmVm()->usesWasmByteOrder());
const auto buf_len = wasmtoh(iovec[1], context->wasmVm()->usesWasmByteOrder());
memslice = context->wasmVm()->getMemory(buf, buf_len);
if (!memslice) {
return 21; // __WASI_EFAULT
}
s.append(memslice.value().data(), memslice.value().size());
}
}
size_t written = s.size();
if (written != 0U) {
// Remove trailing newline from the logs, if any.
if (s[written - 1] == '\n') {
s.erase(written - 1);
}
if (context->log(log_level, s) != WasmResult::Ok) {
return 8; // __WASI_EBADF
}
}
*nwritten_ptr = Word(written);
return 0; // __WASI_ESUCCESS
}