From bbfe541a6d374b769fb9be13c26c3efaf5eec271 Mon Sep 17 00:00:00 2001 From: Filipe Rodrigues Date: Wed, 13 Jan 2021 23:09:25 +0000 Subject: [PATCH] Fixed `{Data, Func}Table::get_*`. `Directive` now implements `InstTargetFmt`. --- dcb-exe/src/exe/data.rs | 6 ++++++ dcb-exe/src/exe/data/table.rs | 5 ++--- dcb-exe/src/exe/func.rs | 14 ++++++++------ dcb-exe/src/exe/func/table.rs | 9 +++++---- dcb-exe/src/exe/inst.rs | 2 +- dcb-exe/src/exe/inst/directive.rs | 15 ++++++++++++++- dcb-tools/src/decompiler/main.rs | 5 ++++- 7 files changed, 40 insertions(+), 16 deletions(-) diff --git a/dcb-exe/src/exe/data.rs b/dcb-exe/src/exe/data.rs index 6ba53ce..a57ec02 100644 --- a/dcb-exe/src/exe/data.rs +++ b/dcb-exe/src/exe/data.rs @@ -52,6 +52,12 @@ impl Data { self.pos + self.size() } + /// Checks if this data contains `pos` + #[must_use] + pub fn contains(&self, pos: Pos) -> bool { + (self.pos..self.end_pos()).contains(&pos) + } + /// Returns the size, in bytes, of this data #[must_use] pub fn size(&self) -> usize { diff --git a/dcb-exe/src/exe/data/table.rs b/dcb-exe/src/exe/data/table.rs index 05543d3..11f9990 100644 --- a/dcb-exe/src/exe/data/table.rs +++ b/dcb-exe/src/exe/data/table.rs @@ -60,14 +60,13 @@ impl DataTable { #[must_use] pub fn get_containing(&self, pos: Pos) -> Option<&Data> { // Find the first data that includes `pos`. - self.range(..=pos).find(|data| pos < data.end_pos()) + self.range(..=pos).filter(|data| data.contains(pos)).min_by_key(|data| data.size()) } /// Retrieves the smallest data location at `pos` #[must_use] pub fn get_starting_at(&self, pos: Pos) -> Option<&Data> { - // Get the first data with position `pos` - self.range(pos..=pos).next() + self.get_containing(pos).filter(|data| data.pos == pos) } /// Returns a range of data diff --git a/dcb-exe/src/exe/func.rs b/dcb-exe/src/exe/func.rs index 1966fba..c57cf8a 100644 --- a/dcb-exe/src/exe/func.rs +++ b/dcb-exe/src/exe/func.rs @@ -45,6 +45,14 @@ pub struct Func { pub end_pos: Pos, } +impl Func { + /// Checks if this function contains `pos` + #[must_use] + pub fn contains(&self, pos: Pos) -> bool { + (self.start_pos..self.end_pos).contains(&pos) + } +} + impl Borrow for Func { fn borrow(&self) -> &Pos { &self.start_pos @@ -60,12 +68,6 @@ impl PartialEq for Func { impl Eq for Func {} -/// Only the start position is hashed, just as in the [`PartialEq`] impl. -impl std::hash::Hash for Func { - fn hash(&self, state: &mut H) { - self.start_pos.hash(state); - } -} /// Only the start position matters for the order impl PartialOrd for Func { diff --git a/dcb-exe/src/exe/func/table.rs b/dcb-exe/src/exe/func/table.rs index c9186c0..3b4e5b4 100644 --- a/dcb-exe/src/exe/func/table.rs +++ b/dcb-exe/src/exe/func/table.rs @@ -49,16 +49,17 @@ impl FuncTable { DiscardingSortedMergeIter::new(self.0.into_iter(), other.0.into_iter()).collect() } - /// Retrieves a function that contains `pos` + /// Retrieves the function containing `pos` #[must_use] pub fn get_containing(&self, pos: Pos) -> Option<&Func> { - self.range(..=pos).next_back().filter(|func| pos < func.end_pos) + // Find the first data that includes `pos`. + self.range(..=pos).find(|func| func.contains(pos)) } - /// Retrieves a function that starting at `pos` + /// Retrieves the function at `pos` #[must_use] pub fn get_starting_at(&self, pos: Pos) -> Option<&Func> { - self.range(pos..=pos).next() + self.get_containing(pos).filter(|func| func.start_pos == pos) } /// Returns a range of functions diff --git a/dcb-exe/src/exe/inst.rs b/dcb-exe/src/exe/inst.rs index d0c6415..75adabd 100644 --- a/dcb-exe/src/exe/inst.rs +++ b/dcb-exe/src/exe/inst.rs @@ -136,7 +136,7 @@ impl<'a> InstFmt for Inst<'a> { match self { Self::Basic(inst) => inst.fmt(pos, f), Self::Pseudo(inst) => inst.fmt(pos, f), - Self::Directive(directive) => directive.fmt(pos, f), + Self::Directive(directive) => ::fmt(directive, pos, f), } } } diff --git a/dcb-exe/src/exe/inst/directive.rs b/dcb-exe/src/exe/inst/directive.rs index 0aa6f65..86dbd1f 100644 --- a/dcb-exe/src/exe/inst/directive.rs +++ b/dcb-exe/src/exe/inst/directive.rs @@ -1,7 +1,7 @@ //! Directives // Imports -use super::{InstFmt, InstSize}; +use super::{InstFmt, InstSize, InstTargetFmt}; use crate::exe::{DataType, Pos}; use ascii::{AsciiChar, AsciiStr}; use dcb_util::NextFromBytes; @@ -157,6 +157,19 @@ impl<'a> InstFmt for Directive<'a> { } } + +impl<'a> InstTargetFmt for Directive<'a> { + fn fmt(&self, _pos: Pos, target: impl std::fmt::Display, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match self { + Self::Dw(_) => write!(f, "dw {target}"), + Self::Dh(_) => write!(f, "dh {target}"), + Self::Db(_) => write!(f, "db {target}"), + Self::Ascii(_) => write!(f, ".ascii {target}"), + } + } +} + + /// Reads an ascii string from a byte slice until null, aligned to a word #[allow(clippy::as_conversions, clippy::cast_possible_truncation)] // Our length will always fit into a `u32`. fn read_ascii_until_null(bytes: &[u8]) -> Option<&AsciiStr> { diff --git a/dcb-tools/src/decompiler/main.rs b/dcb-tools/src/decompiler/main.rs index 42b4384..d03d32a 100644 --- a/dcb-tools/src/decompiler/main.rs +++ b/dcb-tools/src/decompiler/main.rs @@ -82,7 +82,7 @@ use std::fmt; use anyhow::Context; use dcb_exe::{ exe::{ - inst::{basic, pseudo, Inst, InstFmt, InstTarget, InstTargetFmt}, + inst::{basic, pseudo, Directive, Inst, InstFmt, InstTarget, InstTargetFmt}, iter::ExeItem, Func, }, @@ -179,6 +179,9 @@ pub fn inst_display<'a>(inst: &'a Inst, exe: &'a Exe, func: Option<&'a Func>, po )) => write!(f, "{}", self::inst_target_fmt(inst, pos, self::inst_target(exe, func, Pos(*target)))), Inst::Pseudo(pseudo::Inst::Load(inst)) => write!(f, "{}", self::inst_target_fmt(inst, pos, self::inst_target(exe, func, inst.target(pos)))), Inst::Pseudo(pseudo::Inst::Store(inst)) => write!(f, "{}", self::inst_target_fmt(inst, pos, self::inst_target(exe, func, inst.target(pos)))), + Inst::Directive(directive @ Directive::Dw(target)) => { + write!(f, "{}", self::inst_target_fmt(directive, pos, self::inst_target(exe, func, Pos(*target)))) + }, // TODO: Directive inst => write!(f, "{}", self::inst_fmt(inst, pos)), })