reading header
This commit is contained in:
parent
082a52d895
commit
d60cd92a94
8 changed files with 6150 additions and 33 deletions
11
Cargo.lock
generated
11
Cargo.lock
generated
|
@ -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]]
|
||||
|
|
|
@ -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
5982
elf/src/constants.rs
Normal file
File diff suppressed because it is too large
Load diff
37
elf/src/elf.rs
Normal file
37
elf/src/elf.rs
Normal 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
81
elf/src/header.rs
Normal 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);
|
||||
}
|
|
@ -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(())
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in a new issue