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