"""Name functions in the stripped VREND.MNG by matching relocation-invariant signatures harvested from the DPL3 VRENDER .O object files. For each .O .text function we mask (wildcard) every 32-bit word that a COFF relocation touches -- those hold call targets / data addresses that the linker rewrites -- and keep the fixed opcode+register skeleton. A function that carried over into VREND.MNG (even relocated to a new address) still matches its skeleton. Word granularity throughout (i860 is fixed 4-byte, word-aligned).""" import sys, struct, os, glob def parse_coff(path): d = open(path, 'rb').read() magic, nscns, timdat, symptr, nsyms, opthdr, flags = struct.unpack_from(' len(text): continue good = 0 for i in concrete: if struct.unpack_from(' best[1]: second = best[1]; best = (start*4, frac) elif frac > second: second = frac if best[0] is not None and best[1] >= thresh: return (best[0], best[1], best[1] > second + 0.05) return None def main(): mng = sys.argv[1] if len(sys.argv) > 1 else r'C:\VWE\TeslaRel410\sda4\RPLIVE\VREND.MNG' odir = r'C:\VWE\TeslaRel410\sda4\DPL3\VRENDER' text, tsize = load_mng_text(mng) idx = build_index(text) print(f"VREND.MNG .text = {tsize:#x} bytes ({tsize//4} words); {os.path.basename(mng)}") named = {} # addr -> (name, frac) nsig = 0 for opath in sorted(glob.glob(os.path.join(odir, '*.O')) + glob.glob(os.path.join(odir, 'PXPL5SUP', '*.O'))): for nm, skel in sig_for_functions(opath): nsig += 1 r = match(skel, text, idx) if r is None: continue addr, frac, uniq = r if not uniq: nm = nm + "?" if addr not in named or frac > named[addr][1]: named[addr] = (nm, frac) strong = sum(1 for (n, f) in named.values() if f >= 0.95) print(f"signatures tried={nsig}, named={len(named)} " f"(exact/near-exact >=0.95: {strong})") for addr in sorted(named): nm, frac = named[addr] print(f" text+{addr:#08x} (mem {0x0c+addr:#08x}) {frac:0.2f} {nm}") if __name__ == '__main__': main()