Files
rasp/src/libvm/src/obj/disassemble.rs
Alek Ratzloff d0f8d93edf Run rustfmt
Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
2020-03-09 16:47:30 -04:00

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
}