files = CollectionUtils.asList((List>) obj, File.class);
-
- FileImporterService im = tool.getService(FileImporterService.class);
- if (im == null) {
- tool.setStatusInfo("ERROR: Could not get importer service.");
- return;
- }
-
- DomainFolder rootFolder = tool.getProject().getProjectData().getRootFolder();
-
- if (files.size() == 1 && files.get(0).isFile()) {
- im.importFile(rootFolder, files.get(0));
- }
- else {
- im.importFiles(rootFolder, files);
- }
- }
-}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/Option.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/Option.java
index afe63dcd5f..e5262f5181 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/Option.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/Option.java
@@ -96,6 +96,15 @@ public class Option {
this.listener = listener;
}
+ /**
+ * Override if you want to provide a custom widget for selecting your
+ * options.
+ *
+ * Important! If you override this you MUST also override the {@link #copy()}
+ * method so it returns a new instance of your custom editor.
+ *
+ * @return the custom editor
+ */
public Component getCustomEditorComponent() {
return null;
}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/Compare.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/Compare.java
index 58ba286399..4b2fb28cb5 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/Compare.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/Compare.java
@@ -25,17 +25,17 @@ import ghidra.util.Msg;
public class Compare {
public static void compare(ArrayList expectedList, File actualFile) throws Exception {
int index = 0;
- BufferedReader reader = new BufferedReader(new FileReader(actualFile));
-
+
boolean hasFailure = false;
- try {
+ try (BufferedReader reader = new BufferedReader(new FileReader(actualFile))) {
int excess = 0;
while (true) {
String actualLine = reader.readLine();
if (actualLine == null) {
break;
}
+
if (index >= expectedList.size()) {
++excess;
continue;
@@ -73,8 +73,5 @@ public class Compare {
Assert.fail("One or more failures--see output for data");
}
}
- finally {
- reader.close();
- }
}
}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/IntelHexExporter.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/IntelHexExporter.java
index 29242fff3b..47ba38d9ef 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/IntelHexExporter.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/IntelHexExporter.java
@@ -15,10 +15,15 @@
*/
package ghidra.app.util.exporter;
+import java.awt.BorderLayout;
+import java.awt.Component;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
+import javax.swing.*;
+
+import docking.widgets.textfield.HintTextField;
import ghidra.app.util.*;
import ghidra.app.util.opinion.IntelHexRecord;
import ghidra.app.util.opinion.IntelHexRecordWriter;
@@ -29,18 +34,55 @@ import ghidra.program.model.mem.*;
import ghidra.util.HelpLocation;
import ghidra.util.task.TaskMonitor;
+/**
+ * Exports the current program (or program selection) as bytes in Intel Hex format.
+ *
+ * The output defaults to lines of 16-bytes but this is configurable using the
+ * {@link #recordSizeOption} attribute. This allows users to select any record size
+ * up to the max of 0xFF. Users may also choose to Drop Extra Bytes
, which will
+ * cause only lines that match the max record size to be printed; any other
+ * bytes will be dropped. If this option is not set, every byte will be represented in the output.
+ */
public class IntelHexExporter extends Exporter {
- protected final static int MAX_BYTES_PER_LINE = 0x00000010;
-
- protected Option option;
+ /** Option allowing the user to select the address space */
+ protected Option addressSpaceOption;
+
+ /** Option allowing the user to select the number of bytes in each line of output */
+ protected RecordSizeOption recordSizeOption;
+
+ private static final int DEFAULT_RECORD_SIZE = 0x10;
+
/**
- * Constructs a new Intel Hex exporter.
+ * Constructs a new Intel Hex exporter. This will use a record size of 16 (the default)
+ * and will export ALL bytes in the program or selection (even if the total length
+ * is not a multiple of 16.
*/
public IntelHexExporter() {
this("Intel Hex", "hex", new HelpLocation("ExporterPlugin", "intel_hex"));
}
-
+
+ /**
+ * Constructs a new Intel Hex exporter with a custom record size.
+ *
+ * @param recordSize the record size to use when writing to the output file
+ * @param dropBytes if true, bytes at the end of the file that don't match the specified
+ * record size will be dropped
+ */
+ public IntelHexExporter(int recordSize, boolean dropBytes) {
+ this("Intel Hex", "hex", new HelpLocation("ExporterPlugin", "intel_hex"));
+ recordSizeOption = new RecordSizeOption("Record Size", Integer.class);
+ recordSizeOption.setRecordSize(recordSize);
+ recordSizeOption.setDropBytes(dropBytes);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param name the name of the exporter
+ * @param extension the extension to use for the output file
+ * @param help location of Ghidra help
+ */
protected IntelHexExporter(String name, String extension, HelpLocation help) {
super(name, extension, help);
}
@@ -55,16 +97,49 @@ public class IntelHexExporter extends Exporter {
}
Program program = (Program) domainObject;
- option = new Option("Address Space", program.getAddressFactory().getDefaultAddressSpace());
+ addressSpaceOption =
+ new Option("Address Space", program.getAddressFactory().getDefaultAddressSpace());
+
+ if (recordSizeOption == null) {
+ recordSizeOption = new RecordSizeOption("Record Size", Integer.class);
+ }
+
+ optionsList.add(addressSpaceOption);
+ optionsList.add(recordSizeOption);
- optionsList.add(option);
return optionsList;
}
@Override
public void setOptions(List options) throws OptionException {
if (!options.isEmpty()) {
- option = options.get(0);
+ addressSpaceOption = options.get(0);
+ recordSizeOption = (RecordSizeOption) options.get(1);
+ }
+ }
+
+ /**
+ * Verifier for a {@link HintTextField} that ensures input is a numeric value between
+ * 0 and 0xFF.
+ *
+ * Input may be specified in either decimal or hex.
+ */
+ private class BoundedIntegerVerifier extends InputVerifier {
+
+ @Override
+ public boolean verify(JComponent input) {
+ HintTextField field = (HintTextField) input;
+ String text = field.getText();
+
+ int val;
+ try {
+ val = Integer.decode(text);
+ }
+ catch (NumberFormatException e) {
+ return false;
+ }
+
+ return val <= 0xFF && val >= 0;
}
}
@@ -84,33 +159,31 @@ public class IntelHexExporter extends Exporter {
return false;
}
- if (option == null) {
+ if (addressSpaceOption == null || recordSizeOption == null) {
getOptions(() -> program);
}
- PrintWriter writer = new PrintWriter(new FileOutputStream(file));
+ try (PrintWriter writer = new PrintWriter(new FileOutputStream(file))) {
- Memory memory = program.getMemory();
+ Memory memory = program.getMemory();
- if (addrSet == null) {
- addrSet = memory;
- }
-
- try {
- List records = dumpMemory(program, memory, addrSet, monitor);
- for (IntelHexRecord record : records) {
- writer.println(record.format());
+ if (addrSet == null) {
+ addrSet = memory;
}
- }
- catch (MemoryAccessException e) {
- throw new ExporterException(e);
- }
- finally {
- // Close the PrintWriter
- //
- writer.close();
- option = null;
+ try {
+ List records = dumpMemory(program, memory, addrSet, monitor);
+ for (IntelHexRecord record : records) {
+ writer.println(record.format());
+ }
+ }
+ catch (MemoryAccessException e) {
+ throw new ExporterException(e);
+ }
+ finally {
+ addressSpaceOption = null;
+ recordSizeOption = null;
+ }
}
return true;
@@ -118,15 +191,19 @@ public class IntelHexExporter extends Exporter {
protected List dumpMemory(Program program, Memory memory,
AddressSetView addrSetView, TaskMonitor monitor) throws MemoryAccessException {
- IntelHexRecordWriter writer = new IntelHexRecordWriter(MAX_BYTES_PER_LINE);
+
+ int size = (int) recordSizeOption.getValue();
+ boolean dropBytes = recordSizeOption.dropExtraBytes();
+
+ IntelHexRecordWriter writer = new IntelHexRecordWriter(size, dropBytes);
AddressSet set = new AddressSet(addrSetView);
MemoryBlock[] blocks = memory.getBlocks();
- for (int i = 0; i < blocks.length; ++i) {
- if (!blocks[i].isInitialized() ||
- blocks[i].getStart().getAddressSpace() != option.getValue()) {
- set.delete(new AddressRangeImpl(blocks[i].getStart(), blocks[i].getEnd()));
+ for (MemoryBlock block : blocks) {
+ if (!block.isInitialized() ||
+ block.getStart().getAddressSpace() != addressSpaceOption.getValue()) {
+ set.delete(new AddressRangeImpl(block.getStart(), block.getEnd()));
}
}
@@ -148,4 +225,113 @@ public class IntelHexExporter extends Exporter {
}
return writer.finish(entryPoint);
}
+
+ /**
+ * Option for exporting Intel Hex records that allows users to specify a record size for the
+ * output. Users may also optionally select the Drop Extra Bytes
option that
+ * will cause only those records that match the maximum size to be output to the file.
+ *
+ * @see RecordSizeComponent
+ */
+ private class RecordSizeOption extends Option {
+
+ private final RecordSizeComponent comp = new RecordSizeComponent(DEFAULT_RECORD_SIZE);
+
+ public RecordSizeOption(String name, Class> valueClass) {
+ super(name, valueClass);
+ }
+
+ public RecordSizeOption(String name, Class> valueClass, Object value, String arg,
+ String group) {
+ super(name, valueClass, value, arg, group);
+ }
+
+ @Override
+ public Component getCustomEditorComponent() {
+ return comp;
+ }
+
+ @Override
+ public Option copy() {
+ return new RecordSizeOption(getName(), getValueClass(), getValue(), getArg(),
+ getGroup());
+ }
+
+ @Override
+ public Object getValue() {
+ return comp.getValue();
+ }
+
+ @Override
+ public Class> getValueClass() {
+ return Integer.class;
+ }
+
+ public boolean dropExtraBytes() {
+ return comp.dropExtraBytes();
+ }
+
+ public void setRecordSize(int recordSize) {
+ comp.setRecordSize(recordSize);
+ }
+
+ public void setDropBytes(boolean dropBytes) {
+ comp.setDropBytes(dropBytes);
+ }
+ }
+
+ /**
+ * Component that displays two widgets for setting export options:
+ *
+ *
+ * input
: a {@link HintTextField} for entering numeric digits; these
+ * represent the record size for each line of output
+ * dropCb: a {@link JCheckBox} for specifying a setting that enforces that every line in
+ * the output matches the specified record size
+ *
+ *
+ * Note: If the Drop Extra Bytes
option is set, any bytes that are left over
+ * after outputting all lines that match the record size will be omitted from the output.
+ */
+ private class RecordSizeComponent extends JPanel {
+
+ private HintTextField input;
+ private JCheckBox dropCb;
+
+ public RecordSizeComponent(int recordSize) {
+ setLayout(new BorderLayout());
+
+ input = new HintTextField(Integer.toString(recordSize), false, new BoundedIntegerVerifier());
+ dropCb = new JCheckBox("Align To Record Size");
+
+ input.setText(Integer.toString(recordSize));
+
+ add(input, BorderLayout.CENTER);
+ add(dropCb, BorderLayout.EAST);
+ }
+
+ public int getValue() {
+ String val = input.getText();
+ if (!input.isFieldValid()) {
+
+ // If the user clears the input field, revert to the default
+ // record size (16).
+ return DEFAULT_RECORD_SIZE;
+ }
+
+ return Integer.valueOf(val);
+ }
+
+ public boolean dropExtraBytes() {
+ return dropCb.isSelected();
+ }
+
+ public void setRecordSize(int recordSize) {
+ input.setText(Integer.toString(recordSize));
+ }
+
+ public void setDropBytes(boolean dropBytes) {
+ dropCb.setSelected(dropBytes);
+ }
+ }
}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/IntelHexRecordWriter.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/IntelHexRecordWriter.java
index 623417a12a..16d21698c1 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/IntelHexRecordWriter.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/IntelHexRecordWriter.java
@@ -20,21 +20,31 @@ import java.util.*;
import ghidra.program.model.address.*;
public class IntelHexRecordWriter {
+
private final int maxBytesPerLine;
+ private final boolean dropExtraBytes;
private Address startAddress = null;
private Long oldSegment = null;
- private ArrayList bytes = new ArrayList();
+ private ArrayList bytes = new ArrayList<>();
private Boolean isSegmented = null;
- private ArrayList results = new ArrayList();
+ private ArrayList results = new ArrayList<>();
private boolean done = false;
- public IntelHexRecordWriter(int maxBytesPerLine) {
+ /**
+ * Constructor
+ *
+ * @param maxBytesPerLine the maximum number of bytes to write per line in the hex output
+ * @param dropExtraBytes if true, only lines matching {@link #maxBytesPerLine} will be output;
+ * remaining bytes will be left out
+ */
+ public IntelHexRecordWriter(int maxBytesPerLine, boolean dropExtraBytes) {
if (maxBytesPerLine > IntelHexRecord.MAX_RECORD_LENGTH) {
throw new IllegalArgumentException("maxBytesPerLine > IntelHexRecord.MAX_RECORD_LENGTH");
}
this.maxBytesPerLine = maxBytesPerLine;
+ this.dropExtraBytes = dropExtraBytes;
}
public void addByte(Address address, byte b) {
@@ -117,6 +127,14 @@ public class IntelHexRecordWriter {
}
public List finish(Address entryPoint) {
+
+ // Before finalizing things, write out any remaining bytes that haven't yet been written, if
+ // the user has specified to do so via the drop extra bytes option (false =
+ // write out everything).
+ if (bytes.size() > 0 && !dropExtraBytes) {
+ emitData();
+ }
+
if (entryPoint != null && isSegmented != null) {
final long offset = entryPoint.getOffset();
byte[] data = new byte[4];
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/FieldHighlightFactory.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/FieldHighlightFactory.java
index c46721d71e..7f340dc38f 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/FieldHighlightFactory.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/FieldHighlightFactory.java
@@ -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.
@@ -16,6 +15,7 @@
*/
package ghidra.app.util.viewer.field;
+import docking.widgets.fieldpanel.field.Field;
import docking.widgets.fieldpanel.support.Highlight;
import docking.widgets.fieldpanel.support.HighlightFactory;
import ghidra.app.util.HighlightProvider;
@@ -30,26 +30,22 @@ public class FieldHighlightFactory implements HighlightFactory {
private HighlightProvider provider;
private Class extends FieldFactory> fieldFactoryClass;
private Object obj;
-
+
/**
* Constructs a new FieldHighlightFactory.
* @param provider the HighlightProvider that will actually compute the highlights.
* @param fieldFactoryClass the class of the field factory that generated the field to be rendered.
* @param obj the object that holds the information that will be rendered (usually a code unit)
*/
- public FieldHighlightFactory(HighlightProvider provider, Class extends FieldFactory> fieldFactoryClass, Object obj) {
+ public FieldHighlightFactory(HighlightProvider provider,
+ Class extends FieldFactory> fieldFactoryClass, Object obj) {
this.provider = provider;
this.fieldFactoryClass = fieldFactoryClass;
this.obj = obj;
}
-
- /**
- * Returns the highlights for the given text.
- * @param text the text to be considered for highlighting.
- * @return an array of highlights to be rendered.
- */
- public Highlight[] getHighlights(String text, int cursorTextOffset) {
+
+ @Override
+ public Highlight[] getHighlights(Field field, String text, int cursorTextOffset) {
return provider.getHighlights(text, obj, fieldFactoryClass, cursorTextOffset);
}
-
}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/options/OptionsGui.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/options/OptionsGui.java
index 0ef35c6d47..4d58561dec 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/options/OptionsGui.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/options/OptionsGui.java
@@ -51,7 +51,8 @@ public class OptionsGui extends JPanel {
private static final Color DARK_ORANGE = new Color(255, 128, 0);
private static final Color DARK_RED = new Color(130, 0, 75);
private static final Highlight[] NO_HIGHLIGHTS = new Highlight[0];
- private static final HighlightFactory hlFactory = (text, cursorTextOffset) -> NO_HIGHLIGHTS;
+ private static final HighlightFactory hlFactory =
+ (field, text, cursorTextOffset) -> NO_HIGHLIGHTS;
public static final ScreenElement COMMENT_AUTO =
new ScreenElement("Comment, Automatic", Color.LIGHT_GRAY);
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/framework/main/DataTreeDialog.java b/Ghidra/Features/Base/src/main/java/ghidra/framework/main/DataTreeDialog.java
index cee3dd427a..526202aadd 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/framework/main/DataTreeDialog.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/framework/main/DataTreeDialog.java
@@ -26,6 +26,7 @@ import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import docking.*;
+import docking.event.mouse.GMouseListenerAdapter;
import docking.widgets.tree.support.GTreeSelectionEvent;
import docking.widgets.tree.support.GTreeSelectionListener;
import ghidra.framework.main.datatree.ClearCutAction;
@@ -40,7 +41,7 @@ import ghidra.util.layout.PairLayout;
* Dialog to open or save domain data items to a new location or name.
*/
public class DataTreeDialog extends DialogComponentProvider
-implements GTreeSelectionListener, ActionListener {
+ implements GTreeSelectionListener, ActionListener {
/**
* Dialog type for opening domain data files.
@@ -540,10 +541,11 @@ implements GTreeSelectionListener, ActionListener {
protected void addTreeListeners() {
if (type == OPEN) {
- treePanel.addTreeMouseListener(new MouseAdapter() {
+
+ treePanel.addTreeMouseListener(new GMouseListenerAdapter() {
@Override
- public void mousePressed(MouseEvent e) {
- if (e.getClickCount() == 2 && okButton.isEnabled()) {
+ public void doubleClickTriggered(MouseEvent e) {
+ if (okButton.isEnabled()) {
okCallback();
}
}
@@ -671,7 +673,7 @@ implements GTreeSelectionListener, ActionListener {
// populate the combo box
DefaultComboBoxModel model =
- (DefaultComboBoxModel) projectComboBox.getModel();
+ (DefaultComboBoxModel) projectComboBox.getModel();
model.removeAllElements();
Set map = new HashSet<>();
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/framework/main/datatree/GhidraDataFlavorHandlerService.java b/Ghidra/Features/Base/src/main/java/ghidra/framework/main/datatree/GhidraDataFlavorHandlerService.java
index 45967e040a..c17fe17662 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/framework/main/datatree/GhidraDataFlavorHandlerService.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/framework/main/datatree/GhidraDataFlavorHandlerService.java
@@ -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.
@@ -18,9 +17,10 @@ package ghidra.framework.main.datatree;
import java.awt.datatransfer.DataFlavor;
-public class GhidraDataFlavorHandlerService extends DataFlavorHandlerService {
- @Override
- protected void doRegisterDataFlavorHandlers() {
+public class GhidraDataFlavorHandlerService {
+
+ public GhidraDataFlavorHandlerService() {
+
try {
DataFlavor linuxFileUrlFlavor =
new DataFlavor("application/x-java-serialized-object;class=java.lang.String");
@@ -31,15 +31,12 @@ public class GhidraDataFlavorHandlerService extends DataFlavorHandlerService {
// should never happen as it is using java.lang.String
}
- final LocalTreeNodeHandler localTreeNodeHandler = new LocalTreeNodeHandler();
+ LocalTreeNodeHandler localNodeHandler = new LocalTreeNodeHandler();
DataTreeDragNDropHandler.addActiveDataFlavorHandler(
- DataTreeDragNDropHandler.localDomainFileTreeFlavor, localTreeNodeHandler);
+ DataTreeDragNDropHandler.localDomainFileTreeFlavor, localNodeHandler);
DataTreeDragNDropHandler.addActiveDataFlavorHandler(DataFlavor.javaFileListFlavor,
new JavaFileListHandler());
DataTreeDragNDropHandler.addActiveDataFlavorHandler(
VersionInfoTransferable.localVersionInfoFlavor, new LocalVersionInfoHandler());
-
- DataTreeDragNDropHandler.addInactiveDataFlavorHandler(
- DataTreeDragNDropHandler.localDomainFileTreeFlavor, localTreeNodeHandler);
}
}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/framework/main/datatree/JavaFileListHandler.java b/Ghidra/Features/Base/src/main/java/ghidra/framework/main/datatree/JavaFileListHandler.java
index 69c8bb74a5..cf3c03d8a8 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/framework/main/datatree/JavaFileListHandler.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/framework/main/datatree/JavaFileListHandler.java
@@ -19,13 +19,15 @@
package ghidra.framework.main.datatree;
import java.awt.datatransfer.DataFlavor;
+import java.awt.dnd.DropTargetDropEvent;
import java.io.File;
import java.util.List;
import docking.widgets.tree.GTreeNode;
import ghidra.app.services.FileImporterService;
-import ghidra.framework.main.FrontEndTool;
+import ghidra.app.util.FileOpenDataFlavorHandler;
import ghidra.framework.model.DomainFolder;
+import ghidra.framework.plugintool.PluginTool;
import ghidra.util.Msg;
import util.CollectionUtils;
@@ -33,24 +35,43 @@ import util.CollectionUtils;
* A drag-and-drop handler for trees that is specific to List<File>. (see
* {@link DataFlavor#javaFileListFlavor}).
*/
-final class JavaFileListHandler implements DataFlavorHandler {
- @Override
- public void handle(FrontEndTool tool, DataTree dataTree, GTreeNode destinationNode,
- Object transferData, int dropAction) {
- DomainFolder folder = getDomainFolder(destinationNode);
+public final class JavaFileListHandler implements DataTreeFlavorHandler, FileOpenDataFlavorHandler {
- FileImporterService im = tool.getService(FileImporterService.class);
- if (im == null) {
- Msg.showError(this, dataTree, "Could Not Import", "Could not find importer service");
+ @Override
+ public void handle(PluginTool tool, Object transferData, DropTargetDropEvent e, DataFlavor f) {
+
+ FileImporterService importer = tool.getService(FileImporterService.class);
+ if (importer == null) {
+ Msg.showError(this, null, "Could Not Import", "Could not find Importer Service");
return;
}
- List fileList = CollectionUtils.asList((List>) transferData, File.class);
+ DomainFolder folder = tool.getProject().getProjectData().getRootFolder();
+ doImport(importer, folder, transferData);
+ }
+
+ @Override
+ public void handle(PluginTool tool, DataTree dataTree, GTreeNode destinationNode,
+ Object transferData, int dropAction) {
+
+ FileImporterService importer = tool.getService(FileImporterService.class);
+ if (importer == null) {
+ Msg.showError(this, dataTree, "Could Not Import", "Could not find Importer Service");
+ return;
+ }
+
+ DomainFolder folder = getDomainFolder(destinationNode);
+ doImport(importer, folder, transferData);
+ }
+
+ private void doImport(FileImporterService importer, DomainFolder folder, Object files) {
+
+ List fileList = CollectionUtils.asList((List>) files, File.class);
if (fileList.size() == 1 && fileList.get(0).isFile()) {
- im.importFile(folder, fileList.get(0));
+ importer.importFile(folder, fileList.get(0));
}
else {
- im.importFiles(folder, fileList);
+ importer.importFiles(folder, fileList);
}
}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/framework/main/datatree/LinuxFileUrlHandler.java b/Ghidra/Features/Base/src/main/java/ghidra/framework/main/datatree/LinuxFileUrlHandler.java
index 9c6f1c115b..16a7e690ef 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/framework/main/datatree/LinuxFileUrlHandler.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/framework/main/datatree/LinuxFileUrlHandler.java
@@ -27,7 +27,6 @@ import java.util.function.Function;
import docking.widgets.tree.GTreeNode;
import ghidra.app.services.FileImporterService;
import ghidra.app.util.FileOpenDataFlavorHandler;
-import ghidra.framework.main.FrontEndTool;
import ghidra.framework.model.DomainFolder;
import ghidra.framework.plugintool.PluginTool;
import ghidra.framework.plugintool.ServiceProvider;
@@ -38,11 +37,11 @@ import ghidra.util.Msg;
* duty in that it opens files for DataTrees and for Tools (signaled via the interfaces it
* implements).
*/
-public final class LinuxFileUrlHandler implements DataFlavorHandler, FileOpenDataFlavorHandler {
+public final class LinuxFileUrlHandler implements DataTreeFlavorHandler, FileOpenDataFlavorHandler {
@Override
// This is for the DataFlavorHandler interface for handling node drops in DataTrees
- public void handle(FrontEndTool tool, DataTree dataTree, GTreeNode destinationNode,
+ public void handle(PluginTool tool, DataTree dataTree, GTreeNode destinationNode,
Object transferData, int dropAction) {
DomainFolder folder = getDomainFolder(destinationNode);
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/program/util/DiffUtility.java b/Ghidra/Features/Base/src/main/java/ghidra/program/util/DiffUtility.java
index 7b4d9cbf4d..8d8c87e32a 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/program/util/DiffUtility.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/program/util/DiffUtility.java
@@ -193,11 +193,11 @@ public class DiffUtility extends SimpleDiffUtility {
return otherProgram.getSymbolTable().createExternalLibrary(namespace.getName(), source);
}
else if (namespace instanceof GhidraClass) {
- return otherProgram.getSymbolTable().createClass(otherParentNamespace,
- namespace.getName(), source);
+ return otherProgram.getSymbolTable()
+ .createClass(otherParentNamespace, namespace.getName(), source);
}
- return otherProgram.getSymbolTable().createNameSpace(otherParentNamespace,
- namespace.getName(), source);
+ return otherProgram.getSymbolTable()
+ .createNameSpace(otherParentNamespace, namespace.getName(), source);
}
// /**
@@ -329,11 +329,11 @@ public class DiffUtility extends SimpleDiffUtility {
if (toAddr == null) {
return null;
}
- return otherProgram.getReferenceManager().getReference(fromAddr, toAddr,
- ref.getOperandIndex());
+ return otherProgram.getReferenceManager()
+ .getReference(fromAddr, toAddr, ref.getOperandIndex());
}
- Reference otherRef = otherProgram.getReferenceManager().getPrimaryReferenceFrom(fromAddr,
- ref.getOperandIndex());
+ Reference otherRef = otherProgram.getReferenceManager()
+ .getPrimaryReferenceFrom(fromAddr, ref.getOperandIndex());
if (otherRef != null && ref.getToAddress().hasSameAddressSpace(otherRef.getToAddress())) {
return otherRef;
}
@@ -357,11 +357,11 @@ public class DiffUtility extends SimpleDiffUtility {
if (toAddr1 == null) {
return null;
}
- return program.getReferenceManager().getReference(fromAddr1, toAddr1,
- p2Ref.getOperandIndex());
+ return program.getReferenceManager()
+ .getReference(fromAddr1, toAddr1, p2Ref.getOperandIndex());
}
- Reference p1Ref = program.getReferenceManager().getPrimaryReferenceFrom(fromAddr1,
- p2Ref.getOperandIndex());
+ Reference p1Ref = program.getReferenceManager()
+ .getPrimaryReferenceFrom(fromAddr1, p2Ref.getOperandIndex());
if (p1Ref != null && p1Ref.getToAddress().hasSameAddressSpace(p2Ref.getToAddress())) {
return p1Ref;
}
@@ -385,8 +385,9 @@ public class DiffUtility extends SimpleDiffUtility {
otherAddr = getCompatibleAddress(program, addr, otherProgram);
}
// FIXME Should this be passing the Namespace?
- return otherProgram.getExternalManager().addExtLocation(extLoc.getLibraryName(),
- extLoc.getLabel(), otherAddr, extLoc.getSource());
+ return otherProgram.getExternalManager()
+ .addExtLocation(extLoc.getLibraryName(), extLoc.getLabel(), otherAddr,
+ extLoc.getSource());
}
/**
@@ -707,6 +708,9 @@ public class DiffUtility extends SimpleDiffUtility {
Address refAddress = getCompatibleAddress(program, location.refAddr, otherProgram);
if (address != null) {
+ if (byteAddress == null) {
+ byteAddress = address; // Make sure the byte address isn't null.
+ }
ProgramLocation otherLocation = new ProgramLocation(otherProgram, address, byteAddress,
location.getComponentPath(), refAddress, 0, 0, 0);
return otherLocation;
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/program/util/ProgramDiffDetails.java b/Ghidra/Features/Base/src/main/java/ghidra/program/util/ProgramDiffDetails.java
index d0cb2dfefd..751d08d165 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/program/util/ProgramDiffDetails.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/program/util/ProgramDiffDetails.java
@@ -2555,7 +2555,7 @@ public class ProgramDiffDetails {
}
private void addColorAddress(StyledDocument doc, Address addr) {
- String text = addr.toString();
+ String text = (addr != null) ? addr.toString() : "no matching address";
color(ADDRESS_COLOR);
try {
doc.insertString(doc.getLength(), text, textAttrSet);
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/program/util/SymbolicPropogator.java b/Ghidra/Features/Base/src/main/java/ghidra/program/util/SymbolicPropogator.java
index 5486eb65ac..11b468a459 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/program/util/SymbolicPropogator.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/program/util/SymbolicPropogator.java
@@ -43,7 +43,7 @@ public class SymbolicPropogator {
// 1. How are "register-relative" varnodes distinguished based upon target space ? Not sure how we handle wrapping/truncation concerns.
// 1) The offset is the only thing that could be used as a reference.
- private static final int _POINTER_MIN_BOUNDS = 0x7fff;
+ private static final int _POINTER_MIN_BOUNDS = 0x100;
// mask for sub-piece extraction
private static long[] maskSize = { 0xffL, 0xffL, 0xffffL, 0xffffffL, 0xffffffffL, 0xffffffffffL,
@@ -1836,7 +1836,7 @@ public class SymbolicPropogator {
// see if the offset is a large constant offset from the symbolic space
long offset = refLocation.getOffset();
- if (checkPossibleOffsetAddr(offset)) {
+ if (evaluator != null) {
// symbolic spaces will have the name of the symbolic space be the register space
// String spaceName = refLocation.getAddress().getAddressSpace().getName();
// Register register = vContext.getRegister(spaceName);
@@ -1850,7 +1850,7 @@ public class SymbolicPropogator {
// }
// } else
- if (evaluator == null) {
+ if (!vContext.isStackSymbolicSpace(refLocation) && evaluator != null) {
Address constant = program.getAddressFactory().getAddress(
(int) targetSpaceID.getOffset(), offset);
Address newTarget = evaluator.evaluateConstant(vContext, instruction,
@@ -2051,7 +2051,7 @@ public class SymbolicPropogator {
*/
private int getReferenceSpaceID(Instruction instruction, long offset) {
// TODO: this should be passed to the client callback to make the decision
- if (offset <= 4096 && offset >= -1) {
+ if (offset <= 4 && offset >= -1) {
return -1; // don't make speculative reference to certain offset values
}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/program/util/VarnodeContext.java b/Ghidra/Features/Base/src/main/java/ghidra/program/util/VarnodeContext.java
index 6266f9d77c..8be976f8d9 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/program/util/VarnodeContext.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/program/util/VarnodeContext.java
@@ -312,7 +312,7 @@ public class VarnodeContext implements ProcessorContext {
/**
* Return true if this varnode is stored in the symbolic stack space
*/
- private boolean isStackSymbolicSpace(Varnode varnode) {
+ public boolean isStackSymbolicSpace(Varnode varnode) {
// symbolic spaces are off of a register, find the space
AddressSpace regSpace = addrFactory.getAddressSpace(varnode.getSpace());
@@ -785,7 +785,9 @@ public class VarnodeContext implements ProcessorContext {
* return the location that this register was last set
* This is a transient thing, so it should only be used as a particular flow is being processed...
*
- * @param reg
+ * @param reg register to find last set location
+ * @param bval value to look for to differentiate set locations, null if don't care
+ *
* @return address that the register was set.
*/
public Address getLastSetLocation(Register reg, BigInteger bval) {
@@ -1256,6 +1258,13 @@ public class VarnodeContext implements ProcessorContext {
// too big anyway,already extended as far as it will go.
vnodeVal = createConstantVarnode(vnodeVal.getOffset(), out.getSize());
}
+ } else if (vnodeVal.isRegister() && vnodeVal.getSize() < out.getSize()) {
+ Register reg = getRegister(vnodeVal);
+ if (reg == null) {
+ throw notFoundExc;
+ }
+ int spaceID = getAddressSpace(reg.getName());
+ vnodeVal = createVarnode(0,spaceID,out.getSize());
}
return vnodeVal;
}
diff --git a/Ghidra/Features/Base/src/test/java/ghidra/framework/options/OptionsTest.java b/Ghidra/Features/Base/src/test/java/ghidra/framework/options/OptionsTest.java
index 6e468ee1e2..792f46f2c9 100644
--- a/Ghidra/Features/Base/src/test/java/ghidra/framework/options/OptionsTest.java
+++ b/Ghidra/Features/Base/src/test/java/ghidra/framework/options/OptionsTest.java
@@ -623,7 +623,7 @@ public class OptionsTest extends AbstractGenericTest {
@Override
public int hashCode() {
- return 1;// set so that this listener gets called after the storingOptionsListnere
+ return 1;// set so that this listener gets called after the storingOptionsListener
}
}
diff --git a/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/ByteField.java b/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/ByteField.java
index b2e3dbd969..db7371f355 100644
--- a/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/ByteField.java
+++ b/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/ByteField.java
@@ -15,8 +15,6 @@
*/
package ghidra.app.plugin.core.byteviewer;
-import ghidra.util.ColorUtils;
-
import java.awt.*;
import java.math.BigInteger;
@@ -28,6 +26,7 @@ import docking.widgets.fieldpanel.internal.FieldBackgroundColorManager;
import docking.widgets.fieldpanel.internal.PaintContext;
import docking.widgets.fieldpanel.support.HighlightFactory;
import docking.widgets.fieldpanel.support.RowColLocation;
+import ghidra.util.ColorUtils;
/**
* Fields for the ByteViewer. This class extends the SimpleTextField to include
@@ -52,7 +51,8 @@ public class ByteField extends SimpleTextField {
* @param hlFactory the factory used to create highlights
*/
public ByteField(String text, FontMetrics fontMetrics, int startX, int width,
- boolean allowCursorAtEnd, int fieldOffset, BigInteger index, HighlightFactory hlFactory) {
+ boolean allowCursorAtEnd, int fieldOffset, BigInteger index,
+ HighlightFactory hlFactory) {
super(text, fontMetrics, startX, width, allowCursorAtEnd, hlFactory);
this.fieldOffset = fieldOffset;
@@ -64,7 +64,7 @@ public class ByteField extends SimpleTextField {
public void paint(JComponent c, Graphics g, PaintContext context,
FieldBackgroundColorManager colorManager, RowColLocation cursorLoc, int rowHeight) {
paintSelection(g, colorManager, 0);
- paintHighlights(g, hlFactory.getHighlights(text, -1));
+ paintHighlights(g, hlFactory.getHighlights(this, text, -1));
g.setFont(metrics.getFont());
if (foregroundColor == null) {
foregroundColor = context.getForeground();
diff --git a/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/FieldFactory.java b/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/FieldFactory.java
index b821e8b3c9..81ed547bfb 100644
--- a/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/FieldFactory.java
+++ b/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/FieldFactory.java
@@ -213,7 +213,7 @@ class FieldFactory {
}
@Override
- public Highlight[] getHighlights(String text, int cursorTextOffset) {
+ public Highlight[] getHighlights(Field field, String text, int cursorTextOffset) {
return provider.getHighlights(text, null, null, -1);
}
}
diff --git a/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/IndexFieldFactory.java b/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/IndexFieldFactory.java
index bd828d425e..cb7ae28d6c 100644
--- a/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/IndexFieldFactory.java
+++ b/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/IndexFieldFactory.java
@@ -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.
@@ -16,8 +15,6 @@
*/
package ghidra.app.plugin.core.byteviewer;
-import ghidra.app.plugin.core.format.ByteBlockInfo;
-
import java.awt.Color;
import java.awt.FontMetrics;
import java.math.BigInteger;
@@ -26,6 +23,7 @@ import docking.widgets.fieldpanel.field.Field;
import docking.widgets.fieldpanel.field.SimpleTextField;
import docking.widgets.fieldpanel.support.Highlight;
import docking.widgets.fieldpanel.support.HighlightFactory;
+import ghidra.app.plugin.core.format.ByteBlockInfo;
/**
* Implementation for the index/address field.
@@ -145,7 +143,7 @@ class IndexFieldFactory {
}
@Override
- public Highlight[] getHighlights(String text, int cursorTextOffset) {
+ public Highlight[] getHighlights(Field field, String text, int cursorTextOffset) {
return NO_HIGHLIGHTS;
}
}
diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/ruleaction.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/ruleaction.cc
index af1165c37b..e4326eaffd 100644
--- a/Ghidra/Features/Decompiler/src/decompile/cpp/ruleaction.cc
+++ b/Ghidra/Features/Decompiler/src/decompile/cpp/ruleaction.cc
@@ -7333,8 +7333,12 @@ bool RuleConditionalMove::BoolExpress::evaluatePropagation(FlowBlock *root,FlowB
if (root == branch) return true; // Can always propagate if there is no branch
if (op->getParent() != branch) return true; // Can propagate if value formed before branch
mustreconstruct = true; // Final op is performed in branch, so it must be reconstructed
+ if (in0->isFree() && !in0->isConstant()) return false;
if (in0->isWritten() && (in0->getDef()->getParent()==branch)) return false;
- if ((optype==2) && in1->isWritten() && (in1->getDef()->getParent()==branch)) return false;
+ if (optype == 2) {
+ if (in1->isFree() && !in1->isConstant()) return false;
+ if (in1->isWritten() && (in1->getDef()->getParent()==branch)) return false;
+ }
return true;
}
diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/component/ClangTextField.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/component/ClangTextField.java
index 46020f53ca..4968cf02c6 100644
--- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/component/ClangTextField.java
+++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/component/ClangTextField.java
@@ -1,5 +1,6 @@
/* ###
* 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.
@@ -197,4 +198,8 @@ public class ClangTextField extends WrappingVerticalLayoutTextField {
return lineNumberFieldElement.getStringWidth();
}
+ public int getLineNumber() {
+ String text = lineNumberFieldElement.getText().trim();
+ return Integer.parseInt(text);
+ }
}
diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/component/DecompilerHoverProvider.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/component/DecompilerHoverProvider.java
index 0f54d60bcb..63f1cc7c67 100644
--- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/component/DecompilerHoverProvider.java
+++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/component/DecompilerHoverProvider.java
@@ -76,8 +76,9 @@ public class DecompilerHoverProvider extends AbstractHoverProvider {
Varnode vn = token.getVarnode();
if (vn != null) {
- if (vn.getHigh() instanceof HighGlobal) {
- reference = vn.getAddress();
+ HighVariable highVar = vn.getHigh();
+ if (highVar instanceof HighGlobal) {
+ reference = highVar.getRepresentative().getAddress();
}
}
diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/component/DecompilerManager.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/component/DecompilerManager.java
index 617215edb3..f56bba85a7 100644
--- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/component/DecompilerManager.java
+++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/component/DecompilerManager.java
@@ -51,7 +51,7 @@ public class DecompilerManager {
this.decompilerController = decompilerController;
runManager = new RunManager("Decompiler", null);
- decompiler = new Decompiler(options, options.getDefaultTimeout());
+ decompiler = new Decompiler(options, 0);
updateManager = new SwingUpdateManager(500, () -> doPendingDecompile());
}
diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/component/DecompilerPanel.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/component/DecompilerPanel.java
index aed2123de5..0a06f0f9d9 100644
--- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/component/DecompilerPanel.java
+++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/component/DecompilerPanel.java
@@ -37,11 +37,11 @@ import docking.widgets.indexedscrollpane.IndexedScrollPane;
import ghidra.app.decompiler.*;
import ghidra.app.decompiler.component.hover.DecompilerHoverService;
import ghidra.app.plugin.core.decompile.DecompileClipboardProvider;
+import ghidra.app.plugin.core.decompile.actions.FieldBasedSearchLocation;
import ghidra.program.model.address.*;
import ghidra.program.model.listing.Function;
import ghidra.program.model.listing.Program;
-import ghidra.program.model.pcode.PcodeOp;
-import ghidra.program.model.pcode.Varnode;
+import ghidra.program.model.pcode.*;
import ghidra.program.util.ProgramLocation;
import ghidra.program.util.ProgramSelection;
import ghidra.util.*;
@@ -175,6 +175,9 @@ public class DecompilerPanel extends JPanel implements FieldMouseListener, Field
if (clipboard != null) {
clipboard.selectionChanged(null);
}
+
+ // don't highlight search results across functions
+ currentSearchLocation = null;
}
private void setLocation(DecompileData oldData, DecompileData newData) {
@@ -419,6 +422,10 @@ public class DecompilerPanel extends JPanel implements FieldMouseListener, Field
}
}
+ HighVariable highVar = vn.getHigh();
+ if (highVar instanceof HighGlobal) {
+ vn = highVar.getRepresentative();
+ }
if (vn.isAddress()) {
Address addr = vn.getAddress();
if (addr.isMemoryAddress()) {
@@ -696,9 +703,21 @@ public class DecompilerPanel extends JPanel implements FieldMouseListener, Field
}
class SearchHighlightFactory implements HighlightFactory {
+
@Override
- public Highlight[] getHighlights(String text, int cursorTextOffset) {
- if (currentSearchLocation == null || cursorTextOffset == -1) {
+ public Highlight[] getHighlights(Field field, String text, int cursorTextOffset) {
+ if (currentSearchLocation == null) {
+ return new Highlight[0];
+ }
+
+ ClangTextField cField = (ClangTextField) field;
+ int highlightLine = cField.getLineNumber();
+
+ FieldLocation searchCursorLocation =
+ ((FieldBasedSearchLocation) currentSearchLocation).getFieldLocation();
+ int searchLineNumber = searchCursorLocation.getIndex().intValue() + 1;
+ if (highlightLine != searchLineNumber) {
+ // only highlight the match on the actual line
return new Highlight[0];
}
diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/FieldBasedSearchLocation.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/FieldBasedSearchLocation.java
index 0d1434155c..191c32cc21 100644
--- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/FieldBasedSearchLocation.java
+++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/FieldBasedSearchLocation.java
@@ -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.
@@ -39,4 +38,9 @@ public class FieldBasedSearchLocation extends SearchLocation {
public CursorPosition getCursorPosition() {
return new DecompilerCursorPosition(fieldLocation);
}
+
+ @Override
+ protected String fieldsToString() {
+ return super.fieldsToString() + ", fieldLocation=" + fieldLocation;
+ }
}
diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/FindAction.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/FindAction.java
index 78c48a7cf4..70b23623e0 100644
--- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/FindAction.java
+++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/FindAction.java
@@ -1,5 +1,6 @@
/* ###
* 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.
@@ -77,13 +78,20 @@ public class FindAction extends DockingAction {
if (text != null) {
dialog.setSearchText(text);
}
+
// show over the root frame, so the user can still see the Decompiler window
tool.showDialog(dialog);
}
protected FindDialog getFindDialog() {
if (findDialog == null) {
- findDialog = new FindDialog("Decompiler Find Text", new DecompilerSearcher());
+ findDialog = new FindDialog("Decompiler Find Text", new DecompilerSearcher()) {
+ @Override
+ protected void dialogClosed() {
+ // clear the search results when the dialog is closed
+ decompilerPanel.setSearchResults(null);
+ }
+ };
findDialog.setHelpLocation(new HelpLocation("DecompilePlugin", "Find"));
}
return findDialog;
diff --git a/Ghidra/Features/FileFormats/data/build.xml b/Ghidra/Features/FileFormats/data/build.xml
deleted file mode 100644
index 8f72019712..0000000000
--- a/Ghidra/Features/FileFormats/data/build.xml
+++ /dev/null
@@ -1,73 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Ghidra/Features/PDB/src/global/docs/README_PDB.html b/Ghidra/Features/PDB/src/global/docs/README_PDB.html
index 7fff3b07c6..3b39a8ef11 100644
--- a/Ghidra/Features/PDB/src/global/docs/README_PDB.html
+++ b/Ghidra/Features/PDB/src/global/docs/README_PDB.html
@@ -75,9 +75,9 @@ of Visual Studio and DIA SDK.
First, check to see if you already have the msdia140.dll library installed on your system.
It is generally installed installed with Microsoft Visual Studio 2017 when C/C++ development support
-is included.
+is included ( may be Community, Professional, or other VS 2017 distribution package name).
- C:\\Program Files (x86)\Microsoft Visual Studio\2017\DIA SDK\bin\amd64\msdia140.dll
+ C:\Program Files (x86)\Microsoft Visual Studio\2017\\DIA SDK\bin\amd64\msdia140.dll
This file is commonly located here, although it may be installed in other locations as well. Any 64-bit
copy may be registered provided it is the correct version. There is no need to register more than
@@ -86,8 +86,8 @@ one.
Register 'msdia140.dll' in the Windows registry
Please register 64-bit msdia140.dll even if you already had a copy of it on your computer
-since it is not registered by the Visual Studio installation process. You will need administrative rights/privileges in order to register the DLL in the Windows
-registry.
+since it is not registered by the Visual Studio installation process. You will need administrative
+rights/privileges in order to register the DLL in the Windows registry.
Start a command prompt as an administrator:
diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb/PdbParserNEW.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb/PdbParserNEW.java
index 9a446da18d..6adbba1967 100644
--- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb/PdbParserNEW.java
+++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb/PdbParserNEW.java
@@ -576,6 +576,9 @@ public class PdbParserNEW {
}
catch (Exception e) {
if (!isXML) {
+ if (hasErrors()) {
+ throw new PdbException(getErrorAndWarningMessages());
+ }
throw new PdbException("PDB Execution failure of " + PDB_EXE + ".\n" +
"This was likely caused by severe execution failure which can occur if executed\n" +
"on an unsupported platform. It may be neccessary to rebuild the PDB executable\n" +
diff --git a/Ghidra/Features/PDB/src/pdb/cpp/err.cpp b/Ghidra/Features/PDB/src/pdb/cpp/err.cpp
index 47bc2d14f1..bf22cc23bf 100644
--- a/Ghidra/Features/PDB/src/pdb/cpp/err.cpp
+++ b/Ghidra/Features/PDB/src/pdb/cpp/err.cpp
@@ -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.
@@ -26,9 +25,7 @@ void warning( const char * msg )
void fatal( const char * msg )
{
- fprintf( stderr, "ERROR:\n" );
- fprintf( stderr, msg );
- fprintf( stderr, "\n" );
+ fprintf( stderr, "ERROR: %s\n", msg );
exit( -1 );
}
diff --git a/Ghidra/Features/PDB/src/pdb/cpp/pdb.cpp b/Ghidra/Features/PDB/src/pdb/cpp/pdb.cpp
index 4aedf4c8c6..b08daa7b14 100644
--- a/Ghidra/Features/PDB/src/pdb/cpp/pdb.cpp
+++ b/Ghidra/Features/PDB/src/pdb/cpp/pdb.cpp
@@ -46,9 +46,8 @@ int init(const char * szFilename, const char * szSignature, const char * szAge)
if (hr < 0) {
switch (hr) {
case REGDB_E_CLASSNOTREG:
- fatal("Unable to locate the DIA SDK. It is required to load PDB files.\n\n" \
- "* Open {Ghidra install root}/docs/README_PDB.html\n"
- " and follow the instructions therein.\n");
+ fatal("Unable to locate the DIA SDK. It is required to load PDB files.\n" \
+ "* See docs/README_PDB.html for DLL registration instructions.\n");
break;
default:
char msg[256];
diff --git a/Ghidra/Features/PDB/src/pdb/pdb.vcxproj b/Ghidra/Features/PDB/src/pdb/pdb.vcxproj
index 002c8a5723..500065d27c 100644
--- a/Ghidra/Features/PDB/src/pdb/pdb.vcxproj
+++ b/Ghidra/Features/PDB/src/pdb/pdb.vcxproj
@@ -72,7 +72,7 @@
rem copy /y /v /b "$(VSInstallDir)DIA SDK\bin\amd64\msdia*.dll" "$(OutDir)"
-set OS_DIR="$(SolutionDir)..\..\os"
+set OS_DIR=$(SolutionDir)..\..\os
if exist "%OS_DIR%\win64" (
mkdir "%OS_DIR%"
mkdir "%OS_DIR%\win64"
@@ -104,7 +104,7 @@ if exist "%OS_DIR%\win64" (
rem copy /y /v /b "$(VSInstallDir)DIA SDK\bin\amd64\msdia*.dll" "$(OutDir)"
-set OS_DIR="$(SolutionDir)..\..\os"
+set OS_DIR=$(SolutionDir)..\..\os
if exist "%OS_DIR%\win64" (
mkdir "%OS_DIR%"
mkdir "%OS_DIR%\win64"
diff --git a/Ghidra/Features/ProgramDiff/src/main/java/ghidra/app/plugin/core/diff/ProgramDiffPlugin.java b/Ghidra/Features/ProgramDiff/src/main/java/ghidra/app/plugin/core/diff/ProgramDiffPlugin.java
index 9240662b1a..04183ab7cd 100644
--- a/Ghidra/Features/ProgramDiff/src/main/java/ghidra/app/plugin/core/diff/ProgramDiffPlugin.java
+++ b/Ghidra/Features/ProgramDiff/src/main/java/ghidra/app/plugin/core/diff/ProgramDiffPlugin.java
@@ -441,6 +441,9 @@ public class ProgramDiffPlugin extends ProgramPlugin
Address primaryByteAddr = SimpleDiffUtility.getCompatibleAddress(secondaryDiffProgram,
byteAddr, primaryProgram);
+ if (primaryByteAddr == null) {
+ primaryByteAddr = primaryAddr; // Make sure the byte address isn't null.
+ }
Address primaryRefAddr = SimpleDiffUtility.getCompatibleAddress(secondaryDiffProgram,
refAddr, primaryProgram);
ProgramLocation newP1Location = new ProgramLocation(primaryProgram, primaryAddr,
@@ -463,7 +466,9 @@ public class ProgramDiffPlugin extends ProgramPlugin
}
ProgramLocation previousP1LocationAsP2 = DiffUtility
.getCompatibleProgramLocation(primaryProgram, location, secondaryDiffProgram);
- diffListingPanel.setCursorPosition(previousP1LocationAsP2);
+ if (previousP1LocationAsP2 != null) {
+ diffListingPanel.setCursorPosition(previousP1LocationAsP2);
+ }
if (diffDetailsProvider != null && diffDetails != null) {
diffDetailsProvider.locationChanged(previousP1Location);
}
@@ -749,7 +754,7 @@ public class ProgramDiffPlugin extends ProgramPlugin
runSwing(() -> {
MarkerSet selectionMarkers = getSelectionMarkers();
selectionMarkers.clearAll();
- selectionMarkers.add(p2SelectionAsP1);
+ selectionMarkers.add(p2Selection);
});
diffListingPanel.setSelection(p2SelectionAsP1);
@@ -798,9 +803,9 @@ public class ProgramDiffPlugin extends ProgramPlugin
// Limit the apply to the selection in the view.
AddressSet p2SelectionAsP1 =
DiffUtility.getCompatibleAddressSet(p2Selection, primaryProgram);
- AddressSet p1ApplySet =
- p2SelectionAsP1.intersect(p1ViewAddrSet).subtract(addressesOnlyInP1).subtract(
- compatibleOnlyInP2);
+ AddressSet p1ApplySet = p2SelectionAsP1.intersect(p1ViewAddrSet)
+ .subtract(addressesOnlyInP1)
+ .subtract(compatibleOnlyInP2);
if (p1ApplySet.isEmpty()) {
Msg.showInfo(getClass(), tool.getToolFrame(), "Apply Differences",
(p2Selection.isEmpty()) ? "No diff selection in the current view."
@@ -860,7 +865,7 @@ public class ProgramDiffPlugin extends ProgramPlugin
// Right side markers need p1 addresses since they use p1 indexMap.
MarkerSet diffMarkers = getDiffMarkers(); // Get right side markers for program 2.
diffMarkers.clearAll();
- diffMarkers.add(p2DiffSetAsP1);
+ diffMarkers.add(p2DiffSet);
MarkerSet codeViewerDiffMarkers = getCodeViewerMarkers(); // Get left side markers for program 1.
codeViewerDiffMarkers.clearAll();
@@ -884,7 +889,7 @@ public class ProgramDiffPlugin extends ProgramPlugin
AddressSet p1DiffHighlightSet =
DiffUtility.getCompatibleAddressSet(p2Highlight, primaryProgram);
p2DiffHighlight = p2Highlight;
- diffMarkers.add(p1DiffHighlightSet);
+ diffMarkers.add(p2Highlight);
codeViewerDiffMarkers.add(p1DiffHighlightSet);
}
@@ -1603,7 +1608,14 @@ public class ProgramDiffPlugin extends ProgramPlugin
diffListingPanel.goTo(currentLocation);
MarkerSet cursorMarkers = getCursorMarkers();
- cursorMarkers.setAddressSet(new AddressSet(currentLocation.getAddress()));
+ Address currentP2Address = currentLocation.getAddress();
+ if (currentLocation.getProgram() != secondaryDiffProgram) { // Make sure address is from P2.
+ currentP2Address = SimpleDiffUtility.getCompatibleAddress(currentLocation.getProgram(),
+ currentLocation.getAddress(), secondaryDiffProgram);
+ }
+ if (currentP2Address != null) {
+ cursorMarkers.setAddressSet(new AddressSet(currentP2Address));
+ }
updatePgm2Enablement();
diff --git a/Ghidra/Framework/Docking/src/main/java/docking/ActionContext.java b/Ghidra/Framework/Docking/src/main/java/docking/ActionContext.java
index 3fed77d232..f9d950e63e 100644
--- a/Ghidra/Framework/Docking/src/main/java/docking/ActionContext.java
+++ b/Ghidra/Framework/Docking/src/main/java/docking/ActionContext.java
@@ -47,7 +47,12 @@ public class ActionContext {
}
/**
- * For Testing
+ * Constructor
+ *
+ * @param provider the ComponentProvider that generated this context.
+ * @param contextObject an optional contextObject that the ComponentProvider can provide
+ * @param sourceObject an optional source object; this can be anything that actions wish to
+ * later retrieve
*/
public ActionContext(ComponentProvider provider, Object contextObject, Object sourceObject) {
this(provider, contextObject);
@@ -55,8 +60,8 @@ public class ActionContext {
}
/**
- * Returns the {@link #ComponentProvider} that generated this ActionContext
- * @return
+ * Returns the {@link ComponentProvider} that generated this ActionContext
+ * @return the provider
*/
public ComponentProvider getComponentProvider() {
return provider;
diff --git a/Ghidra/Framework/Docking/src/main/java/docking/ComponentProvider.java b/Ghidra/Framework/Docking/src/main/java/docking/ComponentProvider.java
index 521b6c2452..6427e1ac17 100644
--- a/Ghidra/Framework/Docking/src/main/java/docking/ComponentProvider.java
+++ b/Ghidra/Framework/Docking/src/main/java/docking/ComponentProvider.java
@@ -170,8 +170,11 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext
*/
public boolean isFocusedProvider() {
DockingWindowManager dwm = DockingWindowManager.getInstance(getComponent());
+ if (dwm == null) {
+ return false; // can happen in testing
+ }
ComponentPlaceholder placeholder = dwm.getFocusedComponent();
- return placeholder.getProvider() == this;
+ return placeholder != null && placeholder.getProvider() == this;
}
/**
diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/SearchLocation.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/SearchLocation.java
index 9dd7087fe0..064f241389 100644
--- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/SearchLocation.java
+++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/SearchLocation.java
@@ -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.
@@ -60,6 +59,10 @@ public class SearchLocation {
@Override
public String toString() {
- return searchText + "[start=" + startIndexInclusive + ", end=" + endIndexInclusive + "]";
+ return searchText + "[" + fieldsToString() + "]";
+ }
+
+ protected String fieldsToString() {
+ return startIndexInclusive + ", end=" + endIndexInclusive;
}
}
diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/dialogs/ObjectChooserDialog.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/dialogs/ObjectChooserDialog.java
index 0aa754119b..7c9da99b61 100644
--- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/dialogs/ObjectChooserDialog.java
+++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/dialogs/ObjectChooserDialog.java
@@ -63,7 +63,7 @@ public class ObjectChooserDialog extends DialogComponentProvider {
table.addSelectionListener(t -> objectSelected(t));
- table.setItemPickListner(t -> objectPicked(t));
+ table.setItemPickListener(t -> objectPicked(t));
return table;
}
diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/fieldpanel/field/ClippingTextField.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/fieldpanel/field/ClippingTextField.java
index 506e1f8667..bb25ba0477 100644
--- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/fieldpanel/field/ClippingTextField.java
+++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/fieldpanel/field/ClippingTextField.java
@@ -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.
@@ -129,8 +128,8 @@ public class ClippingTextField implements TextField {
int x = findX(col) + startX;
- return new Rectangle(x, -textElement.getHeightAbove(), 2, textElement.getHeightAbove() +
- textElement.getHeightBelow());
+ return new Rectangle(x, -textElement.getHeightAbove(), 2,
+ textElement.getHeightAbove() + textElement.getHeightBelow());
}
/**
@@ -315,7 +314,7 @@ public class ClippingTextField implements TextField {
if (cursorLoc != null) {
cursorTextOffset = screenLocationToTextOffset(cursorLoc.row(), cursorLoc.col());
}
- paintHighlights(g, hlFactory.getHighlights(getString(), cursorTextOffset));
+ paintHighlights(g, hlFactory.getHighlights(this, getString(), cursorTextOffset));
}
protected void paintSelection(Graphics g, FieldBackgroundColorManager colorManager, int row,
@@ -344,10 +343,10 @@ public class ClippingTextField implements TextField {
}
protected void paintHighlights(Graphics g, Highlight[] highlights) {
- for (int i = 0; i < highlights.length; i++) {
- int startCol = Math.max(highlights[i].getStart(), 0);
- int endCol = Math.min(highlights[i].getEnd(), getString().length());
- Color c = highlights[i].getColor();
+ for (Highlight highlight : highlights) {
+ int startCol = Math.max(highlight.getStart(), 0);
+ int endCol = Math.min(highlight.getEnd(), getString().length());
+ Color c = highlight.getColor();
if (endCol >= startCol) {
int start = findX(startCol);
int end = findX(endCol + 1);
diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/fieldpanel/field/ReverseClippingTextField.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/fieldpanel/field/ReverseClippingTextField.java
index 3ffa173ccb..bffa921952 100644
--- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/fieldpanel/field/ReverseClippingTextField.java
+++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/fieldpanel/field/ReverseClippingTextField.java
@@ -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.
@@ -142,8 +141,8 @@ public class ReverseClippingTextField implements TextField {
int x = findX(col) + textStartX;
- return new Rectangle(x, -textElement.getHeightAbove(), 2, textElement.getHeightAbove() +
- textElement.getHeightBelow());
+ return new Rectangle(x, -textElement.getHeightAbove(), 2,
+ textElement.getHeightAbove() + textElement.getHeightBelow());
}
/**
@@ -336,8 +335,7 @@ public class ReverseClippingTextField implements TextField {
private void paintDots(Graphics g, int x) {
int pos = 1; // skip one pixel
for (int i = 0; i < 3; i++) {
- if (pos < DOT_DOT_DOT_WIDTH - 2) { // don't paint too close to next
- // field.
+ if (pos < DOT_DOT_DOT_WIDTH - 2) { // don't paint too close to next field
g.drawRect(x + pos, -2, 1, 1);
pos += 4; // add in size of dot and padding
}
@@ -349,14 +347,14 @@ public class ReverseClippingTextField implements TextField {
if (cursorLoc != null) {
cursorTextOffset = screenLocationToTextOffset(cursorLoc.row(), cursorLoc.col());
}
- paintHighlights(g, hlFactory.getHighlights(getString(), cursorTextOffset));
+ paintHighlights(g, hlFactory.getHighlights(this, getString(), cursorTextOffset));
}
protected void paintHighlights(Graphics g, Highlight[] highlights) {
- for (int i = 0; i < highlights.length; i++) {
- int startCol = Math.max(highlights[i].getStart() - startingCharIndex, 0);
- int endCol = Math.min(highlights[i].getEnd() - startingCharIndex, getString().length());
- Color c = highlights[i].getColor();
+ for (Highlight highlight : highlights) {
+ int startCol = Math.max(highlight.getStart() - startingCharIndex, 0);
+ int endCol = Math.min(highlight.getEnd() - startingCharIndex, getString().length());
+ Color c = highlight.getColor();
if (endCol >= startCol) {
int start = findX(startCol);
int end = findX(endCol + 1);
diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/fieldpanel/field/SimpleTextField.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/fieldpanel/field/SimpleTextField.java
index a4dbdbbbaf..f75903abb6 100644
--- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/fieldpanel/field/SimpleTextField.java
+++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/fieldpanel/field/SimpleTextField.java
@@ -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.
@@ -202,7 +201,7 @@ public class SimpleTextField implements Field {
public void paint(JComponent c, Graphics g, PaintContext context,
FieldBackgroundColorManager colorManager, RowColLocation cursorLoc, int rowHeight) {
paintSelection(g, colorManager, 0);
- paintHighlights(g, hlFactory.getHighlights(text, -1));
+ paintHighlights(g, hlFactory.getHighlights(this, text, -1));
g.setFont(metrics.getFont());
if (foregroundColor == null) {
foregroundColor = context.getForeground();
@@ -226,10 +225,10 @@ public class SimpleTextField implements Field {
}
protected void paintHighlights(Graphics g, Highlight[] highlights) {
- for (int i = 0; i < highlights.length; i++) {
- int startCol = Math.max(highlights[i].getStart(), 0);
- int endCol = Math.min(highlights[i].getEnd(), text.length());
- Color c = highlights[i].getColor();
+ for (Highlight highlight : highlights) {
+ int startCol = Math.max(highlight.getStart(), 0);
+ int endCol = Math.min(highlight.getEnd(), text.length());
+ Color c = highlight.getColor();
if (endCol >= startCol) {
int start = findX(startCol);
int end = findX(endCol + 1);
diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/fieldpanel/field/VerticalLayoutTextField.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/fieldpanel/field/VerticalLayoutTextField.java
index 7f4e79319a..dad543cad9 100644
--- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/fieldpanel/field/VerticalLayoutTextField.java
+++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/fieldpanel/field/VerticalLayoutTextField.java
@@ -268,7 +268,7 @@ public class VerticalLayoutTextField implements TextField {
cursorRow = cursorLoc.row();
}
- Highlight[] highlights = hlFactory.getHighlights(getText(), cursorTextOffset);
+ Highlight[] highlights = hlFactory.getHighlights(this, getText(), cursorTextOffset);
int columns = 0;
int n = subFields.size();
Color fieldBackgroundColor = colorManager.getBackgroundColor();
diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/fieldpanel/internal/TestBigLayoutModel.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/fieldpanel/internal/TestBigLayoutModel.java
index 371314727f..c2803615ea 100644
--- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/fieldpanel/internal/TestBigLayoutModel.java
+++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/fieldpanel/internal/TestBigLayoutModel.java
@@ -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.
@@ -17,8 +16,6 @@
package docking.widgets.fieldpanel.internal;
import java.awt.*;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
import java.math.BigInteger;
import java.util.ArrayList;
@@ -33,11 +30,8 @@ import docking.widgets.indexedscrollpane.IndexedScrollPane;
public class TestBigLayoutModel implements LayoutModel {
private static final Highlight[] NO_HIGHLIGHTS = new Highlight[0];
- private static final HighlightFactory hlFactory = new HighlightFactory() {
- public Highlight[] getHighlights(String text, int cursorTextOffset) {
- return NO_HIGHLIGHTS;
- }
- };
+ private static final HighlightFactory hlFactory =
+ (field, text, cursorTextOffset) -> NO_HIGHLIGHTS;
ArrayList listeners = new ArrayList();
FontMetrics fm;
@@ -86,15 +80,13 @@ public class TestBigLayoutModel implements LayoutModel {
if (index.compareTo(numIndexes) >= 0) {
return null;
}
- String text =
- name + ": This is line " + index +
- " More text to make line longer abcdefghijklmnopqrstuvwxyzabcdefghijk";
+ String text = name + ": This is line " + index +
+ " More text to make line longer abcdefghijklmnopqrstuvwxyzabcdefghijk";
FieldElement fe1 = new TextFieldElement(new AttributedString(text, Color.BLACK, fm), 0, 0);
FieldElement fe2 =
new TextFieldElement(new AttributedString("More text", Color.BLACK, fm), 0, 0);
- SingleRowLayout layout =
- new SingleRowLayout(new ClippingTextField(20, 300, fe1, hlFactory),
- new ClippingTextField(330, 100, fe2, hlFactory));
+ SingleRowLayout layout = new SingleRowLayout(new ClippingTextField(20, 300, fe1, hlFactory),
+ new ClippingTextField(330, 100, fe2, hlFactory));
if (index.intValue() >= startBigSizes && index.intValue() <= endBigSizes) {
layout.insertSpaceAbove(30);
@@ -143,12 +135,7 @@ public class TestBigLayoutModel implements LayoutModel {
contentPane.setLayout(new BorderLayout());
contentPane.add(scrollPanel);
JButton button = new JButton("Hit Me");
- button.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- model.updateData(1000, 2000);
- }
- });
+ button.addActionListener(e -> model.updateData(1000, 2000));
contentPane.add(button, BorderLayout.SOUTH);
frame.pack();
frame.setVisible(true);
diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/fieldpanel/support/HighlightFactory.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/fieldpanel/support/HighlightFactory.java
index 3d46ca7e66..8ac6c85d17 100644
--- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/fieldpanel/support/HighlightFactory.java
+++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/fieldpanel/support/HighlightFactory.java
@@ -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.
@@ -16,13 +15,18 @@
*/
package docking.widgets.fieldpanel.support;
+import docking.widgets.fieldpanel.field.Field;
+
public interface HighlightFactory {
+
/**
- * Returns the highlights for the given text.
- * @param text the text to be considered for highlighting.
+ * Returns the highlights for the given text
+ *
+ * @param field the field that is requesting the highlight
+ * @param text the text to be considered for highlighting
* @param cursorTextOffset the position in the given text of the cursor. A -1 indicates the
- * cursor is not in this field.
- * @return an array of highlights to be rendered.
+ * cursor is not in this field.
+ * @return an array of highlights to be rendered
*/
- public Highlight[] getHighlights(String text, int cursorTextOffset);
+ public Highlight[] getHighlights(Field field, String text, int cursorTextOffset);
}
diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/GTableWidget.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/GTableWidget.java
index d85f891941..b8a6a2cfb5 100644
--- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/GTableWidget.java
+++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/GTableWidget.java
@@ -133,7 +133,7 @@ public class GTableWidget extends JPanel {
listener.itemPicked(gFilterTable.getSelectedRowObject());
}
- public void setItemPickListner(TableItemPickedListener listener) {
+ public void setItemPickListener(TableItemPickedListener listener) {
this.listener = listener;
}
diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/tree/GTree.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/tree/GTree.java
index 2b60c2e053..ea7c7ee19a 100644
--- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/tree/GTree.java
+++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/tree/GTree.java
@@ -867,7 +867,7 @@ public class GTree extends JPanel implements BusyListener {
tree.getModel().addTreeModelListener(listener);
}
- public void removeGTModelListner(TreeModelListener listener) {
+ public void removeGTModelListener(TreeModelListener listener) {
tree.getModel().removeTreeModelListener(listener);
}
diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/tree/support/GTreeNodeTransferable.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/tree/support/GTreeNodeTransferable.java
index db434c3374..7a517077b1 100644
--- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/tree/support/GTreeNodeTransferable.java
+++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/tree/support/GTreeNodeTransferable.java
@@ -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,69 +18,75 @@ package docking.widgets.tree.support;
import java.awt.datatransfer.*;
import java.io.IOException;
import java.util.List;
+import java.util.Objects;
import docking.widgets.tree.GTreeNode;
/**
- * A transferable for sharing data via drag/drop and clipboard operations for GTrees.
+ * A transferable for sharing data via drag/drop and clipboard operations for GTrees
*/
public class GTreeNodeTransferable implements Transferable {
- private final List selectedData;
- private final GTreeTransferHandler transferHandler;
+ private final List selectedData;
+ private final GTreeTransferHandler transferHandler;
- /**
- * Creates this transferable based upon the selected data and uses the given transfer
- * handler to perform {@link Transferable} operations.
- * @param handler the handler used to perform transfer operations.
- * @param selectedData The
- */
- public GTreeNodeTransferable( GTreeTransferHandler handler, List selectedData) {
- this.selectedData = selectedData;
- this.transferHandler = handler;
- }
-
- /**
- * Returns all of the original selected data contained by this transferable.
- * @return all of the original selected data contained by this transferable
- */
- public List getAllData() {
- return selectedData;
- }
-
- /**
- * Gets the transfer data from the selection based upon the given flavor.
- * @param transferNodes The nodes from which to get the data.
- * @param flavor The flavor of data to retreive from the given selection.
- * @return the transfer data from the selection based upon the given flavor.
- * @throws UnsupportedFlavorException if the given flavor is not one of the supported flavors
- * returned by {@link #getSupportedDataFlavors(List)}.
- */
- public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
- return transferHandler.getTransferData(selectedData, flavor);
- }
-
- /**
- * Returns the DataFlavors for the types of data that this transferable supports, based upon
- * the given selection.
- * @param transferNodes The nodes to base the DataFlavor selection upon.
- * @return the DataFlavors for the types of data that this transferable supports, based upon
- * the given selection.
+ /**
+ * Creates this transferable based upon the selected data and uses the given transfer
+ * handler to perform {@link Transferable} operations
+ *
+ * @param handler the handler used to perform transfer operations
+ * @param selectedData The selected tree nodes
*/
- public DataFlavor[] getTransferDataFlavors() {
- return transferHandler.getSupportedDataFlavors(selectedData);
- }
+ public GTreeNodeTransferable(GTreeTransferHandler handler, List selectedData) {
+ this.transferHandler = Objects.requireNonNull(handler);
+ this.selectedData = Objects.requireNonNull(selectedData);
+ }
- /**
- * A convenience method to determine if this transferable supports the given flavor.
- * @return true if this transferable supports the given flavor.
- */
- public boolean isDataFlavorSupported(DataFlavor flavor) {
- DataFlavor[] flavors = transferHandler.getSupportedDataFlavors(selectedData);
- for(int i=0;i getAllData() {
+ return selectedData;
+ }
+
+ /**
+ * Gets the transfer data from the selection based upon the given flavor
+
+ * @param flavor The flavor of data to retrieve from the given selection.
+ * @return the transfer data from the selection based upon the given flavor.
+ * @throws UnsupportedFlavorException if the given flavor is not one of the supported flavors
+ * returned by {@link #getTransferDataFlavors()}
+ */
+ @Override
+ public Object getTransferData(DataFlavor flavor)
+ throws UnsupportedFlavorException, IOException {
+ return transferHandler.getTransferData(selectedData, flavor);
+ }
+
+ /**
+ * Returns the DataFlavors for the types of data that this transferable supports, based upon
+ * the given selection
+ *
+ * @return the DataFlavors for the types of data that this transferable supports, based upon
+ * the given selection
+ */
+ @Override
+ public DataFlavor[] getTransferDataFlavors() {
+ return transferHandler.getSupportedDataFlavors(selectedData);
+ }
+
+ /**
+ * A convenience method to determine if this transferable supports the given flavor
+ * @return true if this transferable supports the given flavor
+ */
+ @Override
+ public boolean isDataFlavorSupported(DataFlavor flavor) {
+ DataFlavor[] flavors = transferHandler.getSupportedDataFlavors(selectedData);
+ for (DataFlavor f : flavors) {
+ if (f.equals(flavor)) {
+ return true;
+ }
+ }
+ return false;
+ }
}
diff --git a/Ghidra/Framework/Docking/src/test/java/docking/widgets/fieldpanel/FlowLayoutTextFieldTest.java b/Ghidra/Framework/Docking/src/test/java/docking/widgets/fieldpanel/FlowLayoutTextFieldTest.java
index 675ec2b03f..604bd46201 100644
--- a/Ghidra/Framework/Docking/src/test/java/docking/widgets/fieldpanel/FlowLayoutTextFieldTest.java
+++ b/Ghidra/Framework/Docking/src/test/java/docking/widgets/fieldpanel/FlowLayoutTextFieldTest.java
@@ -15,7 +15,7 @@
*/
package docking.widgets.fieldpanel;
-import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.*;
import java.awt.*;
@@ -40,11 +40,8 @@ public class FlowLayoutTextFieldTest extends AbstractGenericTest {
@Before
public void setUp() throws Exception {
- HighlightFactory factory = new HighlightFactory() {
- @Override
- public Highlight[] getHighlights(String text, int cursorTextOffset) {
- return new Highlight[] { new Highlight(4, 4, Color.YELLOW) };
- }
+ HighlightFactory factory = (field, text, cursorTextOffset) -> {
+ return new Highlight[] { new Highlight(4, 4, Color.YELLOW) };
};
Font font = new Font("Times New Roman", 0, 14);
diff --git a/Ghidra/Framework/Docking/src/test/java/docking/widgets/fieldpanel/VerticalLayoutTextFieldTest.java b/Ghidra/Framework/Docking/src/test/java/docking/widgets/fieldpanel/VerticalLayoutTextFieldTest.java
index 6d77b473e9..dacf10ab15 100644
--- a/Ghidra/Framework/Docking/src/test/java/docking/widgets/fieldpanel/VerticalLayoutTextFieldTest.java
+++ b/Ghidra/Framework/Docking/src/test/java/docking/widgets/fieldpanel/VerticalLayoutTextFieldTest.java
@@ -15,7 +15,7 @@
*/
package docking.widgets.fieldpanel;
-import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.*;
import java.awt.*;
@@ -40,11 +40,8 @@ public class VerticalLayoutTextFieldTest extends AbstractGenericTest {
@Before
public void setUp() throws Exception {
- HighlightFactory factory = new HighlightFactory() {
- @Override
- public Highlight[] getHighlights(String text, int cursorTextOffset) {
- return new Highlight[] { new Highlight(4, 4, Color.YELLOW) };
- }
+ HighlightFactory factory = (field, text, cursorTextOffset) -> {
+ return new Highlight[] { new Highlight(4, 4, Color.YELLOW) };
};
Font font = new Font("Times New Roman", 0, 14);
diff --git a/Ghidra/Framework/FileSystem/src/main/java/ghidra/framework/store/FileSystem.java b/Ghidra/Framework/FileSystem/src/main/java/ghidra/framework/store/FileSystem.java
index 4cfd3fb7aa..6db0208eef 100644
--- a/Ghidra/Framework/FileSystem/src/main/java/ghidra/framework/store/FileSystem.java
+++ b/Ghidra/Framework/FileSystem/src/main/java/ghidra/framework/store/FileSystem.java
@@ -254,7 +254,7 @@ public interface FileSystem {
/**
* Adds the given listener to be notified of file system changes.
- * @param listener the listner to be added.
+ * @param listener the listener to be added.
*/
public void addFileSystemListener(FileSystemListener listener);
diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/framework/Application.java b/Ghidra/Framework/Generic/src/main/java/ghidra/framework/Application.java
index e6f02965f7..09572b2b80 100644
--- a/Ghidra/Framework/Generic/src/main/java/ghidra/framework/Application.java
+++ b/Ghidra/Framework/Generic/src/main/java/ghidra/framework/Application.java
@@ -460,18 +460,19 @@ public class Application {
if (module == null) {
return null;
}
-
- File file = getModuleFile(module, "build/os/" + Platform.CURRENT_PLATFORM.getDirectoryName(),
- exactFilename);
+
+ File file = getModuleFile(module,
+ "build/os/" + Platform.CURRENT_PLATFORM.getDirectoryName(), exactFilename);
if (file == null) {
file = getModuleFile(module, "os/" + Platform.CURRENT_PLATFORM.getDirectoryName(),
exactFilename);
}
-
+
// Allow win32 to be used for win64 as fallback
if (file == null && Platform.CURRENT_PLATFORM == Platform.WIN_64) {
- file = getModuleFile(module, "build/os/" + Platform.WIN_32.getDirectoryName(), exactFilename);
+ file = getModuleFile(module, "build/os/" + Platform.WIN_32.getDirectoryName(),
+ exactFilename);
}
if (file == null && Platform.CURRENT_PLATFORM == Platform.WIN_64) {
file = getModuleFile(module, "os/" + Platform.WIN_32.getDirectoryName(), exactFilename);
@@ -492,12 +493,13 @@ public class Application {
private File getOSFileInAnyModule(String path) throws FileNotFoundException {
- File file = findModuleFile("build/os/" + Platform.CURRENT_PLATFORM.getDirectoryName(), path);
-
+ File file =
+ findModuleFile("build/os/" + Platform.CURRENT_PLATFORM.getDirectoryName(), path);
+
if (file == null) {
file = findModuleFile("os/" + Platform.CURRENT_PLATFORM.getDirectoryName(), path);
}
-
+
// Allow win32 to be used for win64 as fallback
if (file == null && Platform.CURRENT_PLATFORM == Platform.WIN_64) {
file = findModuleFile("build/os/" + Platform.WIN_32.getDirectoryName(), path);
@@ -657,7 +659,7 @@ public class Application {
/**
* Return the module root directory for the module with the given name.
* @param moduleName the name of the module.
- * @return the module root directory for the module with the given name.
+ * @return the module root directory for the module with the given name or null if not found.
*/
public static ResourceFile getModuleRootDir(String moduleName) {
checkAppInitialized();
diff --git a/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/edge/PathHighlightListner.java b/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/edge/PathHighlightListener.java
similarity index 95%
rename from Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/edge/PathHighlightListner.java
rename to Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/edge/PathHighlightListener.java
index 68529067a9..366c5dd90f 100644
--- a/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/edge/PathHighlightListner.java
+++ b/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/edge/PathHighlightListener.java
@@ -15,7 +15,7 @@
*/
package ghidra.graph.viewer.edge;
-public interface PathHighlightListner {
+public interface PathHighlightListener {
/**
* Called when the a path is highlighted.
diff --git a/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/edge/VisualGraphPathHighlighter.java b/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/edge/VisualGraphPathHighlighter.java
index 0bc45cd701..f6bf916447 100644
--- a/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/edge/VisualGraphPathHighlighter.java
+++ b/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/edge/VisualGraphPathHighlighter.java
@@ -99,7 +99,7 @@ public class VisualGraphPathHighlighter> postDominanceFuture;
private CompletableFuture circuitFuture;
- private PathHighlightListner listener = isHover -> {
+ private PathHighlightListener listener = isHover -> {
// stub
};
@@ -108,7 +108,7 @@ public class VisualGraphPathHighlighter doUpdateFocusedVertex());
- public VisualGraphPathHighlighter(VisualGraph graph, PathHighlightListner listener) {
+ public VisualGraphPathHighlighter(VisualGraph graph, PathHighlightListener listener) {
this.graph = graph;
if (listener != null) {
this.listener = listener;
diff --git a/Ghidra/Framework/Help/src/main/java/help/validator/location/DirectoryHelpModuleLocation.java b/Ghidra/Framework/Help/src/main/java/help/validator/location/DirectoryHelpModuleLocation.java
index 8c26ca404e..d760e42c65 100644
--- a/Ghidra/Framework/Help/src/main/java/help/validator/location/DirectoryHelpModuleLocation.java
+++ b/Ghidra/Framework/Help/src/main/java/help/validator/location/DirectoryHelpModuleLocation.java
@@ -16,8 +16,7 @@
package help.validator.location;
import java.io.File;
-import java.io.IOException;
-import java.nio.file.*;
+import java.nio.file.Path;
import javax.help.HelpSet;
@@ -43,21 +42,13 @@ public class DirectoryHelpModuleLocation extends HelpModuleLocation {
@Override
public GhidraTOCFile loadSourceTOCFile() {
- try (DirectoryStream ds = Files.newDirectoryStream(helpDir, "TOC_Source*.xml")) {
- for (Path file : ds) {
- try {
- return GhidraTOCFile.createGhidraTOCFile(file);
- }
- catch (Exception e) {
- throw new AssertException("Unexpected error loading source TOC file!: " + file,
- e);
- }
- }
+ Path sourceTocPath = helpDir.resolve("TOC_Source.xml");
+ try {
+ return GhidraTOCFile.createGhidraTOCFile(sourceTocPath);
}
- catch (IOException e) {
- throw new AssertException("Error reading help path: " + helpDir);
+ catch (Exception e) {
+ throw new AssertException("Unexpected error loading source TOC file!: " + sourceTocPath,
+ e);
}
-
- throw new AssertException("Help module has no TOC_Source.xml file: " + helpDir);
}
}
diff --git a/Ghidra/Framework/Help/src/main/java/help/validator/location/JarHelpModuleLocation.java b/Ghidra/Framework/Help/src/main/java/help/validator/location/JarHelpModuleLocation.java
index 7305787915..7827499dea 100644
--- a/Ghidra/Framework/Help/src/main/java/help/validator/location/JarHelpModuleLocation.java
+++ b/Ghidra/Framework/Help/src/main/java/help/validator/location/JarHelpModuleLocation.java
@@ -17,11 +17,11 @@ package help.validator.location;
import java.io.File;
import java.io.IOException;
-import java.net.URI;
-import java.net.URISyntaxException;
+import java.net.*;
import java.nio.file.*;
import java.util.HashMap;
import java.util.Map;
+import java.util.regex.Pattern;
import javax.help.HelpSet;
import javax.help.HelpSetException;
@@ -32,6 +32,12 @@ import help.validator.model.GhidraTOCFile;
public class JarHelpModuleLocation extends HelpModuleLocation {
+ /*
+ * format of 'helpDir':
+ * jar:file:///.../ghidra-prep/Ghidra/Features/Base/build/libs/Base.jar!/help
+ */
+ private static final Pattern JAR_FILENAME_PATTERN = Pattern.compile(".*/(\\w*)\\.jar!/.*");
+
private static Map env = new HashMap();
static {
env.put("create", "false");
@@ -69,19 +75,51 @@ public class JarHelpModuleLocation extends HelpModuleLocation {
@Override
public HelpSet loadHelpSet() {
- try (DirectoryStream ds = Files.newDirectoryStream(helpDir, "*_HelpSet.hs");) {
- for (Path path : ds) {
- return new GHelpSet(null, path.toUri().toURL());
- }
- }
- catch (IOException e) {
- throw new AssertException("No _HelpSet.hs file found for help directory: " + helpDir);
- }
- catch (HelpSetException e) {
- throw new AssertException("Error loading help set for " + helpDir);
- }
- throw new AssertException("Pre-built help jar file is missing it's help set: " + helpDir);
+ // Our convention is to name the help set after the module
+ File jarFile = getJarFile();
+ String moduleName = getModuleName(jarFile);
+ Path hsPath = helpDir.resolve(moduleName + "_HelpSet.hs");
+ try {
+ return new GHelpSet(null, hsPath.toUri().toURL());
+ }
+ catch (MalformedURLException | HelpSetException e) {
+ throw new AssertException(
+ "Pre-built help jar file is missing it's help set: " + helpDir, e);
+ }
+ }
+
+ private File getJarFile() {
+
+ // format: jar:file:///.../Ghidra/Features//build/libs/.jar!/help
+ String uriString = helpDir.toUri().toString();
+ int start = uriString.indexOf("file:/");
+ String chopped = uriString.substring(start);
+ int end = chopped.indexOf("!");
+ chopped = chopped.substring(0, end);
+ return new File(chopped);
+ }
+
+ private String getModuleName(File jarFile) {
+
+ String name = jarFile.getName();
+ int dotIndex = name.indexOf('.');
+ return name.substring(0, dotIndex);
+ }
+
+ @Override
+ public Path getHelpModuleLocation() {
+ // start format: jar:file:///.../Ghidra/Features/Base/build/libs/Base.jar!/help
+
+ // format: file:///.../Ghidra/Features//build/libs/.jar
+ File jarFile = getJarFile();
+ String moduleName = getModuleName(jarFile);
+ String fullPath = jarFile.getPath();
+ int moduleNameStart = fullPath.indexOf(moduleName);
+ int end = moduleNameStart + moduleName.length();
+ String moduleString = fullPath.substring(0, end);
+ Path modulePath = Paths.get(moduleString);
+ return modulePath;
}
@Override
diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/app/util/FileOpenDataFlavorHandler.java b/Ghidra/Framework/Project/src/main/java/ghidra/app/util/FileOpenDataFlavorHandler.java
index f4bdd441cc..4852c85c39 100644
--- a/Ghidra/Framework/Project/src/main/java/ghidra/app/util/FileOpenDataFlavorHandler.java
+++ b/Ghidra/Framework/Project/src/main/java/ghidra/app/util/FileOpenDataFlavorHandler.java
@@ -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.
@@ -16,11 +15,14 @@
*/
package ghidra.app.util;
-import ghidra.framework.plugintool.*;
+import java.awt.datatransfer.DataFlavor;
+import java.awt.dnd.DropTargetDropEvent;
-import java.awt.datatransfer.*;
-import java.awt.dnd.*;
+import ghidra.framework.plugintool.PluginTool;
+/**
+ * Interface for classes that will handle drop actions for files dropped onto the tool
+ */
public interface FileOpenDataFlavorHandler {
- public void handle(PluginTool tool, Object obj, DropTargetDropEvent e, DataFlavor f);
+ public void handle(PluginTool tool, Object obj, DropTargetDropEvent e, DataFlavor f);
}
diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/app/util/FileOpenDataFlavorHandlerService.java b/Ghidra/Framework/Project/src/main/java/ghidra/app/util/FileOpenDataFlavorHandlerService.java
deleted file mode 100644
index 687e6aed63..0000000000
--- a/Ghidra/Framework/Project/src/main/java/ghidra/app/util/FileOpenDataFlavorHandlerService.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/* ###
- * 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package ghidra.app.util;
-
-import ghidra.framework.PluggableServiceRegistry;
-import ghidra.framework.main.datatree.DataTreeDragNDropHandler;
-import ghidra.framework.main.datatree.VersionInfoTransferable;
-
-public class FileOpenDataFlavorHandlerService {
- static {
- PluggableServiceRegistry.registerPluggableService(FileOpenDataFlavorHandlerService.class, new FileOpenDataFlavorHandlerService());
- }
-
- public static void registerDataFlavorHandlers() {
- FileOpenDataFlavorHandlerService factory = PluggableServiceRegistry.getPluggableService(FileOpenDataFlavorHandlerService.class);
- factory.doRegisterDataFlavorHandlers();
- }
-
- protected void doRegisterDataFlavorHandlers() {
- FileOpenDropHandler.addDataFlavorHandler(DataTreeDragNDropHandler.localDomainFileFlavor, new LocalTreeNodeFlavorHandler());
- FileOpenDropHandler.addDataFlavorHandler(VersionInfoTransferable.localVersionInfoFlavor, new LocalTreeNodeFlavorHandler());
- }
-}
diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/app/util/FileOpenDropHandler.java b/Ghidra/Framework/Project/src/main/java/ghidra/app/util/FileOpenDropHandler.java
index 7a16da0504..6a4e4428ce 100644
--- a/Ghidra/Framework/Project/src/main/java/ghidra/app/util/FileOpenDropHandler.java
+++ b/Ghidra/Framework/Project/src/main/java/ghidra/app/util/FileOpenDropHandler.java
@@ -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.
@@ -16,9 +15,6 @@
*/
package ghidra.app.util;
-import ghidra.framework.plugintool.PluginTool;
-import ghidra.util.CascadedDropTarget;
-
import java.awt.Component;
import java.awt.Container;
import java.awt.datatransfer.DataFlavor;
@@ -33,6 +29,8 @@ import javax.swing.CellRendererPane;
import docking.DropTargetHandler;
import docking.dnd.DropTgtAdapter;
import docking.dnd.Droppable;
+import ghidra.framework.plugintool.PluginTool;
+import ghidra.util.CascadedDropTarget;
/**
* Handles drag/drop events on a given component such that a file
@@ -44,9 +42,6 @@ import docking.dnd.Droppable;
public class FileOpenDropHandler implements DropTargetHandler, Droppable, ContainerListener {
private static HashMap handlers =
new HashMap();
- static {
- FileOpenDataFlavorHandlerService.registerDataFlavorHandlers();
- }
private DropTgtAdapter dropTargetAdapter;
private DropTarget globalDropTarget;
@@ -75,11 +70,13 @@ public class FileOpenDropHandler implements DropTargetHandler, Droppable, Contai
/**
* Dispose this drop handler.
*/
+ @Override
public void dispose() {
deinitializeComponents(component);
globalDropTarget.removeDropTargetListener(dropTargetAdapter);
}
+ @Override
public boolean isDropOk(DropTargetDragEvent e) {
Set flavors = handlers.keySet();
for (DataFlavor dataFlavor : flavors) {
@@ -90,6 +87,7 @@ public class FileOpenDropHandler implements DropTargetHandler, Droppable, Contai
return false;
}
+ @Override
public void add(Object obj, DropTargetDropEvent e, DataFlavor f) {
FileOpenDataFlavorHandler handler = handlers.get(f);
if (handler != null) {
@@ -97,24 +95,28 @@ public class FileOpenDropHandler implements DropTargetHandler, Droppable, Contai
}
}
+ @Override
public void dragUnderFeedback(boolean ok, DropTargetDragEvent e) {
// nothing to display or do
}
+ @Override
public void undoDragUnderFeedback() {
// nothing to display or do
}
private void initializeComponents(Component comp) {
- if (comp instanceof CellRendererPane)
+ if (comp instanceof CellRendererPane) {
return;
+ }
if (comp instanceof Container) {
Container c = (Container) comp;
c.addContainerListener(this);
Component comps[] = c.getComponents();
- for (Component element : comps)
+ for (Component element : comps) {
initializeComponents(element);
+ }
}
DropTarget primaryDropTarget = comp.getDropTarget();
if (primaryDropTarget != null) {
@@ -123,15 +125,17 @@ public class FileOpenDropHandler implements DropTargetHandler, Droppable, Contai
}
private void deinitializeComponents(Component comp) {
- if (comp instanceof CellRendererPane)
+ if (comp instanceof CellRendererPane) {
return;
+ }
if (comp instanceof Container) {
Container c = (Container) comp;
c.removeContainerListener(this);
Component comps[] = c.getComponents();
- for (Component element : comps)
+ for (Component element : comps) {
deinitializeComponents(element);
+ }
}
DropTarget dt = comp.getDropTarget();
if (dt instanceof CascadedDropTarget) {
@@ -141,15 +145,18 @@ public class FileOpenDropHandler implements DropTargetHandler, Droppable, Contai
}
}
+ @Override
public void componentAdded(ContainerEvent e) {
initializeComponents(e.getChild());
}
+ @Override
public void componentRemoved(ContainerEvent e) {
deinitializeComponents(e.getChild());
}
- public static void addDataFlavorHandler(DataFlavor dataFlavor, FileOpenDataFlavorHandler handler) {
+ public static void addDataFlavorHandler(DataFlavor dataFlavor,
+ FileOpenDataFlavorHandler handler) {
handlers.put(dataFlavor, handler);
}
diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/app/util/LocalTreeNodeFlavorHandler.java b/Ghidra/Framework/Project/src/main/java/ghidra/app/util/LocalTreeNodeFlavorHandler.java
deleted file mode 100644
index fe87e5cf59..0000000000
--- a/Ghidra/Framework/Project/src/main/java/ghidra/app/util/LocalTreeNodeFlavorHandler.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/* ###
- * 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/**
- *
- */
-package ghidra.app.util;
-
-import ghidra.framework.main.GetVersionedObjectTask;
-import ghidra.framework.main.datatree.*;
-import ghidra.framework.model.*;
-import ghidra.framework.plugintool.PluginTool;
-
-import java.awt.datatransfer.DataFlavor;
-import java.awt.dnd.DropTargetDropEvent;
-import java.util.List;
-
-final class LocalTreeNodeFlavorHandler implements FileOpenDataFlavorHandler {
- public void handle(PluginTool tool, Object obj, DropTargetDropEvent e, DataFlavor f) {
- if (f.equals(DataTreeDragNDropHandler.localDomainFileFlavor)) {
- List> files = (List>) obj;
- DomainFile[] domainFiles = new DomainFile[files.size()];
- for (int i = 0; i < files.size(); i++) {
- domainFiles[i] = (DomainFile) files.get(i);
- }
- tool.acceptDomainFiles(domainFiles);
- }
- else if (f.equals(DataTreeDragNDropHandler.localDomainFileTreeFlavor)) {
- List> files = (List>) obj;
- DomainFile[] domainFiles = new DomainFile[files.size()];
- for (int i = 0; i < files.size(); i++) {
- DomainFileNode node = (DomainFileNode) files.get(i);
- domainFiles[i] = node.getDomainFile();
- }
- tool.acceptDomainFiles(domainFiles);
- }
- else if (f.equals(VersionInfoTransferable.localVersionInfoFlavor)) {
- VersionInfo info = (VersionInfo) obj;
- Project project = tool.getProject();
- ProjectData projectData = project.getProjectData();
- DomainFile file = projectData.getFile(info.getDomainFilePath());
- DomainObject versionedObj = getVersionedObject(tool, file, info.getVersionNumber());
-
- if (versionedObj != null) {
- DomainFile domainFile = versionedObj.getDomainFile();
- if (domainFile != null) {
- tool.acceptDomainFiles(new DomainFile[] { domainFile });
- }
- versionedObj.release(this);
- }
- }
- }
-
- private DomainObject getVersionedObject(PluginTool tool, DomainFile file, int versionNumber) {
- GetVersionedObjectTask task = new GetVersionedObjectTask(this, file, versionNumber);
- tool.execute(task, 250);
- return task.getVersionedObject();
- }
-}
diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/app/util/LocalVersionInfoFlavorHandler.java b/Ghidra/Framework/Project/src/main/java/ghidra/app/util/LocalVersionInfoFlavorHandler.java
deleted file mode 100644
index 62d2bd7e75..0000000000
--- a/Ghidra/Framework/Project/src/main/java/ghidra/app/util/LocalVersionInfoFlavorHandler.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/* ###
- * 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/**
- *
- */
-package ghidra.app.util;
-
-import ghidra.framework.main.*;
-import ghidra.framework.main.datatree.*;
-import ghidra.framework.model.*;
-import ghidra.framework.plugintool.*;
-
-import java.awt.datatransfer.*;
-import java.awt.dnd.*;
-
-final class LocalVersionInfoFlavorHandler implements
- FileOpenDataFlavorHandler {
- public void handle(PluginTool tool, Object obj, DropTargetDropEvent e, DataFlavor f) {
- VersionInfo info = (VersionInfo) obj;
-
- DomainFile file = tool.getProject().getProjectData().getFile(info.getDomainFilePath());
- GetVersionedObjectTask task = new GetVersionedObjectTask(this, file,
- info.getVersionNumber());
- tool.execute(task, 250);
- DomainObject versionedObj = task.getVersionedObject();
-
- if (versionedObj != null) {
- DomainFile vfile = versionedObj.getDomainFile();
- tool.acceptDomainFiles(new DomainFile[] {vfile});
- versionedObj.release(this);
- }
- }
-}
diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatable/ProjectDataActionContext.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatable/ProjectDataActionContext.java
index 179325b06a..c2acecdda6 100644
--- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatable/ProjectDataActionContext.java
+++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatable/ProjectDataActionContext.java
@@ -30,6 +30,7 @@ public class ProjectDataActionContext extends ActionContext implements DomainFil
private Component comp;
private boolean isActiveProject;
private ProjectData projectData;
+ private boolean isTransient;
public ProjectDataActionContext(ComponentProvider provider, ProjectData projectData,
Object contextObject, List selectedFolders,
@@ -112,4 +113,20 @@ public class ProjectDataActionContext extends ActionContext implements DomainFil
}
return false;
}
+
+ /**
+ * Transient data is that which will appear in a temporary project dialog
+ * @param isTransient true if transient
+ */
+ public void setTransient(boolean isTransient) {
+ this.isTransient = isTransient;
+ }
+
+ /**
+ * Transient data is that which will appear in a temporary project dialog
+ * @return true if transient
+ */
+ public boolean isTransient() {
+ return isTransient;
+ }
}
diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatable/ProjectDataContextAction.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatable/ProjectDataContextAction.java
index 5e9daa17eb..dd853ebb3a 100644
--- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatable/ProjectDataContextAction.java
+++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatable/ProjectDataContextAction.java
@@ -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.
@@ -26,20 +25,42 @@ public abstract class ProjectDataContextAction extends DockingAction {
}
@Override
- public final boolean isEnabledForContext(ActionContext actionContext) {
+ public boolean isEnabledForContext(ActionContext actionContext) {
if (!(actionContext instanceof ProjectDataActionContext)) {
return false;
}
+
ProjectDataActionContext context = (ProjectDataActionContext) actionContext;
+ if (ignoreTransientProject(context)) {
+ return false;
+ }
+
return isEnabledForContext(context);
}
+ protected boolean ignoreTransientProject(ProjectDataActionContext context) {
+ if (supportsTransientProjectData()) {
+ return false;
+ }
+ return context.isTransient();
+ }
+
+ /**
+ * Signals that this action can work on normal project data, as well as transient data.
+ * Transient data is that which will appear in a temporary project dialog.
+ *
+ * @return true if this action works on transient project data
+ */
+ protected boolean supportsTransientProjectData() {
+ return false;
+ }
+
protected boolean isEnabledForContext(ProjectDataActionContext context) {
return context.hasOneOrMoreFilesAndFolders();
}
@Override
- public final void actionPerformed(ActionContext context) {
+ public void actionPerformed(ActionContext context) {
actionPerformed((ProjectDataActionContext) context);
}
@@ -59,7 +80,7 @@ public abstract class ProjectDataContextAction extends DockingAction {
@Override
public boolean isAddToPopup(ActionContext context) {
- if (!(context instanceof ProjectDataActionContext)) {
+ if (!isEnabledForContext(context)) {
return false;
}
return isAddToPopup((ProjectDataActionContext) context);
diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatable/ProjectDataContextToggleAction.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatable/ProjectDataContextToggleAction.java
index d1fcb555f5..2b9dc7b39c 100644
--- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatable/ProjectDataContextToggleAction.java
+++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatable/ProjectDataContextToggleAction.java
@@ -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.
@@ -30,10 +29,32 @@ public abstract class ProjectDataContextToggleAction extends ToggleDockingAction
if (!(actionContext instanceof ProjectDataActionContext)) {
return false;
}
+
ProjectDataActionContext context = (ProjectDataActionContext) actionContext;
+ if (ignoreTransientProject(context)) {
+ return false;
+ }
+
return isEnabledForContext(context);
}
+ protected boolean ignoreTransientProject(ProjectDataActionContext context) {
+ if (supportsTransientProjectData()) {
+ return false;
+ }
+ return context.isTransient();
+ }
+
+ /**
+ * Signals that this action can work on normal project data, as well as transient data.
+ * Transient data is that which will appear in a temporary project dialog.
+ *
+ * @return true if this action works on transient project data
+ */
+ protected boolean supportsTransientProjectData() {
+ return false;
+ }
+
protected boolean isEnabledForContext(ProjectDataActionContext context) {
return context.hasOneOrMoreFilesAndFolders();
}
diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatable/ProjectDataTreeContextAction.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatable/ProjectDataTreeContextAction.java
index 137b73986f..7df40012df 100644
--- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatable/ProjectDataTreeContextAction.java
+++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatable/ProjectDataTreeContextAction.java
@@ -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.
@@ -16,9 +15,9 @@
*/
package ghidra.framework.main.datatable;
-import ghidra.framework.main.datatree.ProjectDataTreeActionContext;
import docking.ActionContext;
import docking.action.DockingAction;
+import ghidra.framework.main.datatree.ProjectDataTreeActionContext;
public abstract class ProjectDataTreeContextAction extends DockingAction {
@@ -31,10 +30,32 @@ public abstract class ProjectDataTreeContextAction extends DockingAction {
if (!(actionContext instanceof ProjectDataTreeActionContext)) {
return false;
}
+
ProjectDataTreeActionContext context = (ProjectDataTreeActionContext) actionContext;
+ if (ignoreTransientProject(context)) {
+ return false;
+ }
+
return isEnabledForContext(context);
}
+ protected boolean ignoreTransientProject(ProjectDataActionContext context) {
+ if (supportsTransientProjectData()) {
+ return false;
+ }
+ return context.isTransient();
+ }
+
+ /**
+ * Signals that this action can work on normal project data, as well as transient data.
+ * Transient data is that which will appear in a temporary project dialog.
+ *
+ * @return true if this action works on transient project data
+ */
+ protected boolean supportsTransientProjectData() {
+ return false;
+ }
+
protected boolean isEnabledForContext(ProjectDataTreeActionContext context) {
return context.hasOneOrMoreFilesAndFolders();
}
@@ -60,7 +81,7 @@ public abstract class ProjectDataTreeContextAction extends DockingAction {
@Override
public boolean isAddToPopup(ActionContext context) {
- if (!(context instanceof ProjectDataTreeActionContext)) {
+ if (!isEnabledForContext(context)) {
return false;
}
return isAddToPopup((ProjectDataTreeActionContext) context);
diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/DataFlavorHandlerService.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/DataFlavorHandlerService.java
deleted file mode 100644
index 3d6bedb22b..0000000000
--- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/DataFlavorHandlerService.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/* ###
- * 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package ghidra.framework.main.datatree;
-
-import ghidra.framework.PluggableServiceRegistry;
-
-public class DataFlavorHandlerService {
- static {
- PluggableServiceRegistry.registerPluggableService(DataFlavorHandlerService.class, new DataFlavorHandlerService());
- }
-
- public static void registerDataFlavorHandlers() {
- DataFlavorHandlerService factory = PluggableServiceRegistry.getPluggableService(DataFlavorHandlerService.class);
- factory.doRegisterDataFlavorHandlers();
- }
-
- protected void doRegisterDataFlavorHandlers() {
- final LocalTreeNodeHandler localTreeNodeHandler = new LocalTreeNodeHandler();
- DataTreeDragNDropHandler.addActiveDataFlavorHandler(DataTreeDragNDropHandler.localDomainFileTreeFlavor, localTreeNodeHandler);
- DataTreeDragNDropHandler.addActiveDataFlavorHandler(VersionInfoTransferable.localVersionInfoFlavor, new LocalVersionInfoHandler());
-
- DataTreeDragNDropHandler.addInactiveDataFlavorHandler(DataTreeDragNDropHandler.localDomainFileTreeFlavor, localTreeNodeHandler);
- }
-}
diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/DataTree.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/DataTree.java
index 513e2aab26..d2e3c8d145 100644
--- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/DataTree.java
+++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/DataTree.java
@@ -16,8 +16,7 @@
package ghidra.framework.main.datatree;
import java.awt.Component;
-import java.awt.event.*;
-import java.util.List;
+import java.awt.event.KeyEvent;
import javax.swing.JTree;
import javax.swing.KeyStroke;
@@ -30,20 +29,13 @@ import docking.widgets.tree.support.GTreeRenderer;
import ghidra.framework.main.FrontEndTool;
/**
- * Tree that shows the folders and domain files in a Project.
+ * Tree that shows the folders and domain files in a Project
*/
public class DataTree extends GTree {
- static {
- DataFlavorHandlerService.registerDataFlavorHandlers();
- }
private boolean isActive;
private DataTreeDragNDropHandler dragNDropHandler;
- /**
- * Constructor
- * @param folder root domain folder for the project.
- */
DataTree(FrontEndTool tool, GTreeRootNode root) {
super(root);
@@ -53,30 +45,11 @@ public class DataTree extends GTree {
docking.ToolTipManager.sharedInstance().registerComponent(this);
- //When the user right clicks, change selection to what the mouse was under
- addMouseListener(new MouseAdapter() {
- @Override
- public void mousePressed(MouseEvent evt) {
- if (evt.getButton() == MouseEvent.BUTTON3) {
- //Find the would-be newly selected path
- TreePath newPath = getPathForLocation(evt.getX(), evt.getY());
- if (newPath == null) {
- return;
- }
- //Determine if the path is already selected--If so, do not change the selection
- TreePath[] paths = getSelectionPaths();
- if (paths != null) {
- for (TreePath element : paths) {
- if (element.equals(newPath)) {
- return;
- }
- }
- }
- }
- }
- });
- dragNDropHandler = new DataTreeDragNDropHandler(tool, this, isActive);
- setDragNDropHandler(dragNDropHandler);
+ if (tool != null) {
+ dragNDropHandler = new DataTreeDragNDropHandler(tool, this, isActive);
+ setDragNDropHandler(dragNDropHandler);
+ }
+
initializeKeyEvents();
}
@@ -92,74 +65,10 @@ public class DataTree extends GTree {
KeyStroke.getKeyStroke(KeyEvent.VK_X, DockingUtils.CONTROL_KEY_MODIFIER_MASK));
}
- void setProjectActive(boolean b) {
- dragNDropHandler.setProjectActive(b);
- }
-
- /**
- * Return true if this path has all of its subpaths expanded.
- */
- public boolean allPathsExpanded(TreePath path) {
-
- GTreeNode node = (GTreeNode) path.getLastPathComponent();
- if (node.isLeaf()) {
- return true;
+ void setProjectActive(boolean isActive) {
+ if (dragNDropHandler != null) {
+ dragNDropHandler.setProjectActive(isActive);
}
- if (isCollapsed(path)) {
- return false;
- }
-
- boolean allLeaves = true;
-
- List children = node.getChildren();
- for (GTreeNode child : children) {
- if (child.isLeaf()) {
- continue;
- }
- allLeaves = false;
- if (!isExpanded(child.getTreePath())) {
- return false;
- }
-
- if (!allPathsExpanded(child.getTreePath())) {
- return false;
- }
- }
- if (allLeaves) {
- return isExpanded(path);
- }
- return true;
- }
-
- /**
- * Return true if this path has all of its subpaths collapsed.
- */
- public boolean allPathsCollapsed(TreePath path) {
- GTreeNode node = (GTreeNode) path.getLastPathComponent();
-
- if (isExpanded(path)) {
- return false;
- }
- boolean allLeaves = true; // variable for knowing whether all children are leaves
-
- node.getChildren();
- for (GTreeNode child : node) {
- if (child.isLeaf()) {
- continue;
- }
- allLeaves = false;
- if (!isCollapsed(child.getTreePath())) {
- return false;
- }
-
- if (!allPathsCollapsed(child.getTreePath())) {
- return false;
- }
- }
- if (allLeaves) {
- return isCollapsed(path);
- }
- return true;
}
public void clearSelection() {
@@ -183,20 +92,7 @@ public class DataTree extends GTree {
getJTree().stopEditing();
}
- //////////////////////////////////////////////////////////////////////
- // *** private methods
- //////////////////////////////////////////////////////////////////////
- /**
- * Tree cell renderer to use the appropriate icons for the
- * DataTreeNodes.
- */
private class DataTreeCellRenderer extends GTreeRenderer {
-
- /**
- * Configures the renderer based on the passed in components.
- * The icon is set according to value, expanded, and leaf
- * parameters.
- */
@Override
public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel,
boolean expanded, boolean leaf, int row, boolean doesHaveFocus) {
@@ -209,7 +105,5 @@ public class DataTree extends GTree {
}
return this;
}
-
}
-
}
diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/DataTreeClipboardUtils.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/DataTreeClipboardUtils.java
index 40cdb3a720..f522152a2a 100644
--- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/DataTreeClipboardUtils.java
+++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/DataTreeClipboardUtils.java
@@ -23,6 +23,7 @@ import javax.swing.tree.TreePath;
import docking.dnd.GClipboard;
import docking.widgets.tree.GTreeNode;
+import docking.widgets.tree.support.GTreeNodeTransferable;
import ghidra.util.Msg;
/**
@@ -35,14 +36,8 @@ public class DataTreeClipboardUtils {
* Static instance of a callback handler that is notified when the clipboard is changed
* and our data is discarded.
*/
- private static final ClipboardOwner DATATREE_CLIPBOARD_OWNER = new ClipboardOwner() {
- @Override
- public void lostOwnership(Clipboard clipboard, Transferable contents) {
- // This is called when something other than this class modifies the clipboard
- // and our data is discarded.
- clearCuttables(contents);
- }
- };
+ private static final ClipboardOwner DATATREE_CLIPBOARD_OWNER =
+ (clipboard, contents) -> clearCuttables(contents);
/**
* Pushes the GTreeNodes in the specified TreePath array to the clipboard.
@@ -59,8 +54,9 @@ public class DataTreeClipboardUtils {
GTreeNode node = (GTreeNode) element.getLastPathComponent();
list.add(node);
}
- DataTreeNodeTransferable contents =
- new DataTreeNodeTransferable(tree.getDragNDropHandler(), list);
+
+ GTreeNodeTransferable contents =
+ new GTreeNodeTransferable(tree.getDragNDropHandler(), list);
try {
clipboard.setContents(contents, DATATREE_CLIPBOARD_OWNER);
diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/DataTreeDragNDropHandler.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/DataTreeDragNDropHandler.java
index a7b9f32770..70293082f3 100644
--- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/DataTreeDragNDropHandler.java
+++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/DataTreeDragNDropHandler.java
@@ -30,9 +30,7 @@ import ghidra.util.Msg;
import ghidra.util.exception.AssertException;
public class DataTreeDragNDropHandler implements GTreeDragNDropHandler {
- private static Map activeProjectDropFlavorHandlerMap =
- new HashMap<>();
- private static Map inactiveProjectDropFlavorHandlerMap =
+ private static Map activeProjectDropFlavorHandlerMap =
new HashMap<>();
public static DataFlavor localDomainFileTreeFlavor = createLocalTreeNodeFlavor();
public static DataFlavor localDomainFileFlavor = createLocalTreeFlavor();
@@ -79,29 +77,31 @@ public class DataTreeDragNDropHandler implements GTreeDragNDropHandler {
public void drop(GTreeNode destination, Transferable transferable, int dropAction) {
DataFlavor[] transferDataFlavors = transferable.getTransferDataFlavors();
for (DataFlavor dataFlavor : transferDataFlavors) {
- DataFlavorHandler flavorHandler = getFlavorHandler(dataFlavor);
+ DataTreeFlavorHandler flavorHandler = getFlavorHandler(dataFlavor);
if (flavorHandler != null) {
- try {
- Object transferData = transferable.getTransferData(dataFlavor);
- flavorHandler.handle(tool, tree, destination, transferData, dropAction);
- }
- catch (UnsupportedFlavorException e) {
- throw new AssertException(
- "Got unsupported flavor from using a supported flavor");
- }
- catch (IOException e) {
- Msg.showError(this, null, "IO Error", "Error during drop", e);
- }
+ handleDrop(destination, transferable, dropAction, dataFlavor, flavorHandler);
return;
}
}
}
- private DataFlavorHandler getFlavorHandler(DataFlavor flavor) {
- if (isActiveProject) {
- return activeProjectDropFlavorHandlerMap.get(flavor);
+ private void handleDrop(GTreeNode destination, Transferable transferable, int dropAction,
+ DataFlavor dataFlavor, DataTreeFlavorHandler flavorHandler) {
+
+ try {
+ Object transferData = transferable.getTransferData(dataFlavor);
+ flavorHandler.handle(tool, tree, destination, transferData, dropAction);
}
- return inactiveProjectDropFlavorHandlerMap.get(flavor);
+ catch (UnsupportedFlavorException e) {
+ throw new AssertException("Got unsupported flavor from using a supported flavor");
+ }
+ catch (IOException e) {
+ Msg.showError(this, null, "IO Error", "Error during drop", e);
+ }
+ }
+
+ private DataTreeFlavorHandler getFlavorHandler(DataFlavor flavor) {
+ return activeProjectDropFlavorHandlerMap.get(flavor);
}
@Override
@@ -134,13 +134,6 @@ public class DataTreeDragNDropHandler implements GTreeDragNDropHandler {
@Override
public DataFlavor[] getSupportedDataFlavors(List transferNodes) {
return allSupportedFlavors;
-// Set keySet = null;
-// if (isActiveProject) {
-// keySet = activeProjectDropFlavorHandlerMap.keySet();
-// } else {
-// keySet = inactiveProjectDropFlavorHandlerMap.keySet();
-// }
-// return keySet.toArray(new DataFlavor[keySet.size()]);
}
@Override
@@ -196,24 +189,15 @@ public class DataTreeDragNDropHandler implements GTreeDragNDropHandler {
return false;
}
- public static void addActiveDataFlavorHandler(DataFlavor flavor, DataFlavorHandler handler) {
+ public static void addActiveDataFlavorHandler(DataFlavor flavor, DataTreeFlavorHandler handler) {
activeProjectDropFlavorHandlerMap.put(flavor, handler);
}
- public static void addInactiveDataFlavorHandler(DataFlavor flavor, DataFlavorHandler handler) {
- inactiveProjectDropFlavorHandlerMap.put(flavor, handler);
- }
-
- public static DataFlavorHandler removeActiveDataFlavorHandler(DataFlavor flavor) {
+ public static DataTreeFlavorHandler removeActiveDataFlavorHandler(DataFlavor flavor) {
return activeProjectDropFlavorHandlerMap.remove(flavor);
}
- public static DataFlavorHandler removeInctiveDataFlavorHandler(DataFlavor flavor) {
- return inactiveProjectDropFlavorHandlerMap.remove(flavor);
- }
-
public void setProjectActive(boolean b) {
isActiveProject = b;
}
-
}
diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/DataFlavorHandler.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/DataTreeFlavorHandler.java
similarity index 69%
rename from Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/DataFlavorHandler.java
rename to Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/DataTreeFlavorHandler.java
index f63e22469c..18aba84d63 100644
--- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/DataFlavorHandler.java
+++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/DataTreeFlavorHandler.java
@@ -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.
@@ -16,10 +15,13 @@
*/
package ghidra.framework.main.datatree;
-import ghidra.framework.main.FrontEndTool;
import docking.widgets.tree.GTreeNode;
+import ghidra.framework.plugintool.PluginTool;
-public interface DataFlavorHandler {
- public void handle(FrontEndTool tool, DataTree dataTree, GTreeNode destinationNode,
- Object transferData, int dropAction);
+/**
+ * Interface for classes that will handle drop actions for {@link DataTree}s.
+ */
+public interface DataTreeFlavorHandler {
+ public void handle(PluginTool tool, DataTree dataTree, GTreeNode destinationNode,
+ Object transferData, int dropAction);
}
diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/DataTreeNodeTransferable.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/DataTreeNodeTransferable.java
deleted file mode 100644
index 793a178278..0000000000
--- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/DataTreeNodeTransferable.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/* ###
- * 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package ghidra.framework.main.datatree;
-
-import java.util.List;
-
-import docking.widgets.tree.GTreeNode;
-import docking.widgets.tree.support.GTreeNodeTransferable;
-import docking.widgets.tree.support.GTreeTransferHandler;
-
-public class DataTreeNodeTransferable extends GTreeNodeTransferable {
- public DataTreeNodeTransferable(GTreeTransferHandler handler, List selectedData) {
- super(handler, selectedData);
- }
-
-}
diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/LocalTreeNodeHandler.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/LocalTreeNodeHandler.java
index a31fcc76af..bcc70cdd84 100644
--- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/LocalTreeNodeHandler.java
+++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/LocalTreeNodeHandler.java
@@ -15,29 +15,55 @@
*/
package ghidra.framework.main.datatree;
+import java.awt.datatransfer.DataFlavor;
import java.awt.dnd.DnDConstants;
+import java.awt.dnd.DropTargetDropEvent;
import java.io.IOException;
import java.util.List;
-import javax.swing.SwingUtilities;
-
import docking.widgets.tree.GTreeNode;
import docking.widgets.tree.GTreeState;
-import ghidra.framework.main.FrontEndTool;
+import ghidra.app.util.FileOpenDataFlavorHandler;
import ghidra.framework.model.DomainFile;
import ghidra.framework.model.DomainFolder;
+import ghidra.framework.plugintool.PluginTool;
import ghidra.util.Msg;
+import ghidra.util.SystemUtilities;
import ghidra.util.exception.DuplicateFileException;
import ghidra.util.exception.FileInUseException;
import ghidra.util.task.*;
-final class LocalTreeNodeHandler implements DataFlavorHandler {
+public final class LocalTreeNodeHandler
+ implements DataTreeFlavorHandler, FileOpenDataFlavorHandler {
+
private DataTree dataTree;
private GTreeState treeState;
+ @Override
+ public void handle(PluginTool tool, Object obj, DropTargetDropEvent e, DataFlavor f) {
+
+ if (f.equals(DataTreeDragNDropHandler.localDomainFileFlavor)) {
+ List> files = (List>) obj;
+ DomainFile[] domainFiles = new DomainFile[files.size()];
+ for (int i = 0; i < files.size(); i++) {
+ domainFiles[i] = (DomainFile) files.get(i);
+ }
+ tool.acceptDomainFiles(domainFiles);
+ }
+ else if (f.equals(DataTreeDragNDropHandler.localDomainFileTreeFlavor)) {
+ List> files = (List>) obj;
+ DomainFile[] domainFiles = new DomainFile[files.size()];
+ for (int i = 0; i < files.size(); i++) {
+ DomainFileNode node = (DomainFileNode) files.get(i);
+ domainFiles[i] = node.getDomainFile();
+ }
+ tool.acceptDomainFiles(domainFiles);
+ }
+ }
+
@Override
@SuppressWarnings("unchecked")
- public void handle(FrontEndTool tool, DataTree tree, GTreeNode destinationNode,
+ public void handle(PluginTool tool, DataTree tree, GTreeNode destinationNode,
Object transferData, int dropAction) {
this.dataTree = tree;
@@ -52,12 +78,9 @@ final class LocalTreeNodeHandler implements DataFlavorHandler {
new TaskLauncher(task, dataTree, 1000);
if (treeState != null) { // is set to null if drag results in a task
- SwingUtilities.invokeLater(new Runnable() {
- @Override
- public void run() {
- treeState.updateStateForMovedNodes();
- dataTree.restoreTreeState(treeState);
- }
+ SystemUtilities.runSwingLater(() -> {
+ treeState.updateStateForMovedNodes();
+ dataTree.restoreTreeState(treeState);
});
}
}
diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/LocalVersionInfoHandler.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/LocalVersionInfoHandler.java
index 3dc8e451ec..294f45895d 100644
--- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/LocalVersionInfoHandler.java
+++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/LocalVersionInfoHandler.java
@@ -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.
@@ -14,42 +13,64 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-/**
- *
- */
package ghidra.framework.main.datatree;
-import ghidra.framework.client.*;
-import ghidra.framework.main.FrontEndTool;
-import ghidra.framework.model.DomainFile;
-import ghidra.framework.model.DomainFolder;
-import ghidra.util.task.TaskLauncher;
-
+import java.awt.datatransfer.DataFlavor;
+import java.awt.dnd.DropTargetDropEvent;
import java.io.IOException;
import docking.widgets.tree.GTreeNode;
+import ghidra.app.util.FileOpenDataFlavorHandler;
+import ghidra.framework.client.*;
+import ghidra.framework.main.GetVersionedObjectTask;
+import ghidra.framework.model.*;
+import ghidra.framework.plugintool.PluginTool;
+import ghidra.util.task.TaskLauncher;
-final class LocalVersionInfoHandler implements DataFlavorHandler {
- public void handle(FrontEndTool tool, DataTree dataTree, GTreeNode destinationNode,
- Object transferData, int dropAction) {
- DomainFolder folder = getDomainFolder(destinationNode);
-
- VersionInfo info = (VersionInfo) transferData;
- RepositoryAdapter rep = tool.getProject().getProjectData().getRepository();
- try {
- if (rep != null) {
- rep.connect();
- }
- DomainFile file = tool.getProject().getProjectData().getFile(info.getDomainFilePath());
- if (file != null) {
- new TaskLauncher(new CopyFileVersionTask(file, info.getVersionNumber(), folder), dataTree, 500);
- }
- }
- catch (NotConnectedException exc) {}
- catch (IOException exc) {
- ClientUtil.handleException(rep, exc, "Repository Connection", tool.getToolFrame());
- }
- }
+public final class LocalVersionInfoHandler
+ implements DataTreeFlavorHandler, FileOpenDataFlavorHandler {
+
+ @Override
+ public void handle(PluginTool tool, Object obj, DropTargetDropEvent e, DataFlavor f) {
+ VersionInfo info = (VersionInfo) obj;
+
+ DomainFile file = tool.getProject().getProjectData().getFile(info.getDomainFilePath());
+ GetVersionedObjectTask task =
+ new GetVersionedObjectTask(this, file, info.getVersionNumber());
+ tool.execute(task, 250);
+ DomainObject versionedObj = task.getVersionedObject();
+
+ if (versionedObj != null) {
+ DomainFile vfile = versionedObj.getDomainFile();
+ tool.acceptDomainFiles(new DomainFile[] { vfile });
+ versionedObj.release(this);
+ }
+ }
+
+ @Override
+ public void handle(PluginTool tool, DataTree dataTree, GTreeNode destinationNode,
+ Object transferData, int dropAction) {
+ DomainFolder folder = getDomainFolder(destinationNode);
+
+ VersionInfo info = (VersionInfo) transferData;
+ RepositoryAdapter rep = tool.getProject().getProjectData().getRepository();
+ try {
+ if (rep != null) {
+ rep.connect();
+ }
+ DomainFile file = tool.getProject().getProjectData().getFile(info.getDomainFilePath());
+ if (file != null) {
+ new TaskLauncher(new CopyFileVersionTask(file, info.getVersionNumber(), folder),
+ dataTree, 500);
+ }
+ }
+ catch (NotConnectedException exc) {
+ // not sure why we squash this?
+ }
+ catch (IOException exc) {
+ ClientUtil.handleException(rep, exc, "Repository Connection", tool.getToolFrame());
+ }
+ }
private DomainFolder getDomainFolder(GTreeNode destinationNode) {
if (destinationNode instanceof DomainFolderNode) {
diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/ProjectDataTreeActionContext.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/ProjectDataTreeActionContext.java
index 63eba46ece..cffbbc0d28 100644
--- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/ProjectDataTreeActionContext.java
+++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/ProjectDataTreeActionContext.java
@@ -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.
@@ -16,14 +15,13 @@
*/
package ghidra.framework.main.datatree;
-import ghidra.framework.main.datatable.ProjectDataActionContext;
-import ghidra.framework.model.*;
-
import java.util.List;
import javax.swing.tree.TreePath;
import docking.ComponentProvider;
+import ghidra.framework.main.datatable.ProjectDataActionContext;
+import ghidra.framework.model.*;
public class ProjectDataTreeActionContext extends ProjectDataActionContext {
@@ -52,7 +50,7 @@ public class ProjectDataTreeActionContext extends ProjectDataActionContext {
return selectionPaths;
}
- public DataTree getDataTree() {
+ public DataTree getTree() {
return tree;
}
}
diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/ProjectDataTreePanel.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/ProjectDataTreePanel.java
index 1651798827..a3514f5748 100644
--- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/ProjectDataTreePanel.java
+++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/ProjectDataTreePanel.java
@@ -55,33 +55,26 @@ public class ProjectDataTreePanel extends JPanel {
private ChangeManager changeMgr;
private boolean isActiveProject;
- private FrontEndTool tool; // may be null if the panel is inside of the
-
+ // these may be null if the panel is inside of a dialog
+ private FrontEndTool tool;
private FrontEndPlugin plugin;
- // data tree dialog
-
/**
- * Construct an empty panel that is going to be used as the active
- * panel.
- * @param tool front end tool
+ * Construct an empty panel that is going to be used as the active panel
+ * @param plugin front end plugin
*/
public ProjectDataTreePanel(FrontEndPlugin plugin) {
this(null, true, plugin, null);
}
/**
- * Construct a new DataTreePanel.
+ * Constructor
+ *
* @param projectName name of project
- * @param projectData object that provides access to all the user data
- * folders in a project
* @param isActiveProject true if the project is active, and the
* data tree may be modified
- * @param tool front end tool; will be null if the panel is used in a dialog
- * @param actionMgr class to handle enablement of actions; an ActionManager
- * is passed in when several data tree panels all need to use the
- * same ActionManager, e.g., the viewed projects in the front end tool;
- * actionMgr will be null if the panel is used in a dialog
+ * @param plugin front end plugin; will be null if the panel is used in a dialog
+ * @param filter optional filter that is used to hide programs from view
*/
public ProjectDataTreePanel(String projectName, boolean isActiveProject, FrontEndPlugin plugin,
DomainFileFilter filter) {
@@ -211,9 +204,6 @@ public class ProjectDataTreePanel extends JPanel {
}
}
- /**
- * Set the help location for the data tree.
- */
public void setHelpLocation(HelpLocation helpLocation) {
HelpService help = Help.getHelpService();
help.registerHelp(tree, helpLocation);
@@ -228,8 +218,9 @@ public class ProjectDataTreePanel extends JPanel {
}
/**
- * Get the number of selected items in the tree.
- * These could be either DomainFile's or DomainFolder's.
+ * Get the number of selected items in the tree. These could be either files or folders.
+ *
+ * @return the number of selected items in the tree.
*/
public int getSelectedItemCount() {
return tree.getSelectionCount();
@@ -279,47 +270,31 @@ public class ProjectDataTreePanel extends JPanel {
tree.removeGTreeSelectionListener(l);
}
- /**
- * Add a mouse listener to the data tree.
- */
public void addTreeMouseListener(MouseListener l) {
tree.addMouseListener(l);
}
- /**
- * Remove the mouse listener from the data tree.
- */
public void removeTreeMouseListener(MouseListener l) {
tree.removeMouseListener(l);
}
- /**
- * Set the preferred size of the scroll pane that contains the
- * data tree.
- */
public void setPreferredTreePanelSize(Dimension d) {
tree.setPreferredSize(d);
}
- /**
- * Get the project data that this data tree panel is operating on.
- */
public ProjectData getProjectData() {
return projectData;
}
/**
* Notification that the project was renamed; update the root node name
- * and reload the node.
+ * and reload the node
+ * @param newName the new project name
*/
public void projectRenamed(String newName) {
updateProjectName(newName);
}
- /**
- * Notification that panel is being disposed.
- *
- */
public void dispose() {
if (projectData != null) {
projectData.removeDomainFolderChangeListener(changeMgr);
@@ -328,10 +303,12 @@ public class ProjectDataTreePanel extends JPanel {
}
/**
- * Get the data tree node that is selected.
- * @param e mouse event for the popup; may be null if this is being
- * called as a result of the key binding pressed
- * @return null if there is no selection
+ * Get the data tree node that is selected
+ *
+ * @param provider the provider with which to construct the new context
+ * @param e mouse event for the popup; may be null if this is being called as a result of
+ * the key binding pressed
+ * @return the new context; null if there is no selection
*/
public ActionContext getActionContext(ComponentProvider provider, MouseEvent e) {
if (root instanceof NoProjectNode) {
@@ -360,13 +337,13 @@ public class ProjectDataTreePanel extends JPanel {
}
}
- return new ProjectDataTreeActionContext(provider, projectData, selectionPaths,
- domainFolderList, domainFileList, tree, isActiveProject);
+ ProjectDataTreeActionContext context = new ProjectDataTreeActionContext(provider,
+ projectData, selectionPaths, domainFolderList, domainFileList, tree, isActiveProject);
+ boolean isTransient = tool == null; // null for stand-alone dialog, not the project's tree
+ context.setTransient(isTransient);
+ return context;
}
- /**
- * get the data tree for this data tree panel.
- */
public DataTree getDataTree() {
return tree;
}
@@ -380,17 +357,10 @@ public class ProjectDataTreePanel extends JPanel {
tree.setFilterVisible(enabled);
}
- /**
- * Return true if this data tree panel is listening to domain folder
- * changes.
- */
boolean domainFolderListenerAdded() {
return changeMgr != null;
}
- /**
- * Get the folder change listener.
- */
DomainFolderChangeListener getFolderChangeListener() {
return changeMgr;
}
diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataCollapseAction.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataCollapseAction.java
index fdec297512..6e60a4ad5b 100644
--- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataCollapseAction.java
+++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataCollapseAction.java
@@ -33,7 +33,7 @@ public class ProjectDataCollapseAction extends ProjectDataTreeContextAction {
@Override
protected void actionPerformed(ProjectDataTreeActionContext context) {
- DataTree tree = context.getDataTree();
+ DataTree tree = context.getTree();
TreePath[] paths = context.getSelectionPaths();
collapse(tree, paths[0]);
}
diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataCopyAction.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataCopyAction.java
index 858fb08888..c1207ec325 100644
--- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataCopyAction.java
+++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataCopyAction.java
@@ -40,7 +40,7 @@ public class ProjectDataCopyAction extends ProjectDataCopyCutBaseAction {
protected void actionPerformed(ProjectDataTreeActionContext context) {
TreePath[] paths = adjustSelectionPaths(context.getSelectionPaths());
- DataTreeClipboardUtils.setClipboardContents(context.getDataTree(), paths);
+ DataTreeClipboardUtils.setClipboardContents(context.getTree(), paths);
}
diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataCutAction.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataCutAction.java
index 9341248252..ee80774d39 100644
--- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataCutAction.java
+++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataCutAction.java
@@ -40,7 +40,7 @@ public class ProjectDataCutAction extends ProjectDataCopyCutBaseAction {
protected void actionPerformed(ProjectDataTreeActionContext context) {
TreePath[] paths = adjustSelectionPaths(context.getSelectionPaths());
- DataTreeClipboardUtils.setClipboardContents(context.getDataTree(), paths);
+ DataTreeClipboardUtils.setClipboardContents(context.getTree(), paths);
markNodesCut(paths);
}
diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataExpandAction.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataExpandAction.java
index 393457277e..576ce289c3 100644
--- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataExpandAction.java
+++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataExpandAction.java
@@ -33,7 +33,7 @@ public class ProjectDataExpandAction extends ProjectDataTreeContextAction {
@Override
protected void actionPerformed(ProjectDataTreeActionContext context) {
- DataTree tree = context.getDataTree();
+ DataTree tree = context.getTree();
TreePath[] paths = context.getSelectionPaths();
expand(tree, paths[0]);
}
diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataNewFolderAction.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataNewFolderAction.java
index 2e658cf93d..44d8dddf06 100644
--- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataNewFolderAction.java
+++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataNewFolderAction.java
@@ -41,6 +41,12 @@ public class ProjectDataNewFolderAction extends ProjectDataContextAction {
markHelpUnnecessary();
}
+ @Override
+ protected boolean supportsTransientProjectData() {
+ // we allow the user to create new folders even in transient projects
+ return true;
+ }
+
@Override
protected void actionPerformed(ProjectDataActionContext context) {
createNewFolder(context);
diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataPasteAction.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataPasteAction.java
index 9bbaee00c5..5bf29f7245 100644
--- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataPasteAction.java
+++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataPasteAction.java
@@ -44,7 +44,7 @@ public class ProjectDataPasteAction extends ProjectDataCopyCutBaseAction {
GTreeNode node = (GTreeNode) context.getContextObject();
DomainFolderNode destNode = getFolderForNode(node);
- paste(context.getDataTree(), destNode);
+ paste(context.getTree(), destNode);
}
@Override
diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataReadOnlyAction.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataReadOnlyAction.java
index b7e8837547..4ca5086dcf 100644
--- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataReadOnlyAction.java
+++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataReadOnlyAction.java
@@ -50,6 +50,10 @@ public class ProjectDataReadOnlyAction extends ProjectDataContextToggleAction {
if (context.getFolderCount() != 0 || context.getFileCount() != 1) {
return false;
}
+ if (ignoreTransientProject(context)) {
+ return false;
+ }
+
DomainFile domainFile = context.getSelectedFiles().get(0);
setSelected(domainFile.isReadOnly());
return true;
diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataSelectAction.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataSelectAction.java
index f584babf9d..f3fa36668e 100644
--- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataSelectAction.java
+++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataSelectAction.java
@@ -36,7 +36,7 @@ public class ProjectDataSelectAction extends ProjectDataTreeContextAction {
@Override
protected void actionPerformed(ProjectDataTreeActionContext context) {
- DataTree tree = context.getDataTree();
+ DataTree tree = context.getTree();
TreePath[] paths = context.getSelectionPaths();
GTreeNode node = (GTreeNode) paths[0].getLastPathComponent();
selectAllChildren(tree, node);
diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/task/gui/GProgressBar.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/task/gui/GProgressBar.java
index 99b316b2e1..29eb284923 100644
--- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/task/gui/GProgressBar.java
+++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/task/gui/GProgressBar.java
@@ -59,12 +59,12 @@ public class GProgressBar extends JPanel {
private Timer updateTimer;
private EmptyBorderButton cancelButton;
- private CancelledListener cancelledListner;
+ private CancelledListener cancelledListener;
- public GProgressBar(CancelledListener cancelledListner, boolean includeTextField,
+ public GProgressBar(CancelledListener cancelledListener, boolean includeTextField,
boolean includeCancelButton, boolean includeAnimatedIcon, float fontSize) {
super(new BorderLayout(5, 1));
- this.cancelledListner = cancelledListner;
+ this.cancelledListener = cancelledListener;
this.fontSize = fontSize;
buildProgressPanel(includeTextField, includeCancelButton, includeAnimatedIcon);
@@ -199,13 +199,13 @@ public class GProgressBar extends JPanel {
}
public void cancel() {
- if (cancelledListner != null) {
- cancelledListner.cancelled();
+ if (cancelledListener != null) {
+ cancelledListener.cancelled();
}
}
public void setCancelledListener(CancelledListener listener) {
- this.cancelledListner = listener;
+ this.cancelledListener = listener;
}
private void buildProgressPanel(boolean includeTextField, boolean includeCancelButton,
diff --git a/Ghidra/Framework/SoftwareModeling/Sleigh.launch b/Ghidra/Framework/SoftwareModeling/Sleigh.launch
index b4f8e30e41..b8273f84bc 100644
--- a/Ghidra/Framework/SoftwareModeling/Sleigh.launch
+++ b/Ghidra/Framework/SoftwareModeling/Sleigh.launch
@@ -1,19 +1,27 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Ghidra/Framework/SoftwareModeling/build.gradle b/Ghidra/Framework/SoftwareModeling/build.gradle
index ea5e731db3..afcc62f929 100644
--- a/Ghidra/Framework/SoftwareModeling/build.gradle
+++ b/Ghidra/Framework/SoftwareModeling/build.gradle
@@ -23,6 +23,10 @@ dependencies {
antlr "org.antlr:antlr:3.5.2"
}
+// Define classpath needed to execute sleigh compiler during development
+// (see gradleScripts/processorUtils.gradle)
+ext.sleighDevClasspath = project.sourceSets.main.runtimeClasspath.collect { it.absolutePath }.join(':')
+
def genSrcDir = 'generated-src/antlr/main'
generateGrammarSource {
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/antlr/ghidra/sleigh/grammar/SleighCompiler.g b/Ghidra/Framework/SoftwareModeling/src/main/antlr/ghidra/sleigh/grammar/SleighCompiler.g
index ba0bffac28..7170783b57 100644
--- a/Ghidra/Framework/SoftwareModeling/src/main/antlr/ghidra/sleigh/grammar/SleighCompiler.g
+++ b/Ghidra/Framework/SoftwareModeling/src/main/antlr/ghidra/sleigh/grammar/SleighCompiler.g
@@ -1473,8 +1473,10 @@ expr_apply returns [Object value]
;
expr_operands returns [VectorSTL value]
+ scope Return;
@init {
$value = new VectorSTL();
+ $Return::noReturn = false;
}
: (e=expr { value.push_back(e); })*
;
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/processors/sleigh/SleighLanguage.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/processors/sleigh/SleighLanguage.java
index a0cf138fdb..8c12ac945a 100644
--- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/processors/sleigh/SleighLanguage.java
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/processors/sleigh/SleighLanguage.java
@@ -412,11 +412,39 @@ public class SleighLanguage implements Language {
String languageName = specName + ".slaspec";
ResourceFile languageFile = new ResourceFile(slaFile.getParentFile(), languageName);
+ // see gradleScripts/processorUtils.gradle for sleighArgs.txt generation
+ ResourceFile sleighArgsFile = null;
+ ResourceFile languageModule = Application.getModuleContainingResourceFile(languageFile);
+ if (languageModule != null) {
+ if (SystemUtilities.isInReleaseMode()) {
+ sleighArgsFile = new ResourceFile(languageModule, "data/sleighArgs.txt");
+ }
+ else {
+ sleighArgsFile = new ResourceFile(languageModule, "build/data/sleighArgs.txt");
+ }
+ }
+
+ Map defineMap;
+ String[] args;
+ if (sleighArgsFile != null && sleighArgsFile.isFile()) {
+ args = new String[] { "-i", sleighArgsFile.getAbsolutePath(),
+ languageFile.getAbsolutePath(), description.getSlaFile().getAbsolutePath() };
+ defineMap = new HashMap<>();
+ }
+ else {
+ args = new String[] { languageFile.getAbsolutePath(),
+ description.getSlaFile().getAbsolutePath() };
+ defineMap = ModuleDefinitionsMap.getModuleMap();
+ }
+
try {
- int returnCode = SleighCompileLauncher.runMain(
- new String[] { languageFile.getAbsolutePath(),
- description.getSlaFile().getAbsolutePath() },
- ModuleDefinitionsMap.getModuleMap());
+ StringBuilder buf = new StringBuilder();
+ for (String str : args) {
+ buf.append(str);
+ buf.append(" ");
+ }
+ Msg.debug(this, "Sleigh compile: " + buf);
+ int returnCode = SleighCompileLauncher.runMain(args, defineMap);
if (returnCode != 0) {
throw new SleighException("Errors compiling " + languageFile.getAbsolutePath() +
" -- please check log messages for details");
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slgh_compile/SleighCompile.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slgh_compile/SleighCompile.java
index cd3f56fad9..895c894be6 100644
--- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slgh_compile/SleighCompile.java
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slgh_compile/SleighCompile.java
@@ -963,10 +963,9 @@ public class SleighCompile extends SleighBase {
continue;
}
if (firstContextField != null && sym.getId() == firstContextField) {
- reportError(location,
- sym.getName() +
- " cannot be used to attach variables because it occurs at the lowest bit position in context at " +
- sym.getLocation());
+ reportError(location, sym.getName() +
+ " cannot be used to attach variables because it occurs at the lowest bit position in context at " +
+ sym.getLocation());
continue;
}
PatternValue patval = sym.getPatternValue();
@@ -1569,7 +1568,9 @@ public class SleighCompile extends SleighBase {
}
/**
- * Run the sleigh compiler.
+ * Run the sleigh compiler. This provides a direct means of invoking the
+ * compiler without using the launcher. The full SoftwareModeling classpath
+ * must be established including any dependencies.
* @param args compiler command line arguments
* @throws JDOMException
* @throws IOException
@@ -1578,5 +1579,4 @@ public class SleighCompile extends SleighBase {
public static void main(String[] args) throws JDOMException, IOException, RecognitionException {
System.exit(SleighCompileLauncher.runMain(args, new HashMap()));
}
-
}
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slgh_compile/SleighCompileLauncher.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slgh_compile/SleighCompileLauncher.java
index 299ffdc938..c678b37ef7 100644
--- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slgh_compile/SleighCompileLauncher.java
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slgh_compile/SleighCompileLauncher.java
@@ -21,17 +21,18 @@ import java.util.Map.Entry;
import org.antlr.runtime.*;
import org.antlr.runtime.tree.CommonTreeNodeStream;
-import org.jdom.*;
-import org.jdom.input.SAXBuilder;
+import org.jdom.JDOMException;
+import generic.jar.ResourceFile;
import generic.stl.IteratorSTL;
import ghidra.GhidraApplicationLayout;
import ghidra.GhidraLaunchable;
+import ghidra.framework.Application;
+import ghidra.framework.ApplicationConfiguration;
import ghidra.pcodeCPort.context.SleighError;
-import ghidra.pcodeCPort.translate.XmlError;
import ghidra.sleigh.grammar.*;
import ghidra.util.Msg;
-import ghidra.util.xml.XmlUtilities;
+import ghidra.util.SystemUtilities;
import utilities.util.FileResolutionResult;
import utilities.util.FileUtilities;
@@ -63,6 +64,11 @@ public class SleighCompileLauncher implements GhidraLaunchable {
@Override
public void launch(GhidraApplicationLayout layout, String[] args)
throws JDOMException, IOException, RecognitionException {
+
+ // Initialize the application
+ ApplicationConfiguration configuration = new ApplicationConfiguration();
+ Application.initializeApplication(layout, configuration);
+
System.exit(runMain(args, new HashMap()));
}
@@ -87,17 +93,24 @@ public class SleighCompileLauncher implements GhidraLaunchable {
if (args.length < 1) {
// @formatter:off
- Msg.info(SleighCompile.class, "USAGE: sleigh [-x] [-dNAME=VALUE] inputfile outputfile");
- Msg.info(SleighCompile.class, " -x turns on parser debugging");
- Msg.info(SleighCompile.class, " -u print warnings for unnecessary pcode instructions");
- Msg.info(SleighCompile.class, " -l report pattern conflicts");
- Msg.info(SleighCompile.class, " -n print warnings for all NOP constructors");
- Msg.info(SleighCompile.class, " -t print warnings for dead temporaries");
- Msg.info(SleighCompile.class, " -e enforce use of 'local' keyword for temporaries");
- Msg.info(SleighCompile.class, " -f print warnings for unused token fields");
- Msg.info(SleighCompile.class, " -DNAME=VALUE defines a preprocessor macro NAME with value VALUE");
- Msg.info(SleighCompile.class, " OR sleigh -a directory-root");
- Msg.info(SleighCompile.class, " compiles all .slaspec files to .sla files anywhere under directory-root");
+ Msg.info(SleighCompile.class, "Usage: sleigh [options...] [ [] | -a ]");
+ Msg.info(SleighCompile.class, " sleigh [options...] []");
+ Msg.info(SleighCompile.class, " source slaspec file to be compiled");
+ Msg.info(SleighCompile.class, " optional output sla file (infile.sla assumed)");
+ Msg.info(SleighCompile.class, " or");
+ Msg.info(SleighCompile.class, " sleigh [options...] -a ");
+ Msg.info(SleighCompile.class, " directory to have all slaspec files compiled");
+ Msg.info(SleighCompile.class, " options:");
+ Msg.info(SleighCompile.class, " -x turns on parser debugging");
+ Msg.info(SleighCompile.class, " -u print warnings for unnecessary pcode instructions");
+ Msg.info(SleighCompile.class, " -l report pattern conflicts");
+ Msg.info(SleighCompile.class, " -n print warnings for all NOP constructors");
+ Msg.info(SleighCompile.class, " -t print warnings for dead temporaries");
+ Msg.info(SleighCompile.class, " -e enforce use of 'local' keyword for temporaries");
+ Msg.info(SleighCompile.class, " -f print warnings for unused token fields");
+ Msg.info(SleighCompile.class, " -DNAME=VALUE defines a preprocessor macro NAME with value VALUE (option may be repeated)");
+ Msg.info(SleighCompile.class, " -dMODULE defines a preprocessor macro MODULE with a value of its module path (option may be repeated)");
+ Msg.info(SleighCompile.class, " -i inject options from specified file");
// @formatter:on
return 2;
}
@@ -114,6 +127,13 @@ public class SleighCompileLauncher implements GhidraLaunchable {
if (args[i].charAt(0) != '-') {
break;
}
+ else if (args[i].charAt(1) == 'i') {
+ // inject options from file specified by next argument
+ args = injectOptionsFromFile(args, ++i);
+ if (args == null) {
+ return 1;
+ }
+ }
else if (args[i].charAt(1) == 'D') {
String preproc = args[i].substring(2);
int pos = preproc.indexOf('=');
@@ -125,6 +145,18 @@ public class SleighCompileLauncher implements GhidraLaunchable {
String value = preproc.substring(pos + 1);
preprocs.put(name, value); // Preprocessor macro definitions
}
+ else if (args[i].charAt(1) == 'd') {
+ String moduleName = args[i].substring(2);
+ ResourceFile module = Application.getModuleRootDir(moduleName);
+ if (module == null || !module.isDirectory()) {
+ Msg.error(SleighCompile.class,
+ "Failed to resolve module reference: " + args[i]);
+ return 1;
+ }
+ Msg.debug(SleighCompile.class,
+ "Sleigh resolved module: " + moduleName + "=" + module.getAbsolutePath());
+ preprocs.put(moduleName, module.getAbsolutePath()); // Preprocessor macro definitions
+ }
else if (args[i].charAt(1) == 'u') {
unnecessaryPcodeWarning = true;
}
@@ -155,7 +187,16 @@ public class SleighCompileLauncher implements GhidraLaunchable {
}
}
+ if (i < args.length - 2) {
+ Msg.error(SleighCompile.class, "Too many parameters");
+ return 1;
+ }
+
if (allMode) {
+ if (i == args.length) {
+ Msg.error(SleighCompile.class, "Missing input directory path");
+ return 1;
+ }
String directory = args[i];
File dir = new File(directory);
if (!dir.exists() || !dir.isDirectory()) {
@@ -195,6 +236,7 @@ public class SleighCompileLauncher implements GhidraLaunchable {
return -totalFailures;
}
+ // single file compile
SleighCompile compiler = new SleighCompile();
initCompiler(compiler, preprocs, unnecessaryPcodeWarning, lenientConflict, allNopWarning,
deadTempWarning, unusedFieldWarning, enforceLocalKeyWord);
@@ -202,60 +244,71 @@ public class SleighCompileLauncher implements GhidraLaunchable {
Msg.error(SleighCompile.class, "Missing input file name");
return 1;
}
- if (i < args.length - 2) {
- Msg.error(SleighCompile.class, "Too many parameters");
- return 1;
- }
filein = args[i];
if (i < args.length - 1) {
fileout = args[i + 1];
}
- String fileinExamine = filein;
- int extInPos = fileinExamine.indexOf(FILE_IN_DEFAULT_EXT);
- boolean autoExtInSet = false;
- String fileinPreExt = "";
- if (extInPos == -1) {// No Extension Given...
- // cout << "No Ext Given" << endl;
- fileinPreExt = fileinExamine;
- fileinExamine += FILE_IN_DEFAULT_EXT;
- filein = fileinExamine;
- // cout << "filein = " << filein << endl;
- autoExtInSet = true;
+ String baseName = filein;
+ if (filein.toLowerCase().endsWith(FILE_IN_DEFAULT_EXT)) {
+ baseName = filein.substring(0, filein.length() - FILE_IN_DEFAULT_EXT.length());
}
- else {
- fileinPreExt = fileinExamine.substring(0, extInPos);
- }
- // cout << "fileinPreExt = " << fileinPreExt << endl;
+ filein = baseName + FILE_IN_DEFAULT_EXT;
- if (fileout != null) {
- String fileoutExamine = fileout;
- int extOutPos = fileoutExamine.indexOf(FILE_OUT_DEFAULT_EXT);
- if (extOutPos == -1) {// No Extension Given...
- // cout << "No Ext Given" << endl;
- fileoutExamine += FILE_OUT_DEFAULT_EXT;
- fileout = fileoutExamine;
- // cout << "fileout = " << fileout << endl;
- }
- retval = run_compilation(filein, fileout, compiler);
+ String baseOutName = fileout;
+ if (fileout == null) {
+ baseOutName = baseName;
}
- else {
- // First determine whether or not to use Run_XML...
- if (autoExtInSet) {// Assumed format of at least "sleigh file" .
- // "sleigh file.slaspec file.sla"
- String fileoutSTR = fileinPreExt;
- fileoutSTR += FILE_OUT_DEFAULT_EXT;
- fileout = fileoutSTR;
- // cout << "generated fileout = " << fileout << endl;
- retval = run_compilation(filein, fileout, compiler);
- }
- else {
- retval = run_xml(filein, compiler);
- }
+ else if (fileout.toLowerCase().endsWith(FILE_OUT_DEFAULT_EXT)) {
+ baseOutName = fileout.substring(0, fileout.length() - FILE_OUT_DEFAULT_EXT.length());
+ }
+ fileout = baseOutName + FILE_OUT_DEFAULT_EXT;
+ return run_compilation(filein, fileout, compiler);
+ }
+
+ private static String[] injectOptionsFromFile(String[] args, int index) {
+ if (index >= args.length) {
+ Msg.error(SleighCompile.class, "Missing options input file name");
+ return null;
}
- return retval;
+
+ File optionsFile = new File(args[index]);
+ if (!optionsFile.isFile()) {
+ Msg.error(SleighCompile.class,
+ "Options file not found: " + optionsFile.getAbsolutePath());
+ if (SystemUtilities.isInDevelopmentMode()) {
+ Msg.error(SleighCompile.class,
+ "Eclipse language module must be selected and 'gradle prepdev' prevously run");
+ }
+ return null;
+ }
+ ArrayList list = new ArrayList<>();
+ for (int i = 0; i <= index; i++) {
+ list.add(args[i]);
+ }
+
+ try (BufferedReader r = new BufferedReader(new FileReader(optionsFile))) {
+ String option = r.readLine();
+ while (option != null) {
+ option = option.trim();
+ if (option.length() != 0 && !option.startsWith("#")) {
+ list.add(option);
+ }
+ option = r.readLine();
+ }
+ }
+ catch (IOException e) {
+ Msg.error(SleighCompile.class,
+ "Reading options file failed (" + optionsFile.getName() + "): " + e.getMessage());
+ return null;
+ }
+
+ for (int i = index + 1; i < args.length; i++) {
+ list.add(args[i]);
+ }
+ return list.toArray(new String[list.size()]);
}
private static int run_compilation(String filein, String fileout, SleighCompile compiler)
@@ -384,64 +437,4 @@ public class SleighCompileLauncher implements GhidraLaunchable {
return 0;
}
- private static int run_xml(String filein, SleighCompile compiler)
- throws JDOMException, IOException, RecognitionException {
- FileInputStream s = new FileInputStream(new File(filein));
- Document doc = null;
- String specfileout = "";
- String specfilein = "";
-
- try {
- SAXBuilder builder = XmlUtilities.createSecureSAXBuilder(false, false);
- doc = builder.build(s);
- }
- catch (XmlError err) {
- Msg.error(SleighCompile.class,
- "Unable to parse single input file as XML spec: " + filein, err);
- return 1;
- }
- s.close();
-
- Element el = doc.getRootElement();
- for (;;) {
- List> list = el.getChildren();
- Iterator> iter = list.iterator();
- while (iter.hasNext()) {
- el = (Element) iter.next();
- if (el.getName().equals("processorfile")) {
- specfileout = el.getText();
- List> atts = el.getAttributes();
- Iterator> i = atts.iterator();
- while (i.hasNext()) {
- Attribute att = (Attribute) i.next();
- if (att.getName().equals("slaspec")) {
- specfilein = att.getValue();
- }
- else {
- compiler.setPreprocValue(att.getName(), att.getValue());
- }
- }
- }
- else if (el.getName().equals("language_spec")) {
- break;
- }
- else if (el.getName().equals("language_description")) {
- break;
- }
- }
- if (!iter.hasNext()) {
- break;
- }
- }
-
- if (specfilein.length() == 0) {
- Msg.error(SleighCompile.class, "Input slaspec file was not specified in " + filein);
- return 1;
- }
- if (specfileout.length() == 0) {
- Msg.error(SleighCompile.class, "Output sla file was not specified in " + filein);
- return 1;
- }
- return run_compilation(specfilein, specfileout, compiler);
- }
}
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/PcodeDataTypeManager.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/PcodeDataTypeManager.java
index d75023a482..8a8bd055f2 100644
--- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/PcodeDataTypeManager.java
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/PcodeDataTypeManager.java
@@ -261,10 +261,7 @@ public class PcodeDataTypeManager {
if (type instanceof Array) {
return buildType(type, size);
}
- if (type instanceof FunctionDefinition) {
- return buildType(type, size);
- }
- if (type.getLength() <= 0) {
+ if (!(type instanceof FunctionDefinition) && type.getLength() <= 0) {
return buildType(type, size);
}
StringBuilder resBuf = new StringBuilder();
@@ -541,7 +538,7 @@ public class PcodeDataTypeManager {
}
resBuf.append("
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Ghidra/Processors/68000/data/build.xml b/Ghidra/Processors/68000/data/build.xml
deleted file mode 100644
index 8f72019712..0000000000
--- a/Ghidra/Processors/68000/data/build.xml
+++ /dev/null
@@ -1,73 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Ghidra/Processors/6805/data/build.xml b/Ghidra/Processors/6805/data/build.xml
deleted file mode 100644
index 8f72019712..0000000000
--- a/Ghidra/Processors/6805/data/build.xml
+++ /dev/null
@@ -1,73 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Ghidra/Processors/8051/data/build.xml b/Ghidra/Processors/8051/data/build.xml
deleted file mode 100644
index 8f72019712..0000000000
--- a/Ghidra/Processors/8051/data/build.xml
+++ /dev/null
@@ -1,73 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Ghidra/Processors/8085/data/build.xml b/Ghidra/Processors/8085/data/build.xml
deleted file mode 100644
index 2164d961ae..0000000000
--- a/Ghidra/Processors/8085/data/build.xml
+++ /dev/null
@@ -1,76 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Ghidra/Processors/AARCH64/data/build.xml b/Ghidra/Processors/AARCH64/data/build.xml
deleted file mode 100644
index 7c1d69306c..0000000000
--- a/Ghidra/Processors/AARCH64/data/build.xml
+++ /dev/null
@@ -1,76 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Ghidra/Processors/ARM/data/build.xml b/Ghidra/Processors/ARM/data/build.xml
deleted file mode 100644
index 8f72019712..0000000000
--- a/Ghidra/Processors/ARM/data/build.xml
+++ /dev/null
@@ -1,73 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Ghidra/Processors/ARM/data/languages/ARM.ldefs b/Ghidra/Processors/ARM/data/languages/ARM.ldefs
index f98077ed69..08971e3ddf 100644
--- a/Ghidra/Processors/ARM/data/languages/ARM.ldefs
+++ b/Ghidra/Processors/ARM/data/languages/ARM.ldefs
@@ -5,7 +5,7 @@
endian="little"
size="32"
variant="v8"
- version="1.101"
+ version="1.102"
slafile="ARM8_le.sla"
processorspec="ARMt.pspec"
manualindexfile="../manuals/ARM.idx"
@@ -22,7 +22,7 @@
instructionEndian="little"
size="32"
variant="v8LEInstruction"
- version="1.101"
+ version="1.102"
slafile="ARM8_le.sla"
processorspec="ARMt.pspec"
manualindexfile="../manuals/ARM.idx"
@@ -37,7 +37,7 @@
endian="big"
size="32"
variant="v8"
- version="1.101"
+ version="1.102"
slafile="ARM8_be.sla"
processorspec="ARMt.pspec"
manualindexfile="../manuals/ARM.idx"
@@ -53,7 +53,7 @@
endian="little"
size="32"
variant="v7"
- version="1.101"
+ version="1.102"
slafile="ARM7_le.sla"
processorspec="ARMt.pspec"
manualindexfile="../manuals/ARM.idx"
@@ -71,7 +71,7 @@
instructionEndian="little"
size="32"
variant="v7LEInstruction"
- version="1.101"
+ version="1.102"
slafile="ARM7_le.sla"
processorspec="ARMt.pspec"
manualindexfile="../manuals/ARM.idx"
@@ -86,7 +86,7 @@
endian="big"
size="32"
variant="v7"
- version="1.101"
+ version="1.102"
slafile="ARM7_be.sla"
processorspec="ARMt.pspec"
manualindexfile="../manuals/ARM.idx"
@@ -102,7 +102,7 @@
endian="little"
size="32"
variant="Cortex"
- version="1.101"
+ version="1.102"
slafile="ARM7_le.sla"
processorspec="ARMCortex.pspec"
manualindexfile="../manuals/ARM.idx"
@@ -117,7 +117,7 @@
endian="big"
size="32"
variant="Cortex"
- version="1.101"
+ version="1.102"
slafile="ARM7_be.sla"
processorspec="ARMCortex.pspec"
manualindexfile="../manuals/ARM.idx"
@@ -132,7 +132,7 @@
endian="little"
size="32"
variant="v6"
- version="1.101"
+ version="1.102"
slafile="ARM6_le.sla"
processorspec="ARMt.pspec"
manualindexfile="../manuals/ARM.idx"
@@ -150,7 +150,7 @@
endian="big"
size="32"
variant="v6"
- version="1.101"
+ version="1.102"
slafile="ARM6_be.sla"
processorspec="ARMt.pspec"
manualindexfile="../manuals/ARM.idx"
@@ -168,7 +168,7 @@
endian="little"
size="32"
variant="v5t"
- version="1.101"
+ version="1.102"
slafile="ARM5t_le.sla"
processorspec="ARMt_v45.pspec"
manualindexfile="../manuals/ARM.idx"
@@ -184,7 +184,7 @@
endian="big"
size="32"
variant="v5t"
- version="1.101"
+ version="1.102"
slafile="ARM5t_be.sla"
processorspec="ARMt_v45.pspec"
manualindexfile="../manuals/ARM.idx"
@@ -200,7 +200,7 @@
endian="little"
size="32"
variant="v5"
- version="1.101"
+ version="1.102"
slafile="ARM5_le.sla"
processorspec="ARM_v45.pspec"
manualindexfile="../manuals/ARM.idx"
@@ -232,7 +232,7 @@
endian="little"
size="32"
variant="v4t"
- version="1.101"
+ version="1.102"
slafile="ARM4t_le.sla"
processorspec="ARMt_v45.pspec"
manualindexfile="../manuals/ARM.idx"
@@ -248,7 +248,7 @@
endian="big"
size="32"
variant="v4t"
- version="1.101"
+ version="1.102"
slafile="ARM4t_be.sla"
processorspec="ARMt_v45.pspec"
manualindexfile="../manuals/ARM.idx"
@@ -264,7 +264,7 @@
endian="little"
size="32"
variant="v4"
- version="1.101"
+ version="1.102"
slafile="ARM4_le.sla"
processorspec="ARM_v45.pspec"
manualindexfile="../manuals/ARM.idx"
@@ -280,7 +280,7 @@
endian="big"
size="32"
variant="v4"
- version="1.101"
+ version="1.102"
slafile="ARM4_be.sla"
processorspec="ARM_v45.pspec"
manualindexfile="../manuals/ARM.idx"
diff --git a/Ghidra/Processors/ARM/data/languages/ARMTHUMBinstructions.sinc b/Ghidra/Processors/ARM/data/languages/ARMTHUMBinstructions.sinc
index a9c655d332..48a2d6a29f 100644
--- a/Ghidra/Processors/ARM/data/languages/ARMTHUMBinstructions.sinc
+++ b/Ghidra/Processors/ARM/data/languages/ARMTHUMBinstructions.sinc
@@ -185,6 +185,7 @@ define token instrThumb (16)
thc0815=(8,15)
thc0915=(9,15)
thc1015=(10,15)
+ thc1112=(11,12)
thc1115=(11,15)
thc1215=(12,15)
thc1315=(13,15)
@@ -1614,7 +1615,7 @@ define pcodeop IndexCheck;
@if defined(VERSION_6T2) || defined(VERSION_7)
-:cmp^ItCond^".w" Rn0003,ThumbExpandImm12 is TMode=1 & ItCond & (op11=0x1e & thc0909=0 & sop0508=13 & Rn0003; thc1515=0 & thc0811=15) & ThumbExpandImm12
+:cmp^ItCond^".w" Rn0003,ThumbExpandImm12 is TMode=1 & ItCond & (op11=0x1e & thc0909=0 & thc0404=1 & sop0508=13 & Rn0003; thc1515=0 & thc0811=15) & ThumbExpandImm12
{
build ItCond;
th_subflags(Rn0003,ThumbExpandImm12);
@@ -2447,9 +2448,9 @@ define pcodeop ExclusiveAccess;
build CheckInIT_ZN;
}
-:mov^ItCond Rd0002,Rn0305 is TMode=1 & ItCond & op6=0x070 & Rn0305 & Rd0002 & CheckInIT_ZN
+:mov^ItCond Rd0002,Rn0305 is TMode=1 & ItCond & op6=0x000 & Rn0305 & Rd0002 & CheckInIT_ZN
{
- build ItCond;
+ build ItCond;
Rd0002 = Rn0305;
resflags(Rd0002);
build CheckInIT_ZN;
@@ -4482,7 +4483,7 @@ thumbEndianNess: "BE" is op0=0xb658 { export 1:1; }
:sub^ItCond sp,Immed7_4 is TMode=1 & ItCond & op7=0x161 & sp & Immed7_4
{
build ItCond;
- sp = sp - Immed7_4;
+ sp = sp - Immed7_4;
}
@if defined(VERSION_6T2) || defined(VERSION_7)
diff --git a/Ghidra/Processors/Atmel/data/build.xml b/Ghidra/Processors/Atmel/data/build.xml
deleted file mode 100644
index 8f72019712..0000000000
--- a/Ghidra/Processors/Atmel/data/build.xml
+++ /dev/null
@@ -1,73 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Ghidra/Processors/CR16/data/build.xml b/Ghidra/Processors/CR16/data/build.xml
deleted file mode 100644
index 8f72019712..0000000000
--- a/Ghidra/Processors/CR16/data/build.xml
+++ /dev/null
@@ -1,73 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Ghidra/Processors/DATA/data/build.xml b/Ghidra/Processors/DATA/data/build.xml
deleted file mode 100644
index 8f72019712..0000000000
--- a/Ghidra/Processors/DATA/data/build.xml
+++ /dev/null
@@ -1,73 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Ghidra/Processors/JVM/data/build.xml b/Ghidra/Processors/JVM/data/build.xml
deleted file mode 100644
index 8f72019712..0000000000
--- a/Ghidra/Processors/JVM/data/build.xml
+++ /dev/null
@@ -1,73 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Ghidra/Processors/MIPS/data/build.xml b/Ghidra/Processors/MIPS/data/build.xml
deleted file mode 100644
index a6301d23ca..0000000000
--- a/Ghidra/Processors/MIPS/data/build.xml
+++ /dev/null
@@ -1,74 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Ghidra/Processors/PA-RISC/data/build.xml b/Ghidra/Processors/PA-RISC/data/build.xml
deleted file mode 100644
index 8f72019712..0000000000
--- a/Ghidra/Processors/PA-RISC/data/build.xml
+++ /dev/null
@@ -1,73 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Ghidra/Processors/PIC/data/build.xml b/Ghidra/Processors/PIC/data/build.xml
deleted file mode 100644
index 8f72019712..0000000000
--- a/Ghidra/Processors/PIC/data/build.xml
+++ /dev/null
@@ -1,73 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Ghidra/Processors/PowerPC/data/build.xml b/Ghidra/Processors/PowerPC/data/build.xml
deleted file mode 100644
index 8f72019712..0000000000
--- a/Ghidra/Processors/PowerPC/data/build.xml
+++ /dev/null
@@ -1,73 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Ghidra/Processors/Sparc/data/build.xml b/Ghidra/Processors/Sparc/data/build.xml
deleted file mode 100644
index 8f72019712..0000000000
--- a/Ghidra/Processors/Sparc/data/build.xml
+++ /dev/null
@@ -1,73 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Ghidra/Processors/TI_MSP430/data/build.xml b/Ghidra/Processors/TI_MSP430/data/build.xml
deleted file mode 100644
index 8f72019712..0000000000
--- a/Ghidra/Processors/TI_MSP430/data/build.xml
+++ /dev/null
@@ -1,73 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Ghidra/Processors/Toy/data/build.xml b/Ghidra/Processors/Toy/data/build.xml
deleted file mode 100644
index 8f72019712..0000000000
--- a/Ghidra/Processors/Toy/data/build.xml
+++ /dev/null
@@ -1,73 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Ghidra/Processors/Z80/data/build.xml b/Ghidra/Processors/Z80/data/build.xml
deleted file mode 100644
index 8f72019712..0000000000
--- a/Ghidra/Processors/Z80/data/build.xml
+++ /dev/null
@@ -1,73 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Ghidra/Processors/x86/data/build.xml b/Ghidra/Processors/x86/data/build.xml
deleted file mode 100644
index b80b6d91fa..0000000000
--- a/Ghidra/Processors/x86/data/build.xml
+++ /dev/null
@@ -1,73 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Ghidra/RuntimeScripts/Common/support/launch.properties b/Ghidra/RuntimeScripts/Common/support/launch.properties
index 29583412e6..eb7f7a0396 100644
--- a/Ghidra/RuntimeScripts/Common/support/launch.properties
+++ b/Ghidra/RuntimeScripts/Common/support/launch.properties
@@ -68,3 +68,6 @@ VMARGS=-Dfont.size.override=
# generates uncaught exceptions. Disabling it can be helpful when trying to debug what went
# wrong because the ContinuesIntercepter affects the usefulness of the stack trace.
#VMARGS=-DContinuesInterceptor.disabled
+
+# Prevent log4j from using the Jansi DLL on Windows.
+VMARGS=-Dlog4j.skipJansi=true
diff --git a/Ghidra/RuntimeScripts/Windows/server/ghidraSvr.bat b/Ghidra/RuntimeScripts/Windows/server/ghidraSvr.bat
index 26633759bb..98a2bc2310 100644
--- a/Ghidra/RuntimeScripts/Windows/server/ghidraSvr.bat
+++ b/Ghidra/RuntimeScripts/Windows/server/ghidraSvr.bat
@@ -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 JAVA_HOME=
+rem set JAVA_HOME=
setlocal enabledelayedexpansion
@@ -94,7 +94,7 @@ if not exist "%WRAPPER_HOME%\" (
echo Using service wrapper: %WRAPPER_DIRNAME%
-@rem Find java.exe
+rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA=java.exe
@@ -105,28 +105,23 @@ goto reportError
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
-set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+set JAVA=%JAVA_HOME%\bin\java.exe
-if exist "%JAVA_EXE%" goto init
+if exist "%JAVA%" goto lab2
set ERROR=ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
goto reportError
:lab2
-:: Make sure some kind of java is on the path. It's required to run the LaunchSupport program.
-java -version >nul 2>nul
-if not %ERRORLEVEL% == 0 (
- set ERROR=Java runtime not found. Please refer to the Ghidra Installation Guide's Troubleshooting section.
- goto reportError
-)
-
:: Get the java that will be used to launch GhidraServer
set JAVA_HOME=
-for /f "delims=*" %%i in ('java -cp "%LS_CPATH%" LaunchSupport "%GHIDRA_HOME%" -java_home') do set JAVA_HOME=%%i
+for /f "delims=*" %%i in ('call "%JAVA%" -cp "%LS_CPATH%" LaunchSupport "%GHIDRA_HOME%" -java_home') do set JAVA_HOME=%%i
if "%JAVA_HOME%" == "" (
set ERROR=Failed to find a supported Java runtime. Please refer to the Ghidra Installation Guide's Troubleshooting section.
goto reportError
)
+
+rem reestablish JAVA path based upon final JAVA_HOME
set JAVA=%JAVA_HOME%\bin\java.exe
set OS_NAME=win32
diff --git a/Ghidra/application.properties b/Ghidra/application.properties
index d257c4f66c..d147a5076e 100644
--- a/Ghidra/application.properties
+++ b/Ghidra/application.properties
@@ -1,5 +1,5 @@
application.name=Ghidra
-application.version=9.0.1
+application.version=9.0.2
application.release.name=PUBLIC
application.layout.version=1
application.gradle.version=5.0
diff --git a/Ghidra/patch/README.txt b/Ghidra/patch/README.txt
new file mode 100644
index 0000000000..c80aadd7a0
--- /dev/null
+++ b/Ghidra/patch/README.txt
@@ -0,0 +1,3 @@
+Drop jar files in this directory to apply patches to an installation of Ghidra. Any jar files
+found in this directory will be placed at the front of the classpath, allowing them to override
+any existing classes in any module.
\ No newline at end of file
diff --git a/Ghidra/patch/certification.local.manifest b/Ghidra/patch/certification.local.manifest
new file mode 100644
index 0000000000..6018e9ca9f
--- /dev/null
+++ b/Ghidra/patch/certification.local.manifest
@@ -0,0 +1,2 @@
+##VERSION: 2.0
+README.txt||GHIDRA||||END|
diff --git a/GhidraBuild/BuildFiles/JsonDoclet/src/main/java/JsonDoclet.java b/GhidraBuild/BuildFiles/JsonDoclet/src/main/java/JsonDoclet.java
index 438b7cb42d..eecabab05e 100644
--- a/GhidraBuild/BuildFiles/JsonDoclet/src/main/java/JsonDoclet.java
+++ b/GhidraBuild/BuildFiles/JsonDoclet/src/main/java/JsonDoclet.java
@@ -39,8 +39,6 @@ import jdk.javadoc.doclet.*;
@SuppressWarnings("unchecked")
public class JsonDoclet implements Doclet {
- private final Set ACCESS_LEVEL = Set.of(Modifier.PUBLIC);
-
private Reporter log;
private File destDir;
@@ -122,8 +120,7 @@ public class JsonDoclet implements Doclet {
//@formatter:off
ElementFilter.typesIn(docEnv.getIncludedElements())
.stream()
- .filter(el -> el.getModifiers().containsAll(ACCESS_LEVEL))
- .filter(el -> el.getKind().equals(ElementKind.CLASS))
+ .filter(el -> el.getKind().equals(ElementKind.CLASS) || el.getKind().equals(ElementKind.INTERFACE))
.forEach(el -> writeJsonToFile(classToJson(el), el.getQualifiedName()));
//@formatter:on
@@ -211,9 +208,6 @@ public class JsonDoclet implements Doclet {
JSONArray methodArray = new JSONArray();
for (Element el : classElement.getEnclosedElements()) {
- if (!el.getModifiers().containsAll(ACCESS_LEVEL)) {
- continue;
- }
JSONObject obj = new JSONObject();
obj.put("name", el.getSimpleName().toString());
diff --git a/GhidraBuild/BuildFiles/certification.manifest b/GhidraBuild/BuildFiles/certification.manifest
index 40d82f7a77..95930675a6 100644
--- a/GhidraBuild/BuildFiles/certification.manifest
+++ b/GhidraBuild/BuildFiles/certification.manifest
@@ -6,3 +6,5 @@ JsonDoclet/.project||GHIDRA||||END|
JsonDoclet/Module.manifest||GHIDRA||||END|
JsonDoclet/build.gradle||GHIDRA||||END|
build.gradle||GHIDRA||||END|
+sleighDevBuild.template||GHIDRA||||END|
+sleighDistBuild.template||GHIDRA||||END|
diff --git a/GhidraBuild/BuildFiles/sleighDevBuild.template b/GhidraBuild/BuildFiles/sleighDevBuild.template
new file mode 100644
index 0000000000..d81928bd61
--- /dev/null
+++ b/GhidraBuild/BuildFiles/sleighDevBuild.template
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/GhidraBuild/BuildFiles/sleighDistBuild.template b/GhidraBuild/BuildFiles/sleighDistBuild.template
new file mode 100644
index 0000000000..ec9976b7c3
--- /dev/null
+++ b/GhidraBuild/BuildFiles/sleighDistBuild.template
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/GhidraBuild/Skeleton/certification.manifest b/GhidraBuild/Skeleton/certification.manifest
index 25a6ffeb28..89c984df68 100644
--- a/GhidraBuild/Skeleton/certification.manifest
+++ b/GhidraBuild/Skeleton/certification.manifest
@@ -12,6 +12,7 @@ data/languages/skel.opinion||GHIDRA||||END|
data/languages/skel.pspec||GHIDRA||||END|
data/languages/skel.sinc||GHIDRA||||END|
data/languages/skel.slaspec||GHIDRA||||END|
+data/sleighArgs.txt||GHIDRA||||END|
extension.properties||GHIDRA||||END|
ghidra_scripts/README.txt||GHIDRA||||END|
lib/README.txt||GHIDRA||||END|
diff --git a/GhidraBuild/Skeleton/data/build.xml b/GhidraBuild/Skeleton/data/build.xml
index b83278c5e4..1e2a6276bc 100644
--- a/GhidraBuild/Skeleton/data/build.xml
+++ b/GhidraBuild/Skeleton/data/build.xml
@@ -2,50 +2,21 @@
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
+
@@ -58,12 +29,9 @@
+
-
-
-
-
+
+
diff --git a/GhidraBuild/Skeleton/data/sleighArgs.txt b/GhidraBuild/Skeleton/data/sleighArgs.txt
new file mode 100644
index 0000000000..ce06926358
--- /dev/null
+++ b/GhidraBuild/Skeleton/data/sleighArgs.txt
@@ -0,0 +1,6 @@
+# Add sleigh compiler options to this file (one per line) which will
+# be used when compiling each language within this module.
+# All options should start with a '-' character.
+#
+# IMPORTANT: The -a option should NOT be specified
+#
\ No newline at end of file
diff --git a/README.md b/README.md
index 33534f060f..3254c39b25 100644
--- a/README.md
+++ b/README.md
@@ -4,14 +4,13 @@ Ghidra is a software reverse engineering (SRE) framework created and maintained
In support of NSA's Cybersecurity mission, Ghidra was built to solve scaling and teaming problems on complex SRE efforts, and to provide a customizable and extensible SRE research platform. NSA has applied Ghidra SRE capabilities to a variety of problems that involve analyzing malicious code and generating deep insights for SRE analysts who seek a better understanding of potential vulnerabilities in networks and systems.
-This repository is a placeholder for the full open source release.
-Be assured efforts are underway to make the software available here.
-In the meantime, enjoy using Ghidra on your SRE efforts, developing your
-own scripts and plugins, and perusing the over-one-million-lines of Java and
-Sleigh code released within the initial public release.
+This repository contains the framework and core features.
+More often than not, you can develop extensions and scripts without modifying the core framework.
+Nevertheless, we appreciate all your contributions.
+Try out the GhidraDev plugin for Eclipse, which is part of the distribution package, to get started developing.
The release can be downloaded from our [project homepage][project].
-Please consider taking a look at our [contributor guide][contrib] to see how
-you can participate in this open source project when it becomes available.
+If you would like to contribute to the framework and core feature set, please take a look at our [contributor guide][contrib] to see how
+you can participate in this open source project.
If you are interested in projects like this and would like to develop this, and
other cybersecurity tools, for NSA to help protect our nation and its allies,
diff --git a/gradleScripts/distribution.gradle b/gradleScripts/distribution.gradle
index 84bd24a87c..15260c088c 100644
--- a/gradleScripts/distribution.gradle
+++ b/gradleScripts/distribution.gradle
@@ -134,6 +134,10 @@ task createJsondocs(type: Javadoc, description: 'Generate JSON docs for all proj
it.sourceSets.test.compileClasspath
})
+ // Generate at package level because user may try to get help directly on an object they have
+ // rather than its public interface.
+ options.addBooleanOption("package", true)
+
// Some internal packages are not public and need to be exported.
options.addMultilineStringsOption("-add-exports").setValue(["java.desktop/sun.awt.image=ALL-UNNAMED",
"java.desktop/sun.awt=ALL-UNNAMED",
@@ -196,6 +200,8 @@ task assembleCommon (type: Copy) {
exclude "**/.project"
exclude "**/.classpath"
exclude "**/delete.me"
+ exclude "**/.vs/**"
+ exclude "**/*.vcxproj.user"
/////////////////
// GHIDRA PROJECTS
@@ -221,6 +227,7 @@ task assembleCommon (type: Copy) {
from (p.projectDir.toString() + "/data") {
into { getZipPath(p) + "/data" }
+ exclude 'build.xml' // associated with language modules (dev use only)
}
from (BIN_REPO + '/' + getZipPath(p) + "/data") {
@@ -695,6 +702,7 @@ subprojects { p ->
exclude 'bin/**'
exclude 'src/**'
exclude 'test/**'
+ exclude 'data/build.xml'
exclude 'developer_scripts'
// general place where extension modules can put files that won't get
diff --git a/gradleScripts/ip.gradle b/gradleScripts/ip.gradle
index 1522104e6a..18a778c275 100644
--- a/gradleScripts/ip.gradle
+++ b/gradleScripts/ip.gradle
@@ -120,8 +120,11 @@ def Map> getIpForModule(Project p) {
exclude "build.gradle"
exclude "**/Misc/Tips.htm"
exclude "**/*.sla"
+ exclude "**/data/build.xml" // language build file (generated for dev only)
exclude "**/.gradle/**"
exclude "**/.settings/**"
+ exclude "**/.vs/**"
+ exclude "**/*.vcxproj.user"
}
tree.each { file ->
String ip = getIp(p.projectDir, file)
diff --git a/gradleScripts/processorUtils.gradle b/gradleScripts/processorUtils.gradle
index 99bb843875..7d83c68ccc 100644
--- a/gradleScripts/processorUtils.gradle
+++ b/gradleScripts/processorUtils.gradle
@@ -1,4 +1,3 @@
-
/*****************************************************************************************
*
* Create a configuration so the a dependency can be declared on the the software modeling
@@ -14,6 +13,64 @@ dependencies {
sleighConfig project(':SoftwareModeling')
}
+/*****************************************************************************************
+ *
+ * Task to write sleigh compiler args to build/data/sleighArgs.txt for use with sleigh
+ * external sleigh compiler.
+ *
+ *****************************************************************************************/
+task saveSleighArgs {
+ def sleighArgsFile = file("build/data/sleighArgs.txt")
+ outputs.files sleighArgsFile
+ outputs.upToDateWhen { false }
+ doLast {
+ sleighArgsFile.withWriter { out->
+ project.sleighCompile.args.each { a->
+ // don't save -a option
+ if (!"-a".equals(a)) {
+ out.println a
+ }
+ }
+ }
+ }
+}
+
+prepDev.dependsOn(saveSleighArgs)
+
+/*****************************************************************************************
+ *
+ * Task to write sleigh build.xml file for use is development mode only.
+ *
+ *****************************************************************************************/
+task writeSleighDevBuild {
+ def templateFilePath = project(':BuildFiles').projectDir.toString() + "/sleighDevBuild.template"
+ doLast {
+ // Generate build.xml with injected classpath for running sleigh compiler
+ copy {
+ into "data"
+ from (templateFilePath) {
+ rename { "build.xml" }
+ expand ( [ 'gradleSleighDevClasspath': project(':SoftwareModeling').sleighDevClasspath ] )
+ }
+ }
+ }
+}
+
+prepDev.dependsOn(writeSleighDevBuild)
+
+/*****************************************************************************************
+ *
+ * Write sleigh build.xml file for each language module into assembleCommon
+ *
+ *****************************************************************************************/
+rootProject.assembleCommon {
+ into (getZipPath(this.project) + "/data") {
+ from (rootProject.projectDir.toString() + "/GhidraBuild/BuildFiles/sleighDistBuild.template") {
+ rename { "build.xml" }
+ }
+ }
+}
+
/*****************************************************************************************
*
* Task to compile language files using the sleigh compiler.
@@ -22,17 +79,16 @@ dependencies {
task sleighCompile (type: JavaExec) {
group = rootProject.GHIDRA_GROUP
description " Compiles all the sleigh languages. [processorUtils.gradle]\n"
-
+
// define standard parameters for JavaExec
classpath configurations.sleighConfig
main = 'ghidra.pcodeCPort.slgh_compile.SleighCompile'
- args '-a'
-
// Delay adding the directory argument until the first part of the execution phase, so
// that any extra args added by a project override will be added to the arg list before
- // this argument.
+ // these arguments.
doFirst {
+ args '-a'
args './data/languages'
}
@@ -40,8 +96,9 @@ task sleighCompile (type: JavaExec) {
}
// The task that copies the common files to the distribution folder must depend on
-// this sleigh task before executing.
+// the sleigh tasks before executing.
rootProject.assembleCommon.dependsOn(sleighCompile)
+rootProject.assembleCommon.dependsOn(saveSleighArgs)
// For all tasks of type:Test (i.e., integrationTest, cunitTest, etc.), add a task dependency to
// sleighCompile. The sleighCompile task inputs and outputs are defined such that the *.slaspec
@@ -52,8 +109,9 @@ rootProject.assembleCommon.dependsOn(sleighCompile)
// modules as seen in the use of ghidra.test.ToyProgramBuilder.
// The tasks of type:Test do not know about sleighCompile during their configuration phase, so the
// dependency must be done in this gradle file.
-rootProject.subprojects.findAll { subproject ->
- if (!isSupportModule(subproject)) {
+rootProject.subprojects.findAll { subproject ->
+ boolean isSupporProject = subproject.findProperty("isSupportProject") ?: false;
+ if (!isSupporProject) {
subproject.tasks.withType(Test).all {
it.dependsOn(sleighCompile)
}
@@ -91,26 +149,9 @@ def taskOutputs = fileTree(dir: 'data/languages', include: '**/*.sla')
sleighCompile.inputs.files (taskInputs)
sleighCompile.outputs.files (taskOutputs)
-task eclipseSleighLauncher(type: WriteEclipseLauncher) {
- dest = forName("Sleigh $project.name")
- isRunFave = true
- isDbgFave = false
-
- classpath = configurations.sleighConfig
- main 'ghidra.pcodeCPort.slgh_compile.SleighCompile'
-
- args '-a'
-
- // Delay adding the directory argument until the first part of the execution phase, so
- // that any extra args added by a project override will be added to the arg list before
- // this argument.
- doFirst {
- args './data/languages'
- }
-
- jvmArgs '-Xmx2048M'
-}
+// define the sleigh compile inputs to saveSleighArgs to limit task creation to language modules
+saveSleighArgs.inputs.files (taskInputs)
def isSupportModule(Project p) {
return p.findProperty("isSupportProject") ?: false
-}
\ No newline at end of file
+}
diff --git a/licenses/FAMFAMFAM_MINI_ICONS_-_Public_Domain.txt b/licenses/FAMFAMFAM_Mini_Icons_-_Public_Domain.txt
similarity index 100%
rename from licenses/FAMFAMFAM_MINI_ICONS_-_Public_Domain.txt
rename to licenses/FAMFAMFAM_Mini_Icons_-_Public_Domain.txt
diff --git a/licenses/certification.manifest b/licenses/certification.manifest
index 94ef6577e7..b11781ed93 100644
--- a/licenses/certification.manifest
+++ b/licenses/certification.manifest
@@ -5,7 +5,8 @@ Christian_Plattner.txt||LICENSE||||END|
Creative_Commons_Attribution_2.5.html||LICENSE||||END|
Crystal_Clear_Icons_-_LGPL_2.1.txt||LICENSE||||END|
FAMFAMFAM_Icons_-_CC_2.5.txt||LICENSE||||END|
-FAMFAMFAM_MINI_ICONS_-_Public_Domain.txt||LICENSE||||END|
+FAMFAMFAM_Mini_Icons_-_Public_Domain.txt||LICENSE||||END|
+FAMFAMFAM Mini Icons - Public Domain.txt||LICENSE||||END|
GPL_2_With_Classpath_Exception.txt||LICENSE||||END|
JDOM_License.txt||LICENSE||||END|
Jython_License.txt||LICENSE||||END|