]> git.lizzy.rs Git - rust.git/blob - src/backend.rs
Move Object creation into metadata.rs
[rust.git] / src / backend.rs
1 //! Abstraction around the object writing crate
2
3 use std::convert::{TryFrom, TryInto};
4
5 use rustc_data_structures::fx::FxHashMap;
6 use rustc_session::Session;
7
8 use cranelift_codegen::isa::TargetIsa;
9 use cranelift_module::FuncId;
10 use cranelift_object::{ObjectBuilder, ObjectModule, ObjectProduct};
11
12 use object::write::{Relocation, StandardSegment};
13 use object::{RelocationEncoding, SectionKind};
14
15 use gimli::SectionId;
16
17 use crate::debuginfo::{DebugReloc, DebugRelocName};
18
19 pub(crate) trait WriteDebugInfo {
20     type SectionId: Copy;
21
22     fn add_debug_section(&mut self, name: SectionId, data: Vec<u8>) -> Self::SectionId;
23     fn add_debug_reloc(
24         &mut self,
25         section_map: &FxHashMap<SectionId, Self::SectionId>,
26         from: &Self::SectionId,
27         reloc: &DebugReloc,
28     );
29 }
30
31 impl WriteDebugInfo for ObjectProduct {
32     type SectionId = (object::write::SectionId, object::write::SymbolId);
33
34     fn add_debug_section(
35         &mut self,
36         id: SectionId,
37         data: Vec<u8>,
38     ) -> (object::write::SectionId, object::write::SymbolId) {
39         let name = if self.object.format() == object::BinaryFormat::MachO {
40             id.name().replace('.', "__") // machO expects __debug_info instead of .debug_info
41         } else {
42             id.name().to_string()
43         }
44         .into_bytes();
45
46         let segment = self.object.segment_name(StandardSegment::Debug).to_vec();
47         // FIXME use SHT_X86_64_UNWIND for .eh_frame
48         let section_id = self.object.add_section(
49             segment,
50             name,
51             if id == SectionId::EhFrame { SectionKind::ReadOnlyData } else { SectionKind::Debug },
52         );
53         self.object
54             .section_mut(section_id)
55             .set_data(data, if id == SectionId::EhFrame { 8 } else { 1 });
56         let symbol_id = self.object.section_symbol(section_id);
57         (section_id, symbol_id)
58     }
59
60     fn add_debug_reloc(
61         &mut self,
62         section_map: &FxHashMap<SectionId, Self::SectionId>,
63         from: &Self::SectionId,
64         reloc: &DebugReloc,
65     ) {
66         let (symbol, symbol_offset) = match reloc.name {
67             DebugRelocName::Section(id) => (section_map.get(&id).unwrap().1, 0),
68             DebugRelocName::Symbol(id) => {
69                 let symbol_id = self.function_symbol(FuncId::from_u32(id.try_into().unwrap()));
70                 self.object
71                     .symbol_section_and_offset(symbol_id)
72                     .expect("Debug reloc for undef sym???")
73             }
74         };
75         self.object
76             .add_relocation(
77                 from.0,
78                 Relocation {
79                     offset: u64::from(reloc.offset),
80                     symbol,
81                     kind: reloc.kind,
82                     encoding: RelocationEncoding::Generic,
83                     size: reloc.size * 8,
84                     addend: i64::try_from(symbol_offset).unwrap() + reloc.addend,
85                 },
86             )
87             .unwrap();
88     }
89 }
90
91 pub(crate) fn make_module(sess: &Session, isa: Box<dyn TargetIsa>, name: String) -> ObjectModule {
92     let mut builder =
93         ObjectBuilder::new(isa, name + ".o", cranelift_module::default_libcall_names()).unwrap();
94     // Unlike cg_llvm, cg_clif defaults to disabling -Zfunction-sections. For cg_llvm binary size
95     // is important, while cg_clif cares more about compilation times. Enabling -Zfunction-sections
96     // can easily double the amount of time necessary to perform linking.
97     builder.per_function_section(sess.opts.debugging_opts.function_sections.unwrap_or(false));
98     ObjectModule::new(builder)
99 }