1 use rustc_data_structures::fx::FxHashMap; 2 3 use cranelift_module::FuncId; 4 use cranelift_object::ObjectProduct; 5 6 use object::write::{Relocation, StandardSegment}; 7 use object::{RelocationEncoding, SectionKind}; 8 9 use gimli::SectionId; 10 11 use crate::debuginfo::{DebugReloc, DebugRelocName}; 12 13 pub(super) trait WriteDebugInfo { 14 type SectionId: Copy; 15 add_debug_section(&mut self, name: SectionId, data: Vec<u8>) -> Self::SectionId16 fn add_debug_section(&mut self, name: SectionId, data: Vec<u8>) -> Self::SectionId; add_debug_reloc( &mut self, section_map: &FxHashMap<SectionId, Self::SectionId>, from: &Self::SectionId, reloc: &DebugReloc, )17 fn add_debug_reloc( 18 &mut self, 19 section_map: &FxHashMap<SectionId, Self::SectionId>, 20 from: &Self::SectionId, 21 reloc: &DebugReloc, 22 ); 23 } 24 25 impl WriteDebugInfo for ObjectProduct { 26 type SectionId = (object::write::SectionId, object::write::SymbolId); 27 add_debug_section( &mut self, id: SectionId, data: Vec<u8>, ) -> (object::write::SectionId, object::write::SymbolId)28 fn add_debug_section( 29 &mut self, 30 id: SectionId, 31 data: Vec<u8>, 32 ) -> (object::write::SectionId, object::write::SymbolId) { 33 let name = if self.object.format() == object::BinaryFormat::MachO { 34 id.name().replace('.', "__") // machO expects __debug_info instead of .debug_info 35 } else { 36 id.name().to_string() 37 } 38 .into_bytes(); 39 40 let segment = self.object.segment_name(StandardSegment::Debug).to_vec(); 41 // FIXME use SHT_X86_64_UNWIND for .eh_frame 42 let section_id = self.object.add_section( 43 segment, 44 name, 45 if id == SectionId::EhFrame { SectionKind::ReadOnlyData } else { SectionKind::Debug }, 46 ); 47 self.object 48 .section_mut(section_id) 49 .set_data(data, if id == SectionId::EhFrame { 8 } else { 1 }); 50 let symbol_id = self.object.section_symbol(section_id); 51 (section_id, symbol_id) 52 } 53 add_debug_reloc( &mut self, section_map: &FxHashMap<SectionId, Self::SectionId>, from: &Self::SectionId, reloc: &DebugReloc, )54 fn add_debug_reloc( 55 &mut self, 56 section_map: &FxHashMap<SectionId, Self::SectionId>, 57 from: &Self::SectionId, 58 reloc: &DebugReloc, 59 ) { 60 let (symbol, symbol_offset) = match reloc.name { 61 DebugRelocName::Section(id) => (section_map.get(&id).unwrap().1, 0), 62 DebugRelocName::Symbol(id) => { 63 let symbol_id = self.function_symbol(FuncId::from_u32(id.try_into().unwrap())); 64 self.object 65 .symbol_section_and_offset(symbol_id) 66 .expect("Debug reloc for undef sym???") 67 } 68 }; 69 self.object 70 .add_relocation( 71 from.0, 72 Relocation { 73 offset: u64::from(reloc.offset), 74 symbol, 75 kind: reloc.kind, 76 encoding: RelocationEncoding::Generic, 77 size: reloc.size * 8, 78 addend: i64::try_from(symbol_offset).unwrap() + reloc.addend, 79 }, 80 ) 81 .unwrap(); 82 } 83 } 84