Take SHT_NOBITS into account

This commit is contained in:
2024-07-10 23:33:19 +02:00
parent f82dfe38e7
commit a5f280c4c6
2 changed files with 31 additions and 1 deletions

View File

@@ -95,8 +95,11 @@ macro_rules! parse_elf {
let name = &names_section[name_start..name_end];
let name = from_utf8(name).wrap_err(eyre!(".names entry not valid utf-8"))?;
let section_start = entry.start().wrap_err_with(|| name.to_string())?;
// validate that section fits in file (or has SHT_NOBITS set)
let sht_nobits_set = (entry.sh_type.to_native() & 8) != 0;
let section_end = entry.end().wrap_err_with(|| name.to_string())?;
if section_end > elf.len() {
if section_end > elf.len() && !sht_nobits_set {
bail!("section {name:?} end is past eof");
}
@@ -190,6 +193,7 @@ fn main() -> eyre::Result<()> {
let elf = fs::read(opt.elf).wrap_err("failed to read elf file")?;
// extract first part of the header
if elf.len() < HEADER1_LEN {
bail!("not a valid elf file: file too small");
}
@@ -199,6 +203,7 @@ fn main() -> eyre::Result<()> {
let mut out = Output::default();
out.write("header", &header)?;
// validate header
if &header.ei_magic != b"\x7FELF" {
bail!("not a valid elf file: invalid magic");
}
@@ -207,6 +212,7 @@ fn main() -> eyre::Result<()> {
bail!("unknown elf version: 0x{:x}", header.ei_version);
}
// determine endianness and size, then invoke the correct parse macro.
match (header.ei_class, header.ei_data) {
(1, 1) => parse_elf!(LittleEndian32, &mut out, header1, elf),
(2, 1) => parse_elf!(LittleEndian64, &mut out, header1, elf),

View File

@@ -50,6 +50,7 @@ impl ElfConfig for BigEndian64 {
type SymtabEntry = SymbolTableEntry64<BigEndian>;
}
/// First part of an ELF header. Use to determine endian and word size of elf file.
#[derive(Pod, Zeroable, Clone, Copy, Debug, Serialize)]
#[repr(C, packed)]
pub struct ElfHeader1 {
@@ -63,6 +64,7 @@ pub struct ElfHeader1 {
_padding: [u8; 7],
}
/// Second part of an elf header. Size and endianness depends on [ElfHeader1].
#[derive(Pod, Zeroable, Clone, Copy, Debug, Serialize)]
#[repr(C, packed)]
pub struct ElfHeader2<C: ElfConfig> {
@@ -84,15 +86,37 @@ pub struct ElfHeader2<C: ElfConfig> {
#[derive(Pod, Zeroable, Clone, Copy, Debug, Serialize)]
#[repr(C, packed)]
pub struct SectionHeaderEntry<C: ElfConfig> {
/// An index into the section header string table containing the name of this section.
pub sh_name: C::Word,
/// Specifies the section's semantics.
pub sh_type: C::Word,
/// Bitflags that describe the s.ections attributes.
pub sh_flags: C::Addr,
/// If the section will appear in the memory image of a process, this gives the address at
/// which the section should start. Otherwise, this is 0.
pub sh_addr: C::Addr,
/// This member's value gives the byte offset from the beginning of the ELF file to the start
/// of this section. If `SHT_NOBITS` is set in sh_flags, the section occupies no space in the
/// file.
pub sh_offset: C::Addr,
/// The size of the section in bytes.
pub sh_size: C::Addr,
/// Section header table link. Interpretation depends on section type.
pub sh_link: C::Word,
/// Extra section info. Interpretation depends on section type.
pub sh_info: C::Word,
/// Address alignment constraints.
pub sh_addralign: C::Addr,
/// Size in bytes of each entry in the section, or 0 if section does not contain entries.
pub sh_entsize: C::Addr,
}