# 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 void * __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) } }