object/read/xcoff/
relocation.rs1use alloc::fmt;
2use core::fmt::Debug;
3use core::slice;
4
5use crate::endian::BigEndian as BE;
6use crate::pod::Pod;
7use crate::read::{
8 ReadRef, Relocation, RelocationEncoding, RelocationFlags, RelocationKind, RelocationTarget,
9 SymbolIndex,
10};
11use crate::xcoff;
12
13use super::{FileHeader, SectionHeader, XcoffFile};
14
15pub type XcoffRelocationIterator32<'data, 'file, R = &'data [u8]> =
17 XcoffRelocationIterator<'data, 'file, xcoff::FileHeader32, R>;
18pub type XcoffRelocationIterator64<'data, 'file, R = &'data [u8]> =
20 XcoffRelocationIterator<'data, 'file, xcoff::FileHeader64, R>;
21
22pub struct XcoffRelocationIterator<'data, 'file, Xcoff, R = &'data [u8]>
24where
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
34impl<'data, 'file, Xcoff, R> Iterator for XcoffRelocationIterator<'data, 'file, Xcoff, R>
35where
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 subtractor: None,
68 addend,
69 implicit_addend: true,
70 flags,
71 },
72 )
73 })
74 }
75}
76
77impl<'data, 'file, Xcoff, R> fmt::Debug for XcoffRelocationIterator<'data, 'file, Xcoff, R>
78where
79 Xcoff: FileHeader,
80 R: ReadRef<'data>,
81{
82 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
83 f.debug_struct("XcoffRelocationIterator").finish()
84 }
85}
86
87#[allow(missing_docs)]
89pub trait Rel: Debug + Pod {
90 type Word: Into<u64>;
91 fn r_vaddr(&self) -> Self::Word;
92 fn r_symndx(&self) -> u32;
93 fn r_rsize(&self) -> u8;
94 fn r_rtype(&self) -> u8;
95
96 fn symbol(&self) -> SymbolIndex {
97 SymbolIndex(self.r_symndx() as usize)
98 }
99}
100
101impl Rel for xcoff::Rel32 {
102 type Word = u32;
103
104 fn r_vaddr(&self) -> Self::Word {
105 self.r_vaddr.get(BE)
106 }
107
108 fn r_symndx(&self) -> u32 {
109 self.r_symndx.get(BE)
110 }
111
112 fn r_rsize(&self) -> u8 {
113 self.r_rsize
114 }
115
116 fn r_rtype(&self) -> u8 {
117 self.r_rtype
118 }
119}
120
121impl Rel for xcoff::Rel64 {
122 type Word = u64;
123
124 fn r_vaddr(&self) -> Self::Word {
125 self.r_vaddr.get(BE)
126 }
127
128 fn r_symndx(&self) -> u32 {
129 self.r_symndx.get(BE)
130 }
131
132 fn r_rsize(&self) -> u8 {
133 self.r_rsize
134 }
135
136 fn r_rtype(&self) -> u8 {
137 self.r_rtype
138 }
139}