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