#[repr(C)] #[derive(Copy, Clone, Eq, PartialEq, Default)] #[cfg_attr(
feature = "alloc",
derive(scroll::Pread, scroll::Pwrite, scroll::SizeWith)
)] /// Section Headers are typically used by humans and static linkers for additional information or how to relocate the object /// /// **NOTE** section headers are strippable from a binary without any loss of portability/executability; _do not_ rely on them being there! pubstruct SectionHeader { /// Section name (string tbl index) pub sh_name: u32, /// Section type pub sh_type: u32, /// Section flags pub sh_flags: $size, /// Section virtual addr at execution pub sh_addr: $size, /// Section file offset pub sh_offset: $size, /// Section size in bytes pub sh_size: $size, /// Link to another section pub sh_link: u32, /// Additional section information pub sh_info: u32, /// Section alignment pub sh_addralign: $size, /// Entry size if section holds table pub sh_entsize: $size,
}
use plain; // Declare that this is a plain type. unsafeimpl plain::Plain for SectionHeader {}
if_alloc! { usecrate::elf::section_header::SectionHeader as ElfSectionHeader;
use plain::Plain; use alloc::vec::Vec;
if_std! { usecrate::error::Result;
use std::fs::File; use std::io::{Read, Seek}; use std::io::SeekFrom::Start;
}
impl From<SectionHeader> for ElfSectionHeader { fn from(sh: SectionHeader) -> Self {
ElfSectionHeader {
sh_name: sh.sh_name as usize,
sh_type: sh.sh_type,
sh_flags: u64::from(sh.sh_flags),
sh_addr: u64::from(sh.sh_addr),
sh_offset: u64::from(sh.sh_offset),
sh_size: u64::from(sh.sh_size),
sh_link: sh.sh_link,
sh_info: sh.sh_info,
sh_addralign: u64::from(sh.sh_addralign),
sh_entsize: u64::from(sh.sh_entsize),
}
}
} impl From<ElfSectionHeader> for SectionHeader { fn from(sh: ElfSectionHeader) -> Self {
SectionHeader {
sh_name : sh.sh_name as u32,
sh_type : sh.sh_type,
sh_flags : sh.sh_flags as $size,
sh_addr : sh.sh_addr as $size,
sh_offset : sh.sh_offset as $size,
sh_size : sh.sh_size as $size,
sh_link : sh.sh_link,
sh_info : sh.sh_info,
sh_addralign: sh.sh_addralign as $size,
sh_entsize : sh.sh_entsize as $size,
}
}
}
impl SectionHeader { // FIXME: > 65535 sections pubfn from_bytes(bytes: &[u8], shnum: usize) -> Vec<SectionHeader> { letmut shdrs = vec![SectionHeader::default(); shnum];
shdrs.copy_from_bytes(bytes).expect("buffer is too short for given number of entries");
shdrs
}
if_alloc! { usecrate::error; use core::fmt; use core::result; use core::ops::Range; use scroll::ctx; usecrate::container::{Container, Ctx};
#[cfg(feature = "endian_fd")] use alloc::vec::Vec;
#[derive(Default, PartialEq, Clone)] /// A unified SectionHeader - convertable to and from 32-bit and 64-bit variants pubstruct SectionHeader { /// Section name (string tbl index) pub sh_name: usize, /// Section type pub sh_type: u32, /// Section flags pub sh_flags: u64, /// Section virtual addr at execution pub sh_addr: u64, /// Section file offset pub sh_offset: u64, /// Section size in bytes pub sh_size: u64, /// Link to another section pub sh_link: u32, /// Additional section information pub sh_info: u32, /// Section alignment pub sh_addralign: u64, /// Entry size if section holds table pub sh_entsize: u64,
}
impl SectionHeader { /// Return the size of the underlying section header, given a `Ctx` #[inline] pubfn size(ctx: Ctx) -> usize { use scroll::ctx::SizeWith; Self::size_with(&ctx)
} pubfn new() -> Self {
SectionHeader {
sh_name: 0,
sh_type: SHT_PROGBITS,
sh_flags: u64::from(SHF_ALLOC),
sh_addr: 0,
sh_offset: 0,
sh_size: 0,
sh_link: 0,
sh_info: 0,
sh_addralign: 2 << 8,
sh_entsize: 0,
}
} /// Returns this section header's file offset range, /// if the section occupies space in fhe file. pubfn file_range(&self) -> Option<Range<usize>> { // Sections with type SHT_NOBITS have no data in the file itself, // they only exist in memory. ifself.sh_type == SHT_NOBITS {
None
} else {
Some(self.sh_offset as usize..(self.sh_offset as usize).saturating_add(self.sh_size as usize))
}
} /// Returns this section header's virtual memory range pubfn vm_range(&self) -> Range<usize> { self.sh_addr as usize..(self.sh_addr as usize).saturating_add(self.sh_size as usize)
} /// Parse `count` section headers from `bytes` at `offset`, using the given `ctx` /// Assuming this is read from the whole file, it will check offset. #[cfg(feature = "endian_fd")] pubfn parse(bytes: &[u8], offset: usize, count: usize, ctx: Ctx) -> error::Result<Vec<SectionHeader>> { // Zero offset means no section headers, not even the null section header. if offset == 0 { return Ok(Vec::new());
} Self::parse_from(bytes, offset, count, ctx)
} /// Parse `count` section headers from `bytes` at `offset`, using the given `ctx` /// without performing any offset checking to allow parsing relatively #[cfg(feature = "endian_fd")] pubfn parse_from(bytes: &[u8], mut offset: usize, mut count: usize, ctx: Ctx) -> error::Result<Vec<SectionHeader>> { use scroll::Pread; let empty_sh = bytes.gread_with::<SectionHeader>(&mut offset, ctx)?; if count == 0as usize { // Zero count means either no section headers or the number of section headers // overflows SHN_LORESERVE, in which case the count is stored in the sh_size field // of the null section header.
count = empty_sh.sh_size as usize;
}
// Sanity check to avoid OOM if count > bytes.len() / Self::size(ctx) { return Err(error::Error::BufferTooShort(count, "section headers"));
} letmut section_headers = Vec::with_capacity(count);
section_headers.push(empty_sh); for _ in1..count { let shdr = bytes.gread_with(&mut offset, ctx)?;
section_headers.push(shdr);
}
Ok(section_headers)
} pubfn check_size(&self, size: usize) -> error::Result<()> { ifself.sh_type == SHT_NOBITS || self.sh_size == 0 { return Ok(());
} let (end, overflow) = self.sh_offset.overflowing_add(self.sh_size); if overflow || end > size as u64 { let message = format!("Section {} size ({}) + offset ({}) is out of bounds. Overflowed: {}", self.sh_name, self.sh_offset, self.sh_size, overflow); return Err(error::Error::Malformed(message));
} let (_, overflow) = self.sh_addr.overflowing_add(self.sh_size); if overflow { let message = format!("Section {} size ({}) + addr ({}) is out of bounds. Overflowed: {}", self.sh_name, self.sh_addr, self.sh_size, overflow); return Err(error::Error::Malformed(message));
}
Ok(())
} pubfn is_relocation(&self) -> bool { self.sh_type == SHT_RELA
} pubfn is_executable(&self) -> bool { self.is_alloc() && self.sh_flags as u32 & SHF_EXECINSTR == SHF_EXECINSTR
} pubfn is_writable(&self) -> bool { self.is_alloc() && self.sh_flags as u32 & SHF_WRITE == SHF_WRITE
} pubfn is_alloc(&self) -> bool { self.sh_flags as u32 & SHF_ALLOC == SHF_ALLOC
}
}
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.