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