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, Bytes, Error, ReadError, ReadRef, Relocation, RelocationEncoding, RelocationFlags,
11 RelocationKind, 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 || sh_type == elf::SHT_CREL {
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
55 || sh_info_type == elf::SHT_RELA
56 || sh_info_type == elf::SHT_CREL
57 {
58 return Err(Error("Unsupported ELF sh_info for relocation section"));
59 }
60
61 let next = relocations[sh_info.0];
63 relocations[sh_info.0] = index;
64 relocations[index] = next;
65 }
66 }
67 Ok(Self { relocations })
68 }
69
70 pub fn get(&self, index: SectionIndex) -> Option<SectionIndex> {
75 self.relocations
76 .get(index.0)
77 .cloned()
78 .filter(|x| *x != 0)
79 .map(SectionIndex)
80 }
81}
82
83pub(super) enum ElfRelocationIterator<'data, Elf: FileHeader> {
84 Rel(slice::Iter<'data, Elf::Rel>, Elf::Endian),
85 Rela(slice::Iter<'data, Elf::Rela>, Elf::Endian, bool),
86 Crel(CrelIterator<'data>),
87}
88
89impl<'data, Elf: FileHeader> ElfRelocationIterator<'data, Elf> {
90 fn is_rel(&self) -> bool {
91 match self {
92 ElfRelocationIterator::Rel(..) => true,
93 ElfRelocationIterator::Rela(..) => false,
94 ElfRelocationIterator::Crel(i) => !i.is_rela(),
95 }
96 }
97}
98
99impl<'data, Elf: FileHeader> Iterator for ElfRelocationIterator<'data, Elf> {
100 type Item = Crel;
101
102 fn next(&mut self) -> Option<Self::Item> {
103 match self {
104 ElfRelocationIterator::Rel(ref mut i, endian) => {
105 i.next().map(|r| Crel::from_rel(r, *endian))
106 }
107 ElfRelocationIterator::Rela(ref mut i, endian, is_mips64el) => {
108 i.next().map(|r| Crel::from_rela(r, *endian, *is_mips64el))
109 }
110 ElfRelocationIterator::Crel(ref mut i) => i.next().and_then(Result::ok),
111 }
112 }
113}
114
115pub type ElfDynamicRelocationIterator32<'data, 'file, Endian = Endianness, R = &'data [u8]> =
117 ElfDynamicRelocationIterator<'data, 'file, elf::FileHeader32<Endian>, R>;
118pub type ElfDynamicRelocationIterator64<'data, 'file, Endian = Endianness, R = &'data [u8]> =
120 ElfDynamicRelocationIterator<'data, 'file, elf::FileHeader64<Endian>, R>;
121
122pub struct ElfDynamicRelocationIterator<'data, 'file, Elf, R = &'data [u8]>
124where
125 Elf: FileHeader,
126 R: ReadRef<'data>,
127{
128 pub(super) section_index: SectionIndex,
130 pub(super) file: &'file ElfFile<'data, Elf, R>,
131 pub(super) relocations: Option<ElfRelocationIterator<'data, Elf>>,
132}
133
134impl<'data, 'file, Elf, R> Iterator for ElfDynamicRelocationIterator<'data, 'file, Elf, R>
135where
136 Elf: FileHeader,
137 R: ReadRef<'data>,
138{
139 type Item = (u64, Relocation);
140
141 fn next(&mut self) -> Option<Self::Item> {
142 let endian = self.file.endian;
143 loop {
144 if let Some(ref mut relocations) = self.relocations {
145 if let Some(reloc) = relocations.next() {
146 let relocation =
147 parse_relocation(self.file.header, endian, reloc, relocations.is_rel());
148 return Some((reloc.r_offset, relocation));
149 }
150 self.relocations = None;
151 }
152
153 let section = self.file.sections.section(self.section_index).ok()?;
154 self.section_index.0 += 1;
155
156 if section.link(endian) != self.file.dynamic_symbols.section() {
157 continue;
158 }
159
160 match section.sh_type(endian) {
161 elf::SHT_REL => {
162 if let Ok(relocations) = section.data_as_array(endian, self.file.data) {
163 self.relocations =
164 Some(ElfRelocationIterator::Rel(relocations.iter(), endian));
165 }
166 }
167 elf::SHT_RELA => {
168 if let Ok(relocations) = section.data_as_array(endian, self.file.data) {
169 self.relocations = Some(ElfRelocationIterator::Rela(
170 relocations.iter(),
171 endian,
172 self.file.header.is_mips64el(endian),
173 ));
174 }
175 }
176 elf::SHT_CREL => {
177 if let Ok(data) = section.data(endian, self.file.data) {
178 if let Ok(relocations) = CrelIterator::new(data) {
179 self.relocations = Some(ElfRelocationIterator::Crel(relocations));
180 }
181 }
182 }
183 _ => {}
184 }
185 }
186 }
187}
188
189impl<'data, 'file, Elf, R> fmt::Debug for ElfDynamicRelocationIterator<'data, 'file, Elf, R>
190where
191 Elf: FileHeader,
192 R: ReadRef<'data>,
193{
194 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
195 f.debug_struct("ElfDynamicRelocationIterator").finish()
196 }
197}
198
199pub type ElfSectionRelocationIterator32<'data, 'file, Endian = Endianness, R = &'data [u8]> =
201 ElfSectionRelocationIterator<'data, 'file, elf::FileHeader32<Endian>, R>;
202pub type ElfSectionRelocationIterator64<'data, 'file, Endian = Endianness, R = &'data [u8]> =
204 ElfSectionRelocationIterator<'data, 'file, elf::FileHeader64<Endian>, R>;
205
206pub struct ElfSectionRelocationIterator<'data, 'file, Elf, R = &'data [u8]>
208where
209 Elf: FileHeader,
210 R: ReadRef<'data>,
211{
212 pub(super) section_index: SectionIndex,
214 pub(super) file: &'file ElfFile<'data, Elf, R>,
215 pub(super) relocations: Option<ElfRelocationIterator<'data, Elf>>,
216}
217
218impl<'data, 'file, Elf, R> Iterator for ElfSectionRelocationIterator<'data, 'file, Elf, R>
219where
220 Elf: FileHeader,
221 R: ReadRef<'data>,
222{
223 type Item = (u64, Relocation);
224
225 fn next(&mut self) -> Option<Self::Item> {
226 let endian = self.file.endian;
227 loop {
228 if let Some(ref mut relocations) = self.relocations {
229 if let Some(reloc) = relocations.next() {
230 let relocation =
231 parse_relocation(self.file.header, endian, reloc, relocations.is_rel());
232 return Some((reloc.r_offset, relocation));
233 }
234 self.relocations = None;
235 }
236 self.section_index = self.file.relocations.get(self.section_index)?;
237 let section = self.file.sections.section(self.section_index).unwrap();
239 match section.sh_type(endian) {
240 elf::SHT_REL => {
241 if let Ok(relocations) = section.data_as_array(endian, self.file.data) {
242 self.relocations =
243 Some(ElfRelocationIterator::Rel(relocations.iter(), endian));
244 }
245 }
246 elf::SHT_RELA => {
247 if let Ok(relocations) = section.data_as_array(endian, self.file.data) {
248 self.relocations = Some(ElfRelocationIterator::Rela(
249 relocations.iter(),
250 endian,
251 self.file.header.is_mips64el(endian),
252 ));
253 }
254 }
255 elf::SHT_CREL => {
256 if let Ok(data) = section.data(endian, self.file.data) {
257 if let Ok(relocations) = CrelIterator::new(data) {
258 self.relocations = Some(ElfRelocationIterator::Crel(relocations));
259 }
260 }
261 }
262 _ => {}
263 }
264 }
265 }
266}
267
268impl<'data, 'file, Elf, R> fmt::Debug for ElfSectionRelocationIterator<'data, 'file, Elf, R>
269where
270 Elf: FileHeader,
271 R: ReadRef<'data>,
272{
273 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
274 f.debug_struct("ElfSectionRelocationIterator").finish()
275 }
276}
277
278fn parse_relocation<Elf: FileHeader>(
279 header: &Elf,
280 endian: Elf::Endian,
281 reloc: Crel,
282 implicit_addend: bool,
283) -> Relocation {
284 use RelocationEncoding as E;
285 use RelocationKind as K;
286
287 let r_type = reloc.r_type;
288 let flags = RelocationFlags::Elf { r_type };
289 let g = E::Generic;
290 let unknown = (K::Unknown, E::Generic, 0);
291 let (kind, encoding, size) = match header.e_machine(endian) {
292 elf::EM_AARCH64 => {
293 if header.is_type_64() {
294 match r_type {
295 elf::R_AARCH64_ABS64 => (K::Absolute, g, 64),
296 elf::R_AARCH64_ABS32 => (K::Absolute, g, 32),
297 elf::R_AARCH64_ABS16 => (K::Absolute, g, 16),
298 elf::R_AARCH64_PREL64 => (K::Relative, g, 64),
299 elf::R_AARCH64_PREL32 => (K::Relative, g, 32),
300 elf::R_AARCH64_PREL16 => (K::Relative, g, 16),
301 elf::R_AARCH64_CALL26 => (K::PltRelative, E::AArch64Call, 26),
302 _ => unknown,
303 }
304 } else {
305 match r_type {
306 elf::R_AARCH64_P32_ABS32 => (K::Absolute, g, 32),
307 _ => unknown,
308 }
309 }
310 }
311 elf::EM_ALPHA => match r_type {
312 elf::R_ALPHA_REFLONG => (K::Absolute, g, 32),
314 elf::R_ALPHA_REFQUAD => (K::Absolute, g, 64),
315 elf::R_ALPHA_SREL16 => (K::Relative, g, 16),
317 elf::R_ALPHA_SREL32 => (K::Relative, g, 32),
318 elf::R_ALPHA_SREL64 => (K::Relative, g, 64),
319 _ => unknown,
320 },
321 elf::EM_ARM => match r_type {
322 elf::R_ARM_ABS32 => (K::Absolute, g, 32),
323 _ => unknown,
324 },
325 elf::EM_AVR => match r_type {
326 elf::R_AVR_32 => (K::Absolute, g, 32),
327 elf::R_AVR_16 => (K::Absolute, g, 16),
328 _ => unknown,
329 },
330 elf::EM_BPF => match r_type {
331 elf::R_BPF_64_64 => (K::Absolute, g, 64),
332 elf::R_BPF_64_32 => (K::Absolute, g, 32),
333 _ => unknown,
334 },
335 elf::EM_CSKY => match r_type {
336 elf::R_CKCORE_ADDR32 => (K::Absolute, g, 32),
337 elf::R_CKCORE_PCREL32 => (K::Relative, g, 32),
338 _ => unknown,
339 },
340 elf::EM_MCST_ELBRUS => match r_type {
341 elf::R_E2K_32_ABS => (K::Absolute, g, 32),
342 elf::R_E2K_64_ABS => (K::Absolute, g, 64),
343 elf::R_E2K_64_ABS_LIT => (K::Absolute, E::E2KLit, 64),
344 elf::R_E2K_DISP => (K::Relative, E::E2KDisp, 28),
345 elf::R_E2K_GOT => (K::Got, g, 32),
346 _ => unknown,
347 },
348 elf::EM_386 => match r_type {
349 elf::R_386_32 => (K::Absolute, g, 32),
350 elf::R_386_PC32 => (K::Relative, g, 32),
351 elf::R_386_GOT32 => (K::Got, g, 32),
352 elf::R_386_PLT32 => (K::PltRelative, g, 32),
353 elf::R_386_GOTOFF => (K::GotBaseOffset, g, 32),
354 elf::R_386_GOTPC => (K::GotBaseRelative, g, 32),
355 elf::R_386_16 => (K::Absolute, g, 16),
356 elf::R_386_PC16 => (K::Relative, g, 16),
357 elf::R_386_8 => (K::Absolute, g, 8),
358 elf::R_386_PC8 => (K::Relative, g, 8),
359 _ => unknown,
360 },
361 elf::EM_X86_64 => match r_type {
362 elf::R_X86_64_64 => (K::Absolute, g, 64),
363 elf::R_X86_64_PC32 => (K::Relative, g, 32),
364 elf::R_X86_64_GOT32 => (K::Got, g, 32),
365 elf::R_X86_64_PLT32 => (K::PltRelative, g, 32),
366 elf::R_X86_64_GOTPCREL => (K::GotRelative, g, 32),
367 elf::R_X86_64_32 => (K::Absolute, g, 32),
368 elf::R_X86_64_32S => (K::Absolute, E::X86Signed, 32),
369 elf::R_X86_64_16 => (K::Absolute, g, 16),
370 elf::R_X86_64_PC16 => (K::Relative, g, 16),
371 elf::R_X86_64_8 => (K::Absolute, g, 8),
372 elf::R_X86_64_PC8 => (K::Relative, g, 8),
373 _ => unknown,
374 },
375 elf::EM_HEXAGON => match r_type {
376 elf::R_HEX_32 => (K::Absolute, g, 32),
377 _ => unknown,
378 },
379 elf::EM_LOONGARCH => match r_type {
380 elf::R_LARCH_32 => (K::Absolute, g, 32),
381 elf::R_LARCH_64 => (K::Absolute, g, 64),
382 elf::R_LARCH_32_PCREL => (K::Relative, g, 32),
383 elf::R_LARCH_64_PCREL => (K::Relative, g, 64),
384 elf::R_LARCH_B16 => (K::Relative, E::LoongArchBranch, 16),
385 elf::R_LARCH_B21 => (K::Relative, E::LoongArchBranch, 21),
386 elf::R_LARCH_B26 => (K::Relative, E::LoongArchBranch, 26),
387 _ => unknown,
388 },
389 elf::EM_68K => match r_type {
390 elf::R_68K_32 => (K::Absolute, g, 32),
391 elf::R_68K_16 => (K::Absolute, g, 16),
392 elf::R_68K_8 => (K::Absolute, g, 8),
393 elf::R_68K_PC32 => (K::Relative, g, 32),
394 elf::R_68K_PC16 => (K::Relative, g, 16),
395 elf::R_68K_PC8 => (K::Relative, g, 8),
396 elf::R_68K_GOT32O => (K::Got, g, 32),
397 elf::R_68K_GOT16O => (K::Got, g, 16),
398 elf::R_68K_GOT8O => (K::Got, g, 8),
399 elf::R_68K_GOT32 => (K::GotRelative, g, 32),
400 elf::R_68K_GOT16 => (K::GotRelative, g, 16),
401 elf::R_68K_GOT8 => (K::GotRelative, g, 8),
402 elf::R_68K_PLT32 => (K::PltRelative, g, 32),
403 elf::R_68K_PLT16 => (K::PltRelative, g, 16),
404 elf::R_68K_PLT8 => (K::PltRelative, g, 8),
405 _ => unknown,
406 },
407 elf::EM_MIPS => match r_type {
408 elf::R_MIPS_16 => (K::Absolute, g, 16),
409 elf::R_MIPS_32 => (K::Absolute, g, 32),
410 elf::R_MIPS_64 => (K::Absolute, g, 64),
411 _ => unknown,
412 },
413 elf::EM_MSP430 => match r_type {
414 elf::R_MSP430_32 => (K::Absolute, g, 32),
415 elf::R_MSP430_16_BYTE => (K::Absolute, g, 16),
416 _ => unknown,
417 },
418 elf::EM_PARISC => match r_type {
419 elf::R_PARISC_DIR32 => (K::Absolute, g, 32),
420 elf::R_PARISC_PCREL32 => (K::Relative, g, 32),
421 _ => unknown,
422 },
423 elf::EM_PPC => match r_type {
424 elf::R_PPC_ADDR32 => (K::Absolute, g, 32),
425 _ => unknown,
426 },
427 elf::EM_PPC64 => match r_type {
428 elf::R_PPC64_ADDR32 => (K::Absolute, g, 32),
429 elf::R_PPC64_ADDR64 => (K::Absolute, g, 64),
430 _ => unknown,
431 },
432 elf::EM_RISCV => match r_type {
433 elf::R_RISCV_32 => (K::Absolute, g, 32),
434 elf::R_RISCV_64 => (K::Absolute, g, 64),
435 _ => unknown,
436 },
437 elf::EM_S390 => match r_type {
438 elf::R_390_8 => (K::Absolute, g, 8),
439 elf::R_390_16 => (K::Absolute, g, 16),
440 elf::R_390_32 => (K::Absolute, g, 32),
441 elf::R_390_64 => (K::Absolute, g, 64),
442 elf::R_390_PC16 => (K::Relative, g, 16),
443 elf::R_390_PC32 => (K::Relative, g, 32),
444 elf::R_390_PC64 => (K::Relative, g, 64),
445 elf::R_390_PC16DBL => (K::Relative, E::S390xDbl, 16),
446 elf::R_390_PC32DBL => (K::Relative, E::S390xDbl, 32),
447 elf::R_390_PLT16DBL => (K::PltRelative, E::S390xDbl, 16),
448 elf::R_390_PLT32DBL => (K::PltRelative, E::S390xDbl, 32),
449 elf::R_390_GOT16 => (K::Got, g, 16),
450 elf::R_390_GOT32 => (K::Got, g, 32),
451 elf::R_390_GOT64 => (K::Got, g, 64),
452 elf::R_390_GOTENT => (K::GotRelative, E::S390xDbl, 32),
453 elf::R_390_GOTOFF16 => (K::GotBaseOffset, g, 16),
454 elf::R_390_GOTOFF32 => (K::GotBaseOffset, g, 32),
455 elf::R_390_GOTOFF64 => (K::GotBaseOffset, g, 64),
456 elf::R_390_GOTPC => (K::GotBaseRelative, g, 64),
457 elf::R_390_GOTPCDBL => (K::GotBaseRelative, E::S390xDbl, 32),
458 _ => unknown,
459 },
460 elf::EM_SBF => match r_type {
461 elf::R_SBF_64_64 => (K::Absolute, g, 64),
462 elf::R_SBF_64_32 => (K::Absolute, g, 32),
463 _ => unknown,
464 },
465 elf::EM_SHARC => match r_type {
466 elf::R_SHARC_ADDR24_V3 => (K::Absolute, E::SharcTypeA, 24),
467 elf::R_SHARC_ADDR32_V3 => (K::Absolute, E::SharcTypeA, 32),
468 elf::R_SHARC_ADDR_VAR_V3 => (K::Absolute, E::Generic, 32),
469 elf::R_SHARC_PCRSHORT_V3 => (K::Relative, E::SharcTypeA, 6),
470 elf::R_SHARC_PCRLONG_V3 => (K::Relative, E::SharcTypeA, 24),
471 elf::R_SHARC_DATA6_V3 => (K::Absolute, E::SharcTypeA, 6),
472 elf::R_SHARC_DATA16_V3 => (K::Absolute, E::SharcTypeA, 16),
473 elf::R_SHARC_DATA6_VISA_V3 => (K::Absolute, E::SharcTypeB, 6),
474 elf::R_SHARC_DATA7_VISA_V3 => (K::Absolute, E::SharcTypeB, 7),
475 elf::R_SHARC_DATA16_VISA_V3 => (K::Absolute, E::SharcTypeB, 16),
476 elf::R_SHARC_PCR6_VISA_V3 => (K::Relative, E::SharcTypeB, 16),
477 elf::R_SHARC_ADDR_VAR16_V3 => (K::Absolute, E::Generic, 16),
478 _ => unknown,
479 },
480 elf::EM_SPARC | elf::EM_SPARC32PLUS | elf::EM_SPARCV9 => match r_type {
481 elf::R_SPARC_32 | elf::R_SPARC_UA32 => (K::Absolute, g, 32),
482 elf::R_SPARC_64 | elf::R_SPARC_UA64 => (K::Absolute, g, 64),
483 _ => unknown,
484 },
485 elf::EM_SH => match r_type {
486 elf::R_SH_DIR32 => (K::Absolute, g, 32),
487 elf::R_SH_REL32 => (K::Relative, g, 32),
488 _ => unknown,
489 },
490 elf::EM_XTENSA => match r_type {
491 elf::R_XTENSA_32 => (K::Absolute, g, 32),
492 elf::R_XTENSA_32_PCREL => (K::Relative, g, 32),
493 _ => unknown,
494 },
495 _ => unknown,
496 };
497 let target = match reloc.symbol() {
498 None => RelocationTarget::Absolute,
499 Some(symbol) => RelocationTarget::Symbol(symbol),
500 };
501 Relocation {
502 kind,
503 encoding,
504 size,
505 target,
506 addend: reloc.r_addend,
507 implicit_addend,
508 flags,
509 }
510}
511
512#[allow(missing_docs)]
514pub trait Rel: Debug + Pod + Clone {
515 type Word: Into<u64>;
516 type Sword: Into<i64>;
517 type Endian: endian::Endian;
518
519 fn r_offset(&self, endian: Self::Endian) -> Self::Word;
520 fn r_info(&self, endian: Self::Endian) -> Self::Word;
521 fn r_sym(&self, endian: Self::Endian) -> u32;
522 fn r_type(&self, endian: Self::Endian) -> u32;
523
524 fn symbol(&self, endian: Self::Endian) -> Option<SymbolIndex> {
528 let sym = self.r_sym(endian);
529 if sym == 0 {
530 None
531 } else {
532 Some(SymbolIndex(sym as usize))
533 }
534 }
535}
536
537impl<Endian: endian::Endian> Rel for elf::Rel32<Endian> {
538 type Word = u32;
539 type Sword = i32;
540 type Endian = Endian;
541
542 #[inline]
543 fn r_offset(&self, endian: Self::Endian) -> Self::Word {
544 self.r_offset.get(endian)
545 }
546
547 #[inline]
548 fn r_info(&self, endian: Self::Endian) -> Self::Word {
549 self.r_info.get(endian)
550 }
551
552 #[inline]
553 fn r_sym(&self, endian: Self::Endian) -> u32 {
554 self.r_sym(endian)
555 }
556
557 #[inline]
558 fn r_type(&self, endian: Self::Endian) -> u32 {
559 self.r_type(endian)
560 }
561}
562
563impl<Endian: endian::Endian> Rel for elf::Rel64<Endian> {
564 type Word = u64;
565 type Sword = i64;
566 type Endian = Endian;
567
568 #[inline]
569 fn r_offset(&self, endian: Self::Endian) -> Self::Word {
570 self.r_offset.get(endian)
571 }
572
573 #[inline]
574 fn r_info(&self, endian: Self::Endian) -> Self::Word {
575 self.r_info.get(endian)
576 }
577
578 #[inline]
579 fn r_sym(&self, endian: Self::Endian) -> u32 {
580 self.r_sym(endian)
581 }
582
583 #[inline]
584 fn r_type(&self, endian: Self::Endian) -> u32 {
585 self.r_type(endian)
586 }
587}
588
589#[allow(missing_docs)]
591pub trait Rela: Debug + Pod + Clone {
592 type Word: Into<u64>;
593 type Sword: Into<i64>;
594 type Endian: endian::Endian;
595
596 fn r_offset(&self, endian: Self::Endian) -> Self::Word;
597 fn r_info(&self, endian: Self::Endian, is_mips64el: bool) -> Self::Word;
598 fn r_addend(&self, endian: Self::Endian) -> Self::Sword;
599 fn r_sym(&self, endian: Self::Endian, is_mips64el: bool) -> u32;
600 fn r_type(&self, endian: Self::Endian, is_mips64el: bool) -> u32;
601
602 fn symbol(&self, endian: Self::Endian, is_mips64el: bool) -> Option<SymbolIndex> {
606 let sym = self.r_sym(endian, is_mips64el);
607 if sym == 0 {
608 None
609 } else {
610 Some(SymbolIndex(sym as usize))
611 }
612 }
613}
614
615impl<Endian: endian::Endian> Rela for elf::Rela32<Endian> {
616 type Word = u32;
617 type Sword = i32;
618 type Endian = Endian;
619
620 #[inline]
621 fn r_offset(&self, endian: Self::Endian) -> Self::Word {
622 self.r_offset.get(endian)
623 }
624
625 #[inline]
626 fn r_info(&self, endian: Self::Endian, _is_mips64el: bool) -> Self::Word {
627 self.r_info.get(endian)
628 }
629
630 #[inline]
631 fn r_addend(&self, endian: Self::Endian) -> Self::Sword {
632 self.r_addend.get(endian)
633 }
634
635 #[inline]
636 fn r_sym(&self, endian: Self::Endian, _is_mips64el: bool) -> u32 {
637 self.r_sym(endian)
638 }
639
640 #[inline]
641 fn r_type(&self, endian: Self::Endian, _is_mips64el: bool) -> u32 {
642 self.r_type(endian)
643 }
644}
645
646impl<Endian: endian::Endian> Rela for elf::Rela64<Endian> {
647 type Word = u64;
648 type Sword = i64;
649 type Endian = Endian;
650
651 #[inline]
652 fn r_offset(&self, endian: Self::Endian) -> Self::Word {
653 self.r_offset.get(endian)
654 }
655
656 #[inline]
657 fn r_info(&self, endian: Self::Endian, is_mips64el: bool) -> Self::Word {
658 self.get_r_info(endian, is_mips64el)
659 }
660
661 #[inline]
662 fn r_addend(&self, endian: Self::Endian) -> Self::Sword {
663 self.r_addend.get(endian)
664 }
665
666 #[inline]
667 fn r_sym(&self, endian: Self::Endian, is_mips64el: bool) -> u32 {
668 self.r_sym(endian, is_mips64el)
669 }
670
671 #[inline]
672 fn r_type(&self, endian: Self::Endian, is_mips64el: bool) -> u32 {
673 self.r_type(endian, is_mips64el)
674 }
675}
676
677#[derive(Debug)]
681pub struct RelrIterator<'data, Elf: FileHeader> {
682 offset: Elf::Word,
683 bits: Elf::Word,
684 count: u8,
685 iter: slice::Iter<'data, Elf::Relr>,
686 endian: Elf::Endian,
687}
688
689impl<'data, Elf: FileHeader> RelrIterator<'data, Elf> {
690 pub fn new(endian: Elf::Endian, data: &'data [Elf::Relr]) -> Self {
692 RelrIterator {
693 offset: Elf::Word::default(),
694 bits: Elf::Word::default(),
695 count: 0,
696 iter: data.iter(),
697 endian,
698 }
699 }
700}
701
702impl<'data, Elf: FileHeader> Iterator for RelrIterator<'data, Elf> {
703 type Item = Elf::Word;
704
705 fn next(&mut self) -> Option<Self::Item> {
706 loop {
707 while self.count > 0 {
708 self.count -= 1;
709 let offset = Elf::Relr::next(&mut self.offset, &mut self.bits);
710 if offset.is_some() {
711 return offset;
712 }
713 }
714 let next = self.iter.next()?.get(self.endian);
715 if next.into() & 1 == 0 {
716 self.offset = next;
717 return Some(next);
718 }
719 self.bits = next;
720 self.count = Elf::Relr::COUNT;
721 }
722 }
723}
724
725#[allow(missing_docs)]
727pub trait Relr: Debug + Pod + Clone {
728 type Word: Into<u64>;
729 type Endian: endian::Endian;
730
731 const COUNT: u8;
733
734 fn get(&self, endian: Self::Endian) -> Self::Word;
738
739 fn next(offset: &mut Self::Word, bits: &mut Self::Word) -> Option<Self::Word>;
746}
747
748impl<Endian: endian::Endian> Relr for elf::Relr32<Endian> {
749 type Word = u32;
750 type Endian = Endian;
751 const COUNT: u8 = 31;
752
753 fn get(&self, endian: Self::Endian) -> Self::Word {
754 self.0.get(endian)
755 }
756
757 fn next(offset: &mut Self::Word, bits: &mut Self::Word) -> Option<Self::Word> {
758 *offset += 4;
759 *bits >>= 1;
760 if *bits & 1 != 0 {
761 Some(*offset)
762 } else {
763 None
764 }
765 }
766}
767
768impl<Endian: endian::Endian> Relr for elf::Relr64<Endian> {
769 type Word = u64;
770 type Endian = Endian;
771 const COUNT: u8 = 63;
772
773 fn get(&self, endian: Self::Endian) -> Self::Word {
774 self.0.get(endian)
775 }
776
777 fn next(offset: &mut Self::Word, bits: &mut Self::Word) -> Option<Self::Word> {
778 *offset += 8;
779 *bits >>= 1;
780 if *bits & 1 != 0 {
781 Some(*offset)
782 } else {
783 None
784 }
785 }
786}
787
788#[derive(Debug, Clone, Copy)]
792pub struct Crel {
793 pub r_offset: u64,
795 pub r_sym: u32,
797 pub r_type: u32,
799 pub r_addend: i64,
803}
804
805impl Crel {
806 pub fn symbol(&self) -> Option<SymbolIndex> {
810 if self.r_sym == 0 {
811 None
812 } else {
813 Some(SymbolIndex(self.r_sym as usize))
814 }
815 }
816
817 pub fn from_rel<R: Rel>(r: &R, endian: R::Endian) -> Crel {
819 Crel {
820 r_offset: r.r_offset(endian).into(),
821 r_sym: r.r_sym(endian),
822 r_type: r.r_type(endian),
823 r_addend: 0,
824 }
825 }
826
827 pub fn from_rela<R: Rela>(r: &R, endian: R::Endian, is_mips64el: bool) -> Crel {
829 Crel {
830 r_offset: r.r_offset(endian).into(),
831 r_sym: r.r_sym(endian, is_mips64el),
832 r_type: r.r_type(endian, is_mips64el),
833 r_addend: r.r_addend(endian).into(),
834 }
835 }
836}
837
838#[derive(Debug, Clone)]
839struct CrelIteratorHeader {
840 count: usize,
842 flag_bits: u64,
844 shift: u64,
846 is_rela: bool,
848}
849
850#[derive(Default, Debug, Clone)]
851struct CrelIteratorState {
852 index: usize,
854 offset: u64,
856 addend: i64,
858 symidx: u32,
860 typ: u32,
862}
863
864#[derive(Debug, Clone)]
866pub struct CrelIterator<'data> {
867 data: Bytes<'data>,
869 header: CrelIteratorHeader,
871 state: CrelIteratorState,
873}
874
875impl<'data> CrelIterator<'data> {
876 pub fn new(data: &'data [u8]) -> Result<Self, Error> {
878 const HEADER_ADDEND_BIT_MASK: u64 = 1 << 2;
879 const HEADER_SHIFT_MASK: u64 = 0x3;
880
881 let mut data = Bytes(data);
882 let header = data.read_uleb128().read_error("Invalid ELF CREL header")?;
883 let count = header >> 3;
884 let flag_bits = if header & HEADER_ADDEND_BIT_MASK != 0 {
885 3
886 } else {
887 2
888 };
889 let shift = header & HEADER_SHIFT_MASK;
890 let is_rela = header & HEADER_ADDEND_BIT_MASK != 0;
891
892 Ok(CrelIterator {
893 data,
894 header: CrelIteratorHeader {
895 count: count as usize,
896 flag_bits,
897 shift,
898 is_rela,
899 },
900 state: Default::default(),
901 })
902 }
903
904 pub fn is_rela(&self) -> bool {
906 self.header.is_rela
907 }
908
909 pub fn len(&self) -> usize {
911 self.header.count - self.state.index
912 }
913
914 pub fn is_empty(&self) -> bool {
916 self.header.count == self.state.index
917 }
918
919 fn parse(&mut self) -> read::Result<Crel> {
920 const DELTA_SYMBOL_INDEX_MASK: u8 = 1 << 0;
921 const DELTA_TYPE_MASK: u8 = 1 << 1;
922 const DELTA_ADDEND_MASK: u8 = 1 << 2;
923
924 let byte = *self
927 .data
928 .read::<u8>()
929 .read_error("Cannot read offset and flags of CREL relocation")?;
930 let flags = byte & ((1 << self.header.flag_bits) - 1);
931
932 let mut delta_offset = u64::from(byte & 0x7f) >> self.header.flag_bits;
933 if byte & 0x80 != 0 {
934 delta_offset |= self
935 .data
936 .read_uleb128()
937 .read_error("Cannot read offset and flags of CREL relocation")?
938 << (7 - self.header.flag_bits);
939 }
940 self.state.offset = self.state.offset.wrapping_add(delta_offset);
941
942 if flags & DELTA_SYMBOL_INDEX_MASK != 0 {
943 let delta_symidx = self
944 .data
945 .read_sleb128()
946 .read_error("Cannot read symidx of CREL relocation")?;
947 self.state.symidx = self.state.symidx.wrapping_add(delta_symidx as u32);
948 }
949 if flags & DELTA_TYPE_MASK != 0 {
950 let delta_typ = self
951 .data
952 .read_sleb128()
953 .read_error("Cannot read type of CREL relocation")?;
954 self.state.typ = self.state.typ.wrapping_add(delta_typ as u32);
955 }
956 if self.header.is_rela && flags & DELTA_ADDEND_MASK != 0 {
957 let delta_addend = self
958 .data
959 .read_sleb128()
960 .read_error("Cannot read addend of CREL relocation")?;
961 self.state.addend = self.state.addend.wrapping_add(delta_addend);
962 }
963 self.state.index += 1;
964 Ok(Crel {
965 r_offset: self.state.offset << self.header.shift,
966 r_sym: self.state.symidx,
967 r_type: self.state.typ,
968 r_addend: self.state.addend,
969 })
970 }
971}
972
973impl<'data> Iterator for CrelIterator<'data> {
974 type Item = read::Result<Crel>;
975
976 fn next(&mut self) -> Option<Self::Item> {
977 if self.state.index >= self.header.count {
978 return None;
979 }
980
981 let result = self.parse();
982 if result.is_err() {
983 self.state.index = self.header.count;
984 }
985 Some(result)
986 }
987
988 fn size_hint(&self) -> (usize, Option<usize>) {
989 (self.len(), Some(self.len()))
990 }
991}