Update for newer Rust.
This commit is contained in:
parent
6a7dd76bbc
commit
e5e60e6199
@ -16,4 +16,5 @@ name = "rust-readelf"
|
||||
[lib]
|
||||
name = "elf"
|
||||
|
||||
|
||||
[dependencies]
|
||||
byteorder = "*"
|
||||
|
@ -1,9 +1,8 @@
|
||||
#![feature(old_path)]
|
||||
#![feature(collections)]
|
||||
|
||||
extern crate elf;
|
||||
|
||||
use std::old_path::Path;
|
||||
use std::path::Path;
|
||||
|
||||
fn main() {
|
||||
let path = Path::new("stress");
|
||||
@ -18,7 +17,7 @@ fn main() {
|
||||
println!("{}", file);
|
||||
|
||||
println!("Getting the .text section");
|
||||
let text = file.get_section(String::from_str(".text"));
|
||||
let text = file.get_section(".text");
|
||||
match text {
|
||||
Some(s) => println!("shdr: {}", s),
|
||||
None => println!("Failed to look up .text section!"),
|
||||
|
114
src/lib.rs
114
src/lib.rs
@ -1,5 +1,9 @@
|
||||
#![feature(old_io)]
|
||||
#![feature(old_path)]
|
||||
|
||||
use std::fs;
|
||||
use std::io;
|
||||
use std::path::Path;
|
||||
|
||||
extern crate byteorder;
|
||||
|
||||
pub mod types;
|
||||
|
||||
@ -12,6 +16,31 @@ pub struct File {
|
||||
pub sections: Vec<Section>,
|
||||
}
|
||||
|
||||
pub trait ReadExact {
|
||||
fn read_exact(&mut self, len: usize) -> io::Result<Vec<u8>>;
|
||||
}
|
||||
impl<T> ReadExact for T
|
||||
where T: io::Read
|
||||
{
|
||||
fn read_exact(&mut self, len: usize) -> io::Result<Vec<u8>> {
|
||||
use std::io::{Error, ErrorKind};
|
||||
let mut buf = Vec::with_capacity(len);
|
||||
loop {
|
||||
if buf.len() >= len { break; }
|
||||
|
||||
let current_len = buf.len();
|
||||
|
||||
let read = try!(self.read(&mut buf[current_len..]));
|
||||
if read == 0 {
|
||||
return Err(Error::new(ErrorKind::Other,
|
||||
"EOF"));
|
||||
}
|
||||
}
|
||||
|
||||
return Ok(buf);
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for File {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
write!(f, "{:?} {:?} {:?}", self.ehdr, self.phdrs, self.sections)
|
||||
@ -35,35 +64,48 @@ impl std::fmt::Display for File {
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ParseError {
|
||||
IoError,
|
||||
IoError(io::Error),
|
||||
InvalidMagic,
|
||||
InvalidFormat,
|
||||
InvalidFormat(Option<std::string::FromUtf8Error>),
|
||||
NotImplemented,
|
||||
}
|
||||
|
||||
impl std::error::FromError<std::old_io::IoError> for ParseError {
|
||||
fn from_error(_: std::old_io::IoError) -> Self {
|
||||
ParseError::IoError
|
||||
impl std::convert::From<std::io::Error> for ParseError {
|
||||
fn from(e: std::io::Error) -> Self {
|
||||
ParseError::IoError(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::FromError<std::string::FromUtf8Error> for ParseError {
|
||||
fn from_error(_: std::string::FromUtf8Error) -> Self {
|
||||
ParseError::InvalidFormat
|
||||
impl std::convert::From<std::string::FromUtf8Error> for ParseError {
|
||||
fn from(e: std::string::FromUtf8Error) -> Self {
|
||||
ParseError::InvalidFormat(Some(e))
|
||||
}
|
||||
}
|
||||
impl std::convert::From<byteorder::Error> for ParseError {
|
||||
fn from(e: byteorder::Error) -> Self {
|
||||
match e {
|
||||
byteorder::Error::UnexpectedEOF => {
|
||||
ParseError::InvalidFormat(None)
|
||||
},
|
||||
byteorder::Error::Io(e) => {
|
||||
From::from(e)
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl File {
|
||||
pub fn open(path: &std::old_path::Path) -> Result<File, ParseError> {
|
||||
pub fn open<T: AsRef<Path>>(path: T) -> Result<File, ParseError> {
|
||||
use std::io::{Read, Seek};
|
||||
// Open the file for reading
|
||||
let mut io_file = try!(std::old_io::File::open(path));
|
||||
let mut io_file = try!(fs::File::open(path));
|
||||
|
||||
// Read the platform-independent ident bytes
|
||||
let mut ident = [0u8; types::EI_NIDENT];
|
||||
let nread = try!(io_file.read(&mut ident));
|
||||
let nread = try!(io_file.read(ident.as_mut()));
|
||||
|
||||
if nread != types::EI_NIDENT {
|
||||
return Err(ParseError::InvalidFormat);
|
||||
return Err(ParseError::InvalidFormat(None));
|
||||
}
|
||||
|
||||
// Verify the magic number
|
||||
@ -105,7 +147,7 @@ impl File {
|
||||
let shstrndx = try!(read_u16!(elf_f, io_file));
|
||||
|
||||
// Parse the program headers
|
||||
try!(io_file.seek(phoff as i64, std::old_io::SeekStyle::SeekSet));
|
||||
try!(io_file.seek(io::SeekFrom::Start(phoff)));
|
||||
for _ in 0..phnum {
|
||||
let mut progtype: types::ProgType;
|
||||
let mut offset: u64;
|
||||
@ -149,7 +191,7 @@ impl File {
|
||||
|
||||
// Parse the section headers
|
||||
let mut name_idxs: Vec<u32> = Vec::new();
|
||||
try!(io_file.seek(shoff as i64, std::old_io::SeekStyle::SeekSet));
|
||||
try!(io_file.seek(io::SeekFrom::Start(phoff)));
|
||||
for _ in 0..shnum {
|
||||
let name: String = String::new();
|
||||
let mut shtype: types::SectionType;
|
||||
@ -202,30 +244,37 @@ impl File {
|
||||
}
|
||||
|
||||
// Read the section data
|
||||
for s_i in 0..shnum {
|
||||
let off = elf_f.sections[s_i as usize].shdr.offset;
|
||||
let size = elf_f.sections[s_i as usize].shdr.size;
|
||||
try!(io_file.seek(off as i64, std::old_io::SeekStyle::SeekSet));
|
||||
elf_f.sections[s_i as usize].data = try!(io_file.read_exact(size as usize));
|
||||
let mut s_i: usize = 0;
|
||||
loop {
|
||||
if s_i == shnum as usize { break; }
|
||||
|
||||
let off = elf_f.sections[s_i].shdr.offset;
|
||||
let size = elf_f.sections[s_i].shdr.size;
|
||||
try!(io_file.seek(io::SeekFrom::Start(off)));
|
||||
elf_f.sections[s_i].data = try!(io_file.read_exact(size as usize));
|
||||
|
||||
s_i += 1;
|
||||
}
|
||||
|
||||
// Parse the section names from the string header string table
|
||||
for s_i in 0..shnum {
|
||||
elf_f.sections[s_i as usize].shdr.name = try!(utils::get_string(
|
||||
&elf_f.sections[shstrndx as usize].data,
|
||||
name_idxs[s_i as usize] as usize));
|
||||
s_i = 0;
|
||||
loop {
|
||||
if s_i == shnum as usize { break; }
|
||||
|
||||
elf_f.sections[s_i].shdr.name = try!(utils::get_string(
|
||||
&elf_f.sections[shstrndx as usize].data,
|
||||
name_idxs[s_i] as usize));
|
||||
|
||||
s_i += 1;
|
||||
}
|
||||
|
||||
Ok(elf_f)
|
||||
}
|
||||
|
||||
pub fn get_section(&self, name: String) -> Option<&Section> {
|
||||
for s_i in 0..self.sections.len() {
|
||||
if self.sections[s_i].shdr.name == name {
|
||||
return Some(&self.sections[s_i])
|
||||
}
|
||||
}
|
||||
None
|
||||
pub fn get_section<T: AsRef<str>>(&self, name: T) -> Option<&Section> {
|
||||
self.sections
|
||||
.iter()
|
||||
.find(|section| section.shdr.name == name.as_ref() )
|
||||
}
|
||||
|
||||
pub fn new() -> File {
|
||||
@ -248,4 +297,3 @@ impl std::fmt::Display for Section {
|
||||
write!(f, "{}", self.shdr)
|
||||
}
|
||||
}
|
||||
|
||||
|
31
src/types.rs
31
src/types.rs
@ -23,7 +23,7 @@ pub const EI_OSABI: usize = 7;
|
||||
pub const EI_ABIVERSION: usize = 8;
|
||||
|
||||
/// Represents the ELF file class (32-bit vs 64-bit)
|
||||
#[derive(Copy, PartialEq)]
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
pub struct Class(pub u8);
|
||||
/// Invalid ELF file class
|
||||
pub const ELFCLASSNONE : Class = Class(0);
|
||||
@ -51,7 +51,7 @@ impl fmt::Display for Class {
|
||||
}
|
||||
|
||||
/// Represents the ELF file data format (little-endian vs big-endian)
|
||||
#[derive(Copy, PartialEq)]
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
pub struct Data(pub u8);
|
||||
/// Invalid ELF data format
|
||||
pub const ELFDATANONE : Data = Data(0);
|
||||
@ -81,7 +81,7 @@ impl fmt::Display for Data {
|
||||
/// Represents the ELF file version
|
||||
///
|
||||
/// This field represents the values both found in the e_ident byte array and the e_version field.
|
||||
#[derive(Copy)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Version(pub u32);
|
||||
/// Invalid version
|
||||
pub const EV_NONE : Version = Version(0);
|
||||
@ -106,7 +106,7 @@ impl fmt::Display for Version {
|
||||
}
|
||||
|
||||
/// Represents the ELF file OS ABI
|
||||
#[derive(Copy)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct OSABI(pub u8);
|
||||
/// Defaults to Unix System V
|
||||
pub const ELFOSABI_NONE : OSABI = OSABI(0);
|
||||
@ -160,7 +160,7 @@ impl fmt::Display for OSABI {
|
||||
}
|
||||
|
||||
/// Represents the ELF file type (object, executable, shared lib, core)
|
||||
#[derive(Copy)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Type(pub u16);
|
||||
/// No file type
|
||||
pub const ET_NONE : Type = Type(0);
|
||||
@ -194,7 +194,7 @@ impl fmt::Display for Type {
|
||||
}
|
||||
|
||||
/// Represents the ELF file machine architecture
|
||||
#[derive(Copy)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Machine(pub u16);
|
||||
pub const EM_NONE : Machine = Machine(0);
|
||||
pub const EM_M32 : Machine = Machine(1);
|
||||
@ -374,7 +374,7 @@ impl fmt::Display for Machine {
|
||||
/// file contents and informs how to interpret said contents. This includes
|
||||
/// the width of certain fields (32-bit vs 64-bit), the data endianness, the
|
||||
/// file type, and more.
|
||||
#[derive(Copy, Debug)]
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct FileHeader {
|
||||
/// 32-bit vs 64-bit
|
||||
pub class: Class,
|
||||
@ -410,7 +410,7 @@ impl fmt::Display for FileHeader {
|
||||
}
|
||||
|
||||
/// Represents ELF Program Header flags
|
||||
#[derive(Copy, PartialEq)]
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
pub struct ProgFlag(pub u32);
|
||||
pub const PF_NONE : ProgFlag = ProgFlag(0);
|
||||
/// Executable program segment
|
||||
@ -447,7 +447,7 @@ impl fmt::Display for ProgFlag {
|
||||
}
|
||||
|
||||
/// Represents ELF Program Header type
|
||||
#[derive(Copy, PartialEq)]
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
pub struct ProgType(pub u32);
|
||||
/// Program header table entry unused
|
||||
pub const PT_NULL : ProgType = ProgType(0);
|
||||
@ -502,7 +502,7 @@ impl fmt::Display for ProgType {
|
||||
///
|
||||
/// The program header table is an array of program header structures describing
|
||||
/// the various segments for program execution.
|
||||
#[derive(Copy, Debug)]
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct ProgramHeader {
|
||||
/// Program segment type
|
||||
pub progtype: ProgType,
|
||||
@ -531,7 +531,7 @@ impl fmt::Display for ProgramHeader {
|
||||
}
|
||||
|
||||
/// Represens ELF Section type
|
||||
#[derive(Copy, PartialEq)]
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
pub struct SectionType(pub u32);
|
||||
/// Inactive section with undefined values
|
||||
pub const SHT_NULL : SectionType = SectionType(0);
|
||||
@ -624,7 +624,7 @@ impl fmt::Display for SectionType {
|
||||
///
|
||||
/// Wrapper type for SectionFlag
|
||||
///
|
||||
#[derive(Copy, PartialEq)]
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
pub struct SectionFlag(pub u64);
|
||||
/// Empty flags
|
||||
pub const SHF_NONE : SectionFlag = SectionFlag(0);
|
||||
@ -694,7 +694,7 @@ impl fmt::Display for SectionHeader {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct SymbolType(pub u8);
|
||||
/// Unspecified symbol type
|
||||
pub const STT_NOTYPE : SymbolType = SymbolType(0);
|
||||
@ -730,7 +730,7 @@ impl fmt::Display for SymbolType {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct SymbolBind(pub u8);
|
||||
/// Local symbol
|
||||
pub const STB_LOCAL : SymbolBind = SymbolBind(0);
|
||||
@ -754,7 +754,7 @@ impl fmt::Display for SymbolBind {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct SymbolVis(pub u8);
|
||||
/// Default symbol visibility
|
||||
pub const STV_DEFAULT : SymbolVis = SymbolVis(0);
|
||||
@ -802,4 +802,3 @@ impl Symbol {
|
||||
SymbolVis(self.other & 0x3)
|
||||
}
|
||||
}
|
||||
|
||||
|
37
src/utils.rs
37
src/utils.rs
@ -1,50 +1,54 @@
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! read_u8 {
|
||||
($elf:ident, $io:ident) => (
|
||||
($elf:ident, $io:ident) => ({
|
||||
use byteorder::{LittleEndian, BigEndian, ReadBytesExt};
|
||||
match $elf.ehdr.data {
|
||||
types::ELFDATA2LSB => { $io.read_le_u8() }
|
||||
types::ELFDATA2MSB => { $io.read_be_u8() }
|
||||
types::ELFDATA2LSB => { $io.read_u8::<LittleEndian>() }
|
||||
types::ELFDATA2MSB => { $io.read_u8::<BigEndian>() }
|
||||
types::ELFDATANONE => { panic!("Unable to resolve file endianness"); }
|
||||
_ => { panic!("Unable to resolve file endianness"); }
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! read_u16 {
|
||||
($elf:ident, $io:ident) => (
|
||||
($elf:ident, $io:ident) => ({
|
||||
use byteorder::{LittleEndian, BigEndian, ReadBytesExt};
|
||||
match $elf.ehdr.data {
|
||||
types::ELFDATA2LSB => { $io.read_le_u16() }
|
||||
types::ELFDATA2MSB => { $io.read_be_u16() }
|
||||
types::ELFDATA2LSB => { $io.read_u16::<LittleEndian>() }
|
||||
types::ELFDATA2MSB => { $io.read_u16::<BigEndian>() }
|
||||
types::ELFDATANONE => { panic!("Unable to resolve file endianness"); }
|
||||
_ => { panic!("Unable to resolve file endianness"); }
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! read_u32 {
|
||||
($elf:ident, $io:ident) => (
|
||||
($elf:ident, $io:ident) => ({
|
||||
use byteorder::{LittleEndian, BigEndian, ReadBytesExt};
|
||||
match $elf.ehdr.data {
|
||||
types::ELFDATA2LSB => { $io.read_le_u32() }
|
||||
types::ELFDATA2MSB => { $io.read_be_u32() }
|
||||
types::ELFDATA2LSB => { $io.read_u32::<LittleEndian>() }
|
||||
types::ELFDATA2MSB => { $io.read_u32::<BigEndian>() }
|
||||
types::ELFDATANONE => { panic!("Unable to resolve file endianness"); }
|
||||
_ => { panic!("Unable to resolve file endianness"); }
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! read_u64 {
|
||||
($elf:ident, $io:ident) => (
|
||||
($elf:ident, $io:ident) => ({
|
||||
use byteorder::{LittleEndian, BigEndian, ReadBytesExt};
|
||||
match $elf.ehdr.data {
|
||||
types::ELFDATA2LSB => { $io.read_le_u64() }
|
||||
types::ELFDATA2MSB => { $io.read_be_u64() }
|
||||
types::ELFDATA2LSB => { $io.read_u64::<LittleEndian>() }
|
||||
types::ELFDATA2MSB => { $io.read_u64::<BigEndian>() }
|
||||
types::ELFDATANONE => { panic!("Unable to resolve file endianness"); }
|
||||
_ => { panic!("Unable to resolve file endianness"); }
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
use std;
|
||||
@ -62,4 +66,3 @@ pub fn get_string(data: &Vec<u8>, start: usize) -> Result<String, std::string::F
|
||||
}
|
||||
Ok(rtn)
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user