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 let mut code: Vec<u8> = Vec::new(); 335 336 let res = ctx.compile_and_emit(self.isa(), &mut code, ctrl_plane)?; 337 let alignment = res.buffer.alignment as u64; 338 339 self.define_function_bytes( 340 func_id, 341 &ctx.func, 342 alignment, 343 &code, 344 ctx.compiled_code().unwrap().buffer.relocs(), 345 ) 346 } 347 348 fn define_function_bytes( 349 &mut self, 350 func_id: FuncId, 351 func: &ir::Function, 352 alignment: u64, 353 bytes: &[u8], 354 relocs: &[FinalizedMachReloc], 355 ) -> ModuleResult<()> { 356 info!("defining function {} with bytes", func_id); 357 let decl = self.declarations.get_function_decl(func_id); 358 let decl_name = decl.linkage_name(func_id); 359 if !decl.linkage.is_definable() { 360 return Err(ModuleError::InvalidImportDefinition(decl_name.into_owned())); 361 } 362 363 let &mut (symbol, ref mut defined) = self.functions[func_id].as_mut().unwrap(); 364 if *defined { 365 return Err(ModuleError::DuplicateDefinition(decl_name.into_owned())); 366 } 367 *defined = true; 368 369 let align = alignment 370 .max(self.isa.function_alignment().minimum.into()) 371 .max(self.isa.symbol_alignment()); 372 let section = if self.per_function_section { 373 let symbol_name = self.object.symbol(symbol).name.clone(); 374 self.object 375 .add_subsection(StandardSection::Text, &symbol_name) 376 } else { 377 self.object.section_id(StandardSection::Text) 378 }; 379 let offset = self.object.add_symbol_data(symbol, section, bytes, align); 380 381 if !relocs.is_empty() { 382 let relocs = relocs 383 .iter() 384 .map(|record| { 385 self.process_reloc(&ModuleReloc::from_mach_reloc(&record, func, func_id)) 386 }) 387 .collect(); 388 self.relocs.push(SymbolRelocs { 389 section, 390 offset, 391 relocs, 392 }); 393 } 394 395 Ok(()) 396 } 397 398 fn define_data(&mut self, data_id: DataId, data: &DataDescription) -> ModuleResult<()> { 399 let decl = self.declarations.get_data_decl(data_id); 400 if !decl.linkage.is_definable() { 401 return Err(ModuleError::InvalidImportDefinition( 402 decl.linkage_name(data_id).into_owned(), 403 )); 404 } 405 406 let &mut (symbol, ref mut defined) = self.data_objects[data_id].as_mut().unwrap(); 407 if *defined { 408 return Err(ModuleError::DuplicateDefinition( 409 decl.linkage_name(data_id).into_owned(), 410 )); 411 } 412 *defined = true; 413 414 let &DataDescription { 415 ref init, 416 function_decls: _, 417 data_decls: _, 418 function_relocs: _, 419 data_relocs: _, 420 ref custom_segment_section, 421 align, 422 } = data; 423 424 let pointer_reloc = match self.isa.triple().pointer_width().unwrap() { 425 PointerWidth::U16 => unimplemented!("16bit pointers"), 426 PointerWidth::U32 => Reloc::Abs4, 427 PointerWidth::U64 => Reloc::Abs8, 428 }; 429 let relocs = data 430 .all_relocs(pointer_reloc) 431 .map(|record| self.process_reloc(&record)) 432 .collect::<Vec<_>>(); 433 434 let section = if custom_segment_section.is_none() { 435 let section_kind = if let Init::Zeros { .. } = *init { 436 if decl.tls { 437 StandardSection::UninitializedTls 438 } else { 439 StandardSection::UninitializedData 440 } 441 } else if decl.tls { 442 StandardSection::Tls 443 } else if decl.writable { 444 StandardSection::Data 445 } else if relocs.is_empty() { 446 StandardSection::ReadOnlyData 447 } else { 448 StandardSection::ReadOnlyDataWithRel 449 }; 450 self.object.section_id(section_kind) 451 } else { 452 if decl.tls { 453 return Err(cranelift_module::ModuleError::Backend(anyhow::anyhow!( 454 "Custom section not supported for TLS" 455 ))); 456 } 457 let (seg, sec) = &custom_segment_section.as_ref().unwrap(); 458 self.object.add_section( 459 seg.clone().into_bytes(), 460 sec.clone().into_bytes(), 461 if decl.writable { 462 SectionKind::Data 463 } else if relocs.is_empty() { 464 SectionKind::ReadOnlyData 465 } else { 466 SectionKind::ReadOnlyDataWithRel 467 }, 468 ) 469 }; 470 471 let align = std::cmp::max(align.unwrap_or(1), self.isa.symbol_alignment()); 472 let offset = match *init { 473 Init::Uninitialized => { 474 panic!("data is not initialized yet"); 475 } 476 Init::Zeros { size } => self 477 .object 478 .add_symbol_bss(symbol, section, size as u64, align), 479 Init::Bytes { ref contents } => self 480 .object 481 .add_symbol_data(symbol, section, &contents, align), 482 }; 483 if !relocs.is_empty() { 484 self.relocs.push(SymbolRelocs { 485 section, 486 offset, 487 relocs, 488 }); 489 } 490 Ok(()) 491 } 492 } 493 494 impl ObjectModule { 495 /// Finalize all relocations and output an object. 496 pub fn finish(mut self) -> ObjectProduct { 497 let symbol_relocs = mem::take(&mut self.relocs); 498 for symbol in symbol_relocs { 499 for &ObjectRelocRecord { 500 offset, 501 ref name, 502 flags, 503 addend, 504 } in &symbol.relocs 505 { 506 let target_symbol = self.get_symbol(name); 507 self.object 508 .add_relocation( 509 symbol.section, 510 Relocation { 511 offset: symbol.offset + u64::from(offset), 512 flags, 513 symbol: target_symbol, 514 addend, 515 }, 516 ) 517 .unwrap(); 518 } 519 } 520 521 // Indicate that this object has a non-executable stack. 522 if self.object.format() == object::BinaryFormat::Elf { 523 self.object.add_section( 524 vec![], 525 ".note.GNU-stack".as_bytes().to_vec(), 526 SectionKind::Linker, 527 ); 528 } 529 530 ObjectProduct { 531 object: self.object, 532 functions: self.functions, 533 data_objects: self.data_objects, 534 } 535 } 536 537 /// This should only be called during finish because it creates 538 /// symbols for missing libcalls. 539 fn get_symbol(&mut self, name: &ModuleRelocTarget) -> SymbolId { 540 match *name { 541 ModuleRelocTarget::User { .. } => { 542 if ModuleDeclarations::is_function(name) { 543 let id = FuncId::from_name(name); 544 self.functions[id].unwrap().0 545 } else { 546 let id = DataId::from_name(name); 547 self.data_objects[id].unwrap().0 548 } 549 } 550 ModuleRelocTarget::LibCall(ref libcall) => { 551 let name = (self.libcall_names)(*libcall); 552 if let Some(symbol) = self.object.symbol_id(name.as_bytes()) { 553 symbol 554 } else if let Some(symbol) = self.libcalls.get(libcall) { 555 *symbol 556 } else { 557 let symbol = self.object.add_symbol(Symbol { 558 name: name.as_bytes().to_vec(), 559 value: 0, 560 size: 0, 561 kind: SymbolKind::Text, 562 scope: SymbolScope::Unknown, 563 weak: false, 564 section: SymbolSection::Undefined, 565 flags: SymbolFlags::None, 566 }); 567 self.libcalls.insert(*libcall, symbol); 568 symbol 569 } 570 } 571 // These are "magic" names well-known to the linker. 572 // They require special treatment. 573 ModuleRelocTarget::KnownSymbol(ref known_symbol) => { 574 if let Some(symbol) = self.known_symbols.get(known_symbol) { 575 *symbol 576 } else { 577 let symbol = self.object.add_symbol(match known_symbol { 578 ir::KnownSymbol::ElfGlobalOffsetTable => Symbol { 579 name: b"_GLOBAL_OFFSET_TABLE_".to_vec(), 580 value: 0, 581 size: 0, 582 kind: SymbolKind::Data, 583 scope: SymbolScope::Unknown, 584 weak: false, 585 section: SymbolSection::Undefined, 586 flags: SymbolFlags::None, 587 }, 588 ir::KnownSymbol::CoffTlsIndex => Symbol { 589 name: b"_tls_index".to_vec(), 590 value: 0, 591 size: 32, 592 kind: SymbolKind::Tls, 593 scope: SymbolScope::Unknown, 594 weak: false, 595 section: SymbolSection::Undefined, 596 flags: SymbolFlags::None, 597 }, 598 }); 599 self.known_symbols.insert(*known_symbol, symbol); 600 symbol 601 } 602 } 603 604 ModuleRelocTarget::FunctionOffset(func_id, offset) => { 605 match self.known_labels.entry((func_id, offset)) { 606 Entry::Occupied(o) => *o.get(), 607 Entry::Vacant(v) => { 608 let func_symbol_id = self.functions[func_id].unwrap().0; 609 let func_symbol = self.object.symbol(func_symbol_id); 610 611 let name = format!(".L{}_{}", func_id.as_u32(), offset); 612 let symbol_id = self.object.add_symbol(Symbol { 613 name: name.as_bytes().to_vec(), 614 value: func_symbol.value + offset as u64, 615 size: 0, 616 kind: SymbolKind::Label, 617 scope: SymbolScope::Compilation, 618 weak: false, 619 section: SymbolSection::Section(func_symbol.section.id().unwrap()), 620 flags: SymbolFlags::None, 621 }); 622 623 v.insert(symbol_id); 624 symbol_id 625 } 626 } 627 } 628 } 629 } 630 631 fn process_reloc(&self, record: &ModuleReloc) -> ObjectRelocRecord { 632 let flags = match record.kind { 633 Reloc::Abs4 => RelocationFlags::Generic { 634 kind: RelocationKind::Absolute, 635 encoding: RelocationEncoding::Generic, 636 size: 32, 637 }, 638 Reloc::Abs8 => RelocationFlags::Generic { 639 kind: RelocationKind::Absolute, 640 encoding: RelocationEncoding::Generic, 641 size: 64, 642 }, 643 Reloc::X86PCRel4 => RelocationFlags::Generic { 644 kind: RelocationKind::Relative, 645 encoding: RelocationEncoding::Generic, 646 size: 32, 647 }, 648 Reloc::X86CallPCRel4 => RelocationFlags::Generic { 649 kind: RelocationKind::Relative, 650 encoding: RelocationEncoding::X86Branch, 651 size: 32, 652 }, 653 // TODO: Get Cranelift to tell us when we can use 654 // R_X86_64_GOTPCRELX/R_X86_64_REX_GOTPCRELX. 655 Reloc::X86CallPLTRel4 => RelocationFlags::Generic { 656 kind: RelocationKind::PltRelative, 657 encoding: RelocationEncoding::X86Branch, 658 size: 32, 659 }, 660 Reloc::X86SecRel => RelocationFlags::Generic { 661 kind: RelocationKind::SectionOffset, 662 encoding: RelocationEncoding::Generic, 663 size: 32, 664 }, 665 Reloc::X86GOTPCRel4 => RelocationFlags::Generic { 666 kind: RelocationKind::GotRelative, 667 encoding: RelocationEncoding::Generic, 668 size: 32, 669 }, 670 Reloc::Arm64Call => RelocationFlags::Generic { 671 kind: RelocationKind::Relative, 672 encoding: RelocationEncoding::AArch64Call, 673 size: 26, 674 }, 675 Reloc::ElfX86_64TlsGd => { 676 assert_eq!( 677 self.object.format(), 678 object::BinaryFormat::Elf, 679 "ElfX86_64TlsGd is not supported for this file format" 680 ); 681 RelocationFlags::Elf { 682 r_type: object::elf::R_X86_64_TLSGD, 683 } 684 } 685 Reloc::MachOX86_64Tlv => { 686 assert_eq!( 687 self.object.format(), 688 object::BinaryFormat::MachO, 689 "MachOX86_64Tlv is not supported for this file format" 690 ); 691 RelocationFlags::MachO { 692 r_type: object::macho::X86_64_RELOC_TLV, 693 r_pcrel: true, 694 r_length: 2, 695 } 696 } 697 Reloc::MachOAarch64TlsAdrPage21 => { 698 assert_eq!( 699 self.object.format(), 700 object::BinaryFormat::MachO, 701 "MachOAarch64TlsAdrPage21 is not supported for this file format" 702 ); 703 RelocationFlags::MachO { 704 r_type: object::macho::ARM64_RELOC_TLVP_LOAD_PAGE21, 705 r_pcrel: true, 706 r_length: 2, 707 } 708 } 709 Reloc::MachOAarch64TlsAdrPageOff12 => { 710 assert_eq!( 711 self.object.format(), 712 object::BinaryFormat::MachO, 713 "MachOAarch64TlsAdrPageOff12 is not supported for this file format" 714 ); 715 RelocationFlags::MachO { 716 r_type: object::macho::ARM64_RELOC_TLVP_LOAD_PAGEOFF12, 717 r_pcrel: false, 718 r_length: 2, 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 RelocationFlags::Elf { 728 r_type: object::elf::R_AARCH64_TLSDESC_ADR_PAGE21, 729 } 730 } 731 Reloc::Aarch64TlsDescLd64Lo12 => { 732 assert_eq!( 733 self.object.format(), 734 object::BinaryFormat::Elf, 735 "Aarch64TlsDescLd64Lo12 is not supported for this file format" 736 ); 737 RelocationFlags::Elf { 738 r_type: object::elf::R_AARCH64_TLSDESC_LD64_LO12, 739 } 740 } 741 Reloc::Aarch64TlsDescAddLo12 => { 742 assert_eq!( 743 self.object.format(), 744 object::BinaryFormat::Elf, 745 "Aarch64TlsDescAddLo12 is not supported for this file format" 746 ); 747 RelocationFlags::Elf { 748 r_type: object::elf::R_AARCH64_TLSDESC_ADD_LO12, 749 } 750 } 751 Reloc::Aarch64TlsDescCall => { 752 assert_eq!( 753 self.object.format(), 754 object::BinaryFormat::Elf, 755 "Aarch64TlsDescCall is not supported for this file format" 756 ); 757 RelocationFlags::Elf { 758 r_type: object::elf::R_AARCH64_TLSDESC_CALL, 759 } 760 } 761 762 Reloc::Aarch64AdrGotPage21 => match self.object.format() { 763 object::BinaryFormat::Elf => RelocationFlags::Elf { 764 r_type: object::elf::R_AARCH64_ADR_GOT_PAGE, 765 }, 766 object::BinaryFormat::MachO => RelocationFlags::MachO { 767 r_type: object::macho::ARM64_RELOC_GOT_LOAD_PAGE21, 768 r_pcrel: true, 769 r_length: 2, 770 }, 771 _ => unimplemented!("Aarch64AdrGotPage21 is not supported for this file format"), 772 }, 773 Reloc::Aarch64Ld64GotLo12Nc => match self.object.format() { 774 object::BinaryFormat::Elf => RelocationFlags::Elf { 775 r_type: object::elf::R_AARCH64_LD64_GOT_LO12_NC, 776 }, 777 object::BinaryFormat::MachO => RelocationFlags::MachO { 778 r_type: object::macho::ARM64_RELOC_GOT_LOAD_PAGEOFF12, 779 r_pcrel: false, 780 r_length: 2, 781 }, 782 _ => unimplemented!("Aarch64Ld64GotLo12Nc is not supported for this file format"), 783 }, 784 Reloc::S390xPCRel32Dbl => RelocationFlags::Generic { 785 kind: RelocationKind::Relative, 786 encoding: RelocationEncoding::S390xDbl, 787 size: 32, 788 }, 789 Reloc::S390xPLTRel32Dbl => RelocationFlags::Generic { 790 kind: RelocationKind::PltRelative, 791 encoding: RelocationEncoding::S390xDbl, 792 size: 32, 793 }, 794 Reloc::S390xTlsGd64 => { 795 assert_eq!( 796 self.object.format(), 797 object::BinaryFormat::Elf, 798 "S390xTlsGd64 is not supported for this file format" 799 ); 800 RelocationFlags::Elf { 801 r_type: object::elf::R_390_TLS_GD64, 802 } 803 } 804 Reloc::S390xTlsGdCall => { 805 assert_eq!( 806 self.object.format(), 807 object::BinaryFormat::Elf, 808 "S390xTlsGdCall is not supported for this file format" 809 ); 810 RelocationFlags::Elf { 811 r_type: object::elf::R_390_TLS_GDCALL, 812 } 813 } 814 Reloc::RiscvCallPlt => { 815 assert_eq!( 816 self.object.format(), 817 object::BinaryFormat::Elf, 818 "RiscvCallPlt is not supported for this file format" 819 ); 820 RelocationFlags::Elf { 821 r_type: object::elf::R_RISCV_CALL_PLT, 822 } 823 } 824 Reloc::RiscvTlsGdHi20 => { 825 assert_eq!( 826 self.object.format(), 827 object::BinaryFormat::Elf, 828 "RiscvTlsGdHi20 is not supported for this file format" 829 ); 830 RelocationFlags::Elf { 831 r_type: object::elf::R_RISCV_TLS_GD_HI20, 832 } 833 } 834 Reloc::RiscvPCRelLo12I => { 835 assert_eq!( 836 self.object.format(), 837 object::BinaryFormat::Elf, 838 "RiscvPCRelLo12I is not supported for this file format" 839 ); 840 RelocationFlags::Elf { 841 r_type: object::elf::R_RISCV_PCREL_LO12_I, 842 } 843 } 844 Reloc::RiscvGotHi20 => { 845 assert_eq!( 846 self.object.format(), 847 object::BinaryFormat::Elf, 848 "RiscvGotHi20 is not supported for this file format" 849 ); 850 RelocationFlags::Elf { 851 r_type: object::elf::R_RISCV_GOT_HI20, 852 } 853 } 854 // FIXME 855 reloc => unimplemented!("{:?}", reloc), 856 }; 857 858 ObjectRelocRecord { 859 offset: record.offset, 860 name: record.name.clone(), 861 flags, 862 addend: record.addend, 863 } 864 } 865 } 866 867 fn translate_linkage(linkage: Linkage) -> (SymbolScope, bool) { 868 let scope = match linkage { 869 Linkage::Import => SymbolScope::Unknown, 870 Linkage::Local => SymbolScope::Compilation, 871 Linkage::Hidden => SymbolScope::Linkage, 872 Linkage::Export | Linkage::Preemptible => SymbolScope::Dynamic, 873 }; 874 // TODO: this matches rustc_codegen_cranelift, but may be wrong. 875 let weak = linkage == Linkage::Preemptible; 876 (scope, weak) 877 } 878 879 /// This is the output of `ObjectModule`'s 880 /// [`finish`](../struct.ObjectModule.html#method.finish) function. 881 /// It contains the generated `Object` and other information produced during 882 /// compilation. 883 pub struct ObjectProduct { 884 /// Object artifact with all functions and data from the module defined. 885 pub object: Object<'static>, 886 /// Symbol IDs for functions (both declared and defined). 887 pub functions: SecondaryMap<FuncId, Option<(SymbolId, bool)>>, 888 /// Symbol IDs for data objects (both declared and defined). 889 pub data_objects: SecondaryMap<DataId, Option<(SymbolId, bool)>>, 890 } 891 892 impl ObjectProduct { 893 /// Return the `SymbolId` for the given function. 894 #[inline] 895 pub fn function_symbol(&self, id: FuncId) -> SymbolId { 896 self.functions[id].unwrap().0 897 } 898 899 /// Return the `SymbolId` for the given data object. 900 #[inline] 901 pub fn data_symbol(&self, id: DataId) -> SymbolId { 902 self.data_objects[id].unwrap().0 903 } 904 905 /// Write the object bytes in memory. 906 #[inline] 907 pub fn emit(self) -> Result<Vec<u8>, object::write::Error> { 908 self.object.write() 909 } 910 } 911 912 #[derive(Clone)] 913 struct SymbolRelocs { 914 section: SectionId, 915 offset: u64, 916 relocs: Vec<ObjectRelocRecord>, 917 } 918 919 #[derive(Clone)] 920 struct ObjectRelocRecord { 921 offset: CodeOffset, 922 name: ModuleRelocTarget, 923 flags: RelocationFlags, 924 addend: Addend, 925 } 926