71 lines
4.6 KiB
Java
71 lines
4.6 KiB
Java
package rea.extensions.nativeaot;
|
|
|
|
import com.google.gson.JsonArray;
|
|
import com.google.gson.JsonNull;
|
|
import com.google.gson.JsonObject;
|
|
import ghidra.program.model.data.DataType;
|
|
import ghidra.program.model.listing.Program;
|
|
import ghidra.util.task.TaskMonitor;
|
|
import nativeaot.objectmodel.MethodTable;
|
|
import nativeaot.objectmodel.MethodTableManager;
|
|
|
|
/** Translate a selected recovered type into provider-neutral metadata evidence. */
|
|
final class NativeAotTypeMetadata {
|
|
static JsonObject describe(Program program, MethodTableManager manager, NativeAotDirectory.Located located,
|
|
DataType type, JsonObject report, JsonObject derivedRange, TaskMonitor monitor) throws Exception {
|
|
for (MethodTable table : manager.getMethodTables()) {
|
|
monitor.checkCancelled();
|
|
boolean sameType = type.getPathName().equals(table.getMTType().getPathName()) ||
|
|
(table.getInstanceType() != null && type.getPathName().equals(table.getInstanceType().getPathName()));
|
|
if (!sameType) continue;
|
|
JsonObject result = new JsonObject();
|
|
result.addProperty("format", "dotnet-nativeaot");
|
|
result.addProperty("status", report.get("status").getAsString());
|
|
result.addProperty("header_address", NativeAotExtension.address(located.address()));
|
|
result.addProperty("format_major", located.directory().getMajorVersion());
|
|
result.addProperty("format_minor", located.directory().getMinorVersion());
|
|
result.addProperty("method_table_address", NativeAotExtension.address(table.getAddress()));
|
|
result.addProperty("name_origin", table == manager.getObjectMT() || table == manager.getStringMT() ? "inferred" : "generated");
|
|
result.add("original_name", JsonNull.INSTANCE);
|
|
result.addProperty("base_size_bytes", table.getBaseSize());
|
|
result.add("related_type", identity(manager, table.getRelatedTypeAddress()));
|
|
JsonArray interfaces = new JsonArray();
|
|
for (long value : table.getInterfaceAddresses()) if (value != 0) interfaces.add(identity(manager, value));
|
|
result.add("interfaces", interfaces);
|
|
JsonArray slots = new JsonArray();
|
|
for (int slot = 0; slot < table.getVTableSlotCount(); slot++) {
|
|
monitor.checkCancelled();
|
|
long value = table.getVTableSlot(slot);
|
|
JsonObject target = new JsonObject();
|
|
target.addProperty("slot", slot);
|
|
target.addProperty("slot_address", NativeAotExtension.address(table.getAddress().add(24 + slot * 8L)));
|
|
target.add("target_address", value == 0 ? JsonNull.INSTANCE : new com.google.gson.JsonPrimitive("0x" + Long.toUnsignedString(value, 16)));
|
|
var function = value == 0 ? null : program.getFunctionManager().getFunctionAt(table.getAddress().getNewAddress(value));
|
|
target.add("procedure_name", function == null ? JsonNull.INSTANCE : new com.google.gson.JsonPrimitive(function.getName(true)));
|
|
target.addProperty("basis", "method-table-pointer");
|
|
slots.add(target);
|
|
}
|
|
result.add("virtual_slots", slots);
|
|
result.add("derived_memory", derivedRange.deepCopy());
|
|
result.add("diagnostics", report.get("diagnostics").deepCopy());
|
|
JsonArray limitations = new JsonArray();
|
|
limitations.add("Type identities and relationships are recovered by upstream heuristics. Original source names and custom field layouts are not recovered.");
|
|
limitations.add("Method prototypes are inferred, not original signatures. REA preserves pre-recovery calling conventions and the loaded compiler default for new functions.");
|
|
limitations.add("Rehydrated metadata bytes are derived analysis-memory content; their original file offsets and runtime behavior remain unknown.");
|
|
limitations.add("Verified workflow: .NET 8.0.22 NativeAOT RTR 9.1, Linux x64 ELF / Windows x64 PE on Linux; other runtime layouts and hosts are unverified.");
|
|
result.add("limitations", limitations);
|
|
return result;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
private static com.google.gson.JsonElement identity(MethodTableManager manager, long value) throws Exception {
|
|
if (value == 0) return JsonNull.INSTANCE;
|
|
JsonObject result = new JsonObject();
|
|
result.addProperty("address", "0x" + Long.toUnsignedString(value, 16));
|
|
MethodTable table = manager.getMethodTable(value);
|
|
result.add("type", table == null ? JsonNull.INSTANCE : new com.google.gson.JsonPrimitive(table.getMTType().getPathName()));
|
|
return result;
|
|
}
|
|
}
|