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.0) {
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.0) {
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.0) {
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.0) {
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.0) {
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.0) {
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::Unknown, 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_NONE => (K::None, g, 0),
296 elf::R_AARCH64_ABS64 => (K::Absolute, g, 64),
297 elf::R_AARCH64_ABS32 => (K::Absolute, g, 32),
298 elf::R_AARCH64_ABS16 => (K::Absolute, g, 16),
299 elf::R_AARCH64_PREL64 => (K::Relative, g, 64),
300 elf::R_AARCH64_PREL32 => (K::Relative, g, 32),
301 elf::R_AARCH64_PREL16 => (K::Relative, g, 16),
302 elf::R_AARCH64_CALL26 => (K::PltRelative, E::AArch64Call, 26),
303 _ => unknown,
304 }
305 } else {
306 match r_type {
307 elf::R_AARCH64_NONE => (K::None, g, 0),
308 elf::R_AARCH64_P32_ABS32 => (K::Absolute, g, 32),
309 _ => unknown,
310 }
311 }
312 }
313 elf::EM_ALPHA => match r_type {
314 elf::R_ALPHA_NONE => (K::None, g, 0),
315 elf::R_ALPHA_REFLONG => (K::Absolute, g, 32),
317 elf::R_ALPHA_REFQUAD => (K::Absolute, g, 64),
318 elf::R_ALPHA_SREL16 => (K::Relative, g, 16),
320 elf::R_ALPHA_SREL32 => (K::Relative, g, 32),
321 elf::R_ALPHA_SREL64 => (K::Relative, g, 64),
322 _ => unknown,
323 },
324 elf::EM_ARM => match r_type {
325 elf::R_ARM_NONE => (K::None, g, 0),
326 elf::R_ARM_ABS32 => (K::Absolute, g, 32),
327 _ => unknown,
328 },
329 elf::EM_AVR => match r_type {
330 elf::R_AVR_NONE => (K::None, g, 0),
331 elf::R_AVR_32 => (K::Absolute, g, 32),
332 elf::R_AVR_16 => (K::Absolute, g, 16),
333 _ => unknown,
334 },
335 elf::EM_BPF => match r_type {
336 elf::R_BPF_NONE => (K::None, g, 0),
337 elf::R_BPF_64_64 => (K::Absolute, g, 64),
338 elf::R_BPF_64_32 => (K::Absolute, g, 32),
339 _ => unknown,
340 },
341 elf::EM_CSKY => match r_type {
342 elf::R_CKCORE_NONE => (K::None, g, 0),
343 elf::R_CKCORE_ADDR32 => (K::Absolute, g, 32),
344 elf::R_CKCORE_PCREL32 => (K::Relative, g, 32),
345 _ => unknown,
346 },
347 elf::EM_MCST_ELBRUS => match r_type {
348 elf::R_E2K_NONE => (K::None, g, 0),
349 elf::R_E2K_32_ABS => (K::Absolute, g, 32),
350 elf::R_E2K_64_ABS => (K::Absolute, g, 64),
351 elf::R_E2K_64_ABS_LIT => (K::Absolute, E::E2KLit, 64),
352 elf::R_E2K_DISP => (K::Relative, E::E2KDisp, 28),
353 elf::R_E2K_GOT => (K::Got, g, 32),
354 _ => unknown,
355 },
356 elf::EM_386 => match r_type {
357 elf::R_386_NONE => (K::None, g, 0),
358 elf::R_386_32 => (K::Absolute, g, 32),
359 elf::R_386_PC32 => (K::Relative, g, 32),
360 elf::R_386_GOT32 => (K::Got, g, 32),
361 elf::R_386_PLT32 => (K::PltRelative, g, 32),
362 elf::R_386_GOTOFF => (K::GotBaseOffset, g, 32),
363 elf::R_386_GOTPC => (K::GotBaseRelative, g, 32),
364 elf::R_386_16 => (K::Absolute, g, 16),
365 elf::R_386_PC16 => (K::Relative, g, 16),
366 elf::R_386_8 => (K::Absolute, g, 8),
367 elf::R_386_PC8 => (K::Relative, g, 8),
368 _ => unknown,
369 },
370 elf::EM_X86_64 => match r_type {
371 elf::R_X86_64_NONE => (K::None, g, 0),
372 elf::R_X86_64_64 => (K::Absolute, g, 64),
373 elf::R_X86_64_PC32 => (K::Relative, g, 32),
374 elf::R_X86_64_GOT32 => (K::Got, g, 32),
375 elf::R_X86_64_PLT32 => (K::PltRelative, E::X86Branch, 32),
376 elf::R_X86_64_GOTPCREL => (K::GotRelative, g, 32),
377 elf::R_X86_64_GOTPCRELX => (K::GotRelative, E::Unknown, 32),
378 elf::R_X86_64_REX_GOTPCRELX => (K::GotRelative, E::Unknown, 32),
379 elf::R_X86_64_32 => (K::Absolute, g, 32),
380 elf::R_X86_64_32S => (K::Absolute, E::X86Signed, 32),
381 elf::R_X86_64_16 => (K::Absolute, g, 16),
382 elf::R_X86_64_PC16 => (K::Relative, g, 16),
383 elf::R_X86_64_8 => (K::Absolute, g, 8),
384 elf::R_X86_64_PC8 => (K::Relative, g, 8),
385 _ => unknown,
386 },
387 elf::EM_HEXAGON => match r_type {
388 elf::R_HEX_NONE => (K::None, g, 0),
389 elf::R_HEX_32 => (K::Absolute, g, 32),
390 _ => unknown,
391 },
392 elf::EM_LOONGARCH => match r_type {
393 elf::R_LARCH_NONE => (K::None, g, 0),
394 elf::R_LARCH_32 => (K::Absolute, g, 32),
395 elf::R_LARCH_64 => (K::Absolute, g, 64),
396 elf::R_LARCH_32_PCREL => (K::Relative, g, 32),
397 elf::R_LARCH_64_PCREL => (K::Relative, g, 64),
398 elf::R_LARCH_B16 => (K::Relative, E::LoongArchBranch, 16),
399 elf::R_LARCH_B21 => (K::Relative, E::LoongArchBranch, 21),
400 elf::R_LARCH_B26 => (K::Relative, E::LoongArchBranch, 26),
401 _ => unknown,
402 },
403 elf::EM_68K => match r_type {
404 elf::R_68K_NONE => (K::None, g, 0),
405 elf::R_68K_32 => (K::Absolute, g, 32),
406 elf::R_68K_16 => (K::Absolute, g, 16),
407 elf::R_68K_8 => (K::Absolute, g, 8),
408 elf::R_68K_PC32 => (K::Relative, g, 32),
409 elf::R_68K_PC16 => (K::Relative, g, 16),
410 elf::R_68K_PC8 => (K::Relative, g, 8),
411 elf::R_68K_GOT32O => (K::Got, g, 32),
412 elf::R_68K_GOT16O => (K::Got, g, 16),
413 elf::R_68K_GOT8O => (K::Got, g, 8),
414 elf::R_68K_GOT32 => (K::GotRelative, g, 32),
415 elf::R_68K_GOT16 => (K::GotRelative, g, 16),
416 elf::R_68K_GOT8 => (K::GotRelative, g, 8),
417 elf::R_68K_PLT32 => (K::PltRelative, g, 32),
418 elf::R_68K_PLT16 => (K::PltRelative, g, 16),
419 elf::R_68K_PLT8 => (K::PltRelative, g, 8),
420 _ => unknown,
421 },
422 elf::EM_MIPS => match r_type {
423 elf::R_MIPS_NONE => (K::None, g, 0),
424 elf::R_MIPS_16 => (K::Absolute, g, 16),
425 elf::R_MIPS_32 => (K::Absolute, g, 32),
426 elf::R_MIPS_64 => (K::Absolute, g, 64),
427 _ => unknown,
428 },
429 elf::EM_MSP430 => match r_type {
430 elf::R_MSP430_NONE => (K::None, g, 0),
431 elf::R_MSP430_32 => (K::Absolute, g, 32),
432 elf::R_MSP430_16_BYTE => (K::Absolute, g, 16),
433 _ => unknown,
434 },
435 elf::EM_PARISC => match r_type {
436 elf::R_PARISC_NONE => (K::None, g, 0),
437 elf::R_PARISC_DIR32 => (K::Absolute, g, 32),
438 elf::R_PARISC_PCREL32 => (K::Relative, g, 32),
439 _ => unknown,
440 },
441 elf::EM_PPC => match r_type {
442 elf::R_PPC_NONE => (K::None, g, 0),
443 elf::R_PPC_ADDR32 => (K::Absolute, g, 32),
444 _ => unknown,
445 },
446 elf::EM_PPC64 => match r_type {
447 elf::R_PPC64_NONE => (K::None, g, 0),
448 elf::R_PPC64_ADDR32 => (K::Absolute, g, 32),
449 elf::R_PPC64_ADDR64 => (K::Absolute, g, 64),
450 _ => unknown,
451 },
452 elf::EM_RISCV => match r_type {
453 elf::R_RISCV_NONE => (K::None, g, 0),
454 elf::R_RISCV_32 => (K::Absolute, g, 32),
455 elf::R_RISCV_64 => (K::Absolute, g, 64),
456 _ => unknown,
457 },
458 elf::EM_S390 => match r_type {
459 elf::R_390_NONE => (K::None, g, 0),
460 elf::R_390_8 => (K::Absolute, g, 8),
461 elf::R_390_16 => (K::Absolute, g, 16),
462 elf::R_390_32 => (K::Absolute, g, 32),
463 elf::R_390_64 => (K::Absolute, g, 64),
464 elf::R_390_PC16 => (K::Relative, g, 16),
465 elf::R_390_PC32 => (K::Relative, g, 32),
466 elf::R_390_PC64 => (K::Relative, g, 64),
467 elf::R_390_PC16DBL => (K::Relative, E::S390xDbl, 16),
468 elf::R_390_PC32DBL => (K::Relative, E::S390xDbl, 32),
469 elf::R_390_PLT16DBL => (K::PltRelative, E::S390xDbl, 16),
470 elf::R_390_PLT32DBL => (K::PltRelative, E::S390xDbl, 32),
471 elf::R_390_GOT16 => (K::Got, g, 16),
472 elf::R_390_GOT32 => (K::Got, g, 32),
473 elf::R_390_GOT64 => (K::Got, g, 64),
474 elf::R_390_GOTENT => (K::GotRelative, E::S390xDbl, 32),
475 elf::R_390_GOTOFF16 => (K::GotBaseOffset, g, 16),
476 elf::R_390_GOTOFF32 => (K::GotBaseOffset, g, 32),
477 elf::R_390_GOTOFF64 => (K::GotBaseOffset, g, 64),
478 elf::R_390_GOTPC => (K::GotBaseRelative, g, 64),
479 elf::R_390_GOTPCDBL => (K::GotBaseRelative, E::S390xDbl, 32),
480 _ => unknown,
481 },
482 elf::EM_SBF => match r_type {
483 elf::R_SBF_NONE => (K::None, g, 0),
484 elf::R_SBF_64_64 => (K::Absolute, g, 64),
485 elf::R_SBF_64_32 => (K::Absolute, g, 32),
486 _ => unknown,
487 },
488 elf::EM_SHARC => match r_type {
489 elf::R_SHARC_ADDR24_V3 => (K::Absolute, E::SharcTypeA, 24),
490 elf::R_SHARC_ADDR32_V3 => (K::Absolute, E::SharcTypeA, 32),
491 elf::R_SHARC_ADDR_VAR_V3 => (K::Absolute, E::Generic, 32),
492 elf::R_SHARC_PCRSHORT_V3 => (K::Relative, E::SharcTypeA, 6),
493 elf::R_SHARC_PCRLONG_V3 => (K::Relative, E::SharcTypeA, 24),
494 elf::R_SHARC_DATA6_V3 => (K::Absolute, E::SharcTypeA, 6),
495 elf::R_SHARC_DATA16_V3 => (K::Absolute, E::SharcTypeA, 16),
496 elf::R_SHARC_DATA6_VISA_V3 => (K::Absolute, E::SharcTypeB, 6),
497 elf::R_SHARC_DATA7_VISA_V3 => (K::Absolute, E::SharcTypeB, 7),
498 elf::R_SHARC_DATA16_VISA_V3 => (K::Absolute, E::SharcTypeB, 16),
499 elf::R_SHARC_PCR6_VISA_V3 => (K::Relative, E::SharcTypeB, 16),
500 elf::R_SHARC_ADDR_VAR16_V3 => (K::Absolute, E::Generic, 16),
501 _ => unknown,
502 },
503 elf::EM_SPARC | elf::EM_SPARC32PLUS | elf::EM_SPARCV9 => match r_type {
504 elf::R_SPARC_NONE => (K::None, g, 0),
505 elf::R_SPARC_32 | elf::R_SPARC_UA32 => (K::Absolute, g, 32),
506 elf::R_SPARC_64 | elf::R_SPARC_UA64 => (K::Absolute, g, 64),
507 _ => unknown,
508 },
509 elf::EM_SH => match r_type {
510 elf::R_SH_NONE => (K::None, g, 0),
511 elf::R_SH_DIR32 => (K::Absolute, g, 32),
512 elf::R_SH_REL32 => (K::Relative, g, 32),
513 _ => unknown,
514 },
515 elf::EM_XTENSA => match r_type {
516 elf::R_XTENSA_NONE => (K::None, g, 0),
517 elf::R_XTENSA_32 => (K::Absolute, g, 32),
518 elf::R_XTENSA_32_PCREL => (K::Relative, g, 32),
519 _ => unknown,
520 },
521 _ => unknown,
522 };
523 let target = match reloc.symbol() {
524 None => RelocationTarget::Absolute,
525 Some(symbol) => RelocationTarget::Symbol(symbol),
526 };
527 Relocation {
528 kind,
529 encoding,
530 size,
531 target,
532 subtractor: None,
533 addend: reloc.r_addend,
534 implicit_addend,
535 flags,
536 }
537}
538
539#[allow(missing_docs)]
541pub trait Rel: Debug + Pod + Clone {
542 type Word: Into<u64>;
543 type Sword: Into<i64>;
544 type Endian: endian::Endian;
545
546 fn r_offset(&self, endian: Self::Endian) -> Self::Word;
547 fn r_info(&self, endian: Self::Endian) -> Self::Word;
548 fn r_sym(&self, endian: Self::Endian) -> u32;
549 fn r_type(&self, endian: Self::Endian) -> u32;
550
551 fn symbol(&self, endian: Self::Endian) -> Option<SymbolIndex> {
555 let sym = self.r_sym(endian);
556 if sym == 0 {
557 None
558 } else {
559 Some(SymbolIndex(sym as usize))
560 }
561 }
562}
563
564impl<Endian: endian::Endian> Rel for elf::Rel32<Endian> {
565 type Word = u32;
566 type Sword = i32;
567 type Endian = Endian;
568
569 #[inline]
570 fn r_offset(&self, endian: Self::Endian) -> Self::Word {
571 self.r_offset.get(endian)
572 }
573
574 #[inline]
575 fn r_info(&self, endian: Self::Endian) -> Self::Word {
576 self.r_info.get(endian)
577 }
578
579 #[inline]
580 fn r_sym(&self, endian: Self::Endian) -> u32 {
581 self.r_sym(endian)
582 }
583
584 #[inline]
585 fn r_type(&self, endian: Self::Endian) -> u32 {
586 self.r_type(endian)
587 }
588}
589
590impl<Endian: endian::Endian> Rel for elf::Rel64<Endian> {
591 type Word = u64;
592 type Sword = i64;
593 type Endian = Endian;
594
595 #[inline]
596 fn r_offset(&self, endian: Self::Endian) -> Self::Word {
597 self.r_offset.get(endian)
598 }
599
600 #[inline]
601 fn r_info(&self, endian: Self::Endian) -> Self::Word {
602 self.r_info.get(endian)
603 }
604
605 #[inline]
606 fn r_sym(&self, endian: Self::Endian) -> u32 {
607 self.r_sym(endian)
608 }
609
610 #[inline]
611 fn r_type(&self, endian: Self::Endian) -> u32 {
612 self.r_type(endian)
613 }
614}
615
616#[allow(missing_docs)]
618pub trait Rela: Debug + Pod + Clone {
619 type Word: Into<u64>;
620 type Sword: Into<i64>;
621 type Endian: endian::Endian;
622
623 fn r_offset(&self, endian: Self::Endian) -> Self::Word;
624 fn r_info(&self, endian: Self::Endian, is_mips64el: bool) -> Self::Word;
625 fn r_addend(&self, endian: Self::Endian) -> Self::Sword;
626 fn r_sym(&self, endian: Self::Endian, is_mips64el: bool) -> u32;
627 fn r_type(&self, endian: Self::Endian, is_mips64el: bool) -> u32;
628
629 fn symbol(&self, endian: Self::Endian, is_mips64el: bool) -> Option<SymbolIndex> {
633 let sym = self.r_sym(endian, is_mips64el);
634 if sym == 0 {
635 None
636 } else {
637 Some(SymbolIndex(sym as usize))
638 }
639 }
640}
641
642impl<Endian: endian::Endian> Rela for elf::Rela32<Endian> {
643 type Word = u32;
644 type Sword = i32;
645 type Endian = Endian;
646
647 #[inline]
648 fn r_offset(&self, endian: Self::Endian) -> Self::Word {
649 self.r_offset.get(endian)
650 }
651
652 #[inline]
653 fn r_info(&self, endian: Self::Endian, _is_mips64el: bool) -> Self::Word {
654 self.r_info.get(endian)
655 }
656
657 #[inline]
658 fn r_addend(&self, endian: Self::Endian) -> Self::Sword {
659 self.r_addend.get(endian)
660 }
661
662 #[inline]
663 fn r_sym(&self, endian: Self::Endian, _is_mips64el: bool) -> u32 {
664 self.r_sym(endian)
665 }
666
667 #[inline]
668 fn r_type(&self, endian: Self::Endian, _is_mips64el: bool) -> u32 {
669 self.r_type(endian)
670 }
671}
672
673impl<Endian: endian::Endian> Rela for elf::Rela64<Endian> {
674 type Word = u64;
675 type Sword = i64;
676 type Endian = Endian;
677
678 #[inline]
679 fn r_offset(&self, endian: Self::Endian) -> Self::Word {
680 self.r_offset.get(endian)
681 }
682
683 #[inline]
684 fn r_info(&self, endian: Self::Endian, is_mips64el: bool) -> Self::Word {
685 self.get_r_info(endian, is_mips64el)
686 }
687
688 #[inline]
689 fn r_addend(&self, endian: Self::Endian) -> Self::Sword {
690 self.r_addend.get(endian)
691 }
692
693 #[inline]
694 fn r_sym(&self, endian: Self::Endian, is_mips64el: bool) -> u32 {
695 self.r_sym(endian, is_mips64el)
696 }
697
698 #[inline]
699 fn r_type(&self, endian: Self::Endian, is_mips64el: bool) -> u32 {
700 self.r_type(endian, is_mips64el)
701 }
702}
703
704#[derive(Debug)]
708pub struct RelrIterator<'data, Elf: FileHeader> {
709 offset: Elf::Word,
710 bits: Elf::Word,
711 count: u8,
712 iter: slice::Iter<'data, Elf::Relr>,
713 endian: Elf::Endian,
714}
715
716impl<'data, Elf: FileHeader> RelrIterator<'data, Elf> {
717 pub fn new(endian: Elf::Endian, data: &'data [Elf::Relr]) -> Self {
719 RelrIterator {
720 offset: Elf::Word::default(),
721 bits: Elf::Word::default(),
722 count: 0,
723 iter: data.iter(),
724 endian,
725 }
726 }
727}
728
729impl<'data, Elf: FileHeader> Iterator for RelrIterator<'data, Elf> {
730 type Item = Elf::Word;
731
732 fn next(&mut self) -> Option<Self::Item> {
733 loop {
734 while self.count > 0 {
735 self.count -= 1;
736 let offset = Elf::Relr::next(&mut self.offset, &mut self.bits);
737 if offset.is_some() {
738 return offset;
739 }
740 }
741 let next = self.iter.next()?.get(self.endian);
742 if next.into() & 1 == 0 {
743 self.offset = next;
744 return Some(next);
745 }
746 self.bits = next;
747 self.count = Elf::Relr::COUNT;
748 }
749 }
750}
751
752#[allow(missing_docs)]
754pub trait Relr: Debug + Pod + Clone {
755 type Word: Into<u64>;
756 type Endian: endian::Endian;
757
758 const COUNT: u8;
760
761 fn get(&self, endian: Self::Endian) -> Self::Word;
765
766 fn next(offset: &mut Self::Word, bits: &mut Self::Word) -> Option<Self::Word>;
773}
774
775impl<Endian: endian::Endian> Relr for elf::Relr32<Endian> {
776 type Word = u32;
777 type Endian = Endian;
778 const COUNT: u8 = 31;
779
780 fn get(&self, endian: Self::Endian) -> Self::Word {
781 self.0.get(endian)
782 }
783
784 fn next(offset: &mut Self::Word, bits: &mut Self::Word) -> Option<Self::Word> {
785 *offset += 4;
786 *bits >>= 1;
787 if *bits & 1 != 0 {
788 Some(*offset)
789 } else {
790 None
791 }
792 }
793}
794
795impl<Endian: endian::Endian> Relr for elf::Relr64<Endian> {
796 type Word = u64;
797 type Endian = Endian;
798 const COUNT: u8 = 63;
799
800 fn get(&self, endian: Self::Endian) -> Self::Word {
801 self.0.get(endian)
802 }
803
804 fn next(offset: &mut Self::Word, bits: &mut Self::Word) -> Option<Self::Word> {
805 *offset += 8;
806 *bits >>= 1;
807 if *bits & 1 != 0 {
808 Some(*offset)
809 } else {
810 None
811 }
812 }
813}
814
815#[derive(Debug, Clone, Copy, Default)]
819pub struct Crel {
820 pub r_offset: u64,
822 pub r_sym: u32,
824 pub r_type: u32,
826 pub r_addend: i64,
830}
831
832impl Crel {
833 pub fn symbol(&self) -> Option<SymbolIndex> {
837 if self.r_sym == 0 {
838 None
839 } else {
840 Some(SymbolIndex(self.r_sym as usize))
841 }
842 }
843
844 pub fn from_rel<R: Rel>(r: &R, endian: R::Endian) -> Crel {
846 Crel {
847 r_offset: r.r_offset(endian).into(),
848 r_sym: r.r_sym(endian),
849 r_type: r.r_type(endian),
850 r_addend: 0,
851 }
852 }
853
854 pub fn from_rela<R: Rela>(r: &R, endian: R::Endian, is_mips64el: bool) -> Crel {
856 Crel {
857 r_offset: r.r_offset(endian).into(),
858 r_sym: r.r_sym(endian, is_mips64el),
859 r_type: r.r_type(endian, is_mips64el),
860 r_addend: r.r_addend(endian).into(),
861 }
862 }
863}
864
865#[derive(Debug, Clone)]
866struct CrelIteratorHeader {
867 count: usize,
869 flag_bits: u8,
871 shift: u8,
873 is_rela: bool,
875}
876
877#[derive(Debug, Clone)]
879pub struct CrelIterator<'data> {
880 data: Bytes<'data>,
882 header: CrelIteratorHeader,
884 state: Crel,
886}
887
888impl<'data> CrelIterator<'data> {
889 pub fn new(data: &'data [u8]) -> Result<Self, Error> {
891 const HEADER_ADDEND_BIT_MASK: u64 = 1 << 2;
892 const HEADER_SHIFT_MASK: u64 = 0x3;
893
894 let mut data = Bytes(data);
895 let header = data.read_uleb128().read_error("Invalid ELF CREL header")?;
896 let count = header >> 3;
897 let flag_bits = if header & HEADER_ADDEND_BIT_MASK != 0 {
898 3
899 } else {
900 2
901 };
902 let shift = (header & HEADER_SHIFT_MASK) as u8;
903 let is_rela = header & HEADER_ADDEND_BIT_MASK != 0;
904
905 Ok(CrelIterator {
906 data,
907 header: CrelIteratorHeader {
908 count: count as usize,
909 flag_bits,
910 shift,
911 is_rela,
912 },
913 state: Default::default(),
914 })
915 }
916
917 pub fn is_rela(&self) -> bool {
919 self.header.is_rela
920 }
921
922 pub fn len(&self) -> usize {
924 self.header.count
925 }
926
927 pub fn is_empty(&self) -> bool {
929 self.header.count == 0
930 }
931
932 fn parse(&mut self) -> read::Result<Crel> {
933 const DELTA_SYMBOL_INDEX_MASK: u8 = 1 << 0;
934 const DELTA_TYPE_MASK: u8 = 1 << 1;
935 const DELTA_ADDEND_MASK: u8 = 1 << 2;
936
937 let byte = *self
940 .data
941 .read::<u8>()
942 .read_error("Cannot read offset and flags of CREL relocation")?;
943 let flags = byte & ((1 << self.header.flag_bits) - 1);
944
945 let mut delta_offset = u64::from(byte & 0x7f) >> self.header.flag_bits;
946 if byte & 0x80 != 0 {
947 delta_offset |= self
948 .data
949 .read_uleb128()
950 .read_error("Cannot read offset and flags of CREL relocation")?
951 << (7 - self.header.flag_bits);
952 }
953 self.state.r_offset = self
954 .state
955 .r_offset
956 .wrapping_add(delta_offset << self.header.shift);
957
958 if flags & DELTA_SYMBOL_INDEX_MASK != 0 {
959 let delta_symidx = self
960 .data
961 .read_sleb128()
962 .read_error("Cannot read symidx of CREL relocation")?;
963 self.state.r_sym = self.state.r_sym.wrapping_add(delta_symidx as u32);
964 }
965 if flags & DELTA_TYPE_MASK != 0 {
966 let delta_typ = self
967 .data
968 .read_sleb128()
969 .read_error("Cannot read type of CREL relocation")?;
970 self.state.r_type = self.state.r_type.wrapping_add(delta_typ as u32);
971 }
972 if self.header.is_rela && flags & DELTA_ADDEND_MASK != 0 {
973 let delta_addend = self
974 .data
975 .read_sleb128()
976 .read_error("Cannot read addend of CREL relocation")?;
977 self.state.r_addend = self.state.r_addend.wrapping_add(delta_addend);
978 }
979 self.header.count -= 1;
980 Ok(self.state)
981 }
982}
983
984impl<'data> Iterator for CrelIterator<'data> {
985 type Item = read::Result<Crel>;
986
987 fn next(&mut self) -> Option<Self::Item> {
988 if self.is_empty() {
989 return None;
990 }
991
992 let result = self.parse();
993 if result.is_err() {
994 self.header.count = 0;
995 }
996 Some(result)
997 }
998
999 fn size_hint(&self) -> (usize, Option<usize>) {
1000 (self.len(), Some(self.len()))
1001 }
1002}