Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/crates/cranelift/src/debug/transform/refs.rs
1693 views
1
//! Helper utils for tracking and patching intra unit or section references.
2
3
use gimli::write;
4
use gimli::{DebugInfoOffset, Reader, UnitHeader, UnitOffset};
5
use std::collections::HashMap;
6
7
/// Stores compiled unit references: UnitEntryId+DwAt denotes a patch location
8
/// and UnitOffset is a location in original DWARF.
9
pub struct PendingUnitRefs {
10
refs: Vec<(write::UnitEntryId, gimli::DwAt, UnitOffset)>,
11
}
12
13
impl PendingUnitRefs {
14
pub fn new() -> Self {
15
Self { refs: Vec::new() }
16
}
17
pub fn insert(&mut self, entry_id: write::UnitEntryId, attr: gimli::DwAt, offset: UnitOffset) {
18
self.refs.push((entry_id, attr, offset));
19
}
20
}
21
22
/// Stores .debug_info references: UnitEntryId+DwAt denotes a patch location
23
/// and DebugInfoOffset is a location in original DWARF.
24
pub struct PendingDebugInfoRefs {
25
refs: Vec<(write::UnitEntryId, gimli::DwAt, DebugInfoOffset)>,
26
}
27
28
impl PendingDebugInfoRefs {
29
pub fn new() -> Self {
30
Self { refs: Vec::new() }
31
}
32
pub fn insert(
33
&mut self,
34
entry_id: write::UnitEntryId,
35
attr: gimli::DwAt,
36
offset: DebugInfoOffset,
37
) {
38
self.refs.push((entry_id, attr, offset));
39
}
40
}
41
42
/// Stores map between read and written references of DWARF entries of
43
/// a compiled unit.
44
pub struct UnitRefsMap {
45
map: HashMap<UnitOffset, write::UnitEntryId>,
46
}
47
48
impl UnitRefsMap {
49
pub fn new() -> Self {
50
Self {
51
map: HashMap::new(),
52
}
53
}
54
pub fn insert(&mut self, offset: UnitOffset, entry_id: write::UnitEntryId) {
55
self.map.insert(offset, entry_id);
56
}
57
pub fn patch(&self, refs: PendingUnitRefs, comp_unit: &mut write::Unit) {
58
for (die_id, attr_name, offset) in refs.refs {
59
let die = comp_unit.get_mut(die_id);
60
if let Some(unit_id) = self.map.get(&offset) {
61
die.set(attr_name, write::AttributeValue::UnitRef(*unit_id));
62
}
63
}
64
}
65
}
66
67
/// Stores map between read and written references of DWARF entries of
68
/// the entire .debug_info.
69
pub struct DebugInfoRefsMap {
70
map: HashMap<DebugInfoOffset, (write::UnitId, write::UnitEntryId)>,
71
}
72
73
impl DebugInfoRefsMap {
74
pub fn new() -> Self {
75
Self {
76
map: HashMap::new(),
77
}
78
}
79
pub fn insert<R>(&mut self, unit: &UnitHeader<R>, unit_id: write::UnitId, unit_map: UnitRefsMap)
80
where
81
R: Reader<Offset = usize>,
82
{
83
self.map
84
.extend(unit_map.map.into_iter().map(|(off, entry_id)| {
85
let off = off
86
.to_debug_info_offset(unit)
87
.expect("should be in debug_info section");
88
(off, (unit_id, entry_id))
89
}));
90
}
91
pub fn patch(
92
&self,
93
refs: impl Iterator<Item = (write::UnitId, PendingDebugInfoRefs)>,
94
units: &mut write::UnitTable,
95
) {
96
for (id, refs) in refs {
97
let unit = units.get_mut(id);
98
for (die_id, attr_name, offset) in refs.refs {
99
let die = unit.get_mut(die_id);
100
if let Some((id, entry_id)) = self.map.get(&offset) {
101
die.set(
102
attr_name,
103
write::AttributeValue::DebugInfoRef(write::Reference::Entry(
104
*id, *entry_id,
105
)),
106
);
107
}
108
}
109
}
110
}
111
}
112
113