Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/cranelift/object/src/backend.rs
3068 views
1
//! Defines `ObjectModule`.
2
3
use anyhow::anyhow;
4
use cranelift_codegen::binemit::{Addend, CodeOffset, Reloc};
5
use cranelift_codegen::entity::SecondaryMap;
6
use cranelift_codegen::ir;
7
use cranelift_codegen::isa::{OwnedTargetIsa, TargetIsa};
8
use cranelift_control::ControlPlane;
9
use cranelift_module::{
10
DataDescription, DataId, FuncId, Init, Linkage, Module, ModuleDeclarations, ModuleError,
11
ModuleReloc, ModuleRelocTarget, ModuleResult,
12
};
13
use log::info;
14
use object::write::{
15
Object, Relocation, SectionId, StandardSection, Symbol, SymbolId, SymbolSection,
16
};
17
use object::{
18
RelocationEncoding, RelocationFlags, RelocationKind, SectionFlags, SectionKind, SymbolFlags,
19
SymbolKind, SymbolScope, elf,
20
};
21
use std::collections::HashMap;
22
use std::collections::hash_map::Entry;
23
use std::mem;
24
use target_lexicon::PointerWidth;
25
26
/// A builder for `ObjectModule`.
27
pub struct ObjectBuilder {
28
isa: OwnedTargetIsa,
29
binary_format: object::BinaryFormat,
30
architecture: object::Architecture,
31
flags: object::FileFlags,
32
endian: object::Endianness,
33
name: Vec<u8>,
34
libcall_names: Box<dyn Fn(ir::LibCall) -> String + Send + Sync>,
35
per_function_section: bool,
36
per_data_object_section: bool,
37
}
38
39
impl ObjectBuilder {
40
/// Create a new `ObjectBuilder` using the given Cranelift target, that
41
/// can be passed to [`ObjectModule::new`].
42
///
43
/// The `libcall_names` function provides a way to translate `cranelift_codegen`'s [`ir::LibCall`]
44
/// enum to symbols. LibCalls are inserted in the IR as part of the legalization for certain
45
/// floating point instructions, and for stack probes. If you don't know what to use for this
46
/// argument, use [`cranelift_module::default_libcall_names`].
47
pub fn new<V: Into<Vec<u8>>>(
48
isa: OwnedTargetIsa,
49
name: V,
50
libcall_names: Box<dyn Fn(ir::LibCall) -> String + Send + Sync>,
51
) -> ModuleResult<Self> {
52
let mut file_flags = object::FileFlags::None;
53
let binary_format = match isa.triple().binary_format {
54
target_lexicon::BinaryFormat::Elf => object::BinaryFormat::Elf,
55
target_lexicon::BinaryFormat::Coff => object::BinaryFormat::Coff,
56
target_lexicon::BinaryFormat::Macho => object::BinaryFormat::MachO,
57
target_lexicon::BinaryFormat::Wasm => {
58
return Err(ModuleError::Backend(anyhow!(
59
"binary format wasm is unsupported",
60
)));
61
}
62
target_lexicon::BinaryFormat::Unknown => {
63
return Err(ModuleError::Backend(anyhow!("binary format is unknown")));
64
}
65
other => {
66
return Err(ModuleError::Backend(anyhow!(
67
"binary format {other} not recognized"
68
)));
69
}
70
};
71
let architecture = match isa.triple().architecture {
72
target_lexicon::Architecture::X86_32(_) => object::Architecture::I386,
73
target_lexicon::Architecture::X86_64 => object::Architecture::X86_64,
74
target_lexicon::Architecture::Arm(_) => object::Architecture::Arm,
75
target_lexicon::Architecture::Aarch64(_) => object::Architecture::Aarch64,
76
target_lexicon::Architecture::Riscv64(_) => {
77
if binary_format != object::BinaryFormat::Elf {
78
return Err(ModuleError::Backend(anyhow!(
79
"binary format {binary_format:?} is not supported for riscv64",
80
)));
81
}
82
83
// FIXME(#4994): Get the right float ABI variant from the TargetIsa
84
let mut eflags = object::elf::EF_RISCV_FLOAT_ABI_DOUBLE;
85
86
// Set the RVC eflag if we have the C extension enabled.
87
let has_c = isa
88
.isa_flags()
89
.iter()
90
.filter(|f| f.name == "has_zca" || f.name == "has_zcd")
91
.all(|f| f.as_bool().unwrap_or_default());
92
if has_c {
93
eflags |= object::elf::EF_RISCV_RVC;
94
}
95
96
file_flags = object::FileFlags::Elf {
97
os_abi: object::elf::ELFOSABI_NONE,
98
abi_version: 0,
99
e_flags: eflags,
100
};
101
object::Architecture::Riscv64
102
}
103
target_lexicon::Architecture::S390x => object::Architecture::S390x,
104
architecture => {
105
return Err(ModuleError::Backend(anyhow!(
106
"target architecture {architecture:?} is unsupported",
107
)));
108
}
109
};
110
let endian = match isa.triple().endianness().unwrap() {
111
target_lexicon::Endianness::Little => object::Endianness::Little,
112
target_lexicon::Endianness::Big => object::Endianness::Big,
113
};
114
Ok(Self {
115
isa,
116
binary_format,
117
architecture,
118
flags: file_flags,
119
endian,
120
name: name.into(),
121
libcall_names,
122
per_function_section: false,
123
per_data_object_section: false,
124
})
125
}
126
127
/// Set if every function should end up in their own section.
128
pub fn per_function_section(&mut self, per_function_section: bool) -> &mut Self {
129
self.per_function_section = per_function_section;
130
self
131
}
132
133
/// Set if every data object should end up in their own section.
134
pub fn per_data_object_section(&mut self, per_data_object_section: bool) -> &mut Self {
135
self.per_data_object_section = per_data_object_section;
136
self
137
}
138
}
139
140
/// An `ObjectModule` implements `Module` and emits ".o" files using the `object` library.
141
///
142
/// See the `ObjectBuilder` for a convenient way to construct `ObjectModule` instances.
143
pub struct ObjectModule {
144
isa: OwnedTargetIsa,
145
object: Object<'static>,
146
declarations: ModuleDeclarations,
147
functions: SecondaryMap<FuncId, Option<(SymbolId, bool)>>,
148
data_objects: SecondaryMap<DataId, Option<(SymbolId, bool)>>,
149
relocs: Vec<SymbolRelocs>,
150
libcalls: HashMap<ir::LibCall, SymbolId>,
151
libcall_names: Box<dyn Fn(ir::LibCall) -> String + Send + Sync>,
152
known_symbols: HashMap<ir::KnownSymbol, SymbolId>,
153
known_labels: HashMap<(FuncId, CodeOffset), SymbolId>,
154
per_function_section: bool,
155
per_data_object_section: bool,
156
}
157
158
impl ObjectModule {
159
/// Create a new `ObjectModule` using the given Cranelift target.
160
pub fn new(builder: ObjectBuilder) -> Self {
161
let mut object = Object::new(builder.binary_format, builder.architecture, builder.endian);
162
object.flags = builder.flags;
163
object.set_subsections_via_symbols();
164
object.add_file_symbol(builder.name);
165
Self {
166
isa: builder.isa,
167
object,
168
declarations: ModuleDeclarations::default(),
169
functions: SecondaryMap::new(),
170
data_objects: SecondaryMap::new(),
171
relocs: Vec::new(),
172
libcalls: HashMap::new(),
173
libcall_names: builder.libcall_names,
174
known_symbols: HashMap::new(),
175
known_labels: HashMap::new(),
176
per_function_section: builder.per_function_section,
177
per_data_object_section: builder.per_data_object_section,
178
}
179
}
180
}
181
182
fn validate_symbol(name: &str) -> ModuleResult<()> {
183
// null bytes are not allowed in symbol names and will cause the `object`
184
// crate to panic. Let's return a clean error instead.
185
if name.contains("\0") {
186
return Err(ModuleError::Backend(anyhow::anyhow!(
187
"Symbol {name:?} has a null byte, which is disallowed"
188
)));
189
}
190
Ok(())
191
}
192
193
impl Module for ObjectModule {
194
fn isa(&self) -> &dyn TargetIsa {
195
&*self.isa
196
}
197
198
fn declarations(&self) -> &ModuleDeclarations {
199
&self.declarations
200
}
201
202
fn declare_function(
203
&mut self,
204
name: &str,
205
linkage: Linkage,
206
signature: &ir::Signature,
207
) -> ModuleResult<FuncId> {
208
validate_symbol(name)?;
209
210
let (id, linkage) = self
211
.declarations
212
.declare_function(name, linkage, signature)?;
213
214
let (scope, weak) = translate_linkage(linkage);
215
216
if let Some((function, _defined)) = self.functions[id] {
217
let symbol = self.object.symbol_mut(function);
218
symbol.scope = scope;
219
symbol.weak = weak;
220
} else {
221
let symbol_id = self.object.add_symbol(Symbol {
222
name: name.as_bytes().to_vec(),
223
value: 0,
224
size: 0,
225
kind: SymbolKind::Text,
226
scope,
227
weak,
228
section: SymbolSection::Undefined,
229
flags: SymbolFlags::None,
230
});
231
self.functions[id] = Some((symbol_id, false));
232
}
233
234
Ok(id)
235
}
236
237
fn declare_anonymous_function(&mut self, signature: &ir::Signature) -> ModuleResult<FuncId> {
238
let id = self.declarations.declare_anonymous_function(signature)?;
239
240
let symbol_id = self.object.add_symbol(Symbol {
241
name: self
242
.declarations
243
.get_function_decl(id)
244
.linkage_name(id)
245
.into_owned()
246
.into_bytes(),
247
value: 0,
248
size: 0,
249
kind: SymbolKind::Text,
250
scope: SymbolScope::Compilation,
251
weak: false,
252
section: SymbolSection::Undefined,
253
flags: SymbolFlags::None,
254
});
255
self.functions[id] = Some((symbol_id, false));
256
257
Ok(id)
258
}
259
260
fn declare_data(
261
&mut self,
262
name: &str,
263
linkage: Linkage,
264
writable: bool,
265
tls: bool,
266
) -> ModuleResult<DataId> {
267
validate_symbol(name)?;
268
269
let (id, linkage) = self
270
.declarations
271
.declare_data(name, linkage, writable, tls)?;
272
273
// Merging declarations with conflicting values for tls is not allowed, so it is safe to use
274
// the passed in tls value here.
275
let kind = if tls {
276
SymbolKind::Tls
277
} else {
278
SymbolKind::Data
279
};
280
let (scope, weak) = translate_linkage(linkage);
281
282
if let Some((data, _defined)) = self.data_objects[id] {
283
let symbol = self.object.symbol_mut(data);
284
symbol.kind = kind;
285
symbol.scope = scope;
286
symbol.weak = weak;
287
} else {
288
let symbol_id = self.object.add_symbol(Symbol {
289
name: name.as_bytes().to_vec(),
290
value: 0,
291
size: 0,
292
kind,
293
scope,
294
weak,
295
section: SymbolSection::Undefined,
296
flags: SymbolFlags::None,
297
});
298
self.data_objects[id] = Some((symbol_id, false));
299
}
300
301
Ok(id)
302
}
303
304
fn declare_anonymous_data(&mut self, writable: bool, tls: bool) -> ModuleResult<DataId> {
305
let id = self.declarations.declare_anonymous_data(writable, tls)?;
306
307
let kind = if tls {
308
SymbolKind::Tls
309
} else {
310
SymbolKind::Data
311
};
312
313
let symbol_id = self.object.add_symbol(Symbol {
314
name: self
315
.declarations
316
.get_data_decl(id)
317
.linkage_name(id)
318
.into_owned()
319
.into_bytes(),
320
value: 0,
321
size: 0,
322
kind,
323
scope: SymbolScope::Compilation,
324
weak: false,
325
section: SymbolSection::Undefined,
326
flags: SymbolFlags::None,
327
});
328
self.data_objects[id] = Some((symbol_id, false));
329
330
Ok(id)
331
}
332
333
fn define_function_with_control_plane(
334
&mut self,
335
func_id: FuncId,
336
ctx: &mut cranelift_codegen::Context,
337
ctrl_plane: &mut ControlPlane,
338
) -> ModuleResult<()> {
339
info!("defining function {}: {}", func_id, ctx.func.display());
340
341
let res = ctx.compile(self.isa(), ctrl_plane)?;
342
let alignment = res.buffer.alignment as u64;
343
344
let buffer = &ctx.compiled_code().unwrap().buffer;
345
let relocs = buffer
346
.relocs()
347
.iter()
348
.map(|reloc| {
349
self.process_reloc(&ModuleReloc::from_mach_reloc(&reloc, &ctx.func, func_id))
350
})
351
.collect::<Vec<_>>();
352
self.define_function_inner(func_id, alignment, buffer.data(), relocs)
353
}
354
355
fn define_function_bytes(
356
&mut self,
357
func_id: FuncId,
358
alignment: u64,
359
bytes: &[u8],
360
relocs: &[ModuleReloc],
361
) -> ModuleResult<()> {
362
let relocs = relocs
363
.iter()
364
.map(|reloc| self.process_reloc(reloc))
365
.collect();
366
self.define_function_inner(func_id, alignment, bytes, relocs)
367
}
368
369
fn define_data(&mut self, data_id: DataId, data: &DataDescription) -> ModuleResult<()> {
370
let decl = self.declarations.get_data_decl(data_id);
371
if !decl.linkage.is_definable() {
372
return Err(ModuleError::InvalidImportDefinition(
373
decl.linkage_name(data_id).into_owned(),
374
));
375
}
376
377
let &mut (symbol, ref mut defined) = self.data_objects[data_id].as_mut().unwrap();
378
if *defined {
379
return Err(ModuleError::DuplicateDefinition(
380
decl.linkage_name(data_id).into_owned(),
381
));
382
}
383
*defined = true;
384
385
let &DataDescription {
386
ref init,
387
function_decls: _,
388
data_decls: _,
389
function_relocs: _,
390
data_relocs: _,
391
ref custom_segment_section,
392
align,
393
used,
394
} = data;
395
396
let pointer_reloc = match self.isa.triple().pointer_width().unwrap() {
397
PointerWidth::U16 => unimplemented!("16bit pointers"),
398
PointerWidth::U32 => Reloc::Abs4,
399
PointerWidth::U64 => Reloc::Abs8,
400
};
401
let relocs = data
402
.all_relocs(pointer_reloc)
403
.map(|record| self.process_reloc(&record))
404
.collect::<Vec<_>>();
405
406
let section = if custom_segment_section.is_none() {
407
let section_kind = if let Init::Zeros { .. } = *init {
408
if decl.tls {
409
StandardSection::UninitializedTls
410
} else {
411
StandardSection::UninitializedData
412
}
413
} else if decl.tls {
414
StandardSection::Tls
415
} else if decl.writable {
416
StandardSection::Data
417
} else if relocs.is_empty() {
418
StandardSection::ReadOnlyData
419
} else {
420
StandardSection::ReadOnlyDataWithRel
421
};
422
if self.per_data_object_section || used {
423
// FIXME pass empty symbol name once add_subsection produces `.text` as section name
424
// instead of `.text.` when passed an empty symbol name. (object#748) Until then
425
// pass `subsection` to produce `.text.subsection` as section name to reduce
426
// confusion.
427
self.object.add_subsection(section_kind, b"subsection")
428
} else {
429
self.object.section_id(section_kind)
430
}
431
} else {
432
if decl.tls {
433
return Err(cranelift_module::ModuleError::Backend(anyhow::anyhow!(
434
"Custom section not supported for TLS"
435
)));
436
}
437
let (seg, sec) = &custom_segment_section.as_ref().unwrap();
438
self.object.add_section(
439
seg.clone().into_bytes(),
440
sec.clone().into_bytes(),
441
if decl.writable {
442
SectionKind::Data
443
} else if relocs.is_empty() {
444
SectionKind::ReadOnlyData
445
} else {
446
SectionKind::ReadOnlyDataWithRel
447
},
448
)
449
};
450
451
if used {
452
match self.object.format() {
453
object::BinaryFormat::Elf => match self.object.section_flags_mut(section) {
454
SectionFlags::Elf { sh_flags } => *sh_flags |= u64::from(elf::SHF_GNU_RETAIN),
455
_ => unreachable!(),
456
},
457
object::BinaryFormat::Coff => {}
458
object::BinaryFormat::MachO => match self.object.symbol_flags_mut(symbol) {
459
SymbolFlags::MachO { n_desc } => *n_desc |= object::macho::N_NO_DEAD_STRIP,
460
_ => unreachable!(),
461
},
462
_ => unreachable!(),
463
}
464
}
465
466
let align = std::cmp::max(align.unwrap_or(1), self.isa.symbol_alignment());
467
let offset = match *init {
468
Init::Uninitialized => {
469
panic!("data is not initialized yet");
470
}
471
Init::Zeros { size } => self
472
.object
473
.add_symbol_bss(symbol, section, size as u64, align),
474
Init::Bytes { ref contents } => self
475
.object
476
.add_symbol_data(symbol, section, &contents, align),
477
};
478
if !relocs.is_empty() {
479
self.relocs.push(SymbolRelocs {
480
section,
481
offset,
482
relocs,
483
});
484
}
485
Ok(())
486
}
487
}
488
489
impl ObjectModule {
490
fn define_function_inner(
491
&mut self,
492
func_id: FuncId,
493
alignment: u64,
494
bytes: &[u8],
495
relocs: Vec<ObjectRelocRecord>,
496
) -> Result<(), ModuleError> {
497
info!("defining function {func_id} with bytes");
498
let decl = self.declarations.get_function_decl(func_id);
499
let decl_name = decl.linkage_name(func_id);
500
if !decl.linkage.is_definable() {
501
return Err(ModuleError::InvalidImportDefinition(decl_name.into_owned()));
502
}
503
504
let &mut (symbol, ref mut defined) = self.functions[func_id].as_mut().unwrap();
505
if *defined {
506
return Err(ModuleError::DuplicateDefinition(decl_name.into_owned()));
507
}
508
*defined = true;
509
510
let align = alignment.max(self.isa.symbol_alignment());
511
let section = if self.per_function_section {
512
// FIXME pass empty symbol name once add_subsection produces `.text` as section name
513
// instead of `.text.` when passed an empty symbol name. (object#748) Until then pass
514
// `subsection` to produce `.text.subsection` as section name to reduce confusion.
515
self.object
516
.add_subsection(StandardSection::Text, b"subsection")
517
} else {
518
self.object.section_id(StandardSection::Text)
519
};
520
let offset = self.object.add_symbol_data(symbol, section, bytes, align);
521
522
if !relocs.is_empty() {
523
self.relocs.push(SymbolRelocs {
524
section,
525
offset,
526
relocs,
527
});
528
}
529
530
Ok(())
531
}
532
533
/// Finalize all relocations and output an object.
534
pub fn finish(mut self) -> ObjectProduct {
535
if cfg!(debug_assertions) {
536
for (func_id, decl) in self.declarations.get_functions() {
537
if !decl.linkage.requires_definition() {
538
continue;
539
}
540
541
assert!(
542
self.functions[func_id].unwrap().1,
543
"function \"{}\" with linkage {:?} must be defined but is not",
544
decl.linkage_name(func_id),
545
decl.linkage,
546
);
547
}
548
549
for (data_id, decl) in self.declarations.get_data_objects() {
550
if !decl.linkage.requires_definition() {
551
continue;
552
}
553
554
assert!(
555
self.data_objects[data_id].unwrap().1,
556
"data object \"{}\" with linkage {:?} must be defined but is not",
557
decl.linkage_name(data_id),
558
decl.linkage,
559
);
560
}
561
}
562
563
let symbol_relocs = mem::take(&mut self.relocs);
564
for symbol in symbol_relocs {
565
for &ObjectRelocRecord {
566
offset,
567
ref name,
568
flags,
569
addend,
570
} in &symbol.relocs
571
{
572
let target_symbol = self.get_symbol(name);
573
self.object
574
.add_relocation(
575
symbol.section,
576
Relocation {
577
offset: symbol.offset + u64::from(offset),
578
flags,
579
symbol: target_symbol,
580
addend,
581
},
582
)
583
.unwrap();
584
}
585
}
586
587
// Indicate that this object has a non-executable stack.
588
if self.object.format() == object::BinaryFormat::Elf {
589
self.object.add_section(
590
vec![],
591
".note.GNU-stack".as_bytes().to_vec(),
592
SectionKind::Linker,
593
);
594
}
595
596
ObjectProduct {
597
object: self.object,
598
functions: self.functions,
599
data_objects: self.data_objects,
600
}
601
}
602
603
/// This should only be called during finish because it creates
604
/// symbols for missing libcalls.
605
fn get_symbol(&mut self, name: &ModuleRelocTarget) -> SymbolId {
606
match *name {
607
ModuleRelocTarget::User { .. } => {
608
if ModuleDeclarations::is_function(name) {
609
let id = FuncId::from_name(name);
610
self.functions[id].unwrap().0
611
} else {
612
let id = DataId::from_name(name);
613
self.data_objects[id].unwrap().0
614
}
615
}
616
ModuleRelocTarget::LibCall(ref libcall) => {
617
let name = (self.libcall_names)(*libcall);
618
if let Some(symbol) = self.object.symbol_id(name.as_bytes()) {
619
symbol
620
} else if let Some(symbol) = self.libcalls.get(libcall) {
621
*symbol
622
} else {
623
let symbol = self.object.add_symbol(Symbol {
624
name: name.as_bytes().to_vec(),
625
value: 0,
626
size: 0,
627
kind: SymbolKind::Text,
628
scope: SymbolScope::Unknown,
629
weak: false,
630
section: SymbolSection::Undefined,
631
flags: SymbolFlags::None,
632
});
633
self.libcalls.insert(*libcall, symbol);
634
symbol
635
}
636
}
637
// These are "magic" names well-known to the linker.
638
// They require special treatment.
639
ModuleRelocTarget::KnownSymbol(ref known_symbol) => {
640
if let Some(symbol) = self.known_symbols.get(known_symbol) {
641
*symbol
642
} else {
643
let symbol = self.object.add_symbol(match known_symbol {
644
ir::KnownSymbol::ElfGlobalOffsetTable => Symbol {
645
name: b"_GLOBAL_OFFSET_TABLE_".to_vec(),
646
value: 0,
647
size: 0,
648
kind: SymbolKind::Data,
649
scope: SymbolScope::Unknown,
650
weak: false,
651
section: SymbolSection::Undefined,
652
flags: SymbolFlags::None,
653
},
654
ir::KnownSymbol::CoffTlsIndex => Symbol {
655
name: b"_tls_index".to_vec(),
656
value: 0,
657
size: 32,
658
kind: SymbolKind::Tls,
659
scope: SymbolScope::Unknown,
660
weak: false,
661
section: SymbolSection::Undefined,
662
flags: SymbolFlags::None,
663
},
664
});
665
self.known_symbols.insert(*known_symbol, symbol);
666
symbol
667
}
668
}
669
670
ModuleRelocTarget::FunctionOffset(func_id, offset) => {
671
match self.known_labels.entry((func_id, offset)) {
672
Entry::Occupied(o) => *o.get(),
673
Entry::Vacant(v) => {
674
let func_symbol_id = self.functions[func_id].unwrap().0;
675
let func_symbol = self.object.symbol(func_symbol_id);
676
677
let name = format!(".L{}_{}", func_id.as_u32(), offset);
678
let symbol_id = self.object.add_symbol(Symbol {
679
name: name.as_bytes().to_vec(),
680
value: func_symbol.value + offset as u64,
681
size: 0,
682
kind: SymbolKind::Label,
683
scope: SymbolScope::Compilation,
684
weak: false,
685
section: SymbolSection::Section(func_symbol.section.id().unwrap()),
686
flags: SymbolFlags::None,
687
});
688
689
v.insert(symbol_id);
690
symbol_id
691
}
692
}
693
}
694
}
695
}
696
697
fn process_reloc(&self, record: &ModuleReloc) -> ObjectRelocRecord {
698
let flags = match record.kind {
699
Reloc::Abs4 => RelocationFlags::Generic {
700
kind: RelocationKind::Absolute,
701
encoding: RelocationEncoding::Generic,
702
size: 32,
703
},
704
Reloc::Abs8 => RelocationFlags::Generic {
705
kind: RelocationKind::Absolute,
706
encoding: RelocationEncoding::Generic,
707
size: 64,
708
},
709
Reloc::X86PCRel4 => RelocationFlags::Generic {
710
kind: RelocationKind::Relative,
711
encoding: RelocationEncoding::Generic,
712
size: 32,
713
},
714
Reloc::X86CallPCRel4 => RelocationFlags::Generic {
715
kind: RelocationKind::Relative,
716
encoding: RelocationEncoding::X86Branch,
717
size: 32,
718
},
719
// TODO: Get Cranelift to tell us when we can use
720
// R_X86_64_GOTPCRELX/R_X86_64_REX_GOTPCRELX.
721
Reloc::X86CallPLTRel4 => RelocationFlags::Generic {
722
kind: RelocationKind::PltRelative,
723
encoding: RelocationEncoding::X86Branch,
724
size: 32,
725
},
726
Reloc::X86SecRel => RelocationFlags::Generic {
727
kind: RelocationKind::SectionOffset,
728
encoding: RelocationEncoding::Generic,
729
size: 32,
730
},
731
Reloc::X86GOTPCRel4 => RelocationFlags::Generic {
732
kind: RelocationKind::GotRelative,
733
encoding: RelocationEncoding::Generic,
734
size: 32,
735
},
736
Reloc::Arm64Call => RelocationFlags::Generic {
737
kind: RelocationKind::Relative,
738
encoding: RelocationEncoding::AArch64Call,
739
size: 26,
740
},
741
Reloc::ElfX86_64TlsGd => {
742
assert_eq!(
743
self.object.format(),
744
object::BinaryFormat::Elf,
745
"ElfX86_64TlsGd is not supported for this file format"
746
);
747
RelocationFlags::Elf {
748
r_type: object::elf::R_X86_64_TLSGD,
749
}
750
}
751
Reloc::MachOX86_64Tlv => {
752
assert_eq!(
753
self.object.format(),
754
object::BinaryFormat::MachO,
755
"MachOX86_64Tlv is not supported for this file format"
756
);
757
RelocationFlags::MachO {
758
r_type: object::macho::X86_64_RELOC_TLV,
759
r_pcrel: true,
760
r_length: 2,
761
}
762
}
763
Reloc::MachOAarch64TlsAdrPage21 => {
764
assert_eq!(
765
self.object.format(),
766
object::BinaryFormat::MachO,
767
"MachOAarch64TlsAdrPage21 is not supported for this file format"
768
);
769
RelocationFlags::MachO {
770
r_type: object::macho::ARM64_RELOC_TLVP_LOAD_PAGE21,
771
r_pcrel: true,
772
r_length: 2,
773
}
774
}
775
Reloc::MachOAarch64TlsAdrPageOff12 => {
776
assert_eq!(
777
self.object.format(),
778
object::BinaryFormat::MachO,
779
"MachOAarch64TlsAdrPageOff12 is not supported for this file format"
780
);
781
RelocationFlags::MachO {
782
r_type: object::macho::ARM64_RELOC_TLVP_LOAD_PAGEOFF12,
783
r_pcrel: false,
784
r_length: 2,
785
}
786
}
787
Reloc::Aarch64TlsDescAdrPage21 => {
788
assert_eq!(
789
self.object.format(),
790
object::BinaryFormat::Elf,
791
"Aarch64TlsDescAdrPage21 is not supported for this file format"
792
);
793
RelocationFlags::Elf {
794
r_type: object::elf::R_AARCH64_TLSDESC_ADR_PAGE21,
795
}
796
}
797
Reloc::Aarch64TlsDescLd64Lo12 => {
798
assert_eq!(
799
self.object.format(),
800
object::BinaryFormat::Elf,
801
"Aarch64TlsDescLd64Lo12 is not supported for this file format"
802
);
803
RelocationFlags::Elf {
804
r_type: object::elf::R_AARCH64_TLSDESC_LD64_LO12,
805
}
806
}
807
Reloc::Aarch64TlsDescAddLo12 => {
808
assert_eq!(
809
self.object.format(),
810
object::BinaryFormat::Elf,
811
"Aarch64TlsDescAddLo12 is not supported for this file format"
812
);
813
RelocationFlags::Elf {
814
r_type: object::elf::R_AARCH64_TLSDESC_ADD_LO12,
815
}
816
}
817
Reloc::Aarch64TlsDescCall => {
818
assert_eq!(
819
self.object.format(),
820
object::BinaryFormat::Elf,
821
"Aarch64TlsDescCall is not supported for this file format"
822
);
823
RelocationFlags::Elf {
824
r_type: object::elf::R_AARCH64_TLSDESC_CALL,
825
}
826
}
827
828
Reloc::Aarch64AdrGotPage21 => match self.object.format() {
829
object::BinaryFormat::Elf => RelocationFlags::Elf {
830
r_type: object::elf::R_AARCH64_ADR_GOT_PAGE,
831
},
832
object::BinaryFormat::MachO => RelocationFlags::MachO {
833
r_type: object::macho::ARM64_RELOC_GOT_LOAD_PAGE21,
834
r_pcrel: true,
835
r_length: 2,
836
},
837
_ => unimplemented!("Aarch64AdrGotPage21 is not supported for this file format"),
838
},
839
Reloc::Aarch64Ld64GotLo12Nc => match self.object.format() {
840
object::BinaryFormat::Elf => RelocationFlags::Elf {
841
r_type: object::elf::R_AARCH64_LD64_GOT_LO12_NC,
842
},
843
object::BinaryFormat::MachO => RelocationFlags::MachO {
844
r_type: object::macho::ARM64_RELOC_GOT_LOAD_PAGEOFF12,
845
r_pcrel: false,
846
r_length: 2,
847
},
848
_ => unimplemented!("Aarch64Ld64GotLo12Nc is not supported for this file format"),
849
},
850
Reloc::S390xPCRel32Dbl => RelocationFlags::Generic {
851
kind: RelocationKind::Relative,
852
encoding: RelocationEncoding::S390xDbl,
853
size: 32,
854
},
855
Reloc::S390xPLTRel32Dbl => RelocationFlags::Generic {
856
kind: RelocationKind::PltRelative,
857
encoding: RelocationEncoding::S390xDbl,
858
size: 32,
859
},
860
Reloc::S390xTlsGd64 => {
861
assert_eq!(
862
self.object.format(),
863
object::BinaryFormat::Elf,
864
"S390xTlsGd64 is not supported for this file format"
865
);
866
RelocationFlags::Elf {
867
r_type: object::elf::R_390_TLS_GD64,
868
}
869
}
870
Reloc::S390xTlsGdCall => {
871
assert_eq!(
872
self.object.format(),
873
object::BinaryFormat::Elf,
874
"S390xTlsGdCall is not supported for this file format"
875
);
876
RelocationFlags::Elf {
877
r_type: object::elf::R_390_TLS_GDCALL,
878
}
879
}
880
Reloc::RiscvCallPlt => {
881
assert_eq!(
882
self.object.format(),
883
object::BinaryFormat::Elf,
884
"RiscvCallPlt is not supported for this file format"
885
);
886
RelocationFlags::Elf {
887
r_type: object::elf::R_RISCV_CALL_PLT,
888
}
889
}
890
Reloc::RiscvTlsGdHi20 => {
891
assert_eq!(
892
self.object.format(),
893
object::BinaryFormat::Elf,
894
"RiscvTlsGdHi20 is not supported for this file format"
895
);
896
RelocationFlags::Elf {
897
r_type: object::elf::R_RISCV_TLS_GD_HI20,
898
}
899
}
900
Reloc::RiscvPCRelLo12I => {
901
assert_eq!(
902
self.object.format(),
903
object::BinaryFormat::Elf,
904
"RiscvPCRelLo12I is not supported for this file format"
905
);
906
RelocationFlags::Elf {
907
r_type: object::elf::R_RISCV_PCREL_LO12_I,
908
}
909
}
910
Reloc::RiscvGotHi20 => {
911
assert_eq!(
912
self.object.format(),
913
object::BinaryFormat::Elf,
914
"RiscvGotHi20 is not supported for this file format"
915
);
916
RelocationFlags::Elf {
917
r_type: object::elf::R_RISCV_GOT_HI20,
918
}
919
}
920
// FIXME
921
reloc => unimplemented!("{:?}", reloc),
922
};
923
924
ObjectRelocRecord {
925
offset: record.offset,
926
name: record.name.clone(),
927
flags,
928
addend: record.addend,
929
}
930
}
931
}
932
933
fn translate_linkage(linkage: Linkage) -> (SymbolScope, bool) {
934
let scope = match linkage {
935
Linkage::Import => SymbolScope::Unknown,
936
Linkage::Local => SymbolScope::Compilation,
937
Linkage::Hidden => SymbolScope::Linkage,
938
Linkage::Export | Linkage::Preemptible => SymbolScope::Dynamic,
939
};
940
// TODO: this matches rustc_codegen_cranelift, but may be wrong.
941
let weak = linkage == Linkage::Preemptible;
942
(scope, weak)
943
}
944
945
/// This is the output of `ObjectModule`'s
946
/// [`finish`](../struct.ObjectModule.html#method.finish) function.
947
/// It contains the generated `Object` and other information produced during
948
/// compilation.
949
pub struct ObjectProduct {
950
/// Object artifact with all functions and data from the module defined.
951
pub object: Object<'static>,
952
/// Symbol IDs for functions (both declared and defined).
953
pub functions: SecondaryMap<FuncId, Option<(SymbolId, bool)>>,
954
/// Symbol IDs for data objects (both declared and defined).
955
pub data_objects: SecondaryMap<DataId, Option<(SymbolId, bool)>>,
956
}
957
958
impl ObjectProduct {
959
/// Return the `SymbolId` for the given function.
960
#[inline]
961
pub fn function_symbol(&self, id: FuncId) -> SymbolId {
962
self.functions[id].unwrap().0
963
}
964
965
/// Return the `SymbolId` for the given data object.
966
#[inline]
967
pub fn data_symbol(&self, id: DataId) -> SymbolId {
968
self.data_objects[id].unwrap().0
969
}
970
971
/// Write the object bytes in memory.
972
#[inline]
973
pub fn emit(self) -> Result<Vec<u8>, object::write::Error> {
974
self.object.write()
975
}
976
}
977
978
#[derive(Clone)]
979
struct SymbolRelocs {
980
section: SectionId,
981
offset: u64,
982
relocs: Vec<ObjectRelocRecord>,
983
}
984
985
#[derive(Clone)]
986
struct ObjectRelocRecord {
987
offset: CodeOffset,
988
name: ModuleRelocTarget,
989
flags: RelocationFlags,
990
addend: Addend,
991
}
992
993