mirror of
https://codeberg.org/KeybadeBlox/JSRF-Decompilation.git
synced 2026-02-20 10:17:03 +03:00
Miscellaneous name mangling improvements
Improved error reporting, skipping undesirable symbols like jump tables, skipping special symbols like intrinsics, etc.
This commit is contained in:
parent
78127e64ef
commit
d372c17094
1 changed files with 66 additions and 39 deletions
|
|
@ -107,7 +107,10 @@ public class MSVC7Mangle extends GhidraScript{
|
||||||
final Reference[] refs = ins.getReferencesFrom();
|
final Reference[] refs = ins.getReferencesFrom();
|
||||||
for (int i = 0; i < refs.length; i++) {
|
for (int i = 0; i < refs.length; i++) {
|
||||||
final Symbol symbol = getSymbolAt(refs[i].getToAddress());
|
final Symbol symbol = getSymbolAt(refs[i].getToAddress());
|
||||||
if (symbol != null) mangle(symbol);
|
if ( // Guard against spurious references to nonexisting things
|
||||||
|
symbol != null &&
|
||||||
|
symbol.getObject() != null
|
||||||
|
) mangle(symbol);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -116,13 +119,17 @@ public class MSVC7Mangle extends GhidraScript{
|
||||||
|
|
||||||
private void mangle(final Symbol s) throws Exception {
|
private void mangle(final Symbol s) throws Exception {
|
||||||
/* Set the given symbol's name to its mangled version */
|
/* Set the given symbol's name to its mangled version */
|
||||||
// Skip if already mangled
|
// Skip if already mangled; skip jump tables
|
||||||
if (s.getName().charAt(0) == '?') return;
|
final String name = s.getName(true);
|
||||||
|
if (
|
||||||
|
name.charAt(0) == '?' ||
|
||||||
|
name.startsWith("switchD_")
|
||||||
|
) return;
|
||||||
|
|
||||||
// Get mangled name
|
// Get mangled name
|
||||||
final String mangled = switch (s.getObject()) {
|
final String mangled = switch (s.getObject()) {
|
||||||
case Function f -> mangleFn (f);
|
case Function f -> mangleFn (f);
|
||||||
case Data d -> mangleData(d, s.getName(true));
|
case Data d -> mangleData(d, name);
|
||||||
default -> null;
|
default -> null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -145,17 +152,21 @@ public class MSVC7Mangle extends GhidraScript{
|
||||||
|
|
||||||
private String mangleFn(final Function f) throws Exception {
|
private String mangleFn(final Function f) throws Exception {
|
||||||
/* Generate a mangled name for a function */
|
/* Generate a mangled name for a function */
|
||||||
// Special cases for main()
|
final String nameRaw = f.getName(true);
|
||||||
if (f.getName(true).equals("main" )) return "_main";
|
|
||||||
if (f.getName(true).equals("___CxxFrameHandler")) return "___CxxFrameHandler";
|
// Special case for main()
|
||||||
|
if (nameRaw.equals("main")) return "_main";
|
||||||
|
|
||||||
|
// Special symbols like intrinsics aren't mangled
|
||||||
|
if (nameRaw.startsWith("__")) return nameRaw;
|
||||||
|
|
||||||
final ArrayList<String> dict = new ArrayList<>();
|
final ArrayList<String> dict = new ArrayList<>();
|
||||||
|
|
||||||
final List<String> nameParts = Arrays.asList(f.getName(true).split("::"));
|
final List<String> nameParts = Arrays.asList(nameRaw.split("::"));
|
||||||
Collections.reverse(nameParts);
|
Collections.reverse(nameParts);
|
||||||
final boolean isMethod = f.getCallingConventionName().equals("__thiscall") &&
|
final boolean isMethod = f.getCallingConventionName().equals("__thiscall") &&
|
||||||
nameParts.size() >= 2;
|
nameParts.size() >= 2;
|
||||||
final String name = mangleIdentifier(f.getName(true), isMethod, f.getReturnType(), dict);
|
final String name = mangleIdentifier(nameRaw, isMethod, f.getReturnType(), dict);
|
||||||
|
|
||||||
// Special methods with unique formats
|
// Special methods with unique formats
|
||||||
if (isMethod) {
|
if (isMethod) {
|
||||||
|
|
@ -163,14 +174,16 @@ public class MSVC7Mangle extends GhidraScript{
|
||||||
final String clsName = nameParts.get(1);
|
final String clsName = nameParts.get(1);
|
||||||
|
|
||||||
if (unqualified.equals( clsName)) { // Constructor
|
if (unqualified.equals( clsName)) { // Constructor
|
||||||
return "?" + name + "QAE@" + mangleArgs(f.getSignature(true), dict) + "Z";
|
return "?" + name + "QAE@" +
|
||||||
|
mangleArgs(f.getSignature(true), dict, nameRaw + "()") +
|
||||||
|
"Z";
|
||||||
} else if (unqualified.equals("~" + clsName)) { // Destructor
|
} else if (unqualified.equals("~" + clsName)) { // Destructor
|
||||||
return "?" + name + (isVirtual(f) ? "UAE" : "QAE") + "@XZ";
|
return "?" + name + (isVirtual(f) ? "UAE" : "QAE") + "@XZ";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return "?" + name + mangleFnAttrs(f, nameParts) +
|
return "?" + name + mangleFnAttrs(f, nameParts) +
|
||||||
mangleFnType(f.getSignature(true), dict);
|
mangleFnType(f.getSignature(true), dict, nameRaw + "()");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String mangleIdentifier(
|
private static String mangleIdentifier(
|
||||||
|
|
@ -272,7 +285,9 @@ public class MSVC7Mangle extends GhidraScript{
|
||||||
final List<T> dict
|
final List<T> dict
|
||||||
) {
|
) {
|
||||||
/* Produce a backreference string if x is found in dict */
|
/* Produce a backreference string if x is found in dict */
|
||||||
switch (Integer.valueOf(dict.indexOf(x))) {
|
if (x instanceof String s && s.startsWith("?"))
|
||||||
|
return Optional.empty(); // No matching special names
|
||||||
|
else switch (Integer.valueOf(dict.indexOf(x))) {
|
||||||
case -1:
|
case -1:
|
||||||
dict.add(x);
|
dict.add(x);
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
|
|
@ -303,12 +318,15 @@ public class MSVC7Mangle extends GhidraScript{
|
||||||
final Function func = getFunctionContaining(refs[i].getFromAddress());
|
final Function func = getFunctionContaining(refs[i].getFromAddress());
|
||||||
|
|
||||||
if (data != null) {
|
if (data != null) {
|
||||||
final String name = getSymbolAt(data.getRoot()
|
final Symbol s = getSymbolAt(data.getRoot()
|
||||||
.getAddress()).getName(false);
|
.getAddress());
|
||||||
|
if (s != null) {
|
||||||
|
final String name = s.getName(false);
|
||||||
if (
|
if (
|
||||||
name.equals("`vftable'") ||
|
name.equals("`vftable'") ||
|
||||||
name.startsWith("??_7")
|
name.startsWith("??_7")
|
||||||
) return true;
|
) return true;
|
||||||
|
}
|
||||||
} else if (func != null) {
|
} else if (func != null) {
|
||||||
final String name = func.getName(false);
|
final String name = func.getName(false);
|
||||||
if (
|
if (
|
||||||
|
|
@ -334,12 +352,13 @@ public class MSVC7Mangle extends GhidraScript{
|
||||||
|
|
||||||
private static String mangleFnType(
|
private static String mangleFnType(
|
||||||
final FunctionSignature f,
|
final FunctionSignature f,
|
||||||
final List<String> dict
|
final List<String> dict,
|
||||||
|
final String loc
|
||||||
) throws Exception {
|
) throws Exception {
|
||||||
/* Mangle everything in f but its name and visibility/linkage */
|
/* Mangle everything in f but its name and visibility/linkage */
|
||||||
|
return mangleCallC(f) +
|
||||||
return mangleCallC(f) + mangleType(f.getReturnType(), dict) +
|
mangleType(f.getReturnType(), dict, loc) +
|
||||||
mangleArgs(f, dict) + "Z";
|
mangleArgs(f, dict, loc) + "Z";
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String mangleCallC(final FunctionSignature f) throws Exception {
|
private static String mangleCallC(final FunctionSignature f) throws Exception {
|
||||||
|
|
@ -358,15 +377,16 @@ public class MSVC7Mangle extends GhidraScript{
|
||||||
|
|
||||||
private static String mangleType(
|
private static String mangleType(
|
||||||
final DataType t,
|
final DataType t,
|
||||||
final List<String> dict
|
final List<String> dict,
|
||||||
|
final String loc
|
||||||
) throws Exception {
|
) throws Exception {
|
||||||
/* Mangle a data type in a function name
|
/* Mangle a data type in a function name
|
||||||
All types are assumed to have no CV qualifiers.
|
All types are assumed to have no CV qualifiers.
|
||||||
*/
|
*/
|
||||||
if (t == null) throw new Exception (
|
if (t == null) throw new Exception (
|
||||||
"A data type was reported as null. Ensure that all " +
|
"A data type at " + loc + " was reported as null. " +
|
||||||
"data types in the code/data to mangle have been " +
|
"Ensure that all data types in the code/data to " +
|
||||||
"defined."
|
"mangle have been defined."
|
||||||
);
|
);
|
||||||
|
|
||||||
return switch(t) {
|
return switch(t) {
|
||||||
|
|
@ -384,7 +404,7 @@ public class MSVC7Mangle extends GhidraScript{
|
||||||
case LongDoubleDataType _ -> "O";
|
case LongDoubleDataType _ -> "O";
|
||||||
case Pointer p -> "P" +
|
case Pointer p -> "P" +
|
||||||
(p.getDataType() instanceof FunctionSignature ? "6" : "A") +
|
(p.getDataType() instanceof FunctionSignature ? "6" : "A") +
|
||||||
mangleType(p.getDataType(), dict);
|
mangleType(p.getDataType(), dict, loc);
|
||||||
case Union u -> "T" + mangleIdentifier(u.getName(), false, null, dict);
|
case Union u -> "T" + mangleIdentifier(u.getName(), false, null, dict);
|
||||||
case Structure s -> "U" + mangleIdentifier(s.getName(), false, null, dict);
|
case Structure s -> "U" + mangleIdentifier(s.getName(), false, null, dict);
|
||||||
case Enum e -> "W4" + mangleIdentifier(e.getName(), false, null, dict);
|
case Enum e -> "W4" + mangleIdentifier(e.getName(), false, null, dict);
|
||||||
|
|
@ -393,12 +413,12 @@ public class MSVC7Mangle extends GhidraScript{
|
||||||
case UnsignedLongLongDataType _ -> "_K";
|
case UnsignedLongLongDataType _ -> "_K";
|
||||||
case BooleanDataType _ -> "_N";
|
case BooleanDataType _ -> "_N";
|
||||||
case WideCharDataType _ -> "_W";
|
case WideCharDataType _ -> "_W";
|
||||||
case Array a -> "PA" + mangleArrDims(a) + mangleType(arrType(a), dict);
|
case Array a -> "PA" + mangleArrDims(a) + mangleType(arrType(a), dict, loc);
|
||||||
case FunctionSignature f -> mangleFnType(f, dict);
|
case FunctionSignature f -> mangleFnType(f, dict, "function typedef \"" + f.getName() + "\"");
|
||||||
case TypeDef d -> mangleType(d.getBaseDataType(), dict);
|
case TypeDef d -> mangleType(d.getBaseDataType(), dict, "typedef \"" + d.getName() + "\"");
|
||||||
case DefaultDataType _ -> throw new Exception ("Encountered data marked \"undefined\". Ensure that all data types in the code/data to mangle have been defined.");
|
case DefaultDataType _ -> throw new Exception ("Encountered data marked \"undefined\" at " + loc + ". Ensure that all data types in the code/data to mangle have been defined.");
|
||||||
case Undefined _ -> throw new Exception ("Encountered data marked \"undefined\". Ensure that all data types in the code/data to mangle have been defined.");
|
case Undefined _ -> throw new Exception ("Encountered data marked \"undefined\" at " + loc + ". Ensure that all data types in the code/data to mangle have been defined.");
|
||||||
default -> throw new Exception ("Unknown type \"" + t.getClass().getName() + "\"");
|
default -> throw new Exception ("Unknown type \"" + t.getClass().getName() + "\" at " + loc);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -446,7 +466,8 @@ public class MSVC7Mangle extends GhidraScript{
|
||||||
|
|
||||||
private static String mangleArgs(
|
private static String mangleArgs(
|
||||||
final FunctionSignature f,
|
final FunctionSignature f,
|
||||||
final List<String> dict
|
final List<String> dict,
|
||||||
|
final String loc
|
||||||
) throws Exception {
|
) throws Exception {
|
||||||
/* Mangle the arguments for a function */
|
/* Mangle the arguments for a function */
|
||||||
final DataType[] args = Arrays.stream(f.getArguments())
|
final DataType[] args = Arrays.stream(f.getArguments())
|
||||||
|
|
@ -469,10 +490,15 @@ public class MSVC7Mangle extends GhidraScript{
|
||||||
// It turns out that academic-sounding stuff everyone
|
// It turns out that academic-sounding stuff everyone
|
||||||
// freaks out at is actually useful (and Optional still
|
// freaks out at is actually useful (and Optional still
|
||||||
// helped us out here)
|
// helped us out here)
|
||||||
String mangled = "";
|
String mangledArgs = "";
|
||||||
for (int i = 0; i < args.length; i++)
|
for (int i = 0; i < args.length; i++) {
|
||||||
mangled += backref(args[i], argDict).orElse(mangleType(args[i], dict));
|
final String mangledArg = mangleType(args[i], dict, loc);
|
||||||
return mangled + (f.hasVarArgs() ? "Z" : "@");
|
|
||||||
|
mangledArgs += mangledArg.length() == 1 ?
|
||||||
|
mangledArg :
|
||||||
|
backref(args[i], argDict).orElse(mangledArg);
|
||||||
|
}
|
||||||
|
return mangledArgs + (f.hasVarArgs() ? "Z" : "@");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -495,7 +521,8 @@ public class MSVC7Mangle extends GhidraScript{
|
||||||
// vtable
|
// vtable
|
||||||
if (ident.startsWith("?_7")) return "?" + ident + "6B@";
|
if (ident.startsWith("?_7")) return "?" + ident + "6B@";
|
||||||
|
|
||||||
return "?" + ident + "3" + mangleType(d.getDataType(), dict) +
|
return "?" + ident + "3" +
|
||||||
|
mangleType(d.getDataType(), dict, "0x" + d.getAddress().toString()) +
|
||||||
"A";
|
"A";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue