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     /// AArch64 GOT Low bits
86 
87     /// Set the LD/ST immediate field to bits 11:3 of X. No overflow check; check that X&7 = 0
88     /// 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)
89     Aarch64Ld64GotLo12Nc,
90 
91     /// RISC-V Call PLT: 32-bit PC-relative function call, macros call, tail (PIC)
92     ///
93     /// Despite having PLT in the name, this relocation is also used for normal calls.
94     /// The non-PLT version of this relocation has been deprecated.
95     ///
96     /// This is the `R_RISCV_CALL_PLT` relocation from the RISC-V ELF psABI document.
97     /// <https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-elf.adoc#procedure-calls>
98     RiscvCallPlt,
99 
100     /// RISC-V TLS GD: High 20 bits of 32-bit PC-relative TLS GD GOT reference,
101     ///
102     /// This is the `R_RISCV_TLS_GD_HI20` relocation from the RISC-V ELF psABI document.
103     /// <https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-elf.adoc#global-dynamic>
104     RiscvTlsGdHi20,
105 
106     /// Low 12 bits of a 32-bit PC-relative relocation (I-Type instruction)
107     ///
108     /// This is the `R_RISCV_PCREL_LO12_I` relocation from the RISC-V ELF psABI document.
109     /// <https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-elf.adoc#pc-relative-symbol-addresses>
110     RiscvPCRelLo12I,
111 
112     /// High 20 bits of a 32-bit PC-relative GOT offset relocation
113     ///
114     /// This is the `R_RISCV_GOT_HI20` relocation from the RISC-V ELF psABI document.
115     /// <https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-elf.adoc#pc-relative-symbol-addresses>
116     RiscvGotHi20,
117 
118     /// s390x TLS GD64 - 64-bit offset of tls_index for GD symbol in GOT
119     S390xTlsGd64,
120     /// s390x TLS GDCall - marker to enable optimization of TLS calls
121     S390xTlsGdCall,
122 
123     /// Pulley - call a host function indirectly where the embedder resolving
124     /// this relocation needs to fill the 8-bit immediate that's part of the
125     /// `call_indirect_host` opcode (an opaque identifier used by the host).
126     PulleyCallIndirectHost,
127 }
128 
129 impl fmt::Display for Reloc {
130     /// Display trait implementation drops the arch, since its used in contexts where the arch is
131     /// already unambiguous, e.g. clif syntax with isa specified. In other contexts, use Debug.
132     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
133         match *self {
134             Self::Abs4 => write!(f, "Abs4"),
135             Self::Abs8 => write!(f, "Abs8"),
136             Self::S390xPCRel32Dbl => write!(f, "PCRel32Dbl"),
137             Self::S390xPLTRel32Dbl => write!(f, "PLTRel32Dbl"),
138             Self::X86PCRel4 => write!(f, "PCRel4"),
139             Self::X86CallPCRel4 => write!(f, "CallPCRel4"),
140             Self::X86CallPLTRel4 => write!(f, "CallPLTRel4"),
141             Self::X86GOTPCRel4 => write!(f, "GOTPCRel4"),
142             Self::X86SecRel => write!(f, "SecRel"),
143             Self::Arm32Call | Self::Arm64Call => write!(f, "Call"),
144             Self::RiscvCallPlt => write!(f, "RiscvCallPlt"),
145             Self::RiscvTlsGdHi20 => write!(f, "RiscvTlsGdHi20"),
146             Self::RiscvGotHi20 => write!(f, "RiscvGotHi20"),
147             Self::RiscvPCRelLo12I => write!(f, "RiscvPCRelLo12I"),
148             Self::ElfX86_64TlsGd => write!(f, "ElfX86_64TlsGd"),
149             Self::MachOX86_64Tlv => write!(f, "MachOX86_64Tlv"),
150             Self::MachOAarch64TlsAdrPage21 => write!(f, "MachOAarch64TlsAdrPage21"),
151             Self::MachOAarch64TlsAdrPageOff12 => write!(f, "MachOAarch64TlsAdrPageOff12"),
152             Self::Aarch64TlsDescAdrPage21 => write!(f, "Aarch64TlsDescAdrPage21"),
153             Self::Aarch64TlsDescLd64Lo12 => write!(f, "Aarch64TlsDescLd64Lo12"),
154             Self::Aarch64TlsDescAddLo12 => write!(f, "Aarch64TlsDescAddLo12"),
155             Self::Aarch64TlsDescCall => write!(f, "Aarch64TlsDescCall"),
156             Self::Aarch64AdrGotPage21 => write!(f, "Aarch64AdrGotPage21"),
157             Self::Aarch64Ld64GotLo12Nc => write!(f, "Aarch64AdrGotLo12Nc"),
158             Self::S390xTlsGd64 => write!(f, "TlsGd64"),
159             Self::S390xTlsGdCall => write!(f, "TlsGdCall"),
160             Self::PulleyCallIndirectHost => write!(f, "PulleyCallIndirectHost"),
161         }
162     }
163 }
164 
165 /// Container for information about a vector of compiled code and its supporting read-only data.
166 ///
167 /// The code starts at offset 0 and is followed optionally by relocatable jump tables and copyable
168 /// (raw binary) read-only data.  Any padding between sections is always part of the section that
169 /// precedes the boundary between the sections.
170 #[derive(Debug, PartialEq)]
171 pub struct CodeInfo {
172     /// Number of bytes in total.
173     pub total_size: CodeOffset,
174 }
175