]> git.proxmox.com Git - rustc.git/blob - vendor/object-0.26.2/src/read/macho/segment.rs
New upstream version 1.66.0+dfsg1
[rustc.git] / vendor / object-0.26.2 / src / read / macho / segment.rs
1 use core::fmt::Debug;
2 use core::{result, str};
3
4 use crate::endian::{self, Endianness};
5 use crate::macho;
6 use crate::pod::Pod;
7 use crate::read::{self, ObjectSegment, ReadError, ReadRef, Result};
8
9 use super::{LoadCommandData, LoadCommandIterator, MachHeader, MachOFile, Section};
10
11 /// An iterator over the segments of a `MachOFile32`.
12 pub type MachOSegmentIterator32<'data, 'file, Endian = Endianness, R = &'data [u8]> =
13 MachOSegmentIterator<'data, 'file, macho::MachHeader32<Endian>, R>;
14 /// An iterator over the segments of a `MachOFile64`.
15 pub type MachOSegmentIterator64<'data, 'file, Endian = Endianness, R = &'data [u8]> =
16 MachOSegmentIterator<'data, 'file, macho::MachHeader64<Endian>, R>;
17
18 /// An iterator over the segments of a `MachOFile`.
19 #[derive(Debug)]
20 pub struct MachOSegmentIterator<'data, 'file, Mach, R = &'data [u8]>
21 where
22 'data: 'file,
23 Mach: MachHeader,
24 R: ReadRef<'data>,
25 {
26 pub(super) file: &'file MachOFile<'data, Mach, R>,
27 pub(super) commands: LoadCommandIterator<'data, Mach::Endian>,
28 }
29
30 impl<'data, 'file, Mach, R> Iterator for MachOSegmentIterator<'data, 'file, Mach, R>
31 where
32 Mach: MachHeader,
33 R: ReadRef<'data>,
34 {
35 type Item = MachOSegment<'data, 'file, Mach, R>;
36
37 fn next(&mut self) -> Option<Self::Item> {
38 loop {
39 let command = self.commands.next().ok()??;
40 if let Ok(Some((segment, _))) = Mach::Segment::from_command(command) {
41 return Some(MachOSegment {
42 file: self.file,
43 segment,
44 });
45 }
46 }
47 }
48 }
49
50 /// A segment of a `MachOFile32`.
51 pub type MachOSegment32<'data, 'file, Endian = Endianness, R = &'data [u8]> =
52 MachOSegment<'data, 'file, macho::MachHeader32<Endian>, R>;
53 /// A segment of a `MachOFile64`.
54 pub type MachOSegment64<'data, 'file, Endian = Endianness, R = &'data [u8]> =
55 MachOSegment<'data, 'file, macho::MachHeader64<Endian>, R>;
56
57 /// A segment of a `MachOFile`.
58 #[derive(Debug)]
59 pub struct MachOSegment<'data, 'file, Mach, R = &'data [u8]>
60 where
61 'data: 'file,
62 Mach: MachHeader,
63 R: ReadRef<'data>,
64 {
65 file: &'file MachOFile<'data, Mach, R>,
66 segment: &'data Mach::Segment,
67 }
68
69 impl<'data, 'file, Mach, R> MachOSegment<'data, 'file, Mach, R>
70 where
71 Mach: MachHeader,
72 R: ReadRef<'data>,
73 {
74 fn bytes(&self) -> Result<&'data [u8]> {
75 self.segment
76 .data(self.file.endian, self.file.data)
77 .read_error("Invalid Mach-O segment size or offset")
78 }
79 }
80
81 impl<'data, 'file, Mach, R> read::private::Sealed for MachOSegment<'data, 'file, Mach, R>
82 where
83 Mach: MachHeader,
84 R: ReadRef<'data>,
85 {
86 }
87
88 impl<'data, 'file, Mach, R> ObjectSegment<'data> for MachOSegment<'data, 'file, Mach, R>
89 where
90 Mach: MachHeader,
91 R: ReadRef<'data>,
92 {
93 #[inline]
94 fn address(&self) -> u64 {
95 self.segment.vmaddr(self.file.endian).into()
96 }
97
98 #[inline]
99 fn size(&self) -> u64 {
100 self.segment.vmsize(self.file.endian).into()
101 }
102
103 #[inline]
104 fn align(&self) -> u64 {
105 // Page size.
106 0x1000
107 }
108
109 #[inline]
110 fn file_range(&self) -> (u64, u64) {
111 self.segment.file_range(self.file.endian)
112 }
113
114 fn data(&self) -> Result<&'data [u8]> {
115 self.bytes()
116 }
117
118 fn data_range(&self, address: u64, size: u64) -> Result<Option<&'data [u8]>> {
119 Ok(read::util::data_range(
120 self.bytes()?,
121 self.address(),
122 address,
123 size,
124 ))
125 }
126
127 #[inline]
128 fn name(&self) -> Result<Option<&str>> {
129 Ok(Some(
130 str::from_utf8(self.segment.name())
131 .ok()
132 .read_error("Non UTF-8 Mach-O segment name")?,
133 ))
134 }
135 }
136
137 /// A trait for generic access to `SegmentCommand32` and `SegmentCommand64`.
138 #[allow(missing_docs)]
139 pub trait Segment: Debug + Pod {
140 type Word: Into<u64>;
141 type Endian: endian::Endian;
142 type Section: Section<Endian = Self::Endian>;
143
144 fn from_command(command: LoadCommandData<Self::Endian>) -> Result<Option<(&Self, &[u8])>>;
145
146 fn cmd(&self, endian: Self::Endian) -> u32;
147 fn cmdsize(&self, endian: Self::Endian) -> u32;
148 fn segname(&self) -> &[u8; 16];
149 fn vmaddr(&self, endian: Self::Endian) -> Self::Word;
150 fn vmsize(&self, endian: Self::Endian) -> Self::Word;
151 fn fileoff(&self, endian: Self::Endian) -> Self::Word;
152 fn filesize(&self, endian: Self::Endian) -> Self::Word;
153 fn maxprot(&self, endian: Self::Endian) -> u32;
154 fn initprot(&self, endian: Self::Endian) -> u32;
155 fn nsects(&self, endian: Self::Endian) -> u32;
156 fn flags(&self, endian: Self::Endian) -> u32;
157
158 /// Return the `segname` bytes up until the null terminator.
159 fn name(&self) -> &[u8] {
160 let segname = &self.segname()[..];
161 match memchr::memchr(b'\0', segname) {
162 Some(end) => &segname[..end],
163 None => segname,
164 }
165 }
166
167 /// Return the offset and size of the segment in the file.
168 fn file_range(&self, endian: Self::Endian) -> (u64, u64) {
169 (self.fileoff(endian).into(), self.filesize(endian).into())
170 }
171
172 /// Get the segment data from the file data.
173 ///
174 /// Returns `Err` for invalid values.
175 fn data<'data, R: ReadRef<'data>>(
176 &self,
177 endian: Self::Endian,
178 data: R,
179 ) -> result::Result<&'data [u8], ()> {
180 let (offset, size) = self.file_range(endian);
181 data.read_bytes_at(offset, size)
182 }
183
184 /// Get the array of sections from the data following the segment command.
185 ///
186 /// Returns `Err` for invalid values.
187 fn sections<'data, R: ReadRef<'data>>(
188 &self,
189 endian: Self::Endian,
190 section_data: R,
191 ) -> Result<&'data [Self::Section]> {
192 section_data
193 .read_slice_at(0, self.nsects(endian) as usize)
194 .read_error("Invalid Mach-O number of sections")
195 }
196 }
197
198 impl<Endian: endian::Endian> Segment for macho::SegmentCommand32<Endian> {
199 type Word = u32;
200 type Endian = Endian;
201 type Section = macho::Section32<Self::Endian>;
202
203 fn from_command(command: LoadCommandData<Self::Endian>) -> Result<Option<(&Self, &[u8])>> {
204 command.segment_32()
205 }
206
207 fn cmd(&self, endian: Self::Endian) -> u32 {
208 self.cmd.get(endian)
209 }
210 fn cmdsize(&self, endian: Self::Endian) -> u32 {
211 self.cmdsize.get(endian)
212 }
213 fn segname(&self) -> &[u8; 16] {
214 &self.segname
215 }
216 fn vmaddr(&self, endian: Self::Endian) -> Self::Word {
217 self.vmaddr.get(endian)
218 }
219 fn vmsize(&self, endian: Self::Endian) -> Self::Word {
220 self.vmsize.get(endian)
221 }
222 fn fileoff(&self, endian: Self::Endian) -> Self::Word {
223 self.fileoff.get(endian)
224 }
225 fn filesize(&self, endian: Self::Endian) -> Self::Word {
226 self.filesize.get(endian)
227 }
228 fn maxprot(&self, endian: Self::Endian) -> u32 {
229 self.maxprot.get(endian)
230 }
231 fn initprot(&self, endian: Self::Endian) -> u32 {
232 self.initprot.get(endian)
233 }
234 fn nsects(&self, endian: Self::Endian) -> u32 {
235 self.nsects.get(endian)
236 }
237 fn flags(&self, endian: Self::Endian) -> u32 {
238 self.flags.get(endian)
239 }
240 }
241
242 impl<Endian: endian::Endian> Segment for macho::SegmentCommand64<Endian> {
243 type Word = u64;
244 type Endian = Endian;
245 type Section = macho::Section64<Self::Endian>;
246
247 fn from_command(command: LoadCommandData<Self::Endian>) -> Result<Option<(&Self, &[u8])>> {
248 command.segment_64()
249 }
250
251 fn cmd(&self, endian: Self::Endian) -> u32 {
252 self.cmd.get(endian)
253 }
254 fn cmdsize(&self, endian: Self::Endian) -> u32 {
255 self.cmdsize.get(endian)
256 }
257 fn segname(&self) -> &[u8; 16] {
258 &self.segname
259 }
260 fn vmaddr(&self, endian: Self::Endian) -> Self::Word {
261 self.vmaddr.get(endian)
262 }
263 fn vmsize(&self, endian: Self::Endian) -> Self::Word {
264 self.vmsize.get(endian)
265 }
266 fn fileoff(&self, endian: Self::Endian) -> Self::Word {
267 self.fileoff.get(endian)
268 }
269 fn filesize(&self, endian: Self::Endian) -> Self::Word {
270 self.filesize.get(endian)
271 }
272 fn maxprot(&self, endian: Self::Endian) -> u32 {
273 self.maxprot.get(endian)
274 }
275 fn initprot(&self, endian: Self::Endian) -> u32 {
276 self.initprot.get(endian)
277 }
278 fn nsects(&self, endian: Self::Endian) -> u32 {
279 self.nsects.get(endian)
280 }
281 fn flags(&self, endian: Self::Endian) -> u32 {
282 self.flags.get(endian)
283 }
284 }