Yury Delendik
5 years ago
committed by
GitHub
4 changed files with 159 additions and 46 deletions
@ -0,0 +1,111 @@ |
|||
//! Helper utils for tracking and patching intra unit or section references.
|
|||
|
|||
use gimli::write; |
|||
use gimli::{CompilationUnitHeader, DebugInfoOffset, Reader, UnitOffset}; |
|||
use std::collections::HashMap; |
|||
|
|||
/// Stores compiled unit references: UnitEntryId+DwAt denotes a patch location
|
|||
/// and UnitOffset is a location in original DWARF.
|
|||
pub struct PendingUnitRefs { |
|||
refs: Vec<(write::UnitEntryId, gimli::DwAt, UnitOffset)>, |
|||
} |
|||
|
|||
impl PendingUnitRefs { |
|||
pub fn new() -> Self { |
|||
Self { refs: Vec::new() } |
|||
} |
|||
pub fn insert(&mut self, entry_id: write::UnitEntryId, attr: gimli::DwAt, offset: UnitOffset) { |
|||
self.refs.push((entry_id, attr, offset)); |
|||
} |
|||
} |
|||
|
|||
/// Stores .debug_info references: UnitEntryId+DwAt denotes a patch location
|
|||
/// and DebugInfoOffset is a location in original DWARF.
|
|||
pub struct PendingDebugInfoRefs { |
|||
refs: Vec<(write::UnitEntryId, gimli::DwAt, DebugInfoOffset)>, |
|||
} |
|||
|
|||
impl PendingDebugInfoRefs { |
|||
pub fn new() -> Self { |
|||
Self { refs: Vec::new() } |
|||
} |
|||
pub fn insert( |
|||
&mut self, |
|||
entry_id: write::UnitEntryId, |
|||
attr: gimli::DwAt, |
|||
offset: DebugInfoOffset, |
|||
) { |
|||
self.refs.push((entry_id, attr, offset)); |
|||
} |
|||
} |
|||
|
|||
/// Stores map between read and written references of DWARF entries of
|
|||
/// a compiled unit.
|
|||
pub struct UnitRefsMap { |
|||
map: HashMap<UnitOffset, write::UnitEntryId>, |
|||
} |
|||
|
|||
impl UnitRefsMap { |
|||
pub fn new() -> Self { |
|||
Self { |
|||
map: HashMap::new(), |
|||
} |
|||
} |
|||
pub fn insert(&mut self, offset: UnitOffset, entry_id: write::UnitEntryId) { |
|||
self.map.insert(offset, entry_id); |
|||
} |
|||
pub fn patch(&self, refs: PendingUnitRefs, comp_unit: &mut write::Unit) { |
|||
for (die_id, attr_name, offset) in refs.refs { |
|||
let die = comp_unit.get_mut(die_id); |
|||
if let Some(unit_id) = self.map.get(&offset) { |
|||
die.set(attr_name, write::AttributeValue::ThisUnitEntryRef(*unit_id)); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
/// Stores map between read and written references of DWARF entries of
|
|||
/// the entire .debug_info.
|
|||
pub struct DebugInfoRefsMap { |
|||
map: HashMap<DebugInfoOffset, (write::UnitId, write::UnitEntryId)>, |
|||
} |
|||
|
|||
impl DebugInfoRefsMap { |
|||
pub fn new() -> Self { |
|||
Self { |
|||
map: HashMap::new(), |
|||
} |
|||
} |
|||
pub fn insert<R>( |
|||
&mut self, |
|||
unit: &CompilationUnitHeader<R>, |
|||
unit_id: write::UnitId, |
|||
unit_map: UnitRefsMap, |
|||
) where |
|||
R: Reader<Offset = usize>, |
|||
{ |
|||
self.map |
|||
.extend(unit_map.map.into_iter().map(|(off, entry_id)| { |
|||
let off = off.to_debug_info_offset(unit); |
|||
(off, (unit_id, entry_id)) |
|||
})); |
|||
} |
|||
pub fn patch( |
|||
&self, |
|||
refs: impl Iterator<Item = (write::UnitId, PendingDebugInfoRefs)>, |
|||
units: &mut write::UnitTable, |
|||
) { |
|||
for (id, refs) in refs { |
|||
let unit = units.get_mut(id); |
|||
for (die_id, attr_name, offset) in refs.refs { |
|||
let die = unit.get_mut(die_id); |
|||
if let Some((id, entry_id)) = self.map.get(&offset) { |
|||
die.set( |
|||
attr_name, |
|||
write::AttributeValue::AnyUnitEntryRef((*id, *entry_id)), |
|||
); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
Loading…
Reference in new issue