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"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "byteordered"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "32687ee8ab498526e3ef07dfbede151650ce202dc83c53494645a24677d89b37"
|
||||||
|
dependencies = [
|
||||||
|
"byteorder",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap"
|
name = "clap"
|
||||||
version = "2.33.3"
|
version = "2.33.3"
|
||||||
|
@ -60,7 +69,7 @@ name = "elf"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"byteorder",
|
"byteordered",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
|
@ -5,4 +5,4 @@ edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.41"
|
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::io::{Read, Write};
|
||||||
use std::mem::MaybeUninit;
|
use std::mem::MaybeUninit;
|
||||||
|
|
||||||
use anyhow::Result;
|
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)]
|
enum Bitness {
|
||||||
pub struct Elf {
|
Bits32,
|
||||||
header: Header,
|
Bits64,
|
||||||
program_header: Option<ProgramHeader>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[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)]
|
#[derive(Debug)]
|
||||||
pub struct Header {
|
pub enum Elf {
|
||||||
e_ident: [u8; 16],
|
Elf32(crate::elf::elf32::Elf),
|
||||||
e_type: u16,
|
Elf64(crate::elf::elf64::Elf),
|
||||||
e_machine: u16,
|
|
||||||
e_version: u32,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Header {
|
impl Default for Elf {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
let mut header: Self = unsafe { MaybeUninit::zeroed().assume_init() };
|
match SYSTEM_BITNESS {
|
||||||
header.e_ident[0] = 0x7f;
|
Bitness::Bits32 => Elf::Elf32(elf32::Elf::default()),
|
||||||
header.e_ident[1] = b'E';
|
Bitness::Bits64 => Elf::Elf64(elf64::Elf::default()),
|
||||||
header.e_ident[2] = b'L';
|
}
|
||||||
header.e_ident[3] = b'F';
|
|
||||||
header
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
|
||||||
pub struct ProgramHeader {}
|
|
||||||
|
|
||||||
impl Elf {
|
impl Elf {
|
||||||
pub fn read<R: Read>(mut r: R) -> Result<Elf> {
|
pub fn read<R: Read>(mut r: R) -> Result<Self> {
|
||||||
let mut elf = Elf::default();
|
let mut e_ident: E_IDENT = [0u8; EI_NIDENT];
|
||||||
|
r.read_exact(&mut e_ident);
|
||||||
|
|
||||||
// header
|
let res = match e_ident[EI_CLASS] {
|
||||||
r.read_exact(&mut elf.header.e_ident)?;
|
ELFCLASS32 => Elf::Elf32(elf32::Elf::continue_read(e_ident, r)?),
|
||||||
elf.header.e_type = r.read_u16::<LittleEndian>()?;
|
ELFCLASS64 => Elf::Elf64(elf64::Elf::continue_read(e_ident, r)?),
|
||||||
|
n => bail!("invalid class: {}", n),
|
||||||
Ok(elf)
|
};
|
||||||
|
Ok(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write<W: Write>(&self, mut w: W) -> Result<()> {
|
pub fn write<W: Write>(&self, mut w: W) -> Result<()> {
|
||||||
w.write(&self.header.e_ident)?;
|
|
||||||
w.flush()?;
|
w.flush()?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -14,6 +14,7 @@ pub(crate) fn link(opt: &Opt) -> Result<()> {
|
||||||
LinkUnit::Path(path) => {
|
LinkUnit::Path(path) => {
|
||||||
let file = File::open(path)?;
|
let file = File::open(path)?;
|
||||||
let elf = Elf::read(&file)?;
|
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 {
|
pub fn normalize_path(path: &Path) -> PathBuf {
|
||||||
let mut components = path.components().peekable();
|
let mut components = path.components().peekable();
|
||||||
|
@ -25,4 +25,4 @@ pub fn normalize_path(path: &Path) -> PathBuf {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue