Files
ss/tools/ghidra_scripts/GhidraToDtkSymbols.py
T
robojumper fe1c06e056 Import Ghidra symbols (#41)
* Import Ghidra symbols, main dol edition

* Ghidra symbols, RELs edition
2024-09-28 12:25:18 -04:00

127 lines
4.0 KiB
Python

#Export symbols from an organically grown Ghidra repository to a decomp-toolkit symbols.txt file
#@author robojumper
#@category GameCube/Wii
#@keybinding
#@menupath
#@toolbar
import os
import re
AF = currentProgram.getAddressFactory()
mem = currentProgram.getMemory()
listing = currentProgram.getListing()
sym_re = re.compile("(?:lbl|fn|FUN|DAT)_[0-9A-Fa-f_]+ = \.([a-z0-9]+):0x([0-9A-Fa-f]{8})(.*)\n")
default_sym_re = re.compile(".*_[0-9A-Za-z]+$")
used_symbols = set()
def transformer_for_file(file_name):
def transformer(section, address):
if file_name == "MAIN":
# in the main dol, each symbol is loaded at a fixed address
addr_obj = AF.getAddress("0x%08X" % address)
else:
# REL sections can't be reliably identified
if section != "text":
return None
# in rels, every section is relocated indivdually, so treat
# this as an offset
block_name = file_name + "_." + section + "0"
print(block_name)
block = mem.getBlock(block_name)
addr_obj = block.getStart().add(address)
symbol = getSymbolAt(addr_obj)
if symbol: #and symbol.getAddress().equals(addr_obj):
name = symbol.getName(True)
if default_sym_re.match(name):
return None
# in our Ghidra the RVL symbols are helpfully namespaced...
bad_prefixes = [
"ai::",
"arc::",
"axfx::",
"dvd::",
"exi::",
"gx::",
"kpad::",
"mem::",
"mtx::",
"nand::",
"os::",
"sc::",
"si::",
"tpl::",
"vi::",
"wenc::",
"wpad::",
"wud::",
]
lowercase_name = name.lower()
for prefix in bad_prefixes:
if lowercase_name.startswith(prefix):
name = name[len(prefix):]
break
name = name.replace("::", "__")
name = name.replace(":", "__")
name = name.replace("?", "Maybe")
name = name.replace("[", "_")
name = name.replace("]", "_")
name = name.replace("~", "_")
if name in used_symbols:
i = 2
while name + str(i) in used_symbols:
i += 1
name = name + str(i)
return name
return transformer
def transform_symbols_file(file, transformer):
new_file = ""
for line in file:
match = sym_re.match(line)
if match:
# whole match section address metadata
# print(match.group(0), match.group(1), match.group(2), match.group(3))
section = match.group(1)
addr_str = match.group(2)
metadata = match.group(3)
new_name = transformer(section, int(addr_str, 16))
if new_name:
used_symbols.add(new_name)
new_file += new_name + " = ." + section + ":0x" + match.group(2) + metadata + "\n"
continue
used_symbols.add(line.split("=")[0][:-1])
new_file += line
return new_file
path = str(askDirectory("Program config directory (e.g. config/SOUE01)", "Export"))
new_contents = None
main_symbols = os.path.join(path, "symbols.txt")
with open(main_symbols, "rt") as file:
new_contents = transform_symbols_file(file, transformer_for_file("MAIN"))
with open(main_symbols, 'w') as f:
f.write(new_contents)
rels_dir = os.path.join(path, "rels")
for rel_name in os.listdir(rels_dir):
if rel_name.endswith("NP"):
rel_symbols = os.path.join(rels_dir, rel_name, "symbols.txt")
with open(rel_symbols, "rt") as file:
new_contents = transform_symbols_file(file, transformer_for_file(rel_name))
with open(rel_symbols, 'w') as f:
f.write(new_contents)