117 lines
3.8 KiB
Rust
117 lines
3.8 KiB
Rust
use crate::{mem::MemCursor, obj::obj::*};
|
|
use prettytable::{cell, row, Table};
|
|
use std::io::{self, Write};
|
|
|
|
const SEP: &str =
|
|
"================================================================================";
|
|
|
|
pub trait Disasm {
|
|
fn disasm(&self, writer: &mut dyn Write) -> io::Result<()>;
|
|
}
|
|
|
|
impl Disasm for Vec<u8> {
|
|
fn disasm(&self, writer: &mut dyn Write) -> io::Result<()> {
|
|
let obj = Object::from_bytes(self.as_slice()).expect("invalid object bytes");
|
|
obj.disasm(writer)
|
|
}
|
|
}
|
|
|
|
impl Disasm for Object {
|
|
fn disasm(&self, writer: &mut dyn Write) -> io::Result<()> {
|
|
for section in self.sections.iter() {
|
|
section.disasm(writer)?;
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
impl Disasm for Section {
|
|
fn disasm(&self, writer: &mut dyn Write) -> io::Result<()> {
|
|
match self {
|
|
Section::Data(s) => s.disasm(writer),
|
|
Section::Meta(s) => s.disasm(writer),
|
|
}
|
|
}
|
|
}
|
|
|
|
// TODO :
|
|
// Instruction decoding is borked and I don't know why
|
|
// I think it has to do with the DataSection::lines() method, because that's the change that
|
|
// introduced it. The 0xdeadbeef program is only getting the value "200" in %r0 when it goes to do
|
|
// the comparison, so for some reason that value is being put in there. The disassembler is an
|
|
// attempt to make things slightly more readable while I debug.
|
|
//
|
|
// It appears that instructions are being encoded correctly (at least, as far as instructions
|
|
// themselves go) so we will have to look deeper.
|
|
|
|
impl Disasm for DataSection {
|
|
fn disasm(&self, writer: &mut dyn Write) -> io::Result<()> {
|
|
writeln!(writer, "{}", SEP)?;
|
|
writeln!(writer, "= DATA SECTION - {}", self.name)?;
|
|
writeln!(writer, "{}", SEP)?;
|
|
let mut table = Table::new();
|
|
table.add_row(row!["Address", "Bytes", "Info"]);
|
|
let mut cursor = MemCursor::new(self.contents.as_slice());
|
|
loop {
|
|
if cursor.is_end() {
|
|
break;
|
|
}
|
|
let cursor_pos = cursor.position();
|
|
let pos = self.start + cursor_pos;
|
|
if let Ok(inst) = cursor.next_inst() {
|
|
let start = cursor_pos as usize;
|
|
let end = start + inst.len();
|
|
let data = &self.contents.as_slice()[start..end];
|
|
table.add_row(row![
|
|
format!("{:016x} <{}+{:x}>", pos, self.name, cursor_pos),
|
|
bytes_hex(data),
|
|
format!("{:?}", inst),
|
|
]);
|
|
} else {
|
|
let mut count = 0;
|
|
let mut lookahead = MemCursor::new(self.contents.as_slice());
|
|
lookahead.set_position(cursor_pos);
|
|
while !lookahead.is_end() && lookahead.next_inst().is_err() {
|
|
count += 1;
|
|
lookahead.next_u8_unchecked();
|
|
}
|
|
let bytes = cursor.next_bytes(count).unwrap();
|
|
table.add_row(row![
|
|
format!("{:016x} <{}+{:x}>", pos, self.name, cursor_pos),
|
|
bytes_hex(bytes),
|
|
"",
|
|
]);
|
|
}
|
|
}
|
|
table.print(writer)?;
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
impl Disasm for MetaSection {
|
|
fn disasm(&self, writer: &mut dyn Write) -> io::Result<()> {
|
|
let mut table = Table::new();
|
|
writeln!(writer, "{}", SEP)?;
|
|
writeln!(writer, "= META SECTION")?;
|
|
writeln!(writer, "{}", SEP)?;
|
|
table.add_row(row!["Name", "Value"]);
|
|
for (name, value) in self.entries.iter() {
|
|
table.add_row(row![name, format!("0x{:016x}", value)]);
|
|
}
|
|
table.print(writer)?;
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
fn bytes_hex(bytes: &[u8]) -> String {
|
|
let mut out = String::new();
|
|
for b in bytes.iter() {
|
|
out += &format!("{:02x} ", b);
|
|
}
|
|
if !out.is_empty() {
|
|
out.pop();
|
|
}
|
|
out
|
|
}
|