Finally working on we32dis again. Feels good.

This commit is contained in:
Seth Morabito 2019-01-11 21:22:11 -08:00
parent 88b91ac3df
commit a3bb5bc81b
6 changed files with 603 additions and 139 deletions

54
util/test.json Normal file
View File

@ -0,0 +1,54 @@
{
"movb_acceptance": {
"body": [
"MOVB &1,%r0",
"MOVB &-1,%r1",
"MOVB &0xff,%r2",
"MOVB &0x1f,%r3",
"MOVB $0x100,%r0",
"MOVB *$0x200,%r1",
"MOVB 5(%r6),%r2",
"MOVB *8(%r6),%r3",
"MOVB 0xff(%r6),%r4",
"MOVB *0xff(%r6),%r4"
]
},
"add_acceptance": {
"body": [
"ADDW2 &0x100,%r0",
"ADDH2 &0x1ff,%r1",
"ADDB2 &0xff,%r2"
]
},
"alsw3_acceptance": {
"body": [
"ALSW3 &1,&1,%r0",
"ALSW3 &0x80000000,&1,%r0",
"ALSW3 &0x10000000,&1,{sbyte}%r0"
]
},
"andw_acceptance": {
"body": [
"ANDW2 &0xffff00ff,%r0",
"ANDH2 &0xff0f,%r2",
"ANDB2 &0x0f,%r3"
]
},
"beb_acceptance": {
"body": [
"BEB &4",
"NOP",
"NOP",
"BEB &-1"
]
},
"beh_acceptance": {
"body": [
"BEH &4",
"NOP",
"NOP",
"BEH &-1"
]
}
}

View File

