Files
rust/src/backend.rs

100 lines
3.5 KiB
Rust
Raw Normal View History

//! Abstraction around the object writing crate
2020-05-01 19:21:29 +02:00
use std::convert::{TryFrom, TryInto};
2020-04-05 14:01:02 +02:00
use rustc_data_structures::fx::FxHashMap;
use rustc_session::Session;
2019-10-18 17:19:13 +02:00
use cranelift_codegen::isa::TargetIsa;
use cranelift_module::FuncId;
use cranelift_object::{ObjectBuilder, ObjectModule, ObjectProduct};
2021-08-20 21:38:17 +02:00
use object::write::{Relocation, StandardSegment};
use object::{RelocationEncoding, SectionKind};
2019-10-19 10:56:35 +02:00
use gimli::SectionId;
use crate::debuginfo::{DebugReloc, DebugRelocName};
pub(crate) trait WriteDebugInfo {
2020-04-25 18:23:31 +02:00
type SectionId: Copy;
fn add_debug_section(&mut self, name: SectionId, data: Vec<u8>) -> Self::SectionId;
fn add_debug_reloc(
&mut self,
2020-04-05 14:01:02 +02:00
section_map: &FxHashMap<SectionId, Self::SectionId>,
from: &Self::SectionId,
reloc: &DebugReloc,
);
}
impl WriteDebugInfo for ObjectProduct {
type SectionId = (object::write::SectionId, object::write::SymbolId);
fn add_debug_section(
&mut self,
id: SectionId,
data: Vec<u8>,
) -> (object::write::SectionId, object::write::SymbolId) {
2020-06-16 10:38:12 +02:00
let name = if self.object.format() == object::BinaryFormat::MachO {
id.name().replace('.', "__") // machO expects __debug_info instead of .debug_info
} else {
id.name().to_string()
}
.into_bytes();
let segment = self.object.segment_name(StandardSegment::Debug).to_vec();
// FIXME use SHT_X86_64_UNWIND for .eh_frame
let section_id = self.object.add_section(
segment,
2020-10-28 21:46:08 +01:00
name,
2021-03-05 11:21:44 +01:00
if id == SectionId::EhFrame { SectionKind::ReadOnlyData } else { SectionKind::Debug },
);
self.object
.section_mut(section_id)
.set_data(data, if id == SectionId::EhFrame { 8 } else { 1 });
let symbol_id = self.object.section_symbol(section_id);
(section_id, symbol_id)
}
fn add_debug_reloc(
&mut self,
2020-04-05 14:01:02 +02:00
section_map: &FxHashMap<SectionId, Self::SectionId>,
from: &Self::SectionId,
reloc: &DebugReloc,
) {
let (symbol, symbol_offset) = match reloc.name {
DebugRelocName::Section(id) => (section_map.get(&id).unwrap().1, 0),
DebugRelocName::Symbol(id) => {
2020-05-01 19:21:29 +02:00
let symbol_id = self.function_symbol(FuncId::from_u32(id.try_into().unwrap()));
self.object
.symbol_section_and_offset(symbol_id)
.expect("Debug reloc for undef sym???")
}
};
self.object
.add_relocation(
from.0,
Relocation {
offset: u64::from(reloc.offset),
symbol,
kind: reloc.kind,
encoding: RelocationEncoding::Generic,
size: reloc.size * 8,
addend: i64::try_from(symbol_offset).unwrap() + reloc.addend,
},
)
.unwrap();
}
}
2019-10-18 17:19:13 +02:00
pub(crate) fn make_module(sess: &Session, isa: Box<dyn TargetIsa>, name: String) -> ObjectModule {
2021-04-12 12:09:05 +02:00
let mut builder =
ObjectBuilder::new(isa, name + ".o", cranelift_module::default_libcall_names()).unwrap();
2020-10-31 10:13:35 +01:00
// Unlike cg_llvm, cg_clif defaults to disabling -Zfunction-sections. For cg_llvm binary size
// is important, while cg_clif cares more about compilation times. Enabling -Zfunction-sections
// can easily double the amount of time necessary to perform linking.
builder.per_function_section(sess.opts.debugging_opts.function_sections.unwrap_or(false));
2020-10-28 21:46:08 +01:00
ObjectModule::new(builder)
2019-10-18 17:19:13 +02:00
}