diff --git a/CHANGELOG.md b/CHANGELOG.md index 171ca17..99cf68b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,8 +11,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add new parameters to `bss_check.printSymbolComparison`. - `printGoods`: Allows toggling printing the GOOD symbols. - - `printingStyle`: The style to use to print the symbols, either `"csv"` or `"listing"`. + - `printingStyle`: The style to use to print the symbols, either `"csv"` or + `"listing"`. - TODO: port to Rust. +- New `MapFile.fixupNonMatchingSymbols` method. + - Allows to fixup size calculation of symbols messed up by symbols with the + same name suffixed with `.NON_MATCHING`. ### Changed diff --git a/src/mapfile_parser/frontends/jsonify.py b/src/mapfile_parser/frontends/jsonify.py index 7b1a785..cf6493c 100644 --- a/src/mapfile_parser/frontends/jsonify.py +++ b/src/mapfile_parser/frontends/jsonify.py @@ -12,13 +12,15 @@ from .. import mapfile -def doJsonify(mapPath: Path, outputPath: Path|None, humanReadable: bool=True) -> int: +def doJsonify(mapPath: Path, outputPath: Path|None, humanReadable: bool=True, applyFixes: bool=False) -> int: if not mapPath.exists(): print(f"Could not find mapfile at '{mapPath}'") return 1 mapFile = mapfile.MapFile() mapFile.readMapFile(mapPath) + if applyFixes: + mapFile = mapFile.fixupNonMatchingSymbols() jsonStr = json.dumps(mapFile.toJson(humanReadable=humanReadable), indent=4) @@ -35,8 +37,9 @@ def processArguments(args: argparse.Namespace): mapPath: Path = args.mapfile outputPath: Path|None = Path(args.output) if args.output is not None else None machine: bool = args.machine + applyFixes: bool = args.applyFixes - exit(doJsonify(mapPath, outputPath, humanReadable=not machine)) + exit(doJsonify(mapPath, outputPath, humanReadable=not machine, applyFixes=applyFixes)) def addSubparser(subparser: argparse._SubParsersAction[argparse.ArgumentParser]): parser = subparser.add_parser("jsonify", help="Converts a mapfile into a json format.") @@ -44,5 +47,6 @@ def addSubparser(subparser: argparse._SubParsersAction[argparse.ArgumentParser]) parser.add_argument("mapfile", help="Path to a map file", type=Path) parser.add_argument("-o", "--output", help="Output path of for the generated json. If omitted then stdout is used instead.") parser.add_argument("-m", "--machine", help="Emit numbers as numbers instead of outputting them as pretty strings.", action="store_true") + parser.add_argument("-f", "--apply-fixes", help="Apply certain fixups, like fixing size calculation of because of the existence of fake `.NON_MATCHING` symbols.", action="store_true") parser.set_defaults(func=processArguments) diff --git a/src/mapfile_parser/frontends/progress.py b/src/mapfile_parser/frontends/progress.py index ab3326c..6c538bc 100644 --- a/src/mapfile_parser/frontends/progress.py +++ b/src/mapfile_parser/frontends/progress.py @@ -18,7 +18,7 @@ def getProgress(mapPath: Path, asmPath: Path, nonmatchingsPath: Path, pathIndex: mapFile.debugging = debugging mapFile.readMapFile(mapPath) - return mapFile.filterBySectionType(".text").getProgress(asmPath, nonmatchingsPath, pathIndex=pathIndex) + return mapFile.filterBySectionType(".text").fixupNonMatchingSymbols().getProgress(asmPath, nonmatchingsPath, pathIndex=pathIndex) def doProgress(mapPath: Path, asmPath: Path, nonmatchingsPath: Path, pathIndex: int=2, debugging: bool=False) -> int: if not mapPath.exists(): diff --git a/src/mapfile_parser/mapfile.py b/src/mapfile_parser/mapfile.py index bae239e..1d588b7 100644 --- a/src/mapfile_parser/mapfile.py +++ b/src/mapfile_parser/mapfile.py @@ -146,6 +146,10 @@ def toJson(self, humanReadable: bool=True) -> dict[str, Any]: return result + def clone(self) -> Symbol: + return Symbol(self.name, self.vram, self.size, self.vrom, self.align) + + def __eq__(self, other: object) -> bool: if not isinstance(other, Symbol): return False @@ -302,6 +306,13 @@ def appendSymbol(self, sym: Symbol) -> None: self._symbols.append(sym) + def clone(self) -> File: + f = File(self.filepath, self.vram, self.size, self.sectionType, self.vrom, self.align) + for sym in self._symbols: + f._symbols.append(sym.clone()) + return f + + def __iter__(self) -> Generator[Symbol, None, None]: for sym in self._symbols: yield sym @@ -476,6 +487,13 @@ def appendFile(self, file: File) -> None: self._filesList.append(file) + def clone(self) -> Segment: + s = Segment(self.name, self.vram, self.size, self.vrom, self.align) + for f in self._filesList: + s._filesList.append(f.clone()) + return s + + def __iter__(self) -> Generator[File, None, None]: for file in self._filesList: yield file @@ -672,6 +690,20 @@ def mixFolders(self) -> MapFile: return newMapFile + def fixupNonMatchingSymbols(self) -> MapFile: + newMapFile = self.clone() + + for segment in newMapFile._segmentsList: + for file in segment._filesList: + for sym in file._symbols: + if sym.name.endswith(".NON_MATCHING") and sym.size != 0: + realSym = file.findSymbolByName(sym.name.replace(".NON_MATCHING", "")) + if realSym is not None and realSym.size == 0: + realSym.size = sym.size + sym.size = 0 + + return newMapFile + def getProgress(self, asmPath: Path, nonmatchings: Path, aliases: dict[str, str]=dict(), pathIndex: int=2) -> tuple[ProgressStats, dict[str, ProgressStats]]: totalStats = ProgressStats() progressPerFolder: dict[str, ProgressStats] = dict() @@ -810,6 +842,14 @@ def appendSegment(self, segment: Segment) -> None: self._segmentsList.append(segment) + def clone(self) -> MapFile: + m = MapFile() + m.debugging = self.debugging + for s in self._segmentsList: + m._segmentsList.append(s.clone()) + return m + + def __iter__(self) -> Generator[Segment, None, None]: for file in self._segmentsList: yield file diff --git a/src/rs/file.rs b/src/rs/file.rs index 2999aa1..46ed04f 100644 --- a/src/rs/file.rs +++ b/src/rs/file.rs @@ -62,6 +62,22 @@ impl File { self.symbols.iter().find(|&sym| sym.name == sym_name) } + pub fn find_symbol_and_index_by_name( + &self, + sym_name: &str, + ) -> Option<(&symbol::Symbol, usize)> { + for (index, sym) in self.symbols.iter().enumerate() { + if sym.name == sym_name { + return Some((sym, index)); + } + } + None + } + + pub fn find_symbol_by_name_mut(&mut self, sym_name: &str) -> Option<&mut symbol::Symbol> { + self.symbols.iter_mut().find(|sym| sym.name == sym_name) + } + pub fn find_symbol_by_vram_or_vrom(&self, address: u64) -> Option<(&symbol::Symbol, i64)> { let mut prev_sym: Option<&symbol::Symbol> = None; @@ -126,6 +142,29 @@ impl File { None } + pub fn fixup_non_matching_symbols(&mut self) { + let mut symbols_to_fix = Vec::new(); + + for (index, sym) in self.symbols.iter().enumerate() { + if sym.name.ends_with(".NON_MATCHING") && sym.size.is_some() && sym.size == Some(0) { + let real_name = sym.name.replace(".NON_MATCHING", ""); + + if let Some((_real_sym, real_index)) = + self.find_symbol_and_index_by_name(&real_name) + { + symbols_to_fix.push((real_index, sym.size)); + symbols_to_fix.push((index, Some(0))); + } + } + } + + for (index, new_size) in symbols_to_fix { + if let Some(sym) = self.symbols.get_mut(index) { + sym.size = new_size; + } + } + } + pub fn to_csv_header(print_vram: bool) -> String { let mut ret = String::new(); @@ -397,6 +436,10 @@ pub(crate) mod python_bindings { } } + fn fixupNonMatchingSymbols(&mut self) { + self.fixup_non_matching_symbols() + } + #[staticmethod] #[pyo3(signature=(print_vram=true))] fn toCsvHeader(print_vram: bool) -> String { diff --git a/src/rs/mapfile.rs b/src/rs/mapfile.rs index fe40a82..e9d3e25 100644 --- a/src/rs/mapfile.rs +++ b/src/rs/mapfile.rs @@ -599,6 +599,17 @@ impl MapFile { new_map_file } + pub fn fixup_non_matching_symbols(&self) -> Self { + let mut new_map_file = self.clone(); + + new_map_file + .segments_list + .iter_mut() + .for_each(|x| x.fixup_non_matching_symbols()); + + new_map_file + } + pub fn get_progress( &self, asm_path: &Path, @@ -867,6 +878,10 @@ pub(crate) mod python_bindings { self.mix_folders() } + fn fixupNonMatchingSymbols(&self) -> Self { + self.fixup_non_matching_symbols() + } + #[pyo3(signature = (asm_path, nonmatchings, aliases=HashMap::new(), path_index=2))] fn getProgress( &self, diff --git a/src/rs/segment.rs b/src/rs/segment.rs index 2137c72..9da83a7 100644 --- a/src/rs/segment.rs +++ b/src/rs/segment.rs @@ -156,6 +156,12 @@ impl Segment { new_segment } + pub fn fixup_non_matching_symbols(&mut self) { + self.files_list + .iter_mut() + .for_each(|x| x.fixup_non_matching_symbols()) + } + pub fn to_csv(&self, print_vram: bool, skip_without_symbols: bool) -> String { let mut ret = String::new(); @@ -385,6 +391,10 @@ pub(crate) mod python_bindings { self.mix_folders() } + fn fixupNonMatchingSymbols(&mut self) { + self.fixup_non_matching_symbols() + } + #[pyo3(signature=(print_vram=true, skip_without_symbols=true))] fn toCsv(&self, print_vram: bool, skip_without_symbols: bool) -> String { self.to_csv(print_vram, skip_without_symbols)