wasmer_types/compilation/
relocation.rs1use super::section::SectionIndex;
13use crate::entity::PrimaryMap;
14use crate::lib::std::fmt;
15use crate::lib::std::vec::Vec;
16use crate::{Addend, CodeOffset};
17use crate::{LibCall, LocalFunctionIndex};
18use rkyv::{Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize};
19#[cfg(feature = "enable-serde")]
20use serde::{Deserialize, Serialize};
21
22#[cfg_attr(feature = "artifact-size", derive(loupe::MemoryUsage))]
24#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
25#[derive(
26 RkyvSerialize, RkyvDeserialize, Archive, rkyv::CheckBytes, Copy, Clone, Debug, PartialEq, Eq,
27)]
28#[archive(as = "Self")]
29#[repr(u8)]
30pub enum RelocationKind {
31 Abs4,
33 Abs8,
35 X86PCRel4,
37 X86PCRel8,
39 X86CallPCRel4,
41 X86CallPLTRel4,
43 X86GOTPCRel4,
45 Arm32Call,
47 Arm64Call,
49 Arm64Movw0,
51 Arm64Movw1,
53 Arm64Movw2,
55 Arm64Movw3,
57 RiscvPCRelHi20,
59 RiscvPCRelLo12I,
61 RiscvCall,
63 ElfX86_64TlsGd,
65 }
68
69impl fmt::Display for RelocationKind {
70 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
73 match *self {
74 Self::Abs4 => write!(f, "Abs4"),
75 Self::Abs8 => write!(f, "Abs8"),
76 Self::X86PCRel4 => write!(f, "PCRel4"),
77 Self::X86PCRel8 => write!(f, "PCRel8"),
78 Self::X86CallPCRel4 => write!(f, "CallPCRel4"),
79 Self::X86CallPLTRel4 => write!(f, "CallPLTRel4"),
80 Self::X86GOTPCRel4 => write!(f, "GOTPCRel4"),
81 Self::Arm32Call | Self::Arm64Call | Self::RiscvCall => write!(f, "Call"),
82 Self::Arm64Movw0 => write!(f, "Arm64MovwG0"),
83 Self::Arm64Movw1 => write!(f, "Arm64MovwG1"),
84 Self::Arm64Movw2 => write!(f, "Arm64MovwG2"),
85 Self::Arm64Movw3 => write!(f, "Arm64MovwG3"),
86 Self::ElfX86_64TlsGd => write!(f, "ElfX86_64TlsGd"),
87 Self::RiscvPCRelHi20 => write!(f, "RiscvPCRelHi20"),
88 Self::RiscvPCRelLo12I => write!(f, "RiscvPCRelLo12I"),
89 }
91 }
92}
93
94#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
96#[cfg_attr(feature = "artifact-size", derive(loupe::MemoryUsage))]
97#[derive(RkyvSerialize, RkyvDeserialize, Archive, Debug, Clone, PartialEq, Eq)]
98#[archive_attr(derive(rkyv::CheckBytes, Debug))]
99pub struct Relocation {
100 pub kind: RelocationKind,
102 pub reloc_target: RelocationTarget,
104 pub offset: CodeOffset,
106 pub addend: Addend,
108}
109
110#[allow(missing_docs)]
112pub trait RelocationLike {
113 fn kind(&self) -> RelocationKind;
114 fn reloc_target(&self) -> RelocationTarget;
115 fn offset(&self) -> CodeOffset;
116 fn addend(&self) -> Addend;
117
118 fn for_address(&self, start: usize, target_func_address: u64) -> (usize, u64) {
123 match self.kind() {
124 RelocationKind::Abs8
125 | RelocationKind::Arm64Movw0
126 | RelocationKind::Arm64Movw1
127 | RelocationKind::Arm64Movw2
128 | RelocationKind::Arm64Movw3
129 | RelocationKind::RiscvPCRelLo12I => {
130 let reloc_address = start + self.offset() as usize;
131 let reloc_addend = self.addend() as isize;
132 let reloc_abs = target_func_address
133 .checked_add(reloc_addend as u64)
134 .unwrap();
135 (reloc_address, reloc_abs)
136 }
137 RelocationKind::X86PCRel4 => {
138 let reloc_address = start + self.offset() as usize;
139 let reloc_addend = self.addend() as isize;
140 let reloc_delta_u32 = (target_func_address as u32)
141 .wrapping_sub(reloc_address as u32)
142 .checked_add(reloc_addend as u32)
143 .unwrap();
144 (reloc_address, reloc_delta_u32 as u64)
145 }
146 RelocationKind::X86PCRel8 => {
147 let reloc_address = start + self.offset() as usize;
148 let reloc_addend = self.addend() as isize;
149 let reloc_delta = target_func_address
150 .wrapping_sub(reloc_address as u64)
151 .checked_add(reloc_addend as u64)
152 .unwrap();
153 (reloc_address, reloc_delta)
154 }
155 RelocationKind::X86CallPCRel4 | RelocationKind::X86CallPLTRel4 => {
156 let reloc_address = start + self.offset() as usize;
157 let reloc_addend = self.addend() as isize;
158 let reloc_delta_u32 = (target_func_address as u32)
159 .wrapping_sub(reloc_address as u32)
160 .wrapping_add(reloc_addend as u32);
161 (reloc_address, reloc_delta_u32 as u64)
162 }
163 RelocationKind::Arm64Call
164 | RelocationKind::RiscvCall
165 | RelocationKind::RiscvPCRelHi20 => {
166 let reloc_address = start + self.offset() as usize;
167 let reloc_addend = self.addend() as isize;
168 let reloc_delta_u32 = target_func_address
169 .wrapping_sub(reloc_address as u64)
170 .wrapping_add(reloc_addend as u64);
171 (reloc_address, reloc_delta_u32)
172 }
173 _ => panic!("Relocation kind unsupported"),
174 }
175 }
176}
177
178impl RelocationLike for Relocation {
179 fn kind(&self) -> RelocationKind {
180 self.kind
181 }
182
183 fn reloc_target(&self) -> RelocationTarget {
184 self.reloc_target
185 }
186
187 fn offset(&self) -> CodeOffset {
188 self.offset
189 }
190
191 fn addend(&self) -> Addend {
192 self.addend
193 }
194}
195
196impl RelocationLike for ArchivedRelocation {
197 fn kind(&self) -> RelocationKind {
198 self.kind
199 }
200
201 fn reloc_target(&self) -> RelocationTarget {
202 self.reloc_target
203 }
204
205 fn offset(&self) -> CodeOffset {
206 self.offset
207 }
208
209 fn addend(&self) -> Addend {
210 self.addend
211 }
212}
213
214#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
216#[cfg_attr(feature = "artifact-size", derive(loupe::MemoryUsage))]
217#[derive(
218 RkyvSerialize, RkyvDeserialize, Archive, rkyv::CheckBytes, Debug, Copy, Clone, PartialEq, Eq,
219)]
220#[archive(as = "Self")]
221#[repr(u8)]
222pub enum RelocationTarget {
223 LocalFunc(LocalFunctionIndex),
225 LibCall(LibCall),
227 CustomSection(SectionIndex),
229}
230
231pub type Relocations = PrimaryMap<LocalFunctionIndex, Vec<Relocation>>;