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