From 47bf0890e720a6b270e58045950bd07dbd2fec1b Mon Sep 17 00:00:00 2001 From: Ryan Kurtz Date: Wed, 3 Jun 2026 06:01:41 -0400 Subject: [PATCH] GP-6920: Fixing stale monitor message about hashing that shows up during import --- .../ExternalDebugFileSectionProvider.java | 2 +- .../app/util/importer/ProgramLoader.java | 2 +- .../app/util/opinion/LoaderService.java | 53 ++++++++++++++++++- .../plugin/importer/ImporterPlugin.java | 4 +- .../plugin/importer/ImporterUtilities.java | 16 +++--- .../plugins/importer/batch/BatchInfo.java | 2 +- 6 files changed, 65 insertions(+), 14 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/dwarf/sectionprovider/ExternalDebugFileSectionProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/dwarf/sectionprovider/ExternalDebugFileSectionProvider.java index ed57e9be4d..87005d2a0a 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/dwarf/sectionprovider/ExternalDebugFileSectionProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/dwarf/sectionprovider/ExternalDebugFileSectionProvider.java @@ -73,7 +73,7 @@ public class ExternalDebugFileSectionProvider extends BaseSectionProvider { new FileByteProvider(extDebugFile, fsrl, AccessMode.READ)) { Object consumer = new Object(); Language lang = program.getLanguage(); - LoadSpec origLoadSpec = ImporterUtilities.getLoadSpec(program); + LoadSpec origLoadSpec = ImporterUtilities.getLoadSpec(program, monitor); if (origLoadSpec == null) { return null; } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/importer/ProgramLoader.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/importer/ProgramLoader.java index 7a59ddb169..02e041c7fd 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/importer/ProgramLoader.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/importer/ProgramLoader.java @@ -615,7 +615,7 @@ public class ProgramLoader { */ private LoadSpec getLoadSpec(ByteProvider p) throws LanguageNotFoundException, LoadException { - LoaderMap loaderMap = LoaderService.getSupportedLoadSpecs(p, loaderFilter); + LoaderMap loaderMap = LoaderService.getSupportedLoadSpecs(p, loaderFilter, monitor); LoadSpecChooser loadSpecChooser = languageId != null ? new LcsHintLoadSpecChooser(languageId, compilerSpecId) : (compilerSpecId != null ? new CsHintLoadSpecChooser(compilerSpecId) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/LoaderService.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/LoaderService.java index cfa6a79cdd..d6d7ab44d5 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/LoaderService.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/LoaderService.java @@ -21,8 +21,10 @@ import java.util.function.Predicate; import java.util.stream.Collectors; import ghidra.app.util.bin.ByteProvider; +import ghidra.program.util.DefaultLanguageService; import ghidra.util.Msg; import ghidra.util.classfinder.ClassSearcher; +import ghidra.util.task.TaskMonitor; import util.CollectionUtils; /** @@ -37,10 +39,12 @@ public class LoaderService { * * @param provider The {@link ByteProvider} to load. * @param loaderFilter A {@link Predicate} that will filter out undesired {@link Loader}s. + * @param monitor The {@link TaskMonitor} * @return All supported {@link LoadSpec}s in the form of a {@link LoaderMap}. */ public static LoaderMap getSupportedLoadSpecs(ByteProvider provider, - Predicate loaderFilter) { + Predicate loaderFilter, TaskMonitor monitor) { + initializeLanguageService(monitor); LoaderMap loaderMap = new LoaderMap(); List fallback = new ArrayList<>(); for (Loader loader : getAllLoaders()) { @@ -63,6 +67,20 @@ public class LoaderService { return loaderMap; } + /** + * Gets all supported {@link LoadSpec}s for loading the given {@link ByteProvider}. + * + * @param provider The {@link ByteProvider} to load. + * @param loaderFilter A {@link Predicate} that will filter out undesired {@link Loader}s. + * @return All supported {@link LoadSpec}s in the form of a {@link LoaderMap}. + * @deprecated Use {@link #getSupportedLoadSpecs(ByteProvider, Predicate, TaskMonitor)} + */ + @Deprecated(since = "12.2", forRemoval = true) + public static LoaderMap getSupportedLoadSpecs(ByteProvider provider, + Predicate loaderFilter) { + return getSupportedLoadSpecs(provider, loaderFilter, TaskMonitor.DUMMY); + } + /** * Attempts to find and register supported {@link LoadSpec}s for the given {@link Loader} * @@ -90,10 +108,23 @@ public class LoaderService { * Gets all supported {@link LoadSpec}s for loading the given {@link ByteProvider}. * * @param provider The {@link ByteProvider} to load. + * @param monitor The {@link TaskMonitor} * @return All supported {@link LoadSpec}s in the form of a {@link LoaderMap}. */ + public static LoaderMap getAllSupportedLoadSpecs(ByteProvider provider, TaskMonitor monitor) { + return getSupportedLoadSpecs(provider, ACCEPT_ALL, monitor); + } + + /** + * Gets all supported {@link LoadSpec}s for loading the given {@link ByteProvider}. + * + * @param provider The {@link ByteProvider} to load. + * @return All supported {@link LoadSpec}s in the form of a {@link LoaderMap}. + * @deprecated Use {@link #getAllSupportedLoadSpecs(ByteProvider, TaskMonitor)} + */ + @Deprecated(since = "12.2", forRemoval = true) public static LoaderMap getAllSupportedLoadSpecs(ByteProvider provider) { - return getSupportedLoadSpecs(provider, ACCEPT_ALL); + return getAllSupportedLoadSpecs(provider, TaskMonitor.DUMMY); } /** @@ -139,4 +170,22 @@ public class LoaderService { Collections.sort(loaders); return loaders; } + + /** + * Gets the language service so we can show its slow progress with a monitor. + *

+ * Typically the first time the language service is gotten is from within a call to + * {@link Loader#findSupportedLoadSpecs(ByteProvider)}, which doesn't have access to monitor + * (nor does {@link DefaultLanguageService#getLanguageService()}). This results in a stale + * monitor message being shown for several seconds. + * + * @param monitor The {@link TaskMonitor} + */ + private static void initializeLanguageService(TaskMonitor monitor) { + monitor.setMessage("Initializing language service..."); + monitor.setIndeterminate(true); + monitor.setCancelEnabled(false); + DefaultLanguageService.getLanguageService(); + monitor.setCancelEnabled(true); + } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/plugin/importer/ImporterPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/plugin/importer/ImporterPlugin.java index b57b12761b..597ee50ff8 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/plugin/importer/ImporterPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/plugin/importer/ImporterPlugin.java @@ -167,7 +167,7 @@ public class ImporterPlugin extends Plugin if (provider == null) { return false; } - LoadSpec loadSpec = ImporterUtilities.getLoadSpec(provider, program); + LoadSpec loadSpec = ImporterUtilities.getLoadSpec(provider, program, TaskMonitor.DUMMY); if (loadSpec == null) { return false; } @@ -567,7 +567,7 @@ public class ImporterPlugin extends Plugin String rangeName = block.getName() + "[" + minAddress + "," + maxAddress + "]"; String tempName = program.getName() + " " + rangeName; ByteProvider bp = fsService().getNamedTempFile(tmpFile, tempName); - LoaderMap loaderMap = LoaderService.getAllSupportedLoadSpecs(bp); + LoaderMap loaderMap = LoaderService.getAllSupportedLoadSpecs(bp, TaskMonitor.DUMMY); ProgramManager pm = tool.getService(ProgramManager.class); ImporterDialog importerDialog = new ImporterDialog(tool, pm, loaderMap, bp, null); 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 48bc5db167..5d1709ee29 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 @@ -230,7 +230,7 @@ public class ImporterUtilities { } LoaderMap loaderMap = LoaderService.getSupportedLoadSpecs(provider, - loader -> loader.supportsLoadIntoProgram(program)); + loader -> loader.supportsLoadIntoProgram(program), monitor); SystemUtilities.runSwingLater(() -> { AddToProgramDialog dialog = @@ -275,7 +275,7 @@ public class ImporterUtilities { "Cannot Load Libraries. Program does not have file bytes associated with it."); return; } - LoadSpec loadSpec = getLoadSpec(provider, program); + LoadSpec loadSpec = getLoadSpec(provider, program, monitor); if (loadSpec == null || loadSpec.getLoader() .getDefaultOptions(provider, loadSpec, null, false, false) .stream() @@ -319,7 +319,7 @@ public class ImporterUtilities { try { ByteProvider provider = fsService.getByteProvider(fsrl, true, monitor); - LoaderMap loaderMap = LoaderService.getAllSupportedLoadSpecs(provider); + LoaderMap loaderMap = LoaderService.getAllSupportedLoadSpecs(provider, monitor); SystemUtilities.runSwingLater(() -> { ImporterDialog importerDialog = new ImporterDialog(tool, programManager, loaderMap, @@ -573,12 +573,13 @@ public class ImporterUtilities { * * @param provider The original bytes of the {@link Program} * @param program The {@link Program} + * @param monitor The {@link TaskMonitor} * @return The {@link LoadSpec} that was used to import the given {@link Program}, or null if * it could not be determined */ - static LoadSpec getLoadSpec(ByteProvider provider, Program program) { + static LoadSpec getLoadSpec(ByteProvider provider, Program program, TaskMonitor monitor) { LoaderMap loaderMap = LoaderService.getSupportedLoadSpecs(provider, - loader -> loader.getName().equalsIgnoreCase(program.getExecutableFormat())); + loader -> loader.getName().equalsIgnoreCase(program.getExecutableFormat()), monitor); if (loaderMap.isEmpty()) { return null; @@ -601,15 +602,16 @@ public class ImporterUtilities { * Get's the {@link LoadSpec} that was used to import the given {@link Program} * * @param program The {@link Program} + * @param monitor The {@link TaskMonitor} * @return The {@link LoadSpec} that was used to import the given {@link Program}, or null if * it could not be determined */ - public static LoadSpec getLoadSpec(Program program) { + public static LoadSpec getLoadSpec(Program program, TaskMonitor monitor) { ByteProvider provider; if (program == null || (provider = getProvider(program)) == null) { return null; } - return getLoadSpec(provider, program); + return getLoadSpec(provider, program, monitor); } private static boolean ensureFileImportable(RefdFile refdFile, TaskMonitor monitor) { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/plugins/importer/batch/BatchInfo.java b/Ghidra/Features/Base/src/main/java/ghidra/plugins/importer/batch/BatchInfo.java index 88085d6b11..71d7a43639 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/plugins/importer/batch/BatchInfo.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/plugins/importer/batch/BatchInfo.java @@ -396,7 +396,7 @@ public class BatchInfo { TaskMonitor monitor) { monitor.setMessage(fsrl.getName()); return LoaderService.getSupportedLoadSpecs(provider, - loader -> !(loader instanceof BinaryLoader)); + loader -> !(loader instanceof BinaryLoader), monitor); } /**