refactor some scripts to get rid of duplicating code

This commit is contained in:
shibbo 2024-08-11 21:42:39 -04:00
parent 7c56ef4555
commit 0f27b0cb9b
4 changed files with 74 additions and 109 deletions

View File

@ -8,6 +8,7 @@ import sys
import os import os
import pathlib import pathlib
from ninja_syntax import Writer from ninja_syntax import Writer
import helpers
nonmatching_str = "" nonmatching_str = ""
clean = False clean = False
@ -35,7 +36,6 @@ LIBRARIES = ["Game", "ActionLibrary", "agl", "eui", "nn", "sead"]
incdirs = " ".join([f'-I {dir}' for dir in INCLUDE_DIRS]) incdirs = " ".join([f'-I {dir}' for dir in INCLUDE_DIRS])
COMPILER_CMD = f"-x c++ -O3 -fno-omit-frame-pointer -mno-implicit-float -fno-cxx-exceptions -fno-strict-aliasing -std=gnu++14 -fno-common -fno-short-enums -ffunction-sections -fdata-sections -fPIC -mcpu=cortex-a57+fp+simd+crypto+crc -g -Wall {nonmatching_str} {incdirs} -c" COMPILER_CMD = f"-x c++ -O3 -fno-omit-frame-pointer -mno-implicit-float -fno-cxx-exceptions -fno-strict-aliasing -std=gnu++14 -fno-common -fno-short-enums -ffunction-sections -fdata-sections -fPIC -mcpu=cortex-a57+fp+simd+crypto+crc -g -Wall {nonmatching_str} {incdirs} -c"
COMPILER_PATH = pathlib.Path("compiler/nx/aarch64/bin/clang++.exe")
OBJDUMP_PATH = pathlib.Path("compiler/nx/aarch64/bin/llvm-objdump.exe") OBJDUMP_PATH = pathlib.Path("compiler/nx/aarch64/bin/llvm-objdump.exe")
# if we don't have this file, create it # if we don't have this file, create it
@ -65,7 +65,7 @@ def genNinja(compile_tasks):
with open('build.ninja', 'w') as ninja_file: with open('build.ninja', 'w') as ninja_file:
ninja_writer = Writer(ninja_file) ninja_writer = Writer(ninja_file)
cmd = f'{COMPILER_PATH} {COMPILER_CMD} $in -o $out' cmd = f'{helpers.COMPILER_PATH} {COMPILER_CMD} $in -o $out'
if isNotWindows: if isNotWindows:
cmd = f'wine {cmd}' cmd = f'wine {cmd}'
ninja_writer.rule("compile", command=cmd, description='Compiling $in') ninja_writer.rule("compile", command=cmd, description='Compiling $in')

View File

