Merge remote-tracking branch 'origin/main' into pch/wasi_error_handling
This commit is contained in:
19
crates/cranelift/Cargo.toml
Normal file
19
crates/cranelift/Cargo.toml
Normal file
@@ -0,0 +1,19 @@
|
||||
[package]
|
||||
name = "wasmtime-cranelift"
|
||||
version = "0.19.0"
|
||||
authors = ["The Wasmtime Project Developers"]
|
||||
description = "Integration between Cranelift and Wasmtime"
|
||||
license = "Apache-2.0 WITH LLVM-exception"
|
||||
repository = "https://github.com/bytecodealliance/wasmtime"
|
||||
documentation = "https://docs.rs/wasmtime-cranelift/"
|
||||
categories = ["wasm"]
|
||||
keywords = ["webassembly", "wasm"]
|
||||
readme = "README.md"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
wasmtime-environ = { path = "../environ", version = "0.19.0" }
|
||||
cranelift-wasm = { path = "../../cranelift/wasm", version = "0.66.0" }
|
||||
cranelift-codegen = { path = "../../cranelift/codegen", version = "0.66.0" }
|
||||
cranelift-frontend = { path = "../../cranelift/frontend", version = "0.66.0" }
|
||||
cranelift-entity = { path = "../../cranelift/entity", version = "0.66.0" }
|
||||
4
crates/cranelift/README.md
Normal file
4
crates/cranelift/README.md
Normal file
@@ -0,0 +1,4 @@
|
||||
# `wasmtime-cranelfit`
|
||||
|
||||
This crate provides an implementation of the `Compiler` trait which is
|
||||
connected to Cranelift.
|
||||
@@ -1,6 +1,3 @@
|
||||
use crate::module::{MemoryPlan, MemoryStyle, TableStyle};
|
||||
use crate::vmoffsets::VMOffsets;
|
||||
use crate::{Module, Tunables, INTERRUPTED, WASM_PAGE_SIZE};
|
||||
use cranelift_codegen::cursor::FuncCursor;
|
||||
use cranelift_codegen::ir;
|
||||
use cranelift_codegen::ir::condcodes::*;
|
||||
@@ -14,20 +11,18 @@ use cranelift_wasm::{
|
||||
self, FuncIndex, GlobalIndex, GlobalVariable, MemoryIndex, SignatureIndex, TableIndex,
|
||||
TargetEnvironment, WasmError, WasmResult, WasmType,
|
||||
};
|
||||
#[cfg(feature = "lightbeam")]
|
||||
use cranelift_wasm::{DefinedFuncIndex, DefinedGlobalIndex, DefinedMemoryIndex, DefinedTableIndex};
|
||||
use std::convert::TryFrom;
|
||||
use wasmtime_environ::{
|
||||
BuiltinFunctionIndex, MemoryPlan, MemoryStyle, Module, TableStyle, Tunables, VMOffsets,
|
||||
INTERRUPTED, WASM_PAGE_SIZE,
|
||||
};
|
||||
|
||||
/// Compute an `ir::ExternalName` for a given wasm function index.
|
||||
pub fn get_func_name(func_index: FuncIndex) -> ir::ExternalName {
|
||||
ir::ExternalName::user(0, func_index.as_u32())
|
||||
}
|
||||
|
||||
/// An index type for builtin functions.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct BuiltinFunctionIndex(u32);
|
||||
|
||||
macro_rules! declare_builtin_functions {
|
||||
macro_rules! declare_function_signatures {
|
||||
(
|
||||
$(
|
||||
$( #[$attr:meta] )*
|
||||
@@ -91,111 +86,10 @@ macro_rules! declare_builtin_functions {
|
||||
}
|
||||
)*
|
||||
}
|
||||
|
||||
impl BuiltinFunctionIndex {
|
||||
declare_builtin_functions!(
|
||||
@indices;
|
||||
0;
|
||||
$( $( #[$attr] )* $name; )*
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
// Base case: no more indices to declare, so define the total number of
|
||||
// function indices.
|
||||
(
|
||||
@indices;
|
||||
$len:expr;
|
||||
) => {
|
||||
/// Returns the total number of builtin functions.
|
||||
pub const fn builtin_functions_total_number() -> u32 {
|
||||
$len
|
||||
}
|
||||
};
|
||||
|
||||
// Recursive case: declare the next index, and then keep declaring the rest of
|
||||
// the indices.
|
||||
(
|
||||
@indices;
|
||||
$index:expr;
|
||||
$( #[$this_attr:meta] )*
|
||||
$this_name:ident;
|
||||
$(
|
||||
$( #[$rest_attr:meta] )*
|
||||
$rest_name:ident;
|
||||
)*
|
||||
) => {
|
||||
$( #[$this_attr] )*
|
||||
pub const fn $this_name() -> Self {
|
||||
Self($index)
|
||||
}
|
||||
|
||||
declare_builtin_functions!(
|
||||
@indices;
|
||||
($index + 1);
|
||||
$( $( #[$rest_attr] )* $rest_name; )*
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
declare_builtin_functions! {
|
||||
/// Returns an index for wasm's `memory.grow` builtin function.
|
||||
memory32_grow(vmctx, i32, i32) -> (i32);
|
||||
/// Returns an index for wasm's imported `memory.grow` builtin function.
|
||||
imported_memory32_grow(vmctx, i32, i32) -> (i32);
|
||||
/// Returns an index for wasm's `memory.size` builtin function.
|
||||
memory32_size(vmctx, i32) -> (i32);
|
||||
/// Returns an index for wasm's imported `memory.size` builtin function.
|
||||
imported_memory32_size(vmctx, i32) -> (i32);
|
||||
/// Returns an index for wasm's `table.copy` when both tables are locally
|
||||
/// defined.
|
||||
table_copy(vmctx, i32, i32, i32, i32, i32) -> ();
|
||||
/// Returns an index for wasm's `table.init`.
|
||||
table_init(vmctx, i32, i32, i32, i32, i32) -> ();
|
||||
/// Returns an index for wasm's `elem.drop`.
|
||||
elem_drop(vmctx, i32) -> ();
|
||||
/// Returns an index for wasm's `memory.copy` for locally defined memories.
|
||||
defined_memory_copy(vmctx, i32, i32, i32, i32) -> ();
|
||||
/// Returns an index for wasm's `memory.copy` for imported memories.
|
||||
imported_memory_copy(vmctx, i32, i32, i32, i32) -> ();
|
||||
/// Returns an index for wasm's `memory.fill` for locally defined memories.
|
||||
memory_fill(vmctx, i32, i32, i32, i32) -> ();
|
||||
/// Returns an index for wasm's `memory.fill` for imported memories.
|
||||
imported_memory_fill(vmctx, i32, i32, i32, i32) -> ();
|
||||
/// Returns an index for wasm's `memory.init` instruction.
|
||||
memory_init(vmctx, i32, i32, i32, i32, i32) -> ();
|
||||
/// Returns an index for wasm's `data.drop` instruction.
|
||||
data_drop(vmctx, i32) -> ();
|
||||
/// Returns an index for Wasm's `table.grow` instruction for `funcref`s.
|
||||
table_grow_funcref(vmctx, i32, i32, pointer) -> (i32);
|
||||
/// Returns an index for Wasm's `table.grow` instruction for `externref`s.
|
||||
table_grow_externref(vmctx, i32, i32, reference) -> (i32);
|
||||
/// Returns an index for Wasm's `table.fill` instruction for `externref`s.
|
||||
table_fill_externref(vmctx, i32, i32, reference, i32) -> ();
|
||||
/// Returns an index for Wasm's `table.fill` instruction for `funcref`s.
|
||||
table_fill_funcref(vmctx, i32, i32, pointer, i32) -> ();
|
||||
/// Returns an index to drop a `VMExternRef`.
|
||||
drop_externref(pointer) -> ();
|
||||
/// Returns an index to do a GC and then insert a `VMExternRef` into the
|
||||
/// `VMExternRefActivationsTable`.
|
||||
activations_table_insert_with_gc(vmctx, reference) -> ();
|
||||
/// Returns an index for Wasm's `global.get` instruction for `externref`s.
|
||||
externref_global_get(vmctx, i32) -> (reference);
|
||||
/// Returns an index for Wasm's `global.get` instruction for `externref`s.
|
||||
externref_global_set(vmctx, i32, reference) -> ();
|
||||
}
|
||||
|
||||
impl BuiltinFunctionIndex {
|
||||
/// Create a new `BuiltinFunctionIndex` from its index
|
||||
pub const fn from_u32(i: u32) -> Self {
|
||||
Self(i)
|
||||
}
|
||||
|
||||
/// Return the index as an u32 number.
|
||||
pub const fn index(&self) -> u32 {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
wasmtime_environ::foreach_builtin_function!(declare_function_signatures);
|
||||
|
||||
/// The `FuncEnvironment` implementation for use by the `ModuleEnvironment`.
|
||||
pub struct FuncEnvironment<'module_environment> {
|
||||
@@ -464,153 +358,13 @@ impl<'module_environment> FuncEnvironment<'module_environment> {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: This is necessary as if Lightbeam used `FuncEnvironment` directly it would cause
|
||||
// a circular dependency graph. We should extract common types out into a separate
|
||||
// crate that Lightbeam can use but until then we need this trait.
|
||||
#[cfg(feature = "lightbeam")]
|
||||
impl lightbeam::ModuleContext for FuncEnvironment<'_> {
|
||||
type Signature = ir::Signature;
|
||||
type GlobalType = ir::Type;
|
||||
|
||||
fn func_index(&self, defined_func_index: u32) -> u32 {
|
||||
self.module
|
||||
.func_index(DefinedFuncIndex::from_u32(defined_func_index))
|
||||
.as_u32()
|
||||
}
|
||||
|
||||
fn defined_func_index(&self, func_index: u32) -> Option<u32> {
|
||||
self.module
|
||||
.defined_func_index(FuncIndex::from_u32(func_index))
|
||||
.map(DefinedFuncIndex::as_u32)
|
||||
}
|
||||
|
||||
fn defined_global_index(&self, global_index: u32) -> Option<u32> {
|
||||
self.module
|
||||
.defined_global_index(GlobalIndex::from_u32(global_index))
|
||||
.map(DefinedGlobalIndex::as_u32)
|
||||
}
|
||||
|
||||
fn global_type(&self, global_index: u32) -> &Self::GlobalType {
|
||||
&self.module.globals[GlobalIndex::from_u32(global_index)].ty
|
||||
}
|
||||
|
||||
fn func_type_index(&self, func_idx: u32) -> u32 {
|
||||
self.module.functions[FuncIndex::from_u32(func_idx)].as_u32()
|
||||
}
|
||||
|
||||
fn signature(&self, index: u32) -> &Self::Signature {
|
||||
&self.module.signatures[SignatureIndex::from_u32(index)].1
|
||||
}
|
||||
|
||||
fn defined_table_index(&self, table_index: u32) -> Option<u32> {
|
||||
self.module
|
||||
.defined_table_index(TableIndex::from_u32(table_index))
|
||||
.map(DefinedTableIndex::as_u32)
|
||||
}
|
||||
|
||||
fn defined_memory_index(&self, memory_index: u32) -> Option<u32> {
|
||||
self.module
|
||||
.defined_memory_index(MemoryIndex::from_u32(memory_index))
|
||||
.map(DefinedMemoryIndex::as_u32)
|
||||
}
|
||||
|
||||
fn vmctx_builtin_function(&self, func_index: u32) -> u32 {
|
||||
self.offsets
|
||||
.vmctx_builtin_function(BuiltinFunctionIndex::from_u32(func_index))
|
||||
}
|
||||
|
||||
fn vmctx_vmfunction_import_body(&self, func_index: u32) -> u32 {
|
||||
self.offsets
|
||||
.vmctx_vmfunction_import_body(FuncIndex::from_u32(func_index))
|
||||
}
|
||||
fn vmctx_vmfunction_import_vmctx(&self, func_index: u32) -> u32 {
|
||||
self.offsets
|
||||
.vmctx_vmfunction_import_vmctx(FuncIndex::from_u32(func_index))
|
||||
}
|
||||
|
||||
fn vmctx_vmglobal_import_from(&self, global_index: u32) -> u32 {
|
||||
self.offsets
|
||||
.vmctx_vmglobal_import_from(GlobalIndex::from_u32(global_index))
|
||||
}
|
||||
fn vmctx_vmglobal_definition(&self, defined_global_index: u32) -> u32 {
|
||||
self.offsets
|
||||
.vmctx_vmglobal_definition(DefinedGlobalIndex::from_u32(defined_global_index))
|
||||
}
|
||||
fn vmctx_vmmemory_import_from(&self, memory_index: u32) -> u32 {
|
||||
self.offsets
|
||||
.vmctx_vmmemory_import_from(MemoryIndex::from_u32(memory_index))
|
||||
}
|
||||
fn vmctx_vmmemory_definition(&self, defined_memory_index: u32) -> u32 {
|
||||
self.offsets
|
||||
.vmctx_vmmemory_definition(DefinedMemoryIndex::from_u32(defined_memory_index))
|
||||
}
|
||||
fn vmctx_vmmemory_definition_base(&self, defined_memory_index: u32) -> u32 {
|
||||
self.offsets
|
||||
.vmctx_vmmemory_definition_base(DefinedMemoryIndex::from_u32(defined_memory_index))
|
||||
}
|
||||
fn vmctx_vmmemory_definition_current_length(&self, defined_memory_index: u32) -> u32 {
|
||||
self.offsets
|
||||
.vmctx_vmmemory_definition_current_length(DefinedMemoryIndex::from_u32(
|
||||
defined_memory_index,
|
||||
))
|
||||
}
|
||||
fn vmmemory_definition_base(&self) -> u8 {
|
||||
self.offsets.vmmemory_definition_base()
|
||||
}
|
||||
fn vmmemory_definition_current_length(&self) -> u8 {
|
||||
self.offsets.vmmemory_definition_current_length()
|
||||
}
|
||||
fn vmctx_vmtable_import_from(&self, table_index: u32) -> u32 {
|
||||
self.offsets
|
||||
.vmctx_vmtable_import_from(TableIndex::from_u32(table_index))
|
||||
}
|
||||
fn vmctx_vmtable_definition(&self, defined_table_index: u32) -> u32 {
|
||||
self.offsets
|
||||
.vmctx_vmtable_definition(DefinedTableIndex::from_u32(defined_table_index))
|
||||
}
|
||||
fn vmctx_vmtable_definition_base(&self, defined_table_index: u32) -> u32 {
|
||||
self.offsets
|
||||
.vmctx_vmtable_definition_base(DefinedTableIndex::from_u32(defined_table_index))
|
||||
}
|
||||
fn vmctx_vmtable_definition_current_elements(&self, defined_table_index: u32) -> u32 {
|
||||
self.offsets
|
||||
.vmctx_vmtable_definition_current_elements(DefinedTableIndex::from_u32(
|
||||
defined_table_index,
|
||||
))
|
||||
}
|
||||
fn vmtable_definition_base(&self) -> u8 {
|
||||
self.offsets.vmtable_definition_base()
|
||||
}
|
||||
fn vmtable_definition_current_elements(&self) -> u8 {
|
||||
self.offsets.vmtable_definition_current_elements()
|
||||
}
|
||||
fn vmcaller_checked_anyfunc_type_index(&self) -> u8 {
|
||||
self.offsets.vmcaller_checked_anyfunc_type_index()
|
||||
}
|
||||
fn vmcaller_checked_anyfunc_func_ptr(&self) -> u8 {
|
||||
self.offsets.vmcaller_checked_anyfunc_func_ptr()
|
||||
}
|
||||
fn vmcaller_checked_anyfunc_vmctx(&self) -> u8 {
|
||||
self.offsets.vmcaller_checked_anyfunc_vmctx()
|
||||
}
|
||||
fn size_of_vmcaller_checked_anyfunc(&self) -> u8 {
|
||||
self.offsets.size_of_vmcaller_checked_anyfunc()
|
||||
}
|
||||
fn vmctx_vmshared_signature_id(&self, signature_idx: u32) -> u32 {
|
||||
self.offsets
|
||||
.vmctx_vmshared_signature_id(SignatureIndex::from_u32(signature_idx))
|
||||
}
|
||||
|
||||
// TODO: type of a global
|
||||
}
|
||||
|
||||
impl<'module_environment> TargetEnvironment for FuncEnvironment<'module_environment> {
|
||||
fn target_config(&self) -> TargetFrontendConfig {
|
||||
self.target_config
|
||||
}
|
||||
|
||||
fn reference_type(&self, ty: WasmType) -> ir::Type {
|
||||
crate::reference_type(ty, self.pointer_type())
|
||||
wasmtime_environ::reference_type(ty, self.pointer_type())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
//! Support for compiling with Cranelift.
|
||||
//!
|
||||
//! This crate provides an implementation of [`Compiler`] in the form of
|
||||
//! [`Cranelift`].
|
||||
|
||||
// # How does Wasmtime prevent stack overflow?
|
||||
//
|
||||
@@ -86,13 +89,6 @@
|
||||
// assume no valid stack pointer will ever be `usize::max_value() - 32k`.
|
||||
|
||||
use crate::func_environ::{get_func_name, FuncEnvironment};
|
||||
use crate::Compiler;
|
||||
use crate::{
|
||||
CompileError, CompiledFunction, Relocation, RelocationTarget, StackMapInformation,
|
||||
TrapInformation,
|
||||
};
|
||||
use crate::{FunctionAddressMap, InstructionAddressMap};
|
||||
use crate::{FunctionBodyData, ModuleTranslation};
|
||||
use cranelift_codegen::ir::{self, ExternalName};
|
||||
use cranelift_codegen::machinst::buffer::MachSrcLoc;
|
||||
use cranelift_codegen::print_errors::pretty_error;
|
||||
@@ -100,14 +96,21 @@ use cranelift_codegen::{binemit, isa, Context};
|
||||
use cranelift_wasm::{DefinedFuncIndex, FuncIndex, FuncTranslator};
|
||||
use std::convert::TryFrom;
|
||||
use std::sync::Mutex;
|
||||
use wasmtime_environ::{
|
||||
CompileError, CompiledFunction, Compiler, FunctionAddressMap, FunctionBodyData,
|
||||
InstructionAddressMap, ModuleTranslation, Relocation, RelocationTarget, StackMapInformation,
|
||||
TrapInformation,
|
||||
};
|
||||
|
||||
mod func_environ;
|
||||
|
||||
/// Implementation of a relocation sink that just saves all the information for later
|
||||
pub struct RelocSink {
|
||||
struct RelocSink {
|
||||
/// Current function index.
|
||||
func_index: FuncIndex,
|
||||
|
||||
/// Relocations recorded for the function.
|
||||
pub func_relocs: Vec<Relocation>,
|
||||
func_relocs: Vec<Relocation>,
|
||||
}
|
||||
|
||||
impl binemit::RelocSink for RelocSink {
|
||||
@@ -166,7 +169,7 @@ impl binemit::RelocSink for RelocSink {
|
||||
|
||||
impl RelocSink {
|
||||
/// Return a new `RelocSink` instance.
|
||||
pub fn new(func_index: FuncIndex) -> Self {
|
||||
fn new(func_index: FuncIndex) -> Self {
|
||||
Self {
|
||||
func_index,
|
||||
func_relocs: Vec::new(),
|
||||
@@ -176,14 +179,14 @@ impl RelocSink {
|
||||
|
||||
/// Implementation of a trap sink that simply stores all trap info in-memory
|
||||
#[derive(Default)]
|
||||
pub struct TrapSink {
|
||||
struct TrapSink {
|
||||
/// The in-memory vector of trap info
|
||||
pub traps: Vec<TrapInformation>,
|
||||
traps: Vec<TrapInformation>,
|
||||
}
|
||||
|
||||
impl TrapSink {
|
||||
/// Create a new `TrapSink`
|
||||
pub fn new() -> Self {
|
||||
fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@ edition = "2018"
|
||||
[dependencies]
|
||||
gimli = "0.21.0"
|
||||
wasmparser = "0.59.0"
|
||||
object = { version = "0.20", default-features = false, features = ["read", "write"] }
|
||||
object = { version = "0.21.1", default-features = false, features = ["read", "write"] }
|
||||
wasmtime-environ = { path = "../environ", version = "0.19.0" }
|
||||
target-lexicon = { version = "0.10.0", default-features = false }
|
||||
anyhow = "1.0"
|
||||
|
||||
@@ -64,6 +64,10 @@ impl ExpressionWriter {
|
||||
write::Writer::write_u8(&mut self.0, b)
|
||||
}
|
||||
|
||||
pub fn write_u32(&mut self, b: u32) -> write::Result<()> {
|
||||
write::Writer::write_u32(&mut self.0, b)
|
||||
}
|
||||
|
||||
pub fn write_uleb128(&mut self, i: u64) -> write::Result<()> {
|
||||
write::Writer::write_uleb128(&mut self.0, i)
|
||||
}
|
||||
@@ -196,8 +200,8 @@ fn append_memory_deref(
|
||||
}
|
||||
writer.write_op(gimli::constants::DW_OP_deref)?;
|
||||
writer.write_op(gimli::constants::DW_OP_swap)?;
|
||||
writer.write_op(gimli::constants::DW_OP_constu)?;
|
||||
writer.write_uleb128(0xffff_ffff)?;
|
||||
writer.write_op(gimli::constants::DW_OP_const4u)?;
|
||||
writer.write_u32(0xffff_ffff)?;
|
||||
writer.write_op(gimli::constants::DW_OP_and)?;
|
||||
writer.write_op(gimli::constants::DW_OP_plus)?;
|
||||
buf.extend(writer.into_vec());
|
||||
@@ -418,7 +422,7 @@ where
|
||||
let op = Operation::parse(&mut pc, encoding)?;
|
||||
match op {
|
||||
Operation::FrameOffset { offset } => {
|
||||
// Expand DW_OP_fpreg into frame location and DW_OP_plus_uconst.
|
||||
// Expand DW_OP_fbreg into frame location and DW_OP_plus_uconst.
|
||||
if frame_base.is_some() {
|
||||
// Add frame base expressions.
|
||||
flush_code_chunk!();
|
||||
@@ -454,7 +458,8 @@ where
|
||||
Operation::Deref { .. } => {
|
||||
flush_code_chunk!();
|
||||
parts.push(CompiledExpressionPart::Deref);
|
||||
continue;
|
||||
// Don't re-enter the loop here (i.e. continue), because the
|
||||
// DW_OP_deref still needs to be kept.
|
||||
}
|
||||
_ => {
|
||||
return Ok(None);
|
||||
@@ -680,8 +685,7 @@ mod tests {
|
||||
|
||||
let e = expression!(DW_OP_WASM_location, 0x0, 3, DW_OP_stack_value);
|
||||
let fe = compile_expression(&e, DWARF_ENCODING, None).expect("non-error");
|
||||
// DW_OP_fpreg 0x12
|
||||
let e = expression!(0x91, 0x12);
|
||||
let e = expression!(DW_OP_fbreg, 0x12);
|
||||
let ce = compile_expression(&e, DWARF_ENCODING, fe.as_ref())
|
||||
.expect("non-error")
|
||||
.expect("expression");
|
||||
@@ -721,7 +725,7 @@ mod tests {
|
||||
},
|
||||
CompiledExpressionPart::Code(vec![35, 5]),
|
||||
CompiledExpressionPart::Deref,
|
||||
CompiledExpressionPart::Code(vec![159])
|
||||
CompiledExpressionPart::Code(vec![6, 159])
|
||||
],
|
||||
need_deref: false
|
||||
}
|
||||
|
||||
@@ -15,10 +15,8 @@ edition = "2018"
|
||||
anyhow = "1.0"
|
||||
cranelift-codegen = { path = "../../cranelift/codegen", version = "0.66.0", features = ["enable-serde"] }
|
||||
cranelift-entity = { path = "../../cranelift/entity", version = "0.66.0", features = ["enable-serde"] }
|
||||
cranelift-frontend = { path = "../../cranelift/frontend", version = "0.66.0" }
|
||||
cranelift-wasm = { path = "../../cranelift/wasm", version = "0.66.0", features = ["enable-serde"] }
|
||||
wasmparser = "0.59.0"
|
||||
lightbeam = { path = "../lightbeam", optional = true, version = "0.19.0" }
|
||||
indexmap = { version = "1.0.2", features = ["serde-1"] }
|
||||
thiserror = "1.0.4"
|
||||
serde = { version = "1.0.94", features = ["derive"] }
|
||||
|
||||
123
crates/environ/src/builtin.rs
Normal file
123
crates/environ/src/builtin.rs
Normal file
@@ -0,0 +1,123 @@
|
||||
/// Helper macro to iterate over all builtin functions and their signatures.
|
||||
#[macro_export]
|
||||
macro_rules! foreach_builtin_function {
|
||||
($mac:ident) => {
|
||||
$mac! {
|
||||
/// Returns an index for wasm's `memory.grow` builtin function.
|
||||
memory32_grow(vmctx, i32, i32) -> (i32);
|
||||
/// Returns an index for wasm's imported `memory.grow` builtin function.
|
||||
imported_memory32_grow(vmctx, i32, i32) -> (i32);
|
||||
/// Returns an index for wasm's `memory.size` builtin function.
|
||||
memory32_size(vmctx, i32) -> (i32);
|
||||
/// Returns an index for wasm's imported `memory.size` builtin function.
|
||||
imported_memory32_size(vmctx, i32) -> (i32);
|
||||
/// Returns an index for wasm's `table.copy` when both tables are locally
|
||||
/// defined.
|
||||
table_copy(vmctx, i32, i32, i32, i32, i32) -> ();
|
||||
/// Returns an index for wasm's `table.init`.
|
||||
table_init(vmctx, i32, i32, i32, i32, i32) -> ();
|
||||
/// Returns an index for wasm's `elem.drop`.
|
||||
elem_drop(vmctx, i32) -> ();
|
||||
/// Returns an index for wasm's `memory.copy` for locally defined memories.
|
||||
defined_memory_copy(vmctx, i32, i32, i32, i32) -> ();
|
||||
/// Returns an index for wasm's `memory.copy` for imported memories.
|
||||
imported_memory_copy(vmctx, i32, i32, i32, i32) -> ();
|
||||
/// Returns an index for wasm's `memory.fill` for locally defined memories.
|
||||
memory_fill(vmctx, i32, i32, i32, i32) -> ();
|
||||
/// Returns an index for wasm's `memory.fill` for imported memories.
|
||||
imported_memory_fill(vmctx, i32, i32, i32, i32) -> ();
|
||||
/// Returns an index for wasm's `memory.init` instruction.
|
||||
memory_init(vmctx, i32, i32, i32, i32, i32) -> ();
|
||||
/// Returns an index for wasm's `data.drop` instruction.
|
||||
data_drop(vmctx, i32) -> ();
|
||||
/// Returns an index for Wasm's `table.grow` instruction for `funcref`s.
|
||||
table_grow_funcref(vmctx, i32, i32, pointer) -> (i32);
|
||||
/// Returns an index for Wasm's `table.grow` instruction for `externref`s.
|
||||
table_grow_externref(vmctx, i32, i32, reference) -> (i32);
|
||||
/// Returns an index for Wasm's `table.fill` instruction for `externref`s.
|
||||
table_fill_externref(vmctx, i32, i32, reference, i32) -> ();
|
||||
/// Returns an index for Wasm's `table.fill` instruction for `funcref`s.
|
||||
table_fill_funcref(vmctx, i32, i32, pointer, i32) -> ();
|
||||
/// Returns an index to drop a `VMExternRef`.
|
||||
drop_externref(pointer) -> ();
|
||||
/// Returns an index to do a GC and then insert a `VMExternRef` into the
|
||||
/// `VMExternRefActivationsTable`.
|
||||
activations_table_insert_with_gc(vmctx, reference) -> ();
|
||||
/// Returns an index for Wasm's `global.get` instruction for `externref`s.
|
||||
externref_global_get(vmctx, i32) -> (reference);
|
||||
/// Returns an index for Wasm's `global.get` instruction for `externref`s.
|
||||
externref_global_set(vmctx, i32, reference) -> ();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// An index type for builtin functions.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct BuiltinFunctionIndex(u32);
|
||||
|
||||
impl BuiltinFunctionIndex {
|
||||
/// Create a new `BuiltinFunctionIndex` from its index
|
||||
pub const fn from_u32(i: u32) -> Self {
|
||||
Self(i)
|
||||
}
|
||||
|
||||
/// Return the index as an u32 number.
|
||||
pub const fn index(&self) -> u32 {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! declare_indexes {
|
||||
(
|
||||
$(
|
||||
$( #[$attr:meta] )*
|
||||
$name:ident( $( $param:ident ),* ) -> ( $( $result:ident ),* );
|
||||
)*
|
||||
) => {
|
||||
impl BuiltinFunctionIndex {
|
||||
declare_indexes!(
|
||||
@indices;
|
||||
0;
|
||||
$( $( #[$attr] )* $name; )*
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
// Base case: no more indices to declare, so define the total number of
|
||||
// function indices.
|
||||
(
|
||||
@indices;
|
||||
$len:expr;
|
||||
) => {
|
||||
/// Returns the total number of builtin functions.
|
||||
pub const fn builtin_functions_total_number() -> u32 {
|
||||
$len
|
||||
}
|
||||
};
|
||||
|
||||
// Recursive case: declare the next index, and then keep declaring the rest of
|
||||
// the indices.
|
||||
(
|
||||
@indices;
|
||||
$index:expr;
|
||||
$( #[$this_attr:meta] )*
|
||||
$this_name:ident;
|
||||
$(
|
||||
$( #[$rest_attr:meta] )*
|
||||
$rest_name:ident;
|
||||
)*
|
||||
) => {
|
||||
$( #[$this_attr] )*
|
||||
pub const fn $this_name() -> Self {
|
||||
Self($index)
|
||||
}
|
||||
|
||||
declare_indexes!(
|
||||
@indices;
|
||||
($index + 1);
|
||||
$( $( #[$rest_attr] )* $rest_name; )*
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
foreach_builtin_function!(declare_indexes);
|
||||
@@ -25,25 +25,19 @@
|
||||
)]
|
||||
|
||||
mod address_map;
|
||||
mod builtin;
|
||||
mod compilation;
|
||||
mod data_structures;
|
||||
mod func_environ;
|
||||
mod module;
|
||||
mod module_environ;
|
||||
mod tunables;
|
||||
mod vmoffsets;
|
||||
|
||||
pub mod cranelift;
|
||||
#[cfg(feature = "lightbeam")]
|
||||
pub mod lightbeam;
|
||||
|
||||
pub use crate::address_map::*;
|
||||
pub use crate::builtin::*;
|
||||
pub use crate::compilation::*;
|
||||
pub use crate::cranelift::Cranelift;
|
||||
pub use crate::data_structures::*;
|
||||
pub use crate::func_environ::BuiltinFunctionIndex;
|
||||
#[cfg(feature = "lightbeam")]
|
||||
pub use crate::lightbeam::Lightbeam;
|
||||
// pub use crate::func_environ::BuiltinFunctionIndex;
|
||||
pub use crate::module::{
|
||||
EntityIndex, MemoryPlan, MemoryStyle, Module, TableElements, TablePlan, TableStyle,
|
||||
};
|
||||
@@ -60,10 +54,8 @@ pub const WASM_MAX_PAGES: u32 = 0x10000;
|
||||
/// Version number of this crate.
|
||||
pub const VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||
|
||||
pub(crate) fn reference_type(
|
||||
wasm_ty: cranelift_wasm::WasmType,
|
||||
pointer_type: ir::Type,
|
||||
) -> ir::Type {
|
||||
/// Returns the reference type to use for the provided wasm type.
|
||||
pub fn reference_type(wasm_ty: cranelift_wasm::WasmType, pointer_type: ir::Type) -> ir::Type {
|
||||
match wasm_ty {
|
||||
cranelift_wasm::WasmType::FuncRef => pointer_type,
|
||||
cranelift_wasm::WasmType::ExternRef => match pointer_type {
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
//! Support for compiling with Lightbeam.
|
||||
|
||||
use crate::compilation::{CompileError, CompiledFunction, Compiler};
|
||||
use crate::cranelift::{RelocSink, TrapSink};
|
||||
use crate::func_environ::FuncEnvironment;
|
||||
use crate::{FunctionBodyData, ModuleTranslation};
|
||||
use cranelift_codegen::isa;
|
||||
use cranelift_wasm::DefinedFuncIndex;
|
||||
use lightbeam::{CodeGenSession, NullOffsetSink, Sinks};
|
||||
|
||||
/// A compiler that compiles a WebAssembly module with Lightbeam, directly translating the Wasm file.
|
||||
pub struct Lightbeam;
|
||||
|
||||
impl Compiler for Lightbeam {
|
||||
fn compile_function(
|
||||
&self,
|
||||
translation: &ModuleTranslation,
|
||||
i: DefinedFuncIndex,
|
||||
function_body: &FunctionBodyData<'_>,
|
||||
isa: &dyn isa::TargetIsa,
|
||||
) -> Result<CompiledFunction, CompileError> {
|
||||
if translation.tunables.debug_info {
|
||||
return Err(CompileError::DebugInfoNotSupported);
|
||||
}
|
||||
let func_index = translation.module.func_index(i);
|
||||
|
||||
let env = FuncEnvironment::new(
|
||||
isa.frontend_config(),
|
||||
&translation.module,
|
||||
&translation.tunables,
|
||||
);
|
||||
let mut codegen_session: CodeGenSession<_> = CodeGenSession::new(
|
||||
translation.function_body_inputs.len() as u32,
|
||||
&env,
|
||||
lightbeam::microwasm::I32,
|
||||
);
|
||||
|
||||
let mut reloc_sink = RelocSink::new(func_index);
|
||||
let mut trap_sink = TrapSink::new();
|
||||
lightbeam::translate_function(
|
||||
&mut codegen_session,
|
||||
Sinks {
|
||||
relocs: &mut reloc_sink,
|
||||
traps: &mut trap_sink,
|
||||
offsets: &mut NullOffsetSink,
|
||||
},
|
||||
i.as_u32(),
|
||||
wasmparser::FunctionBody::new(0, function_body.data),
|
||||
)
|
||||
.map_err(|e| CompileError::Codegen(format!("Failed to translate function: {}", e)))?;
|
||||
|
||||
let code_section = codegen_session
|
||||
.into_translated_code_section()
|
||||
.map_err(|e| CompileError::Codegen(format!("Failed to generate output code: {}", e)))?;
|
||||
|
||||
Ok(CompiledFunction {
|
||||
// TODO: try to remove copy here (?)
|
||||
body: code_section.buffer().to_vec(),
|
||||
traps: trap_sink.traps,
|
||||
relocations: reloc_sink.func_relocs,
|
||||
|
||||
// not implemented for lightbeam currently
|
||||
unwind_info: None,
|
||||
stack_maps: Default::default(),
|
||||
stack_slots: Default::default(),
|
||||
value_labels_ranges: Default::default(),
|
||||
address_map: Default::default(),
|
||||
jt_offsets: Default::default(),
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,8 @@ cranelift-native = { path = "../../cranelift/native", version = "0.66.0" }
|
||||
cranelift-frontend = { path = "../../cranelift/frontend", version = "0.66.0" }
|
||||
wasmtime-environ = { path = "../environ", version = "0.19.0" }
|
||||
wasmtime-runtime = { path = "../runtime", version = "0.19.0" }
|
||||
wasmtime-cranelift = { path = "../cranelift", version = "0.19.0" }
|
||||
wasmtime-lightbeam = { path = "../lightbeam/wasmtime", version = "0.19.0", optional = true }
|
||||
wasmtime-debug = { path = "../debug", version = "0.19.0" }
|
||||
wasmtime-profiling = { path = "../profiling", version = "0.19.0" }
|
||||
wasmtime-obj = { path = "../obj", version = "0.19.0" }
|
||||
@@ -32,14 +34,14 @@ anyhow = "1.0"
|
||||
cfg-if = "0.1.9"
|
||||
log = "0.4"
|
||||
gimli = { version = "0.21.0", default-features = false, features = ["write"] }
|
||||
object = { version = "0.20", default-features = false, features = ["write"] }
|
||||
object = { version = "0.21.1", default-features = false, features = ["write"] }
|
||||
serde = { version = "1.0.94", features = ["derive"] }
|
||||
|
||||
[target.'cfg(target_os = "windows")'.dependencies]
|
||||
winapi = { version = "0.3.8", features = ["winnt", "impl-default"] }
|
||||
|
||||
[features]
|
||||
lightbeam = ["wasmtime-environ/lightbeam"]
|
||||
lightbeam = ["wasmtime-lightbeam"]
|
||||
jitdump = ["wasmtime-profiling/jitdump"]
|
||||
vtune = ["wasmtime-profiling/vtune"]
|
||||
parallel-compilation = ["rayon"]
|
||||
|
||||
@@ -50,10 +50,10 @@ impl Compiler {
|
||||
strategy,
|
||||
compiler: match strategy {
|
||||
CompilationStrategy::Auto | CompilationStrategy::Cranelift => {
|
||||
Box::new(wasmtime_environ::cranelift::Cranelift::default())
|
||||
Box::new(wasmtime_cranelift::Cranelift::default())
|
||||
}
|
||||
#[cfg(feature = "lightbeam")]
|
||||
CompilationStrategy::Lightbeam => Box::new(wasmtime_environ::lightbeam::Lightbeam),
|
||||
CompilationStrategy::Lightbeam => Box::new(wasmtime_lightbeam::Lightbeam),
|
||||
},
|
||||
tunables,
|
||||
}
|
||||
|
||||
18
crates/lightbeam/wasmtime/Cargo.toml
Normal file
18
crates/lightbeam/wasmtime/Cargo.toml
Normal file
@@ -0,0 +1,18 @@
|
||||
[package]
|
||||
name = "wasmtime-lightbeam"
|
||||
version = "0.19.0"
|
||||
authors = ["The Wasmtime Project Developers"]
|
||||
description = "Integration between Lightbeam and Wasmtime"
|
||||
license = "Apache-2.0 WITH LLVM-exception"
|
||||
repository = "https://github.com/bytecodealliance/wasmtime"
|
||||
documentation = "https://docs.rs/wasmtime-lightbeam/"
|
||||
categories = ["wasm"]
|
||||
keywords = ["webassembly", "wasm"]
|
||||
readme = "README.md"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
lightbeam = { path = "..", version = "0.19.0" }
|
||||
wasmparser = "0.59"
|
||||
cranelift-codegen = { path = "../../../cranelift/codegen", version = "0.66.0" }
|
||||
wasmtime-environ = { path = "../../environ", version = "0.19.0" }
|
||||
4
crates/lightbeam/wasmtime/README.md
Normal file
4
crates/lightbeam/wasmtime/README.md
Normal file
@@ -0,0 +1,4 @@
|
||||
# `wasmtime-lightbeam`
|
||||
|
||||
This crate provides an implementation of the `Compiler` trait which is
|
||||
connected to Lightbeam.
|
||||
334
crates/lightbeam/wasmtime/src/lib.rs
Normal file
334
crates/lightbeam/wasmtime/src/lib.rs
Normal file
@@ -0,0 +1,334 @@
|
||||
//! Support for compiling with Lightbeam.
|
||||
//!
|
||||
//! This crates provides an implementation of [`Compiler`] in the form of
|
||||
//! [`Lightbeam`].
|
||||
|
||||
use cranelift_codegen::binemit;
|
||||
use cranelift_codegen::ir::{self, ExternalName};
|
||||
use cranelift_codegen::isa;
|
||||
use lightbeam::{CodeGenSession, NullOffsetSink, Sinks};
|
||||
use wasmtime_environ::wasm::{
|
||||
DefinedFuncIndex, DefinedGlobalIndex, DefinedMemoryIndex, DefinedTableIndex, FuncIndex,
|
||||
GlobalIndex, MemoryIndex, SignatureIndex, TableIndex,
|
||||
};
|
||||
use wasmtime_environ::{
|
||||
BuiltinFunctionIndex, CompileError, CompiledFunction, Compiler, FunctionBodyData, Module,
|
||||
ModuleTranslation, Relocation, RelocationTarget, TrapInformation, VMOffsets,
|
||||
};
|
||||
|
||||
/// A compiler that compiles a WebAssembly module with Lightbeam, directly translating the Wasm file.
|
||||
pub struct Lightbeam;
|
||||
|
||||
impl Compiler for Lightbeam {
|
||||
fn compile_function(
|
||||
&self,
|
||||
translation: &ModuleTranslation,
|
||||
i: DefinedFuncIndex,
|
||||
function_body: &FunctionBodyData<'_>,
|
||||
isa: &dyn isa::TargetIsa,
|
||||
) -> Result<CompiledFunction, CompileError> {
|
||||
if translation.tunables.debug_info {
|
||||
return Err(CompileError::DebugInfoNotSupported);
|
||||
}
|
||||
let func_index = translation.module.func_index(i);
|
||||
|
||||
let env = FuncEnvironment::new(isa.frontend_config().pointer_bytes(), &translation.module);
|
||||
let mut codegen_session: CodeGenSession<_> = CodeGenSession::new(
|
||||
translation.function_body_inputs.len() as u32,
|
||||
&env,
|
||||
lightbeam::microwasm::I32,
|
||||
);
|
||||
|
||||
let mut reloc_sink = RelocSink::new(func_index);
|
||||
let mut trap_sink = TrapSink::new();
|
||||
lightbeam::translate_function(
|
||||
&mut codegen_session,
|
||||
Sinks {
|
||||
relocs: &mut reloc_sink,
|
||||
traps: &mut trap_sink,
|
||||
offsets: &mut NullOffsetSink,
|
||||
},
|
||||
i.as_u32(),
|
||||
wasmparser::FunctionBody::new(0, function_body.data),
|
||||
)
|
||||
.map_err(|e| CompileError::Codegen(format!("Failed to translate function: {}", e)))?;
|
||||
|
||||
let code_section = codegen_session
|
||||
.into_translated_code_section()
|
||||
.map_err(|e| CompileError::Codegen(format!("Failed to generate output code: {}", e)))?;
|
||||
|
||||
Ok(CompiledFunction {
|
||||
// TODO: try to remove copy here (?)
|
||||
body: code_section.buffer().to_vec(),
|
||||
traps: trap_sink.traps,
|
||||
relocations: reloc_sink.func_relocs,
|
||||
|
||||
// not implemented for lightbeam currently
|
||||
unwind_info: None,
|
||||
stack_maps: Default::default(),
|
||||
stack_slots: Default::default(),
|
||||
value_labels_ranges: Default::default(),
|
||||
address_map: Default::default(),
|
||||
jt_offsets: Default::default(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Implementation of a relocation sink that just saves all the information for later
|
||||
struct RelocSink {
|
||||
/// Current function index.
|
||||
func_index: FuncIndex,
|
||||
|
||||
/// Relocations recorded for the function.
|
||||
func_relocs: Vec<Relocation>,
|
||||
}
|
||||
|
||||
impl binemit::RelocSink for RelocSink {
|
||||
fn reloc_block(
|
||||
&mut self,
|
||||
_offset: binemit::CodeOffset,
|
||||
_reloc: binemit::Reloc,
|
||||
_block_offset: binemit::CodeOffset,
|
||||
) {
|
||||
// This should use the `offsets` field of `ir::Function`.
|
||||
panic!("block headers not yet implemented");
|
||||
}
|
||||
fn reloc_external(
|
||||
&mut self,
|
||||
offset: binemit::CodeOffset,
|
||||
_srcloc: ir::SourceLoc,
|
||||
reloc: binemit::Reloc,
|
||||
name: &ExternalName,
|
||||
addend: binemit::Addend,
|
||||
) {
|
||||
let reloc_target = if let ExternalName::User { namespace, index } = *name {
|
||||
debug_assert_eq!(namespace, 0);
|
||||
RelocationTarget::UserFunc(FuncIndex::from_u32(index))
|
||||
} else if let ExternalName::LibCall(libcall) = *name {
|
||||
RelocationTarget::LibCall(libcall)
|
||||
} else {
|
||||
panic!("unrecognized external name")
|
||||
};
|
||||
self.func_relocs.push(Relocation {
|
||||
reloc,
|
||||
reloc_target,
|
||||
offset,
|
||||
addend,
|
||||
});
|
||||
}
|
||||
|
||||
fn reloc_constant(
|
||||
&mut self,
|
||||
_code_offset: binemit::CodeOffset,
|
||||
_reloc: binemit::Reloc,
|
||||
_constant_offset: ir::ConstantOffset,
|
||||
) {
|
||||
// Do nothing for now: cranelift emits constant data after the function code and also emits
|
||||
// function code with correct relative offsets to the constant data.
|
||||
}
|
||||
|
||||
fn reloc_jt(&mut self, offset: binemit::CodeOffset, reloc: binemit::Reloc, jt: ir::JumpTable) {
|
||||
self.func_relocs.push(Relocation {
|
||||
reloc,
|
||||
reloc_target: RelocationTarget::JumpTable(self.func_index, jt),
|
||||
offset,
|
||||
addend: 0,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl RelocSink {
|
||||
/// Return a new `RelocSink` instance.
|
||||
fn new(func_index: FuncIndex) -> Self {
|
||||
Self {
|
||||
func_index,
|
||||
func_relocs: Vec::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Implementation of a trap sink that simply stores all trap info in-memory
|
||||
#[derive(Default)]
|
||||
struct TrapSink {
|
||||
/// The in-memory vector of trap info
|
||||
traps: Vec<TrapInformation>,
|
||||
}
|
||||
|
||||
impl TrapSink {
|
||||
/// Create a new `TrapSink`
|
||||
fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
}
|
||||
|
||||
impl binemit::TrapSink for TrapSink {
|
||||
fn trap(
|
||||
&mut self,
|
||||
code_offset: binemit::CodeOffset,
|
||||
source_loc: ir::SourceLoc,
|
||||
trap_code: ir::TrapCode,
|
||||
) {
|
||||
self.traps.push(TrapInformation {
|
||||
code_offset,
|
||||
source_loc,
|
||||
trap_code,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// The `FuncEnvironment` implementation for use by the `ModuleEnvironment`.
|
||||
struct FuncEnvironment<'module_environment> {
|
||||
/// The module-level environment which this function-level environment belongs to.
|
||||
module: &'module_environment Module,
|
||||
|
||||
/// Offsets to struct fields accessed by JIT code.
|
||||
offsets: VMOffsets,
|
||||
}
|
||||
|
||||
impl<'module_environment> FuncEnvironment<'module_environment> {
|
||||
fn new(pointer_bytes: u8, module: &'module_environment Module) -> Self {
|
||||
Self {
|
||||
module,
|
||||
offsets: VMOffsets::new(pointer_bytes, module),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: This is necessary as if Lightbeam used `FuncEnvironment` directly it would cause
|
||||
// a circular dependency graph. We should extract common types out into a separate
|
||||
// crate that Lightbeam can use but until then we need this trait.
|
||||
impl lightbeam::ModuleContext for FuncEnvironment<'_> {
|
||||
type Signature = ir::Signature;
|
||||
type GlobalType = ir::Type;
|
||||
|
||||
fn func_index(&self, defined_func_index: u32) -> u32 {
|
||||
self.module
|
||||
.func_index(DefinedFuncIndex::from_u32(defined_func_index))
|
||||
.as_u32()
|
||||
}
|
||||
|
||||
fn defined_func_index(&self, func_index: u32) -> Option<u32> {
|
||||
self.module
|
||||
.defined_func_index(FuncIndex::from_u32(func_index))
|
||||
.map(DefinedFuncIndex::as_u32)
|
||||
}
|
||||
|
||||
fn defined_global_index(&self, global_index: u32) -> Option<u32> {
|
||||
self.module
|
||||
.defined_global_index(GlobalIndex::from_u32(global_index))
|
||||
.map(DefinedGlobalIndex::as_u32)
|
||||
}
|
||||
|
||||
fn global_type(&self, global_index: u32) -> &Self::GlobalType {
|
||||
&self.module.globals[GlobalIndex::from_u32(global_index)].ty
|
||||
}
|
||||
|
||||
fn func_type_index(&self, func_idx: u32) -> u32 {
|
||||
self.module.functions[FuncIndex::from_u32(func_idx)].as_u32()
|
||||
}
|
||||
|
||||
fn signature(&self, index: u32) -> &Self::Signature {
|
||||
&self.module.signatures[SignatureIndex::from_u32(index)].1
|
||||
}
|
||||
|
||||
fn defined_table_index(&self, table_index: u32) -> Option<u32> {
|
||||
self.module
|
||||
.defined_table_index(TableIndex::from_u32(table_index))
|
||||
.map(DefinedTableIndex::as_u32)
|
||||
}
|
||||
|
||||
fn defined_memory_index(&self, memory_index: u32) -> Option<u32> {
|
||||
self.module
|
||||
.defined_memory_index(MemoryIndex::from_u32(memory_index))
|
||||
.map(DefinedMemoryIndex::as_u32)
|
||||
}
|
||||
|
||||
fn vmctx_builtin_function(&self, func_index: u32) -> u32 {
|
||||
self.offsets
|
||||
.vmctx_builtin_function(BuiltinFunctionIndex::from_u32(func_index))
|
||||
}
|
||||
|
||||
fn vmctx_vmfunction_import_body(&self, func_index: u32) -> u32 {
|
||||
self.offsets
|
||||
.vmctx_vmfunction_import_body(FuncIndex::from_u32(func_index))
|
||||
}
|
||||
fn vmctx_vmfunction_import_vmctx(&self, func_index: u32) -> u32 {
|
||||
self.offsets
|
||||
.vmctx_vmfunction_import_vmctx(FuncIndex::from_u32(func_index))
|
||||
}
|
||||
|
||||
fn vmctx_vmglobal_import_from(&self, global_index: u32) -> u32 {
|
||||
self.offsets
|
||||
.vmctx_vmglobal_import_from(GlobalIndex::from_u32(global_index))
|
||||
}
|
||||
fn vmctx_vmglobal_definition(&self, defined_global_index: u32) -> u32 {
|
||||
self.offsets
|
||||
.vmctx_vmglobal_definition(DefinedGlobalIndex::from_u32(defined_global_index))
|
||||
}
|
||||
fn vmctx_vmmemory_import_from(&self, memory_index: u32) -> u32 {
|
||||
self.offsets
|
||||
.vmctx_vmmemory_import_from(MemoryIndex::from_u32(memory_index))
|
||||
}
|
||||
fn vmctx_vmmemory_definition(&self, defined_memory_index: u32) -> u32 {
|
||||
self.offsets
|
||||
.vmctx_vmmemory_definition(DefinedMemoryIndex::from_u32(defined_memory_index))
|
||||
}
|
||||
fn vmctx_vmmemory_definition_base(&self, defined_memory_index: u32) -> u32 {
|
||||
self.offsets
|
||||
.vmctx_vmmemory_definition_base(DefinedMemoryIndex::from_u32(defined_memory_index))
|
||||
}
|
||||
fn vmctx_vmmemory_definition_current_length(&self, defined_memory_index: u32) -> u32 {
|
||||
self.offsets
|
||||
.vmctx_vmmemory_definition_current_length(DefinedMemoryIndex::from_u32(
|
||||
defined_memory_index,
|
||||
))
|
||||
}
|
||||
fn vmmemory_definition_base(&self) -> u8 {
|
||||
self.offsets.vmmemory_definition_base()
|
||||
}
|
||||
fn vmmemory_definition_current_length(&self) -> u8 {
|
||||
self.offsets.vmmemory_definition_current_length()
|
||||
}
|
||||
fn vmctx_vmtable_import_from(&self, table_index: u32) -> u32 {
|
||||
self.offsets
|
||||
.vmctx_vmtable_import_from(TableIndex::from_u32(table_index))
|
||||
}
|
||||
fn vmctx_vmtable_definition(&self, defined_table_index: u32) -> u32 {
|
||||
self.offsets
|
||||
.vmctx_vmtable_definition(DefinedTableIndex::from_u32(defined_table_index))
|
||||
}
|
||||
fn vmctx_vmtable_definition_base(&self, defined_table_index: u32) -> u32 {
|
||||
self.offsets
|
||||
.vmctx_vmtable_definition_base(DefinedTableIndex::from_u32(defined_table_index))
|
||||
}
|
||||
fn vmctx_vmtable_definition_current_elements(&self, defined_table_index: u32) -> u32 {
|
||||
self.offsets
|
||||
.vmctx_vmtable_definition_current_elements(DefinedTableIndex::from_u32(
|
||||
defined_table_index,
|
||||
))
|
||||
}
|
||||
fn vmtable_definition_base(&self) -> u8 {
|
||||
self.offsets.vmtable_definition_base()
|
||||
}
|
||||
fn vmtable_definition_current_elements(&self) -> u8 {
|
||||
self.offsets.vmtable_definition_current_elements()
|
||||
}
|
||||
fn vmcaller_checked_anyfunc_type_index(&self) -> u8 {
|
||||
self.offsets.vmcaller_checked_anyfunc_type_index()
|
||||
}
|
||||
fn vmcaller_checked_anyfunc_func_ptr(&self) -> u8 {
|
||||
self.offsets.vmcaller_checked_anyfunc_func_ptr()
|
||||
}
|
||||
fn vmcaller_checked_anyfunc_vmctx(&self) -> u8 {
|
||||
self.offsets.vmcaller_checked_anyfunc_vmctx()
|
||||
}
|
||||
fn size_of_vmcaller_checked_anyfunc(&self) -> u8 {
|
||||
self.offsets.size_of_vmcaller_checked_anyfunc()
|
||||
}
|
||||
fn vmctx_vmshared_signature_id(&self, signature_idx: u32) -> u32 {
|
||||
self.offsets
|
||||
.vmctx_vmshared_signature_id(SignatureIndex::from_u32(signature_idx))
|
||||
}
|
||||
|
||||
// TODO: type of a global
|
||||
}
|
||||
@@ -13,7 +13,7 @@ edition = "2018"
|
||||
[dependencies]
|
||||
anyhow = "1.0"
|
||||
wasmtime-environ = { path = "../environ", version = "0.19.0" }
|
||||
object = { version = "0.20", default-features = false, features = ["write"] }
|
||||
object = { version = "0.21.1", default-features = false, features = ["write"] }
|
||||
more-asserts = "0.2.1"
|
||||
target-lexicon = { version = "0.10.0", default-features = false }
|
||||
wasmtime-debug = { path = "../debug", version = "0.19.0" }
|
||||
|
||||
@@ -22,7 +22,6 @@ thiserror = "1.0"
|
||||
libc = "0.2"
|
||||
getrandom = { version = "0.1.14", features = ["std"] }
|
||||
cfg-if = "0.1.9"
|
||||
log = "0.4"
|
||||
filetime = "0.2.7"
|
||||
lazy_static = "1.4.0"
|
||||
wig = { path = "wig", version = "0.19.0" }
|
||||
@@ -45,7 +44,7 @@ default = ["trace_log"]
|
||||
# This feature enables the `tracing` logs in the calls to target the `log`
|
||||
# ecosystem of backends (e.g. `env_logger`. Disable this if you want to use
|
||||
# `tracing-subscriber`.
|
||||
trace_log = [ "wiggle/tracing_log" ]
|
||||
trace_log = [ "wiggle/tracing_log", "tracing/log" ]
|
||||
# Need to make the wiggle_metadata feature available to consumers of this
|
||||
# crate if they want the snapshots to have metadata available.
|
||||
wiggle_metadata = ["wiggle/wiggle_metadata"]
|
||||
|
||||
@@ -359,7 +359,10 @@ impl WasiCtxBuilder {
|
||||
self.stdout.take().unwrap(),
|
||||
self.stderr.take().unwrap(),
|
||||
] {
|
||||
log::debug!("WasiCtx inserting entry {:?}", pending);
|
||||
tracing::debug!(
|
||||
pending = tracing::field::debug(&pending),
|
||||
"WasiCtx inserting entry"
|
||||
);
|
||||
let fd = match pending {
|
||||
PendingEntry::Thunk(f) => {
|
||||
let handle = EntryHandle::from(f()?);
|
||||
@@ -376,7 +379,7 @@ impl WasiCtxBuilder {
|
||||
.ok_or(WasiCtxBuilderError::TooManyFilesOpen)?
|
||||
}
|
||||
};
|
||||
log::debug!("WasiCtx inserted at {:?}", fd);
|
||||
tracing::debug!(fd = tracing::field::debug(fd), "WasiCtx inserted");
|
||||
}
|
||||
// Then add the preopen entries.
|
||||
for (guest_path, preopen) in self.preopens.take().unwrap() {
|
||||
@@ -386,7 +389,7 @@ impl WasiCtxBuilder {
|
||||
let fd = entries
|
||||
.insert(entry)
|
||||
.ok_or(WasiCtxBuilderError::TooManyFilesOpen)?;
|
||||
log::debug!("WasiCtx inserted at {:?}", fd);
|
||||
tracing::debug!(fd = tracing::field::debug(fd), "WasiCtx inserted",);
|
||||
}
|
||||
|
||||
Ok(WasiCtx {
|
||||
|
||||
@@ -18,6 +18,12 @@ impl EntryHandle {
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for EntryHandle {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
f.debug_struct("EntryHandle").field("opaque", &()).finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Box<dyn Handle>> for EntryHandle {
|
||||
fn from(handle: Box<dyn Handle>) -> Self {
|
||||
Self(handle.into())
|
||||
@@ -87,10 +93,10 @@ impl Entry {
|
||||
if this_rights.contains(rights) {
|
||||
Ok(())
|
||||
} else {
|
||||
log::trace!(
|
||||
" | validate_rights failed: required rights = {}; actual rights = {}",
|
||||
rights,
|
||||
this_rights,
|
||||
tracing::trace!(
|
||||
required = tracing::field::display(rights),
|
||||
actual = tracing::field::display(this_rights),
|
||||
"validate_rights failed",
|
||||
);
|
||||
Err(Error::Notcapable)
|
||||
}
|
||||
|
||||
@@ -287,7 +287,7 @@ impl WasiCtxBuilder {
|
||||
let fd = fd_pool
|
||||
.allocate()
|
||||
.ok_or(WasiCtxBuilderError::TooManyFilesOpen)?;
|
||||
log::debug!("WasiCtx inserting ({:?}, {:?})", fd, pending);
|
||||
tracing::debug!("WasiCtx inserting ({:?}, {:?})", fd, pending);
|
||||
match pending.take().unwrap() {
|
||||
PendingEntry::Thunk(f) => {
|
||||
entries.insert(fd, f()?);
|
||||
@@ -311,9 +311,9 @@ impl WasiCtxBuilder {
|
||||
|
||||
let mut fe = Entry::from(dir)?;
|
||||
fe.preopen_path = Some(guest_path);
|
||||
log::debug!("WasiCtx inserting ({:?}, {:?})", preopen_fd, fe);
|
||||
tracing::debug!("WasiCtx inserting ({:?}, {:?})", preopen_fd, fe);
|
||||
entries.insert(preopen_fd, fe);
|
||||
log::debug!("WasiCtx entries = {:?}", entries);
|
||||
tracing::debug!("WasiCtx entries = {:?}", entries);
|
||||
}
|
||||
|
||||
Ok(WasiCtx {
|
||||
|
||||
@@ -11,11 +11,11 @@ use crate::old::snapshot_0::wasi::{self, WasiError, WasiResult};
|
||||
use crate::old::snapshot_0::{helpers, host, wasi32};
|
||||
use crate::sandboxed_tty_writer::SandboxedTTYWriter;
|
||||
use filetime::{set_file_handle_times, FileTime};
|
||||
use log::trace;
|
||||
use std::fs::File;
|
||||
use std::io::{self, Read, Seek, SeekFrom, Write};
|
||||
use std::ops::DerefMut;
|
||||
use std::time::{Duration, SystemTime, UNIX_EPOCH};
|
||||
use tracing::trace;
|
||||
|
||||
pub(crate) unsafe fn fd_close(
|
||||
wasi_ctx: &mut WasiCtx,
|
||||
@@ -686,8 +686,8 @@ pub(crate) unsafe fn path_rename(
|
||||
true,
|
||||
)?;
|
||||
|
||||
log::debug!("path_rename resolved_old={:?}", resolved_old);
|
||||
log::debug!("path_rename resolved_new={:?}", resolved_new);
|
||||
tracing::debug!("path_rename resolved_old={:?}", resolved_old);
|
||||
tracing::debug!("path_rename resolved_new={:?}", resolved_new);
|
||||
|
||||
hostcalls_impl::path_rename(resolved_old, resolved_new)
|
||||
}
|
||||
@@ -950,7 +950,7 @@ pub(crate) unsafe fn path_remove_directory(
|
||||
true,
|
||||
)?;
|
||||
|
||||
log::debug!("path_remove_directory resolved={:?}", resolved);
|
||||
tracing::debug!("path_remove_directory resolved={:?}", resolved);
|
||||
|
||||
hostcalls_impl::path_remove_directory(resolved)
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ pub(crate) fn path_get(
|
||||
loop {
|
||||
match path_stack.pop() {
|
||||
Some(cur_path) => {
|
||||
log::debug!("path_get cur_path = {:?}", cur_path);
|
||||
tracing::debug!("path_get cur_path = {:?}", cur_path);
|
||||
|
||||
let ends_with_slash = cur_path.ends_with('/');
|
||||
let mut components = Path::new(&cur_path).components();
|
||||
@@ -86,7 +86,7 @@ pub(crate) fn path_get(
|
||||
path_stack.push(tail);
|
||||
}
|
||||
|
||||
log::debug!("path_get path_stack = {:?}", path_stack);
|
||||
tracing::debug!("path_get path_stack = {:?}", path_stack);
|
||||
|
||||
match head {
|
||||
Component::Prefix(_) | Component::RootDir => {
|
||||
@@ -140,7 +140,7 @@ pub(crate) fn path_get(
|
||||
link_path.push('/');
|
||||
}
|
||||
|
||||
log::debug!(
|
||||
tracing::debug!(
|
||||
"attempted symlink expansion link_path={:?}",
|
||||
link_path
|
||||
);
|
||||
@@ -172,7 +172,7 @@ pub(crate) fn path_get(
|
||||
link_path.push('/');
|
||||
}
|
||||
|
||||
log::debug!(
|
||||
tracing::debug!(
|
||||
"attempted symlink expansion link_path={:?}",
|
||||
link_path
|
||||
);
|
||||
|
||||
@@ -5,8 +5,8 @@ use crate::old::snapshot_0::memory::*;
|
||||
use crate::old::snapshot_0::sys::hostcalls_impl;
|
||||
use crate::old::snapshot_0::wasi::{self, WasiError, WasiResult};
|
||||
use crate::old::snapshot_0::wasi32;
|
||||
use log::{error, trace};
|
||||
use std::convert::TryFrom;
|
||||
use tracing::{error, trace};
|
||||
|
||||
pub(crate) fn args_get(
|
||||
wasi_ctx: &WasiCtx,
|
||||
@@ -227,8 +227,8 @@ pub(crate) fn poll_oneoff(
|
||||
let clock = unsafe { subscription.u.u.clock };
|
||||
let delay = wasi_clock_to_relative_ns_delay(clock)?;
|
||||
|
||||
log::debug!("poll_oneoff event.u.clock = {:?}", clock);
|
||||
log::debug!("poll_oneoff delay = {:?}ns", delay);
|
||||
tracing::debug!("poll_oneoff event.u.clock = {:?}", clock);
|
||||
tracing::debug!("poll_oneoff delay = {:?}ns", delay);
|
||||
|
||||
let current = ClockEventData {
|
||||
delay,
|
||||
@@ -299,8 +299,8 @@ pub(crate) fn poll_oneoff(
|
||||
}
|
||||
}
|
||||
|
||||
log::debug!("poll_oneoff timeout = {:?}", timeout);
|
||||
log::debug!("poll_oneoff fd_events = {:?}", fd_events);
|
||||
tracing::debug!("poll_oneoff timeout = {:?}", timeout);
|
||||
tracing::debug!("poll_oneoff fd_events = {:?}", fd_events);
|
||||
|
||||
hostcalls_impl::poll_oneoff(timeout, fd_events, &mut events)?;
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ pub(crate) fn path_unlink_file(resolved: PathGet) -> WasiResult<()> {
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
log::debug!("path_unlink_file fstatat error: {:?}", err);
|
||||
tracing::debug!("path_unlink_file fstatat error: {:?}", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -50,8 +50,8 @@ pub(crate) fn path_unlink_file(resolved: PathGet) -> WasiResult<()> {
|
||||
pub(crate) fn path_symlink(old_path: &str, resolved: PathGet) -> WasiResult<()> {
|
||||
use yanix::file::{fstatat, symlinkat, AtFlags};
|
||||
|
||||
log::debug!("path_symlink old_path = {:?}", old_path);
|
||||
log::debug!("path_symlink resolved = {:?}", resolved);
|
||||
tracing::debug!("path_symlink old_path = {:?}", old_path);
|
||||
tracing::debug!("path_symlink resolved = {:?}", resolved);
|
||||
|
||||
match unsafe { symlinkat(old_path, resolved.dirfd().as_raw_fd(), resolved.path()) } {
|
||||
Err(err) => {
|
||||
@@ -71,7 +71,7 @@ pub(crate) fn path_symlink(old_path: &str, resolved: PathGet) -> WasiResult<()>
|
||||
} {
|
||||
Ok(_) => return Err(WasiError::EEXIST),
|
||||
Err(err) => {
|
||||
log::debug!("path_symlink fstatat error: {:?}", err);
|
||||
tracing::debug!("path_symlink fstatat error: {:?}", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -119,7 +119,7 @@ pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> WasiR
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
log::debug!("path_rename fstatat error: {:?}", err);
|
||||
tracing::debug!("path_rename fstatat error: {:?}", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,14 +61,14 @@ pub(crate) unsafe fn determine_type_rights<Fd: AsRawFd>(
|
||||
let file = std::mem::ManuallyDrop::new(std::fs::File::from_raw_fd(fd.as_raw_fd()));
|
||||
let ft = file.metadata()?.file_type();
|
||||
if ft.is_block_device() {
|
||||
log::debug!("Host fd {:?} is a block device", fd.as_raw_fd());
|
||||
tracing::debug!("Host fd {:?} is a block device", fd.as_raw_fd());
|
||||
(
|
||||
wasi::__WASI_FILETYPE_BLOCK_DEVICE,
|
||||
wasi::RIGHTS_BLOCK_DEVICE_BASE,
|
||||
wasi::RIGHTS_BLOCK_DEVICE_INHERITING,
|
||||
)
|
||||
} else if ft.is_char_device() {
|
||||
log::debug!("Host fd {:?} is a char device", fd.as_raw_fd());
|
||||
tracing::debug!("Host fd {:?} is a char device", fd.as_raw_fd());
|
||||
use yanix::file::isatty;
|
||||
if isatty(fd.as_raw_fd())? {
|
||||
(
|
||||
@@ -84,21 +84,21 @@ pub(crate) unsafe fn determine_type_rights<Fd: AsRawFd>(
|
||||
)
|
||||
}
|
||||
} else if ft.is_dir() {
|
||||
log::debug!("Host fd {:?} is a directory", fd.as_raw_fd());
|
||||
tracing::debug!("Host fd {:?} is a directory", fd.as_raw_fd());
|
||||
(
|
||||
wasi::__WASI_FILETYPE_DIRECTORY,
|
||||
wasi::RIGHTS_DIRECTORY_BASE,
|
||||
wasi::RIGHTS_DIRECTORY_INHERITING,
|
||||
)
|
||||
} else if ft.is_file() {
|
||||
log::debug!("Host fd {:?} is a file", fd.as_raw_fd());
|
||||
tracing::debug!("Host fd {:?} is a file", fd.as_raw_fd());
|
||||
(
|
||||
wasi::__WASI_FILETYPE_REGULAR_FILE,
|
||||
wasi::RIGHTS_REGULAR_FILE_BASE,
|
||||
wasi::RIGHTS_REGULAR_FILE_INHERITING,
|
||||
)
|
||||
} else if ft.is_socket() {
|
||||
log::debug!("Host fd {:?} is a socket", fd.as_raw_fd());
|
||||
tracing::debug!("Host fd {:?} is a socket", fd.as_raw_fd());
|
||||
use yanix::socket::{get_socket_type, SockType};
|
||||
match get_socket_type(fd.as_raw_fd())? {
|
||||
SockType::Datagram => (
|
||||
@@ -114,14 +114,14 @@ pub(crate) unsafe fn determine_type_rights<Fd: AsRawFd>(
|
||||
_ => return Err(io::Error::from_raw_os_error(libc::EINVAL)),
|
||||
}
|
||||
} else if ft.is_fifo() {
|
||||
log::debug!("Host fd {:?} is a fifo", fd.as_raw_fd());
|
||||
tracing::debug!("Host fd {:?} is a fifo", fd.as_raw_fd());
|
||||
(
|
||||
wasi::__WASI_FILETYPE_UNKNOWN,
|
||||
wasi::RIGHTS_REGULAR_FILE_BASE,
|
||||
wasi::RIGHTS_REGULAR_FILE_INHERITING,
|
||||
)
|
||||
} else {
|
||||
log::debug!("Host fd {:?} is unknown", fd.as_raw_fd());
|
||||
tracing::debug!("Host fd {:?} is unknown", fd.as_raw_fd());
|
||||
return Err(io::Error::from_raw_os_error(libc::EINVAL));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -92,12 +92,12 @@ impl From<io::Error> for WasiError {
|
||||
libc::ENOTRECOVERABLE => Self::ENOTRECOVERABLE,
|
||||
libc::ENOTSUP => Self::ENOTSUP,
|
||||
x => {
|
||||
log::debug!("Unknown errno value: {}", x);
|
||||
tracing::debug!("Unknown errno value: {}", x);
|
||||
Self::EIO
|
||||
}
|
||||
},
|
||||
None => {
|
||||
log::debug!("Other I/O error: {}", err);
|
||||
tracing::debug!("Other I/O error: {}", err);
|
||||
Self::EIO
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,8 +115,8 @@ pub(crate) fn path_open(
|
||||
// umask is, but don't set the executable flag, because it isn't yet
|
||||
// meaningful for WASI programs to create executable files.
|
||||
|
||||
log::debug!("path_open resolved = {:?}", resolved);
|
||||
log::debug!("path_open oflags = {:?}", nix_all_oflags);
|
||||
tracing::debug!("path_open resolved = {:?}", resolved);
|
||||
tracing::debug!("path_open oflags = {:?}", nix_all_oflags);
|
||||
|
||||
let new_fd = match unsafe {
|
||||
openat(
|
||||
@@ -144,7 +144,7 @@ pub(crate) fn path_open(
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
log::debug!("path_open fstatat error: {:?}", err);
|
||||
tracing::debug!("path_open fstatat error: {:?}", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -166,7 +166,7 @@ pub(crate) fn path_open(
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
log::debug!("path_open fstatat error: {:?}", err);
|
||||
tracing::debug!("path_open fstatat error: {:?}", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -182,7 +182,7 @@ pub(crate) fn path_open(
|
||||
}
|
||||
};
|
||||
|
||||
log::debug!("path_open (host) new_fd = {:?}", new_fd);
|
||||
tracing::debug!("path_open (host) new_fd = {:?}", new_fd);
|
||||
|
||||
// Determine the type of the new file descriptor and which rights contradict with this type
|
||||
Ok(unsafe { File::from_raw_fd(new_fd) })
|
||||
@@ -294,10 +294,10 @@ pub(crate) fn fd_readdir<'a>(
|
||||
// Seek if needed. Unless cookie is wasi::__WASI_DIRCOOKIE_START,
|
||||
// new items may not be returned to the caller.
|
||||
if cookie == wasi::__WASI_DIRCOOKIE_START {
|
||||
log::trace!(" | fd_readdir: doing rewinddir");
|
||||
tracing::trace!(" | fd_readdir: doing rewinddir");
|
||||
dir.rewind();
|
||||
} else {
|
||||
log::trace!(" | fd_readdir: doing seekdir to {}", cookie);
|
||||
tracing::trace!(" | fd_readdir: doing seekdir to {}", cookie);
|
||||
let loc = unsafe { SeekLoc::from_raw(cookie as i64)? };
|
||||
dir.seek(loc);
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ pub(crate) fn openat(dirfd: &File, path: &str) -> WasiResult<File> {
|
||||
use std::os::unix::prelude::{AsRawFd, FromRawFd};
|
||||
use yanix::file::{openat, Mode};
|
||||
|
||||
log::debug!("path_get openat path = {:?}", path);
|
||||
tracing::debug!("path_get openat path = {:?}", path);
|
||||
|
||||
unsafe {
|
||||
openat(
|
||||
@@ -58,7 +58,7 @@ pub(crate) fn readlinkat(dirfd: &File, path: &str) -> WasiResult<String> {
|
||||
use std::os::unix::prelude::AsRawFd;
|
||||
use yanix::file::readlinkat;
|
||||
|
||||
log::debug!("path_get readlinkat path = {:?}", path);
|
||||
tracing::debug!("path_get readlinkat path = {:?}", path);
|
||||
|
||||
unsafe { readlinkat(dirfd.as_raw_fd(), path) }
|
||||
.map_err(Into::into)
|
||||
|
||||
@@ -85,7 +85,7 @@ pub(crate) fn poll_oneoff(
|
||||
let delay = timeout.delay / 1_000_000; // poll syscall requires delay to expressed in milliseconds
|
||||
delay.try_into().unwrap_or(libc::c_int::max_value())
|
||||
});
|
||||
log::debug!("poll_oneoff poll_timeout = {:?}", poll_timeout);
|
||||
tracing::debug!("poll_oneoff poll_timeout = {:?}", poll_timeout);
|
||||
|
||||
let ready = loop {
|
||||
match poll(&mut poll_fds, poll_timeout) {
|
||||
@@ -131,15 +131,15 @@ fn poll_oneoff_handle_fd_event<'a>(
|
||||
use yanix::{file::fionread, poll::PollFlags};
|
||||
|
||||
for (fd_event, poll_fd) in ready_events {
|
||||
log::debug!("poll_oneoff_handle_fd_event fd_event = {:?}", fd_event);
|
||||
log::debug!("poll_oneoff_handle_fd_event poll_fd = {:?}", poll_fd);
|
||||
tracing::debug!("poll_oneoff_handle_fd_event fd_event = {:?}", fd_event);
|
||||
tracing::debug!("poll_oneoff_handle_fd_event poll_fd = {:?}", poll_fd);
|
||||
|
||||
let revents = match poll_fd.revents() {
|
||||
Some(revents) => revents,
|
||||
None => continue,
|
||||
};
|
||||
|
||||
log::debug!("poll_oneoff_handle_fd_event revents = {:?}", revents);
|
||||
tracing::debug!("poll_oneoff_handle_fd_event revents = {:?}", revents);
|
||||
|
||||
let nbytes = if fd_event.r#type == wasi::__WASI_EVENTTYPE_FD_READ {
|
||||
unsafe { fionread(fd_event.descriptor.as_raw_fd())? }
|
||||
|
||||
@@ -17,8 +17,8 @@ pub(crate) fn path_unlink_file(resolved: PathGet) -> WasiResult<()> {
|
||||
pub(crate) fn path_symlink(old_path: &str, resolved: PathGet) -> WasiResult<()> {
|
||||
use yanix::file::symlinkat;
|
||||
|
||||
log::debug!("path_symlink old_path = {:?}", old_path);
|
||||
log::debug!("path_symlink resolved = {:?}", resolved);
|
||||
tracing::debug!("path_symlink old_path = {:?}", old_path);
|
||||
tracing::debug!("path_symlink resolved = {:?}", resolved);
|
||||
|
||||
unsafe { symlinkat(old_path, resolved.dirfd().as_raw_fd(), resolved.path()) }
|
||||
.map_err(Into::into)
|
||||
|
||||
@@ -43,12 +43,12 @@ impl From<io::Error> for WasiError {
|
||||
winerror::ERROR_DIRECTORY => Self::ENOTDIR,
|
||||
winerror::ERROR_ALREADY_EXISTS => Self::EEXIST,
|
||||
x => {
|
||||
log::debug!("unknown error value: {}", x);
|
||||
tracing::debug!("unknown error value: {}", x);
|
||||
Self::EIO
|
||||
}
|
||||
},
|
||||
None => {
|
||||
log::debug!("Other I/O error: {}", err);
|
||||
tracing::debug!("Other I/O error: {}", err);
|
||||
Self::EIO
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,13 +9,13 @@ use crate::old::snapshot_0::sys::entry_impl::determine_type_rights;
|
||||
use crate::old::snapshot_0::sys::host_impl::{self, path_from_host};
|
||||
use crate::old::snapshot_0::sys::hostcalls_impl::fs_helpers::PathGetExt;
|
||||
use crate::old::snapshot_0::wasi::{self, WasiError, WasiResult};
|
||||
use log::{debug, trace};
|
||||
use std::convert::TryInto;
|
||||
use std::fs::{File, Metadata, OpenOptions};
|
||||
use std::io::{self, Seek, SeekFrom};
|
||||
use std::os::windows::fs::{FileExt, OpenOptionsExt};
|
||||
use std::os::windows::prelude::{AsRawHandle, FromRawHandle};
|
||||
use std::path::{Path, PathBuf};
|
||||
use tracing::{debug, trace};
|
||||
use winapi::shared::winerror;
|
||||
use winx::file::{AccessMode, CreationDisposition, FileModeInformation, Flags};
|
||||
|
||||
@@ -156,7 +156,7 @@ pub(crate) fn path_open(
|
||||
}
|
||||
Err(err) => match err.raw_os_error() {
|
||||
Some(code) => {
|
||||
log::debug!("path_open at symlink_metadata error code={:?}", code);
|
||||
tracing::debug!("path_open at symlink_metadata error code={:?}", code);
|
||||
|
||||
if code as u32 != winerror::ERROR_FILE_NOT_FOUND {
|
||||
return Err(err.into());
|
||||
@@ -165,7 +165,7 @@ pub(crate) fn path_open(
|
||||
// trying to open it
|
||||
}
|
||||
None => {
|
||||
log::debug!("Inconvertible OS error: {}", err);
|
||||
tracing::debug!("Inconvertible OS error: {}", err);
|
||||
return Err(WasiError::EIO);
|
||||
}
|
||||
},
|
||||
@@ -397,7 +397,7 @@ pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> WasiR
|
||||
};
|
||||
match err.raw_os_error() {
|
||||
Some(code) => {
|
||||
log::debug!("path_rename at rename error code={:?}", code);
|
||||
tracing::debug!("path_rename at rename error code={:?}", code);
|
||||
match code as u32 {
|
||||
winerror::ERROR_ACCESS_DENIED => {
|
||||
// So most likely dealing with new_path == dir.
|
||||
@@ -427,7 +427,7 @@ pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> WasiR
|
||||
Err(err.into())
|
||||
}
|
||||
None => {
|
||||
log::debug!("Inconvertible OS error: {}", err);
|
||||
tracing::debug!("Inconvertible OS error: {}", err);
|
||||
Err(WasiError::EIO)
|
||||
}
|
||||
}
|
||||
@@ -474,7 +474,7 @@ pub(crate) fn path_symlink(old_path: &str, resolved: PathGet) -> WasiResult<()>
|
||||
};
|
||||
match err.raw_os_error() {
|
||||
Some(code) => {
|
||||
log::debug!("path_symlink at symlink_file error code={:?}", code);
|
||||
tracing::debug!("path_symlink at symlink_file error code={:?}", code);
|
||||
match code as u32 {
|
||||
winerror::ERROR_NOT_A_REPARSE_POINT => {
|
||||
// try creating a dir symlink instead
|
||||
@@ -500,7 +500,7 @@ pub(crate) fn path_symlink(old_path: &str, resolved: PathGet) -> WasiResult<()>
|
||||
Err(err.into())
|
||||
}
|
||||
None => {
|
||||
log::debug!("Inconvertible OS error: {}", err);
|
||||
tracing::debug!("Inconvertible OS error: {}", err);
|
||||
Err(WasiError::EIO)
|
||||
}
|
||||
}
|
||||
@@ -526,7 +526,7 @@ pub(crate) fn path_unlink_file(resolved: PathGet) -> WasiResult<()> {
|
||||
};
|
||||
match err.raw_os_error() {
|
||||
Some(code) => {
|
||||
log::debug!("path_unlink_file at symlink_file error code={:?}", code);
|
||||
tracing::debug!("path_unlink_file at symlink_file error code={:?}", code);
|
||||
if code as u32 == winerror::ERROR_ACCESS_DENIED {
|
||||
// try unlinking a dir symlink instead
|
||||
return fs::remove_dir(path).map_err(Into::into);
|
||||
@@ -535,7 +535,7 @@ pub(crate) fn path_unlink_file(resolved: PathGet) -> WasiResult<()> {
|
||||
Err(err.into())
|
||||
}
|
||||
None => {
|
||||
log::debug!("Inconvertible OS error: {}", err);
|
||||
tracing::debug!("Inconvertible OS error: {}", err);
|
||||
Err(WasiError::EIO)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ pub(crate) fn openat(dirfd: &File, path: &str) -> WasiResult<File> {
|
||||
Err(e) => e,
|
||||
};
|
||||
if let Some(code) = err.raw_os_error() {
|
||||
log::debug!("openat error={:?}", code);
|
||||
tracing::debug!("openat error={:?}", code);
|
||||
if code as u32 == winerror::ERROR_INVALID_NAME {
|
||||
return Err(WasiError::ENOTDIR);
|
||||
}
|
||||
@@ -90,7 +90,7 @@ pub(crate) fn readlinkat(dirfd: &File, s_path: &str) -> WasiResult<String> {
|
||||
Err(e) => e,
|
||||
};
|
||||
if let Some(code) = err.raw_os_error() {
|
||||
log::debug!("readlinkat error={:?}", code);
|
||||
tracing::debug!("readlinkat error={:?}", code);
|
||||
if code as u32 == winerror::ERROR_INVALID_NAME {
|
||||
if s_path.ends_with('/') {
|
||||
// strip "/" and check if exists
|
||||
@@ -130,7 +130,7 @@ pub(crate) fn concatenate<P: AsRef<Path>>(dirfd: &File, path: P) -> WasiResult<P
|
||||
// components with `out_path`
|
||||
let out_path = PathBuf::from(strip_extended_prefix(out_path));
|
||||
|
||||
log::debug!("out_path={:?}", out_path);
|
||||
tracing::debug!("out_path={:?}", out_path);
|
||||
|
||||
Ok(out_path)
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ pub(crate) fn get(
|
||||
// Extract path as &str from guest's memory.
|
||||
let path = path_ptr.as_str()?;
|
||||
|
||||
log::trace!(" | (path_ptr,path_len)='{}'", &*path);
|
||||
tracing::trace!(path = &*path);
|
||||
|
||||
if path.contains('\0') {
|
||||
// if contains NUL, return Ilseq
|
||||
@@ -56,7 +56,7 @@ pub(crate) fn get(
|
||||
loop {
|
||||
match path_stack.pop() {
|
||||
Some(cur_path) => {
|
||||
log::debug!("path_get cur_path = {:?}", cur_path);
|
||||
tracing::debug!(cur_path = tracing::field::display(&cur_path), "path get");
|
||||
|
||||
let ends_with_slash = cur_path.ends_with('/');
|
||||
let mut components = Path::new(&cur_path).components();
|
||||
@@ -74,7 +74,7 @@ pub(crate) fn get(
|
||||
path_stack.push(tail);
|
||||
}
|
||||
|
||||
log::debug!("path_get path_stack = {:?}", path_stack);
|
||||
tracing::debug!(path_stack = tracing::field::debug(&path_stack), "path_get");
|
||||
|
||||
match head {
|
||||
Component::Prefix(_) | Component::RootDir => {
|
||||
@@ -130,7 +130,7 @@ pub(crate) fn get(
|
||||
link_path.push('/');
|
||||
}
|
||||
|
||||
log::debug!(
|
||||
tracing::debug!(
|
||||
"attempted symlink expansion link_path={:?}",
|
||||
link_path
|
||||
);
|
||||
@@ -162,7 +162,7 @@ pub(crate) fn get(
|
||||
link_path.push('/');
|
||||
}
|
||||
|
||||
log::debug!(
|
||||
tracing::debug!(
|
||||
"attempted symlink expansion link_path={:?}",
|
||||
link_path
|
||||
);
|
||||
|
||||
@@ -9,6 +9,7 @@ pub(crate) struct ClockEventData {
|
||||
pub(crate) userdata: types::Userdata,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct FdEventData {
|
||||
pub(crate) handle: EntryHandle,
|
||||
pub(crate) r#type: types::Eventtype,
|
||||
|
||||
@@ -3,11 +3,10 @@ use crate::handle::HandleRights;
|
||||
use crate::sys::clock;
|
||||
use crate::wasi::wasi_snapshot_preview1::WasiSnapshotPreview1;
|
||||
use crate::wasi::{types, AsBytes};
|
||||
use crate::{path, poll};
|
||||
use crate::{Error, Result, WasiCtx};
|
||||
use log::{debug, trace};
|
||||
use crate::{path, poll, Error, Result, WasiCtx};
|
||||
use std::convert::TryInto;
|
||||
use std::io::{self, SeekFrom};
|
||||
use tracing::{debug, trace};
|
||||
use wiggle::{GuestPtr, GuestSlice};
|
||||
|
||||
impl<'a> WasiSnapshotPreview1 for WasiCtx {
|
||||
@@ -651,7 +650,7 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx {
|
||||
true,
|
||||
)?;
|
||||
let old_path = old_path.as_str()?;
|
||||
trace!(" | old_path='{}'", &*old_path);
|
||||
trace!(old_path = &*old_path);
|
||||
new_fd.symlink(&old_path, &new_path)
|
||||
}
|
||||
|
||||
@@ -701,8 +700,11 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx {
|
||||
match subscription.u {
|
||||
types::SubscriptionU::Clock(clock) => {
|
||||
let delay = clock::to_relative_ns_delay(&clock)?;
|
||||
debug!("poll_oneoff event.u.clock = {:?}", clock);
|
||||
debug!("poll_oneoff delay = {:?}ns", delay);
|
||||
debug!(
|
||||
clock = tracing::field::debug(&clock),
|
||||
delay_ns = tracing::field::debug(delay),
|
||||
"poll_oneoff"
|
||||
);
|
||||
let current = poll::ClockEventData {
|
||||
delay,
|
||||
userdata: subscription.userdata,
|
||||
@@ -766,8 +768,11 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx {
|
||||
}
|
||||
}
|
||||
}
|
||||
debug!("poll_oneoff events = {:?}", events);
|
||||
debug!("poll_oneoff timeout = {:?}", timeout);
|
||||
debug!(
|
||||
events = tracing::field::debug(&events),
|
||||
timeout = tracing::field::debug(timeout),
|
||||
"poll_oneoff"
|
||||
);
|
||||
// The underlying implementation should successfully and immediately return
|
||||
// if no events have been passed. Such situation may occur if all provided
|
||||
// events have been filtered out as errors in the code above.
|
||||
@@ -780,7 +785,7 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx {
|
||||
event_ptr.write(event)?;
|
||||
}
|
||||
|
||||
trace!(" | *nevents={:?}", nevents);
|
||||
trace!(nevents = nevents);
|
||||
|
||||
Ok(nevents)
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ impl AsFile for dyn Handle + 'static {
|
||||
} else if let Some(other) = self.as_any().downcast_ref::<OsOther>() {
|
||||
other.as_file()
|
||||
} else {
|
||||
log::error!("tried to make std::fs::File from non-OS handle");
|
||||
tracing::error!("tried to make std::fs::File from non-OS handle");
|
||||
Err(io::Error::from_raw_os_error(libc::EBADF))
|
||||
}
|
||||
}
|
||||
@@ -69,17 +69,26 @@ impl TryFrom<File> for Box<dyn Handle> {
|
||||
match file_type {
|
||||
types::Filetype::RegularFile => {
|
||||
let handle = OsFile::try_from(file)?;
|
||||
log::debug!("Created new instance of OsFile: {:?}", handle);
|
||||
tracing::debug!(
|
||||
handle = tracing::field::debug(&handle),
|
||||
"Created new instance of OsFile"
|
||||
);
|
||||
Ok(Box::new(handle))
|
||||
}
|
||||
types::Filetype::Directory => {
|
||||
let handle = OsDir::try_from(file)?;
|
||||
log::debug!("Created new instance of OsDir: {:?}", handle);
|
||||
tracing::debug!(
|
||||
handle = tracing::field::debug(&handle),
|
||||
"Created new instance of OsDir"
|
||||
);
|
||||
Ok(Box::new(handle))
|
||||
}
|
||||
_ => {
|
||||
let handle = OsOther::try_from(file)?;
|
||||
log::debug!("Created new instance of OsOther: {:?}", handle);
|
||||
tracing::debug!(
|
||||
handle = tracing::field::debug(&handle),
|
||||
"Created new instance of OsOther"
|
||||
);
|
||||
Ok(Box::new(handle))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,10 +3,10 @@ use super::{fd, path, AsFile};
|
||||
use crate::handle::{Handle, HandleRights};
|
||||
use crate::wasi::types;
|
||||
use crate::{Error, Result};
|
||||
use log::{debug, error};
|
||||
use std::any::Any;
|
||||
use std::io;
|
||||
use std::ops::Deref;
|
||||
use tracing::{debug, error};
|
||||
|
||||
// TODO could this be cleaned up?
|
||||
// The actual `OsDir` struct is OS-dependent, therefore we delegate
|
||||
|
||||
@@ -24,7 +24,7 @@ pub(crate) fn unlink_file(dirfd: &OsDir, path: &str) -> Result<()> {
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
log::debug!("path_unlink_file fstatat error: {:?}", err);
|
||||
tracing::debug!("path_unlink_file fstatat error: {:?}", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -38,8 +38,8 @@ pub(crate) fn unlink_file(dirfd: &OsDir, path: &str) -> Result<()> {
|
||||
pub(crate) fn symlink(old_path: &str, new_dirfd: &OsDir, new_path: &str) -> Result<()> {
|
||||
use yanix::file::{fstatat, symlinkat, AtFlags};
|
||||
|
||||
log::debug!("path_symlink old_path = {:?}", old_path);
|
||||
log::debug!(
|
||||
tracing::debug!("path_symlink old_path = {:?}", old_path);
|
||||
tracing::debug!(
|
||||
"path_symlink (new_dirfd, new_path) = ({:?}, {:?})",
|
||||
new_dirfd,
|
||||
new_path
|
||||
@@ -58,7 +58,7 @@ pub(crate) fn symlink(old_path: &str, new_dirfd: &OsDir, new_path: &str) -> Resu
|
||||
{
|
||||
Ok(_) => return Err(Error::Exist),
|
||||
Err(err) => {
|
||||
log::debug!("path_symlink fstatat error: {:?}", err);
|
||||
tracing::debug!("path_symlink fstatat error: {:?}", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -106,7 +106,7 @@ pub(crate) fn rename(
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
log::debug!("path_rename fstatat error: {:?}", err);
|
||||
tracing::debug!("path_rename fstatat error: {:?}", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,10 +60,10 @@ pub(crate) fn readdir<'a>(
|
||||
// Seek if needed. Unless cookie is wasi::__WASI_DIRCOOKIE_START,
|
||||
// new items may not be returned to the caller.
|
||||
if cookie == wasi::DIRCOOKIE_START {
|
||||
log::trace!(" | fd_readdir: doing rewinddir");
|
||||
tracing::trace!("fd_readdir: doing rewinddir");
|
||||
dir.rewind();
|
||||
} else {
|
||||
log::trace!(" | fd_readdir: doing seekdir to {}", cookie);
|
||||
tracing::trace!("fd_readdir: doing seekdir to {}", cookie);
|
||||
let loc = unsafe { SeekLoc::from_raw(cookie as i64)? };
|
||||
dir.seek(loc);
|
||||
}
|
||||
|
||||
@@ -11,11 +11,11 @@ pub(crate) fn unlink_file(dirfd: &OsDir, path: &str) -> Result<()> {
|
||||
pub(crate) fn symlink(old_path: &str, new_dirfd: &OsDir, new_path: &str) -> Result<()> {
|
||||
use yanix::file::symlinkat;
|
||||
|
||||
log::debug!("path_symlink old_path = {:?}", old_path);
|
||||
log::debug!(
|
||||
"path_symlink (new_dirfd, new_path) = ({:?}, {:?})",
|
||||
new_dirfd,
|
||||
new_path
|
||||
tracing::debug!(
|
||||
old_path = old_path,
|
||||
new_dirfd = tracing::field::debug(new_dirfd),
|
||||
new_path = new_path,
|
||||
"path symlink"
|
||||
);
|
||||
|
||||
unsafe { symlinkat(old_path, new_dirfd.as_raw_fd(), new_path)? };
|
||||
|
||||
@@ -51,19 +51,22 @@ impl<T: AsRawFd> AsFile for T {
|
||||
pub(super) fn get_file_type(file: &File) -> io::Result<types::Filetype> {
|
||||
let ft = file.metadata()?.file_type();
|
||||
let file_type = if ft.is_block_device() {
|
||||
log::debug!("Host fd {:?} is a block device", file.as_raw_fd());
|
||||
tracing::debug!(
|
||||
host_fd = tracing::field::display(file.as_raw_fd()),
|
||||
"Host fd is a block device"
|
||||
);
|
||||
types::Filetype::BlockDevice
|
||||
} else if ft.is_char_device() {
|
||||
log::debug!("Host fd {:?} is a char device", file.as_raw_fd());
|
||||
tracing::debug!("Host fd {:?} is a char device", file.as_raw_fd());
|
||||
types::Filetype::CharacterDevice
|
||||
} else if ft.is_dir() {
|
||||
log::debug!("Host fd {:?} is a directory", file.as_raw_fd());
|
||||
tracing::debug!("Host fd {:?} is a directory", file.as_raw_fd());
|
||||
types::Filetype::Directory
|
||||
} else if ft.is_file() {
|
||||
log::debug!("Host fd {:?} is a file", file.as_raw_fd());
|
||||
tracing::debug!("Host fd {:?} is a file", file.as_raw_fd());
|
||||
types::Filetype::RegularFile
|
||||
} else if ft.is_socket() {
|
||||
log::debug!("Host fd {:?} is a socket", file.as_raw_fd());
|
||||
tracing::debug!("Host fd {:?} is a socket", file.as_raw_fd());
|
||||
use yanix::socket::{get_socket_type, SockType};
|
||||
match unsafe { get_socket_type(file.as_raw_fd())? } {
|
||||
SockType::Datagram => types::Filetype::SocketDgram,
|
||||
@@ -71,10 +74,10 @@ pub(super) fn get_file_type(file: &File) -> io::Result<types::Filetype> {
|
||||
_ => return Err(io::Error::from_raw_os_error(libc::EINVAL)),
|
||||
}
|
||||
} else if ft.is_fifo() {
|
||||
log::debug!("Host fd {:?} is a fifo", file.as_raw_fd());
|
||||
tracing::debug!("Host fd {:?} is a fifo", file.as_raw_fd());
|
||||
types::Filetype::Unknown
|
||||
} else {
|
||||
log::debug!("Host fd {:?} is unknown", file.as_raw_fd());
|
||||
tracing::debug!("Host fd {:?} is unknown", file.as_raw_fd());
|
||||
return Err(io::Error::from_raw_os_error(libc::EINVAL));
|
||||
};
|
||||
Ok(file_type)
|
||||
|
||||
@@ -55,7 +55,7 @@ pub(crate) fn readlinkat(dirfd: &OsDir, path: &str) -> Result<String> {
|
||||
use std::os::unix::prelude::AsRawFd;
|
||||
use yanix::file::readlinkat;
|
||||
|
||||
log::debug!("path_get readlinkat path = {:?}", path);
|
||||
tracing::debug!(path = path, "path_get readlinkat");
|
||||
|
||||
let path = unsafe { readlinkat(dirfd.as_raw_fd(), path)? };
|
||||
let path = from_host(path)?;
|
||||
@@ -124,9 +124,12 @@ pub(crate) fn open(
|
||||
// umask is, but don't set the executable flag, because it isn't yet
|
||||
// meaningful for WASI programs to create executable files.
|
||||
|
||||
log::debug!("path_open dirfd = {:?}", dirfd);
|
||||
log::debug!("path_open path = {:?}", path);
|
||||
log::debug!("path_open oflags = {:?}", nix_all_oflags);
|
||||
tracing::debug!(
|
||||
dirfd = tracing::field::debug(dirfd),
|
||||
path = tracing::field::debug(path),
|
||||
oflags = tracing::field::debug(nix_all_oflags),
|
||||
"path_open"
|
||||
);
|
||||
|
||||
let fd_no = unsafe {
|
||||
openat(
|
||||
@@ -149,7 +152,10 @@ pub(crate) fn open(
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
log::debug!("path_open fstatat error: {:?}", err);
|
||||
tracing::debug!(
|
||||
error = tracing::field::debug(&err),
|
||||
"path_open fstatat error",
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -165,7 +171,10 @@ pub(crate) fn open(
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
log::debug!("path_open fstatat error: {:?}", err);
|
||||
tracing::debug!(
|
||||
error = tracing::field::debug(&err),
|
||||
"path_open fstatat error",
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -181,7 +190,7 @@ pub(crate) fn open(
|
||||
}
|
||||
};
|
||||
|
||||
log::debug!("path_open (host) new_fd = {:?}", new_fd);
|
||||
tracing::debug!(new_fd = tracing::field::debug(new_fd));
|
||||
|
||||
// Determine the type of the new file descriptor and which rights contradict with this type
|
||||
let file = unsafe { File::from_raw_fd(new_fd) };
|
||||
|
||||
@@ -39,7 +39,10 @@ pub(crate) fn oneoff(
|
||||
let delay = timeout.delay / 1_000_000; // poll syscall requires delay to expressed in milliseconds
|
||||
delay.try_into().unwrap_or(libc::c_int::max_value())
|
||||
});
|
||||
log::debug!("poll_oneoff poll_timeout = {:?}", poll_timeout);
|
||||
tracing::debug!(
|
||||
poll_timeout = tracing::field::debug(poll_timeout),
|
||||
"poll_oneoff"
|
||||
);
|
||||
|
||||
let ready = loop {
|
||||
match poll(&mut poll_fds, poll_timeout) {
|
||||
@@ -92,16 +95,17 @@ fn handle_fd_event(
|
||||
}
|
||||
|
||||
for (fd_event, poll_fd) in ready_events {
|
||||
// log::debug!("poll_oneoff_handle_fd_event fd_event = {:?}", fd_event);
|
||||
log::debug!("poll_oneoff_handle_fd_event poll_fd = {:?}", poll_fd);
|
||||
tracing::debug!(
|
||||
poll_fd = tracing::field::debug(poll_fd),
|
||||
poll_event = tracing::field::debug(&fd_event),
|
||||
"poll_oneoff handle_fd_event"
|
||||
);
|
||||
|
||||
let revents = match poll_fd.revents() {
|
||||
Some(revents) => revents,
|
||||
None => continue,
|
||||
};
|
||||
|
||||
log::debug!("poll_oneoff_handle_fd_event revents = {:?}", revents);
|
||||
|
||||
let nbytes = if fd_event.r#type == types::Eventtype::FdRead {
|
||||
query_nbytes(fd_event.handle)?
|
||||
} else {
|
||||
|
||||
@@ -6,12 +6,12 @@ use crate::sys::osfile::OsFile;
|
||||
use crate::sys::AsFile;
|
||||
use crate::wasi::types;
|
||||
use crate::Result;
|
||||
use log::trace;
|
||||
use std::convert::TryInto;
|
||||
use std::fs::{File, OpenOptions};
|
||||
use std::os::windows::fs::OpenOptionsExt;
|
||||
use std::os::windows::prelude::{AsRawHandle, FromRawHandle};
|
||||
use std::path::Path;
|
||||
use tracing::trace;
|
||||
use winx::file::{AccessMode, FileModeInformation, Flags};
|
||||
|
||||
pub(crate) fn fdstat_get(file: &File) -> Result<types::Fdflags> {
|
||||
|
||||
@@ -47,7 +47,7 @@ fn concatenate<P: AsRef<Path>>(file: &OsDir, path: P) -> Result<PathBuf> {
|
||||
// components with `out_path`
|
||||
let out_path = PathBuf::from(strip_extended_prefix(out_path));
|
||||
|
||||
log::debug!("out_path={:?}", out_path);
|
||||
tracing::debug!(out_path = tracing::field::debug(&out_path));
|
||||
|
||||
Ok(out_path)
|
||||
}
|
||||
@@ -139,7 +139,7 @@ pub(crate) fn readlinkat(dirfd: &OsDir, s_path: &str) -> Result<String> {
|
||||
Err(e) => e,
|
||||
};
|
||||
if let Some(code) = err.raw_os_error() {
|
||||
log::debug!("readlinkat error={:?}", code);
|
||||
tracing::debug!("readlinkat error={:?}", code);
|
||||
if code as u32 == winerror::ERROR_INVALID_NAME {
|
||||
if s_path.ends_with('/') {
|
||||
// strip "/" and check if exists
|
||||
@@ -171,7 +171,10 @@ pub(crate) fn link(
|
||||
let new_path = concatenate(new_dirfd, new_path)?;
|
||||
if follow_symlinks {
|
||||
// in particular, this will return an error if the target path doesn't exist
|
||||
log::debug!("Following symlinks for path: {:?}", old_path);
|
||||
tracing::debug!(
|
||||
old_path = tracing::field::display(old_path.display()),
|
||||
"Following symlinks"
|
||||
);
|
||||
old_path = fs::canonicalize(&old_path).map_err(|e| match e.raw_os_error() {
|
||||
// fs::canonicalize under Windows will return:
|
||||
// * ERROR_FILE_NOT_FOUND, if it encounters a dangling symlink
|
||||
@@ -185,7 +188,7 @@ pub(crate) fn link(
|
||||
Err(e) => e,
|
||||
};
|
||||
if let Some(code) = err.raw_os_error() {
|
||||
log::debug!("path_link at fs::hard_link error code={:?}", code);
|
||||
tracing::debug!("path_link at fs::hard_link error code={:?}", code);
|
||||
if code as u32 == winerror::ERROR_ACCESS_DENIED {
|
||||
// If an attempt is made to create a hard link to a directory, POSIX-compliant
|
||||
// implementations of link return `EPERM`, but `ERROR_ACCESS_DENIED` is converted
|
||||
@@ -249,7 +252,7 @@ pub(crate) fn open(
|
||||
}
|
||||
Err(err) => match err.raw_os_error() {
|
||||
Some(code) => {
|
||||
log::debug!("path_open at symlink_metadata error code={:?}", code);
|
||||
tracing::debug!("path_open at symlink_metadata error code={:?}", code);
|
||||
match code as u32 {
|
||||
winerror::ERROR_FILE_NOT_FOUND => {
|
||||
// file not found, let it proceed to actually
|
||||
@@ -264,7 +267,7 @@ pub(crate) fn open(
|
||||
};
|
||||
}
|
||||
None => {
|
||||
log::debug!("Inconvertible OS error: {}", err);
|
||||
tracing::debug!("Inconvertible OS error: {}", err);
|
||||
return Err(Error::Io);
|
||||
}
|
||||
},
|
||||
@@ -354,7 +357,7 @@ pub(crate) fn rename(
|
||||
};
|
||||
match err.raw_os_error() {
|
||||
Some(code) => {
|
||||
log::debug!("path_rename at rename error code={:?}", code);
|
||||
tracing::debug!("path_rename at rename error code={:?}", code);
|
||||
match code as u32 {
|
||||
winerror::ERROR_ACCESS_DENIED => {
|
||||
// So most likely dealing with new_path == dir.
|
||||
@@ -386,7 +389,7 @@ pub(crate) fn rename(
|
||||
Err(err.into())
|
||||
}
|
||||
None => {
|
||||
log::debug!("Inconvertible OS error: {}", err);
|
||||
tracing::debug!("Inconvertible OS error: {}", err);
|
||||
Err(Error::Io)
|
||||
}
|
||||
}
|
||||
@@ -418,7 +421,7 @@ pub(crate) fn symlink(old_path: &str, new_dirfd: &OsDir, new_path_: &str) -> Res
|
||||
};
|
||||
match err.raw_os_error() {
|
||||
Some(code) => {
|
||||
log::debug!("path_symlink at symlink_file error code={:?}", code);
|
||||
tracing::debug!("path_symlink at symlink_file error code={:?}", code);
|
||||
match code as u32 {
|
||||
// If the target contains a trailing slash, the Windows API returns
|
||||
// ERROR_INVALID_NAME (which corresponds to ENOENT) instead of
|
||||
@@ -443,7 +446,7 @@ pub(crate) fn symlink(old_path: &str, new_dirfd: &OsDir, new_path_: &str) -> Res
|
||||
Err(err.into())
|
||||
}
|
||||
None => {
|
||||
log::debug!("Inconvertible OS error: {}", err);
|
||||
tracing::debug!("Inconvertible OS error: {}", err);
|
||||
Err(Error::Io)
|
||||
}
|
||||
}
|
||||
@@ -469,7 +472,7 @@ pub(crate) fn unlink_file(dirfd: &OsDir, path: &str) -> Result<()> {
|
||||
};
|
||||
match err.raw_os_error() {
|
||||
Some(code) => {
|
||||
log::debug!("path_unlink_file at symlink_file error code={:?}", code);
|
||||
tracing::debug!("path_unlink_file at symlink_file error code={:?}", code);
|
||||
if code as u32 == winerror::ERROR_ACCESS_DENIED {
|
||||
// try unlinking a dir symlink instead
|
||||
return fs::remove_dir(path).map_err(Into::into);
|
||||
@@ -478,7 +481,7 @@ pub(crate) fn unlink_file(dirfd: &OsDir, path: &str) -> Result<()> {
|
||||
Err(err.into())
|
||||
}
|
||||
None => {
|
||||
log::debug!("Inconvertible OS error: {}", err);
|
||||
tracing::debug!("Inconvertible OS error: {}", err);
|
||||
Err(Error::Io)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,12 +8,12 @@ use crate::sys::AsFile;
|
||||
use crate::wasi::types;
|
||||
use crate::{Error, Result};
|
||||
use lazy_static::lazy_static;
|
||||
use log::{debug, error, trace, warn};
|
||||
use std::convert::TryInto;
|
||||
use std::sync::mpsc::{self, Receiver, RecvTimeoutError, Sender, TryRecvError};
|
||||
use std::sync::Mutex;
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
use tracing::{debug, error, trace, warn};
|
||||
|
||||
struct StdinPoll {
|
||||
request_tx: Sender<()>,
|
||||
@@ -245,7 +245,7 @@ pub(crate) fn oneoff(
|
||||
handle_error_event(event, types::Errno::Notsup, events);
|
||||
}
|
||||
} else {
|
||||
log::error!("can poll FdEvent for OS resources only");
|
||||
tracing::error!("can poll FdEvent for OS resources only");
|
||||
return Err(Error::Badf);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
use crate::handle::{Handle, HandleRights};
|
||||
use crate::wasi::{self, types, RightsExt};
|
||||
use crate::{Error, Result};
|
||||
use log::trace;
|
||||
use std::any::Any;
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::collections::hash_map::Entry;
|
||||
@@ -11,6 +10,7 @@ use std::io;
|
||||
use std::io::SeekFrom;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::rc::Rc;
|
||||
use tracing::trace;
|
||||
|
||||
pub mod pipe;
|
||||
|
||||
@@ -97,7 +97,7 @@ impl FileContents for VecFileContents {
|
||||
}
|
||||
|
||||
fn pread(&self, buf: &mut [u8], offset: types::Filesize) -> Result<usize> {
|
||||
trace!(" | pread(buf.len={}, offset={})", buf.len(), offset);
|
||||
trace!(buffer_length = buf.len(), offset = offset, "pread");
|
||||
let offset: usize = offset.try_into().map_err(|_| Error::Inval)?;
|
||||
|
||||
let data_remaining = self.content.len().saturating_sub(offset);
|
||||
@@ -106,9 +106,7 @@ impl FileContents for VecFileContents {
|
||||
|
||||
(&mut buf[..read_count]).copy_from_slice(&self.content[offset..][..read_count]);
|
||||
|
||||
let res = Ok(read_count);
|
||||
trace!(" | pread={:?}", res);
|
||||
res
|
||||
Ok(read_count)
|
||||
}
|
||||
|
||||
fn pwrite(&mut self, buf: &[u8], offset: types::Filesize) -> Result<usize> {
|
||||
@@ -348,26 +346,16 @@ impl Handle for InMemoryFile {
|
||||
fn openat(
|
||||
&self,
|
||||
path: &str,
|
||||
read: bool,
|
||||
write: bool,
|
||||
_read: bool,
|
||||
_write: bool,
|
||||
oflags: types::Oflags,
|
||||
fd_flags: types::Fdflags,
|
||||
_fd_flags: types::Fdflags,
|
||||
) -> Result<Box<dyn Handle>> {
|
||||
log::trace!(
|
||||
"InMemoryFile::openat(path={:?}, read={:?}, write={:?}, oflags={:?}, fd_flags={:?}",
|
||||
path,
|
||||
read,
|
||||
write,
|
||||
oflags,
|
||||
fd_flags
|
||||
);
|
||||
|
||||
if oflags.contains(&types::Oflags::DIRECTORY) {
|
||||
log::trace!(
|
||||
tracing::trace!(
|
||||
"InMemoryFile::openat was passed oflags DIRECTORY, but {:?} is a file.",
|
||||
path
|
||||
);
|
||||
log::trace!(" return Notdir");
|
||||
return Err(Error::Notdir);
|
||||
}
|
||||
|
||||
@@ -527,7 +515,7 @@ impl Handle for VirtualDir {
|
||||
type Item = Result<(types::Dirent, String)>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
log::trace!("VirtualDirIter::next continuing from {}", self.start);
|
||||
tracing::trace!("VirtualDirIter::next continuing from {}", self.start);
|
||||
if self.start == SELF_DIR_COOKIE {
|
||||
self.start += 1;
|
||||
let name = ".".to_owned();
|
||||
@@ -646,20 +634,11 @@ impl Handle for VirtualDir {
|
||||
fn openat(
|
||||
&self,
|
||||
path: &str,
|
||||
read: bool,
|
||||
write: bool,
|
||||
_read: bool,
|
||||
_write: bool,
|
||||
oflags: types::Oflags,
|
||||
fd_flags: types::Fdflags,
|
||||
) -> Result<Box<dyn Handle>> {
|
||||
log::trace!(
|
||||
"VirtualDir::openat(path={:?}, read={:?}, write={:?}, oflags={:?}, fd_flags={:?}",
|
||||
path,
|
||||
read,
|
||||
write,
|
||||
oflags,
|
||||
fd_flags
|
||||
);
|
||||
|
||||
if path == "." {
|
||||
return self.try_clone().map_err(Into::into);
|
||||
} else if path == ".." {
|
||||
@@ -682,19 +661,17 @@ impl Handle for VirtualDir {
|
||||
Entry::Occupied(e) => {
|
||||
let creat_excl_mask = types::Oflags::CREAT | types::Oflags::EXCL;
|
||||
if (oflags & creat_excl_mask) == creat_excl_mask {
|
||||
log::trace!("VirtualDir::openat was passed oflags CREAT|EXCL, but the file {:?} exists.", file_name);
|
||||
log::trace!(" return Exist");
|
||||
tracing::trace!("VirtualDir::openat was passed oflags CREAT|EXCL, but the file {:?} exists.", file_name);
|
||||
return Err(Error::Exist);
|
||||
}
|
||||
|
||||
if oflags.contains(&types::Oflags::DIRECTORY)
|
||||
&& e.get().get_file_type() != types::Filetype::Directory
|
||||
{
|
||||
log::trace!(
|
||||
tracing::trace!(
|
||||
"VirtualDir::openat was passed oflags DIRECTORY, but {:?} is a file.",
|
||||
file_name
|
||||
);
|
||||
log::trace!(" return Notdir");
|
||||
return Err(Error::Notdir);
|
||||
}
|
||||
|
||||
@@ -710,7 +687,7 @@ impl Handle for VirtualDir {
|
||||
return Err(Error::Nospc);
|
||||
}
|
||||
|
||||
log::trace!("VirtualDir::openat creating an InMemoryFile named {}", path);
|
||||
tracing::trace!("VirtualDir::openat creating an InMemoryFile named {}", path);
|
||||
|
||||
let file = Box::new(InMemoryFile::memory_backed());
|
||||
file.fd_flags.set(fd_flags);
|
||||
@@ -758,7 +735,7 @@ impl Handle for VirtualDir {
|
||||
Ok(())
|
||||
}
|
||||
Entry::Vacant(_) => {
|
||||
log::trace!(
|
||||
tracing::trace!(
|
||||
"VirtualDir::remove_directory failed to remove {}, no such entry",
|
||||
trimmed_path
|
||||
);
|
||||
@@ -799,7 +776,7 @@ impl Handle for VirtualDir {
|
||||
Ok(())
|
||||
}
|
||||
Entry::Vacant(_) => {
|
||||
log::trace!(
|
||||
tracing::trace!(
|
||||
"VirtualDir::unlink_file failed to remove {}, no such entry",
|
||||
trimmed_path
|
||||
);
|
||||
|
||||
@@ -96,7 +96,7 @@ fn generate_wrappers(func: &witx::InterfaceFunc, old: bool) -> TokenStream {
|
||||
let ret = #call
|
||||
.err()
|
||||
.unwrap_or(super::wasi::WasiError::ESUCCESS);
|
||||
log::trace!(" | errno={}", ret);
|
||||
tracing::trace!(" | errno={}", ret);
|
||||
ret.as_raw_errno()
|
||||
}
|
||||
};
|
||||
|
||||
@@ -201,7 +201,7 @@ pub fn define_struct(args: TokenStream) -> TokenStream {
|
||||
let #name_ident = wasmtime::Func::wrap(
|
||||
store,
|
||||
move |caller: wasmtime::Caller<'_> #(,#shim_arg_decls)*| -> #ret_ty {
|
||||
log::trace!(
|
||||
tracing::trace!(
|
||||
#format_str,
|
||||
#(#format_args),*
|
||||
);
|
||||
@@ -209,7 +209,7 @@ pub fn define_struct(args: TokenStream) -> TokenStream {
|
||||
let memory = match caller.get_export("memory") {
|
||||
Some(wasmtime::Extern::Memory(m)) => m,
|
||||
_ => {
|
||||
log::warn!("callee does not export a memory as \"memory\"");
|
||||
tracing::warn!("callee does not export a memory as \"memory\"");
|
||||
let e = wasi_common::old::snapshot_0::wasi::__WASI_ERRNO_INVAL;
|
||||
#handle_early_error
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ repository = "https://github.com/bytecodealliance/wasmtime"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
log = "0.4"
|
||||
tracing = "0.1.15"
|
||||
libc = { version = "0.2", features = ["extra_traits"] }
|
||||
bitflags = "1.2"
|
||||
cfg-if = "0.1.9"
|
||||
|
||||
@@ -25,7 +25,7 @@ impl FileTimeExt for filetime::FileTime {
|
||||
let sec = match self.seconds().try_into() {
|
||||
Ok(sec) => sec,
|
||||
Err(_) => {
|
||||
log::debug!("filetime_to_timespec failed converting seconds to required width");
|
||||
tracing::debug!("filetime_to_timespec failed converting seconds to required width");
|
||||
return Err(Error::from_raw_os_error(libc::EOVERFLOW));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -51,7 +51,9 @@ pub unsafe fn posix_fadvise(
|
||||
// is providing a dubiously large hint. This is not confirmed (no helpful info in the man
|
||||
// pages), but offhand, a 2+ GiB advisory read async seems unlikely to help with any kind
|
||||
// of performance, so we log and exit early with a no-op.
|
||||
log::warn!("`len` too big to fit in the host's command. Returning early with no-op!");
|
||||
tracing::warn!(
|
||||
"`len` too big to fit in the host's command. Returning early with no-op!"
|
||||
);
|
||||
return Ok(());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -13,7 +13,7 @@ edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0"
|
||||
log = { version = "0.4.8", default-features = false }
|
||||
tracing = "0.1.15"
|
||||
wasi-common = { path = "../wasi-common", version = "0.19.0" }
|
||||
wasmtime = { path = "../wasmtime", version = "0.19.0", default-features = false }
|
||||
wasmtime-runtime = { path = "../runtime", version = "0.19.0" }
|
||||
|
||||
@@ -229,7 +229,8 @@
|
||||
//! # }
|
||||
//! ```
|
||||
|
||||
#![deny(missing_docs, intra_doc_link_resolution_failure)]
|
||||
#![allow(unknown_lints)]
|
||||
#![deny(missing_docs, broken_intra_doc_links)]
|
||||
#![doc(test(attr(deny(warnings))))]
|
||||
#![doc(test(attr(allow(dead_code, unused_variables, unused_mut))))]
|
||||
|
||||
|
||||
@@ -17,6 +17,3 @@ wast = "22.0.0"
|
||||
|
||||
[badges]
|
||||
maintenance = { status = "actively-developed" }
|
||||
|
||||
[features]
|
||||
lightbeam = ["wasmtime/lightbeam"]
|
||||
|
||||
Reference in New Issue
Block a user