Remove the debug crate's hard-coded dependency on register ordering

This commit is contained in:
Andrew Brown
2020-03-03 10:06:51 -08:00
parent 3f53bcb740
commit 1d15054310
10 changed files with 133 additions and 82 deletions

View File

@@ -5,8 +5,8 @@
use anyhow::Error;
use faerie::{Artifact, Decl};
use more_asserts::assert_gt;
use target_lexicon::{BinaryFormat, Triple};
use wasmtime_environ::isa::TargetFrontendConfig;
use target_lexicon::BinaryFormat;
use wasmtime_environ::isa::TargetIsa;
use wasmtime_environ::{ModuleAddressMap, ModuleVmctxInfo, ValueLabelsRanges};
pub use crate::read_debuginfo::{read_debuginfo, DebugInfoData, WasmFileInfo};
@@ -29,13 +29,13 @@ impl SymbolResolver for FunctionRelocResolver {
pub fn emit_debugsections(
obj: &mut Artifact,
vmctx_info: &ModuleVmctxInfo,
target_config: TargetFrontendConfig,
isa: &dyn TargetIsa,
debuginfo_data: &DebugInfoData,
at: &ModuleAddressMap,
ranges: &ValueLabelsRanges,
) -> Result<(), Error> {
let resolver = FunctionRelocResolver {};
let dwarf = transform_dwarf(target_config, debuginfo_data, at, vmctx_info, ranges)?;
let dwarf = transform_dwarf(isa, debuginfo_data, at, vmctx_info, ranges)?;
emit_dwarf(obj, dwarf, &resolver)?;
Ok(())
}
@@ -52,8 +52,7 @@ impl<'a> SymbolResolver for ImageRelocResolver<'a> {
}
pub fn emit_debugsections_image(
triple: Triple,
target_config: TargetFrontendConfig,
isa: &dyn TargetIsa,
debuginfo_data: &DebugInfoData,
vmctx_info: &ModuleVmctxInfo,
at: &ModuleAddressMap,
@@ -64,9 +63,9 @@ pub fn emit_debugsections_image(
.iter()
.map(|(ptr, _)| *ptr as u64)
.collect::<Vec<u64>>();
let mut obj = Artifact::new(triple, String::from("module"));
let mut obj = Artifact::new(isa.triple().clone(), String::from("module"));
let resolver = ImageRelocResolver { func_offsets };
let dwarf = transform_dwarf(target_config, debuginfo_data, at, vmctx_info, ranges)?;
let dwarf = transform_dwarf(isa, debuginfo_data, at, vmctx_info, ranges)?;
// Assuming all functions in the same code block, looking min/max of its range.
assert_gt!(funcs.len(), 0);

View File

@@ -5,10 +5,11 @@ use super::refs::{PendingDebugInfoRefs, PendingUnitRefs};
use super::{DebugInputContext, Reader, TransformError};
use anyhow::Error;
use gimli::{write, AttributeValue, DebugLineOffset, DebugStr, DebuggingInformationEntry};
use wasmtime_environ::isa::TargetIsa;
pub(crate) enum FileAttributeContext<'a> {
Root(Option<DebugLineOffset>),
Children(&'a Vec<write::FileId>, Option<&'a CompiledExpression>),
Children(&'a Vec<write::FileId>, Option<&'a CompiledExpression<'a>>),
}
fn is_exprloc_to_loclist_allowed(attr_name: gimli::constants::DwAt) -> bool {
@@ -41,6 +42,7 @@ pub(crate) fn clone_die_attributes<'a, R>(
pending_die_refs: &mut PendingUnitRefs,
pending_di_refs: &mut PendingDebugInfoRefs,
file_context: FileAttributeContext<'a>,
isa: &dyn TargetIsa,
) -> Result<(), Error>
where
R: Reader,
@@ -130,7 +132,9 @@ where
};
let mut result = None;
while let Some(loc) = locs.next()? {
if let Some(expr) = compile_expression(&loc.data, unit_encoding, frame_base)? {
if let Some(expr) =
compile_expression(&loc.data, unit_encoding, frame_base, isa)?
{
if result.is_none() {
result = Some(Vec::new());
}
@@ -168,7 +172,7 @@ where
} else {
None
};
if let Some(expr) = compile_expression(expr, unit_encoding, frame_base)? {
if let Some(expr) = compile_expression(expr, unit_encoding, frame_base, isa)? {
if expr.is_simple() {
if let Some(expr) = expr.build() {
write::AttributeValue::Exprloc(expr)

View File

@@ -5,7 +5,7 @@ use more_asserts::{assert_le, assert_lt};
use std::collections::{HashMap, HashSet};
use wasmtime_environ::entity::EntityRef;
use wasmtime_environ::ir::{StackSlots, ValueLabel, ValueLabelsRanges, ValueLoc};
use wasmtime_environ::isa::RegUnit;
use wasmtime_environ::isa::{RegUnit, TargetIsa};
use wasmtime_environ::wasm::{get_vmctx_value_label, DefinedFuncIndex};
use wasmtime_environ::ModuleMemoryOffset;
@@ -37,9 +37,10 @@ enum CompiledExpressionPart {
}
#[derive(Debug)]
pub struct CompiledExpression {
pub struct CompiledExpression<'a> {
parts: Vec<CompiledExpressionPart>,
need_deref: bool,
isa: &'a dyn TargetIsa,
}
impl Clone for CompiledExpressionPart {
@@ -52,77 +53,87 @@ impl Clone for CompiledExpressionPart {
}
}
impl CompiledExpression {
pub fn vmctx() -> CompiledExpression {
CompiledExpression::from_label(get_vmctx_value_label())
impl<'a> CompiledExpression<'a> {
pub fn vmctx(isa: &'a dyn TargetIsa) -> CompiledExpression {
CompiledExpression::from_label(get_vmctx_value_label(), isa)
}
pub fn from_label(label: ValueLabel) -> CompiledExpression {
pub fn from_label(label: ValueLabel, isa: &'a dyn TargetIsa) -> CompiledExpression<'a> {
CompiledExpression {
parts: vec![
CompiledExpressionPart::Local(label),
CompiledExpressionPart::Code(vec![gimli::constants::DW_OP_stack_value.0 as u8]),
],
need_deref: false,
isa,
}
}
}
fn map_reg(reg: RegUnit) -> Register {
static mut REG_X86_MAP: Option<HashMap<RegUnit, Register>> = None;
// FIXME lazy initialization?
unsafe {
if REG_X86_MAP.is_none() {
REG_X86_MAP = Some(HashMap::new());
fn map_reg(isa: &dyn TargetIsa, reg: RegUnit) -> Register {
// TODO avoid duplication with fde.rs
assert!(isa.name() == "x86" && isa.pointer_bits() == 64);
// Mapping from https://github.com/bytecodealliance/cranelift/pull/902 by @iximeow
const X86_GP_REG_MAP: [gimli::Register; 16] = [
X86_64::RAX,
X86_64::RCX,
X86_64::RDX,
X86_64::RBX,
X86_64::RSP,
X86_64::RBP,
X86_64::RSI,
X86_64::RDI,
X86_64::R8,
X86_64::R9,
X86_64::R10,
X86_64::R11,
X86_64::R12,
X86_64::R13,
X86_64::R14,
X86_64::R15,
];
const X86_XMM_REG_MAP: [gimli::Register; 16] = [
X86_64::XMM0,
X86_64::XMM1,
X86_64::XMM2,
X86_64::XMM3,
X86_64::XMM4,
X86_64::XMM5,
X86_64::XMM6,
X86_64::XMM7,
X86_64::XMM8,
X86_64::XMM9,
X86_64::XMM10,
X86_64::XMM11,
X86_64::XMM12,
X86_64::XMM13,
X86_64::XMM14,
X86_64::XMM15,
];
let reg_info = isa.register_info();
let bank = reg_info.bank_containing_regunit(reg).unwrap();
match bank.name {
"IntRegs" => {
// x86 GP registers have a weird mapping to DWARF registers, so we use a
// lookup table.
X86_GP_REG_MAP[(reg - bank.first_unit) as usize]
}
if let Some(val) = REG_X86_MAP.as_mut().unwrap().get(&reg) {
return *val;
"FloatRegs" => X86_XMM_REG_MAP[(reg - bank.first_unit) as usize],
_ => {
panic!("unsupported register bank: {}", bank.name);
}
let result = match reg {
0 => X86_64::RAX,
1 => X86_64::RCX,
2 => X86_64::RDX,
3 => X86_64::RBX,
4 => X86_64::RSP,
5 => X86_64::RBP,
6 => X86_64::RSI,
7 => X86_64::RDI,
8 => X86_64::R8,
9 => X86_64::R9,
10 => X86_64::R10,
11 => X86_64::R11,
12 => X86_64::R12,
13 => X86_64::R13,
14 => X86_64::R14,
15 => X86_64::R15,
16 => X86_64::XMM0,
17 => X86_64::XMM1,
18 => X86_64::XMM2,
19 => X86_64::XMM3,
20 => X86_64::XMM4,
21 => X86_64::XMM5,
22 => X86_64::XMM6,
23 => X86_64::XMM7,
24 => X86_64::XMM8,
25 => X86_64::XMM9,
26 => X86_64::XMM10,
27 => X86_64::XMM11,
28 => X86_64::XMM12,
29 => X86_64::XMM13,
30 => X86_64::XMM14,
31 => X86_64::XMM15,
_ => panic!("unknown x86_64 register {}", reg),
};
REG_X86_MAP.as_mut().unwrap().insert(reg, result);
result
}
}
fn translate_loc(loc: ValueLoc, frame_info: Option<&FunctionFrameInfo>) -> Option<Vec<u8>> {
fn translate_loc(
loc: ValueLoc,
frame_info: Option<&FunctionFrameInfo>,
isa: &dyn TargetIsa,
) -> Option<Vec<u8>> {
use gimli::write::Writer;
match loc {
ValueLoc::Reg(reg) => {
let machine_reg = map_reg(reg).0 as u8;
let machine_reg = map_reg(isa, reg).0 as u8;
Some(if machine_reg < 32 {
vec![gimli::constants::DW_OP_reg0.0 + machine_reg]
} else {
@@ -164,13 +175,14 @@ fn append_memory_deref(
frame_info: &FunctionFrameInfo,
vmctx_loc: ValueLoc,
endian: gimli::RunTimeEndian,
isa: &dyn TargetIsa,
) -> write::Result<bool> {
use gimli::write::Writer;
let mut writer = write::EndianVec::new(endian);
// FIXME for imported memory
match vmctx_loc {
ValueLoc::Reg(vmctx_reg) => {
let reg = map_reg(vmctx_reg);
let reg = map_reg(isa, vmctx_reg);
writer.write_u8(gimli::constants::DW_OP_breg0.0 + reg.0 as u8)?;
let memory_offset = match frame_info.vmctx_memory_offset() {
Some(offset) => offset,
@@ -213,7 +225,7 @@ fn append_memory_deref(
Ok(true)
}
impl CompiledExpression {
impl<'a> CompiledExpression<'a> {
pub fn is_simple(&self) -> bool {
if let [CompiledExpressionPart::Code(_)] = self.parts.as_slice() {
true
@@ -284,7 +296,7 @@ impl CompiledExpression {
CompiledExpressionPart::Code(c) => code_buf.extend_from_slice(c.as_slice()),
CompiledExpressionPart::Local(label) => {
let loc = *label_location.get(&label).expect("loc");
if let Some(expr) = translate_loc(loc, frame_info) {
if let Some(expr) = translate_loc(loc, frame_info, self.isa) {
code_buf.extend_from_slice(&expr)
} else {
continue 'range;
@@ -294,8 +306,14 @@ impl CompiledExpression {
if let (Some(vmctx_loc), Some(frame_info)) =
(label_location.get(&vmctx_label), frame_info)
{
if !append_memory_deref(&mut code_buf, frame_info, *vmctx_loc, endian)
.expect("append_memory_deref")
if !append_memory_deref(
&mut code_buf,
frame_info,
*vmctx_loc,
endian,
self.isa,
)
.expect("append_memory_deref")
{
continue 'range;
}
@@ -309,7 +327,7 @@ impl CompiledExpression {
if let (Some(vmctx_loc), Some(frame_info)) =
(label_location.get(&vmctx_label), frame_info)
{
if !append_memory_deref(&mut code_buf, frame_info, *vmctx_loc, endian)
if !append_memory_deref(&mut code_buf, frame_info, *vmctx_loc, endian, self.isa)
.expect("append_memory_deref")
{
continue 'range;
@@ -342,11 +360,12 @@ fn is_old_expression_format(buf: &[u8]) -> bool {
buf.contains(&(gimli::constants::DW_OP_plus_uconst.0 as u8))
}
pub fn compile_expression<R>(
pub fn compile_expression<'a, R>(
expr: &Expression<R>,
encoding: gimli::Encoding,
frame_base: Option<&CompiledExpression>,
) -> Result<Option<CompiledExpression>, Error>
isa: &'a dyn TargetIsa,
) -> Result<Option<CompiledExpression<'a>>, Error>
where
R: Reader,
{
@@ -437,7 +456,11 @@ where
}
}
Ok(Some(CompiledExpression { parts, need_deref }))
Ok(Some(CompiledExpression {
parts,
need_deref,
isa,
}))
}
#[derive(Debug, Clone)]

View File

@@ -10,7 +10,7 @@ use gimli::{
};
use std::collections::HashSet;
use thiserror::Error;
use wasmtime_environ::isa::TargetFrontendConfig;
use wasmtime_environ::isa::TargetIsa;
use wasmtime_environ::{ModuleAddressMap, ModuleVmctxInfo, ValueLabelsRanges};
pub use address_transform::AddressTransform;
@@ -47,7 +47,7 @@ where
}
pub fn transform_dwarf(
target_config: TargetFrontendConfig,
isa: &dyn TargetIsa,
di: &DebugInfoData,
at: &ModuleAddressMap,
vmctx_info: &ModuleVmctxInfo,
@@ -71,7 +71,7 @@ pub fn transform_dwarf(
// TODO: this should be configurable
// macOS doesn't seem to support DWARF > 3
version: 3,
address_size: target_config.pointer_bytes(),
address_size: isa.pointer_bytes(),
};
let mut out_strings = write::StringTable::default();
@@ -95,6 +95,7 @@ pub fn transform_dwarf(
&mut out_units,
&mut out_strings,
&mut translated,
isa,
)? {
di_ref_map.insert(&header, id, ref_map);
pending_di_refs.push((id, pending_refs));
@@ -111,6 +112,7 @@ pub fn transform_dwarf(
out_encoding,
&mut out_units,
&mut out_strings,
isa,
)?;
Ok(write::Dwarf {

View File

@@ -12,6 +12,7 @@ use wasmtime_environ::wasm::get_vmctx_value_label;
use wasmtime_environ::{ModuleVmctxInfo, ValueLabelsRanges};
pub use crate::read_debuginfo::{DebugInfoData, FunctionMetadata, WasmType};
use wasmtime_environ::isa::TargetIsa;
const PRODUCER_NAME: &str = "wasmtime";
@@ -175,6 +176,7 @@ fn generate_vars(
func_meta: &FunctionMetadata,
locals_names: Option<&HashMap<u32, String>>,
out_strings: &mut write::StringTable,
isa: &dyn TargetIsa,
) {
let vmctx_label = get_vmctx_value_label();
@@ -192,6 +194,7 @@ fn generate_vars(
Some(frame_info),
scope_ranges,
out_strings,
isa,
)
.expect("append_vmctx_info success");
} else {
@@ -207,7 +210,7 @@ fn generate_vars(
let loc_list_id = {
let endian = gimli::RunTimeEndian::Little;
let expr = CompiledExpression::from_label(*label);
let expr = CompiledExpression::from_label(*label, isa);
let mut locs = Vec::new();
for (begin, length, data) in
expr.build_with_locals(scope_ranges, addr_tr, Some(frame_info), endian)
@@ -258,6 +261,7 @@ pub fn generate_simulated_dwarf(
out_encoding: gimli::Encoding,
out_units: &mut write::UnitTable,
out_strings: &mut write::StringTable,
isa: &dyn TargetIsa,
) -> Result<(), Error> {
let path = di
.wasm_file
@@ -365,6 +369,7 @@ pub fn generate_simulated_dwarf(
&di.wasm_file.funcs[index],
locals_names.and_then(|m| m.get(&(index as u32))),
out_strings,
isa,
);
}
}

View File

@@ -11,6 +11,7 @@ use gimli::write;
use gimli::{AttributeValue, DebuggingInformationEntry, Unit};
use std::collections::HashSet;
use wasmtime_environ::entity::EntityRef;
use wasmtime_environ::isa::TargetIsa;
use wasmtime_environ::{ModuleVmctxInfo, ValueLabelsRanges};
struct InheritedAttr<T> {
@@ -148,6 +149,7 @@ pub(crate) fn clone_unit<'a, R>(
out_units: &mut write::UnitTable,
out_strings: &mut write::StringTable,
translated: &mut HashSet<u32>,
isa: &dyn TargetIsa,
) -> Result<Option<(write::UnitId, UnitRefsMap, PendingDebugInfoRefs)>, Error>
where
R: Reader,
@@ -203,6 +205,7 @@ where
&mut pending_die_refs,
&mut pending_di_refs,
FileAttributeContext::Root(Some(debug_line_offset)),
isa,
)?;
let (wp_die_id, vmctx_die_id) =
@@ -296,7 +299,7 @@ where
}
if let Some(AttributeValue::Exprloc(expr)) = entry.attr_value(gimli::DW_AT_frame_base)? {
if let Some(expr) = compile_expression(&expr, unit.encoding(), None)? {
if let Some(expr) = compile_expression(&expr, unit.encoding(), None, isa)? {
current_frame_base.push(new_stack_len, expr);
}
}
@@ -343,6 +346,7 @@ where
&mut pending_die_refs,
&mut pending_di_refs,
FileAttributeContext::Children(&file_map, current_frame_base.top()),
isa,
)?;
if entry.tag() == gimli::DW_TAG_subprogram && !current_scope_ranges.is_empty() {
@@ -354,6 +358,7 @@ where
current_value_range.top(),
current_scope_ranges.top().expect("range"),
out_strings,
isa,
)?;
}
}

View File

@@ -2,6 +2,7 @@ use super::address_transform::AddressTransform;
use super::expression::{CompiledExpression, FunctionFrameInfo};
use anyhow::Error;
use gimli::write;
use wasmtime_environ::isa::TargetIsa;
use wasmtime_environ::wasm::DefinedFuncIndex;
use wasmtime_environ::{ModuleMemoryOffset, ModuleVmctxInfo, ValueLabelsRanges};
@@ -109,11 +110,12 @@ pub(crate) fn append_vmctx_info(
frame_info: Option<&FunctionFrameInfo>,
scope_ranges: &[(u64, u64)],
out_strings: &mut write::StringTable,
isa: &dyn TargetIsa,
) -> Result<(), Error> {
let loc = {
let endian = gimli::RunTimeEndian::Little;
let expr = CompiledExpression::vmctx();
let expr = CompiledExpression::vmctx(isa);
let mut locs = Vec::new();
for (begin, length, data) in
expr.build_with_locals(scope_ranges, addr_tr, frame_info, endian)

View File

@@ -174,8 +174,7 @@ impl Compiler {
}
};
let bytes = emit_debugsections_image(
self.isa.triple().clone(),
target_config,
&*self.isa,
debug_data.as_ref().unwrap(),
&module_vmctx_info,
&address_transform,