gen_addresses: per-lane fragment dir; duplicate names are a hard error
This commit is contained in:
parent
0d84eb2d4c
commit
9834b3d175
2 changed files with 33 additions and 1 deletions
18
ghidra/addresses.d/README.md
Normal file
18
ghidra/addresses.d/README.md
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
# Per-lane address fragments
|
||||||
|
|
||||||
|
`addresses.json` is a single shared file. When several lanes run concurrently they edit the
|
||||||
|
same lines, and three times on 2026-09-08 one lane's `git add` swept another's in-flight
|
||||||
|
entries into the wrong commit. Nothing was lost, but authorship and atomicity were.
|
||||||
|
|
||||||
|
A lane may instead drop its own file here:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{ "entries": [ { "name": "...", "addr": "0x...", "convention": "...",
|
||||||
|
"prototype": "...", "status": "verified", "source": "findings/..." } ] }
|
||||||
|
```
|
||||||
|
|
||||||
|
Name it after the lane (`lane-d.json`). `tools/gen_addresses.py` merges every fragment in
|
||||||
|
sorted order after `addresses.json`. A **duplicate name across files is a hard error**, not
|
||||||
|
last-wins — two lanes disagreeing about an address is exactly the thing we must not paper over.
|
||||||
|
|
||||||
|
The integrator folds fragments back into `addresses.json` once the lane's work is merged.
|
||||||
|
|
@ -1,10 +1,24 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""Emit include/generated/sots_addresses.h for sots-engine from ghidra/addresses.json.
|
"""Emit include/generated/sots_addresses.h for sots-engine from ghidra/addresses.json.
|
||||||
Only facts (name, RVA, convention, prototype, status) — never decompiler text."""
|
Only facts (name, RVA, convention, prototype, status) — never decompiler text."""
|
||||||
import json, os, subprocess, sys, datetime
|
import glob, json, os, subprocess, sys, datetime
|
||||||
root = os.path.join(os.path.dirname(__file__), "..")
|
root = os.path.join(os.path.dirname(__file__), "..")
|
||||||
j = json.load(open(os.path.join(root, "ghidra", "addresses.json")))
|
j = json.load(open(os.path.join(root, "ghidra", "addresses.json")))
|
||||||
base = int(j["image_base"], 16)
|
base = int(j["image_base"], 16)
|
||||||
|
|
||||||
|
# Per-lane fragments. addresses.json is a single shared file, so concurrent lanes kept
|
||||||
|
# sweeping each other's in-flight entries into the wrong commit. A lane may instead write
|
||||||
|
# ghidra/addresses.d/<lane>.json ({"entries": [...]}) — its own file, no shared-line edits.
|
||||||
|
# Fragments are merged here in sorted order; a duplicate name is an error, not a silent
|
||||||
|
# last-wins, because two lanes disagreeing about an address is exactly what we must not paper over.
|
||||||
|
seen = {e["name"]: "addresses.json" for e in j["entries"]}
|
||||||
|
for frag_path in sorted(glob.glob(os.path.join(root, "ghidra", "addresses.d", "*.json"))):
|
||||||
|
frag_name = os.path.basename(frag_path)
|
||||||
|
for e in json.load(open(frag_path))["entries"]:
|
||||||
|
if e["name"] in seen:
|
||||||
|
sys.exit(f"duplicate address entry {e['name']!r}: in {seen[e['name']]} and {frag_name}")
|
||||||
|
seen[e["name"]] = frag_name
|
||||||
|
j["entries"].append(e)
|
||||||
try: rev = subprocess.check_output(["git","-C",root,"rev-parse","--short","HEAD"]).decode().strip()
|
try: rev = subprocess.check_output(["git","-C",root,"rev-parse","--short","HEAD"]).decode().strip()
|
||||||
except Exception: rev = "unknown"
|
except Exception: rev = "unknown"
|
||||||
out = [ "// GENERATED — do not edit. Facts about Sword of the Stars.exe (GOG 1.8.1).",
|
out = [ "// GENERATED — do not edit. Facts about Sword of the Stars.exe (GOG 1.8.1).",
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue