]> git.lizzy.rs Git - rust.git/blob - src/backend.rs
Use pcrel pointers in .eh_frame
[rust.git] / src / backend.rs
1 use std::convert::{TryFrom, TryInto};
2
3 use rustc_data_structures::fx::FxHashMap;
4 use rustc_session::Session;
5
6 use cranelift_module::{FuncId, Module};
7
8 use object::write::*;
9 use object::{RelocationEncoding, RelocationKind, SectionKind, SymbolFlags};
10
11 use cranelift_object::{ObjectBackend, ObjectBuilder, ObjectProduct};
12
13 use gimli::SectionId;
14
15 use crate::debuginfo::{DebugReloc, DebugRelocName};
16
17 pub(crate) trait WriteMetadata {
18     fn add_rustc_section(&mut self, symbol_name: String, data: Vec<u8>, is_like_osx: bool);
19 }
20
21 impl WriteMetadata for object::write::Object {
22     fn add_rustc_section(&mut self, symbol_name: String, data: Vec<u8>, _is_like_osx: bool) {
23         let segment = self
24             .segment_name(object::write::StandardSegment::Data)
25             .to_vec();
26         let section_id = self.add_section(segment, b".rustc".to_vec(), object::SectionKind::Data);
27         let offset = self.append_section_data(section_id, &data, 1);
28         // For MachO and probably PE this is necessary to prevent the linker from throwing away the
29         // .rustc section. For ELF this isn't necessary, but it also doesn't harm.
30         self.add_symbol(object::write::Symbol {
31             name: symbol_name.into_bytes(),
32             value: offset,
33             size: data.len() as u64,
34             kind: object::SymbolKind::Data,
35             scope: object::SymbolScope::Dynamic,
36             weak: false,
37             section: SymbolSection::Section(section_id),
38             flags: SymbolFlags::None,
39         });
40     }
41 }
42
43 pub(crate) trait WriteDebugInfo {
44     type SectionId: Copy;
45
46     fn add_debug_section(&mut self, name: SectionId, data: Vec<u8>) -> Self::SectionId;
47     fn add_debug_reloc(
48         &mut self,
49         section_map: &FxHashMap<SectionId, Self::SectionId>,
50         from: &Self::SectionId,
51         reloc: &DebugReloc,
52     );
53 }
54
55 impl WriteDebugInfo for ObjectProduct {
56     type SectionId = (object::write::SectionId, object::write::SymbolId);
57
58     fn add_debug_section(
59         &mut self,
60         id: SectionId,
61         data: Vec<u8>,
62     ) -> (object::write::SectionId, object::write::SymbolId) {
63         let name = if self.object.format() == object::BinaryFormat::MachO {
64             id.name().replace('.', "__") // machO expects __debug_info instead of .debug_info
65         } else {
66             id.name().to_string()
67         }
68         .into_bytes();
69
70         let segment = self.object.segment_name(StandardSegment::Debug).to_vec();
71         // FIXME use SHT_X86_64_UNWIND for .eh_frame
72         let section_id = self.object.add_section(segment, name.clone(), if id == SectionId::EhFrame {
73             SectionKind::ReadOnlyData
74         } else {
75             SectionKind::Debug
76         });
77         self.object.section_mut(section_id).set_data(data, if id == SectionId::EhFrame {
78             8
79         } else {
80             1
81         });
82         let symbol_id = self.object.section_symbol(section_id);
83         (section_id, symbol_id)
84     }
85
86     fn add_debug_reloc(
87         &mut self,
88         section_map: &FxHashMap<SectionId, Self::SectionId>,
89         from: &Self::SectionId,
90         reloc: &DebugReloc,
91     ) {
92         let (symbol, symbol_offset) = match reloc.name {
93             DebugRelocName::Section(id) => (section_map.get(&id).unwrap().1, 0),
94             DebugRelocName::Symbol(id) => {
95                 let symbol_id = self.function_symbol(FuncId::from_u32(id.try_into().unwrap()));
96                 self.object
97                     .symbol_section_and_offset(symbol_id)
98                     .expect("Debug reloc for undef sym???")
99             }
100         };
101         self.object
102             .add_relocation(
103                 from.0,
104                 Relocation {
105                     offset: u64::from(reloc.offset),
106                     symbol,
107                     kind: reloc.kind,
108                     encoding: RelocationEncoding::Generic,
109                     size: reloc.size * 8,
110                     addend: i64::try_from(symbol_offset).unwrap() + reloc.addend,
111                 },
112             )
113             .unwrap();
114     }
115 }
116
117 // FIXME remove once atomic instructions are implemented in Cranelift.
118 pub(crate) trait AddConstructor {
119     fn add_constructor(&mut self, func_id: FuncId);
120 }
121
122 impl AddConstructor for ObjectProduct {
123     fn add_constructor(&mut self, func_id: FuncId) {
124         let symbol = self.function_symbol(func_id);
125         let segment = self
126             .object
127             .segment_name(object::write::StandardSegment::Data);
128         let init_array_section =
129             self.object
130                 .add_section(segment.to_vec(), b".init_array".to_vec(), SectionKind::Data);
131         self.object.append_section_data(
132             init_array_section,
133             &std::iter::repeat(0)
134                 .take(8 /*FIXME pointer size*/)
135                 .collect::<Vec<u8>>(),
136             8,
137         );
138         self.object
139             .add_relocation(
140                 init_array_section,
141                 object::write::Relocation {
142                     offset: 0,
143                     size: 64, // FIXME pointer size
144                     kind: RelocationKind::Absolute,
145                     encoding: RelocationEncoding::Generic,
146                     symbol,
147                     addend: 0,
148                 },
149             )
150             .unwrap();
151     }
152 }
153
154 pub(crate) trait Emit {
155     fn emit(self) -> Vec<u8>;
156 }
157
158 impl Emit for ObjectProduct {
159     fn emit(self) -> Vec<u8> {
160         self.object.write().unwrap()
161     }
162 }
163
164 pub(crate) fn with_object(sess: &Session, name: &str, f: impl FnOnce(&mut Object)) -> Vec<u8> {
165     let triple = crate::build_isa(sess, true).triple().clone();
166
167     let binary_format = match triple.binary_format {
168         target_lexicon::BinaryFormat::Elf => object::BinaryFormat::Elf,
169         target_lexicon::BinaryFormat::Coff => object::BinaryFormat::Coff,
170         target_lexicon::BinaryFormat::Macho => object::BinaryFormat::MachO,
171         binary_format => sess.fatal(&format!("binary format {} is unsupported", binary_format)),
172     };
173     let architecture = match triple.architecture {
174         target_lexicon::Architecture::X86_32(_) => object::Architecture::I386,
175         target_lexicon::Architecture::X86_64 => object::Architecture::X86_64,
176         target_lexicon::Architecture::Arm(_) => object::Architecture::Arm,
177         target_lexicon::Architecture::Aarch64(_) => object::Architecture::Aarch64,
178         architecture => sess.fatal(&format!(
179             "target architecture {:?} is unsupported",
180             architecture,
181         )),
182     };
183     let endian = match triple.endianness().unwrap() {
184         target_lexicon::Endianness::Little => object::Endianness::Little,
185         target_lexicon::Endianness::Big => object::Endianness::Big,
186     };
187
188     let mut metadata_object = object::write::Object::new(binary_format, architecture, endian);
189     metadata_object.add_file_symbol(name.as_bytes().to_vec());
190     f(&mut metadata_object);
191     metadata_object.write().unwrap()
192 }
193
194 pub(crate) type Backend =
195     impl cranelift_module::Backend<Product: AddConstructor + Emit + WriteDebugInfo>;
196
197 pub(crate) fn make_module(sess: &Session, name: String) -> Module<Backend> {
198     let mut builder = ObjectBuilder::new(
199         crate::build_isa(sess, true),
200         name + ".o",
201         cranelift_module::default_libcall_names(),
202     )
203     .unwrap();
204     if std::env::var("CG_CLIF_FUNCTION_SECTIONS").is_ok() {
205         builder.per_function_section(true);
206     }
207     let module: Module<ObjectBackend> = Module::new(
208         builder,
209     );
210     module
211 }