@ -4,7 +4,7 @@ from capstone import *
from capstone.arm64 import * from capstone.arm64 import *
from elftools.elf.elffile import ELFFile from elftools.elf.elffile import ELFFile
import time import time
import hashlib import helpers
LIBRARIES = ["ActionLibrary", "agl", "eui", "nn", "sead"] LIBRARIES = ["ActionLibrary", "agl", "eui", "nn", "sead"]
@ -73,37 +73,6 @@ def genProgress():
print("Generating JSON...") print("Generating JSON...")
genJSON(prog_total, "decompiled", "decompiled", "blue") genJSON(prog_total, "decompiled", "decompiled", "blue")
def getModule(map, sym):
for root, dirs, files in os.walk(map):
for file in files:
if file.endswith(".map"):
map_path = os.path.join(root, file)
with open(map_path, "r") as f:
lines = f.readlines()
for line in lines:
fmt = line.replace("\n", "")
if fmt == sym:
# we found where our symbol lives!
# we just grab the source module
object_path = map_path.replace("map", "build", 1)
object_path = object_path.replace(".map", ".o")
return object_path
return ""
def getFunctionData(functionAddr, functionSize):
with open("fury.nso", "rb") as f:
data = f.read()
digest = hashlib.sha256(data).hexdigest().upper()
if digest != "80E48BC7BDF7AAA635E7B48C24F49C6A4D8AC19949FB1B9F66EADF2CFBA3BF85":
print("fury.nso is not valid")
sys.exit(1)
nso_file = nso.NSO(data)
return nso_file.getFunction(functionAddr, functionSize)
objs_to_check = [] objs_to_check = []
funcs_to_check = [] funcs_to_check = []
@ -146,11 +115,11 @@ if "-no-diff" in sys.argv:
for sym in funcs_to_check: for sym in funcs_to_check:
print(f"{Fore.BLUE}{sym}{Style.RESET_ALL} =================================================") print(f"{Fore.BLUE}{sym}{Style.RESET_ALL} =================================================")
# first let's see if our symbol even exists somewhere # first let's see if our symbol even exists somewhere
path = getModule("map", sym) path = helpers.getModule("map", sym)
if path == "": if path == "":
for lib in LIBRARIES: for lib in LIBRARIES:
path = getModule(f"lib/{lib}/map", sym) path = helpers.getModule(f"lib/{lib}/map", sym)
if path != "": if path != "":
break break
@ -159,25 +128,8 @@ for sym in funcs_to_check:
print("Unable to find symbol.") print("Unable to find symbol.")
sys.exit(1) sys.exit(1)
functionSize = 0 functionSize, functionAddr = helpers.getFunctionSizeAndAddr(sym)
functionAddr = 0 funcData = helpers.getFunctionData(functionAddr, functionSize)
with open("data/main.map", "r") as f:
lines = f.readlines()
for line in lines:
spl = line.split("=")
name = spl[0]
addr = spl[1]
addr = int(addr[10:], 16)
size = int(spl[2], 16)
if sym == name:
functionSize = size
functionAddr = addr
break
funcData = getFunctionData(functionAddr, functionSize)
capstone_inst = Cs(CS_ARCH_ARM64, CS_MODE_ARM + CS_MODE_LITTLE_ENDIAN) capstone_inst = Cs(CS_ARCH_ARM64, CS_MODE_ARM + CS_MODE_LITTLE_ENDIAN)
capstone_inst.detail = True capstone_inst.detail = True
capstone_inst.imm_unsigned = False capstone_inst.imm_unsigned = False

View File

