1 //! Write the debuginfo into an object file. 2 3 use cranelift_object::ObjectProduct; 4 use rustc_data_structures::fx::FxHashMap; 5 6 use gimli::write::{Address, AttributeValue, EndianVec, Result, Sections, Writer}; 7 use gimli::{RunTimeEndian, SectionId}; 8 9 use super::object::WriteDebugInfo; 10 use super::DebugContext; 11 12 impl DebugContext<'_> { emit(&mut self, product: &mut ObjectProduct)13 pub(crate) fn emit(&mut self, product: &mut ObjectProduct) { 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); 17 root.set(gimli::DW_AT_ranges, AttributeValue::RangeListRef(unit_range_list_id)); 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 §ion.relocs { 34 product.add_debug_reloc(§ion_map, section_id, reloc); 35 } 36 } 37 Ok(()) 38 }); 39 } 40 } 41 42 #[derive(Clone)] 43 pub(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)] 52 pub(crate) enum DebugRelocName { 53 Section(SectionId), 54 Symbol(usize), 55 } 56 57 /// A [`Writer`] that collects all necessary relocations. 58 #[derive(Clone)] 59 pub(super) struct WriterRelocate { 60 pub(super) relocs: Vec<DebugReloc>, 61 pub(super) writer: EndianVec<RunTimeEndian>, 62 } 63 64 impl WriterRelocate { new(endian: RunTimeEndian) -> Self65 pub(super) fn new(endian: RunTimeEndian) -> Self { 66 WriterRelocate { relocs: Vec::new(), writer: EndianVec::new(endian) } 67 } 68 69 /// Perform the collected relocations to be usable for JIT usage. 70 #[cfg(feature = "jit")] relocate_for_jit(mut self, jit_module: &cranelift_jit::JITModule) -> Vec<u8>71 pub(super) fn relocate_for_jit(mut self, jit_module: &cranelift_jit::JITModule) -> Vec<u8> { 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) => { 78 let addr = jit_module.get_finalized_function( 79 cranelift_module::FuncId::from_u32(sym.try_into().unwrap()), 80 ); 81 let val = (addr as u64 as i64 + reloc.addend) as u64; 82 self.writer.write_udata_at(reloc.offset as usize, val, reloc.size).unwrap(); 83 } 84 } 85 } 86 self.writer.into_vec() 87 } 88 } 89 90 impl Writer for WriterRelocate { 91 type Endian = RunTimeEndian; 92 endian(&self) -> Self::Endian93 fn endian(&self) -> Self::Endian { 94 self.writer.endian() 95 } 96 len(&self) -> usize97 fn len(&self) -> usize { 98 self.writer.len() 99 } 100 write(&mut self, bytes: &[u8]) -> Result<()>101 fn write(&mut self, bytes: &[u8]) -> Result<()> { 102 self.writer.write(bytes) 103 } 104 write_at(&mut self, offset: usize, bytes: &[u8]) -> Result<()>105 fn write_at(&mut self, offset: usize, bytes: &[u8]) -> Result<()> { 106 self.writer.write_at(offset, bytes) 107 } 108 write_address(&mut self, address: Address, size: u8) -> Result<()>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 write_offset(&mut self, val: usize, section: SectionId, size: u8) -> Result<()>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 write_offset_at( &mut self, offset: usize, val: usize, section: SectionId, size: u8, ) -> Result<()>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 write_eh_pointer(&mut self, address: Address, eh_pe: gimli::DwEhPe, size: u8) -> Result<()>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 // FIXME 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 } 193