diff --git a/cranelift/filetests/isa/x86/binary32.cton b/cranelift/filetests/isa/x86/binary32.cton index b953d663f6..a6476e3e81 100644 --- a/cranelift/filetests/isa/x86/binary32.cton +++ b/cranelift/filetests/isa/x86/binary32.cton @@ -352,7 +352,7 @@ ebb0: [-,%rsi] v351 = bint.i32 v301 ; bin: 0f b6 f2 ; asm: call foo - call fn0() ; bin: stk_ovf e8 PCRel4(%foo-4) 00000000 + call fn0() ; bin: stk_ovf e8 CallPCRel4(%foo-4) 00000000 ; asm: movl $0, %ecx [-,%rcx] v400 = func_addr.i32 fn0 ; bin: b9 Abs4(%foo) 00000000 diff --git a/cranelift/filetests/isa/x86/binary64-pic.cton b/cranelift/filetests/isa/x86/binary64-pic.cton index 3678906135..2fa66a820f 100644 --- a/cranelift/filetests/isa/x86/binary64-pic.cton +++ b/cranelift/filetests/isa/x86/binary64-pic.cton @@ -30,7 +30,7 @@ ebb0: ; Colocated functions. ; asm: call foo - call fn1() ; bin: stk_ovf e8 PCRel4(%bar-4) 00000000 + call fn1() ; bin: stk_ovf e8 CallPCRel4(%bar-4) 00000000 ; asm: lea 0x0(%rip), %rax [-,%rax] v0 = func_addr.i64 fn1 ; bin: 48 8d 05 PCRel4(%bar-4) 00000000 @@ -49,7 +49,7 @@ ebb0: ; Non-colocated functions. ; asm: call foo@PLT - call fn0() ; bin: stk_ovf e8 PLTRel4(%foo-4) 00000000 + call fn0() ; bin: stk_ovf e8 CallPLTRel4(%foo-4) 00000000 ; asm: mov 0x0(%rip), %rax [-,%rax] v100 = func_addr.i64 fn0 ; bin: 48 8b 05 GOTPCRel4(%foo-4) 00000000 diff --git a/cranelift/filetests/isa/x86/binary64.cton b/cranelift/filetests/isa/x86/binary64.cton index 0b0deb4143..c6ba888579 100644 --- a/cranelift/filetests/isa/x86/binary64.cton +++ b/cranelift/filetests/isa/x86/binary64.cton @@ -485,7 +485,7 @@ ebb0: ; Colocated functions. ; asm: call bar - call fn1() ; bin: stk_ovf e8 PCRel4(%bar-4) 00000000 + call fn1() ; bin: stk_ovf e8 CallPCRel4(%bar-4) 00000000 ; asm: lea 0x0(%rip), %rcx [-,%rcx] v400 = func_addr.i64 fn1 ; bin: 48 8d 0d PCRel4(%bar-4) 00000000 diff --git a/lib/codegen/meta/isa/x86/recipes.py b/lib/codegen/meta/isa/x86/recipes.py index 75c666a8af..66c6326a3a 100644 --- a/lib/codegen/meta/isa/x86/recipes.py +++ b/lib/codegen/meta/isa/x86/recipes.py @@ -1388,7 +1388,7 @@ call_id = TailRecipe( PUT_OP(bits, BASE_REX, sink); // The addend adjusts for the difference between the end of the // instruction and the beginning of the immediate field. - sink.reloc_external(Reloc::X86PCRel4, + sink.reloc_external(Reloc::X86CallPCRel4, &func.dfg.ext_funcs[func_ref].name, -4); sink.put4(0); @@ -1399,7 +1399,7 @@ call_plt_id = TailRecipe( emit=''' sink.trap(TrapCode::StackOverflow, func.srclocs[inst]); PUT_OP(bits, BASE_REX, sink); - sink.reloc_external(Reloc::X86PLTRel4, + sink.reloc_external(Reloc::X86CallPLTRel4, &func.dfg.ext_funcs[func_ref].name, -4); sink.put4(0); diff --git a/lib/codegen/src/binemit/mod.rs b/lib/codegen/src/binemit/mod.rs index 4a95ed4eb7..9e4036b2ed 100644 --- a/lib/codegen/src/binemit/mod.rs +++ b/lib/codegen/src/binemit/mod.rs @@ -33,10 +33,12 @@ pub enum Reloc { Abs8, /// x86 PC-relative 4-byte X86PCRel4, + /// x86 call to PC-relative 4-byte + X86CallPCRel4, + /// x86 call to PLT-relative 4-byte + X86CallPLTRel4, /// x86 GOT PC-relative 4-byte X86GOTPCRel4, - /// x86 PLT-relative 4-byte - X86PLTRel4, /// Arm32 call target Arm32Call, /// Arm64 call target @@ -53,8 +55,9 @@ impl fmt::Display for Reloc { Reloc::Abs4 => write!(f, "Abs4"), Reloc::Abs8 => write!(f, "Abs8"), Reloc::X86PCRel4 => write!(f, "PCRel4"), + Reloc::X86CallPCRel4 => write!(f, "CallPCRel4"), + Reloc::X86CallPLTRel4 => write!(f, "CallPLTRel4"), Reloc::X86GOTPCRel4 => write!(f, "GOTPCRel4"), - Reloc::X86PLTRel4 => write!(f, "PLTRel4"), Reloc::Arm32Call | Reloc::Arm64Call | Reloc::RiscvCall => write!(f, "Call"), } } diff --git a/lib/faerie/src/backend.rs b/lib/faerie/src/backend.rs index 4126ed7582..73d4b3330d 100644 --- a/lib/faerie/src/backend.rs +++ b/lib/faerie/src/backend.rs @@ -11,7 +11,7 @@ use cretonne_module::{ use faerie; use failure::Error; use std::fs::File; -use target_lexicon::BinaryFormat; +use target_lexicon::Triple; use traps::{FaerieTrapManifest, FaerieTrapSink}; #[derive(Debug)] @@ -29,7 +29,6 @@ pub enum FaerieTrapCollection { pub struct FaerieBuilder { isa: Box, name: String, - format: BinaryFormat, collect_traps: FaerieTrapCollection, libcall_names: Box String>, } @@ -51,7 +50,6 @@ impl FaerieBuilder { pub fn new( isa: Box, name: String, - format: BinaryFormat, collect_traps: FaerieTrapCollection, libcall_names: Box String>, ) -> ModuleResult { @@ -63,7 +61,6 @@ impl FaerieBuilder { Ok(Self { isa, name, - format, collect_traps, libcall_names, }) @@ -91,7 +88,6 @@ impl FaerieBuilder { pub struct FaerieBackend { isa: Box, artifact: faerie::Artifact, - format: BinaryFormat, trap_manifest: Option, libcall_names: Box String>, } @@ -120,7 +116,6 @@ impl Backend for FaerieBackend { Self { artifact: faerie::Artifact::new(builder.isa.triple().clone(), builder.name), isa: builder.isa, - format: builder.format, trap_manifest: match builder.collect_traps { FaerieTrapCollection::Enabled => Some(FaerieTrapManifest::new()), FaerieTrapCollection::Disabled => None, @@ -158,7 +153,7 @@ impl Backend for FaerieBackend { // Non-lexical lifetimes would obviate the braces here. { let mut reloc_sink = FaerieRelocSink { - format: self.format, + triple: self.isa.triple().clone(), artifact: &mut self.artifact, name, namespace, @@ -348,7 +343,7 @@ fn translate_data_linkage(linkage: Linkage, writable: bool) -> faerie::Decl { } struct FaerieRelocSink<'a> { - format: BinaryFormat, + triple: Triple, artifact: &'a mut faerie::Artifact, name: &'a str, namespace: &'a ModuleNamespace<'a, FaerieBackend>, @@ -384,9 +379,11 @@ impl<'a> RelocSink for FaerieRelocSink<'a> { } _ => panic!("invalid ExternalName {}", name), }; - let addend_i32 = addend as i32; - debug_assert!(i64::from(addend_i32) == addend); - let raw_reloc = container::raw_relocation(reloc, self.format); + let (raw_reloc, raw_addend) = container::raw_relocation(reloc, &self.triple); + // TODO: Handle overflow. + let final_addend = addend + raw_addend; + let addend_i32 = final_addend as i32; + debug_assert!(i64::from(addend_i32) == final_addend); self.artifact .link_with( faerie::Link { diff --git a/lib/faerie/src/container.rs b/lib/faerie/src/container.rs index 117482020c..72766c1f0f 100644 --- a/lib/faerie/src/container.rs +++ b/lib/faerie/src/container.rs @@ -1,7 +1,7 @@ //! Utilities for working with Faerie container formats. use cretonne_codegen::binemit::Reloc; -use target_lexicon::BinaryFormat; +use target_lexicon::{Architecture, BinaryFormat, Triple}; /// An object file format. #[derive(Copy, Clone, Debug, Eq, PartialEq)] @@ -13,23 +13,53 @@ pub enum Format { } /// Translate from a Cretonne `Reloc` to a raw object-file-format-specific -/// relocation code. -pub fn raw_relocation(reloc: Reloc, format: BinaryFormat) -> u32 { - match format { +/// relocation code and relocation-implied addend. +pub fn raw_relocation(reloc: Reloc, triple: &Triple) -> (u32, i64) { + match triple.binary_format { BinaryFormat::Elf => { use goblin::elf; - match reloc { - Reloc::Abs4 => elf::reloc::R_X86_64_32, - Reloc::Abs8 => elf::reloc::R_X86_64_64, - Reloc::X86PCRel4 => elf::reloc::R_X86_64_PC32, - // TODO: Get Cretonne to tell us when we can use - // R_X86_64_GOTPCRELX/R_X86_64_REX_GOTPCRELX. - Reloc::X86GOTPCRel4 => elf::reloc::R_X86_64_GOTPCREL, - Reloc::X86PLTRel4 => elf::reloc::R_X86_64_PLT32, - _ => unimplemented!(), + ( + match triple.architecture { + Architecture::X86_64 => { + match reloc { + Reloc::Abs4 => elf::reloc::R_X86_64_32, + Reloc::Abs8 => elf::reloc::R_X86_64_64, + Reloc::X86PCRel4 | Reloc::X86CallPCRel4 => elf::reloc::R_X86_64_PC32, + // TODO: Get Cretonne to tell us when we can use + // R_X86_64_GOTPCRELX/R_X86_64_REX_GOTPCRELX. + Reloc::X86CallPLTRel4 => elf::reloc::R_X86_64_PLT32, + Reloc::X86GOTPCRel4 => elf::reloc::R_X86_64_GOTPCREL, + _ => unimplemented!(), + } + } + _ => unimplemented!("unsupported architecture: {}", triple), + }, + // Most ELF relocations do not include an implicit addend. + 0, + ) + } + BinaryFormat::Macho => { + use goblin::mach; + match triple.architecture { + Architecture::X86_64 => { + match reloc { + Reloc::Abs8 => (u32::from(mach::relocation::R_ABS), 0), + // Mach-O doesn't need us to distinguish between PC-relative calls + // and PLT calls, but it does need us to distinguish between calls + // and non-calls. And, it includes the 4-byte addend implicitly. + Reloc::X86PCRel4 => (u32::from(mach::relocation::X86_64_RELOC_SIGNED), 4), + Reloc::X86CallPCRel4 | Reloc::X86CallPLTRel4 => { + (u32::from(mach::relocation::X86_64_RELOC_BRANCH), 4) + } + Reloc::X86GOTPCRel4 => { + (u32::from(mach::relocation::X86_64_RELOC_GOT_LOAD), 4) + } + _ => unimplemented!("unsupported mach-o reloc: {}", reloc), + } + } + _ => unimplemented!("unsupported architecture: {}", triple), } } - BinaryFormat::Macho => unimplemented!("macho relocations"), _ => unimplemented!("unsupported format"), } } diff --git a/lib/simplejit/src/backend.rs b/lib/simplejit/src/backend.rs index 23bed09bdc..29c9c26a32 100644 --- a/lib/simplejit/src/backend.rs +++ b/lib/simplejit/src/backend.rs @@ -271,7 +271,7 @@ impl<'simple_jit_backend> Backend for SimpleJITBackend { write_unaligned(at as *mut u64, what as u64) }; } - Reloc::X86PCRel4 => { + Reloc::X86PCRel4 | Reloc::X86CallPCRel4 => { // TODO: Handle overflow. let pcrel = ((what as isize) - (at as isize)) as i32; #[cfg_attr(feature = "cargo-clippy", allow(cast_ptr_alignment))] @@ -279,7 +279,7 @@ impl<'simple_jit_backend> Backend for SimpleJITBackend { write_unaligned(at as *mut i32, pcrel) }; } - Reloc::X86GOTPCRel4 | Reloc::X86PLTRel4 => panic!("unexpected PIC relocation"), + Reloc::X86GOTPCRel4 | Reloc::X86CallPLTRel4 => panic!("unexpected PIC relocation"), _ => unimplemented!(), } } @@ -336,9 +336,10 @@ impl<'simple_jit_backend> Backend for SimpleJITBackend { write_unaligned(at as *mut u64, what as u64) }; } - Reloc::X86PCRel4 | Reloc::X86GOTPCRel4 | Reloc::X86PLTRel4 => { - panic!("unexpected text relocation in data") - } + Reloc::X86PCRel4 + | Reloc::X86CallPCRel4 + | Reloc::X86GOTPCRel4 + | Reloc::X86CallPLTRel4 => panic!("unexpected text relocation in data"), _ => unimplemented!(), } }