| 1 | use alloc::fmt; | 
| 2 | use core::fmt::Debug; | 
| 3 | use core::slice; | 
| 4 |  | 
| 5 | use crate::pod::Pod; | 
| 6 | use crate::{xcoff, BigEndian as BE, Relocation}; | 
| 7 |  | 
| 8 | use crate::read::{ReadRef, RelocationEncoding, RelocationKind, RelocationTarget, SymbolIndex}; | 
| 9 |  | 
| 10 | use super::{FileHeader, SectionHeader, XcoffFile}; | 
| 11 |  | 
| 12 | /// An iterator for the relocations in an [`XcoffSection32`](super::XcoffSection32). | 
| 13 | pub 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). | 
| 16 | pub 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). | 
| 20 | pub struct XcoffRelocationIterator<'data, 'file, Xcoff, R = &'data [u8]> | 
| 21 | where | 
| 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 |  | 
| 31 | impl<'data, 'file, Xcoff, R> Iterator for XcoffRelocationIterator<'data, 'file, Xcoff, R> | 
| 32 | where | 
| 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 |  | 
| 69 | impl<'data, 'file, Xcoff, R> fmt::Debug for XcoffRelocationIterator<'data, 'file, Xcoff, R> | 
| 70 | where | 
| 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)] | 
| 81 | pub 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 |  | 
| 89 | impl 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 |  | 
| 109 | impl 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 |  |