1 //! Binary machine code emission. 2 //! 3 //! The `binemit` module contains code for translating Cranelift's intermediate representation into 4 //! binary machine code. 5 6 use core::fmt; 7 #[cfg(feature = "enable-serde")] 8 use serde_derive::{Deserialize, Serialize}; 9 10 /// Offset in bytes from the beginning of the function. 11 /// 12 /// Cranelift can be used as a cross compiler, so we don't want to use a type like `usize` which 13 /// depends on the *host* platform, not the *target* platform. 14 pub type CodeOffset = u32; 15 16 /// Addend to add to the symbol value. 17 pub type Addend = i64; 18 19 /// Relocation kinds for every ISA 20 #[derive(Copy, Clone, Debug, PartialEq, Eq)] 21 #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] 22 pub enum Reloc { 23 /// absolute 4-byte 24 Abs4, 25 /// absolute 8-byte 26 Abs8, 27 /// x86 PC-relative 4-byte 28 X86PCRel4, 29 /// x86 call to PC-relative 4-byte 30 X86CallPCRel4, 31 /// x86 call to PLT-relative 4-byte 32 X86CallPLTRel4, 33 /// x86 GOT PC-relative 4-byte 34 X86GOTPCRel4, 35 /// The 32-bit offset of the target from the beginning of its section. 36 /// Equivalent to `IMAGE_REL_AMD64_SECREL`. 37 /// See: [PE Format](https://docs.microsoft.com/en-us/windows/win32/debug/pe-format) 38 X86SecRel, 39 /// Arm32 call target 40 Arm32Call, 41 /// Arm64 call target. Encoded as bottom 26 bits of instruction. This 42 /// value is sign-extended, multiplied by 4, and added to the PC of 43 /// the call instruction to form the destination address. 44 Arm64Call, 45 /// s390x PC-relative 4-byte offset 46 S390xPCRel32Dbl, 47 /// s390x PC-relative 4-byte offset to PLT 48 S390xPLTRel32Dbl, 49 50 /// Elf x86_64 32 bit signed PC relative offset to two GOT entries for GD symbol. 51 ElfX86_64TlsGd, 52 53 /// Mach-O x86_64 32 bit signed PC relative offset to a `__thread_vars` entry. 54 MachOX86_64Tlv, 55 56 /// Mach-O Aarch64 TLS 57 /// PC-relative distance to the page of the TLVP slot. 58 MachOAarch64TlsAdrPage21, 59 60 /// Mach-O Aarch64 TLS 61 /// Offset within page of TLVP slot. 62 MachOAarch64TlsAdrPageOff12, 63 64 /// Aarch64 TLSDESC Adr Page21 65 /// This is equivalent to `R_AARCH64_TLSDESC_ADR_PAGE21` in the [aaelf64](https://github.com/ARM-software/abi-aa/blob/2bcab1e3b22d55170c563c3c7940134089176746/aaelf64/aaelf64.rst#57105thread-local-storage-descriptors) 66 Aarch64TlsDescAdrPage21, 67 68 /// Aarch64 TLSDESC Ld64 Lo12 69 /// This is equivalent to `R_AARCH64_TLSDESC_LD64_LO12` in the [aaelf64](https://github.com/ARM-software/abi-aa/blob/2bcab1e3b22d55170c563c3c7940134089176746/aaelf64/aaelf64.rst#57105thread-local-storage-descriptors) 70 Aarch64TlsDescLd64Lo12, 71 72 /// Aarch64 TLSDESC Add Lo12 73 /// This is equivalent to `R_AARCH64_TLSGD_ADD_LO12` in the [aaelf64](https://github.com/ARM-software/abi-aa/blob/2bcab1e3b22d55170c563c3c7940134089176746/aaelf64/aaelf64.rst#57105thread-local-storage-descriptors) 74 Aarch64TlsDescAddLo12, 75 76 /// Aarch64 TLSDESC Call 77 /// This is equivalent to `R_AARCH64_TLSDESC_CALL` in the [aaelf64](https://github.com/ARM-software/abi-aa/blob/2bcab1e3b22d55170c563c3c7940134089176746/aaelf64/aaelf64.rst#57105thread-local-storage-descriptors) 78 Aarch64TlsDescCall, 79 80 /// AArch64 GOT Page 81 /// Set the immediate value of an ADRP to bits 32:12 of X; check that –2^32 <= X < 2^32 82 /// This is equivalent to `R_AARCH64_ADR_GOT_PAGE` (311) in the [aaelf64](https://github.com/ARM-software/abi-aa/blob/2bcab1e3b22d55170c563c3c7940134089176746/aaelf64/aaelf64.rst#static-aarch64-relocations) 83 Aarch64AdrGotPage21, 84 85 /// Equivalent of `R_AARCH64_ADR_PREL_PG_HI21`. 86 Aarch64AdrPrelPgHi21, 87 /// Equivalent of `R_AARCH64_ADD_ABS_LO12_NC`. 88 Aarch64AddAbsLo12Nc, 89 90 /// AArch64 GOT Low bits 91 92 /// Set the LD/ST immediate field to bits 11:3 of X. No overflow check; check that X&7 = 0 93 /// This is equivalent to `R_AARCH64_LD64_GOT_LO12_NC` (312) in the [aaelf64](https://github.com/ARM-software/abi-aa/blob/2bcab1e3b22d55170c563c3c7940134089176746/aaelf64/aaelf64.rst#static-aarch64-relocations) 94 Aarch64Ld64GotLo12Nc, 95 96 /// RISC-V Call PLT: 32-bit PC-relative function call, macros call, tail (PIC) 97 /// 98 /// Despite having PLT in the name, this relocation is also used for normal calls. 99 /// The non-PLT version of this relocation has been deprecated. 100 /// 101 /// This is the `R_RISCV_CALL_PLT` relocation from the RISC-V ELF psABI document. 102 /// <https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-elf.adoc#procedure-calls> 103 RiscvCallPlt, 104 105 /// RISC-V TLS GD: High 20 bits of 32-bit PC-relative TLS GD GOT reference, 106 /// 107 /// This is the `R_RISCV_TLS_GD_HI20` relocation from the RISC-V ELF psABI document. 108 /// <https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-elf.adoc#global-dynamic> 109 RiscvTlsGdHi20, 110 111 /// Low 12 bits of a 32-bit PC-relative relocation (I-Type instruction) 112 /// 113 /// This is the `R_RISCV_PCREL_LO12_I` relocation from the RISC-V ELF psABI document. 114 /// <https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-elf.adoc#pc-relative-symbol-addresses> 115 RiscvPCRelLo12I, 116 117 /// High 20 bits of a 32-bit PC-relative GOT offset relocation 118 /// 119 /// This is the `R_RISCV_GOT_HI20` relocation from the RISC-V ELF psABI document. 120 /// <https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-elf.adoc#pc-relative-symbol-addresses> 121 RiscvGotHi20, 122 123 /// High 20 bits of a 32-bit PC-relative offset relocation 124 /// 125 /// This is the `R_RISCV_PCREL_HI20` relocation from the RISC-V ELF psABI document. 126 /// <https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-elf.adoc#pc-relative-symbol-addresses> 127 RiscvPCRelHi20, 128 129 /// s390x TLS GD64 - 64-bit offset of tls_index for GD symbol in GOT 130 S390xTlsGd64, 131 /// s390x TLS GDCall - marker to enable optimization of TLS calls 132 S390xTlsGdCall, 133 134 /// Pulley - a relocation which is a pc-relative offset. 135 PulleyPcRel, 136 137 /// Pulley - call a host function indirectly where the embedder resolving 138 /// this relocation needs to fill the 8-bit immediate that's part of the 139 /// `call_indirect_host` opcode (an opaque identifier used by the host). 140 PulleyCallIndirectHost, 141 } 142 143 impl fmt::Display for Reloc { 144 /// Display trait implementation drops the arch, since its used in contexts where the arch is 145 /// already unambiguous, e.g. clif syntax with isa specified. In other contexts, use Debug. fmt(&self, f: &mut fmt::Formatter) -> fmt::Result146 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 147 match *self { 148 Self::Abs4 => write!(f, "Abs4"), 149 Self::Abs8 => write!(f, "Abs8"), 150 Self::S390xPCRel32Dbl => write!(f, "PCRel32Dbl"), 151 Self::S390xPLTRel32Dbl => write!(f, "PLTRel32Dbl"), 152 Self::X86PCRel4 => write!(f, "PCRel4"), 153 Self::X86CallPCRel4 => write!(f, "CallPCRel4"), 154 Self::X86CallPLTRel4 => write!(f, "CallPLTRel4"), 155 Self::X86GOTPCRel4 => write!(f, "GOTPCRel4"), 156 Self::X86SecRel => write!(f, "SecRel"), 157 Self::Arm32Call | Self::Arm64Call => write!(f, "Call"), 158 Self::RiscvCallPlt => write!(f, "RiscvCallPlt"), 159 Self::RiscvTlsGdHi20 => write!(f, "RiscvTlsGdHi20"), 160 Self::RiscvGotHi20 => write!(f, "RiscvGotHi20"), 161 Self::RiscvPCRelHi20 => write!(f, "RiscvPCRelHi20"), 162 Self::RiscvPCRelLo12I => write!(f, "RiscvPCRelLo12I"), 163 Self::ElfX86_64TlsGd => write!(f, "ElfX86_64TlsGd"), 164 Self::MachOX86_64Tlv => write!(f, "MachOX86_64Tlv"), 165 Self::MachOAarch64TlsAdrPage21 => write!(f, "MachOAarch64TlsAdrPage21"), 166 Self::MachOAarch64TlsAdrPageOff12 => write!(f, "MachOAarch64TlsAdrPageOff12"), 167 Self::Aarch64TlsDescAdrPage21 => write!(f, "Aarch64TlsDescAdrPage21"), 168 Self::Aarch64TlsDescLd64Lo12 => write!(f, "Aarch64TlsDescLd64Lo12"), 169 Self::Aarch64TlsDescAddLo12 => write!(f, "Aarch64TlsDescAddLo12"), 170 Self::Aarch64TlsDescCall => write!(f, "Aarch64TlsDescCall"), 171 Self::Aarch64AdrGotPage21 => write!(f, "Aarch64AdrGotPage21"), 172 Self::Aarch64Ld64GotLo12Nc => write!(f, "Aarch64AdrGotLo12Nc"), 173 Self::Aarch64AdrPrelPgHi21 => write!(f, "Aarch64AdrPrelPgHi21"), 174 Self::Aarch64AddAbsLo12Nc => write!(f, "Aarch64AddAbsLo12Nc"), 175 Self::S390xTlsGd64 => write!(f, "TlsGd64"), 176 Self::S390xTlsGdCall => write!(f, "TlsGdCall"), 177 Self::PulleyPcRel => write!(f, "PulleyPcRel"), 178 Self::PulleyCallIndirectHost => write!(f, "PulleyCallIndirectHost"), 179 } 180 } 181 } 182 183 /// Container for information about a vector of compiled code and its supporting read-only data. 184 /// 185 /// The code starts at offset 0 and is followed optionally by relocatable jump tables and copyable 186 /// (raw binary) read-only data. Any padding between sections is always part of the section that 187 /// precedes the boundary between the sections. 188 #[derive(Debug, PartialEq)] 189 pub struct CodeInfo { 190 /// Number of bytes in total. 191 pub total_size: CodeOffset, 192 } 193