reman3/scripts/RebuildFunctionDatabase.java

149 lines
5.5 KiB
Java

// @category _Reman3
// @menupath Reman3.Rebuild Function Database
import ghidra.app.script.GhidraScript;
import ghidra.program.model.address.Address;
import ghidra.program.model.data.DataType;
import ghidra.program.model.data.StandAloneDataTypeManager;
import re3lib.FunctionDatabase;
import re3lib.RecompileConfig;
import java.io.File;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import cparser.Parser;
import cparser.Tokenizer;
public class RebuildFunctionDatabase extends GhidraScript {
// Will rebuild all functions
public boolean rebuildAllGlobals = true;
FunctionDatabase functionDB;
@Override
public void run() throws Exception {
RecompileConfig.INSTANCE = new RecompileConfig(this);
functionDB = new FunctionDatabase(this);
scanFile(new File(RecompileConfig.INSTANCE.outputDir, "gh_auto/r3_engineLoop.cxx"), FunctionDatabase.Type.Auto);
// scanDirectory(RecompileConfig.INSTANCE.dirDecompAuto, FunctionDatabase.Type.Auto);
// scanDirectory(RecompileConfig.INSTANCE.dirDecompFix, FunctionDatabase.Type.Fix);
// scanDirectory(RecompileConfig.INSTANCE.dirDecompStub, FunctionDatabase.Type.Stub);
println("Applying default filters...");
functionDB.applyDefaultFilters(rebuildAllGlobals);
println("Saving function database...");
functionDB.save();
println("Function database rebuilt successfully.");
// for (FunctionDatabase.Entry entry : functionDB.entries) {
// println(entry.address + " " + entry.name + " " + entry.file.getName());
// for (FunctionDatabase.Dependency dependency : entry.dependencies) {
// println(" " + dependency.address + " " + dependency.name);
// }
// }
}
private void scanDirectory(File directory, FunctionDatabase.Type type) throws Exception {
File[] files = directory.listFiles((dir, name) -> name.endsWith(".cxx"));
if (files == null)
return;
for (File file : files) {
scanFile(file, type);
}
}
private void parseOld(BufferedReader reader, File file, FunctionDatabase.Type type) throws Exception {
String line;
Pattern dependencyPattern = Pattern.compile("(\\w+)\\s+(\\w+)\\(.*\\);\\s*//\\s*([0-9A-Fa-f]{8})\\s*//\\s*(.*)");
Pattern addressPattern = Pattern.compile("//\\s*([0-9A-Fa-f]{8})");
Pattern functionNamePattern = Pattern.compile("(\\S+)\\s+(\\S+)\\s*\\(");
List<FunctionDatabase.Dependency> dependencies = new ArrayList<>();
String address = null;
String functionName = null;
while ((line = reader.readLine()) != null) {
Matcher dependencyMatcher = dependencyPattern.matcher(line);
if (dependencyMatcher.find()) {
// println("Found dependency: " + dependencyMatcher.group(3));
Address depAddress = currentProgram.getAddressFactory().getAddress(dependencyMatcher.group(3));
String name = dependencyMatcher.group(2);
FunctionDatabase.Dependency dependency = functionDB.new Dependency(depAddress, name);
dependencies.add(dependency);
continue;
}
Matcher addressMatcher = addressPattern.matcher(line);
if (addressMatcher.find()) {
// println("Found address: " + addressMatcher.group(1));
address = addressMatcher.group(1);
// Skip any comments or newlines between address and function definition
while ((line = reader.readLine()) != null) {
line = line.trim();
// println("Line: " + line);
if (!line.isEmpty()) {
Matcher functionNameMatcher = functionNamePattern.matcher(line);
if (functionNameMatcher.find()) {
functionName = functionNameMatcher.group(2).trim();
break;
}
}
}
if (functionName != null) {
break;
}
}
}
if (address != null && functionName != null) {
Address functionAddress = currentProgram.getAddressFactory().getAddress(address);
FunctionDatabase.Entry entry = functionDB.new Entry();
entry.address = functionAddress;
entry.name = functionName;
entry.file = file;
entry.type = type;
entry.dependencies = dependencies;
functionDB.entries.add(entry);
} else {
// throw new Exception("Failed to parse function at " + file.getName());
println("Failed to parse function at " + file.getName());
}
}
private void scanFile(File file, FunctionDatabase.Type type) throws Exception {
println("Scanning " + file);
String text = new String(Files.readAllBytes(file.toPath()));
Tokenizer.TokenSet tokens = new Tokenizer(text).parse();
Parser parser = new Parser(tokens);
parser.parse();
// for (CTokenizer.Token token : tokens.getTokens()) {
// int line = tokens.getLine(token.ofs);
// println("Line " + line + ": " + token.ofs + " " + token.len + " " + token.type + " - "
// + tokens.getTextNoNewlines(token));
// }
for (Parser.Function function : parser.getFunctions()) {
println("Function: " + function.name + " " + function.startOffset + " " + function.endOffset);
}
for (Parser.FunctionCall functionCall : parser.getFunctionCalls()) {
println("FunctionCall: " + functionCall.name + " " + functionCall.startOffset + " " + functionCall.endOffset);
}
for (Parser.Variable variable : parser.getVariables()) {
println("Variable: " + variable.name + " " + variable.startOffset + " " + variable.endOffset);
}
}
}