2 use core
::{result, str}
;
4 use crate::endian
::{self, Endianness}
;
7 use crate::read
::{self, ObjectSegment, ReadError, ReadRef, Result}
;
9 use super::{LoadCommandData, LoadCommandIterator, MachHeader, MachOFile, Section}
;
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
>;
18 /// An iterator over the segments of a `MachOFile`.
20 pub struct MachOSegmentIterator
<'data
, 'file
, Mach
, R
= &'data
[u8]>
26 pub(super) file
: &'file MachOFile
<'data
, Mach
, R
>,
27 pub(super) commands
: LoadCommandIterator
<'data
, Mach
::Endian
>,
30 impl<'data
, 'file
, Mach
, R
> Iterator
for MachOSegmentIterator
<'data
, 'file
, Mach
, R
>
35 type Item
= MachOSegment
<'data
, 'file
, Mach
, R
>;
37 fn next(&mut self) -> Option
<Self::Item
> {
39 let command
= self.commands
.next().ok()??
;
40 if let Ok(Some((segment
, _
))) = Mach
::Segment
::from_command(command
) {
41 return Some(MachOSegment
{
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
>;
57 /// A segment of a `MachOFile`.
59 pub struct MachOSegment
<'data
, 'file
, Mach
, R
= &'data
[u8]>
65 file
: &'file MachOFile
<'data
, Mach
, R
>,
66 segment
: &'data Mach
::Segment
,
69 impl<'data
, 'file
, Mach
, R
> MachOSegment
<'data
, 'file
, Mach
, R
>
74 fn bytes(&self) -> Result
<&'data
[u8]> {
76 .data(self.file
.endian
, self.file
.data
)
77 .read_error("Invalid Mach-O segment size or offset")
81 impl<'data
, 'file
, Mach
, R
> read
::private
::Sealed
for MachOSegment
<'data
, 'file
, Mach
, R
>
88 impl<'data
, 'file
, Mach
, R
> ObjectSegment
<'data
> for MachOSegment
<'data
, 'file
, Mach
, R
>
94 fn address(&self) -> u64 {
95 self.segment
.vmaddr(self.file
.endian
).into()
99 fn size(&self) -> u64 {
100 self.segment
.vmsize(self.file
.endian
).into()
104 fn align(&self) -> u64 {
110 fn file_range(&self) -> (u64, u64) {
111 self.segment
.file_range(self.file
.endian
)
114 fn data(&self) -> Result
<&'data
[u8]> {
118 fn data_range(&self, address
: u64, size
: u64) -> Result
<Option
<&'data
[u8]>> {
119 Ok(read
::util
::data_range(
128 fn name(&self) -> Result
<Option
<&str>> {
130 str::from_utf8(self.segment
.name())
132 .read_error("Non UTF-8 Mach-O segment name")?
,
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
>;
144 fn from_command(command
: LoadCommandData
<Self::Endian
>) -> Result
<Option
<(&Self, &[u8])>>;
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;
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
],
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())
172 /// Get the segment data from the file data.
174 /// Returns `Err` for invalid values.
175 fn data
<'data
, R
: ReadRef
<'data
>>(
177 endian
: Self::Endian
,
179 ) -> result
::Result
<&'data
[u8], ()> {
180 let (offset
, size
) = self.file_range(endian
);
181 data
.read_bytes_at(offset
, size
)
184 /// Get the array of sections from the data following the segment command.
186 /// Returns `Err` for invalid values.
187 fn sections
<'data
, R
: ReadRef
<'data
>>(
189 endian
: Self::Endian
,
191 ) -> Result
<&'data
[Self::Section
]> {
193 .read_slice_at(0, self.nsects(endian
) as usize)
194 .read_error("Invalid Mach-O number of sections")
198 impl<Endian
: endian
::Endian
> Segment
for macho
::SegmentCommand32
<Endian
> {
200 type Endian
= Endian
;
201 type Section
= macho
::Section32
<Self::Endian
>;
203 fn from_command(command
: LoadCommandData
<Self::Endian
>) -> Result
<Option
<(&Self, &[u8])>> {
207 fn cmd(&self, endian
: Self::Endian
) -> u32 {
210 fn cmdsize(&self, endian
: Self::Endian
) -> u32 {
211 self.cmdsize
.get(endian
)
213 fn segname(&self) -> &[u8; 16] {
216 fn vmaddr(&self, endian
: Self::Endian
) -> Self::Word
{
217 self.vmaddr
.get(endian
)
219 fn vmsize(&self, endian
: Self::Endian
) -> Self::Word
{
220 self.vmsize
.get(endian
)
222 fn fileoff(&self, endian
: Self::Endian
) -> Self::Word
{
223 self.fileoff
.get(endian
)
225 fn filesize(&self, endian
: Self::Endian
) -> Self::Word
{
226 self.filesize
.get(endian
)
228 fn maxprot(&self, endian
: Self::Endian
) -> u32 {
229 self.maxprot
.get(endian
)
231 fn initprot(&self, endian
: Self::Endian
) -> u32 {
232 self.initprot
.get(endian
)
234 fn nsects(&self, endian
: Self::Endian
) -> u32 {
235 self.nsects
.get(endian
)
237 fn flags(&self, endian
: Self::Endian
) -> u32 {
238 self.flags
.get(endian
)
242 impl<Endian
: endian
::Endian
> Segment
for macho
::SegmentCommand64
<Endian
> {
244 type Endian
= Endian
;
245 type Section
= macho
::Section64
<Self::Endian
>;
247 fn from_command(command
: LoadCommandData
<Self::Endian
>) -> Result
<Option
<(&Self, &[u8])>> {
251 fn cmd(&self, endian
: Self::Endian
) -> u32 {
254 fn cmdsize(&self, endian
: Self::Endian
) -> u32 {
255 self.cmdsize
.get(endian
)
257 fn segname(&self) -> &[u8; 16] {
260 fn vmaddr(&self, endian
: Self::Endian
) -> Self::Word
{
261 self.vmaddr
.get(endian
)
263 fn vmsize(&self, endian
: Self::Endian
) -> Self::Word
{
264 self.vmsize
.get(endian
)
266 fn fileoff(&self, endian
: Self::Endian
) -> Self::Word
{
267 self.fileoff
.get(endian
)
269 fn filesize(&self, endian
: Self::Endian
) -> Self::Word
{
270 self.filesize
.get(endian
)
272 fn maxprot(&self, endian
: Self::Endian
) -> u32 {
273 self.maxprot
.get(endian
)
275 fn initprot(&self, endian
: Self::Endian
) -> u32 {
276 self.initprot
.get(endian
)
278 fn nsects(&self, endian
: Self::Endian
) -> u32 {
279 self.nsects
.get(endian
)
281 fn flags(&self, endian
: Self::Endian
) -> u32 {
282 self.flags
.get(endian
)