mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-09-28 17:11:11 -09:00
GP-3490: Fixing GhidraDev classpath issues
This commit is contained in:
@@ -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.
|
||||
@@ -30,7 +30,6 @@ import java.util.stream.Collectors;
|
||||
|
||||
import javax.swing.event.ChangeListener;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
@@ -491,24 +490,11 @@ public class ClassSearcher {
|
||||
// jar files will *not* be on the standard classpath, but instead will be on CP_EXT.
|
||||
//
|
||||
List<String> rawPaths = new ArrayList<>();
|
||||
getPropertyPaths(GhidraClassLoader.CP, rawPaths);
|
||||
getPropertyPaths(GhidraClassLoader.CP_EXT, rawPaths);
|
||||
rawPaths.addAll(GhidraClassLoader.getClasspath(GhidraClassLoader.CP));
|
||||
rawPaths.addAll(GhidraClassLoader.getClasspath(GhidraClassLoader.CP_EXT));
|
||||
return canonicalizePaths(rawPaths);
|
||||
}
|
||||
|
||||
private static void getPropertyPaths(String property, List<String> results) {
|
||||
String paths = System.getProperty(property);
|
||||
log.trace("Paths in {}: {}", property, paths);
|
||||
if (StringUtils.isBlank(paths)) {
|
||||
return;
|
||||
}
|
||||
|
||||
StringTokenizer st = new StringTokenizer(paths, File.pathSeparator);
|
||||
while (st.hasMoreTokens()) {
|
||||
results.add(st.nextToken());
|
||||
}
|
||||
}
|
||||
|
||||
private static List<String> canonicalizePaths(Collection<String> paths) {
|
||||
|
||||
//@formatter:off
|
||||
|
||||
@@ -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.
|
||||
@@ -169,28 +169,15 @@ public class GhidraApplicationLayout extends ApplicationLayout {
|
||||
});
|
||||
}
|
||||
|
||||
// Examine the classpath to look for modules outside of the application root directories.
|
||||
// These might exist if Ghidra was launched from an Eclipse project that resides
|
||||
// external to the Ghidra installation.
|
||||
for (String entry : System.getProperty("java.class.path", "").split(File.pathSeparator)) {
|
||||
ResourceFile classpathEntry = new ResourceFile(entry);
|
||||
|
||||
// We only care about directories (skip jars)
|
||||
if (!classpathEntry.isDirectory()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip extensions in an application root directory... already found those.
|
||||
if (FileUtilities.isPathContainedWithin(applicationRootDirs, classpathEntry)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// We are going to assume that the classpath entry is in a subdirectory of the module
|
||||
// directory (i.e., bin/), so only check parent directory for the module.
|
||||
ResourceFile classpathEntryParent = classpathEntry.getParentFile();
|
||||
if (classpathEntryParent != null &&
|
||||
ModuleUtilities.isModuleDirectory(classpathEntryParent)) {
|
||||
moduleRootDirectories.add(classpathEntryParent);
|
||||
// Add external modules defined via a system property. This will typically be used by
|
||||
// user's developing 3rd party modules from something like Eclipse.
|
||||
String externalModules = System.getProperty("ghidra.external.modules", "");
|
||||
if (!externalModules.isBlank()) {
|
||||
for (String path : externalModules.split(File.pathSeparator)) {
|
||||
ResourceFile eclipseProjectDir = new ResourceFile(path);
|
||||
if (ModuleUtilities.isModuleDirectory(eclipseProjectDir)) {
|
||||
moduleRootDirectories.add(eclipseProjectDir);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
@@ -18,8 +18,7 @@ package ghidra;
|
||||
import java.io.File;
|
||||
import java.lang.instrument.Instrumentation;
|
||||
import java.net.*;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
import ghidra.util.Msg;
|
||||
|
||||
@@ -51,6 +50,25 @@ public class GhidraClassLoader extends URLClassLoader {
|
||||
*/
|
||||
public static final String CP_EXT = "java.class.path.ext";
|
||||
|
||||
/**
|
||||
* Gets a {@link List} containing the current classpath referenced by the given property name
|
||||
*
|
||||
* @param propertyName The property name of the classpath to get
|
||||
* @return A {@link List} containing the current classpath referenced by the given property name
|
||||
*/
|
||||
public static List<String> getClasspath(String propertyName) {
|
||||
List<String> result = new ArrayList<>();
|
||||
|
||||
// StringTokenizer is better than split() here because our result list will stay empty if
|
||||
// the classpath is empty
|
||||
StringTokenizer st =
|
||||
new StringTokenizer(System.getProperty(propertyName, ""), File.pathSeparator);
|
||||
while (st.hasMoreTokens()) {
|
||||
result.add(st.nextToken());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to prevent duplicate URL's from being added to the classpath
|
||||
*/
|
||||
|
||||
@@ -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.
|
||||
@@ -150,11 +150,15 @@ public class GhidraLauncher {
|
||||
List<String> classpathList = new ArrayList<>();
|
||||
Map<String, GModule> modules = getOrderedModules(layout);
|
||||
|
||||
// First add any "bin" paths the module might have. These could come from external modules
|
||||
// being developed and passed in via system property if we are in release mode, or they
|
||||
// could be generated for each Ghidra module by Eclipse if we are in development mode.
|
||||
addModuleBinPaths(classpathList, modules);
|
||||
|
||||
if (SystemUtilities.isInDevelopmentMode()) {
|
||||
|
||||
// First add Eclipse's module "bin" paths. If we didn't find any, assume Ghidra was
|
||||
// If we didn't find any "bin" paths and we are in development mode, assume Ghidra was
|
||||
// compiled with Gradle, and add the module jars Gradle built.
|
||||
addModuleBinPaths(classpathList, modules);
|
||||
boolean gradleDevMode = classpathList.isEmpty();
|
||||
if (gradleDevMode) {
|
||||
// Add the module jars Gradle built.
|
||||
@@ -165,22 +169,16 @@ public class GhidraLauncher {
|
||||
else { /* Eclipse dev mode */
|
||||
// Support loading pre-built, jar-based, non-repo extensions in Eclipse dev mode
|
||||
addExtensionJarPaths(classpathList, modules, layout);
|
||||
|
||||
// Eclipse launches the Utility module, so it's already on the classpath. We don't
|
||||
// want to add it a second time, so remove the one we discovered.
|
||||
GModule utilityModule = modules.get("Utility");
|
||||
if (utilityModule == null) {
|
||||
throw new IOException("Failed to find the 'Utility' module!");
|
||||
}
|
||||
classpathList.removeIf(
|
||||
e -> e.startsWith(utilityModule.getModuleRoot().getAbsolutePath()));
|
||||
}
|
||||
|
||||
// In development mode, jars do not live in module directories. Instead, each jar lives
|
||||
// in an external, non-repo location, which is listed in build/libraryDependencies.txt.
|
||||
// In development mode, 3rd party library jars do not live in module directories.
|
||||
// Instead, each jar lives in an external, non-repo location, which is listed in
|
||||
// build/libraryDependencies.txt.
|
||||
addExternalJarPaths(classpathList, layout.getApplicationRootDirs());
|
||||
}
|
||||
else {
|
||||
|
||||
// Release mode is simple. We expect all of Ghidra's modules to be in pre-build jars.
|
||||
addPatchPaths(classpathList, layout.getPatchDir());
|
||||
addModuleJarPaths(classpathList, modules);
|
||||
}
|
||||
@@ -194,8 +192,16 @@ public class GhidraLauncher {
|
||||
// the standard classpath.)
|
||||
setExtensionJarPaths(modules, layout, classpathList);
|
||||
|
||||
classpathList = orderClasspath(classpathList, modules);
|
||||
return classpathList;
|
||||
// Ghidra launches from the Utility module, so it's already on the classpath. We don't
|
||||
// want to add it a second time, so remove the one we discovered.
|
||||
GModule utilityModule = modules.get("Utility");
|
||||
if (utilityModule == null) {
|
||||
throw new IOException("Failed to find the 'Utility' module!");
|
||||
}
|
||||
classpathList.removeIf(
|
||||
e -> e.startsWith(utilityModule.getModuleRoot().getAbsolutePath()));
|
||||
|
||||
return orderClasspath(classpathList, modules);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -265,9 +271,9 @@ public class GhidraLauncher {
|
||||
}
|
||||
|
||||
/**
|
||||
* Add extension module lib jars to the given path list. (This only needed in dev mode to find
|
||||
* any pre-built extensions that have been installed, since we already find extension module
|
||||
* jars in production mode.)
|
||||
* Add extension module lib jars to the given path list. (This is only needed in dev mode to
|
||||
* find any pre-built extensions that have been installed, since we already find extension
|
||||
* module jars in production mode.)
|
||||
*
|
||||
* @param pathList The list of paths to add to.
|
||||
* @param modules The modules to get the jars of.
|
||||
|
||||
@@ -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.
|
||||
@@ -20,6 +20,7 @@ import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
|
||||
import generic.jar.ResourceFile;
|
||||
import ghidra.GhidraApplicationLayout;
|
||||
|
||||
/**
|
||||
* The application properties. Application properties may either be stored on disk, or created
|
||||
@@ -52,8 +53,11 @@ public class ApplicationProperties extends Properties {
|
||||
* Current application versions are:
|
||||
* <ul>
|
||||
* <li>1: Layout used by Ghidra < 11.1</li>
|
||||
* <li>2: Introduced with Ghidra 11.1. Default user settings/cache/temp directories changed,
|
||||
* and XDG environment variables are supported.
|
||||
* <li>2: Introduced with Ghidra 11.1. Default user settings/cache/temp directories changed,
|
||||
* and XDG environment variables are supported.</li>
|
||||
* <li>3: Introduced with Ghidra 11.2. Ghidra no longer finds external modules by examining
|
||||
* the initial classpath. Instead, the "ghidra.external.modules" system property is used
|
||||
* (see {@link GhidraApplicationLayout}).</li>
|
||||
* </ul>
|
||||
*/
|
||||
public static final String APPLICATION_LAYOUT_VERSION_PROPERTY = "application.layout.version";
|
||||
|
||||
Reference in New Issue
Block a user