1use alloc::fmt;
2use alloc::vec::Vec;
3use core::fmt::Debug;
4use core::slice;
5
6use crate::elf;
7use crate::endian::{self, Endianness};
8use crate::pod::Pod;
9use crate::read::{
10 self, Error, ReadRef, Relocation, RelocationEncoding, RelocationFlags, RelocationKind,
11 RelocationTarget, SectionIndex, SymbolIndex,
12};
13
14use super::{ElfFile, FileHeader, SectionHeader, SectionTable};
15
16#[derive(Debug, Default)]
18pub struct RelocationSections {
19 relocations: Vec<usize>,
20}
21
22impl RelocationSections {
23 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 let sh_link = section.link(endian);
38 if sh_link != symbol_section {
39 continue;
40 }
41
42 let sh_info = section.info_link(endian);
43 if sh_info == SectionIndex(0) {
44 continue;
46 }
47 if sh_info.0 >= relocations.len() {
48 return Err(Error("Invalid ELF sh_info for relocation section"));
49 }
50
51 let sh_info_type = sections.section(sh_info)?.sh_type(endian);
54 if sh_info_type == elf::SHT_REL || sh_info_type == elf::SHT_RELA {
55 return Err(Error("Unsupported ELF sh_info for relocation section"));
56 }
57
58 let next = relocations[sh_info.0];
60 relocations[sh_info.0] = index;
61 relocations[index] = next;
62 }
63 }
64 Ok(Self { relocations })
65 }
66
67 pub fn get(&self, index: SectionIndex) -> Option<SectionIndex> {
72 self.relocations
73 .get(index.0)
74 .cloned()
75 .filter(|x| *x != 0)
76 .map(SectionIndex)
77 }
78}
79
80pub(super) enum ElfRelaIterator<'data, Elf: FileHeader> {
81 Rel(slice::Iter<'data, Elf::Rel>),
82 Rela(slice::Iter<'data, Elf::Rela>),
83}
84
85impl<'data, Elf: FileHeader> ElfRelaIterator<'data, Elf> {
86 fn is_rel(&self) -> bool {
87 match self {
88 ElfRelaIterator::Rel(_) => true,
89 ElfRelaIterator::Rela(_) => false,
90 }
91 }
92}
93
94impl<'data, Elf: FileHeader> Iterator for ElfRelaIterator<'data, Elf> {
95 type Item = Elf::Rela;
96
97 fn next(&mut self) -> Option<Self::Item> {
98 match self {
99 ElfRelaIterator::Rel(ref mut i) => i.next().cloned().map(Self::Item::from),
100 ElfRelaIterator::Rela(ref mut i) => i.next().cloned(),
101 }
102 }
103}
104
105pub type ElfDynamicRelocationIterator32<'data, 'file, Endian = Endianness, R = &'data [u8]> =
107 ElfDynamicRelocationIterator<'data, 'file, elf::FileHeader32<Endian>, R>;
108pub type ElfDynamicRelocationIterator64<'data, 'file, Endian = Endianness, R = &'data [u8]> =
110 ElfDynamicRelocationIterator<'data, 'file, elf::FileHeader64<Endian>, R>;
111
112pub struct ElfDynamicRelocationIterator<'data, 'file, Elf, R = &'data [u8]>
114where
115 Elf: FileHeader,
116 R: ReadRef<'data>,
117{
118 pub(super) section_index: SectionIndex,
120 pub(super) file: &'file ElfFile<'data, Elf, R>,
121 pub(super) relocations: Option<ElfRelaIterator<'data, Elf>>,
122}
123
124impl<'data, 'file, Elf, R> Iterator for ElfDynamicRelocationIterator<'data, 'file, Elf, R>
125where
126 Elf: FileHeader,
127 R: ReadRef<'data>,
128{
129 type Item = (u64, Relocation);
130
131 fn next(&mut self) -> Option<Self::Item> {
132 let endian = self.file.endian;
133 loop {
134 if let Some(ref mut relocations) = self.relocations {
135 if let Some(reloc) = relocations.next() {
136 let relocation =
137 parse_relocation(self.file.header, endian, reloc, relocations.is_rel());
138 return Some((reloc.r_offset(endian).into(), relocation));
139 }
140 self.relocations = None;
141 }
142
143 let section = self.file.sections.section(self.section_index).ok()?;
144 self.section_index.0 += 1;
145
146 if section.link(endian) != self.file.dynamic_symbols.section() {
147 continue;
148 }
149
150 match section.sh_type(endian) {
151 elf::SHT_REL => {
152 if let Ok(relocations) = section.data_as_array(endian, self.file.data) {
153 self.relocations = Some(ElfRelaIterator::Rel(relocations.iter()));
154 }
155 }
156 elf::SHT_RELA => {
157 if let Ok(relocations) = section.data_as_array(endian, self.file.data) {
158 self.relocations = Some(ElfRelaIterator::Rela(relocations.iter()));
159 }
160 }
161 _ => {}
162 }
163 }
164 }
165}
166
167impl<'data, 'file, Elf, R> fmt::Debug for ElfDynamicRelocationIterator<'data, 'file, Elf, R>
168where
169 Elf: FileHeader,
170 R: ReadRef<'data>,
171{
172 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
173 f.debug_struct("ElfDynamicRelocationIterator").finish()
174 }
175}
176
177pub type ElfSectionRelocationIterator32<'data, 'file, Endian = Endianness, R = &'data [u8]> =
179 ElfSectionRelocationIterator<'data, 'file, elf::FileHeader32<Endian>, R>;
180pub type ElfSectionRelocationIterator64<'data, 'file, Endian = Endianness, R = &'data [u8]> =
182 ElfSectionRelocationIterator<'data, 'file, elf::FileHeader64<Endian>, R>;
183
184pub struct ElfSectionRelocationIterator<'data, 'file, Elf, R = &'data [u8]>
186where
187 Elf: FileHeader,
188 R: ReadRef<'data>,
189{
190 pub(super) section_index: SectionIndex,
192 pub(super) file: &'file ElfFile<'data, Elf, R>,
193 pub(super) relocations: Option<ElfRelaIterator<'data, Elf>>,
194}
195
196impl<'data, 'file, Elf, R> Iterator for ElfSectionRelocationIterator<'data, 'file, Elf, R>
197where
198 Elf: FileHeader,
199 R: ReadRef<'data>,
200{
201 type Item = (u64, Relocation);
202
203 fn next(&mut self) -> Option<Self::Item> {
204 let endian = self.file.endian;
205 loop {
206 if let Some(ref mut relocations) = self.relocations {
207 if let Some(reloc) = relocations.next() {
208 let relocation =
209 parse_relocation(self.file.header, endian, reloc, relocations.is_rel());
210 return Some((reloc.r_offset(endian).into(), relocation));
211 }
212 self.relocations = None;
213 }
214 self.section_index = self.file.relocations.get(self.section_index)?;
215 let section = self.file.sections.section(self.section_index).unwrap();
217 match section.sh_type(endian) {
218 elf::SHT_REL => {
219 if let Ok(relocations) = section.data_as_array(endian, self.file.data) {
220 self.relocations = Some(ElfRelaIterator::Rel(relocations.iter()));
221 }
222 }
223 elf::SHT_RELA => {
224 if let Ok(relocations) = section.data_as_array(endian, self.file.data) {
225 self.relocations = Some(ElfRelaIterator::Rela(relocations.iter()));
226 }
227 }
228 _ => {}
229 }
230 }
231 }
232}
233
234impl<'data, 'file, Elf, R> fmt::Debug for ElfSectionRelocationIterator<'data, 'file, Elf, R>
235where
236 Elf: FileHeader,
237 R: ReadRef<'data>,
238{
239 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
240 f.debug_struct("ElfSectionRelocationIterator").finish()
241 }
242}
243
244fn parse_relocation<Elf: FileHeader>(
245 header: &Elf,
246 endian: Elf::Endian,
247 reloc: Elf::Rela,
248 implicit_addend: bool,
249) -> Relocation {
250 use RelocationEncoding as E;
251 use RelocationKind as K;
252
253 let is_mips64el = header.is_mips64el(endian);
254 let r_type = reloc.r_type(endian, is_mips64el);
255 let flags = RelocationFlags::Elf { r_type };
256 let g = E::Generic;
257 let unknown = (K::Unknown, E::Generic, 0);
258 let (kind, encoding, size) = match header.e_machine(endian) {
259 elf::EM_AARCH64 => {
260 if header.is_type_64() {
261 match r_type {
262 elf::R_AARCH64_ABS64 => (K::Absolute, g, 64),
263 elf::R_AARCH64_ABS32 => (K::Absolute, g, 32),
264 elf::R_AARCH64_ABS16 => (K::Absolute, g, 16),
265 elf::R_AARCH64_PREL64 => (K::Relative, g, 64),
266 elf::R_AARCH64_PREL32 => (K::Relative, g, 32),
267 elf::R_AARCH64_PREL16 => (K::Relative, g, 16),
268 elf::R_AARCH64_CALL26 => (K::PltRelative, E::AArch64Call, 26),
269 _ => unknown,
270 }
271 } else {
272 match r_type {
273 elf::R_AARCH64_P32_ABS32 => (K::Absolute, g, 32),
274 _ => unknown,
275 }
276 }
277 }
278 elf::EM_ARM => match r_type {
279 elf::R_ARM_ABS32 => (K::Absolute, g, 32),
280 _ => unknown,
281 },
282 elf::EM_AVR => match r_type {
283 elf::R_AVR_32 => (K::Absolute, g, 32),
284 elf::R_AVR_16 => (K::Absolute, g, 16),
285 _ => unknown,
286 },
287 elf::EM_BPF => match r_type {
288 elf::R_BPF_64_64 => (K::Absolute, g, 64),
289 elf::R_BPF_64_32 => (K::Absolute, g, 32),
290 _ => unknown,
291 },
292 elf::EM_CSKY => match r_type {
293 elf::R_CKCORE_ADDR32 => (K::Absolute, g, 32),
294 elf::R_CKCORE_PCREL32 => (K::Relative, g, 32),
295 _ => unknown,
296 },
297 elf::EM_MCST_ELBRUS => match r_type {
298 elf::R_E2K_32_ABS => (K::Absolute, g, 32),
299 elf::R_E2K_64_ABS => (K::Absolute, g, 64),
300 elf::R_E2K_64_ABS_LIT => (K::Absolute, E::E2KLit, 64),
301 elf::R_E2K_DISP => (K::Relative, E::E2KDisp, 28),
302 elf::R_E2K_GOT => (K::Got, g, 32),
303 _ => unknown,
304 },
305 elf::EM_386 => match r_type {
306 elf::R_386_32 => (K::Absolute, g, 32),
307 elf::R_386_PC32 => (K::Relative, g, 32),
308 elf::R_386_GOT32 => (K::Got, g, 32),
309 elf::R_386_PLT32 => (K::PltRelative, g, 32),
310 elf::R_386_GOTOFF => (K::GotBaseOffset, g, 32),
311 elf::R_386_GOTPC => (K::GotBaseRelative, g, 32),
312 elf::R_386_16 => (K::Absolute, g, 16),
313 elf::R_386_PC16 => (K::Relative, g, 16),
314 elf::R_386_8 => (K::Absolute, g, 8),
315 elf::R_386_PC8 => (K::Relative, g, 8),
316 _ => unknown,
317 },
318 elf::EM_X86_64 => match r_type {
319 elf::R_X86_64_64 => (K::Absolute, g, 64),
320 elf::R_X86_64_PC32 => (K::Relative, g, 32),
321 elf::R_X86_64_GOT32 => (K::Got, g, 32),
322 elf::R_X86_64_PLT32 => (K::PltRelative, g, 32),
323 elf::R_X86_64_GOTPCREL => (K::GotRelative, g, 32),
324 elf::R_X86_64_32 => (K::Absolute, g, 32),
325 elf::R_X86_64_32S => (K::Absolute, E::X86Signed, 32),
326 elf::R_X86_64_16 => (K::Absolute, g, 16),
327 elf::R_X86_64_PC16 => (K::Relative, g, 16),
328 elf::R_X86_64_8 => (K::Absolute, g, 8),
329 elf::R_X86_64_PC8 => (K::Relative, g, 8),
330 _ => unknown,
331 },
332 elf::EM_HEXAGON => match r_type {
333 elf::R_HEX_32 => (K::Absolute, g, 32),
334 _ => unknown,
335 },
336 elf::EM_LOONGARCH => match r_type {
337 elf::R_LARCH_32 => (K::Absolute, g, 32),
338 elf::R_LARCH_64 => (K::Absolute, g, 64),
339 elf::R_LARCH_32_PCREL => (K::Relative, g, 32),
340 elf::R_LARCH_64_PCREL => (K::Relative, g, 64),
341 elf::R_LARCH_B16 => (K::Relative, E::LoongArchBranch, 16),
342 elf::R_LARCH_B21 => (K::Relative, E::LoongArchBranch, 21),
343 elf::R_LARCH_B26 => (K::Relative, E::LoongArchBranch, 26),
344 _ => unknown,
345 },
346 elf::EM_68K => match r_type {
347 elf::R_68K_32 => (K::Absolute, g, 32),
348 elf::R_68K_16 => (K::Absolute, g, 16),
349 elf::R_68K_8 => (K::Absolute, g, 8),
350 elf::R_68K_PC32 => (K::Relative, g, 32),
351 elf::R_68K_PC16 => (K::Relative, g, 16),
352 elf::R_68K_PC8 => (K::Relative, g, 8),
353 elf::R_68K_GOT32O => (K::Got, g, 32),
354 elf::R_68K_GOT16O => (K::Got, g, 16),
355 elf::R_68K_GOT8O => (K::Got, g, 8),
356 elf::R_68K_GOT32 => (K::GotRelative, g, 32),
357 elf::R_68K_GOT16 => (K::GotRelative, g, 16),
358 elf::R_68K_GOT8 => (K::GotRelative, g, 8),
359 elf::R_68K_PLT32 => (K::PltRelative, g, 32),
360 elf::R_68K_PLT16 => (K::PltRelative, g, 16),
361 elf::R_68K_PLT8 => (K::PltRelative, g, 8),
362 _ => unknown,
363 },
364 elf::EM_MIPS => match r_type {
365 elf::R_MIPS_16 => (K::Absolute, g, 16),
366 elf::R_MIPS_32 => (K::Absolute, g, 32),
367 elf::R_MIPS_64 => (K::Absolute, g, 64),
368 _ => unknown,
369 },
370 elf::EM_MSP430 => match r_type {
371 elf::R_MSP430_32 => (K::Absolute, g, 32),
372 elf::R_MSP430_16_BYTE => (K::Absolute, g, 16),
373 _ => unknown,
374 },
375 elf::EM_PPC => match r_type {
376 elf::R_PPC_ADDR32 => (K::Absolute, g, 32),
377 _ => unknown,
378 },
379 elf::EM_PPC64 => match r_type {
380 elf::R_PPC64_ADDR32 => (K::Absolute, g, 32),
381 elf::R_PPC64_ADDR64 => (K::Absolute, g, 64),
382 _ => unknown,
383 },
384 elf::EM_RISCV => match r_type {
385 elf::R_RISCV_32 => (K::Absolute, g, 32),
386 elf::R_RISCV_64 => (K::Absolute, g, 64),
387 _ => unknown,
388 },
389 elf::EM_S390 => match r_type {
390 elf::R_390_8 => (K::Absolute, g, 8),
391 elf::R_390_16 => (K::Absolute, g, 16),
392 elf::R_390_32 => (K::Absolute, g, 32),
393 elf::R_390_64 => (K::Absolute, g, 64),
394 elf::R_390_PC16 => (K::Relative, g, 16),
395 elf::R_390_PC32 => (K::Relative, g, 32),
396 elf::R_390_PC64 => (K::Relative, g, 64),
397 elf::R_390_PC16DBL => (K::Relative, E::S390xDbl, 16),
398 elf::R_390_PC32DBL => (K::Relative, E::S390xDbl, 32),
399 elf::R_390_PLT16DBL => (K::PltRelative, E::S390xDbl, 16),
400 elf::R_390_PLT32DBL => (K::PltRelative, E::S390xDbl, 32),
401 elf::R_390_GOT16 => (K::Got, g, 16),
402 elf::R_390_GOT32 => (K::Got, g, 32),
403 elf::R_390_GOT64 => (K::Got, g, 64),
404 elf::R_390_GOTENT => (K::GotRelative, E::S390xDbl, 32),
405 elf::R_390_GOTOFF16 => (K::GotBaseOffset, g, 16),
406 elf::R_390_GOTOFF32 => (K::GotBaseOffset, g, 32),
407 elf::R_390_GOTOFF64 => (K::GotBaseOffset, g, 64),
408 elf::R_390_GOTPC => (K::GotBaseRelative, g, 64),
409 elf::R_390_GOTPCDBL => (K::GotBaseRelative, E::S390xDbl, 32),
410 _ => unknown,
411 },
412 elf::EM_SBF => match r_type {
413 elf::R_SBF_64_64 => (K::Absolute, g, 64),
414 elf::R_SBF_64_32 => (K::Absolute, g, 32),
415 _ => unknown,
416 },
417 elf::EM_SHARC => match r_type {
418 elf::R_SHARC_ADDR24_V3 => (K::Absolute, E::SharcTypeA, 24),
419 elf::R_SHARC_ADDR32_V3 => (K::Absolute, E::SharcTypeA, 32),
420 elf::R_SHARC_ADDR_VAR_V3 => (K::Absolute, E::Generic, 32),
421 elf::R_SHARC_PCRSHORT_V3 => (K::Relative, E::SharcTypeA, 6),
422 elf::R_SHARC_PCRLONG_V3 => (K::Relative, E::SharcTypeA, 24),
423 elf::R_SHARC_DATA6_V3 => (K::Absolute, E::SharcTypeA, 6),
424 elf::R_SHARC_DATA16_V3 => (K::Absolute, E::SharcTypeA, 16),
425 elf::R_SHARC_DATA6_VISA_V3 => (K::Absolute, E::SharcTypeB, 6),
426 elf::R_SHARC_DATA7_VISA_V3 => (K::Absolute, E::SharcTypeB, 7),
427 elf::R_SHARC_DATA16_VISA_V3 => (K::Absolute, E::SharcTypeB, 16),
428 elf::R_SHARC_PCR6_VISA_V3 => (K::Relative, E::SharcTypeB, 16),
429 elf::R_SHARC_ADDR_VAR16_V3 => (K::Absolute, E::Generic, 16),
430 _ => unknown,
431 },
432 elf::EM_SPARC | elf::EM_SPARC32PLUS | elf::EM_SPARCV9 => match r_type {
433 elf::R_SPARC_32 | elf::R_SPARC_UA32 => (K::Absolute, g, 32),
434 elf::R_SPARC_64 | elf::R_SPARC_UA64 => (K::Absolute, g, 64),
435 _ => unknown,
436 },
437 elf::EM_XTENSA => match r_type {
438 elf::R_XTENSA_32 => (K::Absolute, g, 32),
439 elf::R_XTENSA_32_PCREL => (K::Relative, g, 32),
440 _ => unknown,
441 },
442 _ => unknown,
443 };
444 let target = match reloc.symbol(endian, is_mips64el) {
445 None => RelocationTarget::Absolute,
446 Some(symbol) => RelocationTarget::Symbol(symbol),
447 };
448 Relocation {
449 kind,
450 encoding,
451 size,
452 target,
453 addend: reloc.r_addend(endian).into(),
454 implicit_addend,
455 flags,
456 }
457}
458
459#[allow(missing_docs)]
461pub trait Rel: Debug + Pod + Clone {
462 type Word: Into<u64>;
463 type Sword: Into<i64>;
464 type Endian: endian::Endian;
465
466 fn r_offset(&self, endian: Self::Endian) -> Self::Word;
467 fn r_info(&self, endian: Self::Endian) -> Self::Word;
468 fn r_sym(&self, endian: Self::Endian) -> u32;
469 fn r_type(&self, endian: Self::Endian) -> u32;
470
471 fn symbol(&self, endian: Self::Endian) -> Option<SymbolIndex> {
475 let sym = self.r_sym(endian);
476 if sym == 0 {
477 None
478 } else {
479 Some(SymbolIndex(sym as usize))
480 }
481 }
482}
483
484impl<Endian: endian::Endian> Rel for elf::Rel32<Endian> {
485 type Word = u32;
486 type Sword = i32;
487 type Endian = Endian;
488
489 #[inline]
490 fn r_offset(&self, endian: Self::Endian) -> Self::Word {
491 self.r_offset.get(endian)
492 }
493
494 #[inline]
495 fn r_info(&self, endian: Self::Endian) -> Self::Word {
496 self.r_info.get(endian)
497 }
498
499 #[inline]
500 fn r_sym(&self, endian: Self::Endian) -> u32 {
501 self.r_sym(endian)
502 }
503
504 #[inline]
505 fn r_type(&self, endian: Self::Endian) -> u32 {
506 self.r_type(endian)
507 }
508}
509
510impl<Endian: endian::Endian> Rel for elf::Rel64<Endian> {
511 type Word = u64;
512 type Sword = i64;
513 type Endian = Endian;
514
515 #[inline]
516 fn r_offset(&self, endian: Self::Endian) -> Self::Word {
517 self.r_offset.get(endian)
518 }
519
520 #[inline]
521 fn r_info(&self, endian: Self::Endian) -> Self::Word {
522 self.r_info.get(endian)
523 }
524
525 #[inline]
526 fn r_sym(&self, endian: Self::Endian) -> u32 {
527 self.r_sym(endian)
528 }
529
530 #[inline]
531 fn r_type(&self, endian: Self::Endian) -> u32 {
532 self.r_type(endian)
533 }
534}
535
536#[allow(missing_docs)]
538pub trait Rela: Debug + Pod + Clone {
539 type Word: Into<u64>;
540 type Sword: Into<i64>;
541 type Endian: endian::Endian;
542
543 fn r_offset(&self, endian: Self::Endian) -> Self::Word;
544 fn r_info(&self, endian: Self::Endian, is_mips64el: bool) -> Self::Word;
545 fn r_addend(&self, endian: Self::Endian) -> Self::Sword;
546 fn r_sym(&self, endian: Self::Endian, is_mips64el: bool) -> u32;
547 fn r_type(&self, endian: Self::Endian, is_mips64el: bool) -> u32;
548
549 fn symbol(&self, endian: Self::Endian, is_mips64el: bool) -> Option<SymbolIndex> {
553 let sym = self.r_sym(endian, is_mips64el);
554 if sym == 0 {
555 None
556 } else {
557 Some(SymbolIndex(sym as usize))
558 }
559 }
560}
561
562impl<Endian: endian::Endian> Rela for elf::Rela32<Endian> {
563 type Word = u32;
564 type Sword = i32;
565 type Endian = Endian;
566
567 #[inline]
568 fn r_offset(&self, endian: Self::Endian) -> Self::Word {
569 self.r_offset.get(endian)
570 }
571
572 #[inline]
573 fn r_info(&self, endian: Self::Endian, _is_mips64el: bool) -> Self::Word {
574 self.r_info.get(endian)
575 }
576
577 #[inline]
578 fn r_addend(&self, endian: Self::Endian) -> Self::Sword {
579 self.r_addend.get(endian)
580 }
581
582 #[inline]
583 fn r_sym(&self, endian: Self::Endian, _is_mips64el: bool) -> u32 {
584 self.r_sym(endian)
585 }
586
587 #[inline]
588 fn r_type(&self, endian: Self::Endian, _is_mips64el: bool) -> u32 {
589 self.r_type(endian)
590 }
591}
592
593impl<Endian: endian::Endian> Rela for elf::Rela64<Endian> {
594 type Word = u64;
595 type Sword = i64;
596 type Endian = Endian;
597
598 #[inline]
599 fn r_offset(&self, endian: Self::Endian) -> Self::Word {
600 self.r_offset.get(endian)
601 }
602
603 #[inline]
604 fn r_info(&self, endian: Self::Endian, is_mips64el: bool) -> Self::Word {
605 self.get_r_info(endian, is_mips64el)
606 }
607
608 #[inline]
609 fn r_addend(&self, endian: Self::Endian) -> Self::Sword {
610 self.r_addend.get(endian)
611 }
612
613 #[inline]
614 fn r_sym(&self, endian: Self::Endian, is_mips64el: bool) -> u32 {
615 self.r_sym(endian, is_mips64el)
616 }
617
618 #[inline]
619 fn r_type(&self, endian: Self::Endian, is_mips64el: bool) -> u32 {
620 self.r_type(endian, is_mips64el)
621 }
622}
623
624#[derive(Debug)]
628pub struct RelrIterator<'data, Elf: FileHeader> {
629 offset: Elf::Word,
630 bits: Elf::Word,
631 count: u8,
632 iter: slice::Iter<'data, Elf::Relr>,
633 endian: Elf::Endian,
634}
635
636impl<'data, Elf: FileHeader> RelrIterator<'data, Elf> {
637 pub fn new(endian: Elf::Endian, data: &'data [Elf::Relr]) -> Self {
639 RelrIterator {
640 offset: Elf::Word::default(),
641 bits: Elf::Word::default(),
642 count: 0,
643 iter: data.iter(),
644 endian,
645 }
646 }
647}
648
649impl<'data, Elf: FileHeader> Iterator for RelrIterator<'data, Elf> {
650 type Item = Elf::Word;
651
652 fn next(&mut self) -> Option<Self::Item> {
653 loop {
654 while self.count > 0 {
655 self.count -= 1;
656 let offset = Elf::Relr::next(&mut self.offset, &mut self.bits);
657 if offset.is_some() {
658 return offset;
659 }
660 }
661 let next = self.iter.next()?.get(self.endian);
662 if next.into() & 1 == 0 {
663 self.offset = next;
664 return Some(next);
665 }
666 self.bits = next;
667 self.count = Elf::Relr::COUNT;
668 }
669 }
670}
671
672#[allow(missing_docs)]
674pub trait Relr: Debug + Pod + Clone {
675 type Word: Into<u64>;
676 type Endian: endian::Endian;
677
678 const COUNT: u8;
680
681 fn get(&self, endian: Self::Endian) -> Self::Word;
685
686 fn next(offset: &mut Self::Word, bits: &mut Self::Word) -> Option<Self::Word>;
693}
694
695impl<Endian: endian::Endian> Relr for elf::Relr32<Endian> {
696 type Word = u32;
697 type Endian = Endian;
698 const COUNT: u8 = 31;
699
700 fn get(&self, endian: Self::Endian) -> Self::Word {
701 self.0.get(endian)
702 }
703
704 fn next(offset: &mut Self::Word, bits: &mut Self::Word) -> Option<Self::Word> {
705 *offset += 4;
706 *bits >>= 1;
707 if *bits & 1 != 0 {
708 Some(*offset)
709 } else {
710 None
711 }
712 }
713}
714
715impl<Endian: endian::Endian> Relr for elf::Relr64<Endian> {
716 type Word = u64;
717 type Endian = Endian;
718 const COUNT: u8 = 63;
719
720 fn get(&self, endian: Self::Endian) -> Self::Word {
721 self.0.get(endian)
722 }
723
724 fn next(offset: &mut Self::Word, bits: &mut Self::Word) -> Option<Self::Word> {
725 *offset += 8;
726 *bits >>= 1;
727 if *bits & 1 != 0 {
728 Some(*offset)
729 } else {
730 None
731 }
732 }
733}