From 65f58752dedcaa71a0536d210445adb593fe0957 Mon Sep 17 00:00:00 2001 From: dragonmacher <48328597+dragonmacher@users.noreply.github.com> Date: Tue, 30 Sep 2025 10:35:56 -0400 Subject: [PATCH 1/4] GP-6024 - Version Tracking - Fixed missing tool options --- .../framework/plugintool/PluginManager.java | 1 - .../plugintool/mgr/OptionsManager.java | 41 ++++--------------- 2 files changed, 8 insertions(+), 34 deletions(-) diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/PluginManager.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/PluginManager.java index d8811e190e..de35486898 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/PluginManager.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/PluginManager.java @@ -425,7 +425,6 @@ class PluginManager { private void unregisterPlugin(Plugin plugin) { if (pluginList.remove(plugin)) { plugin.cleanup(); - tool.getOptionsManager().deregisterOwner(plugin); } } diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/mgr/OptionsManager.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/mgr/OptionsManager.java index dd10bfb3a9..b9e5785782 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/mgr/OptionsManager.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/mgr/OptionsManager.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -28,7 +28,6 @@ import docking.options.editor.OptionsDialog; import docking.tool.ToolConstants; import docking.tool.util.DockingToolConstants; import ghidra.framework.options.*; -import ghidra.framework.plugintool.Plugin; import ghidra.framework.plugintool.PluginTool; import ghidra.framework.plugintool.dialog.KeyBindingsPanel; import ghidra.util.HelpLocation; @@ -111,9 +110,7 @@ public class OptionsManager implements OptionsService, OptionsChangeListener { public ToolOptions[] getOptions() { ToolOptions[] opt = new ToolOptions[optionsMap.size()]; int idx = 0; - Iterator iter = optionsMap.keySet().iterator(); - while (iter.hasNext()) { - String key = iter.next(); + for (String key : optionsMap.keySet()) { opt[idx] = optionsMap.get(key); ++idx; } @@ -121,24 +118,6 @@ public class OptionsManager implements OptionsService, OptionsChangeListener { return opt; } - /** - * Deregister the owner from the options; if options are empty, then - * remove the options from the map. - * @param ownerPlugin the owner plugin - */ - public void deregisterOwner(Plugin ownerPlugin) { - List deleteList = new ArrayList<>(); - Iterator iter = optionsMap.keySet().iterator(); - while (iter.hasNext()) { - String key = iter.next(); - ToolOptions opt = optionsMap.get(key); - if (opt.getOptionNames().isEmpty()) { - deleteList.add(opt.getName()); - } - } - removeUnusedOptions(deleteList); - } - /** * Write this object out; first remove any unused options so they * do not hang around. @@ -146,9 +125,7 @@ public class OptionsManager implements OptionsService, OptionsChangeListener { */ public Element getConfigState() { Element root = new Element("OPTIONS"); - Iterator iter = optionsMap.keySet().iterator(); - while (iter.hasNext()) { - String key = iter.next(); + for (String key : optionsMap.keySet()) { ToolOptions opt = optionsMap.get(key); if (hasNonDefaultValues(opt)) { root.addContent(opt.getXmlRoot(false)); @@ -170,9 +147,7 @@ public class OptionsManager implements OptionsService, OptionsChangeListener { public void removeUnusedOptions() { // 1st clean up any unused options before saving... List deleteList = new ArrayList<>(); - Iterator iter = optionsMap.keySet().iterator(); - while (iter.hasNext()) { - String key = iter.next(); + for (String key : optionsMap.keySet()) { ToolOptions opt = optionsMap.get(key); opt.removeUnusedOptions(); if (opt.getOptionNames().isEmpty()) { @@ -239,9 +214,9 @@ public class OptionsManager implements OptionsService, OptionsChangeListener { } keyBindingOptions.registerOptionsEditor(() -> new KeyBindingOptionsEditor()); - OptionsDialog dialog = - new OptionsDialog("Options for " + tool.getName(), "Options", getEditableOptions(), - null, true); + String optionsName = "Options for " + tool.getName(); + Options[] options = getEditableOptions(); + OptionsDialog dialog = new OptionsDialog(optionsName, "Options", options, null, true); dialog.setSelectedPath(path); dialog.setHelpLocation( new HelpLocation(ToolConstants.TOOL_HELP_TOPIC, "ToolOptions_Dialog")); From 3b14dcf58b14bb9f023e2e7f46d650ea128a863b Mon Sep 17 00:00:00 2001 From: dragonmacher <48328597+dragonmacher@users.noreply.github.com> Date: Tue, 30 Sep 2025 16:11:56 -0400 Subject: [PATCH 2/4] GP-6034 - Version Tracking - Fixed Function Comparison view not being resizable --- .../panel/FunctionComparisonPanel.java | 8 ++++ .../VTImpliedMatchesTableProvider.java | 18 +++------ .../VTMarkupItemsTableProvider.java | 12 +----- .../matchtable/VTMatchTableProvider.java | 10 +---- .../VTMatchOneToManyTableProvider.java | 11 +----- .../VTRelatedMatchesTableProvider.java | 39 ++++--------------- 6 files changed, 28 insertions(+), 70 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/features/base/codecompare/panel/FunctionComparisonPanel.java b/Ghidra/Features/Base/src/main/java/ghidra/features/base/codecompare/panel/FunctionComparisonPanel.java index bef7de2281..a362c9d9d2 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/features/base/codecompare/panel/FunctionComparisonPanel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/features/base/codecompare/panel/FunctionComparisonPanel.java @@ -97,6 +97,14 @@ public class FunctionComparisonPanel extends JPanel implements ChangeListener { help.registerHelp(this, new HelpLocation(HELP_TOPIC, "Function Comparison")); } + @Override + public Dimension getMinimumSize() { + // If we don't specify a minimum size, the some layouts will use the preferred size when + // calculating the minimum size. When this happens while this panel is inside of a split + // pane, the split pane can become un-resizable. By specify a value here, we prevent this. + return new Dimension(50, 50); + } + private void comparisonStateUpdated() { readPanelState(); readViewState(); diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/impliedmatches/VTImpliedMatchesTableProvider.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/impliedmatches/VTImpliedMatchesTableProvider.java index e91f72db02..ed204d85cc 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/impliedmatches/VTImpliedMatchesTableProvider.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/impliedmatches/VTImpliedMatchesTableProvider.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -15,7 +15,8 @@ */ package ghidra.feature.vt.gui.provider.impliedmatches; -import java.awt.*; +import java.awt.BorderLayout; +import java.awt.Dimension; import java.util.ArrayList; import java.util.List; @@ -299,15 +300,8 @@ public class VTImpliedMatchesTableProvider extends ComponentProviderAdapter TableColumn statusColumn = columnModel.getColumn(statusColumnIndex); statusColumn.setCellRenderer(new MatchStatusRenderer()); - // override the default behavior so we see our columns in their preferred size - Dimension size = impliedMatchesTable.getPreferredScrollableViewportSize(); - Dimension preferredSize = impliedMatchesTable.getPreferredSize(); - - // ...account for the scroll bar width - JScrollBar scrollBar = new JScrollBar(Adjustable.VERTICAL); - Dimension scrollBarSize = scrollBar.getMinimumSize(); - size.width = preferredSize.width + scrollBarSize.width; - impliedMatchesTable.setPreferredScrollableViewportSize(size); + // a reasonable starting size picked by trial-and-error + impliedMatchesTable.setPreferredScrollableViewportSize(new Dimension(1100, 600)); return impliedMatchTablePanel; } diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/markuptable/VTMarkupItemsTableProvider.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/markuptable/VTMarkupItemsTableProvider.java index 2f24f2ac6e..38eaa776a3 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/markuptable/VTMarkupItemsTableProvider.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/markuptable/VTMarkupItemsTableProvider.java @@ -320,16 +320,8 @@ public class VTMarkupItemsTableProvider extends ComponentProviderAdapter TableColumn column = columnModel.getColumn(columnIndex); column.setCellEditor(new AddressInputDialog(controller)); - // override the default behavior so we see our columns in their preferred size - Dimension size = table.getPreferredScrollableViewportSize(); - Dimension preferredSize = table.getPreferredSize(); - - // ...account for the scroll bar width - JScrollBar scrollBar = new JScrollBar(Adjustable.VERTICAL); - scrollBar.getAccessibleContext().setAccessibleName("Markup Item Table"); - Dimension scrollBarSize = scrollBar.getMinimumSize(); - size.width = preferredSize.width + scrollBarSize.width; - table.setPreferredScrollableViewportSize(size); + // a reasonable starting size picked by trial-and-error + table.setPreferredScrollableViewportSize(new Dimension(1100, 600)); table.getAccessibleContext().setAccessibleName("Markup Item"); return table; } diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/matchtable/VTMatchTableProvider.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/matchtable/VTMatchTableProvider.java index a2b4ddc083..a9ee73fe03 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/matchtable/VTMatchTableProvider.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/matchtable/VTMatchTableProvider.java @@ -373,15 +373,9 @@ public class VTMatchTableProvider extends ComponentProviderAdapter TableColumn statusColumn = columnModel.getColumn(statusColumnIndex); statusColumn.setCellRenderer(new MatchStatusRenderer()); - // override the default behavior so we see our columns in their preferred size - Dimension size = table.getPreferredScrollableViewportSize(); - Dimension preferredSize = table.getPreferredSize(); + // a reasonable starting size picked by trial-and-error + table.setPreferredScrollableViewportSize(new Dimension(1100, 600)); - // ...account for the scroll bar width - JScrollBar scrollBar = new JScrollBar(Adjustable.VERTICAL); - Dimension scrollBarSize = scrollBar.getMinimumSize(); - size.width = preferredSize.width + scrollBarSize.width; - table.setPreferredScrollableViewportSize(size); return table; } diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/onetomany/VTMatchOneToManyTableProvider.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/onetomany/VTMatchOneToManyTableProvider.java index 5820ac9632..a425dc80db 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/onetomany/VTMatchOneToManyTableProvider.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/onetomany/VTMatchOneToManyTableProvider.java @@ -257,15 +257,8 @@ public abstract class VTMatchOneToManyTableProvider extends ComponentProviderAda TableColumn statusColumn = columnModel.getColumn(statusColumnIndex); statusColumn.setCellRenderer(new MatchStatusRenderer()); - // override the default behavior so we see our columns in their preferred size - Dimension size = table.getPreferredScrollableViewportSize(); - Dimension preferredSize = table.getPreferredSize(); - - // ...account for the scroll bar width - JScrollBar scrollBar = new JScrollBar(Adjustable.VERTICAL); - Dimension scrollBarSize = scrollBar.getMinimumSize(); - size.width = preferredSize.width + scrollBarSize.width; - table.setPreferredScrollableViewportSize(size); + // a reasonable starting size picked by trial-and-error + table.setPreferredScrollableViewportSize(new Dimension(1100, 600)); return table; } diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/relatedMatches/VTRelatedMatchesTableProvider.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/relatedMatches/VTRelatedMatchesTableProvider.java index 4e8a90ea51..14d88621c3 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/relatedMatches/VTRelatedMatchesTableProvider.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/relatedMatches/VTRelatedMatchesTableProvider.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -15,10 +15,11 @@ */ package ghidra.feature.vt.gui.provider.relatedMatches; -import java.awt.*; +import java.awt.BorderLayout; +import java.awt.Dimension; import java.awt.event.MouseEvent; -import java.util.*; -import java.util.List; +import java.util.HashSet; +import java.util.Set; import javax.swing.*; import javax.swing.event.ListSelectionEvent; @@ -62,7 +63,6 @@ public class VTRelatedMatchesTableProvider extends ComponentProviderAdapter { setWindowGroup(VTPlugin.WINDOW_GROUP); setIcon(ICON); - createActions(); addToTool(); } @@ -109,44 +109,21 @@ public class VTRelatedMatchesTableProvider extends ComponentProviderAdapter { ListSelectionModel selectionModel = table.getSelectionModel(); selectionModel.addListSelectionListener(matchSelectionListener); - // override the default behavior so we see our columns in their preferred size - Dimension size = table.getPreferredScrollableViewportSize(); - Dimension preferredSize = table.getPreferredSize(); - - // ...account for the scroll bar width - JScrollBar scrollBar = new JScrollBar(Adjustable.VERTICAL); - Dimension scrollBarSize = scrollBar.getMinimumSize(); - size.width = preferredSize.width + scrollBarSize.width; - table.setPreferredScrollableViewportSize(size); + // a reasonable starting size picked by trial-and-error + table.setPreferredScrollableViewportSize(new Dimension(1100, 600)); return table; } - private void createActions() { -// addLocalAction( new AddMarkupItemAction( this ) ); -// addLocalAction( new IgnoreMarkupItemAction( this ) ); - } - private void notifyContextChanged() { tool.contextChanged(this); } @Override public ActionContext getActionContext(MouseEvent event) { -// List selectedItems = getSelectedMatches(); -// return new MarkupItemContext( this, selectedItems ); return null; } - private List getSelectedMatches() { - List list = new ArrayList(); - int[] selectedRows = relatedMatchesTable.getSelectedRows(); - for (int row : selectedRows) { - list.add(relatedMatchesTableModel.getRowObject(row)); - } - return list; - } - public void refresh() { relatedMatchesTableModel.reload(); } From c9b0c8ad76a4170b11860b5f3c4cebffa2b23466 Mon Sep 17 00:00:00 2001 From: dragonmacher <48328597+dragonmacher@users.noreply.github.com> Date: Tue, 30 Sep 2025 16:34:56 -0400 Subject: [PATCH 3/4] Help fixes --- .../functiongraph/actions/FgToggleSatelliteAction.java | 2 +- .../java/ghidra/framework/main/ProjectRepoConnectAction.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Ghidra/Features/CodeCompare/src/main/java/ghidra/features/codecompare/functiongraph/actions/FgToggleSatelliteAction.java b/Ghidra/Features/CodeCompare/src/main/java/ghidra/features/codecompare/functiongraph/actions/FgToggleSatelliteAction.java index a82df30218..f287f759c0 100644 --- a/Ghidra/Features/CodeCompare/src/main/java/ghidra/features/codecompare/functiongraph/actions/FgToggleSatelliteAction.java +++ b/Ghidra/Features/CodeCompare/src/main/java/ghidra/features/codecompare/functiongraph/actions/FgToggleSatelliteAction.java @@ -37,7 +37,7 @@ public class FgToggleSatelliteAction extends ToggleDockingAction { setPopupMenuData(new MenuData(new String[] { "Display Satellite" })); - setHelpLocation(new HelpLocation("FunctionGraphPlugin", "Satellite_View")); + setHelpLocation(new HelpLocation("VisualGraph", "Satellite_View")); } @Override diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/ProjectRepoConnectAction.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/ProjectRepoConnectAction.java index 9b31acd9d2..d14a800a78 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/ProjectRepoConnectAction.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/ProjectRepoConnectAction.java @@ -44,7 +44,7 @@ public class ProjectRepoConnectAction extends FrontendProjectTreeAction { this.plugin = plugin; setPopupMenuData( new MenuData(new String[] { "Connect Shared Repository" }, CONNECT_ICON, group)); - setHelpLocation(new HelpLocation("VersionControl", "Connect_Shared_Repository")); + setHelpLocation(new HelpLocation("VersionControl", "ConnectToServer")); } @Override From aef70ea9becc4a4c752fd685454e8d52afd89707 Mon Sep 17 00:00:00 2001 From: Ryan Kurtz Date: Wed, 1 Oct 2025 04:59:54 -0400 Subject: [PATCH 4/4] GP-6022: Better error reporting when expanding environment variables in launch.properties --- .../java/ghidra/launch/LaunchProperties.java | 25 +++++++++++++------ 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/GhidraBuild/LaunchSupport/src/main/java/ghidra/launch/LaunchProperties.java b/GhidraBuild/LaunchSupport/src/main/java/ghidra/launch/LaunchProperties.java index 92fb71359d..c3822b9d9e 100644 --- a/GhidraBuild/LaunchSupport/src/main/java/ghidra/launch/LaunchProperties.java +++ b/GhidraBuild/LaunchSupport/src/main/java/ghidra/launch/LaunchProperties.java @@ -182,14 +182,23 @@ public class LaunchProperties { * * @param text The string to expand environment variables in * @return The given string, but with set environment variables expanded + * @throws ParseException if there was a problem expanding an environment variable */ - private static String expandEnvVars(String text) { + private static String expandEnvVars(String text) throws ParseException { Map envMap = System.getenv(); - for (Entry entry : envMap.entrySet()) { - String key = entry.getKey(); - String value = entry.getValue(); - text = text.replaceAll("\\$\\{" + key + "\\}", value.replace("\\", "\\\\")); - } - return text; - } + for (Entry entry : envMap.entrySet()) { + String key = entry.getKey(); + String value = entry.getValue(); + try { + text = text.replaceAll("\\$\\{" + key + "\\}", value.replace("\\", "\\\\")); + } + catch (IllegalArgumentException e) { + throw new ParseException( + "Error expanding environment variable in %s (env %s=%s) -- %s".formatted(text, + key, value, e.getMessage()), + 0); + } + } + return text; + } }