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