diff options
Diffstat (limited to 'tools/ghidra/gsp-fwimage-570.144/scripts')
4 files changed, 478 insertions, 0 deletions
diff --git a/tools/ghidra/gsp-fwimage-570.144/scripts/BasicAnalysis.java b/tools/ghidra/gsp-fwimage-570.144/scripts/BasicAnalysis.java new file mode 100644 index 0000000..1776ea2 --- /dev/null +++ b/tools/ghidra/gsp-fwimage-570.144/scripts/BasicAnalysis.java @@ -0,0 +1,156 @@ +// Ghidra script to do basic disassembly analysis of GSP .fwimage binary +// Usage: analyzeHeadless ... -postScript BasicAnalysis.java + +import ghidra.app.script.GhidraScript; +import ghidra.program.model.listing.*; +import ghidra.program.model.mem.*; +import ghidra.program.model.symbol.*; +import ghidra.program.model.address.*; +import ghidra.util.task.TaskMonitor; +import java.io.*; +import java.util.*; +import java.nio.file.*; + +public class BasicAnalysis extends GhidraScript { + + @Override + protected void run() throws Exception { + Program program = getCurrentProgram(); + Listing listing = program.getListing(); + Memory memory = program.getMemory(); + FunctionManager functionManager = program.getFunctionManager(); + + println("=== GSP Firmware .fwimage Basic Analysis ==="); + println("Program: " + program.getName()); + println("Architecture: " + program.getLanguage().toString()); + + // Create output directory + String outputDir = "/home/rmcore/Git/integdev_gpu_drv/open-iov/firmware/570-GSP"; + Files.createDirectories(Paths.get(outputDir)); + + // 1. Check memory blocks + println("\n--- Memory Blocks ---"); + List<Map<String, Object>> memBlocks = new ArrayList<>(); + for (MemoryBlock block : memory.getBlocks()) { + Map<String, Object> blockInfo = new HashMap<>(); + blockInfo.put("name", block.getName()); + blockInfo.put("start", block.getStart().toString()); + blockInfo.put("end", block.getEnd().toString()); + blockInfo.put("size", block.getSize()); + blockInfo.put("execute", block.isExecute()); + blockInfo.put("read", block.isRead()); + blockInfo.put("write", block.isWrite()); + memBlocks.add(blockInfo); + println(" " + block.getName() + ": " + block.getStart() + " - " + block.getEnd() + + " (" + block.getSize() + " bytes) r=" + block.isRead() + " w=" + block.isWrite() + " x=" + block.isExecute()); + } + writeJson(outputDir + "/memory_blocks.json", memBlocks); + + // 2. Find all functions + println("\n--- Finding Functions ---"); + List<Map<String, Object>> functions = new ArrayList<>(); + FunctionIterator funcIter = functionManager.getFunctions(true); + int count = 0; + while (funcIter.hasNext()) { + Function func = funcIter.next(); + Map<String, Object> funcInfo = new HashMap<>(); + funcInfo.put("name", func.getName()); + funcInfo.put("entry", func.getEntryPoint().toString()); + funcInfo.put("size", func.getBody().getNumAddresses()); + functions.add(funcInfo); + count++; + if (count % 1000 == 0) { + println(" Found " + count + " functions..."); + } + } + println("Total functions: " + functions.size()); + writeJson(outputDir + "/functions.json", functions); + + // 3. Find strings + println("\n--- Finding Strings ---"); + List<Map<String, String>> strings = new ArrayList<>(); + DataIterator dataIter = listing.getDefinedData(true); + while (dataIter.hasNext()) { + Data data = dataIter.next(); + if (data.getDataType().getName().equals("string")) { + Object value = data.getValue(); + if (value != null && value.toString().length() > 4) { + Map<String, String> strInfo = new HashMap<>(); + strInfo.put("address", data.getAddress().toString()); + strInfo.put("value", value.toString()); + strings.add(strInfo); + } + } + } + println("Found " + strings.size() + " strings"); + + // Filter for interesting strings + String[] interestingKeywords = {"vgpu", "vmiop", "rpc", "hal", "bar", "migrate", "init", "boot", "kgsp", "wpr", "firmware", "version", "error", "fail", "assert", "panic", "nvidia", "rmapi", "gsp", "falcon", "mailbox", "interrupt", "dma", "iommu", "page", "mmu", "pde", "pte"}; + List<Map<String, String>> interestingStrings = new ArrayList<>(); + for (Map<String, String> s : strings) { + String val = s.get("value").toLowerCase(); + for (String kw : interestingKeywords) { + if (val.contains(kw)) { + interestingStrings.add(s); + break; + } + } + } + println("Interesting strings: " + interestingStrings.size()); + writeJson(outputDir + "/interesting_strings.json", interestingStrings); + + // 4. Find entry point + println("\n--- Entry Point Analysis ---"); + Address entryAddr = program.getMinAddress(); + println("Program entry (min address): " + entryAddr); + Function funcAtZero = functionManager.getFunctionAt(entryAddr); + if (funcAtZero != null) { + println("Function at entry: " + funcAtZero.getName()); + } else { + println("No function at entry point - creating one..."); + Function func = functionManager.createFunction("entry_point", entryAddr, null, null, monitor); + if (func != null) { + println("Created function: " + func.getName()); + } + } + + println("\n--- Analysis Complete ---"); + println("Results saved to " + outputDir); + } + + private void writeJson(String path, Object data) throws IOException { + StringBuilder json = new StringBuilder(); + json.append("[\n"); + if (data instanceof List) { + List<?> list = (List<?>) data; + for (int i = 0; i < list.size(); i++) { + Object item = list.get(i); + if (item instanceof Map) { + Map<?, ?> map = (Map<?, ?>) item; + json.append(" {"); + int j = 0; + for (Map.Entry<?, ?> entry : map.entrySet()) { + json.append("\"").append(entry.getKey()).append("\": "); + Object val = entry.getValue(); + if (val instanceof String) { + json.append("\"").append(escapeJson(val.toString())).append("\""); + } else { + json.append(val); + } + if (j < map.size() - 1) json.append(", "); + j++; + } + json.append("}"); + } + if (i < list.size() - 1) json.append(","); + json.append("\n"); + } + } + json.append("]"); + Files.writeString(Paths.get(path), json.toString()); + } + + private String escapeJson(String s) { + return s.replace("\\", "\\\\").replace("\"", "\\\"").replace("\n", "\\n").replace("\r", "\\r").replace("\t", "\\t"); + } +}
\ No newline at end of file diff --git a/tools/ghidra/gsp-fwimage-570.144/scripts/DecompileFunctions.java b/tools/ghidra/gsp-fwimage-570.144/scripts/DecompileFunctions.java new file mode 100644 index 0000000..da522cd --- /dev/null +++ b/tools/ghidra/gsp-fwimage-570.144/scripts/DecompileFunctions.java @@ -0,0 +1,88 @@ +import ghidra.app.script.GhidraScript; +import ghidra.program.model.address.Address; +import ghidra.program.model.listing.Function; +import ghidra.program.model.listing.FunctionManager; +import ghidra.app.decompiler.DecompInterface; +import ghidra.app.decompiler.DecompileResults; +import ghidra.util.task.TaskMonitor; +import java.io.File; +import java.io.FileWriter; +import java.io.PrintWriter; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +public class DecompileFunctions extends GhidraScript { + private static final String OUTPUT_DIR = "/home/rmcore/Git/integdev_gpu_drv/open-iov/firmware/570-GSP/decompiled/"; + + @Override + protected void run() throws Exception { + File outDir = new File(OUTPUT_DIR); + if (!outDir.exists()) { + outDir.mkdirs(); + } + + String[] args = getScriptArgs(); + if (args.length == 0) { + println("No addresses provided. Usage: <addr1>,<addr2>,..."); + return; + } + + Set<Address> targetAddresses = new HashSet<>(); + for (String arg : args) { + String[] addrs = arg.split(","); + for (String addrStr : addrs) { + addrStr = addrStr.trim(); + if (addrStr.startsWith("0x")) { + addrStr = addrStr.substring(2); + } + Address addr = toAddr(addrStr); + if (addr != null) { + targetAddresses.add(addr); + println("Target: " + addr); + } + } + } + + FunctionManager fm = currentProgram.getFunctionManager(); + DecompInterface decompiler = new DecompInterface(); + decompiler.openProgram(currentProgram); + + for (Address addr : targetAddresses) { + Function func = fm.getFunctionAt(addr); + if (func == null) { + println("No function at " + addr + ", creating..."); + func = createFunction(addr, null); + } + if (func != null) { + decompileAndSave(func, decompiler); + } else { + println("Failed to create function at " + addr); + } + } + + decompiler.dispose(); + } + + private void decompileAndSave(Function func, DecompInterface decompiler) throws Exception { + String name = func.getName(); + Address entry = func.getEntryPoint(); + String safeName = name.replaceAll("[^a-zA-Z0-9_]", "_"); + File outFile = new File(OUTPUT_DIR, safeName + "_" + entry.toString().replace(":", "_") + ".c"); + + DecompileResults results = decompiler.decompileFunction(func, 60, TaskMonitor.DUMMY); + if (results.decompileCompleted()) { + String code = results.getDecompiledFunction().getC(); + try (PrintWriter pw = new PrintWriter(new FileWriter(outFile))) { + pw.println("// Function: " + name); + pw.println("// Address: " + entry); + pw.println("// Size: " + func.getBody().getNumAddresses() + " bytes"); + pw.println(); + pw.print(code); + } + println("Decompiled: " + name + " @ " + entry + " -> " + outFile.getName()); + } else { + println("Decompilation failed for " + name + " @ " + entry + ": " + results.getErrorMessage()); + } + } +}
\ No newline at end of file diff --git a/tools/ghidra/gsp-fwimage-570.144/scripts/ExtractFunctions.java b/tools/ghidra/gsp-fwimage-570.144/scripts/ExtractFunctions.java new file mode 100644 index 0000000..2296a42 --- /dev/null +++ b/tools/ghidra/gsp-fwimage-570.144/scripts/ExtractFunctions.java @@ -0,0 +1,126 @@ +import ghidra.app.script.GhidraScript; +import ghidra.program.model.listing.FunctionManager; +import ghidra.program.model.listing.Function; +import ghidra.program.model.listing.FunctionIterator; +import ghidra.program.model.address.Address; +import ghidra.program.model.listing.Program; +import ghidra.program.model.mem.Memory; +import ghidra.program.model.mem.MemoryBlock; +import ghidra.util.task.TaskMonitor; +import java.io.FileWriter; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +public class ExtractFunctions extends GhidraScript { + + @Override + protected void run() throws Exception { + Program program = currentProgram; + FunctionManager functionManager = program.getFunctionManager(); + Memory memory = program.getMemory(); + + String outputDir = "/home/rmcore/Git/integdev_gpu_drv/open-iov/firmware/570-GSP"; + + // 1. Extract memory blocks + List<MemoryBlockInfo> memBlocks = new ArrayList<>(); + for (MemoryBlock block : memory.getBlocks()) { + memBlocks.add(new MemoryBlockInfo( + block.getName(), + block.getStart().toString(), + block.getEnd().toString(), + block.getSize(), + block.isExecute(), + block.isRead(), + block.isWrite() + )); + } + writeJson(outputDir + "/memory_blocks.json", memBlocks); + + // 2. Extract all functions (analysis must have run first) + List<FunctionInfo> functions = new ArrayList<>(); + FunctionIterator funcIter = functionManager.getFunctions(true); + while (funcIter.hasNext()) { + Function func = funcIter.next(); + functions.add(new FunctionInfo( + func.getName(), + func.getEntryPoint().toString(), + func.getBody().getNumAddresses() + )); + } + writeJson(outputDir + "/functions.json", functions); + + // 3. Extract interesting strings + String[] keywords = {"vgpu", "vmiop", "rpc", "hal", "bar", "migrate", "init", "boot", "kgsp", "wpr", "firmware", "version", "error", "fail", "assert", "panic", "nvidia", "rmapi", "gsp", "falcon", "mailbox", "interrupt", "dma", "iommu", "page", "mmu", "pde", "pte"}; + List<StringInfo> strings = new ArrayList<>(); + var listing = program.getListing(); + var dataIter = listing.getDefinedData(true); + while (dataIter.hasNext()) { + var data = dataIter.next(); + if (data.getDataType().getName().equals("string")) { + String value = data.getValue().toString(); + if (value.length() > 4) { + String lower = value.toLowerCase(); + for (String kw : keywords) { + if (lower.contains(kw)) { + strings.add(new StringInfo(data.getAddress().toString(), value)); + break; + } + } + } + } + } + writeJson(outputDir + "/interesting_strings.json", strings); + + println("Extracted " + functions.size() + " functions, " + memBlocks.size() + " memory blocks, " + strings.size() + " interesting strings"); + } + + private void writeJson(String path, List<?> list) throws IOException { + try (FileWriter fw = new FileWriter(path)) { + fw.write("[\n"); + for (int i = 0; i < list.size(); i++) { + fw.write(" " + toJson(list.get(i))); + if (i < list.size() - 1) fw.write(","); + fw.write("\n"); + } + fw.write("]\n"); + } + } + + private String toJson(Object obj) { + if (obj instanceof MemoryBlockInfo) { + MemoryBlockInfo m = (MemoryBlockInfo) obj; + return String.format("{\"name\":\"%s\",\"start\":\"%s\",\"end\":\"%s\",\"size\":%d,\"execute\":%b,\"read\":%b,\"write\":%b}", + m.name, m.start, m.end, m.size, m.execute, m.read, m.write); + } else if (obj instanceof FunctionInfo) { + FunctionInfo f = (FunctionInfo) obj; + return String.format("{\"name\":\"%s\",\"entry\":\"%s\",\"size\":%d}", + f.name, f.entry, f.size); + } else if (obj instanceof StringInfo) { + StringInfo s = (StringInfo) obj; + return String.format("{\"address\":\"%s\",\"value\":\"%s\"}", + s.address, s.value.replace("\\", "\\\\").replace("\"", "\\\"")); + } + return "{}"; + } + + static class MemoryBlockInfo { + String name, start, end; + long size; + boolean execute, read, write; + MemoryBlockInfo(String n, String s, String e, long sz, boolean ex, boolean rd, boolean wr) { + name = n; start = s; end = e; size = sz; execute = ex; read = rd; write = wr; + } + } + + static class FunctionInfo { + String name, entry; + long size; + FunctionInfo(String n, String e, long sz) { name = n; entry = e; size = sz; } + } + + static class StringInfo { + String address, value; + StringInfo(String a, String v) { address = a; value = v; } + } +} diff --git a/tools/ghidra/gsp-fwimage-570.144/scripts/basic_analysis.py b/tools/ghidra/gsp-fwimage-570.144/scripts/basic_analysis.py new file mode 100644 index 0000000..4992106 --- /dev/null +++ b/tools/ghidra/gsp-fwimage-570.144/scripts/basic_analysis.py @@ -0,0 +1,108 @@ +# Ghidra script to do basic disassembly analysis of GSP .fwimage binary +# Usage: analyzeHeadless ... -postScript basic_analysis.py + +import sys +import os +import json + +# Get the current program +program = getCurrentProgram() +listing = program.getListing() +memory = program.getMemory() +function_manager = program.getFunctionManager() + +print("=== GSP Firmware .fwimage Basic Analysis ===") +print(f"Program: {program.getName()}") +print(f"Architecture: {program.getLanguage().toString()}") + +# Create output directory +output_dir = "/home/rmcore/Git/integdev_gpu_drv/open-iov/firmware/570-GSP" +os.makedirs(output_dir, exist_ok=True) + +# 1. Check memory blocks +print("\n--- Memory Blocks ---") +mem_blocks = [] +for block in memory.getBlocks(): + mem_blocks.append({ + "name": block.getName(), + "start": str(block.getStart()), + "end": str(block.getEnd()), + "size": block.getSize(), + "execute": block.isExecute(), + "read": block.isRead(), + "write": block.isWrite() + }) + print(f" {block.getName()}: {block.getStart()} - {block.getEnd()} ({block.getSize()} bytes) r={block.isRead()} w={block.isWrite()} x={block.isExecute()}") + +with open(os.path.join(output_dir, "memory_blocks.json"), "w") as f: + json.dump(mem_blocks, f, indent=2) + +# 2. Find all functions (but don't decompile yet) +print("\n--- Finding Functions ---") +functions = [] +func_iter = function_manager.getFunctions(True) +count = 0 +while func_iter.hasNext(): + func = func_iter.next() + functions.append({ + "name": func.getName(), + "entry": str(func.getEntryPoint()), + "size": func.getBody().getNumAddresses() + }) + count += 1 + if count % 1000 == 0: + print(f" Found {count} functions...") + +print(f"Total functions: {len(functions)}") + +with open(os.path.join(output_dir, "functions.json"), "w") as f: + json.dump(functions, f, indent=2) + +# 3. Find strings +print("\n--- Finding Strings ---") +strings = [] +string_iter = listing.getDefinedData(True) +while string_iter.hasNext(): + data = string_iter.next() + if data.getDataType().getName() == "string": + value = data.getValue() + if value and len(str(value)) > 4: + strings.append({ + "address": str(data.getAddress()), + "value": str(value) + }) + +print(f"Found {len(strings)} strings") + +# Filter for interesting strings +interesting_keywords = ["vgpu", "vmiop", "rpc", "hal", "bar", "migrate", "init", "boot", "kgsp", "wpr", "firmware", "version", "error", "fail", "assert", "panic", "nvidia", "rmapi", "gsp", "falcon", "mailbox", "interrupt", "dma", "iommu", "page", "mmu", "pde", "pte"] +interesting_strings = [s for s in strings if any(kw in s['value'].lower() for kw in interesting_keywords)] +print(f"Interesting strings: {len(interesting_strings)}") + +with open(os.path.join(output_dir, "interesting_strings.json"), "w") as f: + json.dump(interesting_strings, f, indent=2) + +# 4. Find entry point (offset 0) +print("\n--- Entry Point Analysis ---") +entry_addr = program.getMinAddress() +print(f"Program entry (min address): {entry_addr}") + +# Check what's at address 0 +func_at_zero = function_manager.getFunctionAt(entry_addr) +if func_at_zero: + print(f"Function at entry: {func_at_zero.getName()}") +else: + print("No function at entry point - creating one...") + # Create function at entry point + func = function_manager.createFunction("entry_point", entry_addr, None, None) + if func: + print(f"Created function: {func.getName()}") + +# 5. Look for RISC-V standard function prologues +print("\n--- Looking for Function Prologues ---") +# RISC-V typical prologue: addi sp, sp, -X; sd ra, X-8(sp); sd s0, X-16(sp); addi s0, sp, X +# Let's search for common patterns + +# 6. Find cross-references to interesting addresses +print("\n--- Analysis Complete ---") +print(f"Results saved to {output_dir}")
\ No newline at end of file |
