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