hc_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 = "enable-serde", derive(Serialize, Deserialize))]
24#[derive(
25 RkyvSerialize, RkyvDeserialize, Archive, rkyv::CheckBytes, Copy, Clone, Debug, PartialEq, Eq,
26)]
27#[archive(as = "Self")]
28#[repr(u8)]
29pub enum RelocationKind {
30 Abs4,
32 Abs8,
34 X86PCRel4,
36 X86PCRel8,
38 X86CallPCRel4,
40 X86CallPLTRel4,
42 X86GOTPCRel4,
44 Arm32Call,
46 Arm64Call,
48 Arm64Movw0,
50 Arm64Movw1,
52 Arm64Movw2,
54 Arm64Movw3,
56 RiscvPCRelHi20,
58 RiscvPCRelLo12I,
60 RiscvCall,
62 ElfX86_64TlsGd,
64 }
67
68impl fmt::Display for RelocationKind {
69 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
72 match *self {
73 Self::Abs4 => write!(f, "Abs4"),
74 Self::Abs8 => write!(f, "Abs8"),
75 Self::X86PCRel4 => write!(f, "PCRel4"),
76 Self::X86PCRel8 => write!(f, "PCRel8"),
77 Self::X86CallPCRel4 => write!(f, "CallPCRel4"),
78 Self::X86CallPLTRel4 => write!(f, "CallPLTRel4"),
79 Self::X86GOTPCRel4 => write!(f, "GOTPCRel4"),
80 Self::Arm32Call | Self::Arm64Call | Self::RiscvCall => write!(f, "Call"),
81 Self::Arm64Movw0 => write!(f, "Arm64MovwG0"),
82 Self::Arm64Movw1 => write!(f, "Arm64MovwG1"),
83 Self::Arm64Movw2 => write!(f, "Arm64MovwG2"),
84 Self::Arm64Movw3 => write!(f, "Arm64MovwG3"),
85 Self::ElfX86_64TlsGd => write!(f, "ElfX86_64TlsGd"),
86 Self::RiscvPCRelHi20 => write!(f, "RiscvPCRelHi20"),
87 Self::RiscvPCRelLo12I => write!(f, "RiscvPCRelLo12I"),
88 }
90 }
91}
92
93#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
95#[derive(RkyvSerialize, RkyvDeserialize, Archive, Debug, Clone, PartialEq, Eq)]
96#[archive_attr(derive(rkyv::CheckBytes, Debug))]
97pub struct Relocation {
98 pub kind: RelocationKind,
100 pub reloc_target: RelocationTarget,
102 pub offset: CodeOffset,
104 pub addend: Addend,
106}
107
108#[allow(missing_docs)]
110pub trait RelocationLike {
111 fn kind(&self) -> RelocationKind;
112 fn reloc_target(&self) -> RelocationTarget;
113 fn offset(&self) -> CodeOffset;
114 fn addend(&self) -> Addend;
115
116 fn for_address(&self, start: usize, target_func_address: u64) -> (usize, u64) {
121 match self.kind() {
122 RelocationKind::Abs8
123 | RelocationKind::Arm64Movw0
124 | RelocationKind::Arm64Movw1
125 | RelocationKind::Arm64Movw2
126 | RelocationKind::Arm64Movw3
127 | RelocationKind::RiscvPCRelLo12I => {
128 let reloc_address = start + self.offset() as usize;
129 let reloc_addend = self.addend() as isize;
130 let reloc_abs = target_func_address
131 .checked_add(reloc_addend as u64)
132 .unwrap();
133 (reloc_address, reloc_abs)
134 }
135 RelocationKind::X86PCRel4 => {
136 let reloc_address = start + self.offset() as usize;
137 let reloc_addend = self.addend() as isize;
138 let reloc_delta_u32 = (target_func_address as u32)
139 .wrapping_sub(reloc_address as u32)
140 .checked_add(reloc_addend as u32)
141 .unwrap();
142 (reloc_address, reloc_delta_u32 as u64)
143 }
144 RelocationKind::X86PCRel8 => {
145 let reloc_address = start + self.offset() as usize;
146 let reloc_addend = self.addend() as isize;
147 let reloc_delta = target_func_address
148 .wrapping_sub(reloc_address as u64)
149 .checked_add(reloc_addend as u64)
150 .unwrap();
151 (reloc_address, reloc_delta)
152 }
153 RelocationKind::X86CallPCRel4 | RelocationKind::X86CallPLTRel4 => {
154 let reloc_address = start + self.offset() as usize;
155 let reloc_addend = self.addend() as isize;
156 let reloc_delta_u32 = (target_func_address as u32)
157 .wrapping_sub(reloc_address as u32)
158 .wrapping_add(reloc_addend as u32);
159 (reloc_address, reloc_delta_u32 as u64)
160 }
161 RelocationKind::Arm64Call
162 | RelocationKind::RiscvCall
163 | RelocationKind::RiscvPCRelHi20 => {
164 let reloc_address = start + self.offset() as usize;
165 let reloc_addend = self.addend() as isize;
166 let reloc_delta_u32 = target_func_address
167 .wrapping_sub(reloc_address as u64)
168 .wrapping_add(reloc_addend as u64);
169 (reloc_address, reloc_delta_u32)
170 }
171 _ => panic!("Relocation kind unsupported"),
172 }
173 }
174}
175
176impl RelocationLike for Relocation {
177 fn kind(&self) -> RelocationKind {
178 self.kind
179 }
180
181 fn reloc_target(&self) -> RelocationTarget {
182 self.reloc_target
183 }
184
185 fn offset(&self) -> CodeOffset {
186 self.offset
187 }
188
189 fn addend(&self) -> Addend {
190 self.addend
191 }
192}
193
194impl RelocationLike for ArchivedRelocation {
195 fn kind(&self) -> RelocationKind {
196 self.kind
197 }
198
199 fn reloc_target(&self) -> RelocationTarget {
200 self.reloc_target
201 }
202
203 fn offset(&self) -> CodeOffset {
204 self.offset
205 }
206
207 fn addend(&self) -> Addend {
208 self.addend
209 }
210}
211
212#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
214#[derive(
215 RkyvSerialize, RkyvDeserialize, Archive, rkyv::CheckBytes, Debug, Copy, Clone, PartialEq, Eq,
216)]
217#[archive(as = "Self")]
218#[repr(u8)]
219pub enum RelocationTarget {
220 LocalFunc(LocalFunctionIndex),
222 LibCall(LibCall),
224 CustomSection(SectionIndex),
226}
227
228pub type Relocations = PrimaryMap<LocalFunctionIndex, Vec<Relocation>>;