2020-09-23 13:13:49 +00:00
|
|
|
//! Abstraction around the object writing crate
|
|
|
|
|
2020-05-01 17:21:29 +00:00
|
|
|
use std::convert::{TryFrom, TryInto};
|
2019-10-16 19:21:20 +00:00
|
|
|
|
2020-04-05 12:01:02 +00:00
|
|
|
use rustc_data_structures::fx::FxHashMap;
|
2020-03-24 12:09:44 +00:00
|
|
|
use rustc_session::Session;
|
2019-10-18 15:19:13 +00:00
|
|
|
|
2021-04-07 09:52:11 +00:00
|
|
|
use cranelift_codegen::isa::TargetIsa;
|
2020-10-01 08:38:23 +00:00
|
|
|
use cranelift_module::FuncId;
|
2021-04-07 09:52:11 +00:00
|
|
|
use cranelift_object::{ObjectBuilder, ObjectModule, ObjectProduct};
|
2019-10-16 19:21:20 +00:00
|
|
|
|
|
|
|
use object::write::*;
|
2021-02-09 13:36:25 +00:00
|
|
|
use object::{RelocationEncoding, SectionKind, SymbolFlags};
|
2019-10-19 08:56:35 +00:00
|
|
|
|
2019-10-16 19:21:20 +00:00
|
|
|
use gimli::SectionId;
|
|
|
|
|
|
|
|
use crate::debuginfo::{DebugReloc, DebugRelocName};
|
|
|
|
|
2020-03-27 11:14:45 +00:00
|
|
|
pub(crate) trait WriteMetadata {
|
2021-04-30 08:52:37 +00:00
|
|
|
fn add_rustc_section(&mut self, symbol_name: String, data: Vec<u8>);
|
2019-10-16 18:48:09 +00:00
|
|
|
}
|
|
|
|
|
2019-10-16 19:21:20 +00:00
|
|
|
impl WriteMetadata for object::write::Object {
|
2021-04-30 08:52:37 +00:00
|
|
|
fn add_rustc_section(&mut self, symbol_name: String, data: Vec<u8>) {
|
2021-03-05 10:21:44 +00:00
|
|
|
let segment = self.segment_name(object::write::StandardSegment::Data).to_vec();
|
2019-10-16 18:48:09 +00:00
|
|
|
let section_id = self.add_section(segment, b".rustc".to_vec(), object::SectionKind::Data);
|
|
|
|
let offset = self.append_section_data(section_id, &data, 1);
|
2019-10-19 08:52:56 +00:00
|
|
|
// For MachO and probably PE this is necessary to prevent the linker from throwing away the
|
|
|
|
// .rustc section. For ELF this isn't necessary, but it also doesn't harm.
|
|
|
|
self.add_symbol(object::write::Symbol {
|
|
|
|
name: symbol_name.into_bytes(),
|
|
|
|
value: offset,
|
|
|
|
size: data.len() as u64,
|
|
|
|
kind: object::SymbolKind::Data,
|
2019-10-19 09:08:16 +00:00
|
|
|
scope: object::SymbolScope::Dynamic,
|
2019-10-19 08:52:56 +00:00
|
|
|
weak: false,
|
2020-01-10 12:12:49 +00:00
|
|
|
section: SymbolSection::Section(section_id),
|
|
|
|
flags: SymbolFlags::None,
|
2019-10-19 08:52:56 +00:00
|
|
|
});
|
2019-10-16 18:48:09 +00:00
|
|
|
}
|
|
|
|
}
|
2019-10-16 19:21:20 +00:00
|
|
|
|
2020-03-27 11:14:45 +00:00
|
|
|
pub(crate) trait WriteDebugInfo {
|
2020-04-25 16:23:31 +00:00
|
|
|
type SectionId: Copy;
|
2019-10-16 19:21:20 +00:00
|
|
|
|
|
|
|
fn add_debug_section(&mut self, name: SectionId, data: Vec<u8>) -> Self::SectionId;
|
|
|
|
fn add_debug_reloc(
|
|
|
|
&mut self,
|
2020-04-05 12:01:02 +00:00
|
|
|
section_map: &FxHashMap<SectionId, Self::SectionId>,
|
2019-10-16 19:21:20 +00:00
|
|
|
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 08:38:12 +00:00
|
|
|
let name = if self.object.format() == object::BinaryFormat::MachO {
|
2019-10-19 13:37:07 +00:00
|
|
|
id.name().replace('.', "__") // machO expects __debug_info instead of .debug_info
|
|
|
|
} else {
|
|
|
|
id.name().to_string()
|
2020-08-28 10:10:48 +00:00
|
|
|
}
|
|
|
|
.into_bytes();
|
2019-10-19 13:37:07 +00:00
|
|
|
|
2019-10-16 19:21:20 +00:00
|
|
|
let segment = self.object.segment_name(StandardSegment::Debug).to_vec();
|
2020-09-23 08:00:09 +00:00
|
|
|
// FIXME use SHT_X86_64_UNWIND for .eh_frame
|
2020-10-01 08:38:23 +00:00
|
|
|
let section_id = self.object.add_section(
|
|
|
|
segment,
|
2020-10-28 20:46:08 +00:00
|
|
|
name,
|
2021-03-05 10:21:44 +00:00
|
|
|
if id == SectionId::EhFrame { SectionKind::ReadOnlyData } else { SectionKind::Debug },
|
2020-10-01 08:38:23 +00:00
|
|
|
);
|
|
|
|
self.object
|
|
|
|
.section_mut(section_id)
|
|
|
|
.set_data(data, if id == SectionId::EhFrame { 8 } else { 1 });
|
2019-10-16 19:21:20 +00:00
|
|
|
let symbol_id = self.object.section_symbol(section_id);
|
|
|
|
(section_id, symbol_id)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn add_debug_reloc(
|
|
|
|
&mut self,
|
2020-04-05 12:01:02 +00:00
|
|
|
section_map: &FxHashMap<SectionId, Self::SectionId>,
|
2019-10-16 19:21:20 +00:00
|
|
|
from: &Self::SectionId,
|
|
|
|
reloc: &DebugReloc,
|
|
|
|
) {
|
2019-10-19 13:37:07 +00:00
|
|
|
let (symbol, symbol_offset) = match reloc.name {
|
2020-08-28 10:10:48 +00:00
|
|
|
DebugRelocName::Section(id) => (section_map.get(&id).unwrap().1, 0),
|
2019-10-16 19:21:20 +00:00
|
|
|
DebugRelocName::Symbol(id) => {
|
2020-05-01 17:21:29 +00:00
|
|
|
let symbol_id = self.function_symbol(FuncId::from_u32(id.try_into().unwrap()));
|
2020-08-28 10:10:48 +00:00
|
|
|
self.object
|
|
|
|
.symbol_section_and_offset(symbol_id)
|
|
|
|
.expect("Debug reloc for undef sym???")
|
2019-10-16 19:21:20 +00:00
|
|
|
}
|
|
|
|
};
|
2020-08-28 10:10:48 +00:00
|
|
|
self.object
|
|
|
|
.add_relocation(
|
|
|
|
from.0,
|
|
|
|
Relocation {
|
|
|
|
offset: u64::from(reloc.offset),
|
|
|
|
symbol,
|
2020-09-23 08:00:09 +00:00
|
|
|
kind: reloc.kind,
|
2020-08-28 10:10:48 +00:00
|
|
|
encoding: RelocationEncoding::Generic,
|
|
|
|
size: reloc.size * 8,
|
|
|
|
addend: i64::try_from(symbol_offset).unwrap() + reloc.addend,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
.unwrap();
|
2019-10-16 19:21:20 +00:00
|
|
|
}
|
|
|
|
}
|
2019-10-18 15:19:13 +00:00
|
|
|
|
2020-03-27 11:14:45 +00:00
|
|
|
pub(crate) fn with_object(sess: &Session, name: &str, f: impl FnOnce(&mut Object)) -> Vec<u8> {
|
2021-04-07 09:52:11 +00:00
|
|
|
let triple = crate::target_triple(sess);
|
2020-06-16 08:38:12 +00:00
|
|
|
|
|
|
|
let binary_format = match triple.binary_format {
|
|
|
|
target_lexicon::BinaryFormat::Elf => object::BinaryFormat::Elf,
|
|
|
|
target_lexicon::BinaryFormat::Coff => object::BinaryFormat::Coff,
|
|
|
|
target_lexicon::BinaryFormat::Macho => object::BinaryFormat::MachO,
|
2020-09-21 17:23:39 +00:00
|
|
|
binary_format => sess.fatal(&format!("binary format {} is unsupported", binary_format)),
|
2020-06-16 08:38:12 +00:00
|
|
|
};
|
|
|
|
let architecture = match triple.architecture {
|
2020-09-21 17:23:39 +00:00
|
|
|
target_lexicon::Architecture::X86_32(_) => object::Architecture::I386,
|
2020-06-16 08:38:12 +00:00
|
|
|
target_lexicon::Architecture::X86_64 => object::Architecture::X86_64,
|
|
|
|
target_lexicon::Architecture::Arm(_) => object::Architecture::Arm,
|
|
|
|
target_lexicon::Architecture::Aarch64(_) => object::Architecture::Aarch64,
|
2021-03-05 10:21:44 +00:00
|
|
|
architecture => {
|
|
|
|
sess.fatal(&format!("target architecture {:?} is unsupported", architecture,))
|
|
|
|
}
|
2020-06-16 08:38:12 +00:00
|
|
|
};
|
|
|
|
let endian = match triple.endianness().unwrap() {
|
|
|
|
target_lexicon::Endianness::Little => object::Endianness::Little,
|
|
|
|
target_lexicon::Endianness::Big => object::Endianness::Big,
|
|
|
|
};
|
|
|
|
|
|
|
|
let mut metadata_object = object::write::Object::new(binary_format, architecture, endian);
|
2019-10-18 15:19:13 +00:00
|
|
|
metadata_object.add_file_symbol(name.as_bytes().to_vec());
|
|
|
|
f(&mut metadata_object);
|
|
|
|
metadata_object.write().unwrap()
|
|
|
|
}
|
|
|
|
|
2021-04-07 09:52:11 +00:00
|
|
|
pub(crate) fn make_module(sess: &Session, isa: Box<dyn TargetIsa>, name: String) -> ObjectModule {
|
2021-04-12 10:09:05 +00:00
|
|
|
let mut builder =
|
|
|
|
ObjectBuilder::new(isa, name + ".o", cranelift_module::default_libcall_names()).unwrap();
|
2020-10-31 09:13:35 +00: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 20:46:08 +00:00
|
|
|
ObjectModule::new(builder)
|
2019-10-18 15:19:13 +00:00
|
|
|
}
|