@ -13,37 +13,7 @@ import urllib.request
import urllib.parse import urllib.parse
from typing import Dict from typing import Dict
import json import json
import helpers
def getModule(map, sym):
for root, dirs, files in os.walk(map):
for file in files:
if file.endswith(".map"):
map_path = os.path.join(root, file)
with open(map_path, "r") as f:
lines = f.readlines()
for line in lines:
fmt = line.replace("\n", "")
if fmt == sym:
# we found where our symbol lives!
# we just grab the source module
object_path = map_path.replace("map", "build", 1)
object_path = object_path.replace(".map", ".o")
return object_path
return ""
def getFunctionData(functionAddr, functionSize):
with open("fury.nso", "rb") as f:
data = f.read()
digest = hashlib.sha256(data).hexdigest().upper()
if digest != "80E48BC7BDF7AAA635E7B48C24F49C6A4D8AC19949FB1B9F66EADF2CFBA3BF85":
print("fury.nso is not valid")
sys.exit(1)
nso_file = nso.NSO(data)
return nso_file.getFunction(functionAddr, functionSize)
INCLUDE_DIRS = [ INCLUDE_DIRS = [
"include", "include",
@ -57,7 +27,6 @@ INCLUDE_DIRS = [
LIBRARIES = ["ActionLibrary", "agl", "eui", "nn", "sead"] LIBRARIES = ["ActionLibrary", "agl", "eui", "nn", "sead"]
incdirs = " ".join([f'-I {dir}' for dir in INCLUDE_DIRS]) incdirs = " ".join([f'-I {dir}' for dir in INCLUDE_DIRS])
COMPILER_PATH = pathlib.Path("compiler/nx/aarch64/bin/clang++.exe")
PREPROC_CMD = f"-C -E {incdirs}" PREPROC_CMD = f"-C -E {incdirs}"
COMPILER_CMD = f"-x c++ -O3 -fno-omit-frame-pointer -mno-implicit-float -fno-cxx-exceptions -fno-strict-aliasing -std=gnu++14 -fno-common -fno-short-enums -ffunction-sections -fdata-sections -fPIC -mcpu=cortex-a57+fp+simd+crypto+crc -g -Wall -c" COMPILER_CMD = f"-x c++ -O3 -fno-omit-frame-pointer -mno-implicit-float -fno-cxx-exceptions -fno-strict-aliasing -std=gnu++14 -fno-common -fno-short-enums -ffunction-sections -fdata-sections -fPIC -mcpu=cortex-a57+fp+simd+crypto+crc -g -Wall -c"
@ -72,11 +41,11 @@ isTest = False
if "-test" in sys.argv: if "-test" in sys.argv:
isTest = True isTest = True
path = getModule("map", sym) path = helpers.getModule("map", sym)
if path == "": if path == "":
for lib in LIBRARIES: for lib in LIBRARIES:
path = getModule(f"lib/{lib}/map", sym) path = helpers.getModule(f"lib/{lib}/map", sym)
if path != "": if path != "":
break break
@ -87,7 +56,7 @@ if path == "":
source_path = path.replace("build", "source") source_path = path.replace("build", "source")
source_path = source_path.replace(".o", ".cpp") source_path = source_path.replace(".o", ".cpp")
preproc_cmd = [COMPILER_PATH, "-E"] + incdirs.split() + [source_path] preproc_cmd = [helpers.COMPILER_PATH, "-E"] + incdirs.split() + [source_path]
procOut = subprocess.check_output(preproc_cmd).decode("utf-8").replace("\r", "") procOut = subprocess.check_output(preproc_cmd).decode("utf-8").replace("\r", "")
procOut_Clean = "" procOut_Clean = ""
@ -98,25 +67,8 @@ for line in procOut.split("\n"):
procOut_Clean += f"{line}\n" procOut_Clean += f"{line}\n"
functionSize = 0 functionSize, functionAddr = helpers.getFunctionSizeAndAddr(sym)
functionAddr = 0 funcData = helpers.getFunctionData(functionAddr, functionSize)
with open("data/main.map", "r") as f:
lines = f.readlines()
for line in lines:
spl = line.split("=")
name = spl[0]
addr = spl[1]
addr = int(addr[10:], 16)
size = int(spl[2], 16)
if sym == name:
functionSize = size
functionAddr = addr
break
funcData = getFunctionData(functionAddr, functionSize)
capstone_inst = Cs(CS_ARCH_ARM64, CS_MODE_ARM + CS_MODE_LITTLE_ENDIAN) capstone_inst = Cs(CS_ARCH_ARM64, CS_MODE_ARM + CS_MODE_LITTLE_ENDIAN)
capstone_inst.detail = True capstone_inst.detail = True
capstone_inst.imm_unsigned = False capstone_inst.imm_unsigned = False

61
helpers.py Normal file
View File

@ -0,0 +1,61 @@
import nso
import os
import hashlib
import sys
import pathlib
COMPILER_PATH = pathlib.Path("compiler/nx/aarch64/bin/clang++.exe")
# gets the "module" (object file) that a symbol is contained in from map files
def getModule(map, sym):
for root, dirs, files in os.walk(map):
for file in files:
if file.endswith(".map"):
map_path = os.path.join(root, file)
with open(map_path, "r") as f:
lines = f.readlines()
for line in lines:
fmt = line.replace("\n", "")
if fmt == sym:
# we found where our symbol lives!
# we just grab the source module
object_path = map_path.replace("map", "build", 1)
object_path = object_path.replace(".map", ".o")
return object_path
return ""
# gets bytes from a function with a defined address and size from an NSO file
def getFunctionData(functionAddr, functionSize):
with open("fury.nso", "rb") as f:
data = f.read()
digest = hashlib.sha256(data).hexdigest().upper()
if digest != "80E48BC7BDF7AAA635E7B48C24F49C6A4D8AC19949FB1B9F66EADF2CFBA3BF85":
print("fury.nso is not valid")
sys.exit(1)
nso_file = nso.NSO(data)
return nso_file.getFunction(functionAddr, functionSize)
def getFunctionSizeAndAddr(sym):
functionSize = 0
functionAddr = 0
with open("data/main.map", "r") as f:
lines = f.readlines()
for line in lines:
spl = line.split("=")
name = spl[0]
addr = spl[1]
addr = int(addr[10:], 16)
size = int(spl[2], 16)
if sym == name:
functionSize = size
functionAddr = addr
break
return functionSize, functionAddr