mirror of
https://github.com/zeldaret/mm.git
synced 2024-11-23 12:59:44 +00:00
cd087d8511
* regs.h * gfxalloc.h * z64inventory.h * gfx.h * graph.h * z64olib.h * z64elf_message.h * fix missing include * Include z64inventory.h on z64save.h * fix bss * Move PosRot to z64math.h * So dumb * Update src/overlays/actors/ovl_En_Kusa/z_en_kusa.c Co-authored-by: Derek Hensley <hensley.derek58@gmail.com> * review * Remove graph.h * bss --------- Co-authored-by: Derek Hensley <hensley.derek58@gmail.com>
169 lines
7.3 KiB
Python
Executable File
169 lines
7.3 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
|
|
# SPDX-FileCopyrightText: © 2024 ZeldaRET
|
|
# SPDX-License-Identifier: MIT
|
|
|
|
import colorama
|
|
colorama.init()
|
|
|
|
import argparse
|
|
import sys
|
|
import mapfile_parser
|
|
from pathlib import Path
|
|
|
|
def eprint(*args, **kwargs):
|
|
print(*args, file=sys.stderr, **kwargs)
|
|
|
|
def mapPathToSource(origName: Path) -> Path:
|
|
# Try to map built path to the source path
|
|
parts = origName.parts
|
|
if parts[0] == "build":
|
|
parts = parts[2:]
|
|
|
|
path = Path(*parts)
|
|
# Assume every file in the asm folder has .s extension, while everything else has .c extension
|
|
if path.parts[0] == "asm":
|
|
path = path.with_suffix(".s")
|
|
else:
|
|
path = path.with_suffix(".c")
|
|
return path
|
|
|
|
def compareMapFiles(mapFileBuild: Path, mapFileExpected: Path, section: str=".bss", reverseCheck: bool=True) -> mapfile_parser.MapsComparisonInfo:
|
|
eprint(f"Build mapfile: {mapFileBuild}")
|
|
eprint(f"Expected mapfile: {mapFileExpected}")
|
|
eprint("")
|
|
|
|
if not mapFileBuild.exists():
|
|
eprint(f"{colorama.Fore.LIGHTRED_EX}error{colorama.Fore.RESET}: mapfile not found at {mapFileBuild}. Did you forget to build the rom?")
|
|
exit(1)
|
|
|
|
if not mapFileExpected.exists():
|
|
eprint(f"{colorama.Fore.LIGHTRED_EX}error{colorama.Fore.RESET}: expected mapfile not found at {mapFileExpected}. A mapfile under the 'expected' folder is required")
|
|
exit(1)
|
|
|
|
buildMap = mapfile_parser.MapFile()
|
|
buildMap.readMapFile(mapFileBuild)
|
|
if section != "all":
|
|
buildMap = buildMap.filterBySectionType(section)
|
|
|
|
expectedMap = mapfile_parser.MapFile()
|
|
expectedMap.readMapFile(mapFileExpected)
|
|
if section != "all":
|
|
expectedMap = expectedMap.filterBySectionType(section)
|
|
|
|
return buildMap.compareFilesAndSymbols(expectedMap, checkOtherOnSelf=reverseCheck)
|
|
|
|
|
|
def printSymbolComparison(comparisonInfo: mapfile_parser.MapsComparisonInfo, printAll = True):
|
|
print("Symbol Name,Build Address,Build File,Expected Address,Expected File,Difference,GOOD/BAD/MISSING")
|
|
|
|
# If it's bad or missing, don't need to do anything special.
|
|
# If it's good, check for if it's in a file with bad or missing stuff, and check if print all is on. If none of these, print it.
|
|
|
|
for symbolInfo in comparisonInfo.comparedList:
|
|
buildFile = symbolInfo.buildFile.filepath if symbolInfo.buildFile is not None else None
|
|
expectedFile = symbolInfo.expectedFile.filepath if symbolInfo.expectedFile is not None else None
|
|
|
|
buildFileName = ""
|
|
if buildFile is not None:
|
|
buildFileName = mapPathToSource(buildFile)
|
|
|
|
expectedFileName = ""
|
|
if expectedFile is not None:
|
|
expectedFileName = mapPathToSource(expectedFile)
|
|
|
|
symbolGood = colorama.Fore.RED + "BAD" + colorama.Fore.RESET
|
|
if symbolInfo.diff is None:
|
|
symbolGood = colorama.Fore.YELLOW + "MISSING" + colorama.Fore.RESET
|
|
print(f"{symbolInfo.symbol.name},{symbolInfo.buildAddress:X},{buildFileName},{symbolInfo.expectedAddress:X},{expectedFileName},{symbolInfo.diff},{symbolGood}")
|
|
continue
|
|
|
|
if symbolInfo.diff == 0:
|
|
symbolGood = colorama.Fore.GREEN + "GOOD" + colorama.Fore.RESET
|
|
if not buildFile in comparisonInfo.badFiles and not expectedFile in comparisonInfo.badFiles:
|
|
if not buildFile in comparisonInfo.badFiles and not expectedFile in comparisonInfo.badFiles:
|
|
if not printAll:
|
|
continue
|
|
|
|
if buildFile != expectedFile:
|
|
symbolGood += colorama.Fore.CYAN + " MOVED" + colorama.Fore.RESET
|
|
print(f"{symbolInfo.symbol.name},{symbolInfo.buildAddress:X},{buildFileName},{symbolInfo.expectedAddress:X},{expectedFileName},{symbolInfo.diff:X},{symbolGood}")
|
|
|
|
|
|
def printFileComparison(comparisonInfo: mapfile_parser.MapsComparisonInfo, fun_allowed: bool = True):
|
|
eprint("")
|
|
|
|
if len(comparisonInfo.badFiles) != 0:
|
|
print(colorama.Fore.RED + " BAD" + colorama.Style.RESET_ALL)
|
|
|
|
for file in comparisonInfo.badFiles:
|
|
eprint(f"Symbol reordering in {mapPathToSource(file.filepath)}")
|
|
eprint("")
|
|
|
|
if fun_allowed:
|
|
eprint(colorama.Fore.LIGHTWHITE_EX +
|
|
" Symbols are REORDERED!!\n"
|
|
" Oh! MY GOD!!"
|
|
+ colorama.Style.RESET_ALL)
|
|
eprint("")
|
|
|
|
if len(comparisonInfo.missingFiles) != 0:
|
|
print(colorama.Fore.YELLOW + " MISSING" + colorama.Style.RESET_ALL)
|
|
|
|
for file in comparisonInfo.missingFiles:
|
|
eprint(f"Symbols missing from {mapPathToSource(file.filepath)}")
|
|
eprint("")
|
|
|
|
if fun_allowed:
|
|
eprint(colorama.Fore.LIGHTWHITE_EX + " Error, should (not) be in here " + colorama.Style.RESET_ALL)
|
|
eprint("")
|
|
|
|
eprint("Some files appear to be missing symbols. Have they been renamed or declared as static? You may need to remake 'expected'")
|
|
|
|
|
|
def main():
|
|
description = "Check that globally visible symbols has not been reordered."
|
|
epilog = """\
|
|
N.B. Since this script reads the map files, it can only see globally visible symbols; in-function static symbols must be examined with other tools.
|
|
"""
|
|
|
|
parser = argparse.ArgumentParser(description=description, epilog=epilog, formatter_class=argparse.RawTextHelpFormatter)
|
|
parser.add_argument("-v", "--version", help="MM version to check. Defaults to n64-us", default="n64-us")
|
|
parser.add_argument("-a", "--print-all", help="Print all symbols of the section, not just non-matching.", action="store_true")
|
|
parser.add_argument("-n", "--no-fun-allowed", help="Remove amusing messages.", action="store_true")
|
|
parser.add_argument("-r", "--no-reverse-check", help="Disable looking for symbols on the expected map that are missing on the built map file.", action="store_true")
|
|
parser.add_argument("-s", "--section", help="Specify which section should be checked for reordered symbols. Use `all` to check all sections. Defaults to .bss", default=".bss", choices=[".text", ".data", ".rodata", ".bss", "all"])
|
|
args = parser.parse_args()
|
|
|
|
mapfilePath = Path(f"build/{args.version}/mm-{args.version}.map")
|
|
mapfileExpectedPath = "expected" / mapfilePath
|
|
reverseCheck: bool = not args.no_reverse_check
|
|
section: str = args.section
|
|
|
|
comparisonInfo = compareMapFiles(mapfilePath, mapfileExpectedPath, section, reverseCheck)
|
|
printSymbolComparison(comparisonInfo, args.print_all)
|
|
|
|
if len(comparisonInfo.badFiles) + len(comparisonInfo.missingFiles) != 0:
|
|
printFileComparison(comparisonInfo, not args.no_fun_allowed)
|
|
return 1
|
|
|
|
eprint("")
|
|
eprint(colorama.Fore.GREEN + " GOOD" + colorama.Style.RESET_ALL)
|
|
|
|
if args.no_fun_allowed:
|
|
return 0
|
|
|
|
eprint("\n" + colorama.Fore.LIGHTWHITE_EX +
|
|
colorama.Back.RED + f" " + colorama.Back.RESET + "\n" +
|
|
colorama.Back.RED + f" CONGRATURATIONS! " + colorama.Back.RESET + "\n" +
|
|
colorama.Back.RED + "{:^34}".format(f"All Global {section if section != 'all' else 'Symbols'} is correct.") + colorama.Back.RESET + "\n" +
|
|
colorama.Back.RED + f" THANK YOU! " + colorama.Back.RESET + "\n" +
|
|
colorama.Back.RED + f" You are great decomper! " + colorama.Back.RESET + "\n" +
|
|
colorama.Back.RED + f" " + colorama.Style.RESET_ALL )
|
|
|
|
return 0
|
|
|
|
if __name__ == "__main__":
|
|
ret = main()
|
|
exit(ret)
|