1 | use alloc::fmt; |
2 | use alloc::vec::Vec; |
3 | use core::fmt::Debug; |
4 | use core::slice; |
5 | |
6 | use crate::elf; |
7 | use crate::endian::{self, Endianness}; |
8 | use crate::pod::Pod; |
9 | use crate::read::{ |
10 | self, Error, ReadRef, Relocation, RelocationEncoding, RelocationKind, RelocationTarget, |
11 | SectionIndex, SymbolIndex, |
12 | }; |
13 | |
14 | use super::{ElfFile, FileHeader, SectionHeader, SectionTable}; |
15 | |
16 | /// A mapping from section index to associated relocation sections. |
17 | #[derive (Debug)] |
18 | pub struct RelocationSections { |
19 | relocations: Vec<usize>, |
20 | } |
21 | |
22 | impl RelocationSections { |
23 | /// Create a new mapping using the section table. |
24 | /// |
25 | /// Skips relocation sections that do not use the given symbol table section. |
26 | pub fn parse<'data, Elf: FileHeader, R: ReadRef<'data>>( |
27 | endian: Elf::Endian, |
28 | sections: &SectionTable<'data, Elf, R>, |
29 | symbol_section: SectionIndex, |
30 | ) -> read::Result<Self> { |
31 | let mut relocations = vec![0; sections.len()]; |
32 | for (index, section) in sections.iter().enumerate().rev() { |
33 | let sh_type = section.sh_type(endian); |
34 | if sh_type == elf::SHT_REL || sh_type == elf::SHT_RELA { |
35 | // The symbol indices used in relocations must be for the symbol table |
36 | // we are expecting to use. |
37 | let sh_link = SectionIndex(section.sh_link(endian) as usize); |
38 | if sh_link != symbol_section { |
39 | continue; |
40 | } |
41 | |
42 | let sh_info = section.sh_info(endian) as usize; |
43 | if sh_info == 0 { |
44 | // Skip dynamic relocations. |
45 | continue; |
46 | } |
47 | if sh_info >= relocations.len() { |
48 | return Err(Error("Invalid ELF sh_info for relocation section" )); |
49 | } |
50 | |
51 | // Handle multiple relocation sections by chaining them. |
52 | let next = relocations[sh_info]; |
53 | relocations[sh_info] = index; |
54 | relocations[index] = next; |
55 | } |
56 | } |
57 | Ok(Self { relocations }) |
58 | } |
59 | |
60 | /// Given a section index, return the section index of the associated relocation section. |
61 | /// |
62 | /// This may also be called with a relocation section index, and it will return the |
63 | /// next associated relocation section. |
64 | pub fn get(&self, index: usize) -> Option<usize> { |
65 | self.relocations.get(index).cloned().filter(|x| *x != 0) |
66 | } |
67 | } |
68 | |
69 | pub(super) enum ElfRelaIterator<'data, Elf: FileHeader> { |
70 | Rel(slice::Iter<'data, Elf::Rel>), |
71 | Rela(slice::Iter<'data, Elf::Rela>), |
72 | } |
73 | |
74 | impl<'data, Elf: FileHeader> ElfRelaIterator<'data, Elf> { |
75 | fn is_rel(&self) -> bool { |
76 | match self { |
77 | ElfRelaIterator::Rel(_) => true, |
78 | ElfRelaIterator::Rela(_) => false, |
79 | } |
80 | } |
81 | } |
82 | |
83 | impl<'data, Elf: FileHeader> Iterator for ElfRelaIterator<'data, Elf> { |
84 | type Item = Elf::Rela; |
85 | |
86 | fn next(&mut self) -> Option<Self::Item> { |
87 | match self { |
88 | ElfRelaIterator::Rel(ref mut i: &mut Iter<'_, ::Rel>) => i.next().cloned().map(Self::Item::from), |
89 | ElfRelaIterator::Rela(ref mut i: &mut Iter<'_, ::Rela>) => i.next().cloned(), |
90 | } |
91 | } |
92 | } |
93 | |
94 | /// An iterator for the dynamic relocations in an [`ElfFile32`](super::ElfFile32). |
95 | pub type ElfDynamicRelocationIterator32<'data, 'file, Endian = Endianness, R = &'data [u8]> = |
96 | ElfDynamicRelocationIterator<'data, 'file, elf::FileHeader32<Endian>, R>; |
97 | /// An iterator for the dynamic relocations in an [`ElfFile64`](super::ElfFile64). |
98 | pub type ElfDynamicRelocationIterator64<'data, 'file, Endian = Endianness, R = &'data [u8]> = |
99 | ElfDynamicRelocationIterator<'data, 'file, elf::FileHeader64<Endian>, R>; |
100 | |
101 | /// An iterator for the dynamic relocations in an [`ElfFile`]. |
102 | pub struct ElfDynamicRelocationIterator<'data, 'file, Elf, R = &'data [u8]> |
103 | where |
104 | Elf: FileHeader, |
105 | R: ReadRef<'data>, |
106 | { |
107 | /// The current relocation section index. |
108 | pub(super) section_index: SectionIndex, |
109 | pub(super) file: &'file ElfFile<'data, Elf, R>, |
110 | pub(super) relocations: Option<ElfRelaIterator<'data, Elf>>, |
111 | } |
112 | |
113 | impl<'data, 'file, Elf, R> Iterator for ElfDynamicRelocationIterator<'data, 'file, Elf, R> |
114 | where |
115 | Elf: FileHeader, |
116 | R: ReadRef<'data>, |
117 | { |
118 | type Item = (u64, Relocation); |
119 | |
120 | fn next(&mut self) -> Option<Self::Item> { |
121 | let endian = self.file.endian; |
122 | loop { |
123 | if let Some(ref mut relocations) = self.relocations { |
124 | if let Some(reloc) = relocations.next() { |
125 | let relocation = |
126 | parse_relocation(self.file.header, endian, reloc, relocations.is_rel()); |
127 | return Some((reloc.r_offset(endian).into(), relocation)); |
128 | } |
129 | self.relocations = None; |
130 | } |
131 | |
132 | let section = self.file.sections.section(self.section_index).ok()?; |
133 | self.section_index.0 += 1; |
134 | |
135 | let sh_link = SectionIndex(section.sh_link(endian) as usize); |
136 | if sh_link != self.file.dynamic_symbols.section() { |
137 | continue; |
138 | } |
139 | |
140 | match section.sh_type(endian) { |
141 | elf::SHT_REL => { |
142 | if let Ok(relocations) = section.data_as_array(endian, self.file.data) { |
143 | self.relocations = Some(ElfRelaIterator::Rel(relocations.iter())); |
144 | } |
145 | } |
146 | elf::SHT_RELA => { |
147 | if let Ok(relocations) = section.data_as_array(endian, self.file.data) { |
148 | self.relocations = Some(ElfRelaIterator::Rela(relocations.iter())); |
149 | } |
150 | } |
151 | _ => {} |
152 | } |
153 | } |
154 | } |
155 | } |
156 | |
157 | impl<'data, 'file, Elf, R> fmt::Debug for ElfDynamicRelocationIterator<'data, 'file, Elf, R> |
158 | where |
159 | Elf: FileHeader, |
160 | R: ReadRef<'data>, |
161 | { |
162 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
163 | f.debug_struct(name:"ElfDynamicRelocationIterator" ).finish() |
164 | } |
165 | } |
166 | |
167 | /// An iterator for the relocations for an [`ElfSection32`](super::ElfSection32). |
168 | pub type ElfSectionRelocationIterator32<'data, 'file, Endian = Endianness, R = &'data [u8]> = |
169 | ElfSectionRelocationIterator<'data, 'file, elf::FileHeader32<Endian>, R>; |
170 | /// An iterator for the relocations for an [`ElfSection64`](super::ElfSection64). |
171 | pub type ElfSectionRelocationIterator64<'data, 'file, Endian = Endianness, R = &'data [u8]> = |
172 | ElfSectionRelocationIterator<'data, 'file, elf::FileHeader64<Endian>, R>; |
173 | |
174 | /// An iterator for the relocations for an [`ElfSection`](super::ElfSection). |
175 | pub struct ElfSectionRelocationIterator<'data, 'file, Elf, R = &'data [u8]> |
176 | where |
177 | Elf: FileHeader, |
178 | R: ReadRef<'data>, |
179 | { |
180 | /// The current pointer in the chain of relocation sections. |
181 | pub(super) section_index: SectionIndex, |
182 | pub(super) file: &'file ElfFile<'data, Elf, R>, |
183 | pub(super) relocations: Option<ElfRelaIterator<'data, Elf>>, |
184 | } |
185 | |
186 | impl<'data, 'file, Elf, R> Iterator for ElfSectionRelocationIterator<'data, 'file, Elf, R> |
187 | where |
188 | Elf: FileHeader, |
189 | R: ReadRef<'data>, |
190 | { |
191 | type Item = (u64, Relocation); |
192 | |
193 | fn next(&mut self) -> Option<Self::Item> { |
194 | let endian = self.file.endian; |
195 | loop { |
196 | if let Some(ref mut relocations) = self.relocations { |
197 | if let Some(reloc) = relocations.next() { |
198 | let relocation = |
199 | parse_relocation(self.file.header, endian, reloc, relocations.is_rel()); |
200 | return Some((reloc.r_offset(endian).into(), relocation)); |
201 | } |
202 | self.relocations = None; |
203 | } |
204 | self.section_index = SectionIndex(self.file.relocations.get(self.section_index.0)?); |
205 | // The construction of RelocationSections ensures section_index is valid. |
206 | let section = self.file.sections.section(self.section_index).unwrap(); |
207 | match section.sh_type(endian) { |
208 | elf::SHT_REL => { |
209 | if let Ok(relocations) = section.data_as_array(endian, self.file.data) { |
210 | self.relocations = Some(ElfRelaIterator::Rel(relocations.iter())); |
211 | } |
212 | } |
213 | elf::SHT_RELA => { |
214 | if let Ok(relocations) = section.data_as_array(endian, self.file.data) { |
215 | self.relocations = Some(ElfRelaIterator::Rela(relocations.iter())); |
216 | } |
217 | } |
218 | _ => {} |
219 | } |
220 | } |
221 | } |
222 | } |
223 | |
224 | impl<'data, 'file, Elf, R> fmt::Debug for ElfSectionRelocationIterator<'data, 'file, Elf, R> |
225 | where |
226 | Elf: FileHeader, |
227 | R: ReadRef<'data>, |
228 | { |
229 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
230 | f.debug_struct(name:"ElfSectionRelocationIterator" ).finish() |
231 | } |
232 | } |
233 | |
234 | fn parse_relocation<Elf: FileHeader>( |
235 | header: &Elf, |
236 | endian: Elf::Endian, |
237 | reloc: Elf::Rela, |
238 | implicit_addend: bool, |
239 | ) -> Relocation { |
240 | let mut encoding = RelocationEncoding::Generic; |
241 | let is_mips64el = header.is_mips64el(endian); |
242 | let (kind, size) = match header.e_machine(endian) { |
243 | elf::EM_AARCH64 => { |
244 | if header.is_type_64() { |
245 | match reloc.r_type(endian, false) { |
246 | elf::R_AARCH64_ABS64 => (RelocationKind::Absolute, 64), |
247 | elf::R_AARCH64_ABS32 => (RelocationKind::Absolute, 32), |
248 | elf::R_AARCH64_ABS16 => (RelocationKind::Absolute, 16), |
249 | elf::R_AARCH64_PREL64 => (RelocationKind::Relative, 64), |
250 | elf::R_AARCH64_PREL32 => (RelocationKind::Relative, 32), |
251 | elf::R_AARCH64_PREL16 => (RelocationKind::Relative, 16), |
252 | elf::R_AARCH64_CALL26 => { |
253 | encoding = RelocationEncoding::AArch64Call; |
254 | (RelocationKind::PltRelative, 26) |
255 | } |
256 | r_type => (RelocationKind::Elf(r_type), 0), |
257 | } |
258 | } else { |
259 | match reloc.r_type(endian, false) { |
260 | elf::R_AARCH64_P32_ABS32 => (RelocationKind::Absolute, 32), |
261 | r_type => (RelocationKind::Elf(r_type), 0), |
262 | } |
263 | } |
264 | } |
265 | elf::EM_ARM => match reloc.r_type(endian, false) { |
266 | elf::R_ARM_ABS32 => (RelocationKind::Absolute, 32), |
267 | r_type => (RelocationKind::Elf(r_type), 0), |
268 | }, |
269 | elf::EM_AVR => match reloc.r_type(endian, false) { |
270 | elf::R_AVR_32 => (RelocationKind::Absolute, 32), |
271 | elf::R_AVR_16 => (RelocationKind::Absolute, 16), |
272 | r_type => (RelocationKind::Elf(r_type), 0), |
273 | }, |
274 | elf::EM_BPF => match reloc.r_type(endian, false) { |
275 | elf::R_BPF_64_64 => (RelocationKind::Absolute, 64), |
276 | elf::R_BPF_64_32 => (RelocationKind::Absolute, 32), |
277 | r_type => (RelocationKind::Elf(r_type), 0), |
278 | }, |
279 | elf::EM_CSKY => match reloc.r_type(endian, false) { |
280 | elf::R_CKCORE_ADDR32 => (RelocationKind::Absolute, 32), |
281 | elf::R_CKCORE_PCREL32 => (RelocationKind::Relative, 32), |
282 | r_type => (RelocationKind::Elf(r_type), 0), |
283 | }, |
284 | elf::EM_386 => match reloc.r_type(endian, false) { |
285 | elf::R_386_32 => (RelocationKind::Absolute, 32), |
286 | elf::R_386_PC32 => (RelocationKind::Relative, 32), |
287 | elf::R_386_GOT32 => (RelocationKind::Got, 32), |
288 | elf::R_386_PLT32 => (RelocationKind::PltRelative, 32), |
289 | elf::R_386_GOTOFF => (RelocationKind::GotBaseOffset, 32), |
290 | elf::R_386_GOTPC => (RelocationKind::GotBaseRelative, 32), |
291 | elf::R_386_16 => (RelocationKind::Absolute, 16), |
292 | elf::R_386_PC16 => (RelocationKind::Relative, 16), |
293 | elf::R_386_8 => (RelocationKind::Absolute, 8), |
294 | elf::R_386_PC8 => (RelocationKind::Relative, 8), |
295 | r_type => (RelocationKind::Elf(r_type), 0), |
296 | }, |
297 | elf::EM_X86_64 => match reloc.r_type(endian, false) { |
298 | elf::R_X86_64_64 => (RelocationKind::Absolute, 64), |
299 | elf::R_X86_64_PC32 => (RelocationKind::Relative, 32), |
300 | elf::R_X86_64_GOT32 => (RelocationKind::Got, 32), |
301 | elf::R_X86_64_PLT32 => (RelocationKind::PltRelative, 32), |
302 | elf::R_X86_64_GOTPCREL => (RelocationKind::GotRelative, 32), |
303 | elf::R_X86_64_32 => (RelocationKind::Absolute, 32), |
304 | elf::R_X86_64_32S => { |
305 | encoding = RelocationEncoding::X86Signed; |
306 | (RelocationKind::Absolute, 32) |
307 | } |
308 | elf::R_X86_64_16 => (RelocationKind::Absolute, 16), |
309 | elf::R_X86_64_PC16 => (RelocationKind::Relative, 16), |
310 | elf::R_X86_64_8 => (RelocationKind::Absolute, 8), |
311 | elf::R_X86_64_PC8 => (RelocationKind::Relative, 8), |
312 | r_type => (RelocationKind::Elf(r_type), 0), |
313 | }, |
314 | elf::EM_HEXAGON => match reloc.r_type(endian, false) { |
315 | elf::R_HEX_32 => (RelocationKind::Absolute, 32), |
316 | r_type => (RelocationKind::Elf(r_type), 0), |
317 | }, |
318 | elf::EM_LOONGARCH => match reloc.r_type(endian, false) { |
319 | elf::R_LARCH_32 => (RelocationKind::Absolute, 32), |
320 | elf::R_LARCH_64 => (RelocationKind::Absolute, 64), |
321 | elf::R_LARCH_32_PCREL => (RelocationKind::Relative, 32), |
322 | elf::R_LARCH_64_PCREL => (RelocationKind::Relative, 64), |
323 | elf::R_LARCH_B16 => { |
324 | encoding = RelocationEncoding::LoongArchBranch; |
325 | (RelocationKind::Relative, 16) |
326 | } |
327 | elf::R_LARCH_B21 => { |
328 | encoding = RelocationEncoding::LoongArchBranch; |
329 | (RelocationKind::Relative, 21) |
330 | } |
331 | elf::R_LARCH_B26 => { |
332 | encoding = RelocationEncoding::LoongArchBranch; |
333 | (RelocationKind::Relative, 26) |
334 | } |
335 | r_type => (RelocationKind::Elf(r_type), 0), |
336 | }, |
337 | elf::EM_MIPS => match reloc.r_type(endian, is_mips64el) { |
338 | elf::R_MIPS_16 => (RelocationKind::Absolute, 16), |
339 | elf::R_MIPS_32 => (RelocationKind::Absolute, 32), |
340 | elf::R_MIPS_64 => (RelocationKind::Absolute, 64), |
341 | r_type => (RelocationKind::Elf(r_type), 0), |
342 | }, |
343 | elf::EM_MSP430 => match reloc.r_type(endian, false) { |
344 | elf::R_MSP430_32 => (RelocationKind::Absolute, 32), |
345 | elf::R_MSP430_16_BYTE => (RelocationKind::Absolute, 16), |
346 | r_type => (RelocationKind::Elf(r_type), 0), |
347 | }, |
348 | elf::EM_PPC => match reloc.r_type(endian, false) { |
349 | elf::R_PPC_ADDR32 => (RelocationKind::Absolute, 32), |
350 | r_type => (RelocationKind::Elf(r_type), 0), |
351 | }, |
352 | elf::EM_PPC64 => match reloc.r_type(endian, false) { |
353 | elf::R_PPC64_ADDR32 => (RelocationKind::Absolute, 32), |
354 | elf::R_PPC64_ADDR64 => (RelocationKind::Absolute, 64), |
355 | r_type => (RelocationKind::Elf(r_type), 0), |
356 | }, |
357 | elf::EM_RISCV => match reloc.r_type(endian, false) { |
358 | elf::R_RISCV_32 => (RelocationKind::Absolute, 32), |
359 | elf::R_RISCV_64 => (RelocationKind::Absolute, 64), |
360 | r_type => (RelocationKind::Elf(r_type), 0), |
361 | }, |
362 | elf::EM_S390 => match reloc.r_type(endian, false) { |
363 | elf::R_390_8 => (RelocationKind::Absolute, 8), |
364 | elf::R_390_16 => (RelocationKind::Absolute, 16), |
365 | elf::R_390_32 => (RelocationKind::Absolute, 32), |
366 | elf::R_390_64 => (RelocationKind::Absolute, 64), |
367 | elf::R_390_PC16 => (RelocationKind::Relative, 16), |
368 | elf::R_390_PC32 => (RelocationKind::Relative, 32), |
369 | elf::R_390_PC64 => (RelocationKind::Relative, 64), |
370 | elf::R_390_PC16DBL => { |
371 | encoding = RelocationEncoding::S390xDbl; |
372 | (RelocationKind::Relative, 16) |
373 | } |
374 | elf::R_390_PC32DBL => { |
375 | encoding = RelocationEncoding::S390xDbl; |
376 | (RelocationKind::Relative, 32) |
377 | } |
378 | elf::R_390_PLT16DBL => { |
379 | encoding = RelocationEncoding::S390xDbl; |
380 | (RelocationKind::PltRelative, 16) |
381 | } |
382 | elf::R_390_PLT32DBL => { |
383 | encoding = RelocationEncoding::S390xDbl; |
384 | (RelocationKind::PltRelative, 32) |
385 | } |
386 | elf::R_390_GOT16 => (RelocationKind::Got, 16), |
387 | elf::R_390_GOT32 => (RelocationKind::Got, 32), |
388 | elf::R_390_GOT64 => (RelocationKind::Got, 64), |
389 | elf::R_390_GOTENT => { |
390 | encoding = RelocationEncoding::S390xDbl; |
391 | (RelocationKind::GotRelative, 32) |
392 | } |
393 | elf::R_390_GOTOFF16 => (RelocationKind::GotBaseOffset, 16), |
394 | elf::R_390_GOTOFF32 => (RelocationKind::GotBaseOffset, 32), |
395 | elf::R_390_GOTOFF64 => (RelocationKind::GotBaseOffset, 64), |
396 | elf::R_390_GOTPC => (RelocationKind::GotBaseRelative, 64), |
397 | elf::R_390_GOTPCDBL => { |
398 | encoding = RelocationEncoding::S390xDbl; |
399 | (RelocationKind::GotBaseRelative, 32) |
400 | } |
401 | r_type => (RelocationKind::Elf(r_type), 0), |
402 | }, |
403 | elf::EM_SBF => match reloc.r_type(endian, false) { |
404 | elf::R_SBF_64_64 => (RelocationKind::Absolute, 64), |
405 | elf::R_SBF_64_32 => (RelocationKind::Absolute, 32), |
406 | r_type => (RelocationKind::Elf(r_type), 0), |
407 | }, |
408 | elf::EM_SHARC => match reloc.r_type(endian, false) { |
409 | elf::R_SHARC_ADDR24_V3 => { |
410 | encoding = RelocationEncoding::SharcTypeA; |
411 | (RelocationKind::Absolute, 24) |
412 | } |
413 | elf::R_SHARC_ADDR32_V3 => { |
414 | encoding = RelocationEncoding::SharcTypeA; |
415 | (RelocationKind::Absolute, 32) |
416 | } |
417 | elf::R_SHARC_ADDR_VAR_V3 => { |
418 | encoding = RelocationEncoding::Generic; |
419 | (RelocationKind::Absolute, 32) |
420 | } |
421 | elf::R_SHARC_PCRSHORT_V3 => { |
422 | encoding = RelocationEncoding::SharcTypeA; |
423 | (RelocationKind::Relative, 6) |
424 | } |
425 | elf::R_SHARC_PCRLONG_V3 => { |
426 | encoding = RelocationEncoding::SharcTypeA; |
427 | (RelocationKind::Relative, 24) |
428 | } |
429 | elf::R_SHARC_DATA6_V3 => { |
430 | encoding = RelocationEncoding::SharcTypeA; |
431 | (RelocationKind::Absolute, 6) |
432 | } |
433 | elf::R_SHARC_DATA16_V3 => { |
434 | encoding = RelocationEncoding::SharcTypeA; |
435 | (RelocationKind::Absolute, 16) |
436 | } |
437 | elf::R_SHARC_DATA6_VISA_V3 => { |
438 | encoding = RelocationEncoding::SharcTypeB; |
439 | (RelocationKind::Absolute, 6) |
440 | } |
441 | elf::R_SHARC_DATA7_VISA_V3 => { |
442 | encoding = RelocationEncoding::SharcTypeB; |
443 | (RelocationKind::Absolute, 7) |
444 | } |
445 | elf::R_SHARC_DATA16_VISA_V3 => { |
446 | encoding = RelocationEncoding::SharcTypeB; |
447 | (RelocationKind::Absolute, 16) |
448 | } |
449 | elf::R_SHARC_PCR6_VISA_V3 => { |
450 | encoding = RelocationEncoding::SharcTypeB; |
451 | (RelocationKind::Relative, 16) |
452 | } |
453 | elf::R_SHARC_ADDR_VAR16_V3 => { |
454 | encoding = RelocationEncoding::Generic; |
455 | (RelocationKind::Absolute, 16) |
456 | } |
457 | r_type => (RelocationKind::Elf(r_type), 0), |
458 | }, |
459 | elf::EM_SPARC | elf::EM_SPARC32PLUS | elf::EM_SPARCV9 => { |
460 | match reloc.r_type(endian, false) { |
461 | elf::R_SPARC_32 | elf::R_SPARC_UA32 => (RelocationKind::Absolute, 32), |
462 | elf::R_SPARC_64 | elf::R_SPARC_UA64 => (RelocationKind::Absolute, 64), |
463 | r_type => (RelocationKind::Elf(r_type), 0), |
464 | } |
465 | } |
466 | elf::EM_XTENSA => match reloc.r_type(endian, false) { |
467 | elf::R_XTENSA_32 => (RelocationKind::Absolute, 32), |
468 | elf::R_XTENSA_32_PCREL => (RelocationKind::Relative, 32), |
469 | r_type => (RelocationKind::Elf(r_type), 0), |
470 | }, |
471 | _ => (RelocationKind::Elf(reloc.r_type(endian, false)), 0), |
472 | }; |
473 | let sym = reloc.r_sym(endian, is_mips64el) as usize; |
474 | let target = if sym == 0 { |
475 | RelocationTarget::Absolute |
476 | } else { |
477 | RelocationTarget::Symbol(SymbolIndex(sym)) |
478 | }; |
479 | Relocation { |
480 | kind, |
481 | encoding, |
482 | size, |
483 | target, |
484 | addend: reloc.r_addend(endian).into(), |
485 | implicit_addend, |
486 | } |
487 | } |
488 | |
489 | /// A trait for generic access to [`elf::Rel32`] and [`elf::Rel64`]. |
490 | #[allow (missing_docs)] |
491 | pub trait Rel: Debug + Pod + Clone { |
492 | type Word: Into<u64>; |
493 | type Sword: Into<i64>; |
494 | type Endian: endian::Endian; |
495 | |
496 | fn r_offset(&self, endian: Self::Endian) -> Self::Word; |
497 | fn r_info(&self, endian: Self::Endian) -> Self::Word; |
498 | fn r_sym(&self, endian: Self::Endian) -> u32; |
499 | fn r_type(&self, endian: Self::Endian) -> u32; |
500 | } |
501 | |
502 | impl<Endian: endian::Endian> Rel for elf::Rel32<Endian> { |
503 | type Word = u32; |
504 | type Sword = i32; |
505 | type Endian = Endian; |
506 | |
507 | #[inline ] |
508 | fn r_offset(&self, endian: Self::Endian) -> Self::Word { |
509 | self.r_offset.get(endian) |
510 | } |
511 | |
512 | #[inline ] |
513 | fn r_info(&self, endian: Self::Endian) -> Self::Word { |
514 | self.r_info.get(endian) |
515 | } |
516 | |
517 | #[inline ] |
518 | fn r_sym(&self, endian: Self::Endian) -> u32 { |
519 | self.r_sym(endian) |
520 | } |
521 | |
522 | #[inline ] |
523 | fn r_type(&self, endian: Self::Endian) -> u32 { |
524 | self.r_type(endian) |
525 | } |
526 | } |
527 | |
528 | impl<Endian: endian::Endian> Rel for elf::Rel64<Endian> { |
529 | type Word = u64; |
530 | type Sword = i64; |
531 | type Endian = Endian; |
532 | |
533 | #[inline ] |
534 | fn r_offset(&self, endian: Self::Endian) -> Self::Word { |
535 | self.r_offset.get(endian) |
536 | } |
537 | |
538 | #[inline ] |
539 | fn r_info(&self, endian: Self::Endian) -> Self::Word { |
540 | self.r_info.get(endian) |
541 | } |
542 | |
543 | #[inline ] |
544 | fn r_sym(&self, endian: Self::Endian) -> u32 { |
545 | self.r_sym(endian) |
546 | } |
547 | |
548 | #[inline ] |
549 | fn r_type(&self, endian: Self::Endian) -> u32 { |
550 | self.r_type(endian) |
551 | } |
552 | } |
553 | |
554 | /// A trait for generic access to [`elf::Rela32`] and [`elf::Rela64`]. |
555 | #[allow (missing_docs)] |
556 | pub trait Rela: Debug + Pod + Clone { |
557 | type Word: Into<u64>; |
558 | type Sword: Into<i64>; |
559 | type Endian: endian::Endian; |
560 | |
561 | fn r_offset(&self, endian: Self::Endian) -> Self::Word; |
562 | fn r_info(&self, endian: Self::Endian, is_mips64el: bool) -> Self::Word; |
563 | fn r_addend(&self, endian: Self::Endian) -> Self::Sword; |
564 | fn r_sym(&self, endian: Self::Endian, is_mips64el: bool) -> u32; |
565 | fn r_type(&self, endian: Self::Endian, is_mips64el: bool) -> u32; |
566 | } |
567 | |
568 | impl<Endian: endian::Endian> Rela for elf::Rela32<Endian> { |
569 | type Word = u32; |
570 | type Sword = i32; |
571 | type Endian = Endian; |
572 | |
573 | #[inline ] |
574 | fn r_offset(&self, endian: Self::Endian) -> Self::Word { |
575 | self.r_offset.get(endian) |
576 | } |
577 | |
578 | #[inline ] |
579 | fn r_info(&self, endian: Self::Endian, _is_mips64el: bool) -> Self::Word { |
580 | self.r_info.get(endian) |
581 | } |
582 | |
583 | #[inline ] |
584 | fn r_addend(&self, endian: Self::Endian) -> Self::Sword { |
585 | self.r_addend.get(endian) |
586 | } |
587 | |
588 | #[inline ] |
589 | fn r_sym(&self, endian: Self::Endian, _is_mips64el: bool) -> u32 { |
590 | self.r_sym(endian) |
591 | } |
592 | |
593 | #[inline ] |
594 | fn r_type(&self, endian: Self::Endian, _is_mips64el: bool) -> u32 { |
595 | self.r_type(endian) |
596 | } |
597 | } |
598 | |
599 | impl<Endian: endian::Endian> Rela for elf::Rela64<Endian> { |
600 | type Word = u64; |
601 | type Sword = i64; |
602 | type Endian = Endian; |
603 | |
604 | #[inline ] |
605 | fn r_offset(&self, endian: Self::Endian) -> Self::Word { |
606 | self.r_offset.get(endian) |
607 | } |
608 | |
609 | #[inline ] |
610 | fn r_info(&self, endian: Self::Endian, is_mips64el: bool) -> Self::Word { |
611 | self.get_r_info(endian, is_mips64el) |
612 | } |
613 | |
614 | #[inline ] |
615 | fn r_addend(&self, endian: Self::Endian) -> Self::Sword { |
616 | self.r_addend.get(endian) |
617 | } |
618 | |
619 | #[inline ] |
620 | fn r_sym(&self, endian: Self::Endian, is_mips64el: bool) -> u32 { |
621 | self.r_sym(endian, is_mips64el) |
622 | } |
623 | |
624 | #[inline ] |
625 | fn r_type(&self, endian: Self::Endian, is_mips64el: bool) -> u32 { |
626 | self.r_type(endian, is_mips64el) |
627 | } |
628 | } |
629 | |