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:
Benjamin Bouvier
2021-05-12 17:53:17 +02:00
committed by GitHub
parent 60f7b23ea1
commit d7053ea9c7
16 changed files with 195 additions and 190 deletions

21
Cargo.lock generated
View File

@@ -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",

View File

@@ -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"

View File

@@ -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" }

View File

@@ -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"

View File

@@ -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 }

View File

@@ -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"

View File

@@ -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")
} }

View File

@@ -541,25 +541,8 @@ 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
pc.read_u8()?;
let ty = pc.read_uleb128()?;
// Supporting only wasm locals.
if ty != 0 {
// TODO support wasm globals?
return Ok(None);
}
let index = pc.read_sleb128()?;
flush_code_chunk!();
let label = ValueLabel::from_u32(index as u32);
push!(CompiledExpressionPart::Local {
label,
trailing: false,
});
} else {
let pos = pc.offset_from(&expr.0).into_u64() as usize; let pos = pc.offset_from(&expr.0).into_u64() as usize;
let op = Operation::parse(&mut pc, encoding)?; let op = Operation::parse(&mut pc, encoding)?;
match op { match op {
@@ -649,6 +632,15 @@ where
// Don't re-enter the loop here (i.e. continue), because the // Don't re-enter the loop here (i.e. continue), because the
// DW_OP_deref still needs to be kept. // 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 { .. } => { Operation::Shr { .. } | Operation::Shra { .. } => {
// Insert value normalisation part. // Insert value normalisation part.
// The semantic value is 32 bits (TODO: check unit) // The semantic value is 32 bits (TODO: check unit)
@@ -681,11 +673,14 @@ where
| Operation::ParameterRef { .. } => { | Operation::ParameterRef { .. } => {
return Ok(None); return Ok(None);
} }
Operation::WasmGlobal { index: _ } | Operation::WasmStack { index: _ } => {
// TODO support those two
return Ok(None);
}
} }
let chunk = &buf[pos..pc.offset_from(&expr.0).into_u64() as usize]; let chunk = &buf[pos..pc.offset_from(&expr.0).into_u64() as usize];
code_chunk.extend_from_slice(chunk); code_chunk.extend_from_slice(chunk);
} }
}
flush_code_chunk!(); flush_code_chunk!();
if let Some(marker) = jump_targets.get(&0) { if let Some(marker) = jump_targets.get(&0) {

View File

@@ -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(),

View File

@@ -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" }

View File

@@ -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;

View File

@@ -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"] }

View File

@@ -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,

View File

@@ -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" }

View File

@@ -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']

View File

@@ -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,
}; };