From d8da07825113c0d8c9021808c3867caf73a166e8 Mon Sep 17 00:00:00 2001 From: Ryan Kurtz Date: Tue, 18 Jun 2019 12:07:56 -0400 Subject: [PATCH] GT-2941: Generic support for moving "fat jar" to the end of the classpath. --- .../src/main/java/ghidra/GhidraLauncher.java | 24 +++++++++++++------ .../main/java/ghidra/framework/GModule.java | 6 +++++ .../utility/module/ModuleManifestFile.java | 19 ++++++++++++--- 3 files changed, 39 insertions(+), 10 deletions(-) diff --git a/Ghidra/Framework/Utility/src/main/java/ghidra/GhidraLauncher.java b/Ghidra/Framework/Utility/src/main/java/ghidra/GhidraLauncher.java index 381dc1ad25..13695ad822 100644 --- a/Ghidra/Framework/Utility/src/main/java/ghidra/GhidraLauncher.java +++ b/Ghidra/Framework/Utility/src/main/java/ghidra/GhidraLauncher.java @@ -17,6 +17,7 @@ package ghidra; import java.io.*; import java.util.*; +import java.util.stream.Collectors; import generic.jar.ResourceFile; import ghidra.framework.GModule; @@ -59,7 +60,7 @@ public class GhidraLauncher { addPatchPaths(classpathList, layout.getApplicationInstallationDir()); addModuleJarPaths(classpathList, layout.getModules()); } - classpathList = orderClasspath(classpathList); + classpathList = orderClasspath(classpathList, layout.getModules()); // Add the classpath to the class loader GhidraClassLoader loader = (GhidraClassLoader) ClassLoader.getSystemClassLoader(); @@ -79,11 +80,11 @@ public class GhidraLauncher { } /** - * Add patch jars to the given path list. This should be done - * first so they take precedence in the classpath. + * Add patch jars to the given path list. This should be done first so they take precedence in + * the classpath. * * @param pathList The list of paths to add to. - * @param appRootDirs The application root directories to search. + * @param installDir The application installation directory. */ private static void addPatchPaths(List pathList, ResourceFile installDir) { ResourceFile patchDir = new ResourceFile(installDir, "Ghidra/patch"); @@ -186,17 +187,26 @@ public class GhidraLauncher { * Updates the list of paths to make sure the order is correct for any class-loading dependencies. * * @param pathList The list of paths to order. + * @param modules The modules on the classpath. * @return A new list with the elements of the original list re-ordered as needed. */ - private static List orderClasspath(List pathList) { + private static List orderClasspath(List pathList, + Map modules) { + + //@formatter:off + Set flatJars = modules + .values() + .stream() + .flatMap(m -> m.getFatJars().stream()) + .collect(Collectors.toSet()); + //@formatter:on List orderedList = new ArrayList(pathList); for (String path : pathList) { - if (path.endsWith("Renoir.jar")) { // Renoir.jar must be after all other jars + if (flatJars.contains(new File(path).getName())) { orderedList.remove(path); orderedList.add(path); - break; } } diff --git a/Ghidra/Framework/Utility/src/main/java/ghidra/framework/GModule.java b/Ghidra/Framework/Utility/src/main/java/ghidra/framework/GModule.java index 6aff9f1084..9cb08aab6e 100644 --- a/Ghidra/Framework/Utility/src/main/java/ghidra/framework/GModule.java +++ b/Ghidra/Framework/Utility/src/main/java/ghidra/framework/GModule.java @@ -43,6 +43,7 @@ public class GModule { private ResourceFile moduleRoot; private List searchRootsByPriority = new ArrayList<>(); private Set dataSearchIgnoreDirs = new HashSet<>(); + private Set fatJars = new HashSet<>(); public GModule(Collection appRoots, ResourceFile moduleRoot) { @@ -67,6 +68,7 @@ public class GModule { try { ModuleManifestFile manifestFile = new ModuleManifestFile(moduleRoot); dataSearchIgnoreDirs = manifestFile.getDataSearchIgnoreDirs(); + fatJars = manifestFile.getFatJars(); } catch (IOException e) { // don't care - if not using moduleManifest to find modules, then we don't @@ -145,6 +147,10 @@ public class GModule { return null; } + public Set getFatJars() { + return fatJars; + } + private void accumulateFilesByExtension(String extension, ResourceFile dir, List accumulator) { ResourceFile[] children = dir.listFiles(); diff --git a/Ghidra/Framework/Utility/src/main/java/utility/module/ModuleManifestFile.java b/Ghidra/Framework/Utility/src/main/java/utility/module/ModuleManifestFile.java index f23dc10adb..6050b52c77 100644 --- a/Ghidra/Framework/Utility/src/main/java/utility/module/ModuleManifestFile.java +++ b/Ghidra/Framework/Utility/src/main/java/utility/module/ModuleManifestFile.java @@ -15,12 +15,11 @@ */ package utility.module; -import generic.jar.ResourceFile; -import ghidra.util.Msg; - import java.io.*; import java.util.*; +import generic.jar.ResourceFile; +import ghidra.util.Msg; import utilities.util.FileUtilities; public class ModuleManifestFile { @@ -32,6 +31,7 @@ public class ModuleManifestFile { private static final String EXCLUDE_FROM_GHIDRA_JAR = "EXCLUDE FROM GHIDRA JAR"; private static final String DATA_SEARCH_IGNORE_DIR = "DATA SEARCH IGNORE DIR:"; private static final String MODULE_DIR_IDENTIFIER = "MODULE DIR:"; + private static final String FAT_JAR = "FAT JAR:"; // private static final String EXTENSION_SUFFIX = "EXTENSION SUFFIX:"; // private static final String REQUIRES_CLASS_SEARCH = "REQUIRES CLASS SEARCH:"; // private static final String OWNER_IDENTIFIER = "MODULE DIR:"; @@ -46,6 +46,7 @@ public class ModuleManifestFile { private Map fileIPMap = new HashMap(); private Set dataSearchIgnoreDirs = new HashSet(); + private Set fatJars = new HashSet<>(); public ModuleManifestFile(File moduleRootDir) throws IOException { this(new ResourceFile(moduleRootDir)); @@ -108,6 +109,9 @@ public class ModuleManifestFile { else if (trimmedLine.startsWith(MODULE_DIR_IDENTIFIER)) { // do nothing for now } + else if (trimmedLine.startsWith(FAT_JAR)) { + processFatJar(trimmedLine); + } else { String message = "Module manifest file error on line " + (lineNumber + 1) + " of file: " + file + @@ -144,6 +148,11 @@ public class ModuleManifestFile { moduleName = line.substring(NAME_IDENTIFIER.length()).trim(); } + private void processFatJar(String line) { + String fatJar = line.substring(FAT_JAR.length()).trim(); + fatJars.add(fatJar); + } + public String getModuleName() { return moduleName; } @@ -151,4 +160,8 @@ public class ModuleManifestFile { public Set getDataSearchIgnoreDirs() { return dataSearchIgnoreDirs; } + + public Set getFatJars() { + return fatJars; + } }