mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-08-08 07:40:39 -09:00
GP-5848: Enforce architecture matching when loading libraries from
project
This commit is contained in:
@@ -38,7 +38,6 @@ import ghidra.program.model.lang.*;
|
|||||||
import ghidra.program.model.listing.Library;
|
import ghidra.program.model.listing.Library;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.program.model.symbol.ExternalManager;
|
import ghidra.program.model.symbol.ExternalManager;
|
||||||
import ghidra.util.Msg;
|
|
||||||
import ghidra.util.StringUtilities;
|
import ghidra.util.StringUtilities;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
import ghidra.util.exception.InvalidInputException;
|
import ghidra.util.exception.InvalidInputException;
|
||||||
@@ -632,12 +631,12 @@ public abstract class AbstractLibrarySupportLoader extends AbstractProgramLoader
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
processed.add(library);
|
processed.add(library);
|
||||||
if (findLibraryInProject(library, libraryDestFolder, searchPaths,
|
if (findLibraryInProject(library, libraryDestFolder, searchPaths, true,
|
||||||
settings) != null) {
|
settings) != null) {
|
||||||
log.appendMsg("Found %s in %s...".formatted(library, libraryDestFolder));
|
log.appendMsg("Found %s in %s...".formatted(library, libraryDestFolder));
|
||||||
log.appendMsg("------------------------------------------------\n");
|
log.appendMsg("------------------------------------------------\n");
|
||||||
}
|
}
|
||||||
else if (findLibraryInProject(library, linkSearchFolder, searchPaths,
|
else if (findLibraryInProject(library, linkSearchFolder, searchPaths, true,
|
||||||
settings) != null) {
|
settings) != null) {
|
||||||
log.appendMsg("Found %s in %s...".formatted(library, linkSearchFolder));
|
log.appendMsg("Found %s in %s...".formatted(library, linkSearchFolder));
|
||||||
log.appendMsg("------------------------------------------------\n");
|
log.appendMsg("------------------------------------------------\n");
|
||||||
@@ -779,12 +778,14 @@ public abstract class AbstractLibrarySupportLoader extends AbstractProgramLoader
|
|||||||
* @param folder {@link DomainFolder root folder} within which imported libraries will
|
* @param folder {@link DomainFolder root folder} within which imported libraries will
|
||||||
* be searched. If null this method will return null.
|
* be searched. If null this method will return null.
|
||||||
* @param searchPaths A {@link List} of {@link LibrarySearchPath}s that will be searched
|
* @param searchPaths A {@link List} of {@link LibrarySearchPath}s that will be searched
|
||||||
|
* @param matchLoadSpec True if the returned library must match the desired load spec; false
|
||||||
|
* if a match is not required
|
||||||
* @param settings The {@link Loader.ImporterSettings}
|
* @param settings The {@link Loader.ImporterSettings}
|
||||||
* @return The found {@link DomainFile} or null if not found
|
* @return The found {@link DomainFile} or null if not found
|
||||||
* @throws CancelledException if the user cancelled the load
|
* @throws CancelledException if the user cancelled the load
|
||||||
*/
|
*/
|
||||||
protected DomainFile findLibraryInProject(String library, DomainFolder folder,
|
protected DomainFile findLibraryInProject(String library, DomainFolder folder,
|
||||||
List<LibrarySearchPath> searchPaths, ImporterSettings settings)
|
List<LibrarySearchPath> searchPaths, boolean matchLoadSpec, ImporterSettings settings)
|
||||||
throws CancelledException {
|
throws CancelledException {
|
||||||
if (folder == null) {
|
if (folder == null) {
|
||||||
return null;
|
return null;
|
||||||
@@ -809,7 +810,8 @@ public abstract class AbstractLibrarySupportLoader extends AbstractProgramLoader
|
|||||||
}
|
}
|
||||||
DomainFile ret =
|
DomainFile ret =
|
||||||
lookupLibraryInFolder(FilenameUtils.getName(library), parentFolder);
|
lookupLibraryInFolder(FilenameUtils.getName(library), parentFolder);
|
||||||
if (ret != null) {
|
if (ret != null &&
|
||||||
|
(!matchLoadSpec || matchSupportedLoadSpec(settings.loadSpec(), ret))) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -825,13 +827,19 @@ public abstract class AbstractLibrarySupportLoader extends AbstractProgramLoader
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// First perform a direct filename lookup in the folder (for efficiency)
|
||||||
String libraryName = FilenameUtils.getName(library);
|
String libraryName = FilenameUtils.getName(library);
|
||||||
DomainFile file = folder.getFile(libraryName);
|
DomainFile file = folder.getFile(libraryName);
|
||||||
if (file != null) {
|
if (file != null) {
|
||||||
return file;
|
return !matchLoadSpec || matchSupportedLoadSpec(settings.loadSpec(), file) ? file
|
||||||
|
: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return lookupLibraryInFolder(libraryName, folder);
|
// If necessary, perform a slower comparator-based lookup on every file in the folder
|
||||||
|
file = lookupLibraryInFolder(libraryName, folder);
|
||||||
|
return file != null && (!matchLoadSpec || matchSupportedLoadSpec(settings.loadSpec(), file))
|
||||||
|
? file
|
||||||
|
: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -968,40 +976,50 @@ public abstract class AbstractLibrarySupportLoader extends AbstractProgramLoader
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
monitor.checkCancelled();
|
monitor.checkCancelled();
|
||||||
try {
|
Loaded<Program> match = findLibraryInLoadedList(loadedPrograms, externalLibName);
|
||||||
Loaded<Program> match = findLibraryInLoadedList(loadedPrograms, externalLibName);
|
if (match != null) {
|
||||||
if (match != null) {
|
setExternalLibrary(externalLibName,
|
||||||
extManager.setExternalPath(externalLibName, FSUtilities
|
FSUtilities.appendPath(match.getProjectFolderPath(), match.getName()), program,
|
||||||
.appendPath(match.getProjectFolderPath(), match.getName()),
|
settings);
|
||||||
false);
|
|
||||||
log.appendMsg(" [" + externalLibName + "] -> [" + match.getName() + "]");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
boolean found = false;
|
|
||||||
for (DomainFolder searchFolder : searchFolders) {
|
|
||||||
DomainFile alreadyImportedLib = findLibraryInProject(externalLibName,
|
|
||||||
searchFolder, fsSearchPaths, settings);
|
|
||||||
if (alreadyImportedLib != null) {
|
|
||||||
extManager.setExternalPath(externalLibName,
|
|
||||||
alreadyImportedLib.getPathname(), false);
|
|
||||||
log.appendMsg(" [" + externalLibName + "] -> [" +
|
|
||||||
alreadyImportedLib.getPathname() + "] (previously imported)");
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!found) {
|
|
||||||
log.appendMsg(" [" + externalLibName + "] -> not found in project");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (InvalidInputException e) {
|
else {
|
||||||
Msg.error(this, "Bad library name: " + externalLibName, e);
|
boolean found = false;
|
||||||
|
for (DomainFolder searchFolder : searchFolders) {
|
||||||
|
DomainFile alreadyImportedLib = findLibraryInProject(externalLibName,
|
||||||
|
searchFolder, fsSearchPaths, false, settings);
|
||||||
|
if (alreadyImportedLib != null) {
|
||||||
|
if (matchSupportedLoadSpec(settings.loadSpec(), alreadyImportedLib)) {
|
||||||
|
setExternalLibrary(externalLibName, alreadyImportedLib.getPathname(),
|
||||||
|
program, settings);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
log.appendMsg(
|
||||||
|
" [%s] -> found wrong architecture".formatted(externalLibName));
|
||||||
|
}
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
log.appendMsg(" [%s] -> not found in project".formatted(externalLibName));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
log.appendMsg("------------------------------------------------\n");
|
log.appendMsg("------------------------------------------------\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setExternalLibrary(String libraryName, String pathname, Program program,
|
||||||
|
ImporterSettings settings) {
|
||||||
|
MessageLog log = settings.log();
|
||||||
|
try {
|
||||||
|
program.getExternalManager().setExternalPath(libraryName, pathname, false);
|
||||||
|
log.appendMsg(" [%s] -> [%s] (previously imported)".formatted(libraryName, pathname));
|
||||||
|
}
|
||||||
|
catch (InvalidInputException e) {
|
||||||
|
log.appendMsg(" [%s] -> bad library name".formatted(libraryName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A library that has not been processed by the loader yet
|
* A library that has not been processed by the loader yet
|
||||||
*
|
*
|
||||||
@@ -1175,6 +1193,28 @@ public abstract class AbstractLibrarySupportLoader extends AbstractProgramLoader
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@return whether or not the given {@link LoadSpec} matches the one associated with the given
|
||||||
|
* {@link DomainFile}}
|
||||||
|
* <p>
|
||||||
|
* To avoid having to open each library which might require an upgrade, we just look at the
|
||||||
|
* "Language ID" metadata attached to the {@link DomainFile}.
|
||||||
|
*
|
||||||
|
* @param desiredLoadSpec The desired {@link LoadSpec}
|
||||||
|
* @param df The {@link DomainFile}
|
||||||
|
*/
|
||||||
|
protected boolean matchSupportedLoadSpec(LoadSpec desiredLoadSpec, DomainFile df) {
|
||||||
|
String fileLangId = df.getMetadata().getOrDefault("Language ID", "");
|
||||||
|
String desiredLangId =
|
||||||
|
desiredLoadSpec.getLanguageCompilerSpec().getLanguageID().getIdAsString();
|
||||||
|
|
||||||
|
String[] fileParts = fileLangId.split(":");
|
||||||
|
String[] desiredParts = desiredLangId.split(":");
|
||||||
|
|
||||||
|
return fileParts.length >= 3 && desiredParts.length >= 3 &&
|
||||||
|
Arrays.equals(fileParts, 0, 3, desiredParts, 0, 3);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Looks in the given {@link GFileSystem} for the given library using the loader's
|
* Looks in the given {@link GFileSystem} for the given library using the loader's
|
||||||
* {@link #getLibraryNameComparator() library name comparator}
|
* {@link #getLibraryNameComparator() library name comparator}
|
||||||
|
|||||||
@@ -627,7 +627,7 @@ public class MachoLoader extends AbstractLibrarySupportLoader {
|
|||||||
if (lib == null) {
|
if (lib == null) {
|
||||||
for (DomainFolder searchFolder : searchFolders) {
|
for (DomainFolder searchFolder : searchFolders) {
|
||||||
DomainFile df =
|
DomainFile df =
|
||||||
findLibraryInProject(path, searchFolder, searchPaths, settings);
|
findLibraryInProject(path, searchFolder, searchPaths, true, settings);
|
||||||
if (df != null) {
|
if (df != null) {
|
||||||
DomainObject obj = df.getDomainObject(this, true, true, monitor);
|
DomainObject obj = df.getDomainObject(this, true, true, monitor);
|
||||||
if (obj instanceof Program p) {
|
if (obj instanceof Program p) {
|
||||||
|
|||||||
Reference in New Issue
Block a user