diff options
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | tools/analyze_source/readelf.py | 92 |
2 files changed, 93 insertions, 1 deletions
@@ -132,7 +132,7 @@ MID_OBJS := $(patsubst $(MID_SUBDIR)/%.mid,$(MID_BUILDDIR)/%.o,$(MID_SRCS)) OBJS := $(C_OBJS) $(ASM_OBJS) $(DATA_ASM_OBJS) $(SONG_OBJS) $(MID_OBJS) OBJS_REL := $(patsubst $(OBJ_DIR)/%,%,$(OBJS)) -TOOLDIRS := $(filter-out tools/agbcc tools/binutils,$(wildcard tools/*)) +TOOLDIRS := $(filter-out tools/agbcc tools/binutils tools/analyze_source,$(wildcard tools/*)) TOOLBASE = $(TOOLDIRS:tools/%=%) TOOLS = $(foreach tool,$(TOOLBASE),tools/$(tool)/$(tool)$(EXE)) diff --git a/tools/analyze_source/readelf.py b/tools/analyze_source/readelf.py new file mode 100644 index 000000000..0e36777b4 --- /dev/null +++ b/tools/analyze_source/readelf.py @@ -0,0 +1,92 @@ +import re +import subprocess +from collections import namedtuple +import sys +import os +import argparse + +class SymInfo: + __slots__ = ("value", "scope", "debug", "type", "section", "name", "size") + def __init__(self, *sym_list, **kwargs): + self.value = sym_list[0] + self.scope = sym_list[1] + self.debug = sym_list[2] + self.type = sym_list[3] + self.section = sym_list[4] + self.size = sym_list[5] + self.name = sym_list[6] + +sym_line_regex = re.compile(r"^([0-9a-f]{8}) (.).{4}(.)(.) ([^\t]+)\t([0-9a-f]{8}) (\S+)$") + +def make_and_read_syms(): + nproc_value = subprocess.check_output(["nproc"]).decode("utf-8").strip() + subprocess.check_call(["make", "-j" + nproc_value]) + return read_syms() + +def read_syms(): + syms = [] + syms_small = set() + + print("Reading syms...") + + objdump_path = "./tools/binutils/bin/arm-none-eabi-objdump" + if 'win' in os.name: + output = subprocess.check_output([objdump_path + ".exe", "-t", "pokefirered.elf"]) + else: + output = subprocess.check_output([objdump_path, "-t", "pokefirered.elf"]) + + lines = output.splitlines()[4:] + + for line in lines: + try: + sym_tuple = sym_line_regex.findall(line.decode("utf-8"))[0] + except IndexError: + break + + sym_list = list(sym_tuple) + sym_list[0] = int(sym_list[0], 16) + sym_list[5] = int(sym_list[5], 16) + + temp_small_sym = (sym_list[0], sym_list[5], sym_list[6]) + if temp_small_sym not in syms_small: + syms_small.add(temp_small_sym) + syms.append(SymInfo(*sym_list)) + + print("Done reading syms!") + return syms + +if __name__ == "__main__": + SIMPLE = True + ap = argparse.ArgumentParser() + ap.add_argument("-m", "--make", dest="make", action="store_true") + ap.add_argument("-p", "--path", dest="input_path") + args = ap.parse_args() + + if args.input_path is None and os.path.basename(os.getcwd()) == "analyze_source": + os.chdir("../..") + elif args.input_path is not None: + os.chdir(args.input_path) + + if args.make: + syms = make_and_read_syms() + else: + syms = read_syms() + + print("Size: %s" % sys.getsizeof(syms)) + sym_dump_output = "" + cfg_output = "" + highest_sym_value = 0 + sorted_syms = sorted(syms, key=lambda kv: kv.value) + for sym_info in sorted_syms: + if SIMPLE: + sym_dump_output += f"{sym_info.value:08x} {sym_info.name} (size: 0x{sym_info.size:x})\n" + else: + sym_dump_output += "{}: value={:08x}, size=0x{:x}, scope=\"{}\", debug=\"{}\", type=\"{}\", section=\"{}\"\n".format(sym_info.name, sym_info.value, sym_info.size, sym_info.scope, sym_info.debug, sym_info.type, sym_info.section) + if sym_info.type == "F" and sym_info.value >= 0x8000000: + cfg_output += "{} 0x{:x} {}\n".format("thumb_func", sym_info.value, sym_info.name) + + with open("pokefirered_syms.dump", "w+") as f: + f.write(sym_dump_output) + + #with open("bn6f.cfg", "w+") as f: + # f.write(cfg_output) |