mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-09-25 00:01:50 +08:00
GP-6773: Supporting "fallback" loaders
This commit is contained in:
@@ -215,6 +215,16 @@ public interface Loader extends ExtensionPoint, Comparable<Loader> {
|
||||
*/
|
||||
public int getTierPriority();
|
||||
|
||||
/**
|
||||
* {@return whether or not this is a "fallback" {@link Loader}}
|
||||
* <p>
|
||||
* Fallback loaders are only considered during the import process if no other non-fallback
|
||||
* loaders were compatible with the thing being imported.
|
||||
*/
|
||||
public default boolean isFallback() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* The preferred file name to use when loading.
|
||||
* <p>
|
||||
|
||||
@@ -23,6 +23,7 @@ import java.util.stream.Collectors;
|
||||
import ghidra.app.util.bin.ByteProvider;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.classfinder.ClassSearcher;
|
||||
import util.CollectionUtils;
|
||||
|
||||
/**
|
||||
* Factory and utility methods for working with {@link Loader}s.
|
||||
@@ -41,26 +42,50 @@ public class LoaderService {
|
||||
public static LoaderMap getSupportedLoadSpecs(ByteProvider provider,
|
||||
Predicate<Loader> loaderFilter) {
|
||||
LoaderMap loaderMap = new LoaderMap();
|
||||
List<Loader> fallback = new ArrayList<>();
|
||||
for (Loader loader : getAllLoaders()) {
|
||||
if (loaderFilter.test(loader)) {
|
||||
try {
|
||||
Collection<LoadSpec> loadSpecs = loader.findSupportedLoadSpecs(provider);
|
||||
if (loadSpecs != null && !loadSpecs.isEmpty()) { // shouldn't be null, but protect against rogue loaders
|
||||
loaderMap.put(loader, loadSpecs);
|
||||
}
|
||||
if (!loader.isFallback()) {
|
||||
tryLoadSpecs(loader, provider, loaderMap);
|
||||
}
|
||||
catch (IOException e) {
|
||||
// file not applicable for loader
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
Msg.error(LoaderService.class,
|
||||
"Unexpected Loader exception from " + loader.getName(), e);
|
||||
else {
|
||||
fallback.add(loader);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (loaderMap.size() <= 1) { // BinaryLoader is always there
|
||||
for (Loader loader : fallback) {
|
||||
tryLoadSpecs(loader, provider, loaderMap);
|
||||
}
|
||||
}
|
||||
|
||||
return loaderMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to find and register supported {@link LoadSpec}s for the given {@link Loader}
|
||||
*
|
||||
* @param loader The {@link Loader} to query
|
||||
* @param provider The {@link ByteProvider} to load from
|
||||
* @param loaderMap The {@link LoaderMap} to populate with discovered {@link LoadSpec}s
|
||||
*/
|
||||
private static void tryLoadSpecs(Loader loader, ByteProvider provider, LoaderMap loaderMap) {
|
||||
try {
|
||||
Collection<LoadSpec> loadSpecs = loader.findSupportedLoadSpecs(provider);
|
||||
if (!CollectionUtils.isBlank(loadSpecs)) {
|
||||
loaderMap.put(loader, loadSpecs);
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
// file not applicable for loader
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
Msg.error(LoaderService.class, "Unexpected Loader exception from " + loader.getName(),
|
||||
e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all supported {@link LoadSpec}s for loading the given {@link ByteProvider}.
|
||||
*
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@@ -15,9 +15,13 @@
|
||||
*/
|
||||
package ghidra.app.util.opinion;
|
||||
|
||||
/**
|
||||
* When sorting, {@link Loader}s are first {@link Loader#compareTo(Loader) sorted} by tier, and then
|
||||
* by {@link Loader#getTierPriority()} to break ties
|
||||
*/
|
||||
public enum LoaderTier {
|
||||
SPECIALIZED_TARGET_LOADER,
|
||||
GENERIC_TARGET_LOADER,
|
||||
AMBIGUOUS_TARGET_LOADER,
|
||||
UNTARGETED_LOADER
|
||||
SPECIALIZED_TARGET_LOADER,
|
||||
GENERIC_TARGET_LOADER,
|
||||
AMBIGUOUS_TARGET_LOADER,
|
||||
UNTARGETED_LOADER
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user