mirror of
https://github.com/NationalSecurityAgency/ghidra
synced 2024-08-28 05:20:21 +00:00
GP-2604: More load library options
This commit is contained in:
parent
6d6491905b
commit
fdda6b672e
|
@ -29,38 +29,27 @@
|
|||
|
||||
<BLOCKQUOTE>
|
||||
<UL>
|
||||
<LI>Android APK</LI>
|
||||
<LI>Common Object File Format (COFF)</LI>
|
||||
|
||||
<LI>Dalvik Executable (DEX)</LI>
|
||||
<LI>Debug Symbols (DBG)</LI>
|
||||
|
||||
<LI>Dump File Loader</LI>
|
||||
<LI>DYLD Shared Cache</LI>
|
||||
|
||||
<LI>Executable and Linking Format (ELF)</LI>
|
||||
|
||||
<LI>Ghidra Data Type Archive Format</LI>
|
||||
|
||||
<LI>GZF Input Format</LI>
|
||||
|
||||
<LI>Intel Hex</LI>
|
||||
|
||||
<LI>Java Class File</LI>
|
||||
<LI>Mac OS X Mach-O</LI>
|
||||
|
||||
<LI>Module Definition (DEF)</LI>
|
||||
|
||||
<LI>Motorola Hex</LI>
|
||||
|
||||
<LI>New Executable (NE)</LI>
|
||||
|
||||
<LI>Old-style DOS Executable (MZ)</LI>
|
||||
|
||||
<LI>Portable Executable (PE)</LI>
|
||||
|
||||
<LI>Preferred Executable Format (PEF)</LI>
|
||||
|
||||
<LI>Program Mapfile (MAP)</LI>
|
||||
|
||||
<LI>Raw Binary</LI>
|
||||
|
||||
<LI>Relocatable Object Module Format (OMF)</LI>
|
||||
<LI>XML Input Format</LI>
|
||||
</UL>
|
||||
</BLOCKQUOTE>
|
||||
|
@ -281,8 +270,22 @@
|
|||
those symbols will remain at the address they were originally placed. If the option is
|
||||
off, the symbols will move with the image base or the memory block.</P>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<H4>Link Existing Project Libraries</H4>
|
||||
|
||||
<H4>Load Local Libraries</H4>
|
||||
<BLOCKQUOTE>
|
||||
<P> Searches the project for existing library programs and creates external references to
|
||||
them.</P>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<H4>Project Library Search Folder</H4>
|
||||
|
||||
<BLOCKQUOTE>
|
||||
<P>The project folder that will get searched for existing library programs. If left
|
||||
empty, the folder that the main program is being imported to will be searched.</P>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<H4>Load Local Libraries From Disk</H4>
|
||||
|
||||
<BLOCKQUOTE>
|
||||
<P>Searches the executable's directory to recursively resolve the external libraries used
|
||||
|
@ -292,7 +295,7 @@
|
|||
in these programs will be resolved.<BR>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<H4>Load System Libraries</H4>
|
||||
<H4>Load System Libraries From Disk</H4>
|
||||
|
||||
<BLOCKQUOTE>
|
||||
<P>Searches a user-defined path list to recursively resolve the external libraries used
|
||||
|
@ -309,6 +312,13 @@
|
|||
<P>Specifies how many levels deep the depth-first library dependency tree will be
|
||||
traversed when loading local or system libraries.</P>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<H4>Library Destination Folder</H4>
|
||||
|
||||
<BLOCKQUOTE>
|
||||
<P>The project folder where newly loaded library programs will get created. If left
|
||||
empty, they will get created in the same folder as the main program being imported.</P>
|
||||
</BLOCKQUOTE>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<H3>COFF Options<A name="Options_Common Object_File_Format__COFF_"/></H3>
|
||||
|
|
|
@ -28,12 +28,15 @@ import javax.swing.event.DocumentListener;
|
|||
import org.apache.commons.collections4.map.LazyMap;
|
||||
|
||||
import docking.DockingWindowManager;
|
||||
import docking.options.editor.ButtonPanelFactory;
|
||||
import docking.widgets.checkbox.GCheckBox;
|
||||
import docking.widgets.combobox.GComboBox;
|
||||
import docking.widgets.label.GLabel;
|
||||
import docking.widgets.textfield.IntegerTextField;
|
||||
import ghidra.app.util.opinion.AbstractLibrarySupportLoader;
|
||||
import ghidra.app.util.opinion.LibraryPathsDialog;
|
||||
import ghidra.framework.main.DataTreeDialog;
|
||||
import ghidra.framework.model.DomainFolder;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.util.exception.AssertException;
|
||||
import ghidra.util.layout.*;
|
||||
|
@ -43,7 +46,7 @@ import ghidra.util.layout.*;
|
|||
* in a list of Options and generates editors for each of them on th fly.
|
||||
*/
|
||||
public class OptionsEditorPanel extends JPanel {
|
||||
private static final int MAX_PER_COLUMN = 10;
|
||||
private static final int MAX_PER_COLUMN = 11;
|
||||
private static final int MAX_BOOLEANS_WITH_SELECT_ALL = 5;
|
||||
private int columns;
|
||||
private AddressFactoryService addressFactoryService;
|
||||
|
@ -177,9 +180,13 @@ public class OptionsEditorPanel extends JPanel {
|
|||
|
||||
public Component getEditorComponent(Option option) {
|
||||
|
||||
//special case for load library paths
|
||||
// Special cases for library link/load options
|
||||
if (option.getName().equals(AbstractLibrarySupportLoader.LINK_SEARCH_FOLDER_OPTION_NAME) ||
|
||||
option.getName().equals(AbstractLibrarySupportLoader.LIBRARY_DEST_FOLDER_OPTION_NAME)) {
|
||||
return buildProjectFolderEditor(option);
|
||||
}
|
||||
if (option.getName().equals(AbstractLibrarySupportLoader.SYSTEM_LIBRARY_OPTION_NAME)) {
|
||||
return buildLoadLibraryPathsEditor(option);
|
||||
return buildPathsEditor(option);
|
||||
}
|
||||
|
||||
Component customEditorComponent = option.getCustomEditorComponent();
|
||||
|
@ -216,7 +223,7 @@ public class OptionsEditorPanel extends JPanel {
|
|||
}
|
||||
}
|
||||
|
||||
private Component buildLoadLibraryPathsEditor(Option option) {
|
||||
private Component buildPathsEditor(Option option) {
|
||||
JPanel panel = new JPanel(new BorderLayout());
|
||||
JButton button = new JButton("Edit Paths");
|
||||
button.addActionListener(
|
||||
|
@ -233,6 +240,27 @@ public class OptionsEditorPanel extends JPanel {
|
|||
return panel;
|
||||
}
|
||||
|
||||
private Component buildProjectFolderEditor(Option option) {
|
||||
JPanel panel = new JPanel(new BorderLayout());
|
||||
JTextField textField = new JTextField();
|
||||
textField.setEditable(false);
|
||||
JButton button = ButtonPanelFactory.createButton(ButtonPanelFactory.BROWSE_TYPE);
|
||||
button.addActionListener(e -> {
|
||||
DataTreeDialog dataTreeDialog = new DataTreeDialog(this,
|
||||
"Choose a project folder", DataTreeDialog.CHOOSE_FOLDER);
|
||||
dataTreeDialog.setSelectedFolder(null);
|
||||
dataTreeDialog.showComponent();
|
||||
DomainFolder folder = dataTreeDialog.getDomainFolder();
|
||||
if (folder != null) {
|
||||
textField.setText(folder.getPathname());
|
||||
option.setValue(folder.getPathname());
|
||||
}
|
||||
});
|
||||
panel.add(textField, BorderLayout.CENTER);
|
||||
panel.add(button, BorderLayout.EAST);
|
||||
return panel;
|
||||
}
|
||||
|
||||
private Component getAddressSpaceEditorComponent(Option option) {
|
||||
JComboBox<AddressSpace> combo = new GComboBox<>();
|
||||
AddressFactory addressFactory = addressFactoryService.getAddressFactory();
|
||||
|
|
|
@ -50,15 +50,24 @@ import utilities.util.FileUtilities;
|
|||
*/
|
||||
public abstract class AbstractLibrarySupportLoader extends AbstractProgramLoader {
|
||||
|
||||
public static final String LOCAL_LIBRARY_OPTION_NAME = "Load Local Libraries";
|
||||
public static final String LINK_EXISTING_OPTION_NAME = "Link Existing Project Libraries";
|
||||
static final boolean LINK_EXISTING_OPTION_DEFAULT = true;
|
||||
|
||||
public static final String LINK_SEARCH_FOLDER_OPTION_NAME = "Project Library Search Folder";
|
||||
static final String LINK_SEARCH_FOLDER_OPTION_DEFAULT = "";
|
||||
|
||||
public static final String LOCAL_LIBRARY_OPTION_NAME = "Load Local Libraries From Disk";
|
||||
static final boolean LOCAL_LIBRARY_OPTION_DEFAULT = false;
|
||||
|
||||
public static final String SYSTEM_LIBRARY_OPTION_NAME = "Load System Libraries";
|
||||
public static final String SYSTEM_LIBRARY_OPTION_NAME = "Load System Libraries From Disk";
|
||||
static final boolean SYSTEM_LIBRARY_OPTION_DEFAULT = false;
|
||||
|
||||
public static final String DEPTH_OPTION_NAME = "Recursive Library Load Depth";
|
||||
static final int DEPTH_OPTION_DEFAULT = 1;
|
||||
|
||||
public static final String LIBRARY_DEST_FOLDER_OPTION_NAME = "Library Destination Folder";
|
||||
static final String LIBRARY_DEST_FOLDER_OPTION_DEFAULT = "";
|
||||
|
||||
/**
|
||||
* Loads bytes in a particular format into the given {@link Program}.
|
||||
*
|
||||
|
@ -76,11 +85,11 @@ public abstract class AbstractLibrarySupportLoader extends AbstractProgramLoader
|
|||
throws CancelledException, IOException;
|
||||
|
||||
@Override
|
||||
protected List<Program> loadProgram(ByteProvider provider, String programName,
|
||||
protected List<LoadedProgram> loadProgram(ByteProvider provider, String programName,
|
||||
DomainFolder programFolder, LoadSpec loadSpec, List<Option> options, MessageLog log,
|
||||
Object consumer, TaskMonitor monitor) throws CancelledException, IOException {
|
||||
|
||||
List<Program> programList = new ArrayList<>();
|
||||
List<LoadedProgram> loadedProgramList = new ArrayList<>();
|
||||
List<String> libraryNameList = new ArrayList<>();
|
||||
|
||||
boolean success = false;
|
||||
|
@ -88,21 +97,19 @@ public abstract class AbstractLibrarySupportLoader extends AbstractProgramLoader
|
|||
// Load the primary program
|
||||
Program program = doLoad(provider, programName, programFolder, loadSpec,
|
||||
libraryNameList, options, consumer, log, monitor);
|
||||
programList.add(program);
|
||||
loadedProgramList.add(new LoadedProgram(program, programFolder));
|
||||
|
||||
// Load the libraries, if applicable
|
||||
if (shouldLoadLibraries(options)) {
|
||||
List<Program> libraries = loadLibraries(provider, program, programFolder, loadSpec,
|
||||
options, log, consumer, libraryNameList, monitor);
|
||||
programList.addAll(libraries);
|
||||
}
|
||||
// Load the libraries
|
||||
List<LoadedProgram> libraries = loadLibraries(provider, program, programFolder,
|
||||
loadSpec, options, log, consumer, libraryNameList, monitor);
|
||||
loadedProgramList.addAll(libraries);
|
||||
|
||||
success = true;
|
||||
return programList;
|
||||
return loadedProgramList;
|
||||
}
|
||||
finally {
|
||||
if (!success) {
|
||||
release(programList, consumer);
|
||||
release(loadedProgramList, consumer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -126,11 +133,14 @@ public abstract class AbstractLibrarySupportLoader extends AbstractProgramLoader
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void postLoadProgramFixups(List<Program> loadedPrograms, DomainFolder folder,
|
||||
List<Option> options, MessageLog messageLog, TaskMonitor monitor)
|
||||
throws CancelledException, IOException {
|
||||
if (isLoadLocalLibraries(options) || isLoadSystemLibraries(options)) {
|
||||
fixupExternalLibraries(loadedPrograms, folder, true, messageLog, monitor);
|
||||
protected void postLoadProgramFixups(List<LoadedProgram> loadedPrograms, List<Option> options,
|
||||
MessageLog messageLog, TaskMonitor monitor) throws CancelledException, IOException {
|
||||
if (isLinkExistingLibraries(options) || isLoadLocalLibraries(options) ||
|
||||
isLoadSystemLibraries(options)) {
|
||||
DomainFolder programFolder = loadedPrograms.get(0).destinationFolder();
|
||||
DomainFolder linkSearchFolder = getLinkSearchFolder(programFolder, options);
|
||||
fixupExternalLibraries(loadedPrograms.stream().map(e -> e.program()).toList(),
|
||||
linkSearchFolder, true, messageLog, monitor);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -149,12 +159,18 @@ public abstract class AbstractLibrarySupportLoader extends AbstractProgramLoader
|
|||
DomainObject domainObject, boolean loadIntoProgram) {
|
||||
List<Option> list =
|
||||
super.getDefaultOptions(provider, loadSpec, domainObject, loadIntoProgram);
|
||||
list.add(new Option(LINK_EXISTING_OPTION_NAME, LINK_EXISTING_OPTION_DEFAULT, Boolean.class,
|
||||
Loader.COMMAND_LINE_ARG_PREFIX + "-linkExistingProjectLibraries"));
|
||||
list.add(new Option(LINK_SEARCH_FOLDER_OPTION_NAME, LINK_SEARCH_FOLDER_OPTION_DEFAULT,
|
||||
String.class, Loader.COMMAND_LINE_ARG_PREFIX + "-projectLibrarySearchFolder"));
|
||||
list.add(new Option(LOCAL_LIBRARY_OPTION_NAME, LOCAL_LIBRARY_OPTION_DEFAULT, Boolean.class,
|
||||
Loader.COMMAND_LINE_ARG_PREFIX + "-loadLocalLibraries"));
|
||||
list.add(new Option(SYSTEM_LIBRARY_OPTION_NAME, SYSTEM_LIBRARY_OPTION_DEFAULT, Boolean.class,
|
||||
Loader.COMMAND_LINE_ARG_PREFIX + "-loadSystemLibraries"));
|
||||
list.add(new Option(DEPTH_OPTION_NAME, DEPTH_OPTION_DEFAULT, Integer.class,
|
||||
Loader.COMMAND_LINE_ARG_PREFIX + "-libraryLoadDepth"));
|
||||
list.add(new Option(LIBRARY_DEST_FOLDER_OPTION_NAME, LIBRARY_DEST_FOLDER_OPTION_DEFAULT,
|
||||
String.class, Loader.COMMAND_LINE_ARG_PREFIX + "-libraryDestinationFolder"));
|
||||
return list;
|
||||
}
|
||||
|
||||
|
@ -164,7 +180,9 @@ public abstract class AbstractLibrarySupportLoader extends AbstractProgramLoader
|
|||
if (options != null) {
|
||||
for (Option option : options) {
|
||||
String name = option.getName();
|
||||
if (name.equals(LOCAL_LIBRARY_OPTION_NAME) || name.equals(SYSTEM_LIBRARY_OPTION_NAME)) {
|
||||
if (name.equals(LINK_EXISTING_OPTION_NAME) ||
|
||||
name.equals(LOCAL_LIBRARY_OPTION_NAME) ||
|
||||
name.equals(SYSTEM_LIBRARY_OPTION_NAME)) {
|
||||
if (!Boolean.class.isAssignableFrom(option.getValueClass())) {
|
||||
return "Invalid type for option: " + name + " - " + option.getValueClass();
|
||||
}
|
||||
|
@ -174,11 +192,66 @@ public abstract class AbstractLibrarySupportLoader extends AbstractProgramLoader
|
|||
return "Invalid type for option: " + name + " - " + option.getValueClass();
|
||||
}
|
||||
}
|
||||
else if (name.equals(LINK_SEARCH_FOLDER_OPTION_NAME) ||
|
||||
name.equals(LIBRARY_DEST_FOLDER_OPTION_NAME)) {
|
||||
if (!String.class.isAssignableFrom(option.getValueClass())) {
|
||||
return "Invalid type for option: " + name + " - " + option.getValueClass();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.validateOptions(provider, loadSpec, options, program);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if existing libraries should be linked
|
||||
*
|
||||
* @param options a {@link List} of {@link Option}s
|
||||
* @return True if existing libraries should be linked; otherwise, false
|
||||
*/
|
||||
protected boolean isLinkExistingLibraries(List<Option> options) {
|
||||
boolean isLinkExistingLibraries = LINK_EXISTING_OPTION_DEFAULT;
|
||||
if (options != null) {
|
||||
for (Option option : options) {
|
||||
String optName = option.getName();
|
||||
if (optName.equals(LINK_EXISTING_OPTION_NAME)) {
|
||||
isLinkExistingLibraries = (Boolean) option.getValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
return isLinkExistingLibraries;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link DomainFolder project folder} to search for existing libraries
|
||||
*
|
||||
* @param programFolder The {@link DomainFolder} that the main program is being loaded into
|
||||
* @param options a {@link List} of {@link Option}s
|
||||
* @return The path of the project folder to search for existing libraries, or null if no
|
||||
* project folders should be searched
|
||||
*/
|
||||
protected DomainFolder getLinkSearchFolder(DomainFolder programFolder,
|
||||
List<Option> options) {
|
||||
if (!shouldSearchAllPaths(options) && !isLinkExistingLibraries(options)) {
|
||||
return null;
|
||||
}
|
||||
String folderPath = LINK_SEARCH_FOLDER_OPTION_DEFAULT;
|
||||
if (options != null) {
|
||||
for (Option option : options) {
|
||||
String optName = option.getName();
|
||||
if (optName.equals(LINK_SEARCH_FOLDER_OPTION_NAME)) {
|
||||
folderPath = (String) option.getValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (folderPath.equals(LINK_SEARCH_FOLDER_OPTION_DEFAULT)) {
|
||||
return programFolder;
|
||||
}
|
||||
|
||||
return programFolder.getProjectData().getFolder(FilenameUtils.separatorsToUnix(folderPath));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if local libraries should be loaded. Local libraries are libraries that live
|
||||
* in the same directory as the imported program.
|
||||
|
@ -239,23 +312,39 @@ public abstract class AbstractLibrarySupportLoader extends AbstractProgramLoader
|
|||
}
|
||||
|
||||
/**
|
||||
* Checks whether or not libraries should be loaded (local or system)
|
||||
* Gets the {@link DomainFolder project folder} to load the libraries into
|
||||
*
|
||||
* @param programFolder The {@link DomainFolder} that the main program is being loaded into
|
||||
* @param options a {@link List} of {@link Option}s
|
||||
* @return True if any libraries should be loaded (local or system); otherwise, false
|
||||
* @return The path of the project folder to load the libraries into
|
||||
*/
|
||||
protected boolean shouldLoadLibraries(List<Option> options) {
|
||||
return (isLoadLocalLibraries(options) || isLoadSystemLibraries(options)) &&
|
||||
getLibraryLoadDepth(options) > 0;
|
||||
protected DomainFolder getLibraryDestinationFolder(DomainFolder programFolder,
|
||||
List<Option> options) {
|
||||
String folderPath = LIBRARY_DEST_FOLDER_OPTION_DEFAULT;
|
||||
if (options != null) {
|
||||
for (Option option : options) {
|
||||
String optName = option.getName();
|
||||
if (optName.equals(LIBRARY_DEST_FOLDER_OPTION_NAME)) {
|
||||
folderPath = (String) option.getValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (folderPath.equals(LIBRARY_DEST_FOLDER_OPTION_DEFAULT)) {
|
||||
return programFolder;
|
||||
}
|
||||
|
||||
return programFolder.getProjectData().getFolder(FilenameUtils.separatorsToUnix(folderPath));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether or not to search for libraries using all possible search paths, regardless
|
||||
* of what options are set
|
||||
*
|
||||
* @param options a {@link List} of {@link Option}s
|
||||
* @return True if all possible search paths should be used, regardless of what options are set
|
||||
*/
|
||||
protected boolean shouldSearchAllPaths() {
|
||||
protected boolean shouldSearchAllPaths(List<Option> options) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -340,7 +429,7 @@ public abstract class AbstractLibrarySupportLoader extends AbstractProgramLoader
|
|||
protected boolean processLibrary(Program library, String libraryName, File libraryFile,
|
||||
ByteProvider provider, LoadSpec loadSpec, List<Option> options, MessageLog log,
|
||||
TaskMonitor monitor) throws IOException, CancelledException {
|
||||
return true;
|
||||
return isLoadLocalLibraries(options) || isLoadSystemLibraries(options);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -361,16 +450,18 @@ public abstract class AbstractLibrarySupportLoader extends AbstractProgramLoader
|
|||
* @throws IOException if there was an IO-related problem loading
|
||||
* @throws CancelledException if the user cancelled the load
|
||||
*/
|
||||
private List<Program> loadLibraries(ByteProvider provider, Program program,
|
||||
private List<LoadedProgram> loadLibraries(ByteProvider provider, Program program,
|
||||
DomainFolder programFolder, LoadSpec desiredLoadSpec, List<Option> options,
|
||||
MessageLog log, Object consumer, List<String> libraryNameList, TaskMonitor monitor)
|
||||
throws CancelledException, IOException {
|
||||
|
||||
List<Program> programList = new ArrayList<>();
|
||||
List<LoadedProgram> loadedPrograms = new ArrayList<>();
|
||||
Set<String> processed = new HashSet<>();
|
||||
Queue<UnprocessedLibrary> unprocessed =
|
||||
createUnprocessedQueue(libraryNameList, getLibraryLoadDepth(options));
|
||||
List<String> searchPaths = getLibrarySearchPaths(provider, options);
|
||||
DomainFolder linkSearchFolder = getLinkSearchFolder(programFolder, options);
|
||||
DomainFolder libraryDestFolder = getLibraryDestinationFolder(programFolder, options);
|
||||
|
||||
while (!unprocessed.isEmpty()) {
|
||||
monitor.checkCanceled();
|
||||
|
@ -380,8 +471,12 @@ public abstract class AbstractLibrarySupportLoader extends AbstractProgramLoader
|
|||
if (depth == 0 || processed.contains(libraryName)) {
|
||||
continue;
|
||||
}
|
||||
processed.add(libraryName);
|
||||
boolean foundLibrary = false;
|
||||
if (findLibrary(libraryName, programFolder) == null) {
|
||||
if (linkSearchFolder != null && findLibrary(libraryName, linkSearchFolder) != null) {
|
||||
log.appendMsg("Library " + libraryName + ": Already loaded ");
|
||||
}
|
||||
else if (!searchPaths.isEmpty()) {
|
||||
String simpleLibraryName = FilenameUtils.getName(libraryName);
|
||||
|
||||
List<File> candidateLibraryFiles =
|
||||
|
@ -399,7 +494,7 @@ public abstract class AbstractLibrarySupportLoader extends AbstractProgramLoader
|
|||
foundLibrary = true;
|
||||
if (processLibrary(library, libraryName, candidateLibraryFile, provider,
|
||||
desiredLoadSpec, options, log, monitor)) {
|
||||
programList.add(library);
|
||||
loadedPrograms.add(new LoadedProgram(library, libraryDestFolder));
|
||||
log.appendMsg(
|
||||
"Library " + libraryName + ": Saving " + candidateLibraryFile);
|
||||
}
|
||||
|
@ -415,14 +510,8 @@ public abstract class AbstractLibrarySupportLoader extends AbstractProgramLoader
|
|||
log.appendMsg("Library " + libraryName + ": Not found");
|
||||
}
|
||||
}
|
||||
else {
|
||||
log.appendMsg("Library " + libraryName + ": Already loaded ");
|
||||
}
|
||||
processed.add(libraryName);
|
||||
}
|
||||
log.appendMsg(
|
||||
"Finished importing referenced libraries for: " + program.getName());
|
||||
return programList;
|
||||
return loadedPrograms;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -548,7 +637,7 @@ public abstract class AbstractLibrarySupportLoader extends AbstractProgramLoader
|
|||
* a {@link ByteProvider} available.
|
||||
*
|
||||
* @param libraryName The name of the library to load
|
||||
* @param programFolder The domain folder where the new program will be stored, if null
|
||||
* @param libraryFolder The domain folder where the new library program will be stored, if null
|
||||
* the program should not be pre-saved. NOTE: the newly imported libraries will not be written
|
||||
* to this folder yet, that is handled in a later follow on step.
|
||||
* @param libraryFile The library file to load
|
||||
|
@ -563,7 +652,7 @@ public abstract class AbstractLibrarySupportLoader extends AbstractProgramLoader
|
|||
* @throws CancelledException if the user cancelled the load operation
|
||||
* @throws IOException if there was an IO-related error during the load
|
||||
*/
|
||||
private Program loadLibrary(String libraryName, DomainFolder programFolder, File libraryFile,
|
||||
private Program loadLibrary(String libraryName, DomainFolder libraryFolder, File libraryFile,
|
||||
LoadSpec desiredLoadSpec, List<String> libraryNameList, List<Option> options,
|
||||
Object consumer, MessageLog log, TaskMonitor monitor)
|
||||
throws CancelledException, IOException {
|
||||
|
@ -579,7 +668,7 @@ public abstract class AbstractLibrarySupportLoader extends AbstractProgramLoader
|
|||
return null;
|
||||
}
|
||||
|
||||
Program library = doLoad(provider, libraryName, programFolder, libLoadSpec,
|
||||
Program library = doLoad(provider, libraryName, libraryFolder, libLoadSpec,
|
||||
libraryNameList, options, consumer, log, monitor);
|
||||
|
||||
if (library == null) {
|
||||
|
@ -668,16 +757,16 @@ public abstract class AbstractLibrarySupportLoader extends AbstractProgramLoader
|
|||
*
|
||||
* @param programs the list of programs to resolve against each other. Programs not saved
|
||||
* to the project will be considered as a valid external library.
|
||||
* @param domainFolder the {@link DomainFolder} folder within which imported libraries will
|
||||
* be searched. This folder will be searched if a library is not found within the
|
||||
* list of programs supplied. If null, only the list of programs will be considered.
|
||||
* @param searchFolder the {@link DomainFolder} which imported libraries will be searched.
|
||||
* This folder will be searched if a library is not found within the list of
|
||||
* programs supplied. If null, only the list of programs will be considered.
|
||||
* @param saveIfModified flag to have this method save any programs it modifies
|
||||
* @param messageLog log for messages.
|
||||
* @param monitor the task monitor
|
||||
* @throws IOException if there was an IO-related problem resolving.
|
||||
* @throws CancelledException if the user cancelled the load.
|
||||
*/
|
||||
private void fixupExternalLibraries(List<Program> programs, DomainFolder domainFolder,
|
||||
private void fixupExternalLibraries(List<Program> programs, DomainFolder searchFolder,
|
||||
boolean saveIfModified, MessageLog messageLog, TaskMonitor monitor)
|
||||
throws CancelledException, IOException {
|
||||
|
||||
|
@ -703,7 +792,7 @@ public abstract class AbstractLibrarySupportLoader extends AbstractProgramLoader
|
|||
monitor.setMessage("Resolving..." + program.getName());
|
||||
int id = program.startTransaction("Resolving external references");
|
||||
try {
|
||||
resolveExternalLibraries(program, progsByName, domainFolder, monitor, messageLog);
|
||||
resolveExternalLibraries(program, progsByName, searchFolder, monitor, messageLog);
|
||||
}
|
||||
finally {
|
||||
program.endTransaction(id, true);
|
||||
|
@ -725,15 +814,15 @@ public abstract class AbstractLibrarySupportLoader extends AbstractProgramLoader
|
|||
* @param progsByName map of recently imported programs to be considered
|
||||
* first when resolving external Libraries. Programs not saved to the project
|
||||
* will be ignored.
|
||||
* @param domainFolder the {@link DomainFolder} folder within which imported libraries will
|
||||
* be searched. This folder will be searched if a library is not found within the
|
||||
* progsByName map. If null, only progsByName will be considered.
|
||||
* @param searchFolder the {@link DomainFolder} which imported libraries will be searched.
|
||||
* This folder will be searched if a library is not found within the list of
|
||||
* programs supplied. If null, only the list of programs will be considered.
|
||||
* @param messageLog log for messages.
|
||||
* @param monitor the task monitor
|
||||
* @throws CancelledException if the user cancelled the load.
|
||||
*/
|
||||
private void resolveExternalLibraries(Program program, Map<String, Program> progsByName,
|
||||
DomainFolder domainFolder, TaskMonitor monitor, MessageLog messageLog)
|
||||
DomainFolder searchFolder, TaskMonitor monitor, MessageLog messageLog)
|
||||
throws CancelledException {
|
||||
ExternalManager extManager = program.getExternalManager();
|
||||
String[] extLibNames = extManager.getExternalLibraryNames();
|
||||
|
@ -745,8 +834,7 @@ public abstract class AbstractLibrarySupportLoader extends AbstractProgramLoader
|
|||
monitor.checkCanceled();
|
||||
try {
|
||||
String externalFileName = FilenameUtils.getName(externalLibName);
|
||||
DomainObject matchingExtProgram =
|
||||
findLibraryWithCaseCorrectSearch(progsByName, externalFileName);
|
||||
DomainObject matchingExtProgram = findLibrary(progsByName, externalFileName);
|
||||
if (matchingExtProgram != null && matchingExtProgram.getDomainFile().exists()) {
|
||||
extManager.setExternalPath(externalLibName,
|
||||
matchingExtProgram.getDomainFile().getPathname(), false);
|
||||
|
@ -754,8 +842,7 @@ public abstract class AbstractLibrarySupportLoader extends AbstractProgramLoader
|
|||
matchingExtProgram.getDomainFile().getPathname() + "]");
|
||||
}
|
||||
else {
|
||||
DomainFile alreadyImportedLib =
|
||||
findLibrary(externalLibName, domainFolder);
|
||||
DomainFile alreadyImportedLib = findLibrary(externalLibName, searchFolder);
|
||||
if (alreadyImportedLib != null) {
|
||||
extManager.setExternalPath(externalLibName,
|
||||
alreadyImportedLib.getPathname(), false);
|
||||
|
@ -806,29 +893,32 @@ public abstract class AbstractLibrarySupportLoader extends AbstractProgramLoader
|
|||
private List<String> getLibrarySearchPaths(ByteProvider provider, List<Option> options) {
|
||||
String parent = getProviderFilePath(provider);
|
||||
List<String> paths = new ArrayList<>();
|
||||
if (shouldSearchAllPaths() || isLoadLocalLibraries(options) && parent != null) {
|
||||
if (shouldSearchAllPaths(options) || isLoadLocalLibraries(options) && parent != null) {
|
||||
paths.add(parent);
|
||||
}
|
||||
if (shouldSearchAllPaths() || isLoadSystemLibraries(options)) {
|
||||
if (shouldSearchAllPaths(options) || isLoadSystemLibraries(options)) {
|
||||
paths.addAll(LibrarySearchPathManager.getLibraryPathsList());
|
||||
}
|
||||
return paths;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Looks up a library in the given {@link Program} map using the appropriate case comparisons
|
||||
* Find the library within the given {@link Map} of {@link Program}s
|
||||
*
|
||||
* @param programsByName The map to search
|
||||
* @param libraryName The library name to lookup
|
||||
* @return A {@link Program} that matches the given library name using appropriate case
|
||||
* comparisons, or null if one was not found
|
||||
* @return The found {@link Program} or null if not found
|
||||
*/
|
||||
private Program findLibraryWithCaseCorrectSearch(Map<String, Program> programsByName,
|
||||
String libraryName) {
|
||||
private Program findLibrary(Map<String, Program> programsByName, String libraryName) {
|
||||
Comparator<String> comparator = getLibraryNameComparator();
|
||||
for (String s : programsByName.keySet()) {
|
||||
if (comparator.compare(libraryName, s) == 0) {
|
||||
return programsByName.get(s);
|
||||
boolean noExtension = FilenameUtils.getExtension(libraryName).equals("");
|
||||
for (String key : programsByName.keySet()) {
|
||||
String candidateName = key;
|
||||
if (isOptionalLibraryFilenameExtensions() && noExtension) {
|
||||
candidateName = FilenameUtils.getBaseName(candidateName);
|
||||
}
|
||||
if (comparator.compare(candidateName, libraryName) == 0) {
|
||||
return programsByName.get(key);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
|
|
@ -23,7 +23,6 @@ import java.util.List;
|
|||
import ghidra.app.util.Option;
|
||||
import ghidra.app.util.bin.ByteProvider;
|
||||
import ghidra.app.util.importer.MessageLog;
|
||||
import ghidra.framework.model.DomainFolder;
|
||||
import ghidra.framework.model.DomainObject;
|
||||
import ghidra.framework.options.Options;
|
||||
import ghidra.program.model.listing.Function;
|
||||
|
@ -69,13 +68,8 @@ public abstract class AbstractOrdinalSupportLoader extends AbstractLibrarySuppor
|
|||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldLoadLibraries(List<Option> options) {
|
||||
return shouldPerformOrdinalLookup(options) || super.shouldLoadLibraries(options);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldSearchAllPaths() {
|
||||
return true;
|
||||
protected boolean shouldSearchAllPaths(List<Option> options) {
|
||||
return shouldPerformOrdinalLookup(options);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -122,15 +116,15 @@ public abstract class AbstractOrdinalSupportLoader extends AbstractLibrarySuppor
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void postLoadProgramFixups(List<Program> loadedPrograms, DomainFolder folder,
|
||||
List<Option> options, MessageLog messageLog, TaskMonitor monitor)
|
||||
throws CancelledException, IOException {
|
||||
protected void postLoadProgramFixups(List<LoadedProgram> loadedPrograms, List<Option> options,
|
||||
MessageLog messageLog, TaskMonitor monitor) throws CancelledException, IOException {
|
||||
monitor.initialize(loadedPrograms.size());
|
||||
|
||||
if (shouldPerformOrdinalLookup(options)) {
|
||||
for (Program p : loadedPrograms) {
|
||||
for (LoadedProgram loadedProgram : loadedPrograms) {
|
||||
monitor.checkCanceled();
|
||||
|
||||
Program p = loadedProgram.program();
|
||||
int id = p.startTransaction("Ordinal fixups");
|
||||
boolean success = false;
|
||||
try {
|
||||
|
@ -148,7 +142,7 @@ public abstract class AbstractOrdinalSupportLoader extends AbstractLibrarySuppor
|
|||
}
|
||||
LibraryLookupTable.cleanup();
|
||||
|
||||
super.postLoadProgramFixups(loadedPrograms, folder, options, messageLog, monitor);
|
||||
super.postLoadProgramFixups(loadedPrograms, options, messageLog, monitor);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -15,11 +15,10 @@
|
|||
*/
|
||||
package ghidra.app.util.opinion;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import ghidra.app.plugin.processors.generic.MemoryBlockDefinition;
|
||||
import ghidra.app.util.Option;
|
||||
|
@ -57,6 +56,14 @@ public abstract class AbstractProgramLoader implements Loader {
|
|||
public static final String APPLY_LABELS_OPTION_NAME = "Apply Processor Defined Labels";
|
||||
public static final String ANCHOR_LABELS_OPTION_NAME = "Anchor Processor Defined Labels";
|
||||
|
||||
/**
|
||||
* A {@link Program} with its associated {@link DomainFolder destination folder}
|
||||
*
|
||||
* @param program The {@link Program}
|
||||
* @param destinationFolder The {@link DomainFolder} where the program will get loaded to
|
||||
*/
|
||||
public record LoadedProgram(Program program, DomainFolder destinationFolder) {/**/}
|
||||
|
||||
/**
|
||||
* Loads program bytes in a particular format as a new {@link Program}. Multiple
|
||||
* {@link Program}s may end up getting created, depending on the nature of the format.
|
||||
|
@ -70,12 +77,12 @@ public abstract class AbstractProgramLoader implements Loader {
|
|||
* @param log The message log.
|
||||
* @param consumer A consumer object for {@link Program}s generated.
|
||||
* @param monitor A cancelable task monitor.
|
||||
* @return A list of loaded {@link Program}s (element 0 corresponds to primary loaded
|
||||
* {@link Program}).
|
||||
* @return A list of {@link LoadedProgram loaded programs} (element 0 corresponds to primary
|
||||
* loaded {@link Program}).
|
||||
* @throws IOException if there was an IO-related problem loading.
|
||||
* @throws CancelledException if the user cancelled the load.
|
||||
*/
|
||||
protected abstract List<Program> loadProgram(ByteProvider provider, String programName,
|
||||
protected abstract List<LoadedProgram> loadProgram(ByteProvider provider, String programName,
|
||||
DomainFolder programFolder, LoadSpec loadSpec, List<Option> options, MessageLog log,
|
||||
Object consumer, TaskMonitor monitor) throws IOException, CancelledException;
|
||||
|
||||
|
@ -115,54 +122,56 @@ public abstract class AbstractProgramLoader implements Loader {
|
|||
return results;
|
||||
}
|
||||
|
||||
List<Program> programs =
|
||||
List<LoadedProgram> loadedPrograms =
|
||||
loadProgram(provider, name, folder, loadSpec, options, messageLog, consumer, monitor);
|
||||
|
||||
boolean success = false;
|
||||
try {
|
||||
monitor.checkCanceled();
|
||||
List<Program> programsToFixup = new ArrayList<>();
|
||||
for (Program loadedProgram : programs) {
|
||||
List<LoadedProgram> programsToFixup = new ArrayList<>();
|
||||
for (LoadedProgram loadedProgram : loadedPrograms) {
|
||||
monitor.checkCanceled();
|
||||
|
||||
applyProcessorLabels(options, loadedProgram);
|
||||
Program program = loadedProgram.program();
|
||||
|
||||
loadedProgram.setEventsEnabled(true);
|
||||
applyProcessorLabels(options, program);
|
||||
|
||||
program.setEventsEnabled(true);
|
||||
|
||||
// TODO: null should not be used as a determinant for saving; don't allow null
|
||||
// folders?
|
||||
if (folder == null) {
|
||||
results.add(loadedProgram);
|
||||
if (loadedProgram.destinationFolder() == null) {
|
||||
results.add(program);
|
||||
continue;
|
||||
}
|
||||
|
||||
String domainFileName = loadedProgram.getName();
|
||||
String domainFileName = program.getName();
|
||||
if (isOverrideMainProgramName()) {
|
||||
// If this is the main imported program, use the given name, otherwise, use the
|
||||
// internal program name. The first program in the list is the main imported program
|
||||
if (loadedProgram == programs.get(0)) {
|
||||
if (program == loadedPrograms.get(0).program()) {
|
||||
domainFileName = name;
|
||||
}
|
||||
}
|
||||
|
||||
if (createProgramFile(loadedProgram, folder, domainFileName, messageLog,
|
||||
monitor)) {
|
||||
results.add(loadedProgram);
|
||||
if (createProgramFile(program, loadedProgram.destinationFolder(), domainFileName,
|
||||
messageLog, monitor)) {
|
||||
results.add(program);
|
||||
programsToFixup.add(loadedProgram);
|
||||
}
|
||||
else {
|
||||
loadedProgram.release(consumer); // some kind of exception happened; see MessageLog
|
||||
program.release(consumer); // some kind of exception happened; see MessageLog
|
||||
}
|
||||
}
|
||||
|
||||
// Subclasses can perform custom post-load fix-ups
|
||||
postLoadProgramFixups(programsToFixup, folder, options, messageLog, monitor);
|
||||
postLoadProgramFixups(programsToFixup, options, messageLog, monitor);
|
||||
|
||||
success = true;
|
||||
}
|
||||
finally {
|
||||
if (!success) {
|
||||
release(programs, consumer);
|
||||
release(loadedPrograms, consumer);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -231,20 +240,18 @@ public abstract class AbstractProgramLoader implements Loader {
|
|||
}
|
||||
|
||||
/**
|
||||
* This gets called after the given list of {@link Program}s is finished loading. It provides
|
||||
* subclasses an opportunity to do follow-on actions to the load.
|
||||
* This gets called after the given list of {@link LoadedProgram programs}s is finished loading.
|
||||
* It provides subclasses an opportunity to do follow-on actions to the load.
|
||||
*
|
||||
* @param loadedPrograms The {@link Program}s that got loaded.
|
||||
* @param folder The folder the programs were loaded to.
|
||||
* @param loadedPrograms The {@link LoadedProgram programs} that got loaded.
|
||||
* @param options The load options.
|
||||
* @param messageLog The message log.
|
||||
* @param monitor A cancelable task monitor.
|
||||
* @throws IOException if there was an IO-related problem loading.
|
||||
* @throws CancelledException if the user cancelled the load.
|
||||
*/
|
||||
protected void postLoadProgramFixups(List<Program> loadedPrograms, DomainFolder folder,
|
||||
List<Option> options, MessageLog messageLog, TaskMonitor monitor)
|
||||
throws CancelledException, IOException {
|
||||
protected void postLoadProgramFixups(List<LoadedProgram> loadedPrograms, List<Option> options,
|
||||
MessageLog messageLog, TaskMonitor monitor) throws CancelledException, IOException {
|
||||
// Default behavior is to do nothing.
|
||||
}
|
||||
|
||||
|
@ -449,14 +456,14 @@ public abstract class AbstractProgramLoader implements Loader {
|
|||
}
|
||||
|
||||
/**
|
||||
* Releases the given consumer from each of the provided {@link DomainObject}s.
|
||||
* Releases the given consumer from each of the provided {@link LoadedProgram}s.
|
||||
*
|
||||
* @param domainObjects A list of {@link DomainObject}s which are no longer being used.
|
||||
* @param loadedPrograms A list of {@link LoadedProgram}s which are no longer being used.
|
||||
* @param consumer The consumer that was marking the {@link DomainObject}s as being used.
|
||||
*/
|
||||
protected final void release(List<? extends DomainObject> domainObjects, Object consumer) {
|
||||
for (DomainObject dobj : domainObjects) {
|
||||
dobj.release(consumer);
|
||||
protected final void release(List<LoadedProgram> loadedPrograms, Object consumer) {
|
||||
for (LoadedProgram loadedProgram : loadedPrograms) {
|
||||
loadedProgram.program().release(consumer);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -269,7 +269,7 @@ public class BinaryLoader extends AbstractProgramLoader {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected List<Program> loadProgram(ByteProvider provider, String programName,
|
||||
protected List<LoadedProgram> loadProgram(ByteProvider provider, String programName,
|
||||
DomainFolder programFolder, LoadSpec loadSpec, List<Option> options, MessageLog log,
|
||||
Object consumer, TaskMonitor monitor) throws IOException, CancelledException {
|
||||
LanguageCompilerSpecPair pair = loadSpec.getLanguageCompilerSpec();
|
||||
|
@ -294,9 +294,9 @@ public class BinaryLoader extends AbstractProgramLoader {
|
|||
prog = null;
|
||||
}
|
||||
}
|
||||
List<Program> results = new ArrayList<Program>();
|
||||
List<LoadedProgram> results = new ArrayList<>();
|
||||
if (prog != null) {
|
||||
results.add(prog);
|
||||
results.add(new LoadedProgram(prog, programFolder));
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
|
|
@ -23,7 +23,6 @@ import ghidra.app.util.bin.ByteProvider;
|
|||
import ghidra.app.util.bin.format.elf.ElfException;
|
||||
import ghidra.app.util.bin.format.elf.ElfHeader;
|
||||
import ghidra.app.util.importer.MessageLog;
|
||||
import ghidra.framework.model.DomainFolder;
|
||||
import ghidra.framework.model.DomainObject;
|
||||
import ghidra.framework.options.Options;
|
||||
import ghidra.program.model.lang.Endian;
|
||||
|
@ -153,13 +152,12 @@ public class ElfLoader extends AbstractLibrarySupportLoader {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void postLoadProgramFixups(List<Program> importedPrograms, DomainFolder importFolder,
|
||||
List<Option> options, MessageLog messageLog, TaskMonitor monitor)
|
||||
throws CancelledException, IOException {
|
||||
super.postLoadProgramFixups(importedPrograms, importFolder, options, messageLog, monitor);
|
||||
protected void postLoadProgramFixups(List<LoadedProgram> loadedPrograms, List<Option> options,
|
||||
MessageLog messageLog, TaskMonitor monitor) throws CancelledException, IOException {
|
||||
super.postLoadProgramFixups(loadedPrograms, options, messageLog, monitor);
|
||||
|
||||
for (Program importedProgram : importedPrograms) {
|
||||
ELFExternalSymbolResolver.fixUnresolvedExternalSymbols(importedProgram, true,
|
||||
for (LoadedProgram loadedProgram : loadedPrograms) {
|
||||
ELFExternalSymbolResolver.fixUnresolvedExternalSymbols(loadedProgram.program(), true,
|
||||
messageLog, monitor);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -142,7 +142,7 @@ public class IntelHexLoader extends AbstractProgramLoader {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected List<Program> loadProgram(ByteProvider provider, String programName,
|
||||
protected List<LoadedProgram> loadProgram(ByteProvider provider, String programName,
|
||||
DomainFolder programFolder, LoadSpec loadSpec, List<Option> options, MessageLog log,
|
||||
Object consumer, TaskMonitor monitor) throws IOException, CancelledException {
|
||||
LanguageCompilerSpecPair pair = loadSpec.getLanguageCompilerSpec();
|
||||
|
@ -165,9 +165,9 @@ public class IntelHexLoader extends AbstractProgramLoader {
|
|||
prog = null;
|
||||
}
|
||||
}
|
||||
List<Program> results = new ArrayList<Program>();
|
||||
List<LoadedProgram> results = new ArrayList<>();
|
||||
if (prog != null) {
|
||||
results.add(prog);
|
||||
results.add(new LoadedProgram(prog, programFolder));
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
|
|
@ -160,7 +160,7 @@ public class MotorolaHexLoader extends AbstractProgramLoader {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected List<Program> loadProgram(ByteProvider provider, String programName,
|
||||
protected List<LoadedProgram> loadProgram(ByteProvider provider, String programName,
|
||||
DomainFolder programFolder, LoadSpec loadSpec, List<Option> options, MessageLog log,
|
||||
Object consumer, TaskMonitor monitor) throws IOException, CancelledException {
|
||||
LanguageCompilerSpecPair pair = loadSpec.getLanguageCompilerSpec();
|
||||
|
@ -183,9 +183,9 @@ public class MotorolaHexLoader extends AbstractProgramLoader {
|
|||
prog = null;
|
||||
}
|
||||
}
|
||||
List<Program> results = new ArrayList<Program>();
|
||||
List<LoadedProgram> results = new ArrayList<>();
|
||||
if (prog != null) {
|
||||
results.add(prog);
|
||||
results.add(new LoadedProgram(prog, programFolder));
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
|
|
@ -177,10 +177,10 @@ public class XmlLoader extends AbstractProgramLoader {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected List<Program> loadProgram(ByteProvider provider, String programName,
|
||||
protected List<LoadedProgram> loadProgram(ByteProvider provider, String programName,
|
||||
DomainFolder programFolder, LoadSpec loadSpec, List<Option> options, MessageLog log,
|
||||
Object consumer, TaskMonitor monitor) throws IOException, CancelledException {
|
||||
List<Program> results = new ArrayList<>();
|
||||
List<LoadedProgram> results = new ArrayList<>();
|
||||
|
||||
LanguageCompilerSpecPair pair = loadSpec.getLanguageCompilerSpec();
|
||||
Language importerLanguage = getLanguageService().getLanguage(pair.languageID);
|
||||
|
@ -212,7 +212,7 @@ public class XmlLoader extends AbstractProgramLoader {
|
|||
}
|
||||
}
|
||||
if (prog != null) {
|
||||
results.add(prog);
|
||||
results.add(new LoadedProgram(prog, programFolder));
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
|
|
@ -64,12 +64,12 @@ public class ApkLoader extends DexLoader {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected List<Program> loadProgram(ByteProvider provider, String programName,
|
||||
protected List<LoadedProgram> loadProgram(ByteProvider provider, String programName,
|
||||
DomainFolder programFolder, LoadSpec loadSpec, List<Option> options, MessageLog log,
|
||||
Object consumer, TaskMonitor monitor) throws CancelledException, IOException {
|
||||
|
||||
boolean success = false;
|
||||
List<Program> programList = new ArrayList<>();
|
||||
List<LoadedProgram> allLoadedPrograms = new ArrayList<>();
|
||||
int dexIndex = 1;//DEX file numbering starts at 1
|
||||
try (ZipFileSystem zipFS = openAPK(provider, monitor)) {
|
||||
while (!monitor.isCancelled()) {
|
||||
|
@ -86,11 +86,11 @@ public class ApkLoader extends DexLoader {
|
|||
try (ByteProvider dexProvider =
|
||||
zipFS.getByteProvider(classesDexFile, monitor)) {
|
||||
// defer to the super class (DexLoader) to actually load the DEX file
|
||||
List<Program> program =
|
||||
List<LoadedProgram> loadedPrograms =
|
||||
super.loadProgram(dexProvider, classesDexFile.getName(), programFolder,
|
||||
loadSpec, options, log, consumer, monitor);
|
||||
|
||||
programList.addAll(program);
|
||||
allLoadedPrograms.addAll(loadedPrograms);
|
||||
}
|
||||
++dexIndex;
|
||||
}
|
||||
|
@ -101,11 +101,11 @@ public class ApkLoader extends DexLoader {
|
|||
}
|
||||
finally {
|
||||
if (!success) {
|
||||
release(programList, consumer);
|
||||
release(allLoadedPrograms, consumer);
|
||||
}
|
||||
}
|
||||
link(programList, log, monitor);
|
||||
return programList;
|
||||
link(allLoadedPrograms.stream().map(e -> e.program()).toList(), log, monitor);
|
||||
return allLoadedPrograms;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -590,9 +590,12 @@ The Headless Analyzer uses the command-line parameters discussed below. See <a h
|
|||
<UL>
|
||||
<LI><typewriter>-loader-applyLabels <true|false></typewriter></LI>
|
||||
<LI><typewriter>-loader-anchorLabels <true|false></typewriter></LI>
|
||||
<LI><typewriter>-loader-linkExistingProjectLibraries <true|false></typewriter></LI>
|
||||
<LI><typewriter>-loader-projectLibrarySearchFolder <project path></typewriter></LI>
|
||||
<LI><typewriter>-loader-loadLocalLibraries <true|false></typewriter></LI>
|
||||
<LI><typewriter>-loader-loadSystemLibraries <true|false></typewriter></LI>
|
||||
<LI><typewriter>-loader-libraryLoadDepth <depth></typewriter></LI>
|
||||
<LI><typewriter>-loader-libraryDestinationFolder <project path></typewriter></LI>
|
||||
<LI><typewriter>-loader-applyRelocations <true|false></typewriter></LI>
|
||||
<LI><typewriter>-loader-imagebase <imagebase<sup>3</sup>></typewriter></LI>
|
||||
<LI><typewriter>-loader-dataImageBase <dataImageBase<sup>4</sup>></typewriter></LI>
|
||||
|
@ -602,9 +605,12 @@ The Headless Analyzer uses the command-line parameters discussed below. See <a h
|
|||
<UL>
|
||||
<LI><typewriter>-loader-applyLabels <true|false></typewriter></LI>
|
||||
<LI><typewriter>-loader-anchorLabels <true|false></typewriter></LI>
|
||||
<LI><typewriter>-loader-linkExistingProjectLibraries <true|false></typewriter></LI>
|
||||
<LI><typewriter>-loader-projectLibrarySearchFolder <project path></typewriter></LI>
|
||||
<LI><typewriter>-loader-loadLocalLibraries <true|false></typewriter></LI>
|
||||
<LI><typewriter>-loader-loadSystemLibraries <true|false></typewriter></LI>
|
||||
<LI><typewriter>-loader-libraryLoadDepth <depth></typewriter></LI>
|
||||
<LI><typewriter>-loader-libraryDestinationFolder <project path></typewriter></LI>
|
||||
<LI><typewriter>-loader-ordinalLookup <true|false></typewriter></LI>
|
||||
<LI><typewriter>-loader-parseCliHeaders <true|false></typewriter></LI>
|
||||
</UL>
|
||||
|
@ -612,9 +618,12 @@ The Headless Analyzer uses the command-line parameters discussed below. See <a h
|
|||
<UL>
|
||||
<LI><typewriter>-loader-applyLabels <true|false></typewriter></LI>
|
||||
<LI><typewriter>-loader-anchorLabels <true|false></typewriter></LI>
|
||||
<LI><typewriter>-loader-linkExistingProjectLibraries <true|false></typewriter></LI>
|
||||
<LI><typewriter>-loader-projectLibrarySearchFolder <project path></typewriter></LI>
|
||||
<LI><typewriter>-loader-loadLocalLibraries <true|false></typewriter></LI>
|
||||
<LI><typewriter>-loader-loadSystemLibraries <true|false></typewriter></LI>
|
||||
<LI><typewriter>-loader-libraryLoadDepth <depth></typewriter></LI>
|
||||
<LI><typewriter>-loader-libraryDestinationFolder <project path></typewriter></LI>
|
||||
<LI><typewriter>-loader-addChainedFixupsRelocations <true|false></typewriter></LI>
|
||||
</UL>
|
||||
</UL>
|
||||
|
|
Loading…
Reference in a new issue