Take SHT_NOBITS into account
This commit is contained in:
@@ -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),
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user