wasmer_compiler/
relocation.rs1use crate::lib::std::fmt;
13use crate::lib::std::vec::Vec;
14use crate::section::SectionIndex;
15use crate::{Addend, CodeOffset, JumpTable};
16use wasmer_types::entity::PrimaryMap;
17use wasmer_types::LocalFunctionIndex;
18use wasmer_vm::libcalls::LibCall;
19
20#[derive(rkyv::Serialize, rkyv::Deserialize, rkyv::Archive, Copy, Clone, Debug, PartialEq, Eq)]
22pub enum RelocationKind {
23 Abs4,
25 Abs8,
27 X86PCRel4,
29 X86PCRel8,
31 X86PCRelRodata4,
33 X86CallPCRel4,
35 X86CallPLTRel4,
37 X86GOTPCRel4,
39 Arm32Call,
41 Arm64Call,
43 Arm64Movw0,
45 Arm64Movw1,
47 Arm64Movw2,
49 Arm64Movw3,
51 ElfX86_64TlsGd,
55 }
58
59impl fmt::Display for RelocationKind {
60 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
63 match *self {
64 Self::Abs4 => write!(f, "Abs4"),
65 Self::Abs8 => write!(f, "Abs8"),
66 Self::X86PCRel4 => write!(f, "PCRel4"),
67 Self::X86PCRel8 => write!(f, "PCRel8"),
68 Self::X86PCRelRodata4 => write!(f, "PCRelRodata4"),
69 Self::X86CallPCRel4 => write!(f, "CallPCRel4"),
70 Self::X86CallPLTRel4 => write!(f, "CallPLTRel4"),
71 Self::X86GOTPCRel4 => write!(f, "GOTPCRel4"),
72 Self::Arm32Call | Self::Arm64Call => write!(f, "Call"),
73 Self::Arm64Movw0 => write!(f, "Arm64MovwG0"),
74 Self::Arm64Movw1 => write!(f, "Arm64MovwG1"),
75 Self::Arm64Movw2 => write!(f, "Arm64MovwG2"),
76 Self::Arm64Movw3 => write!(f, "Arm64MovwG3"),
77 Self::ElfX86_64TlsGd => write!(f, "ElfX86_64TlsGd"),
78 }
80 }
81}
82
83#[derive(rkyv::Serialize, rkyv::Deserialize, rkyv::Archive, Debug, Clone, PartialEq, Eq)]
85pub struct Relocation {
86 pub kind: RelocationKind,
88 pub reloc_target: RelocationTarget,
90 pub offset: CodeOffset,
92 pub addend: Addend,
94}
95
96#[derive(rkyv::Serialize, rkyv::Deserialize, rkyv::Archive, Debug, Copy, Clone, PartialEq, Eq)]
98pub enum RelocationTarget {
99 LocalFunc(LocalFunctionIndex),
101 LibCall(LibCall),
103 JumpTable(LocalFunctionIndex, JumpTable),
105 CustomSection(SectionIndex),
107}
108
109impl Relocation {
110 pub fn for_address(&self, start: usize, target_func_address: u64) -> (usize, u64) {
115 match self.kind {
116 RelocationKind::Abs8
117 | RelocationKind::Arm64Movw0
118 | RelocationKind::Arm64Movw1
119 | RelocationKind::Arm64Movw2
120 | RelocationKind::Arm64Movw3 => {
121 let reloc_address = start + self.offset as usize;
122 let reloc_addend = self.addend as isize;
123 let reloc_abs = target_func_address
124 .checked_add(reloc_addend as u64)
125 .unwrap();
126 (reloc_address, reloc_abs)
127 }
128 RelocationKind::X86PCRel4 => {
129 let reloc_address = start + self.offset as usize;
130 let reloc_addend = self.addend as isize;
131 let reloc_delta_u32 = (target_func_address as u32)
132 .wrapping_sub(reloc_address as u32)
133 .checked_add(reloc_addend as u32)
134 .unwrap();
135 (reloc_address, reloc_delta_u32 as u64)
136 }
137 RelocationKind::X86PCRel8 => {
138 let reloc_address = start + self.offset as usize;
139 let reloc_addend = self.addend as isize;
140 let reloc_delta = target_func_address
141 .wrapping_sub(reloc_address as u64)
142 .checked_add(reloc_addend as u64)
143 .unwrap();
144 (reloc_address, reloc_delta)
145 }
146 RelocationKind::X86CallPCRel4 | RelocationKind::X86CallPLTRel4 => {
147 let reloc_address = start + self.offset as usize;
148 let reloc_addend = self.addend as isize;
149 let reloc_delta_u32 = (target_func_address as u32)
150 .wrapping_sub(reloc_address as u32)
151 .wrapping_add(reloc_addend as u32);
152 (reloc_address, reloc_delta_u32 as u64)
153 }
154 RelocationKind::Arm64Call => {
155 let reloc_address = start + self.offset as usize;
156 let reloc_addend = self.addend as isize;
157 let reloc_delta_u32 = target_func_address
158 .wrapping_sub(reloc_address as u64)
159 .wrapping_add(reloc_addend as u64);
160 (reloc_address, reloc_delta_u32)
161 }
162 _ => panic!("Relocation kind unsupported"),
166 }
167 }
168}
169
170pub type Relocations = PrimaryMap<LocalFunctionIndex, Vec<Relocation>>;