]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_codegen_cranelift/src/debuginfo/emit.rs
New upstream version 1.52.0~beta.3+dfsg1
[rustc.git] / compiler / rustc_codegen_cranelift / src / debuginfo / emit.rs
CommitLineData
29967ef6
XL
1//! Write the debuginfo into an object file.
2
3use rustc_data_structures::fx::FxHashMap;
4
5use gimli::write::{Address, AttributeValue, EndianVec, Result, Sections, Writer};
6use gimli::{RunTimeEndian, SectionId};
7
8use crate::backend::WriteDebugInfo;
9
10use super::DebugContext;
11
12impl DebugContext<'_> {
13 pub(crate) fn emit<P: WriteDebugInfo>(&mut self, product: &mut P) {
14 let unit_range_list_id = self.dwarf.unit.ranges.add(self.unit_range_list.clone());
15 let root = self.dwarf.unit.root();
16 let root = self.dwarf.unit.get_mut(root);
6a06907d 17 root.set(gimli::DW_AT_ranges, AttributeValue::RangeListRef(unit_range_list_id));
29967ef6
XL
18
19 let mut sections = Sections::new(WriterRelocate::new(self.endian));
20 self.dwarf.write(&mut sections).unwrap();
21
22 let mut section_map = FxHashMap::default();
23 let _: Result<()> = sections.for_each_mut(|id, section| {
24 if !section.writer.slice().is_empty() {
25 let section_id = product.add_debug_section(id, section.writer.take());
26 section_map.insert(id, section_id);
27 }
28 Ok(())
29 });
30
31 let _: Result<()> = sections.for_each(|id, section| {
32 if let Some(section_id) = section_map.get(&id) {
33 for reloc in &section.relocs {
34 product.add_debug_reloc(&section_map, section_id, reloc);
35 }
36 }
37 Ok(())
38 });
39 }
40}
41
42#[derive(Clone)]
43pub(crate) struct DebugReloc {
44 pub(crate) offset: u32,
45 pub(crate) size: u8,
46 pub(crate) name: DebugRelocName,
47 pub(crate) addend: i64,
48 pub(crate) kind: object::RelocationKind,
49}
50
51#[derive(Clone)]
52pub(crate) enum DebugRelocName {
53 Section(SectionId),
54 Symbol(usize),
55}
56
57/// A [`Writer`] that collects all necessary relocations.
58#[derive(Clone)]
59pub(super) struct WriterRelocate {
60 pub(super) relocs: Vec<DebugReloc>,
61 pub(super) writer: EndianVec<RunTimeEndian>,
62}
63
64impl WriterRelocate {
65 pub(super) fn new(endian: RunTimeEndian) -> Self {
6a06907d 66 WriterRelocate { relocs: Vec::new(), writer: EndianVec::new(endian) }
29967ef6
XL
67 }
68
69 /// Perform the collected relocations to be usable for JIT usage.
70 #[cfg(feature = "jit")]
5869c6ff 71 pub(super) fn relocate_for_jit(mut self, jit_module: &cranelift_jit::JITModule) -> Vec<u8> {
29967ef6
XL
72 use std::convert::TryInto;
73
74 for reloc in self.relocs.drain(..) {
75 match reloc.name {
76 super::DebugRelocName::Section(_) => unreachable!(),
77 super::DebugRelocName::Symbol(sym) => {
fc512014
XL
78 let addr = jit_module.get_finalized_function(
79 cranelift_module::FuncId::from_u32(sym.try_into().unwrap()),
80 );
29967ef6 81 let val = (addr as u64 as i64 + reloc.addend) as u64;
6a06907d 82 self.writer.write_udata_at(reloc.offset as usize, val, reloc.size).unwrap();
29967ef6
XL
83 }
84 }
85 }
86 self.writer.into_vec()
87 }
88}
89
90impl Writer for WriterRelocate {
91 type Endian = RunTimeEndian;
92
93 fn endian(&self) -> Self::Endian {
94 self.writer.endian()
95 }
96
97 fn len(&self) -> usize {
98 self.writer.len()
99 }
100
101 fn write(&mut self, bytes: &[u8]) -> Result<()> {
102 self.writer.write(bytes)
103 }
104
105 fn write_at(&mut self, offset: usize, bytes: &[u8]) -> Result<()> {
106 self.writer.write_at(offset, bytes)
107 }
108
109 fn write_address(&mut self, address: Address, size: u8) -> Result<()> {
110 match address {
111 Address::Constant(val) => self.write_udata(val, size),
112 Address::Symbol { symbol, addend } => {
113 let offset = self.len() as u64;
114 self.relocs.push(DebugReloc {
115 offset: offset as u32,
116 size,
117 name: DebugRelocName::Symbol(symbol),
118 addend: addend as i64,
119 kind: object::RelocationKind::Absolute,
120 });
121 self.write_udata(0, size)
122 }
123 }
124 }
125
126 fn write_offset(&mut self, val: usize, section: SectionId, size: u8) -> Result<()> {
127 let offset = self.len() as u32;
128 self.relocs.push(DebugReloc {
129 offset,
130 size,
131 name: DebugRelocName::Section(section),
132 addend: val as i64,
133 kind: object::RelocationKind::Absolute,
134 });
135 self.write_udata(0, size)
136 }
137
138 fn write_offset_at(
139 &mut self,
140 offset: usize,
141 val: usize,
142 section: SectionId,
143 size: u8,
144 ) -> Result<()> {
145 self.relocs.push(DebugReloc {
146 offset: offset as u32,
147 size,
148 name: DebugRelocName::Section(section),
149 addend: val as i64,
150 kind: object::RelocationKind::Absolute,
151 });
152 self.write_udata_at(offset, 0, size)
153 }
154
155 fn write_eh_pointer(&mut self, address: Address, eh_pe: gimli::DwEhPe, size: u8) -> Result<()> {
156 match address {
157 // Address::Constant arm copied from gimli
158 Address::Constant(val) => {
159 // Indirect doesn't matter here.
160 let val = match eh_pe.application() {
161 gimli::DW_EH_PE_absptr => val,
162 gimli::DW_EH_PE_pcrel => {
163 // TODO: better handling of sign
164 let offset = self.len() as u64;
165 offset.wrapping_sub(val)
166 }
167 _ => {
168 return Err(gimli::write::Error::UnsupportedPointerEncoding(eh_pe));
169 }
170 };
171 self.write_eh_pointer_data(val, eh_pe.format(), size)
172 }
173 Address::Symbol { symbol, addend } => match eh_pe.application() {
174 gimli::DW_EH_PE_pcrel => {
175 let size = match eh_pe.format() {
176 gimli::DW_EH_PE_sdata4 => 4,
177 _ => return Err(gimli::write::Error::UnsupportedPointerEncoding(eh_pe)),
178 };
179 self.relocs.push(DebugReloc {
180 offset: self.len() as u32,
181 size,
182 name: DebugRelocName::Symbol(symbol),
183 addend,
184 kind: object::RelocationKind::Relative,
185 });
186 self.write_udata(0, size)
187 }
188 _ => Err(gimli::write::Error::UnsupportedPointerEncoding(eh_pe)),
189 },
190 }
191 }
192}