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