Move endianness-aware read_u* parsing methods into parse.rs
This is getting us closer to having a more centralized trait-driven parser combinator approach that can hopefully clean up the code a bit and make it easier to follow.
This commit is contained in:
parent
eca60d8f49
commit
e14e083ad3
@ -1,6 +1,5 @@
|
||||
use crate::gabi;
|
||||
use crate::parse::{Endian, Parse};
|
||||
use crate::utils::{read_u16, read_u32, read_u64};
|
||||
use crate::parse::{Endian, Parse, read_u16, read_u32, read_u64};
|
||||
|
||||
/// Encapsulates the contents of the ELF File Header
|
||||
///
|
||||
|
18
src/lib.rs
18
src/lib.rs
@ -10,7 +10,7 @@ pub mod section;
|
||||
pub mod symbol;
|
||||
pub mod parse;
|
||||
|
||||
use crate::parse::{Endian, Parse};
|
||||
use crate::parse::{Endian, Parse, read_u16, read_u32, read_u64};
|
||||
|
||||
mod utils;
|
||||
|
||||
@ -143,19 +143,19 @@ impl File {
|
||||
let mut other: [u8; 1] = [0u8];
|
||||
|
||||
if self.ehdr.class == gabi::ELFCLASS32 {
|
||||
name = utils::read_u32(self.ehdr.endianness, io_section)?;
|
||||
value = utils::read_u32(self.ehdr.endianness, io_section)? as u64;
|
||||
size = utils::read_u32(self.ehdr.endianness, io_section)? as u64;
|
||||
name = read_u32(self.ehdr.endianness, io_section)?;
|
||||
value = read_u32(self.ehdr.endianness, io_section)? as u64;
|
||||
size = read_u32(self.ehdr.endianness, io_section)? as u64;
|
||||
io_section.read_exact(&mut info)?;
|
||||
io_section.read_exact(&mut other)?;
|
||||
shndx = utils::read_u16(self.ehdr.endianness, io_section)?;
|
||||
shndx = read_u16(self.ehdr.endianness, io_section)?;
|
||||
} else {
|
||||
name = utils::read_u32(self.ehdr.endianness, io_section)?;
|
||||
name = read_u32(self.ehdr.endianness, io_section)?;
|
||||
io_section.read_exact(&mut info)?;
|
||||
io_section.read_exact(&mut other)?;
|
||||
shndx = utils::read_u16(self.ehdr.endianness, io_section)?;
|
||||
value = utils::read_u64(self.ehdr.endianness, io_section)?;
|
||||
size = utils::read_u64(self.ehdr.endianness, io_section)?;
|
||||
shndx = read_u16(self.ehdr.endianness, io_section)?;
|
||||
value = read_u64(self.ehdr.endianness, io_section)?;
|
||||
size = read_u64(self.ehdr.endianness, io_section)?;
|
||||
}
|
||||
|
||||
symbols.push(symbol::Symbol {
|
||||
|
103
src/parse.rs
103
src/parse.rs
@ -1,4 +1,5 @@
|
||||
use crate::file::Class;
|
||||
use crate::ParseError;
|
||||
|
||||
/// Represents the ELF file data format (little-endian vs big-endian)
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
@ -17,8 +18,110 @@ impl std::fmt::Display for Endian {
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn read_u16<T: std::io::Read>(endian: Endian, io: &mut T) -> Result<u16, ParseError> {
|
||||
let mut buf = [0u8; 2];
|
||||
io.read_exact(&mut buf)?;
|
||||
match endian {
|
||||
Endian::Little => Ok(u16::from_le_bytes(buf)),
|
||||
Endian::Big => Ok(u16::from_be_bytes(buf)),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn read_u32<T: std::io::Read>(endian: Endian, io: &mut T) -> Result<u32, ParseError> {
|
||||
let mut buf = [0u8; 4];
|
||||
io.read_exact(&mut buf)?;
|
||||
match endian {
|
||||
Endian::Little => Ok(u32::from_le_bytes(buf)),
|
||||
Endian::Big => Ok(u32::from_be_bytes(buf)),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn read_u64<T: std::io::Read>(endian: Endian, io: &mut T) -> Result<u64, ParseError> {
|
||||
let mut buf = [0u8; 8];
|
||||
io.read_exact(&mut buf)?;
|
||||
match endian {
|
||||
Endian::Little => Ok(u64::from_le_bytes(buf)),
|
||||
Endian::Big => Ok(u64::from_be_bytes(buf)),
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Parse<R>: Copy {
|
||||
fn parse(endian: Endian, class: Class, reader: &mut R) -> Result<Self, crate::ParseError>
|
||||
where
|
||||
R: std::io::Read;
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_read_u16_lsb() {
|
||||
let data = [0x10u8, 0x20u8];
|
||||
let result = read_u16(Endian::Little, &mut data.as_ref()).unwrap();
|
||||
assert_eq!(result, 0x2010u16);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_read_u16_msb() {
|
||||
let data = [0x10u8, 0x20u8];
|
||||
let result = read_u16(Endian::Big, &mut data.as_ref()).unwrap();
|
||||
assert_eq!(result, 0x1020u16);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_read_u16_too_short() {
|
||||
let data = [0x10u8];
|
||||
let result: Result<u16, ParseError> = read_u16(Endian::Little, &mut data.as_ref());
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_read_u32_lsb() {
|
||||
let data = [0x10u8, 0x20u8, 0x30u8, 0x40u8];
|
||||
let result = read_u32(Endian::Little, &mut data.as_ref()).unwrap();
|
||||
assert_eq!(result, 0x40302010u32);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_read_u32_msb() {
|
||||
let data = [0x10u8, 0x20u8, 0x30u8, 0x40u8];
|
||||
let result = read_u32(Endian::Big, &mut data.as_ref()).unwrap();
|
||||
assert_eq!(result, 0x10203040u32);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_read_u32_too_short() {
|
||||
let data = [0x10u8, 0x20u8];
|
||||
let result: Result<u32, ParseError> = read_u32(Endian::Little, &mut data.as_ref());
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_read_u64_lsb() {
|
||||
let data = [
|
||||
0x10u8, 0x20u8, 0x30u8, 0x40u8, 0x50u8, 0x60u8, 0x70u8, 0x80u8,
|
||||
];
|
||||
let result = read_u64(Endian::Little, &mut data.as_ref()).unwrap();
|
||||
assert_eq!(result, 0x8070605040302010u64);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_read_u64_msb() {
|
||||
let data = [
|
||||
0x10u8, 0x20u8, 0x30u8, 0x40u8, 0x50u8, 0x60u8, 0x70u8, 0x80u8,
|
||||
];
|
||||
let result = read_u64(Endian::Big, &mut data.as_ref()).unwrap();
|
||||
assert_eq!(result, 0x1020304050607080u64);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_read_u64_too_short() {
|
||||
let data = [0x10u8, 0x20u8];
|
||||
let result: Result<u64, ParseError> = read_u64(Endian::Little, &mut data.as_ref());
|
||||
assert!(result.is_err());
|
||||
}
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
use crate::file::Class;
|
||||
use crate::gabi;
|
||||
use crate::parse::{Endian, Parse};
|
||||
use crate::utils::{read_u32, read_u64};
|
||||
use crate::parse::{Endian, Parse, read_u32, read_u64};
|
||||
|
||||
/// Encapsulates the contents of an ELF Section Header
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
|
@ -1,7 +1,6 @@
|
||||
use crate::file::Class;
|
||||
use crate::gabi;
|
||||
use crate::parse::{Endian, Parse};
|
||||
use crate::utils::{read_u32, read_u64};
|
||||
use crate::parse::{Endian, Parse, read_u32, read_u64};
|
||||
|
||||
/// Encapsulates the contents of an ELF Program Header
|
||||
///
|
||||
|
107
src/utils.rs
107
src/utils.rs
@ -1,36 +1,3 @@
|
||||
use crate::parse::Endian;
|
||||
use std::io;
|
||||
use crate::ParseError;
|
||||
|
||||
#[inline]
|
||||
pub fn read_u16<T: io::Read>(endian: Endian, io: &mut T) -> Result<u16, ParseError> {
|
||||
let mut buf = [0u8; 2];
|
||||
io.read_exact(&mut buf)?;
|
||||
match endian {
|
||||
Endian::Little => Ok(u16::from_le_bytes(buf)),
|
||||
Endian::Big => Ok(u16::from_be_bytes(buf)),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn read_u32<T: io::Read>(endian: Endian, io: &mut T) -> Result<u32, ParseError> {
|
||||
let mut buf = [0u8; 4];
|
||||
io.read_exact(&mut buf)?;
|
||||
match endian {
|
||||
Endian::Little => Ok(u32::from_le_bytes(buf)),
|
||||
Endian::Big => Ok(u32::from_be_bytes(buf)),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn read_u64<T: io::Read>(endian: Endian, io: &mut T) -> Result<u64, ParseError> {
|
||||
let mut buf = [0u8; 8];
|
||||
io.read_exact(&mut buf)?;
|
||||
match endian {
|
||||
Endian::Little => Ok(u64::from_le_bytes(buf)),
|
||||
Endian::Big => Ok(u64::from_be_bytes(buf)),
|
||||
}
|
||||
}
|
||||
|
||||
use std;
|
||||
pub fn get_string(data: &[u8], start: usize) -> Result<String, std::string::FromUtf8Error> {
|
||||
@ -46,76 +13,4 @@ pub fn get_string(data: &[u8], start: usize) -> Result<String, std::string::From
|
||||
rtn.push(data[i] as char);
|
||||
}
|
||||
Ok(rtn)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_read_u16_lsb() {
|
||||
let data = [0x10u8, 0x20u8];
|
||||
let result = read_u16(Endian::Little, &mut data.as_ref()).unwrap();
|
||||
assert_eq!(result, 0x2010u16);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_read_u16_msb() {
|
||||
let data = [0x10u8, 0x20u8];
|
||||
let result = read_u16(Endian::Big, &mut data.as_ref()).unwrap();
|
||||
assert_eq!(result, 0x1020u16);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_read_u16_too_short() {
|
||||
let data = [0x10u8];
|
||||
let result: Result<u16, ParseError> = read_u16(Endian::Little, &mut data.as_ref());
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_read_u32_lsb() {
|
||||
let data = [0x10u8, 0x20u8, 0x30u8, 0x40u8];
|
||||
let result = read_u32(Endian::Little, &mut data.as_ref()).unwrap();
|
||||
assert_eq!(result, 0x40302010u32);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_read_u32_msb() {
|
||||
let data = [0x10u8, 0x20u8, 0x30u8, 0x40u8];
|
||||
let result = read_u32(Endian::Big, &mut data.as_ref()).unwrap();
|
||||
assert_eq!(result, 0x10203040u32);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_read_u32_too_short() {
|
||||
let data = [0x10u8, 0x20u8];
|
||||
let result: Result<u32, ParseError> = read_u32(Endian::Little, &mut data.as_ref());
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_read_u64_lsb() {
|
||||
let data = [
|
||||
0x10u8, 0x20u8, 0x30u8, 0x40u8, 0x50u8, 0x60u8, 0x70u8, 0x80u8,
|
||||
];
|
||||
let result = read_u64(Endian::Little, &mut data.as_ref()).unwrap();
|
||||
assert_eq!(result, 0x8070605040302010u64);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_read_u64_msb() {
|
||||
let data = [
|
||||
0x10u8, 0x20u8, 0x30u8, 0x40u8, 0x50u8, 0x60u8, 0x70u8, 0x80u8,
|
||||
];
|
||||
let result = read_u64(Endian::Big, &mut data.as_ref()).unwrap();
|
||||
assert_eq!(result, 0x1020304050607080u64);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_read_u64_too_short() {
|
||||
let data = [0x10u8, 0x20u8];
|
||||
let result: Result<u64, ParseError> = read_u64(Endian::Little, &mut data.as_ref());
|
||||
assert!(result.is_err());
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user