mirror of
https://github.com/encounter/object.git
synced 2026-03-30 11:32:22 -07:00
read/pe: add SectionTable
Also fix section indices to be 1-based.
This commit is contained in:
+4
-10
@@ -12,14 +12,14 @@ use crate::read::{
|
||||
|
||||
use super::{
|
||||
parse_symbol, CoffSection, CoffSectionIterator, CoffSegment, CoffSegmentIterator,
|
||||
CoffSymbolIterator, SymbolTable,
|
||||
CoffSymbolIterator, SectionTable, SymbolTable,
|
||||
};
|
||||
|
||||
/// A COFF object file.
|
||||
#[derive(Debug)]
|
||||
pub struct CoffFile<'data> {
|
||||
pub(super) header: &'data pe::ImageFileHeader,
|
||||
pub(super) sections: &'data [pe::ImageSectionHeader],
|
||||
pub(super) sections: SectionTable<'data>,
|
||||
// TODO: ImageSymbolExBytes
|
||||
pub(super) symbols: SymbolTable<'data>,
|
||||
pub(super) data: Bytes<'data>,
|
||||
@@ -37,10 +37,7 @@ impl<'data> CoffFile<'data> {
|
||||
// Skip over the optional header and get the section headers.
|
||||
tail.skip(header.size_of_optional_header.get(LE) as usize)
|
||||
.read_error("Invalid COFF optional header size")?;
|
||||
let sections = tail
|
||||
.read_slice(header.number_of_sections.get(LE) as usize)
|
||||
.read_error("Invalid COFF section headers")?;
|
||||
|
||||
let sections = SectionTable::parse(header, tail)?;
|
||||
let symbols = SymbolTable::parse(header, data)?;
|
||||
|
||||
// TODO: maybe validate that the machine is known?
|
||||
@@ -96,10 +93,7 @@ where
|
||||
}
|
||||
|
||||
fn section_by_index(&'file self, index: SectionIndex) -> Result<CoffSection<'data, 'file>> {
|
||||
let section = self
|
||||
.sections
|
||||
.get(index.0)
|
||||
.read_error("Invalid COFF section index")?;
|
||||
let section = self.sections.section(index.0)?;
|
||||
Ok(CoffSection {
|
||||
file: self,
|
||||
index,
|
||||
|
||||
@@ -13,6 +13,70 @@ use crate::read::{
|
||||
|
||||
use super::{CoffFile, CoffRelocationIterator};
|
||||
|
||||
/// The table of section headers in a COFF or PE file.
|
||||
#[derive(Debug, Default, Clone, Copy)]
|
||||
pub struct SectionTable<'data> {
|
||||
sections: &'data [pe::ImageSectionHeader],
|
||||
}
|
||||
|
||||
impl<'data> SectionTable<'data> {
|
||||
/// Parse the section table.
|
||||
///
|
||||
/// `data` must be the data following the optional header.
|
||||
pub fn parse(header: &pe::ImageFileHeader, mut data: Bytes<'data>) -> Result<Self> {
|
||||
let sections = data
|
||||
.read_slice(header.number_of_sections.get(LE) as usize)
|
||||
.read_error("Invalid COFF/PE section headers")?;
|
||||
Ok(SectionTable { sections })
|
||||
}
|
||||
|
||||
/// Iterate over the section headers.
|
||||
///
|
||||
/// Warning: sections indices start at 1.
|
||||
#[inline]
|
||||
pub fn iter(&self) -> slice::Iter<'data, pe::ImageSectionHeader> {
|
||||
self.sections.iter()
|
||||
}
|
||||
|
||||
/// Return true if the section table is empty.
|
||||
#[inline]
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.sections.is_empty()
|
||||
}
|
||||
|
||||
/// The number of section headers.
|
||||
#[inline]
|
||||
pub fn len(&self) -> usize {
|
||||
self.sections.len()
|
||||
}
|
||||
|
||||
/// Return the section header at the given index.
|
||||
///
|
||||
/// The index is 1-based.
|
||||
pub fn section(&self, index: usize) -> read::Result<&'data pe::ImageSectionHeader> {
|
||||
self.sections
|
||||
.get(index.wrapping_sub(1))
|
||||
.read_error("Invalid COFF/PE section index")
|
||||
}
|
||||
|
||||
/// Return the section header with the given name.
|
||||
///
|
||||
/// The returned index is 1-based.
|
||||
///
|
||||
/// Ignores sections with invalid names.
|
||||
pub fn section_by_name(
|
||||
&self,
|
||||
strings: StringTable<'data>,
|
||||
name: &[u8],
|
||||
) -> Option<(usize, &'data pe::ImageSectionHeader)> {
|
||||
self.sections
|
||||
.iter()
|
||||
.enumerate()
|
||||
.find(|(_, section)| section.name(strings) == Ok(name))
|
||||
.map(|(index, section)| (index + 1, section))
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator over the loadable sections of a `CoffFile`.
|
||||
#[derive(Debug)]
|
||||
pub struct CoffSegmentIterator<'data, 'file>
|
||||
|
||||
+14
-15
@@ -8,11 +8,10 @@ use crate::pe;
|
||||
use crate::pod::{Bytes, Pod};
|
||||
use crate::read::coff::{parse_symbol, CoffSymbolIterator, SymbolTable};
|
||||
use crate::read::{
|
||||
self, Error, FileFlags, Object, ObjectSection, ReadError, Result, SectionIndex, Symbol,
|
||||
SymbolIndex, SymbolMap,
|
||||
self, Error, FileFlags, Object, ReadError, Result, SectionIndex, Symbol, SymbolIndex, SymbolMap,
|
||||
};
|
||||
|
||||
use super::{PeSection, PeSectionIterator, PeSegment, PeSegmentIterator};
|
||||
use super::{PeSection, PeSectionIterator, PeSegment, PeSegmentIterator, SectionTable};
|
||||
|
||||
/// A PE32 (32-bit) image file.
|
||||
pub type PeFile32<'data> = PeFile<'data, pe::ImageNtHeaders32>;
|
||||
@@ -25,7 +24,7 @@ pub struct PeFile<'data, Pe: ImageNtHeaders> {
|
||||
pub(super) dos_header: &'data pe::ImageDosHeader,
|
||||
pub(super) nt_headers: &'data Pe,
|
||||
pub(super) data_directories: &'data [pe::ImageDataDirectory],
|
||||
pub(super) sections: &'data [pe::ImageSectionHeader],
|
||||
pub(super) sections: SectionTable<'data>,
|
||||
pub(super) symbols: SymbolTable<'data>,
|
||||
pub(super) data: Bytes<'data>,
|
||||
}
|
||||
@@ -91,11 +90,9 @@ impl<'data, Pe: ImageNtHeaders> PeFile<'data, Pe> {
|
||||
.read_error("Invalid PE number of RVA and sizes")?;
|
||||
|
||||
// Section headers are after the optional header.
|
||||
let sections = nt_tail
|
||||
.read_slice(nt_headers.file_header().number_of_sections.get(LE) as usize)
|
||||
.read_error("Invalid PE section headers")?;
|
||||
|
||||
let symbols = SymbolTable::parse(&nt_headers.file_header(), data)?;
|
||||
let sections = SectionTable::parse(nt_headers.file_header(), nt_tail)?;
|
||||
// Symbols are at an offset specified in the file header.
|
||||
let symbols = SymbolTable::parse(nt_headers.file_header(), data)?;
|
||||
|
||||
Ok(PeFile {
|
||||
dos_header,
|
||||
@@ -153,15 +150,17 @@ where
|
||||
}
|
||||
|
||||
fn section_by_name(&'file self, section_name: &str) -> Option<PeSection<'data, 'file, Pe>> {
|
||||
self.sections()
|
||||
.find(|section| section.name() == Ok(section_name))
|
||||
self.sections
|
||||
.section_by_name(self.symbols.strings, section_name.as_bytes())
|
||||
.map(|(index, section)| PeSection {
|
||||
file: self,
|
||||
index: SectionIndex(index),
|
||||
section,
|
||||
})
|
||||
}
|
||||
|
||||
fn section_by_index(&'file self, index: SectionIndex) -> Result<PeSection<'data, 'file, Pe>> {
|
||||
let section = self
|
||||
.sections
|
||||
.get(index.0)
|
||||
.read_error("Invalid PE section index")?;
|
||||
let section = self.sections.section(index.0)?;
|
||||
Ok(PeSection {
|
||||
file: self,
|
||||
index,
|
||||
|
||||
@@ -12,3 +12,5 @@ pub use file::*;
|
||||
|
||||
mod section;
|
||||
pub use section::*;
|
||||
|
||||
pub use super::coff::SectionTable;
|
||||
|
||||
@@ -134,7 +134,7 @@ impl<'data, 'file, Pe: ImageNtHeaders> Iterator for PeSectionIterator<'data, 'fi
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.iter.next().map(|(index, section)| PeSection {
|
||||
file: self.file,
|
||||
index: SectionIndex(index),
|
||||
index: SectionIndex(index + 1),
|
||||
section,
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user