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}
;
13 use object
::{RelocationEncoding, SectionKind, SymbolFlags}
;
17 use crate::debuginfo
::{DebugReloc, DebugRelocName}
;
19 pub(crate) trait WriteMetadata
{
20 fn add_rustc_section(&mut self, symbol_name
: String
, data
: Vec
<u8>);
23 impl WriteMetadata
for object
::write
::Object
{
24 fn add_rustc_section(&mut self, symbol_name
: String
, data
: Vec
<u8>) {
25 let segment
= self.segment_name(object
::write
::StandardSegment
::Data
).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(),
33 size
: data
.len() as u64,
34 kind
: object
::SymbolKind
::Data
,
35 scope
: object
::SymbolScope
::Dynamic
,
37 section
: SymbolSection
::Section(section_id
),
38 flags
: SymbolFlags
::None
,
43 pub(crate) trait WriteDebugInfo
{
46 fn add_debug_section(&mut self, name
: SectionId
, data
: Vec
<u8>) -> Self::SectionId
;
49 section_map
: &FxHashMap
<SectionId
, Self::SectionId
>,
50 from
: &Self::SectionId
,
55 impl WriteDebugInfo
for ObjectProduct
{
56 type SectionId
= (object
::write
::SectionId
, object
::write
::SymbolId
);
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
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(
75 if id
== SectionId
::EhFrame { SectionKind::ReadOnlyData }
else { SectionKind::Debug }
,
78 .section_mut(section_id
)
79 .set_data(data
, if id
== SectionId
::EhFrame { 8 }
else { 1 }
);
80 let symbol_id
= self.object
.section_symbol(section_id
);
81 (section_id
, symbol_id
)
86 section_map
: &FxHashMap
<SectionId
, Self::SectionId
>,
87 from
: &Self::SectionId
,
90 let (symbol
, symbol_offset
) = match reloc
.name
{
91 DebugRelocName
::Section(id
) => (section_map
.get(&id
).unwrap().1, 0),
92 DebugRelocName
::Symbol(id
) => {
93 let symbol_id
= self.function_symbol(FuncId
::from_u32(id
.try_into().unwrap()));
95 .symbol_section_and_offset(symbol_id
)
96 .expect("Debug reloc for undef sym???")
103 offset
: u64::from(reloc
.offset
),
106 encoding
: RelocationEncoding
::Generic
,
107 size
: reloc
.size
* 8,
108 addend
: i64::try_from(symbol_offset
).unwrap() + reloc
.addend
,
115 pub(crate) fn with_object(sess
: &Session
, name
: &str, f
: impl FnOnce(&mut Object
)) -> Vec
<u8> {
116 let triple
= crate::target_triple(sess
);
118 let binary_format
= match triple
.binary_format
{
119 target_lexicon
::BinaryFormat
::Elf
=> object
::BinaryFormat
::Elf
,
120 target_lexicon
::BinaryFormat
::Coff
=> object
::BinaryFormat
::Coff
,
121 target_lexicon
::BinaryFormat
::Macho
=> object
::BinaryFormat
::MachO
,
122 binary_format
=> sess
.fatal(&format
!("binary format {} is unsupported", binary_format
)),
124 let architecture
= match triple
.architecture
{
125 target_lexicon
::Architecture
::X86_32(_
) => object
::Architecture
::I386
,
126 target_lexicon
::Architecture
::X86_64
=> object
::Architecture
::X86_64
,
127 target_lexicon
::Architecture
::Arm(_
) => object
::Architecture
::Arm
,
128 target_lexicon
::Architecture
::Aarch64(_
) => object
::Architecture
::Aarch64
,
130 sess
.fatal(&format
!("target architecture {:?} is unsupported", architecture
,))
133 let endian
= match triple
.endianness().unwrap() {
134 target_lexicon
::Endianness
::Little
=> object
::Endianness
::Little
,
135 target_lexicon
::Endianness
::Big
=> object
::Endianness
::Big
,
138 let mut metadata_object
= object
::write
::Object
::new(binary_format
, architecture
, endian
);
139 metadata_object
.add_file_symbol(name
.as_bytes().to_vec());
140 f(&mut metadata_object
);
141 metadata_object
.write().unwrap()
144 pub(crate) fn make_module(sess
: &Session
, isa
: Box
<dyn TargetIsa
>, name
: String
) -> ObjectModule
{
146 ObjectBuilder
::new(isa
, name
+ ".o", cranelift_module
::default_libcall_names()).unwrap();
147 // Unlike cg_llvm, cg_clif defaults to disabling -Zfunction-sections. For cg_llvm binary size
148 // is important, while cg_clif cares more about compilation times. Enabling -Zfunction-sections
149 // can easily double the amount of time necessary to perform linking.
150 builder
.per_function_section(sess
.opts
.debugging_opts
.function_sections
.unwrap_or(false));
151 ObjectModule
::new(builder
)