#!/usr/bin/env python3 """Annotate ghidra/decomp.c: resolve absolute VAs (0x180........) to IL2CPP symbol names (methods.tsv) and string literals (strings.tsv). Ghidra image base = 0x180000000. methods.tsv : \t (rva = scriptAddress - 0x1000) strings.tsv : \t (raw ScriptString.Address) Usage: venv/bin/python reverse/resolve_decomp.py # writes ghidra/decomp.annotated.c venv/bin/python reverse/resolve_decomp.py # print only funcs whose name matches substr """ import re, sys, os ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) G = os.path.join(ROOT, "ghidra") BASE = 0x180000000 def load_methods(): m = {} for l in open(os.path.join(G, "methods.tsv")): if "\t" in l: rva, name = l.rstrip("\n").split("\t", 1) m[int(rva)] = name return m def load_strings(): s = {} p = os.path.join(G, "strings.tsv") if os.path.exists(p): for l in open(p): if "\t" in l: a, v = l.rstrip("\n").split("\t", 1) s[int(a)] = v return s def main(): methods = load_methods() strings = load_strings() src = open(os.path.join(G, "decomp.c"), encoding="utf-8", errors="replace").read() hexre = re.compile(r"0x(1[0-9a-fA-F]{8,9})") def repl(m): va = int(m.group(1), 16) rva = va - BASE if rva in methods: return "%s/*%s*/" % (m.group(0), methods[rva]) # string literal: try raw rva, rva+0x1000 (scriptAddress), and the table conventions for cand in (rva, rva + 0x1000, va, va - BASE + 0x1000): if cand in strings: return '%s/*"%s"*/' % (m.group(0), strings[cand][:60]) return m.group(0) out = hexre.sub(repl, src) outp = os.path.join(G, "decomp.annotated.c") open(outp, "w", encoding="utf-8").write(out) nres = out.count("/*") print("wrote %s (%d annotations)" % (outp, nres)) if len(sys.argv) > 1: sub = sys.argv[1] blocks = re.split(r"(?=// ==== )", out) for b in blocks: if sub.lower() in b[:200].lower(): print(b) if __name__ == "__main__": main()