mirror of
https://codeberg.org/KeybadeBlox/JSRF-Decompilation.git
synced 2026-02-20 10:17:03 +03:00
115 lines
3 KiB
Awk
115 lines
3 KiB
Awk
# 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)
|
|
}
|
|
}
|