Fixup _0_0_ like access

This commit is contained in:
Guus Waals 2024-09-20 18:48:03 +08:00
parent 88d10a9a2e
commit a4b12ba2f4
3 changed files with 564 additions and 485 deletions

View File

@ -6,4 +6,30 @@
#include "gh_structs.h"
#include "gh_global.h"
template<size_t Offset, size_t Size>
struct Field {
};
template<size_t Size>
struct _FieldBinderSizeTraits {
using type = undefined;
};
template<>
struct _FieldBinderSizeTraits<4> {
using type = undefined4;
};
template<>
struct _FieldBinderSizeTraits<2> {
using type = undefined2;
};
template<>
struct _FieldBinderSizeTraits<3> {
using type = undefined3;
};
template<size_t Offset, size_t Size>
inline uint32_t& operator+(const char* str, Field<Offset, Size> offset) {
return *(_FieldBinderSizeTraits<Size>*)(str + offset);
}
#endif /* B8D59B54_1674_4C0F_AA2C_611385FF5D03 */

View File

@ -1,14 +1,26 @@
#ifndef A523F6DB_0645_4DEB_8AEB_3792CB732B49
#define A523F6DB_0645_4DEB_8AEB_3792CB732B49
#if _WIN32
#include <Windows.h>
#else
#include "../win32_shim.h"
#include <unistd.h>
#include <sys/proc.h>
#endif
#include <stdint.h>
#include <stdio.h>
#include <string.h>
// Fallback to int if type is not annotated
// typedef int64_t undefined;
typedef uint32_t undefined4;
typedef uint16_t undefined2;
struct undefined3 {
uint8_t _0;
uint8_t _1;
uint8_t _2;
};
typedef unsigned char byte;
typedef byte undefined1;
// typedef uint64_t uint;

View File

