From f58072535ee6d3f01131a595abebb23d8e2e0d60 Mon Sep 17 00:00:00 2001 From: ghizard <50744617+ghizard@users.noreply.github.com> Date: Tue, 9 Apr 2024 21:38:58 +0000 Subject: [PATCH] GP-4503 - Use GhidraScript askValues in two developer PDB scripts --- .../PdbDeveloperApplyDummyScript.java | 76 +++++++++++----- .../PdbDeveloperDumpScript.java | 90 +++++++++++++------ 2 files changed, 118 insertions(+), 48 deletions(-) diff --git a/Ghidra/Features/PDB/developer_scripts/PdbDeveloperApplyDummyScript.java b/Ghidra/Features/PDB/developer_scripts/PdbDeveloperApplyDummyScript.java index 06eb8b9a6b..dcfc1f3fa8 100644 --- a/Ghidra/Features/PDB/developer_scripts/PdbDeveloperApplyDummyScript.java +++ b/Ghidra/Features/PDB/developer_scripts/PdbDeveloperApplyDummyScript.java @@ -20,43 +20,74 @@ import java.io.File; import java.io.IOException; +import db.Transaction; import ghidra.app.script.GhidraScript; import ghidra.app.services.ProgramManager; import ghidra.app.util.bin.format.pdb2.pdbreader.*; import ghidra.app.util.importer.MessageLog; import ghidra.app.util.pdb.pdbapplicator.DefaultPdbApplicator; import ghidra.app.util.pdb.pdbapplicator.PdbApplicatorOptions; +import ghidra.features.base.values.GhidraValuesMap; import ghidra.program.database.ProgramDB; +import ghidra.program.model.address.Address; import ghidra.program.model.lang.Language; import ghidra.program.model.lang.LanguageService; import ghidra.program.model.lang.Processor; import ghidra.program.model.mem.Memory; import ghidra.program.util.DefaultLanguageService; -import ghidra.util.Msg; +import ghidra.util.MessageType; public class PdbDeveloperApplyDummyScript extends GhidraScript { + private static final String PDB_PROMPT = "Choose a PDB file"; + private static final String IMAGE_BASE_PROMPT = "Image Base"; + @Override protected void run() throws Exception { - File pdbFile = askFile("Choose a PDB file", "OK"); - if (pdbFile == null) { - Msg.info(this, "Canceled execution due to no input file"); - return; - } - if (!pdbFile.exists()) { - String message = pdbFile.getAbsolutePath() + " is not a valid file."; - Msg.info(this, message); - popup(message); - return; - } + + LanguageService ls = DefaultLanguageService.getLanguageService(); + Processor processor_x86 = Processor.findOrPossiblyCreateProcessor("x86"); + Language x86 = ls.getDefaultLanguage(processor_x86); + ProgramDB program = new ProgramDB("Test", x86, x86.getDefaultCompilerSpec(), this); + Address imageBase = + program.getAddressFactory().getDefaultAddressSpace().getAddress(0x400000L); + + GhidraValuesMap values = new GhidraValuesMap(); + + values.defineFile(PDB_PROMPT, null); + values.defineAddress(IMAGE_BASE_PROMPT, imageBase, program); + + // Validator for values + values.setValidator((valueMap, status) -> { + File file = valueMap.getFile(PDB_PROMPT); + if (file == null) { + status.setStatusText("PDB file must be selected.", MessageType.ERROR); + return false; + } + if (!file.exists()) { + status.setStatusText(file.getAbsolutePath() + " is not a valid file.", + MessageType.ERROR); + return false; + } + String fileName = file.getAbsolutePath(); + if (!fileName.endsWith(".pdb") && !fileName.endsWith(".PDB")) { + status.setStatusText("Expected .pdb file extenstion (got '" + fileName + "').", + MessageType.ERROR); + return false; + } + // We do not need to check the existence of an image base because we provide a default + // value + return true; + }); + + // asks the script to show a dialog where the user can give values for all the items + // in the ValuesMap. + + values = askValues("Enter Values", null, values); + + File pdbFile = values.getFile(PDB_PROMPT); String pdbFileName = pdbFile.getAbsolutePath(); - if (!pdbFileName.endsWith(".pdb") && !pdbFileName.endsWith(".PDB")) { - String message = "Aborting: Expected input file to have extension of type .pdb (got '" + - pdbFileName + "')."; - Msg.info(this, message); - popup(message); - return; - } + imageBase = values.getAddress(IMAGE_BASE_PROMPT); MessageLog log = new MessageLog(); @@ -64,10 +95,9 @@ public class PdbDeveloperApplyDummyScript extends GhidraScript { PdbReaderOptions pdbReaderOptions = new PdbReaderOptions(); PdbApplicatorOptions pdbApplicatorOptions = new PdbApplicatorOptions(); - LanguageService ls = DefaultLanguageService.getLanguageService(); - Processor processor_x86 = Processor.findOrPossiblyCreateProcessor("x86"); - Language x86 = ls.getDefaultLanguage(processor_x86); - ProgramDB program = new ProgramDB("Test", x86, x86.getDefaultCompilerSpec(), this); + try (Transaction tx = program.openTransaction("Set Image Base")) { + program.setImageBase(imageBase, true); + } ProgramManager programManager = state.getTool().getService(ProgramManager.class); programManager.openProgram(program); diff --git a/Ghidra/Features/PDB/developer_scripts/PdbDeveloperDumpScript.java b/Ghidra/Features/PDB/developer_scripts/PdbDeveloperDumpScript.java index 871a7269d7..de665ea6c9 100644 --- a/Ghidra/Features/PDB/developer_scripts/PdbDeveloperDumpScript.java +++ b/Ghidra/Features/PDB/developer_scripts/PdbDeveloperDumpScript.java @@ -19,39 +19,79 @@ import java.io.*; +import docking.widgets.values.GValuesMap; import ghidra.app.script.GhidraScript; import ghidra.app.util.bin.format.pdb2.pdbreader.*; -import ghidra.util.Msg; +import ghidra.features.base.values.GhidraValuesMap; +import ghidra.util.*; public class PdbDeveloperDumpScript extends GhidraScript { + private static final String PDB_PROMPT = "Choose a PDB file"; + private static final String OUTPUT_PROMPT = "Choose an output file"; + + private static boolean validatePdb(GValuesMap valueMap, StatusListener status) { + File file = valueMap.getFile(PDB_PROMPT); + if (file == null) { + status.setStatusText("PDB file must be selected.", MessageType.ERROR); + return false; + } + if (!file.exists()) { + status.setStatusText(file.getAbsolutePath() + " is not a valid file.", + MessageType.ERROR); + return false; + } + String fileName = file.getAbsolutePath(); + if (!fileName.endsWith(".pdb") && !fileName.endsWith(".PDB")) { + status.setStatusText("Expected .pdb file extenstion (got '" + fileName + "').", + MessageType.ERROR); + return false; + } + // We do not need to check the existence of an image base because we provide a default + // value + return true; + } + + private static boolean validateOutput(GValuesMap valueMap, StatusListener status) { + File file = valueMap.getFile(OUTPUT_PROMPT); + // File will exist, as we supplied a default value + String fileName = file.getAbsolutePath(); + if (fileName.endsWith(".pdb") || fileName.endsWith(".PDB")) { + status.setStatusText("Output file may not end with .pdb (got '" + fileName + "').", + MessageType.ERROR); + return false; + } + return true; + } + @Override protected void run() throws Exception { - File pdbFile = askFile("Choose a PDB file", "OK"); - if (pdbFile == null) { - Msg.info(this, "Canceled execution due to no input file"); - return; - } - if (!pdbFile.exists()) { - String message = pdbFile.getAbsolutePath() + " is not a valid file."; - Msg.info(this, message); - popup(message); - return; - } - String pdbFileName = pdbFile.getAbsolutePath(); - if (!pdbFileName.endsWith(".pdb") && !pdbFileName.endsWith(".PDB")) { - String message = "Aborting: Expected input file to have extension of type .pdb (got '" + - pdbFileName + "')."; - Msg.info(this, message); - popup(message); - return; - } - File dumpFile = askFile("Choose an output file", "OK"); - if (dumpFile == null) { - Msg.info(this, "Canceled execution due to no output file"); - return; - } + GhidraValuesMap values = new GhidraValuesMap(); + + values.defineFile(PDB_PROMPT, null); + values.setValidator((valueMap, status) -> { + return validatePdb(valueMap, status); + }); + values = askValues("Enter Values", null, values); + File pdbFile = values.getFile(PDB_PROMPT); + String pdbFileName = pdbFile.getAbsolutePath(); + + // creating a default output and asking again; PDB file should retain its current value + // from above + String outputFileName = pdbFileName + ".txt"; + values.defineFile(OUTPUT_PROMPT, new File(outputFileName)); + values.setValidator((valueMap, status) -> { + if (!validatePdb(valueMap, status)) { + return false; + } + return validateOutput(valueMap, status); + }); + values = askValues("Enter Values", null, values); + pdbFile = values.getFile(PDB_PROMPT); // might have changed + pdbFileName = pdbFile.getAbsolutePath(); // might have changed + File dumpFile = values.getFile(OUTPUT_PROMPT); + if (dumpFile.exists()) { if (!askYesNo("Confirm Overwrite", "Overwrite file: " + dumpFile.getName())) { Msg.info(this, "Operation canceled");