mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 10:49:34 +02:00
GP-706 - Speed up namespace lookup and creation
This commit is contained in:
parent
79fce9b032
commit
ae69ba87d1
35 changed files with 862 additions and 633 deletions
|
@ -17,10 +17,9 @@
|
|||
//@category Examples
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
|
||||
import generic.jar.ApplicationModule;
|
||||
import generic.jar.ResourceFile;
|
||||
import ghidra.app.script.GhidraScript;
|
||||
import ghidra.framework.Application;
|
||||
import ghidra.util.GhidraJarBuilder;
|
||||
|
@ -32,8 +31,7 @@ public class BuildGhidraJarScript extends GhidraScript {
|
|||
|
||||
@Override
|
||||
public void run() throws Exception {
|
||||
GhidraJarBuilder builder =
|
||||
new GhidraJarBuilder(toFiles(Application.getApplicationRootDirectories()));
|
||||
GhidraJarBuilder builder = new GhidraJarBuilder(Application.getApplicationLayout());
|
||||
|
||||
builder.setMainClass("ghidra.JarRun"); // default is ghidra.JarRun, only here if you want
|
||||
// to change it to something else.
|
||||
|
@ -69,12 +67,4 @@ public class BuildGhidraJarScript extends GhidraScript {
|
|||
// uncomment the following line to create a src zip for debugging.
|
||||
// builder.buildSrcZip(new File(installDir, "GhidraSrc.zip"), monitor);
|
||||
}
|
||||
|
||||
private List<File> toFiles(Collection<ResourceFile> resourceFiles) {
|
||||
List<File> fileList = new ArrayList<>();
|
||||
for (ResourceFile resourceFile : resourceFiles) {
|
||||
fileList.add(resourceFile.getFile(true));
|
||||
}
|
||||
return fileList;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,8 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
|||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import docking.ActionContext;
|
||||
import docking.ComponentProvider;
|
||||
import docking.dnd.GenericDataFlavor;
|
||||
|
@ -303,12 +305,9 @@ public class CodeBrowserClipboardProvider extends ByteCopier
|
|||
private Transferable copyAddress() {
|
||||
|
||||
AddressSetView addressSet = getSelectedAddresses();
|
||||
StringBuilder buffy = new StringBuilder();
|
||||
AddressIterator it = addressSet.getAddresses(true);
|
||||
while (it.hasNext()) {
|
||||
buffy.append(it.next()).append('\n');
|
||||
}
|
||||
return createStringTransferable(buffy.toString());
|
||||
String joined = StringUtils.join((Iterator<Address>) it, "\n");
|
||||
return createStringTransferable(joined);
|
||||
}
|
||||
|
||||
protected Transferable copyCode(TaskMonitor monitor) {
|
||||
|
@ -377,8 +376,8 @@ public class CodeBrowserClipboardProvider extends ByteCopier
|
|||
private boolean pasteLabelsComments(Transferable pasteData, boolean pasteLabels,
|
||||
boolean pasteComments) {
|
||||
try {
|
||||
List<?> list = (List<?>) pasteData.getTransferData(
|
||||
CodeUnitInfoTransferable.localDataTypeFlavor);
|
||||
List<?> list =
|
||||
(List<?>) pasteData.getTransferData(CodeUnitInfoTransferable.localDataTypeFlavor);
|
||||
List<CodeUnitInfo> infos = CollectionUtils.asList(list, CodeUnitInfo.class);
|
||||
Command cmd = new CodeUnitInfoPasteCmd(currentLocation.getAddress(), infos, pasteLabels,
|
||||
pasteComments);
|
||||
|
@ -451,8 +450,8 @@ public class CodeBrowserClipboardProvider extends ByteCopier
|
|||
String oldName = symbol.getName();
|
||||
Namespace namespace = symbol.getParentNamespace();
|
||||
Address symbolAddress = symbol.getAddress();
|
||||
RenameLabelCmd cmd = new RenameLabelCmd(symbolAddress, oldName, labelName,
|
||||
namespace, SourceType.USER_DEFINED);
|
||||
RenameLabelCmd cmd = new RenameLabelCmd(symbolAddress, oldName, labelName, namespace,
|
||||
SourceType.USER_DEFINED);
|
||||
return tool.execute(cmd, currentProgram);
|
||||
}
|
||||
|
||||
|
|
|
@ -441,6 +441,7 @@ public abstract class DemangledObject implements Demangled {
|
|||
namespace = program.getGlobalNamespace();
|
||||
}
|
||||
|
||||
SymbolTable symbolTable = program.getSymbolTable();
|
||||
for (String namespaceName : getNamespaceList(typeNamespace)) {
|
||||
|
||||
// TODO - This is compensating for too long templates. We should probably genericize
|
||||
|
@ -448,16 +449,9 @@ public abstract class DemangledObject implements Demangled {
|
|||
// same name is the same class--would that reflect reality?
|
||||
namespaceName = ensureNameLength(namespaceName);
|
||||
|
||||
SymbolTable symbolTable = program.getSymbolTable();
|
||||
|
||||
List<Symbol> symbols = symbolTable.getSymbols(namespaceName, namespace);
|
||||
Symbol namespaceSymbol =
|
||||
symbols.stream().filter(s -> (s.getSymbolType() == SymbolType.NAMESPACE ||
|
||||
s.getSymbolType() == SymbolType.CLASS)).findFirst().orElse(null);
|
||||
if (namespaceSymbol == null) {
|
||||
try {
|
||||
namespace =
|
||||
symbolTable.createNameSpace(namespace, namespaceName, SourceType.IMPORTED);
|
||||
symbolTable.getOrCreateNameSpace(namespace, namespaceName, SourceType.IMPORTED);
|
||||
}
|
||||
catch (DuplicateNameException e) {
|
||||
Msg.error(DemangledObject.class,
|
||||
|
@ -471,22 +465,27 @@ public abstract class DemangledObject implements Demangled {
|
|||
"Failed to create namespace: " + e.getMessage());
|
||||
break;
|
||||
}
|
||||
|
||||
Symbol nsSymbol = namespace.getSymbol();
|
||||
if (!isPermittedNamespaceType(nsSymbol.getSymbolType(), functionPermitted)) {
|
||||
|
||||
String allowedTypes = "SymbolType.CLASS, SymbolType.NAMESPACE";
|
||||
if (functionPermitted) {
|
||||
allowedTypes += ", SymbolType.FUNCTION";
|
||||
}
|
||||
else if (isPermittedNamespaceSymbol(namespaceSymbol, functionPermitted)) {
|
||||
namespace = (Namespace) namespaceSymbol.getObject();
|
||||
}
|
||||
else {
|
||||
|
||||
Msg.error(DemangledObject.class,
|
||||
"Failed to create namespace due to name conflict: " +
|
||||
"Bad namespace type - must be one of: " + allowedTypes +
|
||||
NamespaceUtils.getNamespaceQualifiedName(namespace, namespaceName, false));
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
return namespace;
|
||||
}
|
||||
|
||||
private static boolean isPermittedNamespaceSymbol(Symbol symbol, boolean functionPermitted) {
|
||||
SymbolType symbolType = symbol.getSymbolType();
|
||||
private static boolean isPermittedNamespaceType(SymbolType symbolType,
|
||||
boolean functionPermitted) {
|
||||
if (symbolType == SymbolType.CLASS || symbolType == SymbolType.NAMESPACE) {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -34,8 +34,7 @@ import ghidra.program.model.scalar.Scalar;
|
|||
import ghidra.program.model.symbol.Reference;
|
||||
import ghidra.program.model.symbol.ReferenceIterator;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
import ghidra.util.exception.NotFoundException;
|
||||
import ghidra.util.exception.*;
|
||||
|
||||
public class VarnodeContext implements ProcessorContext {
|
||||
|
||||
|
@ -88,7 +87,7 @@ public class VarnodeContext implements ProcessorContext {
|
|||
this.program = program;
|
||||
|
||||
// make a copy, because we could be making new spaces.
|
||||
this.addrFactory = new OffsetAddressFactory(program.getAddressFactory());
|
||||
this.addrFactory = new OffsetAddressFactory(program);
|
||||
|
||||
BAD_ADDRESS = addrFactory.getAddress(getAddressSpace("BAD_ADDRESS_SPACE"), 0);
|
||||
|
||||
|
@ -1435,8 +1434,24 @@ public class VarnodeContext implements ProcessorContext {
|
|||
|
||||
class OffsetAddressFactory extends DefaultAddressFactory {
|
||||
|
||||
OffsetAddressFactory(AddressFactory baseFactory) {
|
||||
super(filterSpaces(baseFactory.getAllAddressSpaces()));
|
||||
OffsetAddressFactory(Program program) {
|
||||
// We are only calling super with the address spaces from the language first, and then
|
||||
// following up to explicitly add more spaces due to the treatment of memory address
|
||||
// spaces by DefaultAddressFactory when constructed vs. when added later.
|
||||
// If there is more than one memory address space (e.g., TYPE_RAM, TYPE_CODE, or
|
||||
// TYPE_OTHER), then addresses are output with the space name prefix, which we do not want.
|
||||
super(program.getLanguage().getAddressFactory().getAllAddressSpaces(),
|
||||
program.getLanguage().getAddressFactory().getDefaultAddressSpace());
|
||||
for (AddressSpace space : program.getAddressFactory().getAllAddressSpaces()) {
|
||||
if (space.isLoadedMemorySpace() && getAddressSpace(space.getName()) == null) {
|
||||
try {
|
||||
addAddressSpace(space);
|
||||
}
|
||||
catch (DuplicateNameException e) {
|
||||
throw new AssertException("Duplicate name should not occur.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int getNextUniqueID() {
|
||||
|
@ -1466,17 +1481,4 @@ class OffsetAddressFactory extends DefaultAddressFactory {
|
|||
return (type == AddressSpace.TYPE_SYMBOL);
|
||||
}
|
||||
|
||||
private static AddressSpace[] filterSpaces(AddressSpace[] allSpaces) {
|
||||
List<AddressSpace> spaces = new ArrayList<>();
|
||||
for (AddressSpace space : allSpaces) {
|
||||
int type = space.getType();
|
||||
if (type == AddressSpace.TYPE_VARIABLE || type == AddressSpace.TYPE_STACK ||
|
||||
type == AddressSpace.TYPE_EXTERNAL || type == AddressSpace.TYPE_JOIN) {
|
||||
continue;
|
||||
}
|
||||
spaces.add(space);
|
||||
}
|
||||
return spaces.toArray(new AddressSpace[0]);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -25,28 +25,24 @@ import java.util.zip.*;
|
|||
import generic.jar.*;
|
||||
import ghidra.GhidraApplicationLayout;
|
||||
import ghidra.GhidraLaunchable;
|
||||
import ghidra.framework.Application;
|
||||
import ghidra.framework.HeadlessGhidraApplicationConfiguration;
|
||||
import ghidra.framework.*;
|
||||
import ghidra.framework.plugintool.dialog.ExtensionUtils;
|
||||
import ghidra.util.classfinder.ClassFinder;
|
||||
import ghidra.util.classfinder.ClassSearcher;
|
||||
import ghidra.util.exception.AssertException;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
import ghidra.util.task.TaskMonitorAdapter;
|
||||
import utilities.util.FileUtilities;
|
||||
import utility.application.ApplicationLayout;
|
||||
import utility.module.ModuleUtilities;
|
||||
|
||||
public class GhidraJarBuilder implements GhidraLaunchable {
|
||||
|
||||
private static final String ROOT = "_Root/";
|
||||
private static final String ROOT_GHIDRA = "_Root/Ghidra/";
|
||||
private static final String LIBS_FILE_MODULE_KEY = "Module: ";
|
||||
|
||||
// this is set in the buildGhidraJar batch/script files
|
||||
private static final String GHIDRA_DIR = "Ghidra.Install.Root.Dir";
|
||||
private static final String INVOCATION_NAME_PROPERTY = "GhidraJarBuilder.Name";
|
||||
private static HashMap<String, List<String>> libsMap = new HashMap<>();
|
||||
private List<File> rootGhidraDirs = new ArrayList<>();
|
||||
private List<ApplicationModule> allModules;
|
||||
private Set<ApplicationModule> includedModules = new HashSet<>();
|
||||
|
@ -57,19 +53,18 @@ public class GhidraJarBuilder implements GhidraLaunchable {
|
|||
private Pattern extensionPointSuffixPattern;
|
||||
private List<String> extensionPointClasses = new ArrayList<>();
|
||||
private ClassLoader classLoader;
|
||||
private boolean inGradleMode = false;
|
||||
private Set<File> processedJars = new HashSet<>();
|
||||
|
||||
public GhidraJarBuilder() {
|
||||
// Required for GhidraLaunchable
|
||||
}
|
||||
|
||||
public GhidraJarBuilder(List<File> rootDirs) throws IOException {
|
||||
for (File file : rootDirs) {
|
||||
File rgd = file.getCanonicalFile();
|
||||
public GhidraJarBuilder(ApplicationLayout layout) throws IOException {
|
||||
for (ResourceFile file : layout.getApplicationRootDirs()) {
|
||||
File rgd = file.getFile(false).getCanonicalFile();
|
||||
rootGhidraDirs.add(rgd);
|
||||
}
|
||||
allModules = findAllModules();
|
||||
allModules = findAllModules(layout);
|
||||
Collections.sort(allModules);
|
||||
for (ApplicationModule module : allModules) {
|
||||
if (includeByDefault(module)) {
|
||||
|
@ -203,7 +198,7 @@ public class GhidraJarBuilder implements GhidraLaunchable {
|
|||
|
||||
for (ApplicationModule module : moduleList) {
|
||||
writeModuleClassesAndResources(jar, module);
|
||||
if (!excludeHelp && !inGradleMode) {
|
||||
if (!excludeHelp) {
|
||||
writeModuleHelp(jar, module);
|
||||
}
|
||||
}
|
||||
|
@ -360,16 +355,6 @@ public class GhidraJarBuilder implements GhidraLaunchable {
|
|||
private void writeModuleClassesAndResources(Jar jar, ApplicationModule module)
|
||||
throws CancelledException, IOException {
|
||||
|
||||
if (inGradleMode) {
|
||||
File gradleBuildFileForModule =
|
||||
new File(module.getModuleDir(), "build/libs/" + module.getName() + ".jar");
|
||||
processJarFile(jar, gradleBuildFileForModule, module);
|
||||
File gradleBuildFileForGPLModule =
|
||||
new File(module.getModuleDir(), "build/data/lib/" + module.getName() + ".jar");
|
||||
processJarFile(jar, gradleBuildFileForGPLModule, module);
|
||||
processExternalLibs(jar, module);
|
||||
return;
|
||||
}
|
||||
// NOTE: This only works in a distribution where the 3rd party jars live in each
|
||||
// module's libs directory
|
||||
File binDir = new File(module.getModuleDir(), "bin/main");
|
||||
|
@ -380,18 +365,6 @@ public class GhidraJarBuilder implements GhidraLaunchable {
|
|||
processLibDir(jar, module);
|
||||
}
|
||||
|
||||
private void processExternalLibs(Jar jar, ApplicationModule module)
|
||||
throws CancelledException, IOException {
|
||||
List<String> list = libsMap.get(module.getName());
|
||||
if (list == null) {
|
||||
return;
|
||||
}
|
||||
for (String libPath : list) {
|
||||
File file = new File(libPath);
|
||||
processJarFile(jar, file, module);
|
||||
}
|
||||
}
|
||||
|
||||
private void processLibDir(Jar jar, ApplicationModule module)
|
||||
throws CancelledException, IOException {
|
||||
File libDir = new File(module.getModuleDir(), "lib");
|
||||
|
@ -586,16 +559,34 @@ public class GhidraJarBuilder implements GhidraLaunchable {
|
|||
return manifest;
|
||||
}
|
||||
|
||||
private List<ApplicationModule> findAllModules() {
|
||||
private List<ApplicationModule> findAllModules(ApplicationLayout layout) throws IOException {
|
||||
List<ApplicationModule> modules = new ArrayList<>();
|
||||
for (File appRoot : rootGhidraDirs) {
|
||||
findModules(appRoot, appRoot, modules);
|
||||
findModules(appRoot, new File(appRoot, "../GPL"), modules);
|
||||
|
||||
for (GModule module : layout.getModules().values()) {
|
||||
File moduleDir = module.getModuleRoot().getFile(false).getCanonicalFile();
|
||||
File rootDir = getModuleRootDir(moduleDir);
|
||||
modules.add(new ApplicationModule(rootDir, moduleDir));
|
||||
}
|
||||
|
||||
return modules;
|
||||
}
|
||||
|
||||
private File getModuleRootDir(File moduleDir) {
|
||||
// Look in GPL directories too
|
||||
List<File> rootDirs = new ArrayList<>(rootGhidraDirs);
|
||||
for (File rootDir : rootGhidraDirs) {
|
||||
rootDirs.add(new File(rootDir.getParentFile(), "GPL"));
|
||||
}
|
||||
|
||||
// Check each root directory to see if it contains the module
|
||||
for (File rootDir : rootDirs) {
|
||||
if (FileUtilities.isPathContainedWithin(rootDir, moduleDir)) {
|
||||
return rootDir;
|
||||
}
|
||||
}
|
||||
throw new AssertException("Module root directory could not be determined: " + moduleDir);
|
||||
}
|
||||
|
||||
private String getPathFromRoot(String rootPath, File file) {
|
||||
String filePath = file.getAbsolutePath();
|
||||
if (!filePath.startsWith(rootPath)) {
|
||||
|
@ -604,23 +595,6 @@ public class GhidraJarBuilder implements GhidraLaunchable {
|
|||
return filePath.substring(rootPath.length() + 1);
|
||||
}
|
||||
|
||||
private void findModules(File rootAppDir, File dir, List<ApplicationModule> modules) {
|
||||
File moduleManifest = new File(dir, "Module.manifest");
|
||||
if (moduleManifest.exists()) {
|
||||
ApplicationModule module = new ApplicationModule(rootAppDir, dir);
|
||||
modules.add(module);
|
||||
return; // modules can't live in other modules;
|
||||
}
|
||||
File[] listFiles = dir.listFiles();
|
||||
if (listFiles != null) {
|
||||
for (File file : listFiles) {
|
||||
if (file.isDirectory()) {
|
||||
findModules(rootAppDir, file, modules);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void checkExtensionPointClass(String path, InputStream inputStream) {
|
||||
// remove .class
|
||||
path = path.substring(0, path.length() - 6);
|
||||
|
@ -931,44 +905,15 @@ public class GhidraJarBuilder implements GhidraLaunchable {
|
|||
}
|
||||
}
|
||||
|
||||
private static void parseLibsFile(String libsFilePath) {
|
||||
try {
|
||||
List<String> lines = FileUtilities.getLines(new File(libsFilePath));
|
||||
|
||||
List<String> libPaths = new ArrayList<>();
|
||||
String currentModule = null;
|
||||
for (String line : lines) {
|
||||
if (line.startsWith(LIBS_FILE_MODULE_KEY)) {
|
||||
if (currentModule != null) {
|
||||
libsMap.put(currentModule, libPaths);
|
||||
libPaths = new ArrayList<>();
|
||||
}
|
||||
currentModule = line.substring(LIBS_FILE_MODULE_KEY.length()).trim();
|
||||
}
|
||||
else {
|
||||
libPaths.add(line.trim());
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
System.err.println("Could not read lib paths file: " + libsFilePath);
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
private static void usage(String[] args) {
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
System.err.println("arg " + i + ": " + args[i]);
|
||||
}
|
||||
String invocationName = System.getProperty(INVOCATION_NAME_PROPERTY);
|
||||
String property = System.getProperty(GHIDRA_DIR);
|
||||
|
||||
StringBuffer buf = new StringBuffer();
|
||||
buf.append("\nUsage: ");
|
||||
buf.append(invocationName != null ? invocationName : "GhidraJarBuilder ");
|
||||
if (property == null) {
|
||||
buf.append("<Installation Root Directory> [<Installation Root Directory> ...] ");
|
||||
}
|
||||
buf.append(invocationName != null ? invocationName : "GhidraJarBuilder");
|
||||
buf.append(
|
||||
" [-output <output file>] [-srczip <src zip output file>] [-bin <compiled classes dir>] [-main <main-class>]\n");
|
||||
System.err.println(buf.toString());
|
||||
|
@ -992,17 +937,10 @@ public class GhidraJarBuilder implements GhidraLaunchable {
|
|||
usage(args);
|
||||
}
|
||||
|
||||
List<File> ghidraDirs = new ArrayList<>();
|
||||
File outputFile = null;
|
||||
File srczip = null;
|
||||
File extraBinDir = null;
|
||||
String mainClassArg = null;
|
||||
boolean usingGradle = false;
|
||||
|
||||
String property = System.getProperty(GHIDRA_DIR);
|
||||
if (property != null) {
|
||||
ghidraDirs.add(new File(property));
|
||||
}
|
||||
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
String arg = args[i];
|
||||
|
@ -1030,28 +968,14 @@ public class GhidraJarBuilder implements GhidraLaunchable {
|
|||
}
|
||||
mainClassArg = args[++i];
|
||||
}
|
||||
else if (arg.equals("-gradle")) {
|
||||
if (i == args.length - 1) {
|
||||
usage(args);
|
||||
}
|
||||
usingGradle = true;
|
||||
parseLibsFile(args[++i]);
|
||||
}
|
||||
else if (arg.startsWith("-")) {
|
||||
usage(args);
|
||||
}
|
||||
else {
|
||||
ghidraDirs.add(new File(arg));
|
||||
}
|
||||
}
|
||||
if (ghidraDirs.isEmpty()) {
|
||||
usage(args);
|
||||
}
|
||||
}
|
||||
if (outputFile == null) {
|
||||
outputFile = new File("ghidra.jar");
|
||||
}
|
||||
|
||||
System.out.println("Ghidra dirs = " + ghidraDirs);
|
||||
System.out.println("Output file = " + outputFile);
|
||||
if (srczip != null) {
|
||||
System.out.println("Source Zip File = " + srczip);
|
||||
|
@ -1061,13 +985,10 @@ public class GhidraJarBuilder implements GhidraLaunchable {
|
|||
}
|
||||
|
||||
try {
|
||||
GhidraJarBuilder builder = new GhidraJarBuilder(ghidraDirs);
|
||||
GhidraJarBuilder builder = new GhidraJarBuilder(layout);
|
||||
if (mainClassArg != null) {
|
||||
builder.setMainClass(mainClassArg);
|
||||
}
|
||||
if (usingGradle) {
|
||||
builder.setGradleMode();
|
||||
}
|
||||
builder.addExcludedFileExtension(".pdf");
|
||||
|
||||
// builder.addExcludedFileExtension(".htm");
|
||||
|
@ -1082,10 +1003,10 @@ public class GhidraJarBuilder implements GhidraLaunchable {
|
|||
System.out.println("Exclude " + module.getName());
|
||||
}
|
||||
|
||||
builder.buildJar(outputFile, extraBinDir, TaskMonitorAdapter.DUMMY_MONITOR);
|
||||
builder.buildJar(outputFile, extraBinDir, TaskMonitor.DUMMY);
|
||||
|
||||
if (srczip != null) {
|
||||
builder.buildSrcZip(srczip, TaskMonitorAdapter.DUMMY_MONITOR);
|
||||
builder.buildSrcZip(srczip, TaskMonitor.DUMMY);
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
|
@ -1099,8 +1020,4 @@ public class GhidraJarBuilder implements GhidraLaunchable {
|
|||
return new File(ghidraRootDir, "application.properties");
|
||||
}
|
||||
|
||||
private void setGradleMode() {
|
||||
inGradleMode = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/* ###
|
||||
* IP: Apache License 2.0
|
||||
*
|
||||
*/
|
||||
/***
|
||||
* This is fix for a bug found in the Felix Framework:
|
||||
*
|
||||
* https://issues.apache.org/jira/browse/FELIX-6297
|
||||
|
@ -9,8 +10,8 @@
|
|||
*
|
||||
* THIS FILE SHOULD BE REMOVED WHEN THE ISSUE IS ADDRESSED.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
***
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
|
@ -30,24 +31,15 @@
|
|||
*/
|
||||
package org.apache.felix.framework.util;
|
||||
|
||||
import org.apache.felix.framework.cache.Content;
|
||||
import org.osgi.framework.Version;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.jar.Attributes;
|
||||
import java.util.*;
|
||||
import java.util.jar.Manifest;
|
||||
|
||||
import org.apache.felix.framework.cache.Content;
|
||||
import org.osgi.framework.Version;
|
||||
|
||||
public class MultiReleaseContent implements Content
|
||||
{
|
||||
private final Content m_content;
|
||||
|
|
|
@ -840,6 +840,22 @@
|
|||
location when zooming from the middle-mouse. The default for this option is off, which
|
||||
triggers zoom to work from the center of the graph, regardless of the mouse location.</P>
|
||||
|
||||
<P>The <B>View Settings</B> option describes how the graph will be zoomed when it is first
|
||||
loaded. The values are:</P>
|
||||
|
||||
<UL>
|
||||
<LI><B>Start Fully Zoomed Out</B> - always start fully zoomed out so that the entire
|
||||
graph can be seen.</LI>
|
||||
|
||||
<LI><B>Start Fully Zoomed In/B> - always start fully zoomed in on the vertex containing
|
||||
the current location.</LI>
|
||||
|
||||
<LI><B>Remember User Settings</B> - keep the zoom level where the user previously left
|
||||
it.</LI>
|
||||
</UL>
|
||||
<BR>
|
||||
<BR>
|
||||
|
||||
<P>There are various edge color and highlight color options available to change. The
|
||||
highlight colors are those to be used when the flow animations take place.</P>
|
||||
</BLOCKQUOTE>
|
||||
|
|
|
@ -50,6 +50,13 @@
|
|||
</P>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<BLOCKQUOTE>
|
||||
<P>The <B>Use Dim Return Edges</B> option makes default code block return flow edges
|
||||
lighter than conditional edges. This makes it easier for users to scan the
|
||||
graph and ignore return flows.
|
||||
</P>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
</BLOCKQUOTE>
|
||||
|
||||
|
||||
|
|
|
@ -185,8 +185,8 @@ public class FunctionGraphOptions extends VisualGraphOptions {
|
|||
options.registerOption(SCROLL_WHEEL_PANS_KEY, getScrollWheelPans(), help,
|
||||
SCROLL_WHEEL_PANS_DESCRIPTION);
|
||||
|
||||
options.registerOption(GRAPH_BACKGROUND_COLOR_KEY, DEFAULT_GRAPH_BACKGROUND_COLOR,
|
||||
help, GRAPH_BACKGROUND_COLOR_DESCRPTION);
|
||||
options.registerOption(GRAPH_BACKGROUND_COLOR_KEY, DEFAULT_GRAPH_BACKGROUND_COLOR, help,
|
||||
GRAPH_BACKGROUND_COLOR_DESCRPTION);
|
||||
|
||||
options.registerOption(DEFAULT_VERTEX_BACKGROUND_COLOR_KEY, DEFAULT_VERTEX_BACKGROUND_COLOR,
|
||||
help, DEFAULT_VERTEX_BACKGROUND_COLOR_DESCRPTION);
|
||||
|
|
|
@ -31,7 +31,12 @@ public class DNLayoutOptions implements FGLayoutOptions {
|
|||
"edges should be routed around any intersecting vertex. When toggled off, edges will " +
|
||||
"pass through any intersecting vertices.";
|
||||
|
||||
private static final String DIM_RETURN_EDGES_KEY = "Use Dim Return Edges";
|
||||
private static final String DIM_RETURN_EDGES_DESCRIPTION =
|
||||
"Signals to lighten the default return edges.";
|
||||
|
||||
private boolean useEdgeRoutingAroundVertices;
|
||||
private boolean useDimmedReturnEdges = true;
|
||||
|
||||
@Override
|
||||
public void registerOptions(Options options) {
|
||||
|
@ -40,21 +45,32 @@ public class DNLayoutOptions implements FGLayoutOptions {
|
|||
|
||||
options.registerOption(USE_EDGE_ROUTING_AROUND_VERTICES_KEY, useEdgeRoutingAroundVertices,
|
||||
help, USE_EDGE_ROUTING_AROUND_VERTICES_DESCRIPTION);
|
||||
|
||||
options.registerOption(DIM_RETURN_EDGES_KEY, useDimmedReturnEdges, help,
|
||||
DIM_RETURN_EDGES_DESCRIPTION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadOptions(Options options) {
|
||||
useEdgeRoutingAroundVertices =
|
||||
options.getBoolean(USE_EDGE_ROUTING_AROUND_VERTICES_KEY, useEdgeRoutingAroundVertices);
|
||||
|
||||
useDimmedReturnEdges = options.getBoolean(DIM_RETURN_EDGES_KEY, useDimmedReturnEdges);
|
||||
|
||||
}
|
||||
|
||||
public boolean useEdgeRoutingAroundVertices() {
|
||||
return useEdgeRoutingAroundVertices;
|
||||
}
|
||||
|
||||
public boolean useDimmedReturnEdges() {
|
||||
return useDimmedReturnEdges;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean optionChangeRequiresRelayout(String optionName) {
|
||||
// format: 'Nested Code Layout.Route Edges....'
|
||||
return optionName.endsWith(USE_EDGE_ROUTING_AROUND_VERTICES_KEY);
|
||||
return optionName.endsWith(USE_EDGE_ROUTING_AROUND_VERTICES_KEY) ||
|
||||
optionName.endsWith(DIM_RETURN_EDGES_KEY);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ import ghidra.app.plugin.core.functiongraph.graph.jung.renderer.DNLArticulatedEd
|
|||
import ghidra.app.plugin.core.functiongraph.graph.vertex.FGVertex;
|
||||
import ghidra.app.plugin.core.functiongraph.graph.vertex.GroupedFunctionGraphVertex;
|
||||
import ghidra.graph.VisualGraph;
|
||||
import ghidra.graph.viewer.GraphViewerUtils;
|
||||
import ghidra.graph.viewer.layout.*;
|
||||
import ghidra.graph.viewer.vertex.VisualGraphVertexShapeTransformer;
|
||||
import ghidra.program.model.address.Address;
|
||||
|
@ -262,11 +263,8 @@ public class DecompilerNestedLayout extends AbstractFGLayout {
|
|||
DecompilerBlock loop = block.getParentLoop();
|
||||
|
||||
if (loop != null) {
|
||||
Set<FGVertex> vertices = loop.getVertices();
|
||||
|
||||
Column outermostCol = getOutermostCol(layoutToGridMap, vertices);
|
||||
Column loopEndColumn = layoutToGridMap.nextColumn(outermostCol);
|
||||
List<Point2D> articulations = routeLoopEdge(start, end, loopEndColumn);
|
||||
List<Point2D> articulations =
|
||||
routeUpwardLoop(layoutToGridMap, vertex2dFactory, start, end, loop);
|
||||
newEdgeArticulations.put(e, articulations);
|
||||
continue;
|
||||
}
|
||||
|
@ -331,6 +329,70 @@ public class DecompilerNestedLayout extends AbstractFGLayout {
|
|||
return newEdgeArticulations;
|
||||
}
|
||||
|
||||
private List<Point2D> routeUpwardLoop(LayoutLocationMap<FGVertex, FGEdge> layoutToGridMap,
|
||||
Vertex2dFactory vertex2dFactory, Vertex2d start, Vertex2d end, DecompilerBlock loop) {
|
||||
Set<FGVertex> loopVertices = loop.getVertices();
|
||||
FGVertex rightmostLoopVertex =
|
||||
getRightmostVertex(layoutToGridMap, vertex2dFactory, loopVertices);
|
||||
|
||||
int startRow = start.rowIndex;
|
||||
int endRow = end.rowIndex;
|
||||
int startColumn = Math.min(start.columnIndex, end.columnIndex);
|
||||
int endColumn = Math.max(start.columnIndex, end.columnIndex);
|
||||
|
||||
Column rightmostLoopColumn = layoutToGridMap.col(rightmostLoopVertex);
|
||||
endColumn = Math.max(endColumn, rightmostLoopColumn.index);
|
||||
|
||||
// Look for any vertices that are no part of the loop, but are placed inside
|
||||
// of the loop bounds. This can happen in a graph when the decompiler uses
|
||||
// goto statements. Use the loop's rightmost vertex to establish the loops
|
||||
// right edge and then use that to check for any stray non-loop vertices.
|
||||
List<Vertex2d> interlopers =
|
||||
getVerticesInBounds(vertex2dFactory, startRow, endRow, startColumn, endColumn);
|
||||
|
||||
// place the right x position to the right of the rightmost vertex, not
|
||||
// extending past the next column
|
||||
FGVertex rightmostVertex = getRightmostVertex(interlopers);
|
||||
Column rightmostColumn = layoutToGridMap.col(rightmostVertex);
|
||||
Column nextColumn = layoutToGridMap.nextColumn(rightmostColumn);
|
||||
Vertex2d rightmostV2d = vertex2dFactory.get(rightmostVertex);
|
||||
|
||||
// the padding used for these two lines is somewhat arbitrary and may be changed
|
||||
double rightSide = rightmostV2d.getRight() + GraphViewerUtils.EXTRA_LAYOUT_COLUMN_SPACING;
|
||||
double x = Math.min(rightSide,
|
||||
nextColumn.x - GraphViewerUtils.EXTRA_LAYOUT_COLUMN_SPACING_CONDENSED);
|
||||
|
||||
List<Point2D> articulations = routeLoopEdge(start, end, x);
|
||||
return articulations;
|
||||
}
|
||||
|
||||
private List<Vertex2d> getVerticesInBounds(Vertex2dFactory vertex2dFactory, int startRow,
|
||||
int endRow, int startColumn, int endColumn) {
|
||||
|
||||
if (startRow > endRow) { // going upwards
|
||||
int temp = endRow;
|
||||
endRow = startRow;
|
||||
startRow = temp;
|
||||
}
|
||||
|
||||
List<Vertex2d> toCheck = new LinkedList<>();
|
||||
for (int row = startRow; row < endRow + 1; row++) {
|
||||
|
||||
for (int col = startColumn; col < endColumn + 1; col++) {
|
||||
|
||||
// assume any other vertex in our column can clip (it will not clip when
|
||||
// the 'spacing' above pushes the edge away from this column, like for
|
||||
// large row delta values)
|
||||
Vertex2d otherVertex = vertex2dFactory.get(row, col);
|
||||
if (otherVertex != null) {
|
||||
toCheck.add(otherVertex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return toCheck;
|
||||
}
|
||||
|
||||
private void routeToTheRightGoingUpwards(Vertex2d start, Vertex2d end,
|
||||
Vertex2dFactory vertex2dFactory, List<Point2D> articulations) {
|
||||
|
||||
|
@ -347,11 +409,16 @@ public class DecompilerNestedLayout extends AbstractFGLayout {
|
|||
}
|
||||
int distanceSpacing = delta * multiplier;
|
||||
|
||||
// Condensing is when the graph will pull nodes closer together on the x axis to
|
||||
// reduce whitespace and make the entire graph easier to see. In this case, update
|
||||
// the offset to avoid running into the moved vertices.
|
||||
|
||||
// Condensing Note: we have guilty knowledge that our parent class my condense the
|
||||
// vertices and edges towards the center of the graph after we calculate positions.
|
||||
// To prevent the edges from moving to far behind the vertices, we will compensate a
|
||||
// bit for that effect using this offset value. The getEdgeOffset() method is
|
||||
// updated for the condense factor.
|
||||
|
||||
int exaggerationFactor = 1;
|
||||
if (isCondensedLayout()) {
|
||||
exaggerationFactor = 2; // determined by trial-and-error; can be made into an option
|
||||
|
@ -556,19 +623,6 @@ public class DecompilerNestedLayout extends AbstractFGLayout {
|
|||
private void routeAroundColumnVertices(Vertex2d start, Vertex2d end,
|
||||
Vertex2dFactory vertex2dFactory, List<Point2D> articulations, double edgeX) {
|
||||
|
||||
Column column = vertex2dFactory.getColumn(edgeX);
|
||||
int columnIndex = 0;
|
||||
if (column != null) {
|
||||
// a null column happens with a negative x value that is outside of any column
|
||||
columnIndex = column.index;
|
||||
}
|
||||
|
||||
routeAroundColumnVertices(start, end, columnIndex, vertex2dFactory, articulations, edgeX);
|
||||
}
|
||||
|
||||
private void routeAroundColumnVertices(Vertex2d start, Vertex2d end, int column,
|
||||
Vertex2dFactory vertex2dFactory, List<Point2D> articulations, double edgeX) {
|
||||
|
||||
if (useSimpleRouting()) {
|
||||
return;
|
||||
}
|
||||
|
@ -582,16 +636,36 @@ public class DecompilerNestedLayout extends AbstractFGLayout {
|
|||
startRow = end.rowIndex;
|
||||
}
|
||||
|
||||
int startColumn = Math.min(start.columnIndex, end.columnIndex);
|
||||
int endColumn = Math.max(start.columnIndex, end.columnIndex);
|
||||
if (goingDown) {
|
||||
endRow -= 1;
|
||||
endColumn -= 1;
|
||||
|
||||
if (start.columnIndex <= end.columnIndex) {
|
||||
startRow += 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// going up we swing out to the right; grab the column that is out to the right
|
||||
Column rightColumn = vertex2dFactory.getColumn(edgeX);
|
||||
endColumn = rightColumn.index;
|
||||
}
|
||||
|
||||
List<Vertex2d> toCheck = new LinkedList<>();
|
||||
for (int row = startRow + 1; row < endRow; row++) {
|
||||
for (int row = startRow; row < endRow + 1; row++) {
|
||||
|
||||
for (int col = startColumn; col < endColumn + 1; col++) {
|
||||
|
||||
// assume any other vertex in our column can clip (it will not clip when
|
||||
// the 'spacing' above pushes the edge away from this column, like for
|
||||
// large row delta values)
|
||||
Vertex2d otherVertex = vertex2dFactory.get(row, column);
|
||||
Vertex2d otherVertex = vertex2dFactory.get(row, col);
|
||||
if (otherVertex != null) {
|
||||
toCheck.add(otherVertex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// always process the vertices from the start vertex so that the articulation adjustments
|
||||
// are correct
|
||||
|
@ -605,11 +679,16 @@ public class DecompilerNestedLayout extends AbstractFGLayout {
|
|||
int padding = VERTEX_TO_EDGE_AVOIDANCE_PADDING;
|
||||
int distanceSpacing = padding + delta; // adding the delta makes overlap less likely
|
||||
|
||||
// Condensing is when the graph will pull nodes closer together on the x axis to
|
||||
// reduce whitespace and make the entire graph easier to see. In this case, update
|
||||
// the offset to avoid running into the moved vertices.
|
||||
|
||||
// Condensing Note: we have guilty knowledge that our parent class my condense the
|
||||
// vertices and edges towards the center of the graph after we calculate positions.
|
||||
// To prevent the edges from moving to far behind the vertices, we will compensate a
|
||||
// bit for that effect using this offset value. The getEdgeOffset() method is
|
||||
// updated for the condense factor.
|
||||
|
||||
int vertexToEdgeOffset = otherVertex.getEdgeOffset();
|
||||
int exaggerationFactor = 1;
|
||||
if (isCondensedLayout()) {
|
||||
|
@ -696,15 +775,11 @@ public class DecompilerNestedLayout extends AbstractFGLayout {
|
|||
return !getLayoutOptions().useEdgeRoutingAroundVertices();
|
||||
}
|
||||
|
||||
private List<Point2D> routeLoopEdge(Vertex2d start, Vertex2d end, Column loopEndColumn) {
|
||||
private List<Point2D> routeLoopEdge(Vertex2d start, Vertex2d end, double x) {
|
||||
|
||||
// going backwards
|
||||
List<Point2D> articulations = new ArrayList<>();
|
||||
|
||||
// loop first point - same y coord as the vertex; x is the middle of the next col
|
||||
int halfWidth = loopEndColumn.getPaddedWidth(isCondensedLayout()) >> 1;
|
||||
double x = loopEndColumn.x + halfWidth; // middle of the column
|
||||
|
||||
int startRow = start.rowIndex;
|
||||
int endRow = end.rowIndex;
|
||||
if (startRow > endRow) { // going upwards
|
||||
|
@ -733,27 +808,47 @@ public class DecompilerNestedLayout extends AbstractFGLayout {
|
|||
|
||||
private void lighten(FGEdge e) {
|
||||
|
||||
if (!getLayoutOptions().useDimmedReturnEdges()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// assumption: edges that move to the left in this layout are return flows that happen
|
||||
// after the code block has been executed. We dim those a bit so that they
|
||||
// produce less clutter.
|
||||
e.setDefaultAlpha(.25);
|
||||
}
|
||||
|
||||
private Column getOutermostCol(LayoutLocationMap<FGVertex, FGEdge> layoutLocations,
|
||||
Set<FGVertex> vertices) {
|
||||
private FGVertex getRightmostVertex(LayoutLocationMap<FGVertex, FGEdge> layoutLocations,
|
||||
Vertex2dFactory vertex2dFactory, Set<FGVertex> vertices) {
|
||||
|
||||
Column outermost = null;
|
||||
List<Vertex2d> points = new ArrayList<>();
|
||||
for (FGVertex v : vertices) {
|
||||
Column col = layoutLocations.col(v);
|
||||
if (outermost == null) {
|
||||
outermost = col;
|
||||
Vertex2d v2d = vertex2dFactory.get(v);
|
||||
points.add(v2d);
|
||||
}
|
||||
|
||||
FGVertex v = getRightmostVertex(points);
|
||||
return v;
|
||||
}
|
||||
|
||||
private FGVertex getRightmostVertex(Collection<Vertex2d> points) {
|
||||
|
||||
Vertex2d rightmost = null;
|
||||
for (Vertex2d v2d : points) {
|
||||
if (rightmost == null) {
|
||||
rightmost = v2d;
|
||||
}
|
||||
else {
|
||||
// the rightmost is that which extends furthest to the right
|
||||
double current = rightmost.getRight();
|
||||
double other = v2d.getRight();
|
||||
if (other > current) {
|
||||
rightmost = v2d;
|
||||
}
|
||||
else if (col.x > outermost.x) {
|
||||
outermost = col;
|
||||
}
|
||||
}
|
||||
|
||||
return outermost;
|
||||
return rightmost.v;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -840,8 +935,11 @@ public class DecompilerNestedLayout extends AbstractFGLayout {
|
|||
BlockCopy copy = (BlockCopy) child;
|
||||
|
||||
StringBuilder buffy = new StringBuilder();
|
||||
buffy.append(printDepth(depth, depth + 1)).append(' ').append(ID).append(
|
||||
" plain - ").append(copy.getRef());
|
||||
buffy.append(printDepth(depth, depth + 1))
|
||||
.append(' ')
|
||||
.append(ID)
|
||||
.append(" plain - ")
|
||||
.append(copy.getRef());
|
||||
|
||||
debug(buffy.toString());
|
||||
}
|
||||
|
@ -1207,8 +1305,7 @@ public class DecompilerNestedLayout extends AbstractFGLayout {
|
|||
|
||||
int row = startRow;
|
||||
|
||||
for (int i = 0; i < allChildren.size(); i++) {
|
||||
DecompilerBlock block = allChildren.get(i);
|
||||
for (DecompilerBlock block : allChildren) {
|
||||
if (block instanceof DecompilerBlockGraph) {
|
||||
row = ((DecompilerBlockGraph) block).setRows(row);
|
||||
}
|
||||
|
@ -1229,8 +1326,7 @@ public class DecompilerNestedLayout extends AbstractFGLayout {
|
|||
String getChildrenString(int depth) {
|
||||
StringBuilder buffy = new StringBuilder();
|
||||
int childCount = 0;
|
||||
for (int i = 0; i < allChildren.size(); i++) {
|
||||
DecompilerBlock block = allChildren.get(i);
|
||||
for (DecompilerBlock block : allChildren) {
|
||||
if (block instanceof DecompilerBlockGraph) {
|
||||
|
||||
String blockName = block.getName();
|
||||
|
@ -1447,9 +1543,8 @@ public class DecompilerNestedLayout extends AbstractFGLayout {
|
|||
// The 'list' structure for children's nesting:
|
||||
// -all nodes are at the same level
|
||||
//
|
||||
for (int i = 0; i < allChildren.size(); i++) {
|
||||
for (DecompilerBlock block : allChildren) {
|
||||
int column = col;
|
||||
DecompilerBlock block = allChildren.get(i);
|
||||
block.setCol(column);
|
||||
}
|
||||
|
||||
|
@ -1477,8 +1572,7 @@ public class DecompilerNestedLayout extends AbstractFGLayout {
|
|||
// -each successive condition is another level nested
|
||||
//
|
||||
int column = col;
|
||||
for (int i = 0; i < allChildren.size(); i++) {
|
||||
DecompilerBlock block = allChildren.get(i);
|
||||
for (DecompilerBlock block : allChildren) {
|
||||
block.setCol(column);
|
||||
column++;
|
||||
}
|
||||
|
@ -1518,8 +1612,7 @@ public class DecompilerNestedLayout extends AbstractFGLayout {
|
|||
// -all blocks nested
|
||||
//
|
||||
int column = col + 1;
|
||||
for (int i = 0; i < allChildren.size(); i++) {
|
||||
DecompilerBlock block = allChildren.get(i);
|
||||
for (DecompilerBlock block : allChildren) {
|
||||
block.setCol(column);
|
||||
}
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ public class ServerAdmin implements GhidraLaunchable {
|
|||
* The following properties may be set:
|
||||
* <pre>
|
||||
* UserAdmin.invocation - identifies the name of the application used when displaying usage text.
|
||||
* UserAdmin.serverDir - identifies the server directory instead of passing on command line.
|
||||
* UserAdmin.config - identifies the config file instead of passing on command line.
|
||||
* </pre>
|
||||
* @param args command line arguments
|
||||
*/
|
||||
|
@ -75,22 +75,18 @@ public class ServerAdmin implements GhidraLaunchable {
|
|||
* The following properties may be set:
|
||||
* <pre>
|
||||
* UserAdmin.invocation - identifies the name of the application used when displaying usage text.
|
||||
* UserAdmin.serverDir - identifies the server directory instead of passing on command line.
|
||||
* UserAdmin.config - identifies the config file instead of passing on command line.
|
||||
* </pre>
|
||||
* @param args command line arguments
|
||||
*/
|
||||
public void execute(String[] args) {
|
||||
|
||||
File serverDir = null;
|
||||
|
||||
int ix = 0;
|
||||
if (args.length != 0 && !args[0].startsWith("-")) {
|
||||
serverDir = new File(args[ix++]);
|
||||
}
|
||||
else {
|
||||
serverDir = getServerDirFromConfig();
|
||||
}
|
||||
|
||||
String configFilePath = args.length != 0 && !args[0].startsWith("-") ? args[ix++]
|
||||
: System.getProperty(CONFIG_FILE_PROPERTY);
|
||||
|
||||
File serverDir = getServerDirFromConfig(configFilePath);
|
||||
if (serverDir == null || (args.length - ix) == 0) {
|
||||
displayUsage("");
|
||||
System.exit(-1);
|
||||
|
@ -105,9 +101,7 @@ public class ServerAdmin implements GhidraLaunchable {
|
|||
System.exit(-1);
|
||||
}
|
||||
|
||||
if (propertyUsed) {
|
||||
System.out.println("Using server directory: " + serverDir);
|
||||
}
|
||||
|
||||
File userFile = new File(serverDir, UserManager.USER_PASSWORD_FILE);
|
||||
if (!serverDir.isDirectory() || !userFile.isFile()) {
|
||||
|
@ -423,13 +417,14 @@ public class ServerAdmin implements GhidraLaunchable {
|
|||
}
|
||||
}
|
||||
|
||||
private File getServerDirFromConfig() {
|
||||
String p = System.getProperty(CONFIG_FILE_PROPERTY);
|
||||
if (p == null) {
|
||||
private File getServerDirFromConfig(String configFilePath) {
|
||||
System.out.println("Using config file: " + configFilePath);
|
||||
|
||||
if (configFilePath == null) {
|
||||
return null;
|
||||
}
|
||||
propertyUsed = true;
|
||||
File configFile = new File(p);
|
||||
|
||||
File configFile = new File(configFilePath);
|
||||
|
||||
if (!configFile.exists()) {
|
||||
System.out.println("Config file not found: " + configFile.getAbsolutePath());
|
||||
|
@ -455,8 +450,9 @@ public class ServerAdmin implements GhidraLaunchable {
|
|||
}
|
||||
}
|
||||
|
||||
p = config.getProperty(SERVER_DIR_CONFIG_PROPERTY);
|
||||
String p = config.getProperty(SERVER_DIR_CONFIG_PROPERTY);
|
||||
if (p == null) {
|
||||
System.out.println("Failed to find property: " + SERVER_DIR_CONFIG_PROPERTY);
|
||||
return null;
|
||||
}
|
||||
File dir = new File(p);
|
||||
|
@ -482,8 +478,8 @@ public class ServerAdmin implements GhidraLaunchable {
|
|||
}
|
||||
String invocationName = System.getProperty(INVOCATION_NAME_PROPERTY);
|
||||
System.err.println("Usage: " +
|
||||
(invocationName != null ? invocationName : "java " + UserAdmin.class.getName()) +
|
||||
(propertyUsed ? "" : " <serverPath>") + " [<command>] [<command>] ...");
|
||||
(invocationName != null ? invocationName : "java " + ServerAdmin.class.getName()) +
|
||||
(invocationName != null ? "" : " <configPath>") + " [<command>] [<command>] ...");
|
||||
System.err.println("\nSupported commands:");
|
||||
System.err.println(" -add <sid> [--p]");
|
||||
System.err.println(
|
||||
|
|
|
@ -151,6 +151,10 @@ public class DockableComponent extends JPanel implements ContainerListener {
|
|||
}
|
||||
|
||||
private void showContextMenu(MouseEvent e) {
|
||||
if (e.isConsumed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Component component = e.getComponent();
|
||||
if (component == null) {
|
||||
return; // not sure this can happen
|
||||
|
|
|
@ -16,12 +16,12 @@
|
|||
package docking.framework;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Objects;
|
||||
import java.util.*;
|
||||
|
||||
import generic.jar.ResourceFile;
|
||||
import ghidra.framework.ApplicationProperties;
|
||||
import ghidra.util.SystemUtilities;
|
||||
import util.CollectionUtils;
|
||||
import utility.application.ApplicationLayout;
|
||||
import utility.application.ApplicationUtilities;
|
||||
import utility.module.ModuleUtilities;
|
||||
|
@ -34,16 +34,6 @@ public class DockingApplicationLayout extends ApplicationLayout {
|
|||
|
||||
private static final String NO_RELEASE_NAME = "NO_RELEASE";
|
||||
|
||||
/**
|
||||
* Constructs a new docking application layout object with the given name.
|
||||
*
|
||||
* @param name The name of the application.
|
||||
* @throws FileNotFoundException if there was a problem getting a user directory.
|
||||
*/
|
||||
public DockingApplicationLayout(String name) throws FileNotFoundException {
|
||||
this(name, "0.1");
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new docking application layout object with the given name and version.
|
||||
*
|
||||
|
@ -57,24 +47,31 @@ public class DockingApplicationLayout extends ApplicationLayout {
|
|||
|
||||
/**
|
||||
* Constructs a new docking application layout object with the given set of application
|
||||
* properties.
|
||||
* properties. The default Ghidra application root directory(s) will be used.
|
||||
*
|
||||
* @param applicationProperties The properties object that will be read system properties.
|
||||
* @throws FileNotFoundException if there was a problem getting a user directory.
|
||||
*/
|
||||
public DockingApplicationLayout(ApplicationProperties applicationProperties)
|
||||
throws FileNotFoundException {
|
||||
this(getDefaultApplicationRootDirs(), applicationProperties);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new docking application layout object with the given set of application
|
||||
* properties.
|
||||
*
|
||||
* @param applicationRootDirs list of application root directories which should be
|
||||
* used to idenitfy modules and resources. The first entry will be treated as the
|
||||
* installation root.
|
||||
* @param applicationProperties The properties object that will be read system properties.
|
||||
* @throws FileNotFoundException if there was a problem getting a user directory.
|
||||
*/
|
||||
public DockingApplicationLayout(Collection<ResourceFile> applicationRootDirs,
|
||||
ApplicationProperties applicationProperties) throws FileNotFoundException {
|
||||
|
||||
this.applicationProperties = Objects.requireNonNull(applicationProperties);
|
||||
|
||||
// Application root directories
|
||||
if (SystemUtilities.isInDevelopmentMode()) {
|
||||
applicationRootDirs = ApplicationUtilities.findDefaultApplicationRootDirs();
|
||||
}
|
||||
else {
|
||||
applicationRootDirs = new ArrayList<>();
|
||||
applicationRootDirs.add(new ResourceFile(System.getProperty("user.dir")));
|
||||
}
|
||||
this.applicationRootDirs = applicationRootDirs;
|
||||
|
||||
// Application installation directory
|
||||
applicationInstallationDir = applicationRootDirs.iterator().next().getParentFile();
|
||||
|
@ -97,4 +94,18 @@ public class DockingApplicationLayout extends ApplicationLayout {
|
|||
applicationInstallationDir);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default list of Application directories. In repo-based
|
||||
* development mode this includes the root Ghidra directory within each repo.
|
||||
* When not in development mode, the requirement is that the current working
|
||||
* directory correspond to the installation root. The first entry will be
|
||||
* the primary root in both cases.
|
||||
* @return root directories
|
||||
*/
|
||||
public static Collection<ResourceFile> getDefaultApplicationRootDirs() {
|
||||
if (SystemUtilities.isInDevelopmentMode()) {
|
||||
return ApplicationUtilities.findDefaultApplicationRootDirs();
|
||||
}
|
||||
return CollectionUtils.asList(new ResourceFile(System.getProperty("user.dir")));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -313,14 +313,7 @@ public abstract class AbstractVisualGraphLayout<V extends VisualVertex,
|
|||
Map<V, Point2D> vertexLayoutLocations =
|
||||
positionVerticesInLayoutSpace(transformer, vertices, layoutLocations);
|
||||
|
||||
Map<E, List<Point2D>> edgeLayoutArticulationLocations =
|
||||
positionEdgeArticulationsInLayoutSpace(transformer, vertexLayoutLocations, edges,
|
||||
layoutLocations);
|
||||
|
||||
// DEGUG triggers grid lines to be printed; useful for debugging
|
||||
// VisualGraphRenderer.DEBUG_ROW_COL_MAP.put((Graph<?, ?>) visualGraph,
|
||||
// layoutLocations.copy());
|
||||
|
||||
Map<E, List<Point2D>> edgeLayoutArticulationLocations = new HashMap<>();
|
||||
Rectangle graphBounds =
|
||||
getTotalGraphSize(vertexLayoutLocations, edgeLayoutArticulationLocations, transformer);
|
||||
double centerX = graphBounds.getCenterX();
|
||||
|
@ -332,6 +325,12 @@ public abstract class AbstractVisualGraphLayout<V extends VisualVertex,
|
|||
centerX, centerY);
|
||||
}
|
||||
|
||||
edgeLayoutArticulationLocations = positionEdgeArticulationsInLayoutSpace(transformer,
|
||||
vertexLayoutLocations, edges, layoutLocations);
|
||||
|
||||
// DEGUG triggers grid lines to be printed; useful for debugging
|
||||
// VisualGraphRenderer.DEBUG_ROW_COL_MAP.put(this, layoutLocations.copy());
|
||||
|
||||
layoutLocations.dispose();
|
||||
gridLocations.dispose();
|
||||
|
||||
|
|
|
@ -22,8 +22,8 @@ import java.util.*;
|
|||
import com.google.common.base.Function;
|
||||
|
||||
import edu.uci.ics.jung.algorithms.layout.Layout;
|
||||
import edu.uci.ics.jung.graph.Graph;
|
||||
import edu.uci.ics.jung.visualization.*;
|
||||
import edu.uci.ics.jung.visualization.layout.ObservableCachingLayout;
|
||||
import edu.uci.ics.jung.visualization.renderers.Renderer;
|
||||
import edu.uci.ics.jung.visualization.transform.shape.GraphicsDecorator;
|
||||
import ghidra.graph.viewer.*;
|
||||
|
@ -44,7 +44,8 @@ public class VisualGraphRenderer<V extends VisualVertex, E extends VisualEdge<V>
|
|||
/**
|
||||
* Used for displaying grid information for graph layouts
|
||||
*/
|
||||
public static Map<Graph<?, ?>, LayoutLocationMap<?, ?>> DEBUG_ROW_COL_MAP = new HashMap<>();
|
||||
public static Map<VisualGraphLayout<?, ?>, LayoutLocationMap<?, ?>> DEBUG_ROW_COL_MAP =
|
||||
new HashMap<>();
|
||||
|
||||
private Renderer.EdgeLabel<V, E> edgeLabelRenderer = new BasicEdgeLabelRenderer<>();
|
||||
|
||||
|
@ -122,11 +123,15 @@ public class VisualGraphRenderer<V extends VisualVertex, E extends VisualEdge<V>
|
|||
edgeLabelRenderer.labelEdge(rc, layout, e, xform.apply(e));
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" }) // the types in the cast matter not
|
||||
private void paintLayoutGridCells(RenderContext<V, E> renderContext, Layout<V, E> layout) {
|
||||
|
||||
// to enable this debug, search java files for commented-out uses of 'DEBUG_ROW_COL_MAP'
|
||||
Graph<V, E> graph = layout.getGraph();
|
||||
LayoutLocationMap<?, ?> locationMap = DEBUG_ROW_COL_MAP.get(graph);
|
||||
Layout<V, E> key = layout;
|
||||
if (layout instanceof ObservableCachingLayout) {
|
||||
key = ((ObservableCachingLayout) layout).getDelegate();
|
||||
}
|
||||
LayoutLocationMap<?, ?> locationMap = DEBUG_ROW_COL_MAP.get(key);
|
||||
if (locationMap == null) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -33,7 +33,6 @@ import ghidra.framework.model.ToolServices;
|
|||
import ghidra.util.Msg;
|
||||
import ghidra.util.SystemUtilities;
|
||||
import ghidra.util.classfinder.ClassSearcher;
|
||||
import ghidra.util.exception.AssertException;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.xml.GenericXMLOutputter;
|
||||
import ghidra.util.xml.XmlUtilities;
|
||||
|
@ -52,7 +51,6 @@ public abstract class StandAloneApplication implements GenericStandAloneApplicat
|
|||
/**
|
||||
* Creates a new application using the given properties filename. The
|
||||
* filename is expected reside in the current working directory.
|
||||
*
|
||||
* <p>
|
||||
* <b>The given properties file is expected to have the
|
||||
* {@link ApplicationProperties#APPLICATION_NAME_PROPERTY} and
|
||||
|
@ -60,43 +58,59 @@ public abstract class StandAloneApplication implements GenericStandAloneApplicat
|
|||
* set.</b>
|
||||
*
|
||||
* @param propertiesFilename the name of the properties file.
|
||||
* @throws IOException error causing application initialization failure
|
||||
*/
|
||||
public StandAloneApplication(String propertiesFilename) {
|
||||
public StandAloneApplication(String propertiesFilename) throws IOException {
|
||||
this(new DockingApplicationLayout(readApplicationProperties(propertiesFilename)));
|
||||
}
|
||||
|
||||
try {
|
||||
/**
|
||||
* Creates a new application using the specified application name
|
||||
* and version.
|
||||
* @param name application name
|
||||
* @param version application version
|
||||
* @throws IOException error causing application initialization failure
|
||||
*/
|
||||
public StandAloneApplication(String name, String version) throws IOException {
|
||||
this(new DockingApplicationLayout(name, version));
|
||||
}
|
||||
|
||||
/**
|
||||
* reates a new application using the given application layout
|
||||
* and associated application properties.
|
||||
* @param applicationLayout application layout
|
||||
*/
|
||||
public StandAloneApplication(ApplicationLayout applicationLayout) {
|
||||
init(applicationLayout);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read {@link ApplicationProperties} from the specified file path relative
|
||||
* to the current working directory.
|
||||
* <p>
|
||||
* <b>The given properties file is expected to have the
|
||||
* {@link ApplicationProperties#APPLICATION_NAME_PROPERTY} and
|
||||
* {@link ApplicationProperties#APPLICATION_VERSION_PROPERTY} properties
|
||||
* set.</b>
|
||||
* @param propertiesFilename the name of the properties file.
|
||||
* @return application properties
|
||||
* @throws IOException if file read error occurs
|
||||
*/
|
||||
public static ApplicationProperties readApplicationProperties(String propertiesFilename)
|
||||
throws IOException {
|
||||
ApplicationProperties properties = ApplicationProperties.fromFile(propertiesFilename);
|
||||
String name = properties.getProperty(ApplicationProperties.APPLICATION_NAME_PROPERTY);
|
||||
if (name == null) {
|
||||
Msg.error(this,
|
||||
Msg.error(StandAloneApplication.class,
|
||||
"The application.name property is not set in " + propertiesFilename);
|
||||
}
|
||||
|
||||
String version =
|
||||
properties.getProperty(ApplicationProperties.APPLICATION_VERSION_PROPERTY);
|
||||
String version = properties.getProperty(ApplicationProperties.APPLICATION_VERSION_PROPERTY);
|
||||
if (version == null) {
|
||||
Msg.error(this,
|
||||
Msg.error(StandAloneApplication.class,
|
||||
"The application.name property is not set in " + propertiesFilename);
|
||||
}
|
||||
|
||||
ApplicationLayout applicationLayout = new DockingApplicationLayout(properties);
|
||||
init(applicationLayout);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new AssertException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public StandAloneApplication(String name, String version) {
|
||||
|
||||
// Setup application layout
|
||||
try {
|
||||
ApplicationLayout applicationLayout = new DockingApplicationLayout(name, version);
|
||||
init(applicationLayout);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new AssertException(e);
|
||||
}
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
||||
private void init(ApplicationLayout applicationLayout) {
|
||||
|
|
|
@ -534,53 +534,7 @@ public class NamespaceUtils {
|
|||
throws InvalidInputException {
|
||||
|
||||
Symbol namespaceSymbol = namespace.getSymbol();
|
||||
String name = namespaceSymbol.getName();
|
||||
SourceType originalSource = namespaceSymbol.getSource();
|
||||
|
||||
SymbolTable symbolTable = namespaceSymbol.getProgram().getSymbolTable();
|
||||
|
||||
// Temporarily rename old namespace (it will be removed at the end)
|
||||
int count = 1;
|
||||
while (true) {
|
||||
String n = name + "_" + count++;
|
||||
try {
|
||||
namespaceSymbol.setName(n, SourceType.ANALYSIS);
|
||||
break;
|
||||
}
|
||||
catch (DuplicateNameException e) {
|
||||
// continue
|
||||
}
|
||||
catch (InvalidInputException e) {
|
||||
throw new AssertException(e);
|
||||
}
|
||||
}
|
||||
|
||||
// create new class namespace
|
||||
GhidraClass classNamespace = null;
|
||||
try {
|
||||
classNamespace =
|
||||
symbolTable.createClass(namespace.getParentNamespace(), name, originalSource);
|
||||
}
|
||||
catch (DuplicateNameException e) {
|
||||
throw new AssertException(e);
|
||||
}
|
||||
catch (InvalidInputException e) {
|
||||
// The only cause of this exception can be assumed but we need to
|
||||
// avoid showing the user a temporary name
|
||||
throw new InvalidInputException(
|
||||
"Namespace contained within Function may not be converted to a class: " + name);
|
||||
}
|
||||
|
||||
// move everything from old namespace into new class namespace
|
||||
try {
|
||||
for (Symbol s : symbolTable.getSymbols(namespace)) {
|
||||
s.setNamespace(classNamespace);
|
||||
}
|
||||
namespaceSymbol.delete();
|
||||
}
|
||||
catch (DuplicateNameException | InvalidInputException | CircularDependencyException e) {
|
||||
throw new AssertException(e);
|
||||
}
|
||||
return classNamespace;
|
||||
return symbolTable.convertNamespaceToClass(namespace);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1695,6 +1695,9 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
|
|||
|
||||
@Override
|
||||
public void disassociate(DataType dataType) {
|
||||
|
||||
lock.acquire();
|
||||
try {
|
||||
UniversalID oldDtID = dataType.getUniversalID();
|
||||
SourceArchive sourceArchive = dataType.getSourceArchive();
|
||||
sourceArchive = resolveSourceArchive(sourceArchive);
|
||||
|
@ -1724,6 +1727,10 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
|
|||
|
||||
dataTypeChanged(dataType);
|
||||
}
|
||||
finally {
|
||||
lock.release();
|
||||
}
|
||||
}
|
||||
|
||||
private Collection<DataType> filterOutNonSourceSettableDataTypes(
|
||||
Collection<DataType> datatypes) {
|
||||
|
@ -2694,7 +2701,8 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
|
|||
}
|
||||
try {
|
||||
creatingDataType++;
|
||||
DBRecord record = functionDefAdapter.createRecord(name, funDef.getComment(), cat.getID(),
|
||||
DBRecord record =
|
||||
functionDefAdapter.createRecord(name, funDef.getComment(), cat.getID(),
|
||||
DEFAULT_DATATYPE_ID, funDef.hasVarArgs(), funDef.getGenericCallingConvention(),
|
||||
sourceArchiveIdValue, universalIdValue, funDef.getLastChangeTime());
|
||||
FunctionDefinitionDB funDefDb =
|
||||
|
@ -3696,8 +3704,14 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
|
|||
@Override
|
||||
public DataType getDataType(SourceArchive sourceArchive, UniversalID datatypeID) {
|
||||
UniversalID sourceID = sourceArchive == null ? null : sourceArchive.getSourceArchiveID();
|
||||
lock.acquire();
|
||||
try {
|
||||
return idsToDataTypeMap.getDataType(sourceID, datatypeID);
|
||||
}
|
||||
finally {
|
||||
lock.release();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType findDataTypeForID(UniversalID datatypeID) {
|
||||
|
@ -4162,7 +4176,11 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
|
|||
|
||||
Map<UniversalID, DataType> idMap =
|
||||
map.computeIfAbsent(sourceID, k -> new ConcurrentHashMap<>());
|
||||
final UniversalID sourceArchiveID = sourceID;
|
||||
UniversalID sourceArchiveID = sourceID;
|
||||
|
||||
// note: this call is atomic and has a lock on the 'idMap'. It may call to a method
|
||||
// that requires a db lock. As such, the call to computeIfAbsent() must be
|
||||
// made while holding the db lock.
|
||||
return idMap.computeIfAbsent(dataTypeID,
|
||||
k -> findDataTypeForIDs(sourceArchiveID, dataTypeID));
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -19,8 +18,7 @@ package ghidra.program.database.symbol;
|
|||
import ghidra.program.model.address.AddressSetView;
|
||||
import ghidra.program.model.listing.CircularDependencyException;
|
||||
import ghidra.program.model.listing.GhidraClass;
|
||||
import ghidra.program.model.symbol.Namespace;
|
||||
import ghidra.program.model.symbol.Symbol;
|
||||
import ghidra.program.model.symbol.*;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
import ghidra.util.exception.InvalidInputException;
|
||||
|
||||
|
@ -63,6 +61,19 @@ class GhidraClassDB implements GhidraClass {
|
|||
return symbol.getName();
|
||||
}
|
||||
|
||||
public void setName(String name, SourceType source, boolean checkForDuplicates)
|
||||
throws DuplicateNameException, InvalidInputException {
|
||||
|
||||
try {
|
||||
symbol.doSetNameAndNamespace(name, symbol.getParentNamespace(), source,
|
||||
checkForDuplicates);
|
||||
}
|
||||
catch (CircularDependencyException e) {
|
||||
// can't happen since we are not changing the namespace
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.symbol.Namespace#getID()
|
||||
*/
|
||||
|
|
|
@ -104,7 +104,8 @@ public abstract class SymbolDB extends DatabaseObject implements Symbol {
|
|||
return false;
|
||||
}
|
||||
record = rec;
|
||||
address = symbolMgr.getAddressMap().decodeAddress(
|
||||
address = symbolMgr.getAddressMap()
|
||||
.decodeAddress(
|
||||
rec.getLongValue(SymbolDatabaseAdapter.SYMBOL_ADDR_COL));
|
||||
return true;
|
||||
}
|
||||
|
@ -522,8 +523,8 @@ public abstract class SymbolDB extends DatabaseObject implements Symbol {
|
|||
return source;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNameAndNamespace(String newName, Namespace newNamespace, SourceType source)
|
||||
public void doSetNameAndNamespace(String newName, Namespace newNamespace, SourceType source,
|
||||
boolean checkForDuplicates)
|
||||
throws DuplicateNameException, InvalidInputException, CircularDependencyException {
|
||||
|
||||
lock.acquire();
|
||||
|
@ -563,7 +564,11 @@ public abstract class SymbolDB extends DatabaseObject implements Symbol {
|
|||
if (!namespaceChange && !nameChange) {
|
||||
return;
|
||||
}
|
||||
symbolMgr.checkDuplicateSymbolName(address, newName, newNamespace, getSymbolType());
|
||||
|
||||
if (checkForDuplicates) {
|
||||
symbolMgr.checkDuplicateSymbolName(address, newName, newNamespace,
|
||||
getSymbolType());
|
||||
}
|
||||
}
|
||||
|
||||
if (record != null) {
|
||||
|
@ -617,6 +622,13 @@ public abstract class SymbolDB extends DatabaseObject implements Symbol {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNameAndNamespace(String newName, Namespace newNamespace, SourceType source)
|
||||
throws DuplicateNameException, InvalidInputException, CircularDependencyException {
|
||||
|
||||
doSetNameAndNamespace(newName, newNamespace, source, true);
|
||||
}
|
||||
|
||||
protected List<SymbolDB> getSymbolsDynamicallyRenamedByMyRename() {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -40,7 +40,6 @@ import ghidra.program.util.LanguageTranslator;
|
|||
import ghidra.util.*;
|
||||
import ghidra.util.exception.*;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
import ghidra.util.task.TaskMonitorAdapter;
|
||||
|
||||
public class SymbolManager implements SymbolTable, ManagerDB {
|
||||
|
||||
|
@ -128,7 +127,7 @@ public class SymbolManager implements SymbolTable, ManagerDB {
|
|||
* Find previously defined variable storage address
|
||||
* @param storage variable storage
|
||||
* @return previously defined variable storage address or null if not found
|
||||
* @throws IOException
|
||||
* @throws IOException if there is database exception
|
||||
*/
|
||||
public Address findVariableStorageAddress(VariableStorage storage) throws IOException {
|
||||
return variableStorageMgr.getVariableStorageAddress(storage, false);
|
||||
|
@ -183,7 +182,7 @@ public class SymbolManager implements SymbolTable, ManagerDB {
|
|||
* where all the moved external addresses will be placed.
|
||||
* The triggering of this upgrade relies on the addition of the VariableManager which
|
||||
* trigger an upgrade.
|
||||
* @param monitor
|
||||
* @param monitor the task monitor
|
||||
*/
|
||||
private boolean upgradeOldNamespaceAddresses(TaskMonitor monitor)
|
||||
throws IOException, CancelledException {
|
||||
|
@ -239,9 +238,9 @@ public class SymbolManager implements SymbolTable, ManagerDB {
|
|||
/**
|
||||
* Upgrade old stack and register variable symbol address to variable addresses.
|
||||
* Also force associated references to be updated to new variable addresses.
|
||||
* @param monitor
|
||||
* @throws IOException
|
||||
* @throws CancelledException
|
||||
* @param monitor the task monitor
|
||||
* @throws IOException if there is database exception
|
||||
* @throws CancelledException if the operation is cancelled
|
||||
*/
|
||||
private void processOldVariableAddresses(TaskMonitor monitor)
|
||||
throws IOException, CancelledException {
|
||||
|
@ -296,8 +295,8 @@ public class SymbolManager implements SymbolTable, ManagerDB {
|
|||
* No more sharing the same variable address for multiple variable symbols.
|
||||
* Must split these up. Only reference to variable addresses should be the
|
||||
* symbol address - reference refer to physical/stack addresses, and symbolIDs.
|
||||
* @param monitor
|
||||
* @throws CancelledException
|
||||
* @param monitor the task monitor
|
||||
* @throws CancelledException if the operation is cancelled
|
||||
*/
|
||||
public void migrateFromOldVariableStorageManager(TaskMonitor monitor)
|
||||
throws CancelledException {
|
||||
|
@ -396,9 +395,8 @@ public class SymbolManager implements SymbolTable, ManagerDB {
|
|||
|
||||
/**
|
||||
* Add old local symbols
|
||||
* @param table
|
||||
* @throws IOException
|
||||
* @throws CancelledException
|
||||
* @throws IOException if there is database exception
|
||||
* @throws CancelledException if the operation is cancelled
|
||||
*/
|
||||
private void processOldLocalSymbols(TaskMonitor monitor)
|
||||
throws IOException, CancelledException {
|
||||
|
@ -450,6 +448,7 @@ public class SymbolManager implements SymbolTable, ManagerDB {
|
|||
* @param oldAddr old address value from symbol table
|
||||
* @param name symbol name
|
||||
* @param isPrimary true if symbol is primary at oldAddr
|
||||
* @throws IOException if there is database exception
|
||||
*/
|
||||
public static void saveLocalSymbol(DBHandle tmpHandle, long symbolID, long oldAddr, String name,
|
||||
boolean isPrimary) throws IOException {
|
||||
|
@ -480,18 +479,15 @@ public class SymbolManager implements SymbolTable, ManagerDB {
|
|||
return;
|
||||
}
|
||||
|
||||
List<Symbol> symbolList = getSymbols(name, namespace);
|
||||
for (Symbol symbol : symbolList) {
|
||||
if (!symbol.getSymbolType().allowsDuplicates()) {
|
||||
Symbol symbol = getFirstSymbol(name, namespace, s -> !s.getSymbolType().allowsDuplicates());
|
||||
if (symbol != null) {
|
||||
throw new DuplicateNameException(
|
||||
"A " + symbol.getSymbolType() + " symbol with name " + name +
|
||||
" already exists in namespace " + symbol.getParentNamespace().getName());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* Convert the specified dynamic symbol to a named symbol. Both symbol removed and symbol added
|
||||
* notifications are performed, although the symbol instance is changed and continues to be
|
||||
* valid.
|
||||
|
@ -509,7 +505,8 @@ public class SymbolManager implements SymbolTable, ManagerDB {
|
|||
Address address = symbol.getAddress();
|
||||
symbolRemoved(symbol, address, symbol.getName(), oldKey, Namespace.GLOBAL_NAMESPACE_ID,
|
||||
null);
|
||||
DBRecord record = adapter.createSymbol(newName, address, newParentID, SymbolType.LABEL, 0,
|
||||
DBRecord record =
|
||||
adapter.createSymbol(newName, address, newParentID, SymbolType.LABEL, 0,
|
||||
1, null, source);
|
||||
symbol.setRecord(record);// symbol object was morphed
|
||||
symbolAdded(symbol);
|
||||
|
@ -987,10 +984,11 @@ public class SymbolManager implements SymbolTable, ManagerDB {
|
|||
return searchSymbolsByNamespaceFirst(name, namespace);
|
||||
}
|
||||
|
||||
// Try to find the symbols by searching through all the symbols with the given name and including
|
||||
// only those in the specified namespace. If there are too many symbols with the same name and
|
||||
// we are not in the global space, abandon this approach and instead search through all
|
||||
// the symbols in the namespace and only include those with the specified name.
|
||||
// Try to find the symbols by searching through all the symbols with the given name
|
||||
// and including only those in the specified namespace. If there are too many symbols
|
||||
// with the same name and we are not in the global space, abandon this approach and
|
||||
// instead search through all the symbols in the namespace and only include those with
|
||||
// the specified name.
|
||||
int count = 0;
|
||||
List<Symbol> list = new ArrayList<>();
|
||||
SymbolIterator symbols = getSymbols(name);
|
||||
|
@ -1009,6 +1007,42 @@ public class SymbolManager implements SymbolTable, ManagerDB {
|
|||
}
|
||||
}
|
||||
|
||||
// note: this could be public; adding it may be confusing due to the potential for having
|
||||
// multiple symbols and not knowing when to call which method.
|
||||
private Symbol getFirstSymbol(String name, Namespace namespace, Predicate<Symbol> test) {
|
||||
if (namespace == null) {
|
||||
namespace = namespaceMgr.getGlobalNamespace();
|
||||
}
|
||||
|
||||
if (namespace.isExternal() &&
|
||||
SymbolUtilities.isReservedExternalDefaultName(name, program.getAddressFactory())) {
|
||||
return findFirstSymbol(name, namespace, test);
|
||||
}
|
||||
|
||||
else if (namespace instanceof Function && hasDefaultVariablePrefix(name)) {
|
||||
return findFirstSymbol(name, namespace, test);
|
||||
}
|
||||
|
||||
// Try to find the symbols by searching through all the symbols with the given name
|
||||
// and including only those in the specified namespace. If there are too many symbols
|
||||
// with the same name and we are not in the global space, abandon this approach and
|
||||
// instead search through all the symbols in the namespace and only include those with
|
||||
// the specified name.
|
||||
int count = 0;
|
||||
SymbolIterator symbols = getSymbols(name);
|
||||
for (Symbol s : symbols) {
|
||||
if (++count == MAX_DUPLICATE_COUNT && !namespace.isGlobal()) {
|
||||
return findFirstSymbol(name, namespace, test);
|
||||
}
|
||||
if (s.getParentNamespace().equals(namespace) &&
|
||||
test.test(s)) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of symbols with the given name and namespace.
|
||||
*
|
||||
|
@ -1143,7 +1177,7 @@ public class SymbolManager implements SymbolTable, ManagerDB {
|
|||
|
||||
/**
|
||||
* Returns the next available external symbol address
|
||||
* @return
|
||||
* @return the address
|
||||
*/
|
||||
public Address getNextExternalSymbolAddress() {
|
||||
int extID = 1;
|
||||
|
@ -1414,6 +1448,7 @@ public class SymbolManager implements SymbolTable, ManagerDB {
|
|||
if (!symbol.isDynamic()) {
|
||||
createLabelHistoryRecord(addr, oldName, newName, LabelHistory.RENAME);
|
||||
}
|
||||
|
||||
program.symbolChanged(symbol, ChangeManager.DOCR_SYMBOL_RENAMED, addr, symbol, oldName,
|
||||
newName);
|
||||
}
|
||||
|
@ -1493,7 +1528,7 @@ public class SymbolManager implements SymbolTable, ManagerDB {
|
|||
|
||||
// fire event
|
||||
program.symbolChanged(symbol, ChangeManager.DOCR_SYMBOL_REMOVED, addr, symbol, name,
|
||||
new Long(symbolID));
|
||||
symbolID);
|
||||
}
|
||||
|
||||
void externalEntryPointRemoved(Address addr) {
|
||||
|
@ -1543,11 +1578,6 @@ public class SymbolManager implements SymbolTable, ManagerDB {
|
|||
|
||||
Symbol sym;
|
||||
|
||||
/**
|
||||
* Construct iterator which returns a single symbol
|
||||
*
|
||||
* @param addr
|
||||
*/
|
||||
SingleSymbolIterator(Symbol sym) {
|
||||
this.sym = sym;
|
||||
}
|
||||
|
@ -2175,8 +2205,7 @@ public class SymbolManager implements SymbolTable, ManagerDB {
|
|||
|
||||
void moveLabelHistory(Address oldAddress, Address address) {
|
||||
try {
|
||||
historyAdapter.moveAddressRange(oldAddress, address, 1, addrMap,
|
||||
TaskMonitorAdapter.DUMMY_MONITOR);
|
||||
historyAdapter.moveAddressRange(oldAddress, address, 1, addrMap, TaskMonitor.DUMMY);
|
||||
}
|
||||
catch (CancelledException e) {
|
||||
// can't happen, used dummy monitor
|
||||
|
@ -2266,6 +2295,109 @@ public class SymbolManager implements SymbolTable, ManagerDB {
|
|||
return new NamespaceDB(s, namespaceMgr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GhidraClass convertNamespaceToClass(Namespace namespace) {
|
||||
|
||||
if (namespace instanceof GhidraClass) {
|
||||
return (GhidraClass) namespace;
|
||||
}
|
||||
|
||||
lock.acquire();
|
||||
try {
|
||||
|
||||
checkIsValidNamespaceForMyProgram(namespace);
|
||||
|
||||
Symbol namespaceSymbol = namespace.getSymbol();
|
||||
String name = namespaceSymbol.getName();
|
||||
SourceType originalSource = namespaceSymbol.getSource();
|
||||
|
||||
// no duplicate check, since this class name will be set to that of the existing namespace
|
||||
String tempName = name + System.nanoTime();
|
||||
SymbolDB classSymbol =
|
||||
doCreateSpecialSymbol(Address.NO_ADDRESS, tempName, namespace.getParentNamespace(),
|
||||
SymbolType.CLASS, -1, -1, null, originalSource, false /*check for duplicate */);
|
||||
GhidraClassDB classNamespace = new GhidraClassDB(classSymbol, namespaceMgr);
|
||||
|
||||
// move everything from old namespace into new class namespace
|
||||
for (Symbol s : getSymbols(namespace)) {
|
||||
|
||||
// no duplicate check, since these symbols all lived under the existing namespace
|
||||
((SymbolDB) s).doSetNameAndNamespace(s.getName(), classNamespace, s.getSource(),
|
||||
false /*check for duplicate */);
|
||||
}
|
||||
|
||||
namespaceSymbol.delete();
|
||||
|
||||
// fix name now that the old namespace is deleted
|
||||
classNamespace.setName(name, SourceType.ANALYSIS, false /*check for duplicate */);
|
||||
|
||||
return classNamespace;
|
||||
}
|
||||
catch (DuplicateNameException | InvalidInputException | CircularDependencyException e) {
|
||||
throw new AssertException("Unexpected exception creating class from namespace", e);
|
||||
}
|
||||
finally {
|
||||
lock.release();
|
||||
}
|
||||
}
|
||||
|
||||
private void checkIsValidNamespaceForMyProgram(Namespace namespace) {
|
||||
|
||||
if (namespace == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (namespace == program.getGlobalNamespace()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(namespace instanceof NamespaceDB)) {
|
||||
throw new IllegalArgumentException(
|
||||
"Namespace is not a valid parent for symbols: " +
|
||||
namespace.getClass());
|
||||
}
|
||||
|
||||
SymbolDB dbSymbol = (SymbolDB) namespace.getSymbol();
|
||||
if (program != dbSymbol.getProgram()) {
|
||||
throw new IllegalArgumentException(
|
||||
"Namespace symbol is from a different program");
|
||||
}
|
||||
|
||||
// may throw a ConcurrentModificationException
|
||||
dbSymbol.checkDeleted();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Namespace getOrCreateNameSpace(Namespace parent, String name, SourceType source)
|
||||
throws DuplicateNameException, InvalidInputException {
|
||||
|
||||
lock.acquire();
|
||||
try {
|
||||
|
||||
checkIsValidNamespaceForMyProgram(parent);
|
||||
|
||||
Symbol namespaceSymbol = getFirstSymbol(name, parent, s -> {
|
||||
return s.getSymbolType() == SymbolType.NAMESPACE ||
|
||||
s.getSymbolType() == SymbolType.CLASS;
|
||||
});
|
||||
|
||||
if (namespaceSymbol != null) {
|
||||
return (Namespace) namespaceSymbol.getObject();
|
||||
}
|
||||
|
||||
// Note: We know there are no namespaces with the name; do we still have to check for
|
||||
// duplicates? Assuming yes, as another symbol type may exist with this name.
|
||||
SymbolDB s =
|
||||
doCreateSpecialSymbol(Address.NO_ADDRESS, name, parent, SymbolType.NAMESPACE, -1,
|
||||
-1, null, source, true /*check for duplicates*/);
|
||||
return new NamespaceDB(s, namespaceMgr);
|
||||
|
||||
}
|
||||
finally {
|
||||
lock.release();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Symbol createSymbolPlaceholder(Address address, long id) {
|
||||
return SymbolDB.createSymbolPlaceholder(this, address, id);
|
||||
|
@ -2293,12 +2425,24 @@ public class SymbolManager implements SymbolTable, ManagerDB {
|
|||
SymbolType symbolType, long data1, int data2, String data3, SourceType source)
|
||||
throws DuplicateNameException, InvalidInputException {
|
||||
|
||||
return doCreateSpecialSymbol(addr, name, parent, symbolType, data1, data2, data3, source,
|
||||
true);
|
||||
}
|
||||
|
||||
private SymbolDB doCreateSpecialSymbol(Address addr, String name, Namespace parent,
|
||||
SymbolType symbolType, long data1, int data2, String data3, SourceType source,
|
||||
boolean checkForDuplicates)
|
||||
throws DuplicateNameException, InvalidInputException {
|
||||
|
||||
lock.acquire();
|
||||
try {
|
||||
parent = validateNamespace(parent, addr, symbolType);
|
||||
source = validateSource(source, name, addr, symbolType);
|
||||
name = validateName(name, source);
|
||||
|
||||
if (checkForDuplicates) {
|
||||
checkDuplicateSymbolName(addr, name, parent, symbolType);
|
||||
}
|
||||
|
||||
return doCreateSymbol(name, addr, parent, symbolType, data1, data2, data3, source);
|
||||
}
|
||||
|
@ -2378,7 +2522,8 @@ public class SymbolManager implements SymbolTable, ManagerDB {
|
|||
}
|
||||
|
||||
/**
|
||||
* Internal method for creating funcions symbols.
|
||||
* Internal method for creating function symbols
|
||||
*
|
||||
* @param addr the address for the new symbol
|
||||
* @param name the name of the new symbol
|
||||
* @param namespace the namespace for the new symbol
|
||||
|
@ -2489,7 +2634,8 @@ public class SymbolManager implements SymbolTable, ManagerDB {
|
|||
long data1, int data2, String data3, SourceType source) {
|
||||
|
||||
try {
|
||||
DBRecord record = adapter.createSymbol(name, addr, namespace.getID(), type, data1, data2,
|
||||
DBRecord record =
|
||||
adapter.createSymbol(name, addr, namespace.getID(), type, data1, data2,
|
||||
data3, source);
|
||||
|
||||
SymbolDB newSymbol = makeSymbol(addr, record, type);
|
||||
|
@ -2633,19 +2779,29 @@ public class SymbolManager implements SymbolTable, ManagerDB {
|
|||
|
||||
@Override
|
||||
public Symbol getVariableSymbol(String name, Function function) {
|
||||
return findFirstSymbol(name, function, s -> {
|
||||
return getFirstSymbol(name, function, s -> {
|
||||
SymbolType t = s.getSymbolType();
|
||||
return t == SymbolType.PARAMETER || t == SymbolType.LOCAL_VAR;
|
||||
});
|
||||
}
|
||||
|
||||
private Symbol getSpecificSymbol(String name, Namespace namespace, SymbolType type) {
|
||||
return findFirstSymbol(name, namespace, s -> s.getSymbolType() == type);
|
||||
return getFirstSymbol(name, namespace, s -> s.getSymbolType() == type);
|
||||
}
|
||||
|
||||
private Symbol findFirstSymbol(String name, Namespace namespace, Predicate<Symbol> test) {
|
||||
List<Symbol> symbols = getSymbols(name, namespace);
|
||||
return symbols.stream().filter(test).findFirst().orElse(null);
|
||||
if (namespace == null) {
|
||||
namespace = namespaceMgr.getGlobalNamespace();
|
||||
}
|
||||
|
||||
SymbolIterator it = getSymbols(namespace);
|
||||
while (it.hasNext()) {
|
||||
Symbol s = it.next();
|
||||
if (s.getName().equals(name) && test.test(s)) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,8 +15,7 @@
|
|||
*/
|
||||
package ghidra.program.model.symbol;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.listing.*;
|
||||
|
@ -504,7 +503,7 @@ public interface SymbolTable {
|
|||
* @param name name of the namespace
|
||||
* @param source the source of this class namespace's symbol
|
||||
* @return new class namespace
|
||||
* @throws DuplicateNameException thrown if another non function or lable symbol exists with the given name
|
||||
* @throws DuplicateNameException thrown if another non function or label symbol exists with the given name
|
||||
* @throws InvalidInputException throw if the name has invalid characters or is null
|
||||
* @throws IllegalArgumentException if you try to set the source to 'Symbol.DEFAULT'.
|
||||
*/
|
||||
|
@ -523,7 +522,7 @@ public interface SymbolTable {
|
|||
* @param source the source of this external library's symbol
|
||||
* @return the new Library namespace.
|
||||
* @throws IllegalArgumentException if you try to set the source to 'Symbol.DEFAULT'.
|
||||
* @throws DuplicateNameException thrown if another non function or lable symbol exists with the given name
|
||||
* @throws DuplicateNameException thrown if another non function or label symbol exists with the given name
|
||||
*/
|
||||
public Library createExternalLibrary(String name, SourceType source)
|
||||
throws DuplicateNameException, InvalidInputException;
|
||||
|
@ -534,7 +533,7 @@ public interface SymbolTable {
|
|||
* @param name the name of the new namespace
|
||||
* @param source the source of this namespace's symbol
|
||||
* @return the new Namespace object.
|
||||
* @throws DuplicateNameException thrown if another non function or lable symbol exists with the given name
|
||||
* @throws DuplicateNameException thrown if another non function or label symbol exists with the given name
|
||||
* @throws InvalidInputException if the name is invalid.
|
||||
* @throws IllegalArgumentException if you try to set the source to 'Symbol.DEFAULT'.
|
||||
*/
|
||||
|
@ -552,4 +551,32 @@ public interface SymbolTable {
|
|||
*/
|
||||
public Symbol createSymbolPlaceholder(Address address, long id);
|
||||
|
||||
/**
|
||||
* Converts the given namespace to a class namespace
|
||||
*
|
||||
* @param namespace the namespace to convert
|
||||
* @return the new class
|
||||
* @throws IllegalArgumentException if the given parent namespace is from a different program
|
||||
* than that of this symbol table
|
||||
* @throws ConcurrentModificationException if the given parent namespace has been deleted
|
||||
*/
|
||||
public GhidraClass convertNamespaceToClass(Namespace namespace);
|
||||
|
||||
/**
|
||||
* Gets an existing namespace with the given name in the given parent. If no namespace exists,
|
||||
* then one will be created.
|
||||
*
|
||||
* @param parent the parent namespace
|
||||
* @param name the namespace name
|
||||
* @param source the source type for the namespace if one is created
|
||||
* @return the namespace
|
||||
* @throws DuplicateNameException thrown if another non function or label symbol exists with
|
||||
* the given name
|
||||
* @throws InvalidInputException if the name is invalid
|
||||
* @throws IllegalArgumentException if the given parent namespace is from a different program
|
||||
* than that of this symbol table
|
||||
* @throws ConcurrentModificationException if the given parent namespace has been deleted
|
||||
*/
|
||||
public Namespace getOrCreateNameSpace(Namespace parent, String name, SourceType source)
|
||||
throws DuplicateNameException, InvalidInputException;
|
||||
}
|
||||
|
|
|
@ -518,15 +518,15 @@ N_0t_dbr1: @^N_0^"+,"^DBR is N_0 & DBR { export N_0; }
|
|||
|
||||
N_0t_bank1: @^N_0^"+" is N_0 { export N_0; }
|
||||
|
||||
FR0_t: fr0 is OP_0 & fr0 { x:4 = 0; export x; } # dummy export, just looking for the display
|
||||
FR0_t: fr0 is OP_0 & fr0 { export fr0; }
|
||||
|
||||
XMTRX_t: "xmtrx" is OP_0 { x:4 = 0; export x; } # dummy export, just looking for the display
|
||||
|
||||
mach_t: MACH is OP_0 & MACH { x:4 = 0; export x; } # dummy export, just looking for the display
|
||||
mach_t: MACH is OP_0 & MACH { export MACH; }
|
||||
|
||||
macl_t: MACL is OP_0 & MACL { x:4 = 0; export x; } # dummy export, just looking for the display
|
||||
macl_t: MACL is OP_0 & MACL { export MACL; }
|
||||
|
||||
fpul_t: FPUL is OP_0 & FPUL { x:4 = 0; export x; } # dummy export, just looking for the display
|
||||
fpul_t: FPUL is OP_0 & FPUL { export FPUL; }
|
||||
|
||||
fpscr_t: "FPSCR" is OP_0 { x:4 = 0; export x; } # dummy export, just looking for the display
|
||||
|
||||
|
|
|
@ -45,8 +45,8 @@ fi
|
|||
OWNER="$(grep '^wrapper.app.account=' "${CONFIG}" | sed -e 's/^.*=\(.*\)\s*.*$/\1/')"
|
||||
|
||||
if [ -z "${OWNER}" -o "${OWNER}" = "$(whoami)" ]; then
|
||||
VMARGS="-DUserAdmin.invocation=$(basename "${SCRIPT_FILE}") -DUserAdmin.config=\"${CONFIG}\""
|
||||
"${SCRIPT_DIR}"/../support/launch.sh fg svrAdmin "${MAXMEM}" "$VMARGS" ghidra.server.ServerAdmin "$@"
|
||||
VMARGS="-DUserAdmin.invocation=$(basename "${SCRIPT_FILE}")"
|
||||
"${SCRIPT_DIR}"/../support/launch.sh fg svrAdmin "${MAXMEM}" "$VMARGS" ghidra.server.ServerAdmin "${CONFIG}" "$@"
|
||||
else
|
||||
echo "Running svrAdmin with $SUDO as ${OWNER} ..."
|
||||
$SUDO -u $OWNER "$0" "$@"
|
||||
|
|
|
@ -25,7 +25,7 @@ if [ ! -d "${GHIDRA_ROOT_DIR}" ]; then
|
|||
fi
|
||||
|
||||
# Set required VMARGS for jar builder application
|
||||
APP_VMARGS="-DGhidraJarBuilder.Name=$(basename "${SCRIPT_FILE}") -DGhidra.Install.Root.Dir=\"${GHIDRA_ROOT_DIR}\" "
|
||||
APP_VMARGS="-DGhidraJarBuilder.Name=$(basename "${SCRIPT_FILE}")"
|
||||
|
||||
# Launch jar builder
|
||||
"${SCRIPT_DIR}"/launch.sh "${LAUNCH_MODE}" Ghidra "${MAXMEM}" "${APP_VMARGS}" ghidra.util.GhidraJarBuilder -main ghidra.JarRun "$@"
|
||||
|
|
|
@ -11,7 +11,7 @@ rem runtime which has been configured into the system PATH ahead of other Java
|
|||
rem it may be necessary to explicitly specify the path to the installation by setting JAVA_HOME
|
||||
rem below:
|
||||
|
||||
rem set JAVA_HOME=
|
||||
rem set "JAVA_HOME="
|
||||
|
||||
setlocal enabledelayedexpansion
|
||||
|
||||
|
@ -50,7 +50,7 @@ if "%IS_ADMIN%"=="NO" (
|
|||
|
||||
rem Find the script directory
|
||||
rem %~dsp0 is location of current script under NT
|
||||
set _REALPATH=%~dp0
|
||||
set "_REALPATH=%~dp0"
|
||||
|
||||
set APP_NAME=ghidraSvr
|
||||
set APP_LONG_NAME=Ghidra Server
|
||||
|
@ -64,26 +64,26 @@ if exist "%_REALPATH%..\Ghidra\" goto normal
|
|||
rem NOTE: If adjusting JAVA command assignment - do not attempt to add parameters (e.g., -d64, -version:1.7, etc.)
|
||||
|
||||
rem Development Environment
|
||||
set GHIDRA_HOME=%_REALPATH%..\..\..\..
|
||||
set WRAPPER_CONF=%_REALPATH%..\..\Common\server\server.conf
|
||||
set DATA_DIR=%GHIDRA_HOME%\%MODULE_DIR%\build\data
|
||||
set CLASSPATH_FRAG=%GHIDRA_HOME%\%MODULE_DIR%\build\dev-meta\classpath.frag
|
||||
set LS_CPATH=%GHIDRA_HOME%\GhidraBuild\LaunchSupport\bin\main
|
||||
set "GHIDRA_HOME=%_REALPATH%..\..\..\.."
|
||||
set "WRAPPER_CONF=%_REALPATH%..\..\Common\server\server.conf"
|
||||
set "DATA_DIR=%GHIDRA_HOME%\%MODULE_DIR%\build\data"
|
||||
set "CLASSPATH_FRAG=%GHIDRA_HOME%\%MODULE_DIR%\build\dev-meta\classpath.frag"
|
||||
set "LS_CPATH=%GHIDRA_HOME%\GhidraBuild\LaunchSupport\bin\main"
|
||||
|
||||
goto lab1
|
||||
|
||||
:normal
|
||||
set GHIDRA_HOME=%_REALPATH%..
|
||||
set WRAPPER_CONF=%_REALPATH%server.conf
|
||||
set DATA_DIR=%GHIDRA_HOME%\%MODULE_DIR%\data
|
||||
set CLASSPATH_FRAG=%GHIDRA_HOME%\%MODULE_DIR%\data\classpath.frag
|
||||
set LS_CPATH=%GHIDRA_HOME%\support\LaunchSupport.jar
|
||||
set "GHIDRA_HOME=%_REALPATH%.."
|
||||
set "WRAPPER_CONF=%_REALPATH%server.conf"
|
||||
set "DATA_DIR=%GHIDRA_HOME%\%MODULE_DIR%\data"
|
||||
set "CLASSPATH_FRAG=%GHIDRA_HOME%\%MODULE_DIR%\data\classpath.frag"
|
||||
set "LS_CPATH=%GHIDRA_HOME%\support\LaunchSupport.jar"
|
||||
|
||||
:lab1
|
||||
|
||||
rem set WRAPPER_HOME to unpacked yajsw location (crazy FOR syntax to set variable from command output)
|
||||
for /F "usebackq delims=" %%p in (`dir "%DATA_DIR%" /ad /b ^| findstr "^%WRAPPER_NAME_PREFIX%"`) do set WRAPPER_DIRNAME=%%p
|
||||
set WRAPPER_HOME=%DATA_DIR%\%WRAPPER_DIRNAME%
|
||||
set "WRAPPER_HOME=%DATA_DIR%\%WRAPPER_DIRNAME%"
|
||||
|
||||
if not exist "%WRAPPER_HOME%\" (
|
||||
echo.
|
||||
|
@ -104,8 +104,7 @@ set ERROR=ERROR: JAVA_HOME is not set and no 'java' command could be found in yo
|
|||
goto reportError
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA=%JAVA_HOME%\bin\java.exe
|
||||
set "JAVA=%JAVA_HOME%\bin\java.exe"
|
||||
|
||||
if exist "%JAVA%" goto lab2
|
||||
set ERROR=ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
|
@ -122,15 +121,7 @@ if "%JAVA_HOME%" == "" (
|
|||
)
|
||||
|
||||
rem reestablish JAVA path based upon final JAVA_HOME
|
||||
set JAVA=%JAVA_HOME%\bin\java.exe
|
||||
|
||||
set OS_NAME=win32
|
||||
"%JAVA%" -version 2>&1 | findstr /I " 64-Bit " >NUL
|
||||
if errorlevel 0 (
|
||||
set OS_NAME=win64
|
||||
)
|
||||
|
||||
set OS_DIR=%GHIDRA_HOME%\%MODULE_DIR%\os\%OS_NAME%
|
||||
set "JAVA=%JAVA_HOME%\bin\java.exe"
|
||||
|
||||
:: set DEBUG=-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=*:18888
|
||||
|
||||
|
|
|
@ -31,18 +31,18 @@ set MAXMEM=128M
|
|||
:: '% ~' dereferences the value in param 0
|
||||
:: 'd' - drive
|
||||
:: 'p' - path (without filename)
|
||||
set SCRIPT_DIR=%~dp0
|
||||
set "SCRIPT_DIR=%~dp0"
|
||||
|
||||
:: Production Environment
|
||||
set CONFIG=%SCRIPT_DIR%.\server.conf
|
||||
set "CONFIG=%SCRIPT_DIR%.\server.conf"
|
||||
|
||||
if exist "%CONFIG%" goto continue
|
||||
|
||||
:: Development Environment
|
||||
set CONFIG=%SCRIPT_DIR%..\..\Common\server\server.conf
|
||||
set "CONFIG=%SCRIPT_DIR%..\..\Common\server\server.conf"
|
||||
|
||||
:continue
|
||||
|
||||
set VMARGS=-DUserAdmin.invocation="%0" -DUserAdmin.config="%CONFIG%"
|
||||
set VMARGS=-DUserAdmin.invocation=%~n0
|
||||
|
||||
call "%~dp0\..\support\launch.bat" fg svrAdmin "%MAXMEM%" "%VMARGS%" ghidra.server.ServerAdmin %*
|
||||
call "%~dp0\..\support\launch.bat" fg svrAdmin "%MAXMEM%" "%VMARGS%" ghidra.server.ServerAdmin "%CONFIG%" %*
|
||||
|
|
|
@ -3,7 +3,7 @@ setlocal
|
|||
|
||||
rem Find the script directory
|
||||
rem %~dsp0 is location of current script under NT
|
||||
set _REALPATH=%~dp0
|
||||
set "_REALPATH=%~dp0"
|
||||
|
||||
call "%_REALPATH%\ghidraSvr" install
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ setlocal
|
|||
|
||||
rem Find the script directory
|
||||
rem %~dsp0 is location of current script under NT
|
||||
set _REALPATH=%~dp0
|
||||
set "_REALPATH=%~dp0"
|
||||
|
||||
call "%_REALPATH%\ghidraSvr" uninstall
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ set VMARG_LIST=-XX:ParallelGCThreads=2
|
|||
set VMARG_LIST=%VMARG_LIST% -XX:CICompilerCount=2
|
||||
|
||||
:: store current path
|
||||
set filepath=%~dp0
|
||||
set "filepath=%~dp0"
|
||||
|
||||
:: Loop through parameters (if there aren't any, just continue) and store
|
||||
:: in params variable.
|
||||
|
|
|
@ -8,9 +8,9 @@ setlocal
|
|||
set LAUNCH_MODE=fg
|
||||
|
||||
:: Sets SCRIPT_DIR to the directory that contains this file (ends with '\')
|
||||
set SCRIPT_DIR=%~dp0
|
||||
set "SCRIPT_DIR=%~dp0"
|
||||
|
||||
set GHIDRA_ROOT_DIR=%SCRIPT_DIR%..\Ghidra
|
||||
set "GHIDRA_ROOT_DIR=%SCRIPT_DIR%..\Ghidra"
|
||||
if exist "%GHIDRA_ROOT_DIR%" goto continue
|
||||
|
||||
echo This script does not support development mode use
|
||||
|
@ -18,6 +18,6 @@ exit /B 1
|
|||
|
||||
:continue
|
||||
|
||||
set APP_VMARGS=-DGhidraJarBuilder.Name=%0 -DGhidra.Install.Root.Dir=%GHIDRA_ROOT_DIR%
|
||||
set APP_VMARGS=-DGhidraJarBuilder.Name=%~n0
|
||||
|
||||
call "%~dp0launch.bat" %LAUNCH_MODE% Ghidra "" "%APP_VMARGS%" ghidra.util.GhidraJarBuilder -main ghidra.JarRun %*
|
||||
|
|
|
@ -11,16 +11,16 @@
|
|||
setlocal
|
||||
|
||||
REM Get parent of current folder
|
||||
set SCRIPT_DIR=%~dp0
|
||||
set "SCRIPT_DIR=%~dp0"
|
||||
|
||||
set GHIDRA_DIR=%SCRIPT_DIR%..\Ghidra
|
||||
set "GHIDRA_DIR=%SCRIPT_DIR%..\Ghidra"
|
||||
set OS_DIR=os
|
||||
|
||||
REM Production Environment
|
||||
if exist "%GHIDRA_DIR%" goto continue
|
||||
|
||||
REM Development Environment
|
||||
set GHIDRA_DIR=%SCRIPT_DIR%..\..\..
|
||||
set "GHIDRA_DIR=%SCRIPT_DIR%..\..\.."
|
||||
set OS_DIR=build\os
|
||||
|
||||
:continue
|
||||
|
@ -35,7 +35,7 @@ if exist "%PROGRAMFILES(X86)%" (
|
|||
set OS_TYPE=win32
|
||||
)
|
||||
|
||||
set PDB_EXE=%GHIDRA_DIR%\Features\PDB\%OS_DIR%\%OS_TYPE%\pdb.exe
|
||||
set "PDB_EXE=%GHIDRA_DIR%\Features\PDB\%OS_DIR%\%OS_TYPE%\pdb.exe"
|
||||
|
||||
if not exist "%PDB_EXE%" (
|
||||
echo "%PDB_EXE% not found"
|
||||
|
|
|
@ -36,7 +36,7 @@ for /f "tokens=2" %%# in ("%cmdcmdline%") do if /i "%%#" equ "/c" set DOUBLE_CLI
|
|||
:: '% ~' dereferences the value in param 0
|
||||
:: 'd' - drive
|
||||
:: 'p' - path (without filename)
|
||||
set SUPPORT_DIR=%~dp0
|
||||
set "SUPPORT_DIR=%~dp0"
|
||||
|
||||
::
|
||||
:: Parse arguments
|
||||
|
@ -63,20 +63,20 @@ goto showUsage
|
|||
::
|
||||
:: Production Environment
|
||||
::
|
||||
set INSTALL_DIR=%SUPPORT_DIR%..\
|
||||
set CPATH=%INSTALL_DIR%Ghidra\Framework\Utility\lib\Utility.jar
|
||||
set LS_CPATH=%SUPPORT_DIR%LaunchSupport.jar
|
||||
set DEBUG_LOG4J=%SUPPORT_DIR%debug.log4j.xml
|
||||
set "INSTALL_DIR=%SUPPORT_DIR%..\"
|
||||
set "CPATH=%INSTALL_DIR%Ghidra\Framework\Utility\lib\Utility.jar"
|
||||
set "LS_CPATH=%SUPPORT_DIR%LaunchSupport.jar"
|
||||
set "DEBUG_LOG4J=%SUPPORT_DIR%debug.log4j.xml"
|
||||
|
||||
if exist "%INSTALL_DIR%Ghidra" goto continue2
|
||||
|
||||
::
|
||||
:: Development Environment
|
||||
::
|
||||
set INSTALL_DIR=%INSTALL_DIR%..\..\..\
|
||||
set CPATH=%INSTALL_DIR%Ghidra\Framework\Utility\bin\main
|
||||
set LS_CPATH=%INSTALL_DIR%GhidraBuild\LaunchSupport\bin\main
|
||||
set DEBUG_LOG4J=%INSTALL_DIR%Ghidra\RuntimeScripts\Common\support\debug.log4j.xml
|
||||
set "INSTALL_DIR=%INSTALL_DIR%..\..\..\"
|
||||
set "CPATH=%INSTALL_DIR%Ghidra\Framework\Utility\bin\main"
|
||||
set "LS_CPATH=%INSTALL_DIR%GhidraBuild\LaunchSupport\bin\main"
|
||||
set "DEBUG_LOG4J=%INSTALL_DIR%Ghidra\RuntimeScripts\Common\support\debug.log4j.xml"
|
||||
|
||||
:continue2
|
||||
|
||||
|
@ -108,7 +108,7 @@ if "%JAVA_HOME%" == "" (
|
|||
goto exit1
|
||||
)
|
||||
)
|
||||
set JAVA_CMD=%JAVA_HOME%\bin\java
|
||||
set "JAVA_CMD=%JAVA_HOME%\bin\java"
|
||||
|
||||
:: Get the configurable VM arguments from the launch properties
|
||||
for /f "delims=*" %%i in ('java -cp "%LS_CPATH%" LaunchSupport "%INSTALL_DIR%\" -vmargs') do set VMARG_LIST=%VMARG_LIST% %%i
|
||||
|
|
|
@ -26,6 +26,6 @@ set VMARG_LIST=-XX:ParallelGCThreads=2
|
|||
set VMARG_LIST=%VMARG_LIST% -XX:CICompilerCount=2
|
||||
|
||||
:: store current path
|
||||
set filepath=%~dp0
|
||||
set "filepath=%~dp0"
|
||||
|
||||
call "%filepath%launch.bat" %LAUNCH_MODE% Ghidra-Python "%MAXMEM%" "%VMARG_LIST%" ghidra.python.PythonRun %params%
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue