1 //! Abstraction around the object writing crate
3 use std::convert::{TryFrom, TryInto};
5 use rustc_data_structures::fx::FxHashMap;
6 use rustc_session::Session;
8 use cranelift_codegen::isa::TargetIsa;
9 use cranelift_module::FuncId;
10 use cranelift_object::{ObjectBuilder, ObjectModule, ObjectProduct};
12 use object::write::{Relocation, StandardSegment};
13 use object::{RelocationEncoding, SectionKind};
17 use crate::debuginfo::{DebugReloc, DebugRelocName};
19 pub(crate) trait WriteDebugInfo {
22 fn add_debug_section(&mut self, name: SectionId, data: Vec<u8>) -> Self::SectionId;
25 section_map: &FxHashMap<SectionId, Self::SectionId>,
26 from: &Self::SectionId,
31 impl WriteDebugInfo for ObjectProduct {
32 type SectionId = (object::write::SectionId, object::write::SymbolId);
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
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(
51 if id == SectionId::EhFrame { SectionKind::ReadOnlyData } else { SectionKind::Debug },
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)
62 section_map: &FxHashMap<SectionId, Self::SectionId>,
63 from: &Self::SectionId,
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()));
71 .symbol_section_and_offset(symbol_id)
72 .expect("Debug reloc for undef sym???")
79 offset: u64::from(reloc.offset),
82 encoding: RelocationEncoding::Generic,
84 addend: i64::try_from(symbol_offset).unwrap() + reloc.addend,
91 pub(crate) fn make_module(sess: &Session, isa: Box<dyn TargetIsa>, name: String) -> ObjectModule {
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)