Add beginning program and section header parsing, slight cleanup and comments

This commit is contained in:
Garrett Dickinson 2023-02-09 01:47:19 -06:00
parent 0b6fc85612
commit 80d346ae03
3 changed files with 141 additions and 22 deletions

View File

@ -1,5 +1,15 @@
// elf.rs
// Author: Garrett Dickinson
// Created: 02/02/2023
// Description: Provides constant and struct definitions for data
// structures related to the ELF binary specification
// Generic ELF information offsets.
///////////////////////////////////////////////////////////////////////////////
///
/// Generic ELF information offsets.
///
///////////////////////////////////////////////////////////////////////////////
pub const MAGIC_NUMBER: &[u8] = &[0x7F,0x45,0x4C,0x46];
pub const ARCH_OFFSET: u8 = 0x04; // x86 or x64 indiicator; 1 byte
@ -9,10 +19,14 @@ pub const TYPE_OFFSET: u8 = 0x10; // Object type identifier; 2 bytes
pub const MACHINE_OFFSET: u8 = 0x12; // Instruction set type; 2 bytes
// Offsets for file header entry points and table inforamtion.
// Arrayed offset are split by architecture:
// 0 : x86
// 1 : x86_64
///////////////////////////////////////////////////////////////////////////////
///
/// Offsets for file header entry points and table information.
/// Arrayed offset are split by architecture:
/// 0 : x86
/// 1 : x86_64
///
///////////////////////////////////////////////////////////////////////////////
pub const ENTRYPOINT_OFFSET: u8 = 0x18;
pub const PHOFF_OFFSET: [u8; 2] = [0x1C, 0x20]; // Program header table pointer; 2 bytes
@ -25,8 +39,49 @@ pub const SHNUM_OFFSET: [u8; 2] = [0x30, 0x3C]; // Number of entries in s
pub const SHSTRNDX_OFFSET: [u8; 2] = [0x32, 0x3E]; // Index of section header that contains names; 2 bytes
///////////////////////////////////////////////////////////////////////////////
///
/// Offsets for program header information.
/// Arrayed offset are split by architecture:
/// 0 : x86
/// 1 : x86_64
///
///////////////////////////////////////////////////////////////////////////////
pub const PH_TYPE_OFFSET: u8 = 0x00;
pub const PH_FLAGS_OFFSET: [u8; 2] = [0x18, 0x04];
pub const PH_OFFSET_OFFSET: [u8; 2] = [0x04, 0x08];
pub const PH_VADDR_OFFSET: [u8; 2] = [0x08, 0x10];
pub const PH_PADDR_OFFSET: [u8; 2] = [0x0C, 0x18];
pub const PH_FILESZ_OFFSET: [u8; 2] = [0x10, 0x20];
pub const PH_MEMSZ_OFFSET: [u8; 2] = [0x14, 0x28];
pub const PH_ALIGN_OFFSET: [u8; 2] = [0x1C, 0x30];
///////////////////////////////////////////////////////////////////////////////
///
/// Offsets for section header information.
/// Arrayed offset are split by architecture:
/// 0 : x86
/// 1 : x86_64
///
///////////////////////////////////////////////////////////////////////////////
pub const SH_NAME_OFFSET: u8 = 0x00;
pub const SH_TYPE_OFFSET: u8 = 0x04;
pub const SH_FLAGS_OFFSET: u8 = 0x08;
pub const SH_ADDR_OFFSET: [u8; 2] = [0x0C, 0x10];
pub const SH_OFFSET_OFFSET: [u8; 2] = [0x10, 0x18];
pub const SH_SIZE_OFFSET: [u8; 2] = [0x14, 0x20];
pub const SH_LINK_OFFSET: [u8; 2] = [0x18, 0x28];
pub const SH_INFO_OFFSET: [u8; 2] = [0x1C, 0x2C];
pub const SH_ADDRALIGN_OFFSET: [u8; 2] = [0x20, 0x30];
pub const SH_ENTSIZE_OFFSET: [u8; 2] = [0x24, 0x38];
#[derive(Debug)]
pub enum ArchitecureType {
pub enum ArchitectureType {
X86,
X86_64,
Unknown
@ -40,10 +95,13 @@ pub enum EndianType {
Unknown
}
// TODO: Types in structs for holding addresses are most likely
// too small, increase to u32 maybe?
// Refer to structs in /usr/include/elf.h for this
#[derive(Debug)]
pub struct FileHeader {
pub arch: ArchitecureType,
pub arch: ArchitectureType,
pub is_x86_64: bool,
pub endian: EndianType,
pub abi: u8,
@ -69,6 +127,7 @@ pub struct ProgramHeader {
pub vaddr: u8,
pub paddr: u8,
pub filesz: u8,
pub memsz: u8,
pub align: u8,
}

View File

@ -43,11 +43,33 @@ fn main() {
// Build the File Header data structure
let file_header: elf::FileHeader = build_file_header(bytes);
// TODO: This is fundamentally wrong. Using the phentsize and phnum
// values from the file header, iterate over the program header
// table to find all of the individual program headers. There is
// not just one over-arching program header
// Build Program Header data structure
//let program_header: elf::ProgramHeader = build_program_header(bytes, file_header.is_x86_64);
let program_header: elf::ProgramHeader = build_program_header(
bytes,
file_header.phoff,
file_header.is_x86_64
);
// TODO: Same thing applies for the Section Headers...
// Build Section Header data structure
let section_header: elf::SectionHeader = build_section_header(
bytes,
file_header.shoff,
file_header.is_x86_64
);
println!("{:?}", file_header);
//println!("{:?}", program_header);
println!("{:?}", program_header);
println!("{:?}", section_header);
} else {
println!("[Error] Could not find magic number, is this an ELF executable?")
@ -91,15 +113,47 @@ fn build_file_header(data: &Vec<u8>) -> elf::FileHeader {
}
// fn build_program_header(data: &Vec<u8>, is_x86_64: bool) -> elf::ProgramHeader {
fn build_program_header(data: &Vec<u8>, phoffset: u8, is_x86_64: bool) -> elf::ProgramHeader {
// let arch: i8 = if is_x86_64 { 1 } else { 0 };
// Cast the supplied is_x86_64 bool to an array offset
// 0 : x86
// 1 : x64
let arch: usize = is_x86_64.into();
// let mut program_header: elf::ProgramHeader;
let program_header: elf::ProgramHeader = elf::ProgramHeader {
program_type: data[(elf::PH_TYPE_OFFSET + phoffset) as usize],
flags: data[(elf::PH_FLAGS_OFFSET[arch] + phoffset) as usize],
offset: data[(elf::PH_OFFSET_OFFSET[arch] + phoffset) as usize],
vaddr: data[(elf::PH_VADDR_OFFSET[arch] + phoffset) as usize],
paddr: data[(elf::PH_PADDR_OFFSET[arch] + phoffset) as usize],
filesz: data[(elf::PH_FILESZ_OFFSET[arch] + phoffset) as usize],
memsz: data[(elf::PH_MEMSZ_OFFSET[arch] + phoffset) as usize],
align: data[(elf::PH_ALIGN_OFFSET[arch] + phoffset) as usize],
};
// // let mut program_header: elf::ProgramHeader = elf::ProgramHeader {
// // arch: util::parse_architecture(data[elf::ARCH_OFFSET as usize])
// // };
return program_header;
}
// return program_header;
// }
fn build_section_header(data: &Vec<u8>, shoffset: u8, is_x86_64: bool) -> elf::SectionHeader {
// Cast the supplied is_x86_64 bool to an array offset
// 0 : x86
// 1 : x64
let arch: usize = is_x86_64.into();
let section_header: elf::SectionHeader = elf::SectionHeader {
name: data[(elf::SH_NAME_OFFSET + shoffset) as usize],
section_type: data[(elf::SH_TYPE_OFFSET + shoffset) as usize],
flags: data[(elf::SH_FLAGS_OFFSET + shoffset) as usize],
addr: data[(elf::SH_ADDR_OFFSET[arch] + shoffset) as usize],
offset: data[(elf::SH_OFFSET_OFFSET[arch] + shoffset) as usize],
size: data[(elf::SH_SIZE_OFFSET[arch] + shoffset) as usize],
link: data[(elf::SH_LINK_OFFSET[arch] + shoffset) as usize],
info: data[(elf::SH_INFO_OFFSET[arch] + shoffset) as usize],
addralign: data[(elf::SH_ADDRALIGN_OFFSET[arch] + shoffset) as usize],
entsize: data[(elf::SH_ENTSIZE_OFFSET[arch] + shoffset) as usize],
};
return section_header;
}

View File

@ -1,4 +1,10 @@
use crate::elf::{self, EndianType, ArchitecureType};
// util.rs
// Author: Garrett Dickinson
// Created: 02/02/2023
// Description: Utility script for storing common-use and helper
// functions.
use crate::elf::{self, EndianType, ArchitectureType};
pub fn parse_endian(endian: u8) -> elf::EndianType {
@ -10,11 +16,11 @@ pub fn parse_endian(endian: u8) -> elf::EndianType {
}
pub fn parse_architecture(arch: u8) -> elf::ArchitecureType {
pub fn parse_architecture(arch: u8) -> elf::ArchitectureType {
match arch {
0x01 => return ArchitecureType::X86,
0x02 => return ArchitecureType::X86_64,
_ => return ArchitecureType::Unknown
0x01 => return ArchitectureType::X86,
0x02 => return ArchitectureType::X86_64,
_ => return ArchitectureType::Unknown
}
}