From a9efc2e5c59160116626e9f64f854f5138b83036 Mon Sep 17 00:00:00 2001 From: KeelrLeek <156356974+KeelrLeek@users.noreply.github.com> Date: Mon, 5 Oct 2026 15:16:04 -0500 Subject: [PATCH] re_lookup shows the original source file (Xbox file/line sites) and the Mac build's original name --- harbor/reverse.py | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/harbor/reverse.py b/harbor/reverse.py index 176ebbb..9e59969 100644 --- a/harbor/reverse.py +++ b/harbor/reverse.py @@ -40,6 +40,8 @@ class Reverse: self.annotations = Path(config["annotations"]) if config.get("annotations") else None self.src = Path(config["src"]) if config.get("src") else None self.conventions_path = Path(config["conventions"]) if config.get("conventions") else None + self.source_files = Path(config["source_files"]) if config.get("source_files") else None + self.mac_names = Path(config["mac_names"]) if config.get("mac_names") else None self._cache = {} # ----------------------------------------------------------------- loading (cached by file mtime) @@ -183,6 +185,32 @@ class Reverse: return {"summary": module.describe(result), "registers_in": result["registers_in"], "ret_pops": result["ret_pops"]} + def _keyed_csv(self, key, path, column): + def load(p): + out = {} + if p: + for row in csv.DictReader(p.read_text(encoding="utf-8").splitlines()): + try: + out.setdefault(int(row[column], 16), row) + except (KeyError, ValueError): + pass + return out + return self._load(key, path, load) + + def origins(self, addr): + """What the other builds say about a function: its original source file (Xbox file/line sites) and its + original name with parameter types (the unstripped Mac build). Evidence, not truth.""" + out = {} + src = self._keyed_csv("source_files", self.source_files, "pc_address").get(addr) + if src: + out["source_file"] = {k: src.get(k) for k in ("source_file", "lines", "confidence", "xbox_address", + "evidence") if src.get(k)} + mac = self._keyed_csv("mac_names", self.mac_names, "pc_address").get(addr) + if mac: + out["mac_name"] = {k: mac.get(k) for k in ("demangled", "mac_symbol", "confidence", "evidence") + if mac.get(k)} + return out + # ----------------------------------------------------------------- tools def read(self, addr, count): data = self._bytes() @@ -289,6 +317,7 @@ class Reverse: conv = self.convention(func[0]) if conv: out["convention_from_bytes"] = conv + out.update(self.origins(func[0])) for table, key in (("names.csv", "names_row"), ("functions.csv", "functions_row"), ("globals.csv", "globals_row")): row = self._csv(table).get(addr) if row: