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