diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/AbstractProgramLoader.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/AbstractProgramLoader.java index e825b26d45..3670bb38e4 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/AbstractProgramLoader.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/AbstractProgramLoader.java @@ -15,11 +15,12 @@ */ package ghidra.app.util.opinion; -import java.io.IOException; -import java.io.InputStream; import java.util.ArrayList; import java.util.List; +import java.io.IOException; +import java.io.InputStream; + import ghidra.app.plugin.processors.generic.MemoryBlockDefinition; import ghidra.app.util.Option; import ghidra.app.util.OptionUtils; @@ -29,6 +30,7 @@ import ghidra.formats.gfilesystem.FSRL; import ghidra.framework.model.DomainFolder; import ghidra.framework.model.DomainObject; import ghidra.framework.store.LockException; +import ghidra.plugin.importer.ProgramMappingService; import ghidra.program.database.ProgramDB; import ghidra.program.database.function.OverlappingFunctionException; import ghidra.program.model.address.*; @@ -284,14 +286,7 @@ public abstract class AbstractProgramLoader implements Loader { prog.setEventsEnabled(false); int id = prog.startTransaction("Set program properties"); try { - prog.setExecutablePath(provider.getAbsolutePath()); - if (executableFormatName != null) { - prog.setExecutableFormat(executableFormatName); - } - String md5 = computeBinaryMD5(provider); - prog.setExecutableMD5(md5); - String sha256 = computeBinarySHA256(provider); - prog.setExecutableSHA256(sha256); + setProgramProperties(prog, provider, executableFormatName); if (shouldSetImageBase(prog, imageBase)) { try { @@ -311,6 +306,37 @@ public abstract class AbstractProgramLoader implements Loader { return prog; } + /** + * Sets a program's Executable Path, Executable Format, MD5, SHA256, and FSRL properties. + *

+ * + * @param prog {@link Program} (with active transaction) + * @param provider {@link ByteProvider} that the program was created from + * @param executableFormatName executable format string + * @throws IOException if error reading from ByteProvider + */ + public static void setProgramProperties(Program prog, ByteProvider provider, + String executableFormatName) throws IOException { + prog.setExecutablePath(provider.getAbsolutePath()); + if (executableFormatName != null) { + prog.setExecutableFormat(executableFormatName); + } + FSRL fsrl = provider.getFSRL(); + String md5 = (fsrl != null && fsrl.getMD5() != null) + ? fsrl.getMD5() + : computeBinaryMD5(provider); + if (fsrl != null) { + if (fsrl.getMD5() == null) { + fsrl = fsrl.withMD5(md5); + } + prog.getOptions(Program.PROGRAM_INFO) + .setString(ProgramMappingService.PROGRAM_SOURCE_FSRL, fsrl.toString()); + } + prog.setExecutableMD5(md5); + String sha256 = computeBinarySHA256(provider); + prog.setExecutableSHA256(sha256); + } + private String getProgramNameFromSourceData(ByteProvider provider, String domainFileName) { FSRL fsrl = provider.getFSRL(); if (fsrl != null) { @@ -529,13 +555,13 @@ public abstract class AbstractProgramLoader implements Loader { } } - private String computeBinaryMD5(ByteProvider provider) throws IOException { + private static String computeBinaryMD5(ByteProvider provider) throws IOException { try (InputStream in = provider.getInputStream(0)) { return MD5Utilities.getMD5Hash(in); } } - private String computeBinarySHA256(ByteProvider provider) throws IOException { + private static String computeBinarySHA256(ByteProvider provider) throws IOException { try (InputStream in = provider.getInputStream(0)) { return HashUtilities.getHash(HashUtilities.SHA256_ALGORITHM, in); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/plugin/importer/ImporterUtilities.java b/Ghidra/Features/Base/src/main/java/ghidra/plugin/importer/ImporterUtilities.java index 2330c817da..9831cc1f18 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/plugin/importer/ImporterUtilities.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/plugin/importer/ImporterUtilities.java @@ -34,7 +34,6 @@ import ghidra.formats.gfilesystem.*; import ghidra.framework.main.AppInfo; import ghidra.framework.main.FrontEndTool; import ghidra.framework.model.*; -import ghidra.framework.options.Options; import ghidra.framework.plugintool.PluginTool; import ghidra.plugins.importer.batch.BatchImportDialog; import ghidra.program.model.lang.LanguageCompilerSpecPair; @@ -86,41 +85,6 @@ public class ImporterUtilities { return CollectionUtils.asList(pairs); } - /** - * Ensure that a {@link Program}'s metadata includes its import origin. - * - * @param program imported {@link Program} to modify - * @param fsrl {@link FSRL} of the import source. - * @param monitor {@link TaskMonitor} to use when accessing filesystem stuff. - * @throws CancelledException if user cancels - * @throws IOException if IO error - */ - public static void setProgramProperties(Program program, FSRL fsrl, TaskMonitor monitor) - throws CancelledException, IOException { - - Objects.requireNonNull(monitor); - - int id = program.startTransaction("setImportProperties"); - try { - fsrl = fsService.getFullyQualifiedFSRL(fsrl, monitor); - - Options propertyList = program.getOptions(Program.PROGRAM_INFO); - if (!propertyList.contains(ProgramMappingService.PROGRAM_SOURCE_FSRL)) { - propertyList.setString(ProgramMappingService.PROGRAM_SOURCE_FSRL, fsrl.toString()); - } - String md5 = program.getExecutableMD5(); - if ((md5 == null || md5.isEmpty()) && fsrl.getMD5() != null) { - program.setExecutableMD5(fsrl.getMD5()); - } - } - finally { - program.endTransaction(id, true); - } - if (program.canSave()) { - program.save("Added import properties", monitor); - } - } - /** * Displays the appropriate import dialog for the specified {@link FSRL file}. *

@@ -431,13 +395,12 @@ public class ImporterUtilities { if (importedObject instanceof Program) { Program program = (Program) importedObject; - - setProgramProperties(program, fsrl, monitor); ProgramMappingService.createAssociation(fsrl, program); if (programManager != null) { - int openState = - firstProgram ? ProgramManager.OPEN_CURRENT : ProgramManager.OPEN_VISIBLE; + int openState = firstProgram + ? ProgramManager.OPEN_CURRENT + : ProgramManager.OPEN_VISIBLE; programManager.openProgram(program, openState); } importedFilesSet.add(program.getDomainFile()); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/plugins/fsbrowser/tasks/GFileSystemLoadKernelTask.java b/Ghidra/Features/Base/src/main/java/ghidra/plugins/fsbrowser/tasks/GFileSystemLoadKernelTask.java index c7edd625e1..b9b215576b 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/plugins/fsbrowser/tasks/GFileSystemLoadKernelTask.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/plugins/fsbrowser/tasks/GFileSystemLoadKernelTask.java @@ -15,16 +15,16 @@ */ package ghidra.plugins.fsbrowser.tasks; -import java.io.IOException; import java.util.List; +import java.io.IOException; + import ghidra.app.services.ProgramManager; import ghidra.formats.gfilesystem.*; import ghidra.framework.main.AppInfo; import ghidra.framework.model.DomainFolder; import ghidra.framework.model.ProjectDataUtils; import ghidra.framework.plugintool.Plugin; -import ghidra.plugin.importer.ImporterUtilities; import ghidra.plugin.importer.ProgramMappingService; import ghidra.program.model.lang.LanguageService; import ghidra.program.model.listing.Program; @@ -141,7 +141,6 @@ public class GFileSystemLoadKernelTask extends Task { String fileName = ProjectDataUtils.getUniqueName(folder, program.getName()); GhidraProgramUtilities.setAnalyzedFlag(program, true); - ImporterUtilities.setProgramProperties(program, file.getFSRL(), monitor); folder.createFile(fileName, program, monitor); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/plugins/importer/tasks/ImportBatchTask.java b/Ghidra/Features/Base/src/main/java/ghidra/plugins/importer/tasks/ImportBatchTask.java index c10ed0a9be..7543db8091 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/plugins/importer/tasks/ImportBatchTask.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/plugins/importer/tasks/ImportBatchTask.java @@ -15,9 +15,10 @@ */ package ghidra.plugins.importer.tasks; -import java.io.IOException; import java.util.List; +import java.io.IOException; + import org.apache.commons.io.FilenameUtils; import generic.stl.Pair; @@ -29,7 +30,6 @@ import ghidra.app.util.opinion.LoadSpec; import ghidra.formats.gfilesystem.*; import ghidra.framework.model.*; import ghidra.framework.store.local.LocalFileSystem; -import ghidra.plugin.importer.ImporterUtilities; import ghidra.plugin.importer.ProgramMappingService; import ghidra.plugins.importer.batch.*; import ghidra.plugins.importer.batch.BatchGroup.BatchLoadConfig; @@ -199,9 +199,7 @@ public class ImportBatchTask extends Task { } /* - * sets the imported program's source properties, creates fsrl associations, - * updates task statistics, opens the imported program (if allowed), and - * calls the ImportManagerServiceListener callback. + * creates fsrl associations, updates task statistics, opens the imported program (if allowed) */ private void processImportResults(List importedObjects, BatchLoadConfig appInfo, TaskMonitor monitor) throws CancelledException, IOException { @@ -209,7 +207,6 @@ public class ImportBatchTask extends Task { for (DomainObject obj : importedObjects) { if (obj instanceof Program) { Program program = (Program) obj; - ImporterUtilities.setProgramProperties(program, appInfo.getFSRL(), monitor); if (programManager != null && totalObjsImported < MAX_PROGRAMS_TO_OPEN) { programManager.openProgram(program, diff --git a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ios/prelink/PrelinkFileSystem.java b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ios/prelink/PrelinkFileSystem.java index 902c949393..209aee38af 100644 --- a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ios/prelink/PrelinkFileSystem.java +++ b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ios/prelink/PrelinkFileSystem.java @@ -15,9 +15,10 @@ */ package ghidra.file.formats.ios.prelink; +import java.util.*; + import java.io.IOException; import java.io.InputStream; -import java.util.*; import org.apache.commons.collections4.BidiMap; import org.jdom.JDOMException; @@ -194,8 +195,10 @@ public class PrelinkFileSystem extends GFileSystemBase implements GFileSystemPro new ByteProviderWrapper(provider, offset, provider.length() - offset); MachoProgramBuilder.buildProgram(program, providerWrapper, fileBytes, new MessageLog(), monitor); - program.setExecutableFormat(MachoLoader.MACH_O_NAME); - program.setExecutablePath(file.getPath()); + + AbstractProgramLoader.setProgramProperties(program, providerWrapper, + MachoLoader.MACH_O_NAME); + program.setExecutablePath(file.getPath()); // override the value set by AbstractProgramLoader.setProgramProperties if (file.equals(systemKextFile)) { processSystemKext(languageService, program, monitor);