Path: blob/main/crates/cranelift/src/debug/transform/refs.rs
1693 views
//! Helper utils for tracking and patching intra unit or section references.12use gimli::write;3use gimli::{DebugInfoOffset, Reader, UnitHeader, UnitOffset};4use std::collections::HashMap;56/// Stores compiled unit references: UnitEntryId+DwAt denotes a patch location7/// and UnitOffset is a location in original DWARF.8pub struct PendingUnitRefs {9refs: Vec<(write::UnitEntryId, gimli::DwAt, UnitOffset)>,10}1112impl PendingUnitRefs {13pub fn new() -> Self {14Self { refs: Vec::new() }15}16pub fn insert(&mut self, entry_id: write::UnitEntryId, attr: gimli::DwAt, offset: UnitOffset) {17self.refs.push((entry_id, attr, offset));18}19}2021/// Stores .debug_info references: UnitEntryId+DwAt denotes a patch location22/// and DebugInfoOffset is a location in original DWARF.23pub struct PendingDebugInfoRefs {24refs: Vec<(write::UnitEntryId, gimli::DwAt, DebugInfoOffset)>,25}2627impl PendingDebugInfoRefs {28pub fn new() -> Self {29Self { refs: Vec::new() }30}31pub fn insert(32&mut self,33entry_id: write::UnitEntryId,34attr: gimli::DwAt,35offset: DebugInfoOffset,36) {37self.refs.push((entry_id, attr, offset));38}39}4041/// Stores map between read and written references of DWARF entries of42/// a compiled unit.43pub struct UnitRefsMap {44map: HashMap<UnitOffset, write::UnitEntryId>,45}4647impl UnitRefsMap {48pub fn new() -> Self {49Self {50map: HashMap::new(),51}52}53pub fn insert(&mut self, offset: UnitOffset, entry_id: write::UnitEntryId) {54self.map.insert(offset, entry_id);55}56pub fn patch(&self, refs: PendingUnitRefs, comp_unit: &mut write::Unit) {57for (die_id, attr_name, offset) in refs.refs {58let die = comp_unit.get_mut(die_id);59if let Some(unit_id) = self.map.get(&offset) {60die.set(attr_name, write::AttributeValue::UnitRef(*unit_id));61}62}63}64}6566/// Stores map between read and written references of DWARF entries of67/// the entire .debug_info.68pub struct DebugInfoRefsMap {69map: HashMap<DebugInfoOffset, (write::UnitId, write::UnitEntryId)>,70}7172impl DebugInfoRefsMap {73pub fn new() -> Self {74Self {75map: HashMap::new(),76}77}78pub fn insert<R>(&mut self, unit: &UnitHeader<R>, unit_id: write::UnitId, unit_map: UnitRefsMap)79where80R: Reader<Offset = usize>,81{82self.map83.extend(unit_map.map.into_iter().map(|(off, entry_id)| {84let off = off85.to_debug_info_offset(unit)86.expect("should be in debug_info section");87(off, (unit_id, entry_id))88}));89}90pub fn patch(91&self,92refs: impl Iterator<Item = (write::UnitId, PendingDebugInfoRefs)>,93units: &mut write::UnitTable,94) {95for (id, refs) in refs {96let unit = units.get_mut(id);97for (die_id, attr_name, offset) in refs.refs {98let die = unit.get_mut(die_id);99if let Some((id, entry_id)) = self.map.get(&offset) {100die.set(101attr_name,102write::AttributeValue::DebugInfoRef(write::Reference::Entry(103*id, *entry_id,104)),105);106}107}108}109}110}111112113