/// Generalized 32/64 bit Section #[derive(Default)] pubstruct Section { /// name of this section pub sectname: [u8; 16], /// segment this section goes in pub segname: [u8; 16], /// memory address of this section pub addr: u64, /// size in bytes of this section pub size: u64, /// file offset of this section pub offset: u32, /// section alignment (power of 2) pub align: u32, /// file offset of relocation entries pub reloff: u32, /// number of relocation entries pub nreloc: u32, /// flags (section type and attributes pub flags: u32,
}
impl Section { /// The name of this section pubfn name(&self) -> error::Result<&str> {
Ok(self.sectname.pread::<&str>(0)?)
} /// The containing segment's name pubfn segname(&self) -> error::Result<&str> {
Ok(self.segname.pread::<&str>(0)?)
} /// Iterate this sections relocations given `data`; `data` must be the original binary pubfn iter_relocations<'b>(
&self,
data: &'b [u8],
ctx: container::Ctx,
) -> RelocationIterator<'b> { let offset = self.reloff as usize;
debug!( "Relocations for {} starting at offset: {:#x}", self.name().unwrap_or("BAD_SECTION_NAME"),
offset
);
RelocationIterator {
offset,
nrelocs: self.nreloc as usize,
count: 0,
data,
ctx: ctx.le,
}
}
}
impl<'a> Iterator for SectionIterator<'a> { type Item = error::Result<(Section, SectionData<'a>)>; fn next(&mutself) -> Option<Self::Item> { ifself.idx >= self.count {
None
} else { self.idx += 1; matchself.data.gread_with::<Section>(&mutself.offset, self.ctx) {
Ok(section) => { let section_type = section.flags & SECTION_TYPE; let data = if section_type == S_ZEROFILL
|| section_type == S_GB_ZEROFILL
|| section_type == S_THREAD_LOCAL_ZEROFILL
{
&[]
} else { // it's not uncommon to encounter macho files where files are // truncated but the sections are still remaining in the header. // Because of this we want to not panic here but instead just // slice down to a empty data slice. This way only if code // actually needs to access those sections it will fall over. self.data
.get(section.offset as usize..)
.unwrap_or_else(|| {
warn!( "section #{} offset {} out of bounds", self.idx, section.offset
);
&[]
})
.get(..section.size as usize)
.unwrap_or_else(|| {
warn!("section #{} size {} out of bounds", self.idx, section.size);
&[]
})
};
Some(Ok((section, data)))
}
Err(e) => Some(Err(e)),
}
}
}
}
impl<'a, 'b> IntoIterator for &'b Segment<'a> { type Item = error::Result<(Section, SectionData<'a>)>; type IntoIter = SectionIterator<'a>; fn into_iter(self) -> Self::IntoIter {
SectionIterator {
data: self.raw_data,
count: self.nsects as usize,
offset: self.offset + Segment::size_with(&self.ctx),
idx: 0,
ctx: self.ctx,
}
}
}
impl<'a> ctx::TryIntoCtx<container::Ctx> for Segment<'a> { type Error = crate::error::Error; fn try_into_ctx(self, bytes: &mut [u8], ctx: container::Ctx) -> Result<usize, Self::Error> { let segment_size = Self::size_with(&ctx); // should be able to write the section data inline after this, but not working at the moment //let section_size = bytes.pwrite(data, segment_size)?; //debug!("Segment size: {} raw section data size: {}", segment_size, data.len()); if ctx.is_big() {
bytes.pwrite_with::<SegmentCommand64>(self.into(), 0, ctx.le)?;
} else {
bytes.pwrite_with::<SegmentCommand32>(self.into(), 0, ctx.le)?;
} //debug!("Section size: {}", section_size);
Ok(segment_size)
}
}
/// Read data that belongs to a segment if the offset is within the boundaries of bytes. fn segment_data(bytes: &[u8], fileoff: u64, filesize: u64) -> Result<&[u8], error::Error> { let data: &[u8] = if filesize != 0 {
bytes.pread_with(fileoff as usize, filesize as usize)?
} else {
&[]
};
Ok(data)
}
impl<'a> Segment<'a> { /// Create a new, blank segment, with cmd either `LC_SEGMENT_64`, or `LC_SEGMENT`, depending on `ctx`. /// **NB** You are responsible for providing a correctly marshalled byte array as the sections. You should not use this for anything other than writing. pubfn new(ctx: container::Ctx, sections: &'a [u8]) -> Self {
Segment {
cmd: if ctx.is_big() {
LC_SEGMENT_64
} else {
LC_SEGMENT
},
cmdsize: (Self::size_with(&ctx) + sections.len()) as u32,
segname: [0; 16],
vmaddr: 0,
vmsize: 0,
fileoff: 0,
filesize: 0,
maxprot: 0,
initprot: 0,
nsects: 0,
flags: 0,
data: sections,
offset: 0,
raw_data: &[],
ctx,
}
} /// Get the name of this segment pubfn name(&self) -> error::Result<&str> {
Ok(self.segname.pread::<&str>(0)?)
} /// Get the sections from this segment, erroring if any section couldn't be retrieved pubfn sections(&self) -> error::Result<Vec<(Section, SectionData<'a>)>> { letmut sections = Vec::new(); for section inself.into_iter() {
sections.push(section?);
}
Ok(sections)
} /// Convert the raw C 32-bit segment command to a generalized version pubfn from_32(
bytes: &'a [u8],
segment: &SegmentCommand32,
offset: usize,
ctx: container::Ctx,
) -> Result<Self, error::Error> { Self::from_32_impl(bytes, segment, offset, ctx, false)
}
/// Convert the raw C 32-bit segment command to a generalized version pubfn from_32_lossy(
bytes: &'a [u8],
segment: &SegmentCommand32,
offset: usize,
ctx: container::Ctx,
) -> Result<Self, error::Error> { Self::from_32_impl(bytes, segment, offset, ctx, true)
}
impl<'a, 'b> IntoIterator for &'b Segments<'a> { type Item = &'b Segment<'a>; type IntoIter = ::core::slice::Iter<'b, Segment<'a>>; fn into_iter(self) -> Self::IntoIter { self.segments.iter()
}
}
impl<'a> Segments<'a> { /// Construct a new generalized segment container from this `ctx` pubfn new(_ctx: container::Ctx) -> Self {
Segments {
segments: Vec::new(),
}
} /// Get every section from every segment // thanks to SpaceManic for figuring out the 'b lifetimes here :) pubfn sections<'b>(&'b self) -> Box<dyn Iterator<Item = SectionIterator<'a>> + 'b> { Box::new(self.segments.iter().map(|segment| segment.into_iter()))
}
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.12 Sekunden
(vorverarbeitet am 2026-06-19)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.