Update gimli version; refactor debug data structures
This commit is contained in:
committed by
Dan Gohman
parent
adadf835f0
commit
efe9dd7b86
@@ -12,13 +12,12 @@ readme = "README.md"
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
gimli = "0.17.0"
|
gimli = "0.19.0"
|
||||||
wasmparser = { version = "0.32.1" }
|
wasmparser = { version = "0.32.1" }
|
||||||
cranelift-codegen = "0.33.0"
|
cranelift-codegen = "0.33.0"
|
||||||
cranelift-entity = "0.33.0"
|
cranelift-entity = "0.33.0"
|
||||||
cranelift-wasm = "0.33.0"
|
cranelift-wasm = "0.33.0"
|
||||||
faerie = "0.10.1"
|
faerie = "0.10.1"
|
||||||
wasmtime-environ = { path = "../wasmtime-environ", default-features = false }
|
|
||||||
target-lexicon = { version = "0.4.0", default-features = false }
|
target-lexicon = { version = "0.4.0", default-features = false }
|
||||||
failure = { version = "0.1.3", default-features = false }
|
failure = { version = "0.1.3", default-features = false }
|
||||||
failure_derive = { version = "0.1.3", default-features = false }
|
failure_derive = { version = "0.1.3", default-features = false }
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
use crate::read_debuginfo::WasmFileInfo;
|
use crate::read_debuginfo::WasmFileInfo;
|
||||||
|
use crate::transform::ModuleAddressMap;
|
||||||
use cranelift_entity::{EntityRef, PrimaryMap};
|
use cranelift_entity::{EntityRef, PrimaryMap};
|
||||||
use cranelift_wasm::DefinedFuncIndex;
|
use cranelift_wasm::DefinedFuncIndex;
|
||||||
use gimli::write;
|
use gimli::write;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::ops::Bound::{Included, Unbounded};
|
use std::ops::Bound::{Included, Unbounded};
|
||||||
use std::vec::Vec;
|
use std::vec::Vec;
|
||||||
use wasmtime_environ::AddressTransforms;
|
|
||||||
|
|
||||||
pub type GeneratedAddress = usize;
|
pub type GeneratedAddress = usize;
|
||||||
pub type WasmAddress = u64;
|
pub type WasmAddress = u64;
|
||||||
@@ -32,7 +32,7 @@ pub struct AddressTransform {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl AddressTransform {
|
impl AddressTransform {
|
||||||
pub fn new(at: &AddressTransforms, wasm_file: &WasmFileInfo) -> Self {
|
pub fn new(at: &ModuleAddressMap, wasm_file: &WasmFileInfo) -> Self {
|
||||||
let code_section_offset = wasm_file.code_section_offset;
|
let code_section_offset = wasm_file.code_section_offset;
|
||||||
let function_offsets = &wasm_file.function_offsets_and_sizes;
|
let function_offsets = &wasm_file.function_offsets_and_sizes;
|
||||||
let mut lookup = BTreeMap::new();
|
let mut lookup = BTreeMap::new();
|
||||||
@@ -50,7 +50,7 @@ impl AddressTransform {
|
|||||||
(index, ft.body_offset, ft.body_offset),
|
(index, ft.body_offset, ft.body_offset),
|
||||||
);
|
);
|
||||||
let mut fn_map = Vec::new();
|
let mut fn_map = Vec::new();
|
||||||
for t in &ft.locations {
|
for t in &ft.instructions {
|
||||||
if t.srcloc.is_default() {
|
if t.srcloc.is_default() {
|
||||||
// TODO extend some range if possible
|
// TODO extend some range if possible
|
||||||
continue;
|
continue;
|
||||||
@@ -90,7 +90,7 @@ impl AddressTransform {
|
|||||||
}
|
}
|
||||||
let search = self.lookup.range((Unbounded, Included(addr)));
|
let search = self.lookup.range((Unbounded, Included(addr)));
|
||||||
if let Some((_, value)) = search.last() {
|
if let Some((_, value)) = search.last() {
|
||||||
return Some(write::Address::Relative {
|
return Some(write::Address::Symbol {
|
||||||
symbol: value.0,
|
symbol: value.0,
|
||||||
addend: value.1 as i64,
|
addend: value.1 as i64,
|
||||||
});
|
});
|
||||||
@@ -106,11 +106,11 @@ impl AddressTransform {
|
|||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
if let (
|
if let (
|
||||||
Some(write::Address::Relative {
|
Some(write::Address::Symbol {
|
||||||
symbol: s1,
|
symbol: s1,
|
||||||
addend: a,
|
addend: a,
|
||||||
}),
|
}),
|
||||||
Some(write::Address::Relative {
|
Some(write::Address::Symbol {
|
||||||
symbol: s2,
|
symbol: s2,
|
||||||
addend: b,
|
addend: b,
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -4,12 +4,13 @@ use faerie::{Artifact, Decl};
|
|||||||
use failure::Error;
|
use failure::Error;
|
||||||
use target_lexicon::{BinaryFormat, Triple};
|
use target_lexicon::{BinaryFormat, Triple};
|
||||||
|
|
||||||
pub use crate::read_debuginfo::{read_debuginfo, DebugInfoData};
|
pub use crate::read_debuginfo::{read_debuginfo, DebugInfoData, WasmFileInfo};
|
||||||
pub use crate::transform::transform_dwarf;
|
pub use crate::transform::{
|
||||||
|
transform_dwarf, FunctionAddressMap, InstructionAddressMap, ModuleAddressMap, ModuleVmctxInfo,
|
||||||
|
ValueLabelsRanges,
|
||||||
|
};
|
||||||
pub use crate::write_debuginfo::{emit_dwarf, ResolvedSymbol, SymbolResolver};
|
pub use crate::write_debuginfo::{emit_dwarf, ResolvedSymbol, SymbolResolver};
|
||||||
|
|
||||||
use wasmtime_environ::AddressTransforms;
|
|
||||||
|
|
||||||
mod address_transform;
|
mod address_transform;
|
||||||
mod read_debuginfo;
|
mod read_debuginfo;
|
||||||
mod transform;
|
mod transform;
|
||||||
@@ -30,11 +31,11 @@ pub fn emit_debugsections(
|
|||||||
obj: &mut Artifact,
|
obj: &mut Artifact,
|
||||||
target_config: &TargetFrontendConfig,
|
target_config: &TargetFrontendConfig,
|
||||||
debuginfo_data: &DebugInfoData,
|
debuginfo_data: &DebugInfoData,
|
||||||
at: &AddressTransforms,
|
at: &ModuleAddressMap,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let dwarf = transform_dwarf(target_config, debuginfo_data, at)?;
|
|
||||||
let resolver = FunctionRelocResolver {};
|
let resolver = FunctionRelocResolver {};
|
||||||
emit_dwarf(obj, dwarf, &resolver);
|
let dwarf = transform_dwarf(target_config, debuginfo_data, at)?;
|
||||||
|
emit_dwarf(obj, dwarf, &resolver)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,7 +54,7 @@ pub fn emit_debugsections_image(
|
|||||||
triple: Triple,
|
triple: Triple,
|
||||||
target_config: &TargetFrontendConfig,
|
target_config: &TargetFrontendConfig,
|
||||||
debuginfo_data: &DebugInfoData,
|
debuginfo_data: &DebugInfoData,
|
||||||
at: &AddressTransforms,
|
at: &ModuleAddressMap,
|
||||||
funcs: &Vec<(*const u8, usize)>,
|
funcs: &Vec<(*const u8, usize)>,
|
||||||
) -> Result<Vec<u8>, Error> {
|
) -> Result<Vec<u8>, Error> {
|
||||||
let ref func_offsets = funcs
|
let ref func_offsets = funcs
|
||||||
@@ -61,8 +62,8 @@ pub fn emit_debugsections_image(
|
|||||||
.map(|(ptr, _)| *ptr as u64)
|
.map(|(ptr, _)| *ptr as u64)
|
||||||
.collect::<Vec<u64>>();
|
.collect::<Vec<u64>>();
|
||||||
let mut obj = Artifact::new(triple, String::from("module"));
|
let mut obj = Artifact::new(triple, String::from("module"));
|
||||||
let dwarf = transform_dwarf(target_config, debuginfo_data, at)?;
|
|
||||||
let resolver = ImageRelocResolver { func_offsets };
|
let resolver = ImageRelocResolver { func_offsets };
|
||||||
|
let dwarf = transform_dwarf(target_config, debuginfo_data, at)?;
|
||||||
|
|
||||||
// Assuming all functions in the same code block, looking min/max of its range.
|
// Assuming all functions in the same code block, looking min/max of its range.
|
||||||
assert!(funcs.len() > 0);
|
assert!(funcs.len() > 0);
|
||||||
@@ -76,7 +77,7 @@ pub fn emit_debugsections_image(
|
|||||||
let body = unsafe { ::std::slice::from_raw_parts(segment_body.0, segment_body.1) };
|
let body = unsafe { ::std::slice::from_raw_parts(segment_body.0, segment_body.1) };
|
||||||
obj.declare_with("all", Decl::function(), body.to_vec())?;
|
obj.declare_with("all", Decl::function(), body.to_vec())?;
|
||||||
|
|
||||||
emit_dwarf(&mut obj, dwarf, &resolver);
|
emit_dwarf(&mut obj, dwarf, &resolver)?;
|
||||||
|
|
||||||
// LLDB is too "magical" about mach-o, generating elf
|
// LLDB is too "magical" about mach-o, generating elf
|
||||||
let mut bytes = obj.emit_as(BinaryFormat::Elf)?;
|
let mut bytes = obj.emit_as(BinaryFormat::Elf)?;
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
use crate::address_transform::AddressTransform;
|
use crate::address_transform::AddressTransform;
|
||||||
pub use crate::read_debuginfo::DebugInfoData;
|
pub use crate::read_debuginfo::DebugInfoData;
|
||||||
|
use cranelift_codegen::ir;
|
||||||
use cranelift_codegen::isa::TargetFrontendConfig;
|
use cranelift_codegen::isa::TargetFrontendConfig;
|
||||||
use cranelift_entity::EntityRef;
|
use cranelift_entity::{EntityRef, PrimaryMap};
|
||||||
|
use cranelift_wasm::DefinedFuncIndex;
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
use std::collections::{BTreeMap, HashMap};
|
use std::collections::{BTreeMap, HashMap};
|
||||||
use std::ops::Bound::{Included, Unbounded};
|
use std::ops::Bound::{Included, Unbounded};
|
||||||
@@ -24,14 +26,45 @@ impl<'input, Endian> Reader for gimli::EndianSlice<'input, Endian> where Endian:
|
|||||||
#[fail(display = "Debug info transform error: {}", _0)]
|
#[fail(display = "Debug info transform error: {}", _0)]
|
||||||
pub struct TransformError(&'static str);
|
pub struct TransformError(&'static str);
|
||||||
|
|
||||||
pub struct TransformedDwarf {
|
/// Single wasm source location to generated address mapping.
|
||||||
pub encoding: gimli::Encoding,
|
#[derive(Debug, Clone)]
|
||||||
pub strings: write::StringTable,
|
pub struct InstructionAddressMap {
|
||||||
pub units: write::UnitTable,
|
/// Original source location.
|
||||||
pub line_strings: write::LineStringTable,
|
pub srcloc: ir::SourceLoc,
|
||||||
pub range_lists: write::RangeListTable,
|
|
||||||
|
/// Generated instructions offset.
|
||||||
|
pub code_offset: usize,
|
||||||
|
|
||||||
|
/// Generated instructions length.
|
||||||
|
pub code_len: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Function and its instructions addresses mappings.
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct FunctionAddressMap {
|
||||||
|
/// Instructions maps.
|
||||||
|
/// The array is sorted by the InstructionAddressMap::code_offset field.
|
||||||
|
pub instructions: Vec<InstructionAddressMap>,
|
||||||
|
|
||||||
|
/// Generated function body offset if applicable, otherwise 0.
|
||||||
|
pub body_offset: usize,
|
||||||
|
|
||||||
|
/// Generated function body length.
|
||||||
|
pub body_len: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Module functions addresses mappings.
|
||||||
|
pub type ModuleAddressMap = PrimaryMap<DefinedFuncIndex, FunctionAddressMap>;
|
||||||
|
|
||||||
|
/// Module `vmctx` related info.
|
||||||
|
pub struct ModuleVmctxInfo {
|
||||||
|
pub memory_offset: i64,
|
||||||
|
pub stack_slots: PrimaryMap<DefinedFuncIndex, ir::StackSlots>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Value ranges for functions.
|
||||||
|
pub type ValueLabelsRanges = PrimaryMap<DefinedFuncIndex, cranelift_codegen::ValueLabelsRanges>;
|
||||||
|
|
||||||
struct DebugInputContext<'a, R>
|
struct DebugInputContext<'a, R>
|
||||||
where
|
where
|
||||||
R: Reader,
|
R: Reader,
|
||||||
@@ -84,7 +117,7 @@ where
|
|||||||
write::AttributeValue::Udata(subprogram_range.unwrap().1)
|
write::AttributeValue::Udata(subprogram_range.unwrap().1)
|
||||||
}
|
}
|
||||||
AttributeValue::Addr(u) => {
|
AttributeValue::Addr(u) => {
|
||||||
let addr = addr_tr.translate(u).unwrap_or(write::Address::Absolute(0));
|
let addr = addr_tr.translate(u).unwrap_or(write::Address::Constant(0));
|
||||||
if attr.name() == gimli::DW_AT_low_pc {
|
if attr.name() == gimli::DW_AT_low_pc {
|
||||||
low_pc = Some((u, addr));
|
low_pc = Some((u, addr));
|
||||||
}
|
}
|
||||||
@@ -370,7 +403,7 @@ where
|
|||||||
for (i, map) in addr_tr.map() {
|
for (i, map) in addr_tr.map() {
|
||||||
let symbol = i.index();
|
let symbol = i.index();
|
||||||
let base_addr = map.offset;
|
let base_addr = map.offset;
|
||||||
out_program.begin_sequence(Some(write::Address::Relative { symbol, addend: 0 }));
|
out_program.begin_sequence(Some(write::Address::Symbol { symbol, addend: 0 }));
|
||||||
// TODO track and place function declaration line here
|
// TODO track and place function declaration line here
|
||||||
let mut last_address = None;
|
let mut last_address = None;
|
||||||
for addr_map in map.addresses.iter() {
|
for addr_map in map.addresses.iter() {
|
||||||
@@ -440,9 +473,9 @@ where
|
|||||||
let low_pc = entry.attr_value(gimli::DW_AT_low_pc)?;
|
let low_pc = entry.attr_value(gimli::DW_AT_low_pc)?;
|
||||||
if let Some(AttributeValue::Addr(addr)) = low_pc {
|
if let Some(AttributeValue::Addr(addr)) = low_pc {
|
||||||
let transformed = addr_tr.translate(addr);
|
let transformed = addr_tr.translate(addr);
|
||||||
if let Some(write::Address::Relative { symbol, .. }) = transformed {
|
if let Some(write::Address::Symbol { symbol, .. }) = transformed {
|
||||||
let range = addr_tr.func_range(symbol);
|
let range = addr_tr.func_range(symbol);
|
||||||
let addr = write::Address::Relative {
|
let addr = write::Address::Symbol {
|
||||||
symbol,
|
symbol,
|
||||||
addend: range.0 as i64,
|
addend: range.0 as i64,
|
||||||
};
|
};
|
||||||
@@ -580,8 +613,8 @@ where
|
|||||||
pub fn transform_dwarf(
|
pub fn transform_dwarf(
|
||||||
target_config: &TargetFrontendConfig,
|
target_config: &TargetFrontendConfig,
|
||||||
di: &DebugInfoData,
|
di: &DebugInfoData,
|
||||||
at: &wasmtime_environ::AddressTransforms,
|
at: &ModuleAddressMap,
|
||||||
) -> Result<TransformedDwarf, Error> {
|
) -> Result<write::Dwarf, Error> {
|
||||||
let context = DebugInputContext {
|
let context = DebugInputContext {
|
||||||
debug_abbrev: &di.dwarf.debug_abbrev,
|
debug_abbrev: &di.dwarf.debug_abbrev,
|
||||||
debug_str: &di.dwarf.debug_str,
|
debug_str: &di.dwarf.debug_str,
|
||||||
@@ -605,7 +638,6 @@ pub fn transform_dwarf(
|
|||||||
let mut out_strings = write::StringTable::default();
|
let mut out_strings = write::StringTable::default();
|
||||||
let mut out_units = write::UnitTable::default();
|
let mut out_units = write::UnitTable::default();
|
||||||
|
|
||||||
let out_range_lists = write::RangeListTable::default();
|
|
||||||
let out_line_strings = write::LineStringTable::default();
|
let out_line_strings = write::LineStringTable::default();
|
||||||
|
|
||||||
let mut iter = di.dwarf.debug_info.units();
|
let mut iter = di.dwarf.debug_info.units();
|
||||||
@@ -620,22 +652,10 @@ pub fn transform_dwarf(
|
|||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// let unit_range_list = write::RangeList(Vec::new());
|
Ok(write::Dwarf {
|
||||||
// let unit_range_list_id = out_range_lists.add(unit_range_list.clone());
|
|
||||||
// let unit = dwarf.units.get_mut(self.unit_id);
|
|
||||||
// let root = unit.root();
|
|
||||||
// let root = unit.get_mut(root);
|
|
||||||
// root.set(
|
|
||||||
// gimli::DW_AT_ranges,
|
|
||||||
// AttributeValue::RangeListRef(unit_range_list_id),
|
|
||||||
// );
|
|
||||||
|
|
||||||
//println!("{:?} \n====\n {:?}", di, at);
|
|
||||||
Ok(TransformedDwarf {
|
|
||||||
encoding: out_encoding,
|
|
||||||
strings: out_strings,
|
|
||||||
units: out_units,
|
units: out_units,
|
||||||
|
line_programs: vec![],
|
||||||
line_strings: out_line_strings,
|
line_strings: out_line_strings,
|
||||||
range_lists: out_range_lists,
|
strings: out_strings,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,11 @@
|
|||||||
use crate::transform::TransformedDwarf;
|
use gimli::write::{Address, Dwarf, EndianVec, Result, Sections, Writer};
|
||||||
|
use gimli::{RunTimeEndian, SectionId};
|
||||||
use gimli::write::{
|
|
||||||
Address, DebugAbbrev, DebugInfo, DebugLine, DebugLineStr, DebugRanges, DebugRngLists, DebugStr,
|
|
||||||
EndianVec, Result, SectionId, Sections, Writer,
|
|
||||||
};
|
|
||||||
use gimli::RunTimeEndian;
|
|
||||||
|
|
||||||
use faerie::artifact::{Decl, SectionKind};
|
use faerie::artifact::{Decl, SectionKind};
|
||||||
use faerie::*;
|
use faerie::*;
|
||||||
|
use std::result;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
struct DebugReloc {
|
struct DebugReloc {
|
||||||
offset: u32,
|
offset: u32,
|
||||||
size: u8,
|
size: u8,
|
||||||
@@ -16,38 +13,6 @@ struct DebugReloc {
|
|||||||
addend: i64,
|
addend: i64,
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! decl_section {
|
|
||||||
($artifact:ident . $section:ident = $name:expr) => {
|
|
||||||
$artifact
|
|
||||||
.declare_with(
|
|
||||||
SectionId::$section.name(),
|
|
||||||
Decl::section(SectionKind::Debug),
|
|
||||||
$name.0.writer.into_vec(),
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! sect_relocs {
|
|
||||||
($artifact:ident . $section:ident = $name:expr) => {
|
|
||||||
for reloc in $name.0.relocs {
|
|
||||||
$artifact
|
|
||||||
.link_with(
|
|
||||||
faerie::Link {
|
|
||||||
from: SectionId::$section.name(),
|
|
||||||
to: &reloc.name,
|
|
||||||
at: u64::from(reloc.offset),
|
|
||||||
},
|
|
||||||
faerie::Reloc::Debug {
|
|
||||||
size: reloc.size,
|
|
||||||
addend: reloc.addend as i32,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.expect("faerie relocation error");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum ResolvedSymbol {
|
pub enum ResolvedSymbol {
|
||||||
PhysicalAddress(u64),
|
PhysicalAddress(u64),
|
||||||
Reloc { name: String, addend: i64 },
|
Reloc { name: String, addend: i64 },
|
||||||
@@ -59,75 +24,48 @@ pub trait SymbolResolver {
|
|||||||
|
|
||||||
pub fn emit_dwarf(
|
pub fn emit_dwarf(
|
||||||
artifact: &mut Artifact,
|
artifact: &mut Artifact,
|
||||||
mut dwarf: TransformedDwarf,
|
mut dwarf: Dwarf,
|
||||||
symbol_resolver: &SymbolResolver,
|
symbol_resolver: &SymbolResolver,
|
||||||
) {
|
) -> result::Result<(), failure::Error> {
|
||||||
let endian = RunTimeEndian::Little;
|
let endian = RunTimeEndian::Little;
|
||||||
let debug_abbrev = DebugAbbrev::from(WriterRelocate::new(endian, symbol_resolver));
|
|
||||||
let debug_info = DebugInfo::from(WriterRelocate::new(endian, symbol_resolver));
|
|
||||||
let debug_str = DebugStr::from(WriterRelocate::new(endian, symbol_resolver));
|
|
||||||
let debug_line = DebugLine::from(WriterRelocate::new(endian, symbol_resolver));
|
|
||||||
let debug_ranges = DebugRanges::from(WriterRelocate::new(endian, symbol_resolver));
|
|
||||||
let debug_rnglists = DebugRngLists::from(WriterRelocate::new(endian, symbol_resolver));
|
|
||||||
let debug_line_str = DebugLineStr::from(WriterRelocate::new(endian, symbol_resolver));
|
|
||||||
|
|
||||||
let mut sections = Sections {
|
let mut sections = Sections::new(WriterRelocate::new(endian, symbol_resolver));
|
||||||
debug_abbrev,
|
dwarf.write(&mut sections)?;
|
||||||
debug_info,
|
sections.for_each_mut(|id, s| -> result::Result<(), failure::Error> {
|
||||||
debug_line,
|
artifact.declare_with(
|
||||||
debug_line_str,
|
id.name(),
|
||||||
debug_ranges,
|
Decl::section(SectionKind::Debug),
|
||||||
debug_rnglists,
|
s.writer.take(),
|
||||||
debug_str,
|
)
|
||||||
};
|
})?;
|
||||||
|
sections.for_each_mut(|id, s| -> result::Result<(), failure::Error> {
|
||||||
let debug_str_offsets = dwarf.strings.write(&mut sections.debug_str).unwrap();
|
for reloc in &s.relocs {
|
||||||
let debug_line_str_offsets = dwarf
|
artifact.link_with(
|
||||||
.line_strings
|
faerie::Link {
|
||||||
.write(&mut sections.debug_line_str)
|
from: id.name(),
|
||||||
.unwrap();
|
to: &reloc.name,
|
||||||
dwarf
|
at: u64::from(reloc.offset),
|
||||||
.units
|
},
|
||||||
.write(&mut sections, &debug_line_str_offsets, &debug_str_offsets)
|
faerie::Reloc::Debug {
|
||||||
.unwrap();
|
size: reloc.size,
|
||||||
|
addend: reloc.addend as i32,
|
||||||
decl_section!(artifact.DebugAbbrev = sections.debug_abbrev);
|
},
|
||||||
decl_section!(artifact.DebugInfo = sections.debug_info);
|
)?;
|
||||||
decl_section!(artifact.DebugStr = sections.debug_str);
|
|
||||||
decl_section!(artifact.DebugLine = sections.debug_line);
|
|
||||||
|
|
||||||
let debug_ranges_not_empty = !sections.debug_ranges.0.writer.slice().is_empty();
|
|
||||||
if debug_ranges_not_empty {
|
|
||||||
decl_section!(artifact.DebugRanges = sections.debug_ranges);
|
|
||||||
}
|
|
||||||
|
|
||||||
let debug_rnglists_not_empty = !sections.debug_rnglists.0.writer.slice().is_empty();
|
|
||||||
if debug_rnglists_not_empty {
|
|
||||||
decl_section!(artifact.DebugRngLists = sections.debug_rnglists);
|
|
||||||
}
|
|
||||||
|
|
||||||
sect_relocs!(artifact.DebugAbbrev = sections.debug_abbrev);
|
|
||||||
sect_relocs!(artifact.DebugInfo = sections.debug_info);
|
|
||||||
sect_relocs!(artifact.DebugStr = sections.debug_str);
|
|
||||||
sect_relocs!(artifact.DebugLine = sections.debug_line);
|
|
||||||
|
|
||||||
if debug_ranges_not_empty {
|
|
||||||
sect_relocs!(artifact.DebugRanges = sections.debug_ranges);
|
|
||||||
}
|
|
||||||
|
|
||||||
if debug_rnglists_not_empty {
|
|
||||||
sect_relocs!(artifact.DebugRngLists = sections.debug_rnglists);
|
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
|
})?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
struct WriterRelocate<'a> {
|
#[derive(Clone)]
|
||||||
|
pub struct WriterRelocate<'a> {
|
||||||
relocs: Vec<DebugReloc>,
|
relocs: Vec<DebugReloc>,
|
||||||
writer: EndianVec<RunTimeEndian>,
|
writer: EndianVec<RunTimeEndian>,
|
||||||
symbol_resolver: &'a SymbolResolver,
|
symbol_resolver: &'a SymbolResolver,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> WriterRelocate<'a> {
|
impl<'a> WriterRelocate<'a> {
|
||||||
fn new(endian: RunTimeEndian, symbol_resolver: &'a SymbolResolver) -> Self {
|
pub fn new(endian: RunTimeEndian, symbol_resolver: &'a SymbolResolver) -> Self {
|
||||||
WriterRelocate {
|
WriterRelocate {
|
||||||
relocs: Vec::new(),
|
relocs: Vec::new(),
|
||||||
writer: EndianVec::new(endian),
|
writer: EndianVec::new(endian),
|
||||||
@@ -157,10 +95,10 @@ impl<'a> Writer for WriterRelocate<'a> {
|
|||||||
|
|
||||||
fn write_address(&mut self, address: Address, size: u8) -> Result<()> {
|
fn write_address(&mut self, address: Address, size: u8) -> Result<()> {
|
||||||
match address {
|
match address {
|
||||||
Address::Absolute(val) => self.write_word(val, size),
|
Address::Constant(val) => self.write_udata(val, size),
|
||||||
Address::Relative { symbol, addend } => {
|
Address::Symbol { symbol, addend } => {
|
||||||
match self.symbol_resolver.resolve_symbol(symbol, addend as i64) {
|
match self.symbol_resolver.resolve_symbol(symbol, addend as i64) {
|
||||||
ResolvedSymbol::PhysicalAddress(addr) => self.write_word(addr, size),
|
ResolvedSymbol::PhysicalAddress(addr) => self.write_udata(addr, size),
|
||||||
ResolvedSymbol::Reloc { name, addend } => {
|
ResolvedSymbol::Reloc { name, addend } => {
|
||||||
let offset = self.len() as u64;
|
let offset = self.len() as u64;
|
||||||
self.relocs.push(DebugReloc {
|
self.relocs.push(DebugReloc {
|
||||||
@@ -169,7 +107,7 @@ impl<'a> Writer for WriterRelocate<'a> {
|
|||||||
name,
|
name,
|
||||||
addend,
|
addend,
|
||||||
});
|
});
|
||||||
self.write_word(addend as u64, size)
|
self.write_udata(addend as u64, size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -185,7 +123,7 @@ impl<'a> Writer for WriterRelocate<'a> {
|
|||||||
name,
|
name,
|
||||||
addend: val as i64,
|
addend: val as i64,
|
||||||
});
|
});
|
||||||
self.write_word(val as u64, size)
|
self.write_udata(val as u64, size)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_offset_at(
|
fn write_offset_at(
|
||||||
@@ -202,6 +140,6 @@ impl<'a> Writer for WriterRelocate<'a> {
|
|||||||
name,
|
name,
|
||||||
addend: val as i64,
|
addend: val as i64,
|
||||||
});
|
});
|
||||||
self.write_word_at(offset, val as u64, size)
|
self.write_udata_at(offset, val as u64, size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ failure = { version = "0.1.3", default-features = false }
|
|||||||
failure_derive = { version = "0.1.3", default-features = false }
|
failure_derive = { version = "0.1.3", default-features = false }
|
||||||
indexmap = "1.0.2"
|
indexmap = "1.0.2"
|
||||||
rayon = "1.0"
|
rayon = "1.0"
|
||||||
|
wasmtime-debug = { path = "../wasmtime-debug", default-features = false }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["std"]
|
default = ["std"]
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ use cranelift_entity::PrimaryMap;
|
|||||||
use cranelift_wasm::{DefinedFuncIndex, FuncIndex, WasmError};
|
use cranelift_wasm::{DefinedFuncIndex, FuncIndex, WasmError};
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
use std::vec::Vec;
|
use std::vec::Vec;
|
||||||
|
use wasmtime_debug::ModuleAddressMap;
|
||||||
|
|
||||||
/// Compiled machine code: body and jump table offsets.
|
/// Compiled machine code: body and jump table offsets.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@@ -139,35 +140,6 @@ pub enum CompileError {
|
|||||||
Codegen(CodegenError),
|
Codegen(CodegenError),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Single address point transform.
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct InstructionAddressTransform {
|
|
||||||
/// Original source location.
|
|
||||||
pub srcloc: ir::SourceLoc,
|
|
||||||
|
|
||||||
/// Generated instructions offset.
|
|
||||||
pub code_offset: usize,
|
|
||||||
|
|
||||||
/// Generated instructions length.
|
|
||||||
pub code_len: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Function and its instructions transforms.
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct FunctionAddressTransform {
|
|
||||||
/// Instructions transforms
|
|
||||||
pub locations: Vec<InstructionAddressTransform>,
|
|
||||||
|
|
||||||
/// Generated function body offset if applicable, otherwise 0.
|
|
||||||
pub body_offset: usize,
|
|
||||||
|
|
||||||
/// Generated function body length.
|
|
||||||
pub body_len: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Function AddressTransforms collection.
|
|
||||||
pub type AddressTransforms = PrimaryMap<DefinedFuncIndex, FunctionAddressTransform>;
|
|
||||||
|
|
||||||
/// An implementation of a compiler from parsed WebAssembly module to native code.
|
/// An implementation of a compiler from parsed WebAssembly module to native code.
|
||||||
pub trait Compiler {
|
pub trait Compiler {
|
||||||
/// Compile a parsed module with the given `TargetIsa`.
|
/// Compile a parsed module with the given `TargetIsa`.
|
||||||
@@ -176,5 +148,5 @@ pub trait Compiler {
|
|||||||
function_body_inputs: PrimaryMap<DefinedFuncIndex, FunctionBodyData<'data>>,
|
function_body_inputs: PrimaryMap<DefinedFuncIndex, FunctionBodyData<'data>>,
|
||||||
isa: &dyn isa::TargetIsa,
|
isa: &dyn isa::TargetIsa,
|
||||||
generate_debug_info: bool,
|
generate_debug_info: bool,
|
||||||
) -> Result<(Compilation, Relocations, AddressTransforms), CompileError>;
|
) -> Result<(Compilation, Relocations, ModuleAddressMap), CompileError>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
//! Support for compiling with Cranelift.
|
//! Support for compiling with Cranelift.
|
||||||
|
|
||||||
use crate::compilation::{
|
use crate::compilation::{
|
||||||
AddressTransforms, CodeAndJTOffsets, Compilation, CompileError, FunctionAddressTransform,
|
CodeAndJTOffsets, Compilation, CompileError, Relocation, RelocationTarget, Relocations,
|
||||||
InstructionAddressTransform, Relocation, RelocationTarget, Relocations,
|
|
||||||
};
|
};
|
||||||
use crate::func_environ::{
|
use crate::func_environ::{
|
||||||
get_func_name, get_imported_memory32_grow_name, get_imported_memory32_size_name,
|
get_func_name, get_imported_memory32_grow_name, get_imported_memory32_size_name,
|
||||||
@@ -19,6 +18,7 @@ use cranelift_entity::PrimaryMap;
|
|||||||
use cranelift_wasm::{DefinedFuncIndex, FuncIndex, FuncTranslator};
|
use cranelift_wasm::{DefinedFuncIndex, FuncIndex, FuncTranslator};
|
||||||
use rayon::prelude::{IntoParallelRefIterator, ParallelIterator};
|
use rayon::prelude::{IntoParallelRefIterator, ParallelIterator};
|
||||||
use std::vec::Vec;
|
use std::vec::Vec;
|
||||||
|
use wasmtime_debug::{FunctionAddressMap, InstructionAddressMap, ModuleAddressMap};
|
||||||
|
|
||||||
/// Implementation of a relocation sink that just saves all the information for later
|
/// Implementation of a relocation sink that just saves all the information for later
|
||||||
pub struct RelocSink {
|
pub struct RelocSink {
|
||||||
@@ -89,10 +89,7 @@ impl RelocSink {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_address_transform(
|
fn get_address_transform(context: &Context, isa: &isa::TargetIsa) -> Vec<InstructionAddressMap> {
|
||||||
context: &Context,
|
|
||||||
isa: &isa::TargetIsa,
|
|
||||||
) -> Vec<InstructionAddressTransform> {
|
|
||||||
let mut result = Vec::new();
|
let mut result = Vec::new();
|
||||||
|
|
||||||
let func = &context.func;
|
let func = &context.func;
|
||||||
@@ -103,7 +100,7 @@ fn get_address_transform(
|
|||||||
for ebb in ebbs {
|
for ebb in ebbs {
|
||||||
for (offset, inst, size) in func.inst_offsets(ebb, &encinfo) {
|
for (offset, inst, size) in func.inst_offsets(ebb, &encinfo) {
|
||||||
let srcloc = func.srclocs[inst];
|
let srcloc = func.srclocs[inst];
|
||||||
result.push(InstructionAddressTransform {
|
result.push(InstructionAddressMap {
|
||||||
srcloc,
|
srcloc,
|
||||||
code_offset: offset as usize,
|
code_offset: offset as usize,
|
||||||
code_len: size as usize,
|
code_len: size as usize,
|
||||||
@@ -125,7 +122,7 @@ impl crate::compilation::Compiler for Cranelift {
|
|||||||
function_body_inputs: PrimaryMap<DefinedFuncIndex, FunctionBodyData<'data>>,
|
function_body_inputs: PrimaryMap<DefinedFuncIndex, FunctionBodyData<'data>>,
|
||||||
isa: &dyn isa::TargetIsa,
|
isa: &dyn isa::TargetIsa,
|
||||||
generate_debug_info: bool,
|
generate_debug_info: bool,
|
||||||
) -> Result<(Compilation, Relocations, AddressTransforms), CompileError> {
|
) -> Result<(Compilation, Relocations, ModuleAddressMap), CompileError> {
|
||||||
let mut functions = PrimaryMap::with_capacity(function_body_inputs.len());
|
let mut functions = PrimaryMap::with_capacity(function_body_inputs.len());
|
||||||
let mut relocations = PrimaryMap::with_capacity(function_body_inputs.len());
|
let mut relocations = PrimaryMap::with_capacity(function_body_inputs.len());
|
||||||
let mut address_transforms = PrimaryMap::with_capacity(function_body_inputs.len());
|
let mut address_transforms = PrimaryMap::with_capacity(function_body_inputs.len());
|
||||||
@@ -162,8 +159,9 @@ impl crate::compilation::Compiler for Cranelift {
|
|||||||
let address_transform = if generate_debug_info {
|
let address_transform = if generate_debug_info {
|
||||||
let body_len = code_buf.len();
|
let body_len = code_buf.len();
|
||||||
let at = get_address_transform(&context, isa);
|
let at = get_address_transform(&context, isa);
|
||||||
Some(FunctionAddressTransform {
|
|
||||||
locations: at,
|
Some(FunctionAddressMap {
|
||||||
|
instructions: at,
|
||||||
body_offset: 0,
|
body_offset: 0,
|
||||||
body_len,
|
body_len,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -49,8 +49,7 @@ pub mod cranelift;
|
|||||||
pub mod lightbeam;
|
pub mod lightbeam;
|
||||||
|
|
||||||
pub use crate::compilation::{
|
pub use crate::compilation::{
|
||||||
AddressTransforms, Compilation, CompileError, Compiler, InstructionAddressTransform,
|
Compilation, CompileError, Compiler, Relocation, RelocationTarget, Relocations,
|
||||||
Relocation, RelocationTarget, Relocations,
|
|
||||||
};
|
};
|
||||||
pub use crate::cranelift::Cranelift;
|
pub use crate::cranelift::Cranelift;
|
||||||
#[cfg(feature = "lightbeam")]
|
#[cfg(feature = "lightbeam")]
|
||||||
|
|||||||
Reference in New Issue
Block a user