Upgrade to the latest versions of gimli, addr2line, object (#2901)
* Upgrade to the latest versions of gimli, addr2line, object And adapt to API changes. New gimli supports wasm dwarf, resulting in some simplifications in the debug crate. * upgrade gimli usage in linux-specific profiling too * Add "continue" statement after interpreting a wasm local dwarf opcode
This commit is contained in:
21
Cargo.lock
generated
21
Cargo.lock
generated
@@ -4,9 +4,9 @@ version = 3
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "addr2line"
|
name = "addr2line"
|
||||||
version = "0.14.1"
|
version = "0.15.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a55f82cfe485775d02112886f4169bde0c5894d75e79ead7eafe7e40a25e45f7"
|
checksum = "03345e98af8f3d786b6d9f656ccfa6ac316d954e92bc4841f0bba20789d5fb5a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"gimli",
|
"gimli",
|
||||||
]
|
]
|
||||||
@@ -161,11 +161,12 @@ checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "backtrace"
|
name = "backtrace"
|
||||||
version = "0.3.56"
|
version = "0.3.59"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9d117600f438b1707d4e4ae15d3595657288f8235a0eb593e80ecc98ab34e1bc"
|
checksum = "4717cfcbfaa661a0fd48f8453951837ae7e8f81e481fbb136e3202d72805a744"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"addr2line",
|
"addr2line",
|
||||||
|
"cc",
|
||||||
"cfg-if 1.0.0",
|
"cfg-if 1.0.0",
|
||||||
"libc",
|
"libc",
|
||||||
"miniz_oxide",
|
"miniz_oxide",
|
||||||
@@ -1225,9 +1226,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gimli"
|
name = "gimli"
|
||||||
version = "0.23.0"
|
version = "0.24.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f6503fe142514ca4799d4c26297c4248239fe8838d827db6bd6065c6ed29a6ce"
|
checksum = "0e4075386626662786ddb0ec9081e7c7eeb1ba31951f447ca780ef9f5d568189"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"fallible-iterator",
|
"fallible-iterator",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
@@ -1435,9 +1436,9 @@ checksum = "3576a87f2ba00f6f106fdfcd16db1d698d648a26ad8e0573cad8537c3c362d2a"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.87"
|
version = "0.2.94"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "265d751d31d6780a3f956bb5b8022feba2d94eeee5a84ba64f4212eedca42213"
|
checksum = "18794a8ad5b29321f790b55d93dfba91e125cb1a9edbd4f8e3150acc771c1a5e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libfuzzer-sys"
|
name = "libfuzzer-sys"
|
||||||
@@ -1732,9 +1733,9 @@ checksum = "17b02fc0ff9a9e4b35b3342880f48e896ebf69f2967921fe8646bf5b7125956a"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "object"
|
name = "object"
|
||||||
version = "0.23.0"
|
version = "0.24.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a9a7ab5d64814df0fe4a4b5ead45ed6c5f181ee3ff04ba344313a6c80446c5d4"
|
checksum = "1a5b3dd1c072ee7963717671d1ca129f1048fda25edea6b752bfc71ac8854170"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crc32fast",
|
"crc32fast",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ wasmtime-wasi = { path = "crates/wasi", version = "0.26.0" }
|
|||||||
wasmtime-wasi-crypto = { path = "crates/wasi-crypto", version = "0.26.0", optional = true }
|
wasmtime-wasi-crypto = { path = "crates/wasi-crypto", version = "0.26.0", optional = true }
|
||||||
wasmtime-wasi-nn = { path = "crates/wasi-nn", version = "0.26.0", optional = true }
|
wasmtime-wasi-nn = { path = "crates/wasi-nn", version = "0.26.0", optional = true }
|
||||||
structopt = { version = "0.3.5", features = ["color", "suggestions"] }
|
structopt = { version = "0.3.5", features = ["color", "suggestions"] }
|
||||||
object = { version = "0.23.0", default-features = false, features = ["write"] }
|
object = { version = "0.24.0", default-features = false, features = ["write"] }
|
||||||
anyhow = "1.0.19"
|
anyhow = "1.0.19"
|
||||||
target-lexicon = { version = "0.12.0", default-features = false }
|
target-lexicon = { version = "0.12.0", default-features = false }
|
||||||
pretty_env_logger = "0.4.0"
|
pretty_env_logger = "0.4.0"
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ target-lexicon = "0.12"
|
|||||||
log = { version = "0.4.6", default-features = false }
|
log = { version = "0.4.6", default-features = false }
|
||||||
serde = { version = "1.0.94", features = ["derive"], optional = true }
|
serde = { version = "1.0.94", features = ["derive"], optional = true }
|
||||||
bincode = { version = "1.2.1", optional = true }
|
bincode = { version = "1.2.1", optional = true }
|
||||||
gimli = { version = "0.23.0", default-features = false, features = ["write"], optional = true }
|
gimli = { version = "0.24.0", default-features = false, features = ["write"], optional = true }
|
||||||
smallvec = { version = "1.6.1" }
|
smallvec = { version = "1.6.1" }
|
||||||
peepmatic = { path = "../peepmatic", optional = true, version = "0.73.0" }
|
peepmatic = { path = "../peepmatic", optional = true, version = "0.73.0" }
|
||||||
peepmatic-traits = { path = "../peepmatic/crates/traits", optional = true, version = "0.73.0" }
|
peepmatic-traits = { path = "../peepmatic/crates/traits", optional = true, version = "0.73.0" }
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ cranelift-reader = { path = "../reader", version = "0.73.0" }
|
|||||||
cranelift-preopt = { path = "../preopt", version = "0.73.0" }
|
cranelift-preopt = { path = "../preopt", version = "0.73.0" }
|
||||||
file-per-thread-logger = "0.1.2"
|
file-per-thread-logger = "0.1.2"
|
||||||
filecheck = "0.5.0"
|
filecheck = "0.5.0"
|
||||||
gimli = { version = "0.23.0", default-features = false, features = ["read"] }
|
gimli = { version = "0.24.0", default-features = false, features = ["read"] }
|
||||||
log = "0.4.6"
|
log = "0.4.6"
|
||||||
memmap2 = "0.2.1"
|
memmap2 = "0.2.1"
|
||||||
num_cpus = "1.8.0"
|
num_cpus = "1.8.0"
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ edition = "2018"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
cranelift-module = { path = "../module", version = "0.73.0" }
|
cranelift-module = { path = "../module", version = "0.73.0" }
|
||||||
cranelift-codegen = { path = "../codegen", version = "0.73.0", default-features = false, features = ["std"] }
|
cranelift-codegen = { path = "../codegen", version = "0.73.0", default-features = false, features = ["std"] }
|
||||||
object = { version = "0.23.0", default-features = false, features = ["write"] }
|
object = { version = "0.24.0", default-features = false, features = ["write"] }
|
||||||
target-lexicon = "0.12"
|
target-lexicon = "0.12"
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
log = { version = "0.4.6", default-features = false }
|
log = { version = "0.4.6", default-features = false }
|
||||||
|
|||||||
@@ -12,9 +12,9 @@ readme = "README.md"
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
gimli = "0.23.0"
|
gimli = "0.24.0"
|
||||||
wasmparser = "0.77"
|
wasmparser = "0.77"
|
||||||
object = { version = "0.23.0", default-features = false, features = ["read_core", "elf", "write"] }
|
object = { version = "0.24.0", default-features = false, features = ["read_core", "elf", "write"] }
|
||||||
wasmtime-environ = { path = "../environ", version = "0.26.0" }
|
wasmtime-environ = { path = "../environ", version = "0.26.0" }
|
||||||
target-lexicon = { version = "0.12.0", default-features = false }
|
target-lexicon = { version = "0.12.0", default-features = false }
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
|
|||||||
@@ -19,10 +19,10 @@ pub fn create_gdbjit_image(
|
|||||||
defined_funcs_offset: usize,
|
defined_funcs_offset: usize,
|
||||||
funcs: &[*const u8],
|
funcs: &[*const u8],
|
||||||
) -> Result<Vec<u8>, Error> {
|
) -> Result<Vec<u8>, Error> {
|
||||||
let e = ensure_supported_elf_format(&mut bytes)?;
|
let e = ensure_supported_elf_format(&bytes)?;
|
||||||
|
|
||||||
// patch relocs
|
// patch relocs
|
||||||
relocate_dwarf_sections(&mut bytes, defined_funcs_offset, funcs)?;
|
relocate_dwarf_sections(&bytes, defined_funcs_offset, funcs)?;
|
||||||
|
|
||||||
// elf is still missing details...
|
// elf is still missing details...
|
||||||
match e {
|
match e {
|
||||||
@@ -41,7 +41,7 @@ pub fn create_gdbjit_image(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn relocate_dwarf_sections(
|
fn relocate_dwarf_sections(
|
||||||
bytes: &mut [u8],
|
bytes: &[u8],
|
||||||
defined_funcs_offset: usize,
|
defined_funcs_offset: usize,
|
||||||
funcs: &[*const u8],
|
funcs: &[*const u8],
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
@@ -91,10 +91,9 @@ fn relocate_dwarf_sections(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ensure_supported_elf_format(bytes: &mut Vec<u8>) -> Result<Endianness, Error> {
|
fn ensure_supported_elf_format(bytes: &[u8]) -> Result<Endianness, Error> {
|
||||||
use object::elf::*;
|
use object::elf::*;
|
||||||
use object::read::elf::*;
|
use object::read::elf::*;
|
||||||
use object::Bytes;
|
|
||||||
use std::mem::size_of;
|
use std::mem::size_of;
|
||||||
|
|
||||||
let kind = match object::FileKind::parse(bytes) {
|
let kind = match object::FileKind::parse(bytes) {
|
||||||
@@ -104,14 +103,12 @@ fn ensure_supported_elf_format(bytes: &mut Vec<u8>) -> Result<Endianness, Error>
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
let header = match kind {
|
let header = match kind {
|
||||||
object::FileKind::Elf64 => {
|
object::FileKind::Elf64 => match object::elf::FileHeader64::<Endianness>::parse(bytes) {
|
||||||
match object::elf::FileHeader64::<Endianness>::parse(Bytes(bytes)) {
|
Ok(header) => header,
|
||||||
Ok(header) => header,
|
Err(err) => {
|
||||||
Err(err) => {
|
bail!("Unsupported ELF file: {}", err);
|
||||||
bail!("Unsupported ELF file: {}", err);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
_ => {
|
_ => {
|
||||||
bail!("only 64-bit ELF files currently supported")
|
bail!("only 64-bit ELF files currently supported")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -541,150 +541,145 @@ where
|
|||||||
parts.push(CompiledExpressionPart::LandingPad(marker.clone()));
|
parts.push(CompiledExpressionPart::LandingPad(marker.clone()));
|
||||||
}
|
}
|
||||||
|
|
||||||
let next = buf[pc.offset_from(&expr.0).into_u64() as usize];
|
|
||||||
need_deref = true;
|
need_deref = true;
|
||||||
if next == 0xED {
|
|
||||||
// WebAssembly DWARF extension
|
let pos = pc.offset_from(&expr.0).into_u64() as usize;
|
||||||
pc.read_u8()?;
|
let op = Operation::parse(&mut pc, encoding)?;
|
||||||
let ty = pc.read_uleb128()?;
|
match op {
|
||||||
// Supporting only wasm locals.
|
Operation::FrameOffset { offset } => {
|
||||||
if ty != 0 {
|
// Expand DW_OP_fbreg into frame location and DW_OP_plus_uconst.
|
||||||
// TODO support wasm globals?
|
if frame_base.is_some() {
|
||||||
|
// Add frame base expressions.
|
||||||
|
flush_code_chunk!();
|
||||||
|
parts.extend_from_slice(&frame_base.unwrap().parts);
|
||||||
|
}
|
||||||
|
if let Some(CompiledExpressionPart::Local { trailing, .. }) = parts.last_mut() {
|
||||||
|
// Reset local trailing flag.
|
||||||
|
*trailing = false;
|
||||||
|
}
|
||||||
|
// Append DW_OP_plus_uconst part.
|
||||||
|
let mut writer = ExpressionWriter::new();
|
||||||
|
writer.write_op(gimli::constants::DW_OP_plus_uconst)?;
|
||||||
|
writer.write_uleb128(offset as u64)?;
|
||||||
|
code_chunk.extend(writer.into_vec());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Operation::Drop { .. }
|
||||||
|
| Operation::Pick { .. }
|
||||||
|
| Operation::Swap { .. }
|
||||||
|
| Operation::Rot { .. }
|
||||||
|
| Operation::Nop { .. }
|
||||||
|
| Operation::UnsignedConstant { .. }
|
||||||
|
| Operation::SignedConstant { .. }
|
||||||
|
| Operation::ConstantIndex { .. }
|
||||||
|
| Operation::PlusConstant { .. }
|
||||||
|
| Operation::Abs { .. }
|
||||||
|
| Operation::And { .. }
|
||||||
|
| Operation::Or { .. }
|
||||||
|
| Operation::Xor { .. }
|
||||||
|
| Operation::Shl { .. }
|
||||||
|
| Operation::Plus { .. }
|
||||||
|
| Operation::Minus { .. }
|
||||||
|
| Operation::Div { .. }
|
||||||
|
| Operation::Mod { .. }
|
||||||
|
| Operation::Mul { .. }
|
||||||
|
| Operation::Neg { .. }
|
||||||
|
| Operation::Not { .. }
|
||||||
|
| Operation::Lt { .. }
|
||||||
|
| Operation::Gt { .. }
|
||||||
|
| Operation::Le { .. }
|
||||||
|
| Operation::Ge { .. }
|
||||||
|
| Operation::Eq { .. }
|
||||||
|
| Operation::Ne { .. }
|
||||||
|
| Operation::TypedLiteral { .. }
|
||||||
|
| Operation::Convert { .. }
|
||||||
|
| Operation::Reinterpret { .. }
|
||||||
|
| Operation::Piece { .. } => (),
|
||||||
|
Operation::Bra { target } | Operation::Skip { target } => {
|
||||||
|
flush_code_chunk!();
|
||||||
|
let arc_to = (pc.len().into_u64() as isize - target as isize) as u64;
|
||||||
|
let marker = match jump_targets.get(&arc_to) {
|
||||||
|
Some(m) => m.clone(),
|
||||||
|
None => {
|
||||||
|
// Marker not found: probably out of bounds.
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
push!(CompiledExpressionPart::Jump {
|
||||||
|
conditionally: match op {
|
||||||
|
Operation::Bra { .. } => true,
|
||||||
|
_ => false,
|
||||||
|
},
|
||||||
|
target: marker,
|
||||||
|
});
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Operation::StackValue => {
|
||||||
|
need_deref = false;
|
||||||
|
|
||||||
|
// Find extra stack_value, that follow wasm-local operators,
|
||||||
|
// and mark such locals with special flag.
|
||||||
|
if let (Some(CompiledExpressionPart::Local { trailing, .. }), true) =
|
||||||
|
(parts.last_mut(), code_chunk.is_empty())
|
||||||
|
{
|
||||||
|
*trailing = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Operation::Deref { .. } => {
|
||||||
|
flush_code_chunk!();
|
||||||
|
push!(CompiledExpressionPart::Deref);
|
||||||
|
// Don't re-enter the loop here (i.e. continue), because the
|
||||||
|
// DW_OP_deref still needs to be kept.
|
||||||
|
}
|
||||||
|
Operation::WasmLocal { index } => {
|
||||||
|
flush_code_chunk!();
|
||||||
|
let label = ValueLabel::from_u32(index as u32);
|
||||||
|
push!(CompiledExpressionPart::Local {
|
||||||
|
label,
|
||||||
|
trailing: false,
|
||||||
|
});
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Operation::Shr { .. } | Operation::Shra { .. } => {
|
||||||
|
// Insert value normalisation part.
|
||||||
|
// The semantic value is 32 bits (TODO: check unit)
|
||||||
|
// but the target architecture is 64-bits. So we'll
|
||||||
|
// clean out the upper 32 bits (in a sign-correct way)
|
||||||
|
// to avoid contamination of the result with randomness.
|
||||||
|
let mut writer = ExpressionWriter::new();
|
||||||
|
writer.write_op(gimli::constants::DW_OP_plus_uconst)?;
|
||||||
|
writer.write_uleb128(32)?; // increase shift amount
|
||||||
|
writer.write_op(gimli::constants::DW_OP_swap)?;
|
||||||
|
writer.write_op(gimli::constants::DW_OP_const1u)?;
|
||||||
|
writer.write_u8(32)?;
|
||||||
|
writer.write_op(gimli::constants::DW_OP_shl)?;
|
||||||
|
writer.write_op(gimli::constants::DW_OP_swap)?;
|
||||||
|
code_chunk.extend(writer.into_vec());
|
||||||
|
// Don't re-enter the loop here (i.e. continue), because the
|
||||||
|
// DW_OP_shr* still needs to be kept.
|
||||||
|
}
|
||||||
|
Operation::Address { .. }
|
||||||
|
| Operation::AddressIndex { .. }
|
||||||
|
| Operation::Call { .. }
|
||||||
|
| Operation::Register { .. }
|
||||||
|
| Operation::RegisterOffset { .. }
|
||||||
|
| Operation::CallFrameCFA
|
||||||
|
| Operation::PushObjectAddress
|
||||||
|
| Operation::TLS
|
||||||
|
| Operation::ImplicitValue { .. }
|
||||||
|
| Operation::ImplicitPointer { .. }
|
||||||
|
| Operation::EntryValue { .. }
|
||||||
|
| Operation::ParameterRef { .. } => {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
let index = pc.read_sleb128()?;
|
Operation::WasmGlobal { index: _ } | Operation::WasmStack { index: _ } => {
|
||||||
flush_code_chunk!();
|
// TODO support those two
|
||||||
let label = ValueLabel::from_u32(index as u32);
|
return Ok(None);
|
||||||
push!(CompiledExpressionPart::Local {
|
|
||||||
label,
|
|
||||||
trailing: false,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
let pos = pc.offset_from(&expr.0).into_u64() as usize;
|
|
||||||
let op = Operation::parse(&mut pc, encoding)?;
|
|
||||||
match op {
|
|
||||||
Operation::FrameOffset { offset } => {
|
|
||||||
// Expand DW_OP_fbreg into frame location and DW_OP_plus_uconst.
|
|
||||||
if frame_base.is_some() {
|
|
||||||
// Add frame base expressions.
|
|
||||||
flush_code_chunk!();
|
|
||||||
parts.extend_from_slice(&frame_base.unwrap().parts);
|
|
||||||
}
|
|
||||||
if let Some(CompiledExpressionPart::Local { trailing, .. }) = parts.last_mut() {
|
|
||||||
// Reset local trailing flag.
|
|
||||||
*trailing = false;
|
|
||||||
}
|
|
||||||
// Append DW_OP_plus_uconst part.
|
|
||||||
let mut writer = ExpressionWriter::new();
|
|
||||||
writer.write_op(gimli::constants::DW_OP_plus_uconst)?;
|
|
||||||
writer.write_uleb128(offset as u64)?;
|
|
||||||
code_chunk.extend(writer.into_vec());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
Operation::Drop { .. }
|
|
||||||
| Operation::Pick { .. }
|
|
||||||
| Operation::Swap { .. }
|
|
||||||
| Operation::Rot { .. }
|
|
||||||
| Operation::Nop { .. }
|
|
||||||
| Operation::UnsignedConstant { .. }
|
|
||||||
| Operation::SignedConstant { .. }
|
|
||||||
| Operation::ConstantIndex { .. }
|
|
||||||
| Operation::PlusConstant { .. }
|
|
||||||
| Operation::Abs { .. }
|
|
||||||
| Operation::And { .. }
|
|
||||||
| Operation::Or { .. }
|
|
||||||
| Operation::Xor { .. }
|
|
||||||
| Operation::Shl { .. }
|
|
||||||
| Operation::Plus { .. }
|
|
||||||
| Operation::Minus { .. }
|
|
||||||
| Operation::Div { .. }
|
|
||||||
| Operation::Mod { .. }
|
|
||||||
| Operation::Mul { .. }
|
|
||||||
| Operation::Neg { .. }
|
|
||||||
| Operation::Not { .. }
|
|
||||||
| Operation::Lt { .. }
|
|
||||||
| Operation::Gt { .. }
|
|
||||||
| Operation::Le { .. }
|
|
||||||
| Operation::Ge { .. }
|
|
||||||
| Operation::Eq { .. }
|
|
||||||
| Operation::Ne { .. }
|
|
||||||
| Operation::TypedLiteral { .. }
|
|
||||||
| Operation::Convert { .. }
|
|
||||||
| Operation::Reinterpret { .. }
|
|
||||||
| Operation::Piece { .. } => (),
|
|
||||||
Operation::Bra { target } | Operation::Skip { target } => {
|
|
||||||
flush_code_chunk!();
|
|
||||||
let arc_to = (pc.len().into_u64() as isize - target as isize) as u64;
|
|
||||||
let marker = match jump_targets.get(&arc_to) {
|
|
||||||
Some(m) => m.clone(),
|
|
||||||
None => {
|
|
||||||
// Marker not found: probably out of bounds.
|
|
||||||
return Ok(None);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
push!(CompiledExpressionPart::Jump {
|
|
||||||
conditionally: match op {
|
|
||||||
Operation::Bra { .. } => true,
|
|
||||||
_ => false,
|
|
||||||
},
|
|
||||||
target: marker,
|
|
||||||
});
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
Operation::StackValue => {
|
|
||||||
need_deref = false;
|
|
||||||
|
|
||||||
// Find extra stack_value, that follow wasm-local operators,
|
|
||||||
// and mark such locals with special flag.
|
|
||||||
if let (Some(CompiledExpressionPart::Local { trailing, .. }), true) =
|
|
||||||
(parts.last_mut(), code_chunk.is_empty())
|
|
||||||
{
|
|
||||||
*trailing = true;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Operation::Deref { .. } => {
|
|
||||||
flush_code_chunk!();
|
|
||||||
push!(CompiledExpressionPart::Deref);
|
|
||||||
// Don't re-enter the loop here (i.e. continue), because the
|
|
||||||
// DW_OP_deref still needs to be kept.
|
|
||||||
}
|
|
||||||
Operation::Shr { .. } | Operation::Shra { .. } => {
|
|
||||||
// Insert value normalisation part.
|
|
||||||
// The semantic value is 32 bits (TODO: check unit)
|
|
||||||
// but the target architecture is 64-bits. So we'll
|
|
||||||
// clean out the upper 32 bits (in a sign-correct way)
|
|
||||||
// to avoid contamination of the result with randomness.
|
|
||||||
let mut writer = ExpressionWriter::new();
|
|
||||||
writer.write_op(gimli::constants::DW_OP_plus_uconst)?;
|
|
||||||
writer.write_uleb128(32)?; // increase shift amount
|
|
||||||
writer.write_op(gimli::constants::DW_OP_swap)?;
|
|
||||||
writer.write_op(gimli::constants::DW_OP_const1u)?;
|
|
||||||
writer.write_u8(32)?;
|
|
||||||
writer.write_op(gimli::constants::DW_OP_shl)?;
|
|
||||||
writer.write_op(gimli::constants::DW_OP_swap)?;
|
|
||||||
code_chunk.extend(writer.into_vec());
|
|
||||||
// Don't re-enter the loop here (i.e. continue), because the
|
|
||||||
// DW_OP_shr* still needs to be kept.
|
|
||||||
}
|
|
||||||
Operation::Address { .. }
|
|
||||||
| Operation::AddressIndex { .. }
|
|
||||||
| Operation::Call { .. }
|
|
||||||
| Operation::Register { .. }
|
|
||||||
| Operation::RegisterOffset { .. }
|
|
||||||
| Operation::CallFrameCFA
|
|
||||||
| Operation::PushObjectAddress
|
|
||||||
| Operation::TLS
|
|
||||||
| Operation::ImplicitValue { .. }
|
|
||||||
| Operation::ImplicitPointer { .. }
|
|
||||||
| Operation::EntryValue { .. }
|
|
||||||
| Operation::ParameterRef { .. } => {
|
|
||||||
return Ok(None);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
let chunk = &buf[pos..pc.offset_from(&expr.0).into_u64() as usize];
|
|
||||||
code_chunk.extend_from_slice(chunk);
|
|
||||||
}
|
}
|
||||||
|
let chunk = &buf[pos..pc.offset_from(&expr.0).into_u64() as usize];
|
||||||
|
code_chunk.extend_from_slice(chunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
flush_code_chunk!();
|
flush_code_chunk!();
|
||||||
|
|||||||
@@ -189,10 +189,10 @@ where
|
|||||||
address: row.address(),
|
address: row.address(),
|
||||||
op_index: row.op_index(),
|
op_index: row.op_index(),
|
||||||
file_index: row.file_index(),
|
file_index: row.file_index(),
|
||||||
line: row.line().unwrap_or(0),
|
line: row.line().map(|nonzero| nonzero.get()).unwrap_or(0),
|
||||||
column: match row.column() {
|
column: match row.column() {
|
||||||
gimli::ColumnType::LeftEdge => 0,
|
gimli::ColumnType::LeftEdge => 0,
|
||||||
gimli::ColumnType::Column(val) => val,
|
gimli::ColumnType::Column(val) => val.get(),
|
||||||
},
|
},
|
||||||
discriminator: row.discriminator(),
|
discriminator: row.discriminator(),
|
||||||
is_stmt: row.is_stmt(),
|
is_stmt: row.is_stmt(),
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ serde = { version = "1.0.94", features = ["derive"] }
|
|||||||
log = { version = "0.4.8", default-features = false }
|
log = { version = "0.4.8", default-features = false }
|
||||||
more-asserts = "0.2.1"
|
more-asserts = "0.2.1"
|
||||||
cfg-if = "1.0"
|
cfg-if = "1.0"
|
||||||
gimli = "0.23"
|
gimli = "0.24"
|
||||||
|
|
||||||
[badges]
|
[badges]
|
||||||
maintenance = { status = "actively-developed" }
|
maintenance = { status = "actively-developed" }
|
||||||
|
|||||||
@@ -205,19 +205,28 @@ impl<'data> ModuleEnvironment<'data> {
|
|||||||
let slice = gimli::EndianSlice::new(data, endian);
|
let slice = gimli::EndianSlice::new(data, endian);
|
||||||
|
|
||||||
match name {
|
match name {
|
||||||
".debug_str" => dwarf.debug_str = gimli::DebugStr::new(data, endian),
|
// Dwarf fields.
|
||||||
".debug_abbrev" => dwarf.debug_abbrev = gimli::DebugAbbrev::new(data, endian),
|
".debug_abbrev" => dwarf.debug_abbrev = gimli::DebugAbbrev::new(data, endian),
|
||||||
|
".debug_addr" => dwarf.debug_addr = gimli::DebugAddr::from(slice),
|
||||||
|
// TODO aranges?
|
||||||
".debug_info" => dwarf.debug_info = gimli::DebugInfo::new(data, endian),
|
".debug_info" => dwarf.debug_info = gimli::DebugInfo::new(data, endian),
|
||||||
".debug_line" => dwarf.debug_line = gimli::DebugLine::new(data, endian),
|
".debug_line" => dwarf.debug_line = gimli::DebugLine::new(data, endian),
|
||||||
".debug_addr" => dwarf.debug_addr = gimli::DebugAddr::from(slice),
|
|
||||||
".debug_line_str" => dwarf.debug_line_str = gimli::DebugLineStr::from(slice),
|
".debug_line_str" => dwarf.debug_line_str = gimli::DebugLineStr::from(slice),
|
||||||
".debug_str_sup" => dwarf.debug_str_sup = gimli::DebugStr::from(slice),
|
".debug_str" => dwarf.debug_str = gimli::DebugStr::new(data, endian),
|
||||||
".debug_ranges" => info.debug_ranges = gimli::DebugRanges::new(data, endian),
|
".debug_str_offsets" => dwarf.debug_str_offsets = gimli::DebugStrOffsets::from(slice),
|
||||||
".debug_rnglists" => info.debug_rnglists = gimli::DebugRngLists::new(data, endian),
|
".debug_str_sup" => {
|
||||||
|
let mut dwarf_sup: Dwarf<'data> = Default::default();
|
||||||
|
dwarf_sup.debug_str = gimli::DebugStr::from(slice);
|
||||||
|
dwarf.sup = Some(Arc::new(dwarf_sup));
|
||||||
|
}
|
||||||
|
".debug_types" => dwarf.debug_types = gimli::DebugTypes::from(slice),
|
||||||
|
|
||||||
|
// Additional fields.
|
||||||
".debug_loc" => info.debug_loc = gimli::DebugLoc::from(slice),
|
".debug_loc" => info.debug_loc = gimli::DebugLoc::from(slice),
|
||||||
".debug_loclists" => info.debug_loclists = gimli::DebugLocLists::from(slice),
|
".debug_loclists" => info.debug_loclists = gimli::DebugLocLists::from(slice),
|
||||||
".debug_str_offsets" => dwarf.debug_str_offsets = gimli::DebugStrOffsets::from(slice),
|
".debug_ranges" => info.debug_ranges = gimli::DebugRanges::new(data, endian),
|
||||||
".debug_types" => dwarf.debug_types = gimli::DebugTypes::from(slice),
|
".debug_rnglists" => info.debug_rnglists = gimli::DebugRngLists::new(data, endian),
|
||||||
|
|
||||||
other => {
|
other => {
|
||||||
log::warn!("unknown debug section `{}`", other);
|
log::warn!("unknown debug section `{}`", other);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -33,10 +33,10 @@ more-asserts = "0.2.1"
|
|||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
cfg-if = "1.0"
|
cfg-if = "1.0"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
gimli = { version = "0.23.0", default-features = false, features = ["write"] }
|
gimli = { version = "0.24.0", default-features = false, features = ["write"] }
|
||||||
object = { version = "0.23.0", default-features = false, features = ["write"] }
|
object = { version = "0.24.0", default-features = false, features = ["write"] }
|
||||||
serde = { version = "1.0.94", features = ["derive"] }
|
serde = { version = "1.0.94", features = ["derive"] }
|
||||||
addr2line = { version = "0.14", default-features = false }
|
addr2line = { version = "0.15", default-features = false }
|
||||||
|
|
||||||
[target.'cfg(target_os = "windows")'.dependencies]
|
[target.'cfg(target_os = "windows")'.dependencies]
|
||||||
winapi = { version = "0.3.8", features = ["winnt", "impl-default"] }
|
winapi = { version = "0.3.8", features = ["winnt", "impl-default"] }
|
||||||
|
|||||||
@@ -83,6 +83,7 @@ struct DebugInfo {
|
|||||||
code_section_offset: u64,
|
code_section_offset: u64,
|
||||||
debug_abbrev: Range<usize>,
|
debug_abbrev: Range<usize>,
|
||||||
debug_addr: Range<usize>,
|
debug_addr: Range<usize>,
|
||||||
|
debug_aranges: Range<usize>,
|
||||||
debug_info: Range<usize>,
|
debug_info: Range<usize>,
|
||||||
debug_line: Range<usize>,
|
debug_line: Range<usize>,
|
||||||
debug_line_str: Range<usize>,
|
debug_line_str: Range<usize>,
|
||||||
@@ -400,6 +401,7 @@ impl CompiledModule {
|
|||||||
let cx = addr2line::Context::from_sections(
|
let cx = addr2line::Context::from_sections(
|
||||||
EndianSlice::new(&data[info.debug_abbrev.clone()], endian).into(),
|
EndianSlice::new(&data[info.debug_abbrev.clone()], endian).into(),
|
||||||
EndianSlice::new(&data[info.debug_addr.clone()], endian).into(),
|
EndianSlice::new(&data[info.debug_addr.clone()], endian).into(),
|
||||||
|
EndianSlice::new(&data[info.debug_aranges.clone()], endian).into(),
|
||||||
EndianSlice::new(&data[info.debug_info.clone()], endian).into(),
|
EndianSlice::new(&data[info.debug_info.clone()], endian).into(),
|
||||||
EndianSlice::new(&data[info.debug_line.clone()], endian).into(),
|
EndianSlice::new(&data[info.debug_line.clone()], endian).into(),
|
||||||
EndianSlice::new(&data[info.debug_line_str.clone()], endian).into(),
|
EndianSlice::new(&data[info.debug_line_str.clone()], endian).into(),
|
||||||
@@ -546,6 +548,7 @@ impl From<DebugInfoData<'_>> for DebugInfo {
|
|||||||
};
|
};
|
||||||
let debug_abbrev = push(raw.dwarf.debug_abbrev.reader().slice());
|
let debug_abbrev = push(raw.dwarf.debug_abbrev.reader().slice());
|
||||||
let debug_addr = push(raw.dwarf.debug_addr.reader().slice());
|
let debug_addr = push(raw.dwarf.debug_addr.reader().slice());
|
||||||
|
let debug_aranges = push(raw.dwarf.debug_aranges.reader().slice());
|
||||||
let debug_info = push(raw.dwarf.debug_info.reader().slice());
|
let debug_info = push(raw.dwarf.debug_info.reader().slice());
|
||||||
let debug_line = push(raw.dwarf.debug_line.reader().slice());
|
let debug_line = push(raw.dwarf.debug_line.reader().slice());
|
||||||
let debug_line_str = push(raw.dwarf.debug_line_str.reader().slice());
|
let debug_line_str = push(raw.dwarf.debug_line_str.reader().slice());
|
||||||
@@ -557,6 +560,7 @@ impl From<DebugInfoData<'_>> for DebugInfo {
|
|||||||
data: data.into(),
|
data: data.into(),
|
||||||
debug_abbrev,
|
debug_abbrev,
|
||||||
debug_addr,
|
debug_addr,
|
||||||
|
debug_aranges,
|
||||||
debug_info,
|
debug_info,
|
||||||
debug_line,
|
debug_line,
|
||||||
debug_line_str,
|
debug_line_str,
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ edition = "2018"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
wasmtime-environ = { path = "../environ", version = "0.26.0" }
|
wasmtime-environ = { path = "../environ", version = "0.26.0" }
|
||||||
object = { version = "0.23.0", default-features = false, features = ["write"] }
|
object = { version = "0.24.0", default-features = false, features = ["write"] }
|
||||||
more-asserts = "0.2.1"
|
more-asserts = "0.2.1"
|
||||||
target-lexicon = { version = "0.12.0", default-features = false }
|
target-lexicon = { version = "0.12.0", default-features = false }
|
||||||
wasmtime-debug = { path = "../debug", version = "0.26.0" }
|
wasmtime-debug = { path = "../debug", version = "0.26.0" }
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ edition = "2018"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
cfg-if = "1.0"
|
cfg-if = "1.0"
|
||||||
gimli = { version = "0.23.0", optional = true }
|
gimli = { version = "0.24.0", optional = true }
|
||||||
lazy_static = "1.4"
|
lazy_static = "1.4"
|
||||||
libc = { version = "0.2.60", default-features = false }
|
libc = { version = "0.2.60", default-features = false }
|
||||||
scroll = { version = "0.10.1", features = ["derive"], optional = true }
|
scroll = { version = "0.10.1", features = ["derive"], optional = true }
|
||||||
@@ -24,7 +24,7 @@ wasmtime-runtime = { path = "../runtime", version = "0.26.0" }
|
|||||||
ittapi-rs = { version = "0.1.5", optional = true }
|
ittapi-rs = { version = "0.1.5", optional = true }
|
||||||
|
|
||||||
[dependencies.object]
|
[dependencies.object]
|
||||||
version = "0.23.0"
|
version = "0.24.0"
|
||||||
optional = true
|
optional = true
|
||||||
default-features = false
|
default-features = false
|
||||||
features = ['read_core', 'elf', 'std']
|
features = ['read_core', 'elf', 'std']
|
||||||
|
|||||||
@@ -371,7 +371,7 @@ impl State {
|
|||||||
pid: u32,
|
pid: u32,
|
||||||
tid: u32,
|
tid: u32,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let file = object::File::parse(&dbg_image).unwrap();
|
let file = object::File::parse(dbg_image).unwrap();
|
||||||
let endian = if file.is_little_endian() {
|
let endian = if file.is_little_endian() {
|
||||||
gimli::RunTimeEndian::Little
|
gimli::RunTimeEndian::Little
|
||||||
} else {
|
} else {
|
||||||
@@ -386,8 +386,7 @@ impl State {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let load_section_sup = |_| Ok(borrow::Cow::Borrowed(&[][..]));
|
let dwarf_cow = gimli::Dwarf::load(&load_section)?;
|
||||||
let dwarf_cow = gimli::Dwarf::load(&load_section, &load_section_sup)?;
|
|
||||||
let borrow_section: &dyn for<'a> Fn(
|
let borrow_section: &dyn for<'a> Fn(
|
||||||
&'a borrow::Cow<[u8]>,
|
&'a borrow::Cow<[u8]>,
|
||||||
)
|
)
|
||||||
@@ -599,9 +598,9 @@ impl State {
|
|||||||
header: RecordHeader {
|
header: RecordHeader {
|
||||||
id: RecordId::JitCodeDebugInfo as u32,
|
id: RecordId::JitCodeDebugInfo as u32,
|
||||||
record_size: 0,
|
record_size: 0,
|
||||||
timestamp: timestamp,
|
timestamp,
|
||||||
},
|
},
|
||||||
address: address,
|
address,
|
||||||
count: 0,
|
count: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -617,9 +616,9 @@ impl State {
|
|||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let filename = myfile.to_string_lossy()?;
|
let filename = myfile.to_string_lossy()?;
|
||||||
let line = row.line().unwrap_or(0);
|
let line = row.line().map(|nonzero| nonzero.get()).unwrap_or(0);
|
||||||
let column = match row.column() {
|
let column = match row.column() {
|
||||||
gimli::ColumnType::Column(column) => column,
|
gimli::ColumnType::Column(column) => column.get(),
|
||||||
gimli::ColumnType::LeftEdge => 0,
|
gimli::ColumnType::LeftEdge => 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user