mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-06-01 09:34:56 +08:00
Merge remote-tracking branch 'origin/patch'
This commit is contained in:
+8
-5
@@ -41,12 +41,15 @@
|
||||
dead or terminated. A "dead" trace can still be manipulated and marked up, but it will not
|
||||
record any new target information.</P>
|
||||
|
||||
<H3><A name="close_trace"></A><A name="close_all_traces"></A><A name=
|
||||
"close_other_traces"></A><A name="close_dead_traces"></A>Close Trace / All / Other / Dead
|
||||
Traces</H3>
|
||||
|
||||
<P>In most cases, a trace is ephemeral, but occasionally, interesting behavior is observed that
|
||||
is difficult to store as static mark-up. When a trace is no longer needed, it can be closed by
|
||||
right-clicking the tab and selecting "Close Trace." <FONT color="red">Warning:</FONT> closing a
|
||||
trace that has not been saved <EM>cannot</EM> be undone. If you accumulate many unwanted
|
||||
traces, use one of the "Close Others," "Close Dead," or "Close All" actions from the pop-up
|
||||
menu.</P>
|
||||
is difficult to store as static mark-up. When traces are no longer needed, they can be closed
|
||||
by right-clicking a tab and selecting one of the actions. See <A href=
|
||||
"help/topics/DebuggerTraceManagerServicePlugin/DebuggerTraceManagerServicePlugin.html#close_trace">Trace
|
||||
Management</A> for details of each action.</P>
|
||||
|
||||
<H2>Navigating Threads</H2>
|
||||
|
||||
|
||||
+58
-15
@@ -1748,26 +1748,36 @@ public interface DebuggerResources {
|
||||
.menuIcon(ICON)
|
||||
.menuPath(DebuggerPluginPackage.NAME, NAME)
|
||||
.helpLocation(new HelpLocation(ownerName, HELP_ANCHOR));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
interface CloseTraceAction {
|
||||
String NAME_PREFIX = "Close ";
|
||||
String DESCRIPTION = "Close the current trace";
|
||||
String DESCRIPTION = "Close the current or selected trace";
|
||||
String GROUP = GROUP_TRACE_CLOSE;
|
||||
String SUB_GROUP = "a";
|
||||
Icon ICON = ICON_CLOSE;
|
||||
String HELP_ANCHOR = "close_trace";
|
||||
|
||||
static ActionBuilder builder(Plugin owner) {
|
||||
static ActionBuilder builderCommon(Plugin owner) {
|
||||
String ownerName = owner.getName();
|
||||
return new ActionBuilder(NAME_PREFIX, ownerName)
|
||||
.description(DESCRIPTION)
|
||||
.menuGroup(GROUP)
|
||||
.menuIcon(ICON)
|
||||
.menuPath(DebuggerPluginPackage.NAME, NAME_PREFIX + "...")
|
||||
.helpLocation(new HelpLocation(ownerName, HELP_ANCHOR));
|
||||
}
|
||||
|
||||
static ActionBuilder builder(Plugin owner) {
|
||||
return builderCommon(owner)
|
||||
.menuGroup(GROUP, SUB_GROUP)
|
||||
.menuIcon(ICON)
|
||||
.menuPath(DebuggerPluginPackage.NAME, NAME_PREFIX + "...");
|
||||
}
|
||||
|
||||
static ActionBuilder builderPopup(Plugin owner) {
|
||||
return builderCommon(owner)
|
||||
.popupMenuGroup(GROUP, SUB_GROUP)
|
||||
.popupMenuIcon(ICON)
|
||||
.popupMenuPath(NAME_PREFIX + "...");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1776,14 +1786,25 @@ public interface DebuggerResources {
|
||||
String DESCRIPTION = "Close all traces";
|
||||
String HELP_ANCHOR = "close_all_traces";
|
||||
|
||||
static ActionBuilder builder(Plugin owner) {
|
||||
static ActionBuilder builderCommon(Plugin owner) {
|
||||
String ownerName = owner.getName();
|
||||
return new ActionBuilder(NAME, ownerName)
|
||||
.description(DESCRIPTION)
|
||||
.helpLocation(new HelpLocation(ownerName, HELP_ANCHOR));
|
||||
}
|
||||
|
||||
static ActionBuilder builder(Plugin owner) {
|
||||
return builderCommon(owner)
|
||||
.menuGroup(GROUP)
|
||||
.menuIcon(ICON)
|
||||
.menuPath(DebuggerPluginPackage.NAME, NAME)
|
||||
.helpLocation(new HelpLocation(ownerName, HELP_ANCHOR));
|
||||
.menuPath(DebuggerPluginPackage.NAME, NAME);
|
||||
}
|
||||
|
||||
static ActionBuilder builderPopup(Plugin owner) {
|
||||
return builderCommon(owner)
|
||||
.popupMenuGroup(GROUP)
|
||||
.popupMenuIcon(ICON)
|
||||
.popupMenuPath(NAME);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1792,14 +1813,25 @@ public interface DebuggerResources {
|
||||
String DESCRIPTION = "Close all traces except the current one";
|
||||
String HELP_ANCHOR = "close_other_traces";
|
||||
|
||||
static ActionBuilder builder(Plugin owner) {
|
||||
static ActionBuilder builderCommon(Plugin owner) {
|
||||
String ownerName = owner.getName();
|
||||
return new ActionBuilder(NAME, ownerName)
|
||||
.description(DESCRIPTION)
|
||||
.helpLocation(new HelpLocation(ownerName, HELP_ANCHOR));
|
||||
}
|
||||
|
||||
static ActionBuilder builder(Plugin owner) {
|
||||
return builderCommon(owner)
|
||||
.menuGroup(GROUP)
|
||||
.menuIcon(ICON)
|
||||
.menuPath(DebuggerPluginPackage.NAME, NAME)
|
||||
.helpLocation(new HelpLocation(ownerName, HELP_ANCHOR));
|
||||
.menuPath(DebuggerPluginPackage.NAME, NAME);
|
||||
}
|
||||
|
||||
static ActionBuilder builderPopup(Plugin owner) {
|
||||
return builderCommon(owner)
|
||||
.popupMenuGroup(GROUP)
|
||||
.popupMenuIcon(ICON)
|
||||
.popupMenuPath(NAME);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1808,14 +1840,25 @@ public interface DebuggerResources {
|
||||
String DESCRIPTION = "Close all traces not being recorded";
|
||||
String HELP_ANCHOR = "close_dead_traces";
|
||||
|
||||
static ActionBuilder builder(Plugin owner) {
|
||||
static ActionBuilder builderCommon(Plugin owner) {
|
||||
String ownerName = owner.getName();
|
||||
return new ActionBuilder(NAME, ownerName)
|
||||
.description(DESCRIPTION)
|
||||
.helpLocation(new HelpLocation(ownerName, HELP_ANCHOR));
|
||||
}
|
||||
|
||||
static ActionBuilder builder(Plugin owner) {
|
||||
return builderCommon(owner)
|
||||
.menuGroup(GROUP)
|
||||
.menuIcon(ICON)
|
||||
.menuPath(DebuggerPluginPackage.NAME, NAME)
|
||||
.helpLocation(new HelpLocation(ownerName, HELP_ANCHOR));
|
||||
.menuPath(DebuggerPluginPackage.NAME, NAME);
|
||||
}
|
||||
|
||||
static ActionBuilder builderPopup(Plugin owner) {
|
||||
return builderCommon(owner)
|
||||
.popupMenuGroup(GROUP)
|
||||
.popupMenuIcon(ICON)
|
||||
.popupMenuPath(NAME);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+68
-59
@@ -15,11 +15,11 @@
|
||||
*/
|
||||
package ghidra.app.plugin.core.debug.gui.thread;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.ListSelectionEvent;
|
||||
@@ -361,6 +361,12 @@ public class DebuggerThreadsProvider extends ComponentProviderAdapter {
|
||||
SeekTracePresentAction actionSeekTracePresent;
|
||||
ToggleDockingAction actionSyncFocus;
|
||||
DockingAction actionGoToTime;
|
||||
|
||||
DockingAction actionCloseTrace;
|
||||
DockingAction actionCloseOtherTraces;
|
||||
DockingAction actionCloseDeadTraces;
|
||||
DockingAction actionCloseAllTraces;
|
||||
|
||||
Set<Object> strongRefs = new HashSet<>(); // Eww
|
||||
|
||||
public DebuggerThreadsProvider(final DebuggerThreadsPlugin plugin) {
|
||||
@@ -554,6 +560,11 @@ public class DebuggerThreadsProvider extends ComponentProviderAdapter {
|
||||
|
||||
threadTable.getSelectionModel().addListSelectionListener(this::threadRowSelected);
|
||||
threadTable.addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e) {
|
||||
setThreadRowActionContext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseReleased(MouseEvent e) {
|
||||
int selectedRow = threadTable.getSelectedRow();
|
||||
@@ -584,15 +595,13 @@ public class DebuggerThreadsProvider extends ComponentProviderAdapter {
|
||||
list.addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e) {
|
||||
checkTraceTabPopupViaMouse(e);
|
||||
setTraceTabActionContext(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseReleased(MouseEvent e) {
|
||||
checkTraceTabPopupViaMouse(e);
|
||||
}
|
||||
});
|
||||
// TODO: The popup key? Only seems to have rawCode=0x93 (147) in Swing
|
||||
mainPanel.add(traceTabs, BorderLayout.NORTH);
|
||||
|
||||
TableColumnModel columnModel = threadTable.getColumnModel();
|
||||
@@ -622,53 +631,6 @@ public class DebuggerThreadsProvider extends ComponentProviderAdapter {
|
||||
});
|
||||
}
|
||||
|
||||
private void checkTraceTabPopupViaMouse(MouseEvent e) {
|
||||
if (!e.isPopupTrigger()) {
|
||||
return;
|
||||
}
|
||||
JList<Trace> list = traceTabs.getList();
|
||||
int i = list.locationToIndex(e.getPoint());
|
||||
if (i < 0) {
|
||||
return;
|
||||
}
|
||||
Rectangle cell = list.getCellBounds(i, i);
|
||||
if (!cell.contains(e.getPoint())) {
|
||||
return;
|
||||
}
|
||||
showTraceTabPopup(e.getComponent(), e.getPoint(), i);
|
||||
}
|
||||
|
||||
private void showTraceTabPopup(Component comp, Point p, int i) {
|
||||
// TODO: Make this use action contexts and docking actions instead
|
||||
traceTabPopupMenu.removeAll();
|
||||
final Trace trace = traceTabs.getItem(i);
|
||||
JMenuItem closeItem =
|
||||
new JMenuItem("Close " + trace.getName(), DebuggerResources.ICON_CLOSE);
|
||||
closeItem.addActionListener(evt -> {
|
||||
traceManager.closeTrace(trace);
|
||||
});
|
||||
JMenuItem closeOthers = new JMenuItem("Close Others", DebuggerResources.ICON_CLOSE);
|
||||
closeOthers.addActionListener(evt -> {
|
||||
traceManager.closeOtherTraces(trace);
|
||||
});
|
||||
JMenuItem closeDead = new JMenuItem("Close Dead", DebuggerResources.ICON_CLOSE);
|
||||
closeDead.addActionListener(evt -> {
|
||||
traceManager.closeDeadTraces();
|
||||
});
|
||||
JMenuItem closeAll = new JMenuItem("Close All", DebuggerResources.ICON_CLOSE);
|
||||
closeAll.addActionListener(evt -> {
|
||||
for (Trace t : List.copyOf(traceManager.getOpenTraces())) {
|
||||
traceManager.closeTrace(t);
|
||||
}
|
||||
});
|
||||
traceTabPopupMenu.add(closeItem);
|
||||
traceTabPopupMenu.addSeparator();
|
||||
traceTabPopupMenu.add(closeOthers);
|
||||
traceTabPopupMenu.add(closeDead);
|
||||
traceTabPopupMenu.add(closeAll);
|
||||
traceTabPopupMenu.show(comp, p.x, p.y);
|
||||
}
|
||||
|
||||
protected void createActions() {
|
||||
// TODO: Make other actions use builder?
|
||||
actionStepSnapBackward = new StepSnapBackwardAction();
|
||||
@@ -687,6 +649,27 @@ public class DebuggerThreadsProvider extends ComponentProviderAdapter {
|
||||
.buildAndInstallLocal(this);
|
||||
traceManager.addSynchronizeFocusChangeListener(
|
||||
strongRef(new ToToggleSelectionListener(actionSyncFocus)));
|
||||
|
||||
actionCloseTrace = CloseTraceAction.builderPopup(plugin)
|
||||
.withContext(DebuggerTraceFileActionContext.class)
|
||||
.popupWhen(c -> c.getTrace() != null)
|
||||
.onAction(c -> traceManager.closeTrace(c.getTrace()))
|
||||
.buildAndInstallLocal(this);
|
||||
actionCloseAllTraces = CloseAllTracesAction.builderPopup(plugin)
|
||||
.withContext(DebuggerTraceFileActionContext.class)
|
||||
.popupWhen(c -> !traceManager.getOpenTraces().isEmpty())
|
||||
.onAction(c -> traceManager.closeAllTraces())
|
||||
.buildAndInstallLocal(this);
|
||||
actionCloseOtherTraces = CloseOtherTracesAction.builderPopup(plugin)
|
||||
.withContext(DebuggerTraceFileActionContext.class)
|
||||
.popupWhen(c -> traceManager.getOpenTraces().size() > 1 && c.getTrace() != null)
|
||||
.onAction(c -> traceManager.closeOtherTraces(c.getTrace()))
|
||||
.buildAndInstallLocal(this);
|
||||
actionCloseDeadTraces = CloseDeadTracesAction.builderPopup(plugin)
|
||||
.withContext(DebuggerTraceFileActionContext.class)
|
||||
.popupWhen(c -> !traceManager.getOpenTraces().isEmpty() && modelService != null)
|
||||
.onAction(c -> traceManager.closeDeadTraces())
|
||||
.buildAndInstallLocal(this);
|
||||
}
|
||||
|
||||
private void toggleSyncFocus(boolean enabled) {
|
||||
@@ -712,24 +695,50 @@ public class DebuggerThreadsProvider extends ComponentProviderAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
private Trace computeClickedTraceTab(MouseEvent e) {
|
||||
JList<Trace> list = traceTabs.getList();
|
||||
int i = list.locationToIndex(e.getPoint());
|
||||
if (i < 0) {
|
||||
return null;
|
||||
}
|
||||
Rectangle cell = list.getCellBounds(i, i);
|
||||
if (!cell.contains(e.getPoint())) {
|
||||
return null;
|
||||
}
|
||||
return traceTabs.getItem(i);
|
||||
}
|
||||
|
||||
private Trace setTraceTabActionContext(MouseEvent e) {
|
||||
Trace newTrace = e == null ? traceTabs.getSelectedItem() : computeClickedTraceTab(e);
|
||||
actionCloseTrace.getPopupMenuData()
|
||||
.setMenuItemName(
|
||||
CloseTraceAction.NAME_PREFIX + (newTrace == null ? "..." : newTrace.getName()));
|
||||
myActionContext = new DebuggerTraceFileActionContext(newTrace);
|
||||
contextChanged();
|
||||
return newTrace;
|
||||
}
|
||||
|
||||
private void traceTabSelected(ListSelectionEvent e) {
|
||||
if (e.getValueIsAdjusting()) {
|
||||
return;
|
||||
}
|
||||
Trace newTrace = traceTabs.getSelectedItem();
|
||||
myActionContext = new DebuggerThreadActionContext(newTrace, null);
|
||||
contextChanged();
|
||||
Trace newTrace = setTraceTabActionContext(null);
|
||||
cbCoordinateActivation.invoke(() -> traceManager.activateTrace(newTrace));
|
||||
}
|
||||
|
||||
private ThreadRow setThreadRowActionContext() {
|
||||
ThreadRow row = threadFilterPanel.getSelectedItem();
|
||||
myActionContext = new DebuggerThreadActionContext(current.getTrace(),
|
||||
row == null ? null : row.getThread());
|
||||
contextChanged();
|
||||
return row;
|
||||
}
|
||||
|
||||
private void threadRowSelected(ListSelectionEvent e) {
|
||||
if (e.getValueIsAdjusting()) {
|
||||
return;
|
||||
}
|
||||
ThreadRow row = threadFilterPanel.getSelectedItem();
|
||||
myActionContext = new DebuggerThreadActionContext(current.getTrace(),
|
||||
row == null ? null : row.getThread());
|
||||
contextChanged();
|
||||
ThreadRow row = setThreadRowActionContext();
|
||||
if (row != null && traceManager != null) {
|
||||
cbCoordinateActivation.invoke(() -> traceManager.activateThread(row.getThread()));
|
||||
}
|
||||
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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.plugin.core.debug.gui.thread;
|
||||
|
||||
import docking.ActionContext;
|
||||
import ghidra.trace.model.Trace;
|
||||
|
||||
public class DebuggerTraceFileActionContext extends ActionContext {
|
||||
private final Trace trace;
|
||||
|
||||
public DebuggerTraceFileActionContext(Trace trace) {
|
||||
this.trace = trace;
|
||||
}
|
||||
|
||||
public Trace getTrace() {
|
||||
return trace;
|
||||
}
|
||||
}
|
||||
+9
-1
@@ -23,6 +23,7 @@ import ghidra.framework.client.RepositoryAdapter;
|
||||
import ghidra.framework.model.*;
|
||||
import ghidra.framework.protocol.ghidra.GhidraURL;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.util.Msg;
|
||||
|
||||
public enum ProgramURLUtils {
|
||||
;
|
||||
@@ -33,7 +34,9 @@ public enum ProgramURLUtils {
|
||||
if (projectLocator == null) {
|
||||
return null;
|
||||
}
|
||||
RepositoryAdapter repository = file.getParent().getProjectData().getRepository();
|
||||
DomainFolder parent = file.getParent();
|
||||
ProjectData projectData = parent == null ? null : parent.getProjectData();
|
||||
RepositoryAdapter repository = projectData == null ? null : projectData.getRepository();
|
||||
if (repository != null) { // There is an associated remote repo
|
||||
if (file.isVersioned()) { // The domain file exists there
|
||||
ServerInfo server = repository.getServerInfo();
|
||||
@@ -66,6 +69,11 @@ public enum ProgramURLUtils {
|
||||
}
|
||||
URL localProjURL = new URL(asString.substring(0, bangLoc));
|
||||
ProjectData projectData = project.getProjectData(localProjURL);
|
||||
if (projectData == null) {
|
||||
Msg.error(ProgramURLUtils.class, "The repository containing " + ghidraURL +
|
||||
" is not open in the Project manager.");
|
||||
return null;
|
||||
}
|
||||
return projectData.getFile(asString.substring(bangLoc + 1));
|
||||
}
|
||||
catch (MalformedURLException e) {
|
||||
|
||||
Reference in New Issue
Block a user