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