// Decode the track-row builder: the function that maps a djmdContent record into // the on-disk DeviceSQL row (offset 0x02 index_shift, 0x14 u4 hash, 0x18/0x1a u2). // Decompiles FUN_141c04be0 (AnalysisDataPath/SearchStr/MasterContentID mapper) and // FUN_141ae4860 (djmdContent), plus scans for code referencing the constant // 0x21b4a7ab / 0xa7ab and for `<<5` row-index assignment. // Output -> ~/ghidra_proj/decrow.txt import java.io.PrintWriter; import java.util.*; import ghidra.app.script.GhidraScript; import ghidra.app.decompiler.*; import ghidra.program.model.address.*; import ghidra.program.model.listing.*; import ghidra.program.model.scalar.Scalar; import ghidra.program.model.lang.OperandType; public class DecRow extends GhidraScript { PrintWriter out; DecompInterface di; Set done = new HashSet<>(); FunctionManager fm; void dec(String a, String why) { Function f = fm.getFunctionContaining(currentProgram.getAddressFactory().getAddress(a)); if (f == null) { out.println("// no function at " + a + " (" + why + ")"); return; } if (!done.add(f.getEntryPoint().toString())) return; out.println("\n//===== " + f.getName() + " @ " + f.getEntryPoint() + " [" + why + "] ====="); DecompileResults r = di.decompileFunction(f, 90, monitor); out.println(r != null && r.decompileCompleted() ? r.getDecompiledFunction().getC() : "// decompile failed"); } @Override public void run() throws Exception { out = new PrintWriter("/home/ntr/ghidra_proj/decrow.txt"); di = new DecompInterface(); di.openProgram(currentProgram); fm = currentProgram.getFunctionManager(); dec("0x141c04be0", "AnalysisDataPath/SearchStr/MasterContentID mapper"); dec("0x141c07230", "SearchStr 2"); dec("0x141c076d0", "SearchStr 3"); dec("0x141ae4860", "djmdContent xrefs"); // Scan all instructions for the per-export constants used in 0x18/0x1a // (0xa7ab=42923, 0x21b4=8628, combined u4 0x21b4a7ab=565353387) and for // an immediate 0x20 / shift-by-5 pattern that would build index_shift. long[] consts = {0xa7abL, 0x21b4L, 0x21b4a7abL, 0xa7ab21b4L}; Set hitFns = new LinkedHashSet<>(); Listing lst = currentProgram.getListing(); InstructionIterator it = lst.getInstructions(true); int scanned = 0; while (it.hasNext() && !monitor.isCancelled()) { Instruction ins = it.next(); scanned++; for (int op = 0; op < ins.getNumOperands(); op++) { Object[] objs = ins.getOpObjects(op); for (Object o : objs) { if (o instanceof Scalar) { long v = ((Scalar) o).getUnsignedValue(); for (long c : consts) { if (v == c) { Function f = fm.getFunctionContaining(ins.getAddress()); String tag = "const 0x" + Long.toHexString(c) + " @" + ins.getAddress() + " in " + (f != null ? f.getName() + "@" + f.getEntryPoint() : "?") + " : " + ins.toString(); out.println("// SCAN " + tag); if (f != null) hitFns.add(f.getEntryPoint().toString() + "|const0x" + Long.toHexString(c)); } } } } } } out.println("// scanned " + scanned + " instructions"); for (String h : hitFns) { String[] parts = h.split("\\|"); dec("0x" + parts[0], parts[1]); } out.flush(); out.close(); println("wrote decrow.txt"); } }