@ -85,10 +85,6 @@
require 'json'
require 'optparse'
#
# Monkey patch Numeric with some convenient 2's complement
# features.
#
class Encoder
@@registers = {
"%r0" => 0,
@ -163,10 +159,9 @@ class Encoder
SUBW3: 0xfc, SUBH3: 0xfe, SUBB: 0xff
}
attr_accessor :pc
def initialize
@pc = 0x2000000
def initialize(initial_pc, output_handler)
@initial_pc = initial_pc
@output_handler = output_handler
end
# Tokenize an instruction and return an array containing 0 to n
@ -235,10 +230,12 @@ class Encoder
end
def displacement_value(operand_token)
md = /^\*?([^\(]+)\(/.match(operand_token)
md = /^\*?(-?[^\(]+)\(/.match(operand_token)
if md
parse_number(md[1])
else
return 0
end
end
@ -454,10 +451,82 @@ class Encoder
return bytes
end
def escape(str)
str.gsub(/\%/, "\\%")
def consume_file(file)
test_count = 0
json_hash = JSON.parse(File.open(file).read)
@output_handler.print_file_header()
json_hash.each do |test_name, test_block|
@pc = @initial_pc
@output_handler.print_test_header(test_count, test_name)
test_count += 1
@output_handler.print_test_setup(@pc, test_block)
if test_block["body"]
test_block["body"].each do |instruction|
bytes = to_bytes(instruction)
@output_handler.print_instruction(bytes, instruction, @pc)
end
end
@output_handler.print_test_teardown(@pc, test_block["body"].size)
@output_handler.print_execute(test_block)
@output_handler.print_asserts(test_block)
end
@output_handler.print_file_footer()
end
end
class BlitOutputHandler
def print_file_header
end
def print_test_header(test_count, test_name)
puts "#[test]"
puts "fn %s() {" % test_name
end
def print_test_setup(pc, test_block)
puts " let program = ["
end
def print_instruction(bytes, instruction, pc)
print " "
print(bytes.map {|b| "0x%02x," % b }.join(" "))
puts " // %s" % instruction
end
def print_test_teardown(pc, test_count)
puts " ];"
puts " do_with_program(&program, |cpu, mut bus| {"
test_count.times do
puts " cpu.step(&mut bus);"
puts " assert_eq!(0, 0);"
end
puts " });"
puts "}"
end
def print_execute(test_block)
end
def print_asserts(test_block)
end
def print_file_footer
end
end
class SimhOutputHandler
def print_file_header
puts <<EOF
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@ -475,6 +544,59 @@ on afail goto failure
EOF
end
def print_test_header(test_count, test_name)
puts ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"
puts "ECHO TEST #{test_count}: #{test_name}..."
puts
end
def print_test_setup(pc, test_block)
puts "; SETUP"
puts "d pc %04x" % [pc]
puts
if test_block["setup"]
test_block["setup"].each do |key, val|
puts "d #{key} #{val}"
end
puts
end
end
def print_test_teardown(pc, test_count)
end
def print_instruction(bytes, instruction, pc)
if !bytes
raise "Unable to assemble instruction: #{instruction}"
end
puts "; #{instruction}"
bytes.each do |b|
puts "dep -b %04x %02x" % [pc, b]
pc += 1
end
end
def print_execute(test_block)
puts
puts "; Execute the instruction(s)"
puts "STEP %d" % test_block["body"].size
puts
end
def print_asserts(test_block)
if test_block["asserts"]
puts "; ASSERTS"
test_block["asserts"].each do |key, val|
puts "ASSERT #{key}=#{val}"
end
puts
end
end
def print_file_footer
puts <<EOF
:success
@ -493,68 +615,6 @@ show history=1
EOF
end
def consume_file(file)
test_count = 0
json_hash = JSON.parse(File.open(file).read)
print_file_header()
json_hash.each do |test_name, test_block|
@pc = 0x2000000
puts ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"
puts "ECHO TEST #{test_count}: #{test_name}..."
puts
test_count += 1
puts "; SETUP"
puts "d pc %04x" % [@pc]
puts
if test_block["setup"]
test_block["setup"].each do |key, val|
puts "d #{key} #{val}"
end
puts
end
if test_block["body"]
test_block["body"].each do |instruction|
bytes = to_bytes(instruction)
if !bytes
raise "Unable to assemble instruction: #{instruction}"
end
puts "; #{instruction}"
bytes.each do |b|
puts "dep -b %04x %02x" % [@pc, b]
@pc += 1
end
end
puts
end
puts "; Execute the instruction(s)"
puts "STEP %d" % test_block["body"].size
puts
if test_block["asserts"]
puts "; ASSERTS"
test_block["asserts"].each do |key, val|
puts "ASSERT #{key}=#{val}"
end
puts
end
end
print_file_footer()
end
end
@ -576,7 +636,7 @@ if __FILE__ == $0
# Start reading in from the input
encoder = Encoder.new
encoder = Encoder.new(0x2000, BlitOutputHandler.new)
infile = ARGV[0]

142
we32dis/Cargo.lock generated
View File

@ -1,14 +1,10 @@
[root]
name = "we32dis"
version = "0.1.0"
dependencies = [
"clap 2.22.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "ansi_term"
version = "0.9.0"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "atty"
@ -22,22 +18,36 @@ dependencies = [
[[package]]
name = "bitflags"
version = "0.8.2"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "clap"
version = "2.22.1"
name = "byteorder"
version = "1.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "chrono"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "clap"
version = "2.32.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"atty 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
"strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"term_size 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"vec_map 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -55,25 +65,46 @@ version = "0.2.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "strsim"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "term_size"
version = "0.2.3"
name = "num-integer"
version = "0.1.39"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "unicode-segmentation"
version = "1.1.0"
name = "num-traits"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "redox_syscall"
version = "0.1.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "strsim"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "textwrap"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "time"
version = "0.1.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_syscall 0.1.50 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "unicode-width"
version = "0.1.4"
@ -81,30 +112,67 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "vec_map"
version = "0.7.0"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "we32dis"
version = "0.1.0"
dependencies = [
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
"chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "winapi"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "winapi-build"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6"
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
"checksum atty 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d912da0db7fa85514874458ca3651fe2cddace8d0b0505571dbdcd41ab490159"
"checksum bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1370e9fc2a6ae53aea8b7a5110edbd08836ed87c88736dfabccade1c2b44bff4"
"checksum clap 2.22.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e17a4a72ffea176f77d6e2db609c6c919ef221f23862c9915e687fb54d833485"
"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12"
"checksum byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "94f88df23a25417badc922ab0f5716cc1330e87f71ddd9203b3a3ccd9cedf75d"
"checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878"
"checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e"
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
"checksum libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)" = "88ee81885f9f04bff991e306fea7c1c60a5f0f9e409e99f6b40e3311a3363135"
"checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694"
"checksum term_size 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "07b6c1ac5b3fffd75073276bca1ceed01f67a28537097a2a9539e116e50fb21a"
"checksum unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18127285758f0e2c6cf325bb3f3d138a12fee27de4f23e146cd6a179f26c2cf3"
"checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea"
"checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1"
"checksum redox_syscall 0.1.50 (registry+https://github.com/rust-lang/crates.io-index)" = "52ee9a534dc1301776eff45b4fa92d2c39b1d8c3d3357e6eb593e0d795506fc2"
"checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550"
"checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6"
"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f"
"checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f"
"checksum vec_map 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8cdc8b93bd0198ed872357fb2e667f7125646b1762f16d60b2c96350d361897"
"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
"checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0"
"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"

View File

@ -2,6 +2,10 @@
name = "we32dis"
version = "0.1.0"
authors = ["Seth Morabito <web@loomcom.com>"]
edition = "2018"
[dependencies]
clap = "2.22.1"
clap = "2.32.0"
byteorder = "1"
chrono = "0.4.6"
bitflags = "1.0.4"

242
we32dis/src/coff.rs Normal file
View File

@ -0,0 +1,242 @@
///
/// WE32000 COFF File Parsing and Utilities
///
use std::fmt;
use std::io::Cursor;
use std::io;
use std::io::{Read, Seek, SeekFrom};
use chrono::prelude::*;
use chrono::TimeZone;
use byteorder::{BigEndian, ReadBytesExt};
// WE32000 without transfer vector
const MAGIC_WE32K: u16 = 0x170;
// WE32000 with transfer vector
const MAGIC_WE32K_TV: u16 = 0x171;
// The optional header (if present) is 28 bytes long
const OPT_HEADER_SIZE: u16 = 0x1c;
bitflags! {
pub struct Flags: u16 {
// Relocation info stripped from file
const REL_STRIPPED = 0x0001;
// File is executable (i.e. no unresolved external references)
const EXECUTABLE = 0x0002;
// Line numbers stripped from file
const LINE_NUM_STRIPPED = 0x0004;
// Local symbols stripped from file
const LSYM_STRIPPED = 0x0010;
// This is a minimal object file (".m") output of fextract
const MINMAL_OBJECT = 0x0020;
// This is a fully bound update file, output of ogen
const UPDATE_FILE = 0x0040;
// This file has had its bytes swabbed (in names)
const SWABBED = 0x0100;
// This file has the byte ordering of an AR16WR (e.g. 11/70) machine
const BYTES_AR16WR = 0x0200;
// This file has the byte ordering of an AR32WR machine (e.g. vax)
const BYTES_AR32WR = 0x0400;
// This file has the byte ordering of an AR32W machine (e.g. 3b, maxi)
const BYTES_AR32W = 0x1000;
// File contains "patch" list in optional header
const F_PATCH = 0x2000;
// (minimal file only) no decision functions for replaced functions
const F_NODF = 0x2000;
}
}
pub struct FileHeader {
pub magic: u16,
pub section_count: u16,
pub timestamp: u32,
pub symbols_pointer: u32,
pub symbol_count: u32,
pub opt_header: u16,
pub flags: Flags,
}
impl fmt::Debug for FileHeader {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut desc = String::new();
let magic = match self.magic {
MAGIC_WE32K => "WE32000 COFF",
MAGIC_WE32K_TV => "WE32000 COFF (TV)",
_ => "Unknown"
};
desc.push_str(magic);
if self.flags.contains(Flags::EXECUTABLE) {
desc.push_str(" executable");
}
if self.flags.contains(Flags::LSYM_STRIPPED) {
desc.push_str(", symbols stripped");
} else {
desc.push_str(", with symbols");
}
if self.flags.contains(Flags::REL_STRIPPED) {
desc.push_str(", relocation info stripped");
} else {
desc.push_str(", with relocation info");
}
write!(f, "{}", desc)
}
}
// Only present in the file if the file header's opt_header == 0x1c (28 bytes)
pub struct OptionalHeader {
pub magic: u16,
pub version_stamp: u16,
pub text_size: u32,
pub dsize: u32,
pub bsize: u32,
pub entry_point: u32,
pub text_start: u32,
pub data_start: u32,
}
pub struct SectionHeader {
pub name: [u8; 8],
pub paddr: u32,
pub vaddr: u32,
pub size: u32,
pub scnptr: u32,
pub relptr: u32,
pub lnnoptr: u32,
pub nreloc: u16,
pub nlnno: u16,
pub flags: u32,
}
pub struct RelocationEntry {
pub vaddr: u32,
pub symndx: u32,
pub rtype: u16,
}
pub struct Section {
pub header: SectionHeader,
pub relocation_entries: Vec<RelocationEntry>,
}
pub struct MetaData {
pub header: FileHeader,
pub timestamp: DateTime<Utc>,
pub opt_header: Option<OptionalHeader>,
pub sections: Vec<Section>,
}
impl MetaData {
pub fn read(cursor: &mut Cursor<&[u8]>) -> io::Result<MetaData> {
// FIRST PASS: Pull out File Header, Optional Header (if any),
// and Section Headers
cursor.seek(SeekFrom::Start(0))?;
let header = FileHeader {
magic: cursor.read_u16::<BigEndian>()?,
section_count: cursor.read_u16::<BigEndian>()?,
timestamp: cursor.read_u32::<BigEndian>()?,
symbols_pointer: cursor.read_u32::<BigEndian>()?,
symbol_count: cursor.read_u32::<BigEndian>()?,
opt_header: cursor.read_u16::<BigEndian>()?,
flags: Flags::from_bits_truncate(cursor.read_u16::<BigEndian>()?),
};
let opt_header = if header.opt_header == OPT_HEADER_SIZE {
Some(
OptionalHeader {
magic: cursor.read_u16::<BigEndian>()?,
version_stamp: cursor.read_u16::<BigEndian>()?,
text_size: cursor.read_u32::<BigEndian>()?,
dsize: cursor.read_u32::<BigEndian>()?,
bsize: cursor.read_u32::<BigEndian>()?,
entry_point: cursor.read_u32::<BigEndian>()?,
text_start: cursor.read_u32::<BigEndian>()?,
data_start: cursor.read_u32::<BigEndian>()?
}
)
} else {
None
};
let mut section_headers: Vec<SectionHeader> = vec!();
for _ in 0..header.section_count {
let mut name: [u8; 8] = [0; 8];
cursor.read_exact(&mut name)?;
let sec_header = SectionHeader {
name: name,
paddr: cursor.read_u32::<BigEndian>()?,
vaddr: cursor.read_u32::<BigEndian>()?,
size: cursor.read_u32::<BigEndian>()?,
scnptr: cursor.read_u32::<BigEndian>()?,
relptr: cursor.read_u32::<BigEndian>()?,
lnnoptr: cursor.read_u32::<BigEndian>()?,
nreloc: cursor.read_u16::<BigEndian>()?,
nlnno: cursor.read_u16::<BigEndian>()?,
flags: cursor.read_u32::<BigEndian>()?,
};
section_headers.push(sec_header);
}
// SECOND PASS: Now that we have decoded the section headers,
// let's decode the section relocation tables.
let mut sections: Vec<Section> = vec!();
for header in section_headers {
let mut relocation_entries: Vec<RelocationEntry> = vec!();
if header.nreloc > 0 {
let offset = header.relptr;
cursor.seek(SeekFrom::Start(u64::from(offset)))?;
for _ in 0..header.nreloc {
let entry = RelocationEntry {
vaddr: cursor.read_u32::<BigEndian>()?,
symndx: cursor.read_u32::<BigEndian>()?,
rtype: cursor.read_u16::<BigEndian>()?,
};
relocation_entries.push(entry);
}
}
let section = Section {
header,
relocation_entries,
};
sections.push(section);
}
// FINAL TOUCHUPS
let timestamp = Utc.timestamp(i64::from(header.timestamp), 0);
let metadata = MetaData {
header,
timestamp,
opt_header,
sections,
};
Ok(metadata)
}
}

View File

@ -1,42 +1,81 @@
extern crate clap;
#[macro_use] extern crate bitflags;
use std::error::Error;
use std::fs::File;
use std::io::prelude::*;
use std::io::Read;
use std::path::Path;
use std::vec::Vec;
use std::io::Cursor;
use std::str;
use clap::{Arg, App};
use we32k::get_opcodes;
mod we32k;
use crate::coff::*;
fn disassemble(buf: &Vec<u8>) {
println!("I'm disassembling a {} byte buffer", buf.len());
mod coff;
let opcodes = get_opcodes();
fn name(buf: &[u8]) -> Result<&str, std::str::Utf8Error> {
let nul = buf.iter().position( |&c| c == b'\0').unwrap_or(buf.len());
str::from_utf8(&buf[0..nul])
}
println!("I have {} opcodes to look at.", opcodes.len());
fn disassemble(buf: &[u8]) {
let mut cursor = Cursor::new(buf);
let mut i = 0;
let mut op: u16;
if let Ok(metadata) = MetaData::read(&mut cursor) {
println!("File Header:");
println!(" {:?}", metadata.header);
println!(" Magic Number: 0x{:04x}", metadata.header.magic);
println!(" # Sections: {}", metadata.header.section_count);
println!(" Date: {}", metadata.timestamp.to_rfc2822());
println!(" Symbols Ptr: 0x{:x}", metadata.header.symbols_pointer);
println!(" Symbol Count: {}", metadata.header.symbol_count);
println!(" Opt Hdr: {:?}", metadata.header.opt_header == 0x1c);
println!(" Flags: 0x{:04x}", metadata.header.flags);
while i < buf.len() {
op = buf[i] as u16;
// Not all opcodes are one byte. All opcodes starting with
// 0x30 are two-bytes long.
if op == 0x30 {
// Fetch the second byte of the opcode.
op = 0x3000 | buf[i + 1] as u16;
i = i + 1;
if let Some(opt_header) = metadata.opt_header {
println!();
println!("Optional Header:");
println!(" Magic Number: 0x{:04x}", opt_header.magic);
println!(" Version Stamp: 0x{:04x}", opt_header.version_stamp);
println!(" Text Size: 0x{:x}", opt_header.text_size);
println!(" dsize: 0x{:x}", opt_header.dsize);
println!(" bsize: 0x{:x}", opt_header.bsize);
println!(" Entry Point: 0x{:x}", opt_header.entry_point);
println!(" Text Start: 0x{:x}", opt_header.text_start);
println!(" Data Start: 0x{:x}", opt_header.data_start);
}
println!("0x{:04x}", op);
for section in metadata.sections {
i += 1;
}
let header = section.header;
println!();
println!();
println!("Section Header:");
println!(" Name: {}", name(&header.name).unwrap());
println!(" Phys. Addr: 0x{:x}", header.paddr);
println!(" Virtual Addr: 0x{:x}", header.vaddr);
println!(" Sec. Size: 0x{:x}", header.size);
println!(" Data Offset: 0x{:x}", header.scnptr);
println!(" Rel. Tab. Offset: 0x{:x}", header.relptr);
println!(" Line Num. Offset: 0x{:x}", header.lnnoptr);
println!(" Rel. Tab. Entries: {}", header.nreloc);
println!(" Line Num. Entries: {}", header.nlnno);
println!(" Flags: 0x{:08x}", header.flags);
// If there is relocation data, let's dump that too.
if header.nreloc > 0 {
println!(" Relocation Table:");
for (i, entry) in section.relocation_entries.iter().enumerate() {
println!(" [{:03}] vaddr=0x{:08x}, symndx={}, type={}",
i, entry.vaddr, entry.symndx, entry.rtype);
}
}
}
};
}
fn main() {
@ -62,8 +101,6 @@ fn main() {
let path = Path::new(infile);
let display = path.display();
println!("I'm decompiling: {}", display);
let mut file = match File::open(&path) {
Err(why) => panic!("Couldn't open {}: {}", display, why.description()),
Ok(file) => file,
@ -71,9 +108,8 @@ fn main() {
let mut buf = Vec::new();
match file.read_to_end(&mut buf) {
Err(why) => panic!("Couldn't open {}: {}", display, why.description()),
Ok(_) => (),
if let Err(why) = file.read_to_end(&mut buf) {
panic!("Couldn't open {}: {}", display, why.description())
}
disassemble(&buf);