mirror of
https://codeberg.org/KeybadeBlox/JSRF-Decompilation.git
synced 2026-02-20 02:07:02 +03:00
Add data type import for Ghidra
This commit is contained in:
parent
30f8a5879e
commit
63002e0f08
9 changed files with 233 additions and 31 deletions
1
ghidra/.gitignore
vendored
Normal file
1
ghidra/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
jsrf.h
|
||||
115
ghidra/headerconvert.awk
Normal file
115
ghidra/headerconvert.awk
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
# awk script to convert C++ header files into valid C for Ghidra
|
||||
# This script naturally isn't 100% robust, but so long as the header files
|
||||
# stay simple without the formatting getting too weird, this works fairly well.
|
||||
|
||||
function fn_ptr(cls, signature, ret, fname, args) {
|
||||
# Convert the given method signature to a function pointer
|
||||
if ($1 ~ /^~/) # Special case for virtual destructor
|
||||
return "\t\t" cls " * __attribute__((thiscall)) "\
|
||||
"(*scalar_deleting_destructor)("\
|
||||
cls " *, "\
|
||||
"BOOL"\
|
||||
");\n"
|
||||
else {
|
||||
ret = signature
|
||||
sub(/[a-zA-Z_][a-zA-Z_0-9]+\(.*/, "", ret)
|
||||
|
||||
fname = substr(signature, length(ret)+1)
|
||||
sub(/\(.*/, "", fname)
|
||||
|
||||
args = signature
|
||||
sub(/.*\(/ , "(" cls " *, ", args) # Add "this" pointer
|
||||
sub(/,[ \t]\)/, ")" , args) # Remove trailing ','
|
||||
|
||||
return ret "__attribute__((thiscall)) (*" fname ")" args "\n"
|
||||
}
|
||||
}
|
||||
|
||||
# Exclude lines with no code
|
||||
NF == 0 || $1 ~ /^\/\// { next }
|
||||
|
||||
# Include preprocessor directives, except some unneeded ones
|
||||
$1 ~ /^#/ && !($1 ~ /^#(if|endif|include)/) && !/_HPP$/
|
||||
|
||||
# Include typedefs
|
||||
/^typedef/
|
||||
|
||||
# Make enums and unions typedef'd
|
||||
/^(enum|union)/,/^\}/ {
|
||||
# Pull name from first line and prefix with "typedef"
|
||||
if (/^(enum|union)/) {
|
||||
name = $2
|
||||
printf("typedef %s\n", $0)
|
||||
next
|
||||
}
|
||||
|
||||
if (!/^\}/) print # Print body unchanged
|
||||
else printf("} %s;\n\n", name) # Add name to complete typedef
|
||||
}
|
||||
|
||||
# The main event: turn classes and structs into typedef'd C structs
|
||||
# This means turning parent classes into members and defining vtable members
|
||||
# pointing to structs of appropriately-typed function pointers.
|
||||
/^(class|struct)/,/^\}/ {
|
||||
# Initialize some data describing struct
|
||||
if (/^(class|struct)/) {
|
||||
name = $2
|
||||
parent = $3 == ":" ? $4 : ""
|
||||
body = ""
|
||||
vtable = ""
|
||||
|
||||
next
|
||||
}
|
||||
|
||||
# Read struct members
|
||||
if (/\(/) { # Method start
|
||||
in_method = 1
|
||||
|
||||
if ($1 == "virtual") { # Record virtual method for vtable
|
||||
sub(/virtual[ \t]+/, "")
|
||||
method = "\t" $0
|
||||
}
|
||||
}
|
||||
|
||||
if (/\)/) { # Method end
|
||||
if (method) { # Add method to vtable
|
||||
if (!/\(/) { # Add line if not added already
|
||||
sub(/^[ \t]+/, "")
|
||||
method = method $0
|
||||
}
|
||||
|
||||
vtable = vtable fn_ptr(name, method)
|
||||
}
|
||||
|
||||
in_method = 0
|
||||
method = ""
|
||||
next
|
||||
}
|
||||
|
||||
if (in_method) { # Method arguments
|
||||
# Add line if not added already and method is virtual
|
||||
if (method && !/\(/) {
|
||||
sub(/^[ \t]+/, "")
|
||||
method = method $0
|
||||
}
|
||||
|
||||
next
|
||||
}
|
||||
|
||||
if (!/^\}/) body = body $0 "\n" # Add to body
|
||||
else { # Reached end; output struct
|
||||
# Add parent as first member, if there is one
|
||||
if (parent) printf("typedef struct %s {\n\t%s super;\n", name, parent)
|
||||
else printf("typedef struct %s {\n" , name )
|
||||
|
||||
# Add vtable as first member, if there is one
|
||||
# We assume that if a class has virtual methods and a parent,
|
||||
# the parent already has a vtable, and we don't handle the case
|
||||
# of a derived class having virtual methods not on its parent.
|
||||
if (vtable && !parent) {
|
||||
printf("\tstruct %sVtbl {\n%s\t} * vtable;\n", name, vtable)
|
||||
}
|
||||
|
||||
printf("%s} %s;\n\n", body, name)
|
||||
}
|
||||
}
|
||||
22
ghidra/make_header.sh
Executable file
22
ghidra/make_header.sh
Executable file
|
|
@ -0,0 +1,22 @@
|
|||
#!/bin/sh -eu
|
||||
# Merges all header files in the decompilation into a C header file called
|
||||
# jsrf.h for importing into Ghidra
|
||||
|
||||
# Create output file
|
||||
printf '%s\n' '// Automatically generated mass header file for Ghidra' > jsrf.h
|
||||
|
||||
# Figuring out include order programmatically is awful, so we'll have to add
|
||||
# all the headers here by hand in an order that functions properly
|
||||
HEADERS="
|
||||
Std.hpp
|
||||
XDK/Win32.hpp
|
||||
XDK/D3D.hpp
|
||||
Smilebit/MMatrix.hpp
|
||||
JSRF/Core.hpp
|
||||
JSRF/GameData.hpp
|
||||
"
|
||||
|
||||
# Process each header file into jsrf.h
|
||||
for header in $HEADERS; do
|
||||
awk -f headerconvert.awk "../decompile/src/$header" >> jsrf.h
|
||||
done
|
||||
50
ghidra/make_symboltable.sh
Executable file
50
ghidra/make_symboltable.sh
Executable file
|
|
@ -0,0 +1,50 @@
|
|||
#!/bin/sh -eu
|
||||
# Script to convert Ghidra symbol table CSV export data to the format used by
|
||||
# the Ghidra script ImportSymbolsScript.py
|
||||
|
||||
main() {
|
||||
if [ $# -ne 1 ]; then usage; fi
|
||||
|
||||
printf 'Writing symbol table to symboltable.tsv...'
|
||||
|
||||
>symboltable.tsv # Create/truncate output file
|
||||
|
||||
while IFS=, read -r location namespace name type; do # Iterate rows
|
||||
# Determine symbol type (skip if unrecognized, e.g. header row)
|
||||
if [ "$type" = '"Function"' ]; then type_out=f
|
||||
elif [ "$type" = '"Data Label"' ]; then type_out=l
|
||||
else continue
|
||||
fi
|
||||
|
||||
# Add namespace prefix if not in global namespace
|
||||
if [ "$namespace" = '"Global"' ]; then namespace_out=
|
||||
else
|
||||
namespace_out=${namespace#'"'}
|
||||
namespace_out=${namespace_out%'"'}::
|
||||
fi
|
||||
|
||||
# Strip quotes from other columns
|
||||
name_out=${name#'"'} ; name_out=${name_out%'"'}
|
||||
location_out=${location#'"'}; location_out=${location_out%'"'}
|
||||
|
||||
# Output row
|
||||
printf '%s\t%s\t%s\n'\
|
||||
"$namespace_out$name_out" "$location_out" "$type_out"\
|
||||
>> symboltable.tsv
|
||||
done < $1
|
||||
|
||||
printf ' done.\n'
|
||||
}
|
||||
|
||||
usage() {
|
||||
printf '%s\n'\
|
||||
'Usage: make_symboltable.sh CSVFILE'\
|
||||
' CSVFILE is the path of a symbol table CSV from Ghidra'\
|
||||
''\
|
||||
'The CSV file should have columns Name, Location, and Type. The output file'\
|
||||
'will be named "symboltable.tsv".' >&2
|
||||
exit 2
|
||||
}
|
||||
|
||||
|
||||
main "$@"
|
||||
1252
ghidra/symboltable.tsv
Normal file
1252
ghidra/symboltable.tsv
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue