1 | use alloc::fmt; |
2 | use core::fmt::Debug; |
3 | use core::slice; |
4 | |
5 | use crate::endian::BigEndian as BE; |
6 | use crate::pod::Pod; |
7 | use crate::read::{ |
8 | ReadRef, Relocation, RelocationEncoding, RelocationFlags, RelocationKind, RelocationTarget, |
9 | SymbolIndex, |
10 | }; |
11 | use crate::xcoff; |
12 | |
13 | use super::{FileHeader, SectionHeader, XcoffFile}; |
14 | |
15 | /// An iterator for the relocations in an [`XcoffSection32`](super::XcoffSection32). |
16 | pub type XcoffRelocationIterator32<'data, 'file, R = &'data [u8]> = |
17 | XcoffRelocationIterator<'data, 'file, xcoff::FileHeader32, R>; |
18 | /// An iterator for the relocations in an [`XcoffSection64`](super::XcoffSection64). |
19 | pub type XcoffRelocationIterator64<'data, 'file, R = &'data [u8]> = |
20 | XcoffRelocationIterator<'data, 'file, xcoff::FileHeader64, R>; |
21 | |
22 | /// An iterator for the relocations in an [`XcoffSection`](super::XcoffSection). |
23 | pub struct XcoffRelocationIterator<'data, 'file, Xcoff, R = &'data [u8]> |
24 | where |
25 | Xcoff: FileHeader, |
26 | R: ReadRef<'data>, |
27 | { |
28 | #[allow (unused)] |
29 | pub(super) file: &'file XcoffFile<'data, Xcoff, R>, |
30 | pub(super) relocations: |
31 | slice::Iter<'data, <<Xcoff as FileHeader>::SectionHeader as SectionHeader>::Rel>, |
32 | } |
33 | |
34 | impl<'data, 'file, Xcoff, R> Iterator for XcoffRelocationIterator<'data, 'file, Xcoff, R> |
35 | where |
36 | Xcoff: FileHeader, |
37 | R: ReadRef<'data>, |
38 | { |
39 | type Item = (u64, Relocation); |
40 | |
41 | fn next(&mut self) -> Option<Self::Item> { |
42 | self.relocations.next().map(|relocation| { |
43 | let r_rtype = relocation.r_rtype(); |
44 | let r_rsize = relocation.r_rsize(); |
45 | let flags = RelocationFlags::Xcoff { r_rtype, r_rsize }; |
46 | let encoding = RelocationEncoding::Generic; |
47 | let (kind, addend) = match r_rtype { |
48 | xcoff::R_POS |
49 | | xcoff::R_RL |
50 | | xcoff::R_RLA |
51 | | xcoff::R_BA |
52 | | xcoff::R_RBA |
53 | | xcoff::R_TLS => (RelocationKind::Absolute, 0), |
54 | xcoff::R_REL | xcoff::R_BR | xcoff::R_RBR => (RelocationKind::Relative, -4), |
55 | xcoff::R_TOC | xcoff::R_TOCL | xcoff::R_TOCU => (RelocationKind::Got, 0), |
56 | _ => (RelocationKind::Unknown, 0), |
57 | }; |
58 | let size = (r_rsize & 0x3F) + 1; |
59 | let target = RelocationTarget::Symbol(relocation.symbol()); |
60 | ( |
61 | relocation.r_vaddr().into(), |
62 | Relocation { |
63 | kind, |
64 | encoding, |
65 | size, |
66 | target, |
67 | addend, |
68 | implicit_addend: true, |
69 | flags, |
70 | }, |
71 | ) |
72 | }) |
73 | } |
74 | } |
75 | |
76 | impl<'data, 'file, Xcoff, R> fmt::Debug for XcoffRelocationIterator<'data, 'file, Xcoff, R> |
77 | where |
78 | Xcoff: FileHeader, |
79 | R: ReadRef<'data>, |
80 | { |
81 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
82 | f.debug_struct(name:"XcoffRelocationIterator" ).finish() |
83 | } |
84 | } |
85 | |
86 | /// A trait for generic access to [`xcoff::Rel32`] and [`xcoff::Rel64`]. |
87 | #[allow (missing_docs)] |
88 | pub trait Rel: Debug + Pod { |
89 | type Word: Into<u64>; |
90 | fn r_vaddr(&self) -> Self::Word; |
91 | fn r_symndx(&self) -> u32; |
92 | fn r_rsize(&self) -> u8; |
93 | fn r_rtype(&self) -> u8; |
94 | |
95 | fn symbol(&self) -> SymbolIndex { |
96 | SymbolIndex(self.r_symndx() as usize) |
97 | } |
98 | } |
99 | |
100 | impl Rel for xcoff::Rel32 { |
101 | type Word = u32; |
102 | |
103 | fn r_vaddr(&self) -> Self::Word { |
104 | self.r_vaddr.get(BE) |
105 | } |
106 | |
107 | fn r_symndx(&self) -> u32 { |
108 | self.r_symndx.get(BE) |
109 | } |
110 | |
111 | fn r_rsize(&self) -> u8 { |
112 | self.r_rsize |
113 | } |
114 | |
115 | fn r_rtype(&self) -> u8 { |
116 | self.r_rtype |
117 | } |
118 | } |
119 | |
120 | impl Rel for xcoff::Rel64 { |
121 | type Word = u64; |
122 | |
123 | fn r_vaddr(&self) -> Self::Word { |
124 | self.r_vaddr.get(BE) |
125 | } |
126 | |
127 | fn r_symndx(&self) -> u32 { |
128 | self.r_symndx.get(BE) |
129 | } |
130 | |
131 | fn r_rsize(&self) -> u8 { |
132 | self.r_rsize |
133 | } |
134 | |
135 | fn r_rtype(&self) -> u8 { |
136 | self.r_rtype |
137 | } |
138 | } |
139 | |