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