6
Cargo.lock
generated
6
Cargo.lock
generated
@@ -490,6 +490,7 @@ dependencies = [
|
|||||||
name = "cranelift-object"
|
name = "cranelift-object"
|
||||||
version = "0.65.0"
|
version = "0.65.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
"cranelift-codegen",
|
"cranelift-codegen",
|
||||||
"cranelift-module",
|
"cranelift-module",
|
||||||
"object",
|
"object",
|
||||||
@@ -1223,13 +1224,12 @@ checksum = "17b02fc0ff9a9e4b35b3342880f48e896ebf69f2967921fe8646bf5b7125956a"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "object"
|
name = "object"
|
||||||
version = "0.18.0"
|
version = "0.19.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e5666bbb90bc4d1e5bdcb26c0afda1822d25928341e9384ab187a9b37ab69e36"
|
checksum = "9cbca9424c482ee628fa549d9c812e2cd22f1180b9222c9200fdfa6eb31aecb2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crc32fast",
|
"crc32fast",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"target-lexicon",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ wasmtime-wast = { path = "crates/wast", version = "0.18.0" }
|
|||||||
wasmtime-wasi = { path = "crates/wasi", version = "0.18.0" }
|
wasmtime-wasi = { path = "crates/wasi", version = "0.18.0" }
|
||||||
wasi-common = { path = "crates/wasi-common", version = "0.18.0" }
|
wasi-common = { path = "crates/wasi-common", version = "0.18.0" }
|
||||||
structopt = { version = "0.3.5", features = ["color", "suggestions"] }
|
structopt = { version = "0.3.5", features = ["color", "suggestions"] }
|
||||||
object = { version = "0.18", default-features = false, features = ["write"] }
|
object = { version = "0.19", default-features = false, features = ["write"] }
|
||||||
anyhow = "1.0.19"
|
anyhow = "1.0.19"
|
||||||
target-lexicon = { version = "0.10.0", default-features = false }
|
target-lexicon = { version = "0.10.0", default-features = false }
|
||||||
pretty_env_logger = "0.4.0"
|
pretty_env_logger = "0.4.0"
|
||||||
|
|||||||
@@ -12,8 +12,9 @@ edition = "2018"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
cranelift-module = { path = "../module", version = "0.65.0" }
|
cranelift-module = { path = "../module", version = "0.65.0" }
|
||||||
cranelift-codegen = { path = "../codegen", version = "0.65.0", default-features = false, features = ["std"] }
|
cranelift-codegen = { path = "../codegen", version = "0.65.0", default-features = false, features = ["std"] }
|
||||||
object = { version = "0.18", default-features = false, features = ["write"] }
|
object = { version = "0.19", default-features = false, features = ["write"] }
|
||||||
target-lexicon = "0.10"
|
target-lexicon = "0.10"
|
||||||
|
anyhow = "1.0"
|
||||||
|
|
||||||
[badges]
|
[badges]
|
||||||
maintenance = { status = "experimental" }
|
maintenance = { status = "experimental" }
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
//! Defines `ObjectBackend`.
|
//! Defines `ObjectBackend`.
|
||||||
|
|
||||||
|
use anyhow::anyhow;
|
||||||
use cranelift_codegen::binemit::{
|
use cranelift_codegen::binemit::{
|
||||||
Addend, CodeOffset, NullStackmapSink, Reloc, RelocSink, TrapSink,
|
Addend, CodeOffset, NullStackmapSink, Reloc, RelocSink, TrapSink,
|
||||||
};
|
};
|
||||||
@@ -7,8 +8,8 @@ use cranelift_codegen::entity::SecondaryMap;
|
|||||||
use cranelift_codegen::isa::TargetIsa;
|
use cranelift_codegen::isa::TargetIsa;
|
||||||
use cranelift_codegen::{self, binemit, ir};
|
use cranelift_codegen::{self, binemit, ir};
|
||||||
use cranelift_module::{
|
use cranelift_module::{
|
||||||
Backend, DataContext, DataDescription, DataId, FuncId, Init, Linkage, ModuleNamespace,
|
Backend, DataContext, DataDescription, DataId, FuncId, Init, Linkage, ModuleError,
|
||||||
ModuleResult,
|
ModuleNamespace, ModuleResult,
|
||||||
};
|
};
|
||||||
use object::write::{
|
use object::write::{
|
||||||
Object, Relocation, SectionId, StandardSection, Symbol, SymbolId, SymbolSection,
|
Object, Relocation, SectionId, StandardSection, Symbol, SymbolId, SymbolSection,
|
||||||
@@ -18,11 +19,14 @@ use object::{
|
|||||||
};
|
};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use target_lexicon::{BinaryFormat, PointerWidth};
|
use target_lexicon::PointerWidth;
|
||||||
|
|
||||||
/// A builder for `ObjectBackend`.
|
/// A builder for `ObjectBackend`.
|
||||||
pub struct ObjectBuilder {
|
pub struct ObjectBuilder {
|
||||||
isa: Box<dyn TargetIsa>,
|
isa: Box<dyn TargetIsa>,
|
||||||
|
binary_format: object::BinaryFormat,
|
||||||
|
architecture: object::Architecture,
|
||||||
|
endian: object::Endianness,
|
||||||
name: Vec<u8>,
|
name: Vec<u8>,
|
||||||
libcall_names: Box<dyn Fn(ir::LibCall) -> String>,
|
libcall_names: Box<dyn Fn(ir::LibCall) -> String>,
|
||||||
function_alignment: u64,
|
function_alignment: u64,
|
||||||
@@ -40,13 +44,47 @@ impl ObjectBuilder {
|
|||||||
isa: Box<dyn TargetIsa>,
|
isa: Box<dyn TargetIsa>,
|
||||||
name: V,
|
name: V,
|
||||||
libcall_names: Box<dyn Fn(ir::LibCall) -> String>,
|
libcall_names: Box<dyn Fn(ir::LibCall) -> String>,
|
||||||
) -> Self {
|
) -> ModuleResult<Self> {
|
||||||
Self {
|
let binary_format = match isa.triple().binary_format {
|
||||||
|
target_lexicon::BinaryFormat::Elf => object::BinaryFormat::Elf,
|
||||||
|
target_lexicon::BinaryFormat::Coff => object::BinaryFormat::Coff,
|
||||||
|
target_lexicon::BinaryFormat::Macho => object::BinaryFormat::MachO,
|
||||||
|
target_lexicon::BinaryFormat::Wasm => {
|
||||||
|
return Err(ModuleError::Backend(anyhow!(
|
||||||
|
"binary format wasm is unsupported",
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
target_lexicon::BinaryFormat::Unknown => {
|
||||||
|
return Err(ModuleError::Backend(anyhow!("binary format is unknown")))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let architecture = match isa.triple().architecture {
|
||||||
|
target_lexicon::Architecture::I386
|
||||||
|
| target_lexicon::Architecture::I586
|
||||||
|
| target_lexicon::Architecture::I686 => object::Architecture::I386,
|
||||||
|
target_lexicon::Architecture::X86_64 => object::Architecture::X86_64,
|
||||||
|
target_lexicon::Architecture::Arm(_) => object::Architecture::Arm,
|
||||||
|
target_lexicon::Architecture::Aarch64(_) => object::Architecture::Aarch64,
|
||||||
|
architecture => {
|
||||||
|
return Err(ModuleError::Backend(anyhow!(
|
||||||
|
"target architecture {:?} is unsupported",
|
||||||
|
architecture,
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let endian = match isa.triple().endianness().unwrap() {
|
||||||
|
target_lexicon::Endianness::Little => object::Endianness::Little,
|
||||||
|
target_lexicon::Endianness::Big => object::Endianness::Big,
|
||||||
|
};
|
||||||
|
Ok(Self {
|
||||||
isa,
|
isa,
|
||||||
|
binary_format,
|
||||||
|
architecture,
|
||||||
|
endian,
|
||||||
name: name.into(),
|
name: name.into(),
|
||||||
libcall_names,
|
libcall_names,
|
||||||
function_alignment: 1,
|
function_alignment: 1,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the alignment used for functions.
|
/// Set the alignment used for functions.
|
||||||
@@ -85,8 +123,7 @@ impl Backend for ObjectBackend {
|
|||||||
|
|
||||||
/// Create a new `ObjectBackend` using the given Cranelift target.
|
/// Create a new `ObjectBackend` using the given Cranelift target.
|
||||||
fn new(builder: ObjectBuilder) -> Self {
|
fn new(builder: ObjectBuilder) -> Self {
|
||||||
let triple = builder.isa.triple();
|
let mut object = Object::new(builder.binary_format, builder.architecture, builder.endian);
|
||||||
let mut object = Object::new(triple.binary_format, triple.architecture);
|
|
||||||
object.add_file_symbol(builder.name);
|
object.add_file_symbol(builder.name);
|
||||||
Self {
|
Self {
|
||||||
isa: builder.isa,
|
isa: builder.isa,
|
||||||
@@ -383,7 +420,7 @@ impl Backend for ObjectBackend {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Indicate that this object has a non-executable stack.
|
// Indicate that this object has a non-executable stack.
|
||||||
if self.object.format() == BinaryFormat::Elf {
|
if self.object.format() == object::BinaryFormat::Elf {
|
||||||
self.object.add_section(
|
self.object.add_section(
|
||||||
vec![],
|
vec![],
|
||||||
".note.GNU-stack".as_bytes().to_vec(),
|
".note.GNU-stack".as_bytes().to_vec(),
|
||||||
@@ -509,12 +546,12 @@ struct RelocRecord {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct ObjectRelocSink {
|
struct ObjectRelocSink {
|
||||||
format: BinaryFormat,
|
format: object::BinaryFormat,
|
||||||
relocs: Vec<RelocRecord>,
|
relocs: Vec<RelocRecord>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ObjectRelocSink {
|
impl ObjectRelocSink {
|
||||||
fn new(format: BinaryFormat) -> Self {
|
fn new(format: object::BinaryFormat) -> Self {
|
||||||
Self {
|
Self {
|
||||||
format,
|
format,
|
||||||
relocs: vec![],
|
relocs: vec![],
|
||||||
@@ -552,7 +589,7 @@ impl RelocSink for ObjectRelocSink {
|
|||||||
Reloc::ElfX86_64TlsGd => {
|
Reloc::ElfX86_64TlsGd => {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
self.format,
|
self.format,
|
||||||
BinaryFormat::Elf,
|
object::BinaryFormat::Elf,
|
||||||
"ElfX86_64TlsGd is not supported for this file format"
|
"ElfX86_64TlsGd is not supported for this file format"
|
||||||
);
|
);
|
||||||
(
|
(
|
||||||
@@ -564,7 +601,7 @@ impl RelocSink for ObjectRelocSink {
|
|||||||
Reloc::MachOX86_64Tlv => {
|
Reloc::MachOX86_64Tlv => {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
self.format,
|
self.format,
|
||||||
BinaryFormat::Macho,
|
object::BinaryFormat::MachO,
|
||||||
"MachOX86_64Tlv is not supported for this file format"
|
"MachOX86_64Tlv is not supported for this file format"
|
||||||
);
|
);
|
||||||
addend += 4; // X86_64_RELOC_TLV has an implicit addend of -4
|
addend += 4; // X86_64_RELOC_TLV has an implicit addend of -4
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ edition = "2018"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
gimli = "0.21.0"
|
gimli = "0.21.0"
|
||||||
wasmparser = "0.57.0"
|
wasmparser = "0.57.0"
|
||||||
object = { version = "0.18", default-features = false, features = ["write"] }
|
object = { version = "0.19", default-features = false, features = ["write"] }
|
||||||
wasmtime-environ = { path = "../environ", version = "0.18.0" }
|
wasmtime-environ = { path = "../environ", version = "0.18.0" }
|
||||||
target-lexicon = { version = "0.10.0", default-features = false }
|
target-lexicon = { version = "0.10.0", default-features = false }
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
|
|||||||
@@ -2,12 +2,13 @@
|
|||||||
|
|
||||||
#![allow(clippy::cast_ptr_alignment)]
|
#![allow(clippy::cast_ptr_alignment)]
|
||||||
|
|
||||||
use anyhow::Error;
|
use anyhow::{bail, Error};
|
||||||
use more_asserts::assert_gt;
|
use more_asserts::assert_gt;
|
||||||
use object::write::{Object, Relocation, StandardSegment};
|
use object::write::{Object, Relocation, StandardSegment};
|
||||||
use object::{RelocationEncoding, RelocationKind, SectionKind};
|
use object::{
|
||||||
|
Architecture, BinaryFormat, Endianness, RelocationEncoding, RelocationKind, SectionKind,
|
||||||
|
};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use target_lexicon::BinaryFormat;
|
|
||||||
use wasmtime_environ::isa::TargetIsa;
|
use wasmtime_environ::isa::TargetIsa;
|
||||||
|
|
||||||
pub use crate::read_debuginfo::{read_debuginfo, DebugInfoData, WasmFileInfo};
|
pub use crate::read_debuginfo::{read_debuginfo, DebugInfoData, WasmFileInfo};
|
||||||
@@ -91,7 +92,14 @@ pub fn write_debugsections_image(
|
|||||||
code_region: (*const u8, usize),
|
code_region: (*const u8, usize),
|
||||||
funcs: &[*const u8],
|
funcs: &[*const u8],
|
||||||
) -> Result<Vec<u8>, Error> {
|
) -> Result<Vec<u8>, Error> {
|
||||||
let mut obj = Object::new(BinaryFormat::Elf, isa.triple().architecture);
|
if isa.triple().architecture != target_lexicon::Architecture::X86_64 {
|
||||||
|
bail!(
|
||||||
|
"Unsupported architecture for DWARF image: {}",
|
||||||
|
isa.triple().architecture
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut obj = Object::new(BinaryFormat::Elf, Architecture::X86_64, Endianness::Little);
|
||||||
|
|
||||||
assert!(!code_region.0.is_null() && code_region.1 > 0);
|
assert!(!code_region.0.is_null() && code_region.1 > 0);
|
||||||
assert_gt!(funcs.len(), 0);
|
assert_gt!(funcs.len(), 0);
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ edition = "2018"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
wasmtime-environ = { path = "../environ", version = "0.18.0" }
|
wasmtime-environ = { path = "../environ", version = "0.18.0" }
|
||||||
object = { version = "0.18", default-features = false, features = ["write"] }
|
object = { version = "0.19", default-features = false, features = ["write"] }
|
||||||
more-asserts = "0.2.1"
|
more-asserts = "0.2.1"
|
||||||
|
|
||||||
[badges]
|
[badges]
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ wasmtime-runtime = { path = "../runtime", version = "0.18.0" }
|
|||||||
ittapi-rs = { version = "0.1.5", optional = true }
|
ittapi-rs = { version = "0.1.5", optional = true }
|
||||||
|
|
||||||
[dependencies.object]
|
[dependencies.object]
|
||||||
version = "0.18.0"
|
version = "0.19.0"
|
||||||
optional = true
|
optional = true
|
||||||
default-features = false
|
default-features = false
|
||||||
features = ['read_core', 'elf', 'std']
|
features = ['read_core', 'elf', 'std']
|
||||||
|
|||||||
39
src/obj.rs
39
src/obj.rs
@@ -13,6 +13,42 @@ use wasmtime_environ::{
|
|||||||
use wasmtime_jit::native;
|
use wasmtime_jit::native;
|
||||||
use wasmtime_obj::emit_module;
|
use wasmtime_obj::emit_module;
|
||||||
|
|
||||||
|
fn to_obj_format(
|
||||||
|
triple: &Triple,
|
||||||
|
) -> Result<(
|
||||||
|
object::BinaryFormat,
|
||||||
|
object::Architecture,
|
||||||
|
object::Endianness,
|
||||||
|
)> {
|
||||||
|
let binary_format = match triple.binary_format {
|
||||||
|
target_lexicon::BinaryFormat::Elf => object::BinaryFormat::Elf,
|
||||||
|
target_lexicon::BinaryFormat::Coff => object::BinaryFormat::Coff,
|
||||||
|
target_lexicon::BinaryFormat::Macho => object::BinaryFormat::MachO,
|
||||||
|
target_lexicon::BinaryFormat::Wasm => {
|
||||||
|
bail!("binary format wasm is unsupported");
|
||||||
|
}
|
||||||
|
target_lexicon::BinaryFormat::Unknown => {
|
||||||
|
bail!("binary format is unknown");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let architecture = match triple.architecture {
|
||||||
|
target_lexicon::Architecture::I386
|
||||||
|
| target_lexicon::Architecture::I586
|
||||||
|
| target_lexicon::Architecture::I686 => object::Architecture::I386,
|
||||||
|
target_lexicon::Architecture::X86_64 => object::Architecture::X86_64,
|
||||||
|
target_lexicon::Architecture::Arm(_) => object::Architecture::Arm,
|
||||||
|
target_lexicon::Architecture::Aarch64(_) => object::Architecture::Aarch64,
|
||||||
|
architecture => {
|
||||||
|
bail!("target architecture {:?} is unsupported", architecture,);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let endian = match triple.endianness().unwrap() {
|
||||||
|
target_lexicon::Endianness::Little => object::Endianness::Little,
|
||||||
|
target_lexicon::Endianness::Big => object::Endianness::Big,
|
||||||
|
};
|
||||||
|
Ok((binary_format, architecture, endian))
|
||||||
|
}
|
||||||
|
|
||||||
/// Creates object file from binary wasm data.
|
/// Creates object file from binary wasm data.
|
||||||
pub fn compile_to_obj(
|
pub fn compile_to_obj(
|
||||||
wasm: &[u8],
|
wasm: &[u8],
|
||||||
@@ -50,7 +86,8 @@ pub fn compile_to_obj(
|
|||||||
|
|
||||||
let isa = isa_builder.finish(settings::Flags::new(flag_builder));
|
let isa = isa_builder.finish(settings::Flags::new(flag_builder));
|
||||||
|
|
||||||
let mut obj = Object::new(isa.triple().binary_format, isa.triple().architecture);
|
let (obj_format, obj_arch, obj_endian) = to_obj_format(isa.triple())?;
|
||||||
|
let mut obj = Object::new(obj_format, obj_arch, obj_endian);
|
||||||
|
|
||||||
// TODO: Expose the tunables as command-line flags.
|
// TODO: Expose the tunables as command-line flags.
|
||||||
let mut tunables = Tunables::default();
|
let mut tunables = Tunables::default();
|
||||||
|
|||||||
Reference in New Issue
Block a user