@ -10,10 +10,14 @@ import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.Arrays;
import java.util.Dictionary;
import ghidra.app.decompiler.ClangFieldToken;
import ghidra.app.decompiler.ClangLine;
import ghidra.app.decompiler.ClangSyntaxToken;
import ghidra.app.decompiler.ClangToken;
import ghidra.app.decompiler.DecompileResults;
import ghidra.app.decompiler.PrettyPrinter;
@ -24,7 +28,6 @@ import ghidra.program.model.data.BitFieldDataType;
import ghidra.program.model.data.DataType;
import ghidra.program.model.data.DataTypeComponent;
import ghidra.program.model.data.DataTypeManager;
import re3lib.DataTypeWriter;
import ghidra.program.model.data.PointerDataType;
import ghidra.program.model.data.ProgramBasedDataTypeManager;
import ghidra.program.model.data.Structure;
@ -76,7 +79,8 @@ public class Decompile extends GhidraScript {
if (comment != null && comment.contains("Library Function")) {
println("Adding library function " + function.getName() + " to blacklist");
println("ac:" + functionAddrBlackList.size() + " jj:"
+ functionAddrBlackList.contains(function.getEntryPoint()) + " " + function.getEntryPoint());
+ functionAddrBlackList.contains(function.getEntryPoint()) + " "
+ function.getEntryPoint());
isIgnoredFunction = true;
}
@ -141,6 +145,8 @@ public class Decompile extends GhidraScript {
}
};
static final Pattern fieldAccessRegex = Pattern.compile("^_([0-9]+)_([0-9]+)_$");
void decompileFunction(Hashtable<String, GlobalRec> outGlobalSymbols, Function function)
throws Exception {
String fileName = sanitizeFunctionName(function.getName()) + ".cxx";
@ -182,8 +188,50 @@ public class Decompile extends GhidraScript {
for (int i = 0; i < line.getIndent(); i++) {
codeWriter.write(' ');
}
for (int t = 0; t < line.getNumTokens(); t++) {
ClangToken token = line.getToken(t);
List<ClangToken> tokens = new ArrayList<>();
// Parse preliminary line tokens
for (int i = 0; i < line.getNumTokens(); i++) {
ClangToken token = line.getToken(i);
if (!token.getText().isEmpty())
tokens.add(token);
}
// Preprocess tokens
boolean prevDot = false;
for (int t = 0; t < tokens.size(); t++) {
ClangToken token = tokens.get(t);
boolean thisDot = false;
// println("Token: " + token.toString());
if (token.toString().equals(".")) {
// println("Found dot: " + token.toString() + " - " + token.getClass());
thisDot = true;
}
if (prevDot) {
// println("Possible field access: " + token.getText());
if (token instanceof ClangSyntaxToken) {
// Parse _4_4_ sub-access using regex
String text = token.getText();
Matcher matcher = fieldAccessRegex.matcher(text);
if (matcher.matches()) {
int offset = Integer.parseInt(matcher.group(1));
int size = Integer.parseInt(matcher.group(2));
// println("MATCHED: " + token.getText() + " - " + token.getSyntaxType() + " - " + token.getVarnode() + " - "
// + token.getPcodeOp());
// Replace tokens with + Field<offset, size>
ClangToken replacement = new ClangToken(token.Parent(), " + Field<" + offset + ", " + size + ">()");
tokens.remove(t);
tokens.remove(t - 1);
tokens.add(t - 1, replacement);
t--;
}
}
}
// Extract memory references
HighSymbol gsym = token.getHighSymbol(highFunction);
if (gsym != null) {
var symStorage = gsym.getStorage();
@ -197,27 +245,11 @@ public class Decompile extends GhidraScript {
}
if (address.isMemoryAddress()) {
// println("Memory: " + token.toString() + " - " + gsym.getName() + " - " +
// address);
// boolean defined = address.isConstantAddress();
// Symbol symAtAddr = getSymbolAt(address);
// if (defined && symAtAddr != null) {
// } else {
// // println("NOT FULLY DEFINED: " + address + " - " + symAtAddr);
// // defined = false;
// }
outGlobalSymbols.put(gsym.getName(), new GlobalRec(gsym, address));
} else {
// println("Unknown: " + token.toString() + " - " + gsym.getName() + " - " +
// address);
}
}
// println("CONST: " + token.toString() + " - " + gsym.getName());
// println(
// "Token: " + token.toString() + " - " + gsym.getName() + " - " +
// symStorage.getSerializationString());
}
// Extract external function calls
PcodeOp op = token.getPcodeOp();
if (op != null && op.getOpcode() == PcodeOp.CALL) {
// println("PcodeOp: " + op.toString() + " - " + op.getInput(0).toString());
@ -230,11 +262,18 @@ public class Decompile extends GhidraScript {
// println("Adding header: " + calledFunction + " / " +
// calledFunction.getSignature().getPrototypeString(true));
headers.add("extern " + calledFunction.getSignature().getPrototypeString(true)
+ "; // " + calledFunction.getEntryPoint() + " // " + calledFunction.getName());
+ "; // " + calledFunction.getEntryPoint() + " // "
+ calledFunction.getName());
}
}
}
}
prevDot = thisDot;
}
// Print tokens
for (int t = 0; t < tokens.size(); t++) {
ClangToken token = tokens.get(t);
codeWriter.write(token.toString());
}
codeWriter.write('\n');
@ -387,7 +426,8 @@ public class Decompile extends GhidraScript {
if (dt instanceof Structure || dt instanceof TypedefDataType) {
if (typeBlacklist.contains(dt.getDisplayName()))
continue;
println("Adding: " + dt.getDisplayName() + " - " + dt.getClass().getSimpleName());
// println("Adding: " + dt.getDisplayName() + " - " +
// dt.getClass().getSimpleName());
filteredTypes.add(dt);
}
@ -399,7 +439,8 @@ public class Decompile extends GhidraScript {
// }
}
try (PrintWriter writer = new PrintWriter(new File(RecompileConfig.INSTANCE.outputDir, "gh_structs.h"), "UTF-8")) {
try (PrintWriter writer = new PrintWriter(new File(RecompileConfig.INSTANCE.outputDir, "gh_structs.h"),
"UTF-8")) {
headerGuardPre(writer, "STRUCTS");
writer.println("// AUTO-GENERATED FILE ");
writer.println("#include <gh_struct_binder.h>");