[WIP] Set local DW_AT_location
This commit is contained in:
parent
21f0dfd014
commit
3fed880057
1 changed files with 122 additions and 6 deletions
128
src/debuginfo.rs
128
src/debuginfo.rs
|
@ -6,11 +6,15 @@ use std::marker::PhantomData;
|
||||||
|
|
||||||
use syntax::source_map::FileName;
|
use syntax::source_map::FileName;
|
||||||
|
|
||||||
|
use cranelift::codegen::ir::{StackSlots, ValueLoc};
|
||||||
|
use cranelift::codegen::isa::RegUnit;
|
||||||
|
|
||||||
use gimli::write::{
|
use gimli::write::{
|
||||||
Address, AttributeValue, DwarfUnit, EndianVec, FileId, LineProgram, LineString,
|
self, Address, AttributeValue, DwarfUnit, EndianVec, Expression, FileId, LineProgram,
|
||||||
LineStringTable, Range, RangeList, Result, Sections, UnitEntryId, Writer,
|
LineString, LineStringTable, Location, LocationList, Range, RangeList, Result, Sections,
|
||||||
|
UnitEntryId, Writer,
|
||||||
};
|
};
|
||||||
use gimli::{Encoding, Format, LineEncoding, RunTimeEndian, SectionId};
|
use gimli::{Encoding, Format, LineEncoding, Register, RunTimeEndian, SectionId, X86_64};
|
||||||
|
|
||||||
fn target_endian(tcx: TyCtxt) -> RunTimeEndian {
|
fn target_endian(tcx: TyCtxt) -> RunTimeEndian {
|
||||||
use rustc::ty::layout::Endian;
|
use rustc::ty::layout::Endian;
|
||||||
|
@ -380,9 +384,9 @@ impl<'a, 'tcx> FunctionDebugContext<'a, 'tcx> {
|
||||||
.chain(
|
.chain(
|
||||||
value_loc_ranges
|
value_loc_ranges
|
||||||
.iter()
|
.iter()
|
||||||
.map(|val_loc_range| Range::OffsetPair {
|
.map(|value_loc_range| Range::OffsetPair {
|
||||||
begin: u64::from(val_loc_range.start),
|
begin: u64::from(value_loc_range.start),
|
||||||
end: u64::from(val_loc_range.end),
|
end: u64::from(value_loc_range.end),
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.collect(),
|
.collect(),
|
||||||
|
@ -415,6 +419,34 @@ impl<'a, 'tcx> FunctionDebugContext<'a, 'tcx> {
|
||||||
gimli::DW_AT_type,
|
gimli::DW_AT_type,
|
||||||
AttributeValue::ThisUnitEntryRef(local_type),
|
AttributeValue::ThisUnitEntryRef(local_type),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
let loc_list = LocationList(
|
||||||
|
Some(Location::BaseAddress {
|
||||||
|
address: Address::Symbol {
|
||||||
|
symbol: self.symbol,
|
||||||
|
addend: 0,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.into_iter()
|
||||||
|
.chain(
|
||||||
|
value_loc_ranges
|
||||||
|
.iter()
|
||||||
|
.map(|value_loc_range| Location::OffsetPair {
|
||||||
|
begin: u64::from(value_loc_range.start),
|
||||||
|
end: u64::from(value_loc_range.end),
|
||||||
|
data: Expression(translate_loc(value_loc_range.loc, &context.func.stack_slots).unwrap()),
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.collect(),
|
||||||
|
);
|
||||||
|
let loc_list_id = self.debug_context.dwarf.unit.locations.add(loc_list);
|
||||||
|
|
||||||
|
let var_entry = self.debug_context.dwarf.unit.get_mut(var_id);
|
||||||
|
var_entry.set(
|
||||||
|
gimli::DW_AT_location,
|
||||||
|
AttributeValue::LocationListRef(loc_list_id),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -510,3 +542,87 @@ impl Writer for WriterRelocate {
|
||||||
self.write_udata_at(offset, 0, size)
|
self.write_udata_at(offset, 0, size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Adapted from https://github.com/CraneStation/wasmtime/blob/5a1845b4caf7a5dba8eda1fef05213a532ed4259/crates/debug/src/transform/expression.rs#L59-L137
|
||||||
|
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
if let Some(val) = REG_X86_MAP.as_mut().unwrap().get(®) {
|
||||||
|
return *val;
|
||||||
|
}
|
||||||
|
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, stack_slots: &StackSlots) -> Option<Vec<u8>> {
|
||||||
|
match loc {
|
||||||
|
ValueLoc::Reg(reg) => {
|
||||||
|
let machine_reg = map_reg(reg).0 as u8;
|
||||||
|
assert!(machine_reg <= 32); // FIXME
|
||||||
|
Some(vec![gimli::constants::DW_OP_reg0.0 + machine_reg])
|
||||||
|
}
|
||||||
|
ValueLoc::Stack(ss) => {
|
||||||
|
if let Some(ss_offset) = stack_slots[ss].offset {
|
||||||
|
let endian = gimli::RunTimeEndian::Little;
|
||||||
|
let mut writer = write::EndianVec::new(endian);
|
||||||
|
writer
|
||||||
|
.write_u8(gimli::constants::DW_OP_breg0.0 + X86_64::RBP.0 as u8)
|
||||||
|
.expect("bp wr");
|
||||||
|
writer.write_sleb128(ss_offset as i64 + 16).expect("ss wr");
|
||||||
|
writer
|
||||||
|
.write_u8(gimli::constants::DW_OP_deref.0 as u8)
|
||||||
|
.expect("bp wr");
|
||||||
|
let buf = writer.into_vec();
|
||||||
|
return Some(buf);
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue