From 6ed438a927617cce3fea4f9b443dd8586c597dd5 Mon Sep 17 00:00:00 2001 From: angie Date: Wed, 4 Dec 2024 16:40:09 -0300 Subject: [PATCH] common sym display --- src/spimdisasm/src/context/the_context.rs | 9 +- .../src/metadata/segment_metadata.rs | 12 ++- .../src/sections/section_executable.rs | 2 - src/spimdisasm/src/sections/section_noload.rs | 43 +++++--- .../src/symbols/display/function_display.rs | 77 ++++----------- src/spimdisasm/src/symbols/display/mod.rs | 4 + .../src/symbols/display/sym_common_display.rs | 88 +++++++++++++++++ .../src/symbols/display/sym_data_display.rs | 35 ++++--- .../src/symbols/display/sym_noload_display.rs | 98 +++++++++++++++++++ src/spimdisasm/src/symbols/symbol_noload.rs | 10 +- src/spimdisasm/tests/game_tests.rs | 22 ++++- 11 files changed, 297 insertions(+), 103 deletions(-) create mode 100644 src/spimdisasm/src/symbols/display/sym_common_display.rs create mode 100644 src/spimdisasm/src/symbols/display/sym_noload_display.rs diff --git a/src/spimdisasm/src/context/the_context.rs b/src/spimdisasm/src/context/the_context.rs index 72e63a0..50c4d44 100644 --- a/src/spimdisasm/src/context/the_context.rs +++ b/src/spimdisasm/src/context/the_context.rs @@ -398,18 +398,19 @@ pub(crate) mod python_bindings { ) } - /* #[pyo3(name = "create_section_bss")] pub fn py_create_section_bss( &mut self, settings: &SectionNoloadSettings, name: String, - vram_range: AddressRange, + vram_start: u32, // Vram // TODO + vram_end: u32, // Vram // TODO parent_segment_info: ParentSegmentInfo, ) -> Result { - self.create_section_bss(settings, name, vram_range, parent_segment_info) + let vram_ranges = AddressRange::new(Vram::new(vram_start), Vram::new(vram_end)); + + self.create_section_bss(settings, name, vram_ranges, parent_segment_info) } - */ #[pyo3(name = "create_section_gcc_except_table")] pub fn py_create_section_gcc_except_table( diff --git a/src/spimdisasm/src/metadata/segment_metadata.rs b/src/spimdisasm/src/metadata/segment_metadata.rs index 0198426..9c230a0 100644 --- a/src/spimdisasm/src/metadata/segment_metadata.rs +++ b/src/spimdisasm/src/metadata/segment_metadata.rs @@ -1,14 +1,12 @@ /* SPDX-FileCopyrightText: © 2024 Decompollaborate */ /* SPDX-License-Identifier: MIT */ -use alloc::collections::btree_map::BTreeMap; +use alloc::collections::btree_map::{self, BTreeMap}; use alloc::vec::Vec; #[cfg(not(feature = "nightly"))] use ::polonius_the_crab::prelude::*; -#[cfg(feature = "nightly")] -use alloc::collections::btree_map; #[cfg(feature = "nightly")] use core::ops::Bound; @@ -399,6 +397,14 @@ impl SegmentMetadata { } } } + + pub(crate) fn find_symbols_range( + &self, + vram_start: Vram, + vram_end: Vram, + ) -> btree_map::Range<'_, Vram, SymbolMetadata> { + self.symbols.range(vram_start..vram_end) + } } impl SegmentMetadata { diff --git a/src/spimdisasm/src/sections/section_executable.rs b/src/spimdisasm/src/sections/section_executable.rs index 1470e28..8da2eaa 100644 --- a/src/spimdisasm/src/sections/section_executable.rs +++ b/src/spimdisasm/src/sections/section_executable.rs @@ -556,8 +556,6 @@ fn find_functions_check_function_ended( #[cfg(feature = "pyo3")] pub(crate) mod python_bindings { - use rabbitizer::InstructionFlags; - use crate::symbols::display::FunctionDisplaySettings; use super::*; diff --git a/src/spimdisasm/src/sections/section_noload.rs b/src/spimdisasm/src/sections/section_noload.rs index 0a960fa..b8545b2 100644 --- a/src/spimdisasm/src/sections/section_noload.rs +++ b/src/spimdisasm/src/sections/section_noload.rs @@ -67,15 +67,39 @@ impl SectionNoload { let mut noload_symbols = Vec::new(); let mut symbol_vrams = BTreeSet::new(); - // let owned_segment = context.find_owned_segment(&parent_segment_info)?; + let owned_segment = context.find_owned_segment(&parent_segment_info)?; let mut symbols_info = BTreeSet::new(); // Ensure there's a symbol at the beginning of the section. symbols_info.insert(vram_range.start()); - // let mut maybe_pointers_to_other_sections = Vec::new(); + /* + # If something that could be a pointer found in data happens to be in + # the middle of this bss file's addresses space then consider it as a + # new bss variable + for ptr in self.getAndPopPointerInDataReferencesRange(self.bssVramStart, self.bssVramEnd): + # Check if the symbol already exists, in case the user has provided size + contextSym = self.getSymbol(ptr, tryPlusOffset=True) + if contextSym is None: + self.addSymbol(ptr, sectionType=self.sectionType, isAutogenerated=True) + */ - // TODO: fill `symbols_info`` + // TODO: fill `symbols_info` + + for (sym_vram, sym) in + owned_segment.find_symbols_range(vram_range.start(), vram_range.end()) + { + symbols_info.insert(*sym_vram); + + if let Some(size) = sym.user_declared_size() { + // TODO: signal this symbol is an autogenerated pad + let next_vram = sym.vram() + size; + if next_vram != vram_range.end() { + // Avoid generating a symbol at the end of the section + symbols_info.insert(sym.vram() + size); + } + } + } let symbols_info_vec: Vec = symbols_info.into_iter().collect(); @@ -101,13 +125,6 @@ impl SectionNoload { noload_symbols.push(sym); } - // let owned_segment_mut = context.find_owned_segment_mut(&parent_segment_info)?; - // for (possible_pointer, rom_address_referencing_pointer) in maybe_pointers_to_other_sections - // { - // owned_segment_mut - // .add_possible_pointer_in_data(possible_pointer, rom_address_referencing_pointer); - // } - Ok(Self { name, vram_range, @@ -152,6 +169,8 @@ impl Section for SectionNoload { #[cfg(feature = "pyo3")] pub(crate) mod python_bindings { + use crate::symbols::display::SymNoloadDisplaySettings; + use super::*; #[pymethods] @@ -169,18 +188,16 @@ pub(crate) mod python_bindings { self.noload_symbols.len() } - /* #[pyo3(name = "display_sym")] pub fn py_display_sym( &self, context: &Context, index: usize, - settings: &SymDataDisplaySettings, + settings: &SymNoloadDisplaySettings, ) -> Option { self.noload_symbols .get(index) .map(|sym| sym.display(context, settings).to_string()) } - */ } } diff --git a/src/spimdisasm/src/symbols/display/function_display.rs b/src/spimdisasm/src/symbols/display/function_display.rs index dc8fbd3..0b03269 100644 --- a/src/spimdisasm/src/symbols/display/function_display.rs +++ b/src/spimdisasm/src/symbols/display/function_display.rs @@ -3,7 +3,6 @@ use core::fmt; -use alloc::string::String; use rabbitizer::{DisplayFlags, Instruction, Vram}; #[cfg(feature = "pyo3")] @@ -16,30 +15,29 @@ use crate::{ symbols::{trait_symbol::RomSymbol, Symbol, SymbolFunction}, }; +use super::SymCommonDisplaySettings; + #[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] #[cfg_attr(feature = "pyo3", pyclass(module = "spimdisasm"))] pub struct FunctionDisplaySettings { + common: SymCommonDisplaySettings, + display_flags: DisplayFlags, - line_end: Option, + + asm_label_indentation: u8, + _gp_rel_hack: bool, } impl FunctionDisplaySettings { pub fn new(display_flags: DisplayFlags) -> Self { Self { + common: SymCommonDisplaySettings::new(), display_flags, - line_end: None, + asm_label_indentation: 2, _gp_rel_hack: false, } } - - pub(crate) fn line_end(&self) -> &str { - if let Some(line_end) = &self.line_end { - line_end - } else { - "\n" - } - } } #[derive(Debug, Copy, Clone, Hash, PartialEq)] @@ -105,7 +103,7 @@ impl FunctionDisplay<'_, '_, '_> { f, "{}:{}", sym_label.display_name(), - self.settings.line_end() + self.settings.common.line_end() )?; } } @@ -113,53 +111,18 @@ impl FunctionDisplay<'_, '_, '_> { Ok(()) } - fn display_asm_comment(&self, f: &mut fmt::Formatter<'_>, instr: &Instruction) -> fmt::Result { - // TODO: - /* - indentation = " " * common.GlobalConfig.ASM_INDENTATION - - if not common.GlobalConfig.ASM_COMMENT: - return indentation - - if emitRomOffset: - offsetHex = "{0:0{1}X} ".format(localOffset + self.inFileOffset + self.commentOffset, common.GlobalConfig.ASM_COMMENT_OFFSET_WIDTH) - else: - offsetHex = "" - - currentVram = self.getVramOffset(localOffset) - vramHex = f"{currentVram:08X}" - - wordValueHex = "" - if wordValue is not None: - if isDouble: - wordValueHex = f"{common.Utils.qwordToCurrenEndian(wordValue):016X} " - else: - wordValueHex = f"{common.Utils.wordToCurrenEndian(wordValue):08X} " - - return f"{indentation}/* {offsetHex}{vramHex} {wordValueHex}*/ -" - */ - - write!(f, "/* ")?; - let current_vram = instr.vram(); - if let Some(rom) = self.sym.rom_vram_range().rom_from_vram(current_vram) { - // TODO: implement display for RomAddress - write!(f, "{:06X} ", rom.inner())?; - } - write!(f, "{} ", current_vram)?; - // TODO: endian - write!(f, "{:08X} ", instr.word())?; - - write!(f, "*/") - } - fn display_instruction( &self, f: &mut fmt::Formatter<'_>, instr: &Instruction, prev_instr_had_delay_slot: bool, ) -> fmt::Result { - self.display_asm_comment(f, instr)?; + let vram = instr.vram(); + let rom = self.sym.rom_vram_range().rom_from_vram(vram); + self.settings + .common + .display_asm_comment(f, rom, vram, Some(instr.word()))?; + // TODO: why two spaces instead of one? write!(f, " ")?; @@ -175,7 +138,7 @@ impl FunctionDisplay<'_, '_, '_> { f, "{}{}", instr.display(imm_override, &self.settings.display_flags), - self.settings.line_end() + self.settings.common.line_end() ) } @@ -198,9 +161,9 @@ impl fmt::Display for FunctionDisplay<'_, '_, '_> { .ok_or(fmt::Error)?; let name = metadata.display_name(); - write!(f, ".globl {}{}", name, self.settings.line_end())?; + write!(f, ".globl {}{}", name, self.settings.common.line_end())?; - write!(f, "{}:{}", name, self.settings.line_end())?; + write!(f, "{}:{}", name, self.settings.common.line_end())?; let mut prev_instr_had_delay_slot = false; for instr in self.sym.instructions() { @@ -211,7 +174,7 @@ impl fmt::Display for FunctionDisplay<'_, '_, '_> { prev_instr_had_delay_slot = instr.opcode().has_delay_slot(); } - write!(f, ".end {}{}", name, self.settings.line_end()) + write!(f, ".end {}{}", name, self.settings.common.line_end()) } } diff --git a/src/spimdisasm/src/symbols/display/mod.rs b/src/spimdisasm/src/symbols/display/mod.rs index d4cee10..9161d81 100644 --- a/src/spimdisasm/src/symbols/display/mod.rs +++ b/src/spimdisasm/src/symbols/display/mod.rs @@ -2,7 +2,11 @@ /* SPDX-License-Identifier: MIT */ mod function_display; +mod sym_common_display; mod sym_data_display; +mod sym_noload_display; pub use function_display::{FunctionDisplay, FunctionDisplaySettings}; +pub(crate) use sym_common_display::SymCommonDisplaySettings; pub use sym_data_display::{SymDataDisplay, SymDataDisplaySettings}; +pub use sym_noload_display::{SymNoloadDisplay, SymNoloadDisplaySettings}; diff --git a/src/spimdisasm/src/symbols/display/sym_common_display.rs b/src/spimdisasm/src/symbols/display/sym_common_display.rs new file mode 100644 index 0000000..47198d7 --- /dev/null +++ b/src/spimdisasm/src/symbols/display/sym_common_display.rs @@ -0,0 +1,88 @@ +/* SPDX-FileCopyrightText: © 2024 Decompollaborate */ +/* SPDX-License-Identifier: MIT */ + +use core::fmt; + +use alloc::string::String; +use rabbitizer::Vram; + +use crate::rom_address::RomAddress; + +#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] +pub struct SymCommonDisplaySettings { + line_end: Option, + + emit_asm_comment: bool, + + asm_indentation: u8, +} + +impl SymCommonDisplaySettings { + pub fn new() -> Self { + Self { + line_end: None, + emit_asm_comment: true, + asm_indentation: 4, + } + } + + pub fn line_end(&self) -> &str { + if let Some(line_end) = &self.line_end { + line_end + } else { + "\n" + } + } +} + +impl SymCommonDisplaySettings { + pub fn display_asm_comment( + &self, + f: &mut fmt::Formatter<'_>, + rom: Option, + vram: Vram, + word: Option, + ) -> fmt::Result { + if self.asm_indentation > 0 { + write!(f, "{:width$}", " ", width = self.asm_indentation as usize)?; + } + + if !self.emit_asm_comment { + return Ok(()); + } + + // TODO: + /* + if emitRomOffset: + offsetHex = "{0:0{1}X} ".format(localOffset + self.inFileOffset + self.commentOffset, common.GlobalConfig.ASM_COMMENT_OFFSET_WIDTH) + else: + offsetHex = "" + + currentVram = self.getVramOffset(localOffset) + vramHex = f"{currentVram:08X}" + + wordValueHex = "" + if wordValue is not None: + if isDouble: + wordValueHex = f"{common.Utils.qwordToCurrenEndian(wordValue):016X} " + else: + wordValueHex = f"{common.Utils.wordToCurrenEndian(wordValue):08X} " + + return f"{indentation}/* {offsetHex}{vramHex} {wordValueHex}*/ +" + */ + + write!(f, "/* ")?; + if let Some(rom) = rom { + // TODO: implement display for RomAddress + write!(f, "{:06X} ", rom.inner())?; + } + write!(f, "{} ", vram)?; + if let Some(word) = word { + // TODO: endian + write!(f, "{:08X} ", word)?; + } + + write!(f, "*/") + } +} diff --git a/src/spimdisasm/src/symbols/display/sym_data_display.rs b/src/spimdisasm/src/symbols/display/sym_data_display.rs index 06e3c70..14c8e77 100644 --- a/src/spimdisasm/src/symbols/display/sym_data_display.rs +++ b/src/spimdisasm/src/symbols/display/sym_data_display.rs @@ -3,21 +3,22 @@ use core::fmt; -use alloc::string::String; - #[cfg(feature = "pyo3")] use pyo3::prelude::*; use crate::{ context::Context, metadata::segment_metadata::FindSettings, - symbols::{Symbol, SymbolData}, + size::Size, + symbols::{RomSymbol, Symbol, SymbolData}, }; +use super::SymCommonDisplaySettings; + #[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] #[cfg_attr(feature = "pyo3", pyclass(module = "spimdisasm"))] pub struct SymDataDisplaySettings { - line_end: Option, + common: SymCommonDisplaySettings, } impl Default for SymDataDisplaySettings { @@ -28,14 +29,8 @@ impl Default for SymDataDisplaySettings { impl SymDataDisplaySettings { pub fn new() -> Self { - Self { line_end: None } - } - - pub(crate) fn line_end(&self) -> &str { - if let Some(line_end) = &self.line_end { - line_end - } else { - "\n" + Self { + common: SymCommonDisplaySettings::new(), } } } @@ -72,12 +67,20 @@ impl fmt::Display for SymDataDisplay<'_, '_, '_> { .ok_or(fmt::Error)?; let name = metadata.display_name(); - write!(f, ".globl {}{}", name, self.settings.line_end())?; + write!(f, ".globl {}{}", name, self.settings.common.line_end())?; + + write!(f, "{}:{}", name, self.settings.common.line_end())?; - write!(f, "{}:{}", name, self.settings.line_end())?; + let ranges = self.sym.rom_vram_range(); + let rom = ranges.rom().start(); + let vram = ranges.vram().start(); + for (i, byte) in self.sym.raw_bytes().iter().enumerate() { + let offset = Size::new(i as u32); - for byte in self.sym.raw_bytes() { - write!(f, ".byte 0x{:02X}{}", byte, self.settings.line_end())?; + self.settings + .common + .display_asm_comment(f, Some(rom + offset), vram + offset, None)?; + write!(f, ".byte 0x{:02X}{}", byte, self.settings.common.line_end())?; } Ok(()) diff --git a/src/spimdisasm/src/symbols/display/sym_noload_display.rs b/src/spimdisasm/src/symbols/display/sym_noload_display.rs new file mode 100644 index 0000000..eba5cb9 --- /dev/null +++ b/src/spimdisasm/src/symbols/display/sym_noload_display.rs @@ -0,0 +1,98 @@ +/* SPDX-FileCopyrightText: © 2024 Decompollaborate */ +/* SPDX-License-Identifier: MIT */ + +use core::fmt; + +#[cfg(feature = "pyo3")] +use pyo3::prelude::*; + +use crate::{ + context::Context, + metadata::segment_metadata::FindSettings, + symbols::{Symbol, SymbolNoload}, +}; + +use super::SymCommonDisplaySettings; + +#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] +#[cfg_attr(feature = "pyo3", pyclass(module = "spimdisasm"))] +pub struct SymNoloadDisplaySettings { + common: SymCommonDisplaySettings, +} + +impl Default for SymNoloadDisplaySettings { + fn default() -> Self { + Self::new() + } +} + +impl SymNoloadDisplaySettings { + pub fn new() -> Self { + Self { + common: SymCommonDisplaySettings::new(), + } + } +} + +#[derive(Debug, Copy, Clone, Hash, PartialEq)] +pub struct SymNoloadDisplay<'ctx, 'sym, 'flg> { + context: &'ctx Context, + sym: &'sym SymbolNoload, + settings: &'flg SymNoloadDisplaySettings, +} + +impl<'ctx, 'sym, 'flg> SymNoloadDisplay<'ctx, 'sym, 'flg> { + pub(crate) fn new( + context: &'ctx Context, + sym: &'sym SymbolNoload, + settings: &'flg SymNoloadDisplaySettings, + ) -> Self { + Self { + context, + sym, + settings, + } + } +} + +impl fmt::Display for SymNoloadDisplay<'_, '_, '_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let owned_segment = self + .context + .find_owned_segment(self.sym.parent_segment_info())?; + let find_settings = FindSettings::default().with_allow_addend(false); + let metadata = owned_segment + .find_symbol(self.sym.vram_range().start(), find_settings) + .ok_or(fmt::Error)?; + + let name = metadata.display_name(); + write!(f, ".globl {}{}", name, self.settings.common.line_end())?; + + write!(f, "{}:{}", name, self.settings.common.line_end())?; + + self.settings + .common + .display_asm_comment(f, None, self.sym.vram_range().start(), None)?; + write!( + f, + " .space 0x{:02X}{}", + self.sym.size(), + self.settings.common.line_end() + )?; + + Ok(()) + } +} + +#[cfg(feature = "pyo3")] +pub(crate) mod python_bindings { + use super::*; + + #[pymethods] + impl SymNoloadDisplaySettings { + #[new] + pub fn py_new() -> Self { + Self::new() + } + } +} diff --git a/src/spimdisasm/src/symbols/symbol_noload.rs b/src/spimdisasm/src/symbols/symbol_noload.rs index 5718ba7..05dd914 100644 --- a/src/spimdisasm/src/symbols/symbol_noload.rs +++ b/src/spimdisasm/src/symbols/symbol_noload.rs @@ -12,7 +12,7 @@ use crate::{ }; use super::{ - // display::{SymDataDisplay, SymDataDisplaySettings}, + display::{SymNoloadDisplay, SymNoloadDisplaySettings}, Symbol, }; @@ -50,17 +50,15 @@ impl SymbolNoload { impl SymbolNoload {} -/* impl<'ctx, 'sym, 'flg> SymbolNoload { pub fn display( &'sym self, context: &'ctx Context, - settings: &'flg SymDataDisplaySettings, - ) -> SymDataDisplay<'ctx, 'sym, 'flg> { - SymDataDisplay::new(context, self, settings) + settings: &'flg SymNoloadDisplaySettings, + ) -> SymNoloadDisplay<'ctx, 'sym, 'flg> { + SymNoloadDisplay::new(context, self, settings) } } -*/ impl Symbol for SymbolNoload { fn vram_range(&self) -> &AddressRange { diff --git a/src/spimdisasm/tests/game_tests.rs b/src/spimdisasm/tests/game_tests.rs index 73acaf7..2ec04c4 100644 --- a/src/spimdisasm/tests/game_tests.rs +++ b/src/spimdisasm/tests/game_tests.rs @@ -10,7 +10,7 @@ use spimdisasm::{ parent_segment_info::ParentSegmentInfo, rom_vram_range::RomVramRange, sections::{SectionDataSettings, SectionExecutableSettings, SectionNoloadSettings}, - symbols::display::{FunctionDisplaySettings, SymDataDisplaySettings}, + symbols::display::{FunctionDisplaySettings, SymDataDisplaySettings, SymNoloadDisplaySettings}, }; mod game_tests_info; @@ -351,6 +351,7 @@ fn drmario64_us_without_symbols() { let instr_display_flags = DisplayFlags::default(); let function_display_settings = FunctionDisplaySettings::new(instr_display_flags); let sym_data_display_settings = SymDataDisplaySettings::new(); + let sym_noload_display_settings = SymNoloadDisplaySettings::new(); for seg in &segments { for sect in &seg.text_sections { for sym in sect.functions() { @@ -376,6 +377,14 @@ fn drmario64_us_without_symbols() { .to_string(); } } + for sect in &seg.bss_sections { + for sym in sect.noload_symbols() { + // sym.display(&context, &data_display_settings).hash(&mut hasher); + let _a = sym + .display(&context, &sym_noload_display_settings) + .to_string(); + } + } } assert_eq!(context.global_segment().symbols().len(), 9274); @@ -432,6 +441,7 @@ fn drmario64_us_with_symbols() { let instr_display_flags = DisplayFlags::default(); let function_display_settings = FunctionDisplaySettings::new(instr_display_flags); let sym_data_display_settings = SymDataDisplaySettings::new(); + let sym_noload_display_settings = SymNoloadDisplaySettings::new(); for seg in &segments { for sect in &seg.text_sections { for sym in sect.functions() { @@ -457,9 +467,17 @@ fn drmario64_us_with_symbols() { .to_string(); } } + for sect in &seg.bss_sections { + for sym in sect.noload_symbols() { + // sym.display(&context, &data_display_settings).hash(&mut hasher); + let _a = sym + .display(&context, &sym_noload_display_settings) + .to_string(); + } + } } - assert_eq!(context.global_segment().symbols().len(), 9560); + assert_eq!(context.global_segment().symbols().len(), 9620); /* for seg in &segments {