1 | use alloc::fmt; |
2 | use core::slice; |
3 | |
4 | use crate::endian::LittleEndian as LE; |
5 | use crate::pe; |
6 | use crate::read::{ |
7 | ReadRef, Relocation, RelocationEncoding, RelocationFlags, RelocationKind, RelocationTarget, |
8 | SymbolIndex, |
9 | }; |
10 | |
11 | use super::{CoffFile, CoffHeader}; |
12 | |
13 | /// An iterator for the relocations in a [`CoffBigSection`](super::CoffBigSection). |
14 | pub type CoffBigRelocationIterator<'data, 'file, R = &'data [u8]> = |
15 | CoffRelocationIterator<'data, 'file, R, pe::AnonObjectHeaderBigobj>; |
16 | |
17 | /// An iterator for the relocations in a [`CoffSection`](super::CoffSection). |
18 | pub struct CoffRelocationIterator< |
19 | 'data, |
20 | 'file, |
21 | R: ReadRef<'data> = &'data [u8], |
22 | Coff: CoffHeader = pe::ImageFileHeader, |
23 | > { |
24 | pub(super) file: &'file CoffFile<'data, R, Coff>, |
25 | pub(super) iter: slice::Iter<'data, pe::ImageRelocation>, |
26 | } |
27 | |
28 | impl<'data, 'file, R: ReadRef<'data>, Coff: CoffHeader> Iterator |
29 | for CoffRelocationIterator<'data, 'file, R, Coff> |
30 | { |
31 | type Item = (u64, Relocation); |
32 | |
33 | fn next(&mut self) -> Option<Self::Item> { |
34 | use RelocationEncoding as E; |
35 | use RelocationKind as K; |
36 | |
37 | self.iter.next().map(|relocation| { |
38 | let typ = relocation.typ.get(LE); |
39 | let flags = RelocationFlags::Coff { typ }; |
40 | let g = E::Generic; |
41 | let unknown = (K::Unknown, E::Generic, 0, 0); |
42 | let (kind, encoding, size, addend) = match self.file.header.machine() { |
43 | pe::IMAGE_FILE_MACHINE_ARMNT => match typ { |
44 | pe::IMAGE_REL_ARM_ADDR32 => (K::Absolute, g, 32, 0), |
45 | pe::IMAGE_REL_ARM_ADDR32NB => (K::ImageOffset, g, 32, 0), |
46 | pe::IMAGE_REL_ARM_REL32 => (K::Relative, g, 32, -4), |
47 | pe::IMAGE_REL_ARM_SECTION => (K::SectionIndex, g, 16, 0), |
48 | pe::IMAGE_REL_ARM_SECREL => (K::SectionOffset, g, 32, 0), |
49 | _ => unknown, |
50 | }, |
51 | pe::IMAGE_FILE_MACHINE_ARM64 | pe::IMAGE_FILE_MACHINE_ARM64EC => match typ { |
52 | pe::IMAGE_REL_ARM64_ADDR32 => (K::Absolute, g, 32, 0), |
53 | pe::IMAGE_REL_ARM64_ADDR32NB => (K::ImageOffset, g, 32, 0), |
54 | pe::IMAGE_REL_ARM64_SECREL => (K::SectionOffset, g, 32, 0), |
55 | pe::IMAGE_REL_ARM64_SECTION => (K::SectionIndex, g, 16, 0), |
56 | pe::IMAGE_REL_ARM64_ADDR64 => (K::Absolute, g, 64, 0), |
57 | pe::IMAGE_REL_ARM64_REL32 => (K::Relative, g, 32, -4), |
58 | pe::IMAGE_REL_ARM64_BRANCH26 => (K::Relative, E::AArch64Call, 26, 0), |
59 | _ => unknown, |
60 | }, |
61 | pe::IMAGE_FILE_MACHINE_I386 => match typ { |
62 | pe::IMAGE_REL_I386_DIR16 => (K::Absolute, g, 16, 0), |
63 | pe::IMAGE_REL_I386_REL16 => (K::Relative, g, 16, 0), |
64 | pe::IMAGE_REL_I386_DIR32 => (K::Absolute, g, 32, 0), |
65 | pe::IMAGE_REL_I386_DIR32NB => (K::ImageOffset, g, 32, 0), |
66 | pe::IMAGE_REL_I386_SECTION => (K::SectionIndex, g, 16, 0), |
67 | pe::IMAGE_REL_I386_SECREL => (K::SectionOffset, g, 32, 0), |
68 | pe::IMAGE_REL_I386_SECREL7 => (K::SectionOffset, g, 7, 0), |
69 | pe::IMAGE_REL_I386_REL32 => (K::Relative, g, 32, -4), |
70 | _ => unknown, |
71 | }, |
72 | pe::IMAGE_FILE_MACHINE_AMD64 => match typ { |
73 | pe::IMAGE_REL_AMD64_ADDR64 => (K::Absolute, g, 64, 0), |
74 | pe::IMAGE_REL_AMD64_ADDR32 => (K::Absolute, g, 32, 0), |
75 | pe::IMAGE_REL_AMD64_ADDR32NB => (K::ImageOffset, g, 32, 0), |
76 | pe::IMAGE_REL_AMD64_REL32 => (K::Relative, g, 32, -4), |
77 | pe::IMAGE_REL_AMD64_REL32_1 => (K::Relative, g, 32, -5), |
78 | pe::IMAGE_REL_AMD64_REL32_2 => (K::Relative, g, 32, -6), |
79 | pe::IMAGE_REL_AMD64_REL32_3 => (K::Relative, g, 32, -7), |
80 | pe::IMAGE_REL_AMD64_REL32_4 => (K::Relative, g, 32, -8), |
81 | pe::IMAGE_REL_AMD64_REL32_5 => (K::Relative, g, 32, -9), |
82 | pe::IMAGE_REL_AMD64_SECTION => (K::SectionIndex, g, 16, 0), |
83 | pe::IMAGE_REL_AMD64_SECREL => (K::SectionOffset, g, 32, 0), |
84 | pe::IMAGE_REL_AMD64_SECREL7 => (K::SectionOffset, g, 7, 0), |
85 | _ => unknown, |
86 | }, |
87 | _ => unknown, |
88 | }; |
89 | let target = RelocationTarget::Symbol(relocation.symbol()); |
90 | ( |
91 | u64::from(relocation.virtual_address.get(LE)), |
92 | Relocation { |
93 | kind, |
94 | encoding, |
95 | size, |
96 | target, |
97 | addend, |
98 | implicit_addend: true, |
99 | flags, |
100 | }, |
101 | ) |
102 | }) |
103 | } |
104 | } |
105 | |
106 | impl<'data, 'file, R: ReadRef<'data>, Coff: CoffHeader> fmt::Debug |
107 | for CoffRelocationIterator<'data, 'file, R, Coff> |
108 | { |
109 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
110 | f.debug_struct(name:"CoffRelocationIterator" ).finish() |
111 | } |
112 | } |
113 | |
114 | impl pe::ImageRelocation { |
115 | /// Get the index of the symbol referenced by this relocation. |
116 | pub fn symbol(&self) -> SymbolIndex { |
117 | SymbolIndex(self.symbol_table_index.get(LE) as usize) |
118 | } |
119 | } |
120 | |