I parsed all instructions before executing, but this is not how intel works. We need to decode the instructions, pointed to by IP, on the fly.
127 lines
3.6 KiB
Rust
127 lines
3.6 KiB
Rust
//! Internal a.out File abstraction.
|
|
|
|
use core::fmt;
|
|
use std::{
|
|
ffi::{c_uchar, c_ushort},
|
|
fs::File,
|
|
io::Read,
|
|
};
|
|
|
|
use crate::{Args, disasm::DisasmError, operands::Byte};
|
|
|
|
#[allow(non_camel_case_types)]
|
|
pub type c_long = i32; // we use a a.out with 32 byte
|
|
|
|
#[derive(Debug, Clone)]
|
|
/// Internal representation of the a.out binary format.
|
|
pub struct Aout {
|
|
pub header: Header,
|
|
pub text: Vec<Byte>,
|
|
pub data: Vec<Byte>,
|
|
}
|
|
|
|
impl fmt::Display for Aout {
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
write!(f, "Header: {:#?}\n", self.header).unwrap();
|
|
write!(f, "Text: {:#?}\n", self.text).unwrap();
|
|
write!(f, "Data: {:#?}\n", self.data)
|
|
}
|
|
}
|
|
|
|
impl Aout {
|
|
pub fn new_from_args(args: &Args) -> Self {
|
|
let path = args
|
|
.path
|
|
.clone()
|
|
.ok_or(DisasmError::NoFile(args.path.clone()))
|
|
.unwrap();
|
|
let mut file = File::open(path).unwrap();
|
|
let mut buf = Vec::new();
|
|
file.read_to_end(&mut buf).unwrap();
|
|
let aout = Aout::new(buf);
|
|
log::debug!("{:?}", aout);
|
|
aout
|
|
}
|
|
|
|
pub fn new(buf: Vec<u8>) -> Self {
|
|
let hdr = Header {
|
|
magic: [buf[0], buf[1]],
|
|
flags: buf[2],
|
|
cpu: buf[3],
|
|
hdrlen: buf[4],
|
|
unused: buf[5],
|
|
version: c_ushort::from_be_bytes([buf[6], buf[7]]),
|
|
text: c_long::from_le_bytes([buf[8], buf[9], buf[10], buf[11]]),
|
|
data: c_long::from_le_bytes([buf[12], buf[13], buf[14], buf[15]]),
|
|
bss: c_long::from_le_bytes([buf[16], buf[17], buf[18], buf[19]]),
|
|
entry: c_long::from_le_bytes([buf[20], buf[21], buf[22], buf[23]]),
|
|
total: c_long::from_le_bytes([buf[24], buf[25], buf[26], buf[27]]),
|
|
syms: c_long::from_le_bytes([buf[28], buf[29], buf[30], buf[31]]),
|
|
};
|
|
|
|
let text_start = hdr.hdrlen as usize;
|
|
let text_end = text_start + hdr.text as usize;
|
|
let data_start = text_end;
|
|
let data_end = data_start + hdr.data as usize;
|
|
|
|
let text_section = &buf[text_start..text_end];
|
|
let data_section = &buf[data_start..data_end];
|
|
|
|
Aout {
|
|
header: hdr,
|
|
text: Vec::from(text_section),
|
|
data: Vec::from(data_section),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct Header {
|
|
pub magic: [c_uchar; 2], // magic number
|
|
pub flags: c_uchar, // flags, see below
|
|
pub cpu: c_uchar, // cpu id
|
|
pub hdrlen: c_uchar, // length of header
|
|
pub unused: c_uchar, // reserved for future use
|
|
pub version: c_ushort, // version stamp
|
|
pub text: c_long, // size of text segment in bytes
|
|
pub data: c_long, // size of data segment in bytes
|
|
pub bss: c_long, // size of bss segment in bytes
|
|
pub entry: c_long, // entry point
|
|
pub total: c_long, // total memory allocated
|
|
pub syms: c_long, // size of symbol table
|
|
}
|
|
|
|
impl fmt::Display for Header {
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
write!(
|
|
f,
|
|
"Header:
|
|
Magic: {:02X?}
|
|
Flags: {:#04X}
|
|
CPU: {}
|
|
Header Length: {}
|
|
Unused: {}
|
|
Version: {:#06X}
|
|
Text Size: {}
|
|
Data Size: {}
|
|
BSS Size: {}
|
|
Entry Point: {:#X}
|
|
Total Allocated: {}
|
|
Symbol Table Size: {}
|
|
",
|
|
self.magic,
|
|
self.flags,
|
|
self.cpu,
|
|
self.hdrlen,
|
|
self.unused,
|
|
self.version,
|
|
self.text,
|
|
self.data,
|
|
self.bss,
|
|
self.entry,
|
|
self.total,
|
|
self.syms
|
|
)
|
|
}
|
|
}
|