Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update swift_demangler.py #5

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 72 additions & 18 deletions swift_demangler.py
Original file line number Diff line number Diff line change
@@ -1,33 +1,35 @@
# Demangle swift function names
#@author Thomas Roth
#@author Thomas Roth & Or Dagmi
#@category Ghidra Ninja.Swift
#@keybinding
#@menupath
#@toolbar

import subprocess

from ghidra.program.model.symbol import SourceType
from ghidra.program.model.listing import CodeUnit
import java.lang

functionManager = currentProgram.getFunctionManager()

# Get functions in ascending order
fns = functionManager.getFunctions(True)
for f in fns:
f_name = f.getName()
# Is it a mangled name?
if not f_name.startswith("_$"):
continue
OS = java.lang.System.getProperty("os.name").lower()
IS_WINDOWS = OS.startswith("windows")


previous_comment = f.getComment()
if not previous_comment:
previous_comment = ""
def execute_swift(params):
exec_parameters = ["swift"] + params
if IS_WINDOWS:
cmd_line = ' '.join(exec_parameters)
# Since the $ symbol is reserved for accessing environment variables, we need to escape it.
# To make it work we actually need to escape it with 3 backsapces, and since we need to also
# escape the '\' in python, we need 6 escapes in total.
cmd_line = cmd_line.replace('$', '\\\\\\$')
exec_parameters = ["bash", "-c", cmd_line]
return subprocess.check_output(exec_parameters)

signature_full = subprocess.check_output(["swift", "demangle", "-compact", f_name])[:-1]
signature = signature_full

def demangle(name):
signature_full = execute_swift(["demangle", "-compact", name])[:-1]
signature = signature_full

# Check if it's one of those strange verbose names like:
# generic specialization <Any> of Swift._allocateUninitializedArray<A>(Builtin.Word) -> ([A], Builtin.RawPointer)
Expand All @@ -37,7 +39,7 @@
# We basically just check whether there is more than 1 space in the function name
func_description = signature.split("(")[0]
if func_description.count(" ") > 1:
signature = subprocess.check_output(["swift", "demangle", "-compact", "-simplified", f_name])[:-1]
signature = execute_swift(["demangle", "-compact", "-simplified", name])[:-1]

# Replace characters we can't have in our name
signature = signature.split("(")[0]
Expand All @@ -47,6 +49,58 @@
lines = len(signature_full) / 58
for l in range(1, lines+1):
signature_full = signature_full[:(l*58)+(l-1)] + "\n" + signature_full[(l*58)+(l-1):]

return (signature_full, signature)


def is_mangled_name(name):
if name.startswith('_$'):
return True

if name.startswith('_T'):
return True

return False

def demangle_functions():
functionManager = currentProgram.getFunctionManager()

# Get functions in ascending order
fns = functionManager.getFunctions(True)
for f in fns:
try:
f_name = f.getName()
# Is it a mangled name?
if not is_mangled_name(f_name):
continue

previous_comment = f.getComment()
if not previous_comment:
previous_comment = ""

signature_full, signature = demangle(f_name)

f.setComment(previous_comment + "\n" + signature_full)
f.setName(signature, SourceType.ANALYSIS)
except:
print("WARNING: could not change function name for: %s" % f_name)


def demangle_symbols():
symbolTable = currentProgram.getSymbolTable()
for s in symbolTable.getAllSymbols(True):
try:
s_name = s.getName()

if not is_mangled_name(s_name):
continue

demangled_name = demangle(s_name)[1]
if demangled_name != '':
s.setName(demangled_name, SourceType.ANALYSIS)
except:
print("WARNING: could not change symbol name for: %s" % s_name)


f.setComment(previous_comment + "\n" + signature_full)
f.setName(signature, SourceType.ANALYSIS)
demangle_functions()
demangle_symbols()