reading header

This commit is contained in:
Michael Zhang 2021-06-28 18:45:30 -05:00
parent 082a52d895
commit d60cd92a94
Signed by: michael
GPG key ID: BDA47A31A3C8EE6B
8 changed files with 6150 additions and 33 deletions

11
Cargo.lock generated
View file

@ -40,6 +40,15 @@ version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]]
name = "byteordered"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32687ee8ab498526e3ef07dfbede151650ce202dc83c53494645a24677d89b37"
dependencies = [
"byteorder",
]
[[package]]
name = "clap"
version = "2.33.3"
@ -60,7 +69,7 @@ name = "elf"
version = "0.1.0"
dependencies = [
"anyhow",
"byteorder",
"byteordered",
]
[[package]]

View file

@ -5,4 +5,4 @@ edition = "2018"
[dependencies]
anyhow = "1.0.41"
byteorder = "1.4.3"
byteordered = "0.5.0"

5982
elf/src/constants.rs Normal file

File diff suppressed because it is too large Load diff

37
elf/src/elf.rs Normal file
View file

@ -0,0 +1,37 @@
use std::io::Read;
use std::mem::MaybeUninit;
use anyhow::Result;
use crate::constants::*;
use crate::header::E_IDENT;
macro_rules! elf {
($size:ty) => {
#[derive(Debug, Default)]
pub struct Elf {
pub header: Header,
}
impl Elf {
pub(crate) fn continue_read<R: Read>(e_ident: E_IDENT, mut r: R) -> Result<Self> {
let mut elf: Self = unsafe { MaybeUninit::zeroed().assume_init() };
elf.header = Header::continue_read(e_ident, r)?;
Ok(elf)
}
}
};
}
pub mod elf32 {
use super::*;
use crate::header::header32::Header;
elf!(u32);
}
pub mod elf64 {
use super::*;
use crate::header::header64::Header;
elf!(u64);
}

81
elf/src/header.rs Normal file
View file

@ -0,0 +1,81 @@
use std::io::Read;
use std::mem::MaybeUninit;
use anyhow::Result;
use byteordered::{ByteOrdered, Endianness};
use crate::constants::*;
pub type E_IDENT = [u8; EI_NIDENT];
macro_rules! elf_header {
($size:ty, $read_size:ident) => {
#[derive(Debug)]
pub struct Header {
pub e_ident: E_IDENT,
pub e_type: u16,
pub e_machine: u16,
pub e_version: u32,
pub e_entry: $size,
pub e_phoff: $size,
pub e_shoff: $size,
pub e_flags: u32,
pub e_ehsize: u16,
pub e_phentsize: u16,
pub e_phnum: u16,
pub e_shentsize: u16,
pub e_shnum: u16,
pub e_shstrndx: u16,
}
impl Default for Header {
fn default() -> Self {
let mut header: Self = unsafe { MaybeUninit::zeroed().assume_init() };
header.e_ident[EI_MAG0] = ELFMAG0;
header.e_ident[EI_MAG1] = ELFMAG1;
header.e_ident[EI_MAG2] = ELFMAG2;
header.e_ident[EI_MAG3] = ELFMAG3;
header
}
}
impl Header {
pub(crate) fn continue_read<R: Read>(e_ident: E_IDENT, mut r: R) -> Result<Self> {
let mut header = Header::default();
header.e_ident = e_ident;
let mut r = match header.e_ident[EI_DATA] {
ELFDATA2LSB => ByteOrdered::runtime(r, Endianness::Little),
ELFDATA2MSB => ByteOrdered::runtime(r, Endianness::Big),
_ => bail!("unknown endianness"),
};
header.e_type = r.read_u16()?;
header.e_machine = r.read_u16()?;
header.e_version = r.read_u32()?;
header.e_entry = r.$read_size()?;
header.e_phoff = r.$read_size()?;
header.e_shoff = r.$read_size()?;
header.e_flags = r.read_u32()?;
header.e_ehsize = r.read_u16()?;
header.e_phentsize = r.read_u16()?;
header.e_phnum = r.read_u16()?;
header.e_shentsize = r.read_u16()?;
header.e_shnum = r.read_u16()?;
header.e_shstrndx = r.read_u16()?;
Ok(header)
}
}
};
}
pub mod header32 {
pub use super::*;
elf_header!(u32, read_u32);
}
pub mod header64 {
pub use super::*;
elf_header!(u64, read_u64);
}

View file

@ -1,52 +1,59 @@
#[macro_use]
extern crate anyhow;
#[allow(dead_code, non_upper_case_globals, non_camel_case_types)]
pub mod constants;
pub mod elf;
pub mod header;
use std::io::{Read, Write};
use std::mem::MaybeUninit;
use anyhow::Result;
use byteorder::{LittleEndian, ReadBytesExt};
const EI_DATA: i32 = 5;
use crate::constants::*;
pub use crate::elf::{elf32, elf64};
use crate::header::E_IDENT;
#[derive(Debug, Default)]
pub struct Elf {
header: Header,
program_header: Option<ProgramHeader>,
enum Bitness {
Bits32,
Bits64,
}
#[cfg(target_pointer_width = "64")]
const SYSTEM_BITNESS: Bitness = Bitness::Bits64;
#[cfg(not(target_pointer_width = "64"))]
const SYSTEM_BITNESS: Bitness = Bitness::Bits32;
#[derive(Debug)]
pub struct Header {
e_ident: [u8; 16],
e_type: u16,
e_machine: u16,
e_version: u32,
pub enum Elf {
Elf32(crate::elf::elf32::Elf),
Elf64(crate::elf::elf64::Elf),
}
impl Default for Header {
impl Default for Elf {
fn default() -> Self {
let mut header: Self = unsafe { MaybeUninit::zeroed().assume_init() };
header.e_ident[0] = 0x7f;
header.e_ident[1] = b'E';
header.e_ident[2] = b'L';
header.e_ident[3] = b'F';
header
match SYSTEM_BITNESS {
Bitness::Bits32 => Elf::Elf32(elf32::Elf::default()),
Bitness::Bits64 => Elf::Elf64(elf64::Elf::default()),
}
}
}
#[derive(Debug, Default)]
pub struct ProgramHeader {}
impl Elf {
pub fn read<R: Read>(mut r: R) -> Result<Elf> {
let mut elf = Elf::default();
pub fn read<R: Read>(mut r: R) -> Result<Self> {
let mut e_ident: E_IDENT = [0u8; EI_NIDENT];
r.read_exact(&mut e_ident);
// header
r.read_exact(&mut elf.header.e_ident)?;
elf.header.e_type = r.read_u16::<LittleEndian>()?;
Ok(elf)
let res = match e_ident[EI_CLASS] {
ELFCLASS32 => Elf::Elf32(elf32::Elf::continue_read(e_ident, r)?),
ELFCLASS64 => Elf::Elf64(elf64::Elf::continue_read(e_ident, r)?),
n => bail!("invalid class: {}", n),
};
Ok(res)
}
pub fn write<W: Write>(&self, mut w: W) -> Result<()> {
w.write(&self.header.e_ident)?;
w.flush()?;
Ok(())

View file

@ -14,6 +14,7 @@ pub(crate) fn link(opt: &Opt) -> Result<()> {
LinkUnit::Path(path) => {
let file = File::open(path)?;
let elf = Elf::read(&file)?;
println!("elf: {:?}", elf);
}
_ => {}
}

View file

@ -1,4 +1,4 @@
use std::path::{Path, PathBuf, Component};
use std::path::{Component, Path, PathBuf};
pub fn normalize_path(path: &Path) -> PathBuf {
let mut components = path.components().peekable();