Skip to content

Commit 010e6b3

Browse files
committed
Add missing scripts
1 parent 82b3f1e commit 010e6b3

2 files changed

Lines changed: 185 additions & 0 deletions

File tree

scripts/apply-symbol-mappings.py

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
#!/usr/bin/env python3
2+
"""Apply symbol_mappings from objdiff.json to symbols.txt, then remove them."""
3+
4+
import json
5+
import sys
6+
from pathlib import Path
7+
8+
ROOT = Path(__file__).resolve().parent.parent
9+
OBJDIFF_PATH = ROOT / "objdiff.json"
10+
SYMBOLS_PATH = ROOT / "config" / "GM8E01_00" / "symbols.txt"
11+
12+
13+
def main():
14+
with open(OBJDIFF_PATH, "r") as f:
15+
objdiff = json.load(f)
16+
17+
# Collect all mappings: old_name -> new_name
18+
mappings = {}
19+
units_with_mappings = []
20+
for unit in objdiff.get("units", []):
21+
sm = unit.get("symbol_mappings")
22+
if sm:
23+
units_with_mappings.append(unit["name"])
24+
for old, new in sm.items():
25+
if old in mappings and mappings[old] != new:
26+
print(
27+
f"WARNING: conflicting mapping for '{old}':\n"
28+
f" '{mappings[old]}' vs '{new}'",
29+
file=sys.stderr,
30+
)
31+
mappings[old] = new
32+
33+
if not mappings:
34+
print("No symbol_mappings found in objdiff.json.")
35+
return
36+
37+
print(f"Found {len(mappings)} mapping(s) in {len(units_with_mappings)} unit(s):")
38+
for name in units_with_mappings:
39+
print(f" {name}")
40+
41+
# Apply to symbols.txt
42+
with open(SYMBOLS_PATH, "r") as f:
43+
lines = f.readlines()
44+
45+
applied = set()
46+
new_lines = []
47+
for line in lines:
48+
replaced = False
49+
for old, new in mappings.items():
50+
prefix = old + " = "
51+
if line.startswith(prefix):
52+
new_lines.append(new + " = " + line[len(prefix):])
53+
applied.add(old)
54+
replaced = True
55+
break
56+
if not replaced:
57+
new_lines.append(line)
58+
59+
not_found = set(mappings.keys()) - applied
60+
if not_found:
61+
print(f"\nWARNING: {len(not_found)} mapping(s) not found in symbols.txt:",
62+
file=sys.stderr)
63+
for name in sorted(not_found):
64+
print(f" {name}", file=sys.stderr)
65+
66+
with open(SYMBOLS_PATH, "w") as f:
67+
f.writelines(new_lines)
68+
69+
print(f"\nApplied {len(applied)} rename(s) to {SYMBOLS_PATH.relative_to(ROOT)}")
70+
71+
# Remove symbol_mappings from objdiff.json
72+
for unit in objdiff.get("units", []):
73+
if unit.get("symbol_mappings"):
74+
unit["symbol_mappings"] = None
75+
76+
with open(OBJDIFF_PATH, "w") as f:
77+
json.dump(objdiff, f, indent=2)
78+
f.write("\n")
79+
80+
print(f"Cleared symbol_mappings from {OBJDIFF_PATH.relative_to(ROOT)}")
81+
82+
83+
if __name__ == "__main__":
84+
main()

scripts/function-order.py

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
#!/usr/bin/env python3
2+
3+
import re
4+
import subprocess
5+
import sys
6+
from pathlib import Path
7+
8+
ROOT = Path(__file__).resolve().parent.parent
9+
SPLITS = ROOT / "config/GM8E01_00/splits.txt"
10+
SYMBOLS = ROOT / "config/GM8E01_00/symbols.txt"
11+
DTK = ROOT / "build/tools/dtk"
12+
13+
14+
def find_text_range(tu_path):
15+
tu_header = f"{tu_path}:"
16+
in_tu = False
17+
start = None
18+
end = None
19+
20+
with SPLITS.open() as f:
21+
for raw_line in f:
22+
line = raw_line.rstrip("\n")
23+
if not line:
24+
continue
25+
26+
if not raw_line.startswith((" ", "\t")):
27+
in_tu = line == tu_header
28+
continue
29+
30+
if not in_tu:
31+
continue
32+
33+
match = re.match(r"\s*\.text\s+start:0x([0-9A-Fa-f]+)\s+end:0x([0-9A-Fa-f]+)", line)
34+
if match:
35+
start = int(match.group(1), 16)
36+
end = int(match.group(2), 16)
37+
break
38+
39+
if start is None or end is None:
40+
raise SystemExit(f"Failed to find .text range for TU: {tu_path}")
41+
42+
return start, end
43+
44+
45+
def find_symbols_in_range(start, end):
46+
out = []
47+
pattern = re.compile(
48+
r"^(?P<name>[^=\s]+)\s*=\s*\.text:0x(?P<addr>[0-9A-Fa-f]+);\s*//\s*(?P<meta>.*)$"
49+
)
50+
51+
with SYMBOLS.open() as f:
52+
for raw_line in f:
53+
line = raw_line.rstrip("\n")
54+
match = pattern.match(line)
55+
if not match:
56+
continue
57+
58+
meta = match.group("meta")
59+
if "type:function" not in meta:
60+
continue
61+
62+
addr = int(match.group("addr"), 16)
63+
if start <= addr < end:
64+
out.append((addr, match.group("name")))
65+
66+
out.sort()
67+
out.reverse()
68+
return out
69+
70+
71+
def demangle(symbol):
72+
try:
73+
result = subprocess.run(
74+
[str(DTK), "demangle", symbol],
75+
check=True,
76+
capture_output=True,
77+
text=True,
78+
cwd=ROOT,
79+
)
80+
except FileNotFoundError:
81+
raise SystemExit(f"Missing demangler: {DTK}")
82+
except subprocess.CalledProcessError:
83+
return symbol
84+
85+
return result.stdout.strip() or symbol
86+
87+
88+
def main():
89+
if len(sys.argv) != 2:
90+
raise SystemExit(f"Usage: {Path(sys.argv[0]).name} <TU path>")
91+
92+
tu_path = sys.argv[1]
93+
start, end = find_text_range(tu_path)
94+
symbols = find_symbols_in_range(start, end)
95+
96+
for _, symbol in symbols:
97+
print(demangle(symbol))
98+
99+
100+
if __name__ == "__main__":
101+
main()

0 commit comments

Comments
 (0)