mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 02:39:44 +02:00
Updated GoTo service to handle concurrent usage
This commit is contained in:
parent
0f3aa2b9de
commit
6ca07aa2c3
21 changed files with 530 additions and 502 deletions
|
@ -17,12 +17,16 @@ package ghidra.app.plugin.core.debug.gui.breakpoint;
|
|||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.junit.experimental.categories.Category;
|
||||
|
||||
import generic.test.category.NightlyCategory;
|
||||
import ghidra.dbg.target.schema.SchemaContext;
|
||||
import ghidra.dbg.target.schema.TargetObjectSchema.SchemaName;
|
||||
import ghidra.dbg.target.schema.XmlSchemaContext;
|
||||
import ghidra.trace.model.Trace;
|
||||
import ghidra.util.database.UndoableTransaction;
|
||||
|
||||
@Category(NightlyCategory.class)
|
||||
public class DebuggerBreakpointsProviderObjectTest extends DebuggerBreakpointsProviderTest {
|
||||
|
||||
protected SchemaContext ctx;
|
||||
|
|
|
@ -23,11 +23,13 @@ import java.util.concurrent.TimeUnit;
|
|||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.experimental.categories.Category;
|
||||
|
||||
import com.google.common.collect.Range;
|
||||
|
||||
import docking.action.DockingActionIf;
|
||||
import generic.Unique;
|
||||
import generic.test.category.NightlyCategory;
|
||||
import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerGUITest;
|
||||
import ghidra.app.plugin.core.debug.gui.action.AutoReadMemorySpec;
|
||||
import ghidra.app.plugin.core.debug.gui.action.NoneAutoReadMemorySpec;
|
||||
|
@ -50,6 +52,7 @@ import ghidra.trace.model.TraceLocation;
|
|||
import ghidra.trace.model.memory.TraceMemoryFlag;
|
||||
import ghidra.util.database.UndoableTransaction;
|
||||
|
||||
@Category(NightlyCategory.class)
|
||||
public class DebuggerCopyActionsPluginTest extends AbstractGhidraHeadedDebuggerGUITest {
|
||||
|
||||
DebuggerCopyActionsPlugin copyActionsPlugin;
|
||||
|
@ -136,8 +139,8 @@ public class DebuggerCopyActionsPluginTest extends AbstractGhidraHeadedDebuggerG
|
|||
|
||||
try (UndoableTransaction tid = UndoableTransaction.start(program, "Add blocks", true)) {
|
||||
program.getMemory()
|
||||
.createInitializedBlock(".text", tb.addr(stSpace, 0x00400000), 0x8000,
|
||||
(byte) 0, monitor, false);
|
||||
.createInitializedBlock(".text", tb.addr(stSpace, 0x00400000), 0x8000, (byte) 0,
|
||||
monitor, false);
|
||||
program.getMemory()
|
||||
.createInitializedBlock(".text2", tb.addr(stSpace, 0x00408000), 0x8000,
|
||||
(byte) 0, monitor, false);
|
||||
|
@ -145,8 +148,8 @@ public class DebuggerCopyActionsPluginTest extends AbstractGhidraHeadedDebuggerG
|
|||
|
||||
try (UndoableTransaction tid = tb.startTransaction()) {
|
||||
DBTraceMemoryManager mm = tb.trace.getMemoryManager();
|
||||
mm.createRegion(".text", 0, tb.range(0x00400000, 0x0040ffff),
|
||||
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
||||
mm.createRegion(".text", 0, tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ,
|
||||
TraceMemoryFlag.EXECUTE);
|
||||
mm.putBytes(0, tb.addr(0x00401234), tb.buf(1, 2, 3, 4));
|
||||
|
||||
// This region should be excluded, since it cannot be mapped identically into 32-bits
|
||||
|
@ -163,9 +166,7 @@ public class DebuggerCopyActionsPluginTest extends AbstractGhidraHeadedDebuggerG
|
|||
traceManager.activateTrace(tb.trace);
|
||||
assertDisabled(copyActionsPlugin.actionCopyIntoCurrentProgram);
|
||||
|
||||
select(tb.set(
|
||||
tb.range(0x00400000, 0x0040ffff),
|
||||
tb.range(0x7fff00400000L, 0x7fff0040ffffL),
|
||||
select(tb.set(tb.range(0x00400000, 0x0040ffff), tb.range(0x7fff00400000L, 0x7fff0040ffffL),
|
||||
tb.range(0xfffff000L, 0x100000fffL)));
|
||||
|
||||
performEnabledAction(copyActionsPlugin.actionCopyIntoCurrentProgram);
|
||||
|
|
|
@ -24,13 +24,16 @@ import java.util.Map;
|
|||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.experimental.categories.Category;
|
||||
|
||||
import generic.test.category.NightlyCategory;
|
||||
import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerGUITest;
|
||||
import ghidra.app.plugin.core.interpreter.InterpreterComponentProvider;
|
||||
import ghidra.dbg.model.TestTargetInterpreter.ExecuteCall;
|
||||
import ghidra.dbg.target.TargetConsole.Channel;
|
||||
import ghidra.dbg.testutil.DebuggerModelTestUtils;
|
||||
|
||||
@Category(NightlyCategory.class)
|
||||
public class DebuggerInterpreterPluginTest extends AbstractGhidraHeadedDebuggerGUITest
|
||||
implements DebuggerModelTestUtils {
|
||||
private DebuggerInterpreterPlugin interpreterPlugin;
|
||||
|
@ -124,8 +127,7 @@ public class DebuggerInterpreterPluginTest extends AbstractGhidraHeadedDebuggerG
|
|||
InterpreterComponentProvider interpreter =
|
||||
waitForComponentProvider(InterpreterComponentProvider.class);
|
||||
|
||||
mb.testModel.session.changeAttributes(List.of(
|
||||
"Interpreter" //
|
||||
mb.testModel.session.changeAttributes(List.of("Interpreter" //
|
||||
), Map.of(), "Invalidate interpreter");
|
||||
waitForSwing();
|
||||
|
||||
|
@ -142,8 +144,7 @@ public class DebuggerInterpreterPluginTest extends AbstractGhidraHeadedDebuggerG
|
|||
waitForComponentProvider(InterpreterComponentProvider.class);
|
||||
conn.setPinned(true);
|
||||
|
||||
mb.testModel.session.changeAttributes(List.of(
|
||||
"Interpreter" //
|
||||
mb.testModel.session.changeAttributes(List.of("Interpreter" //
|
||||
), Map.of(), "Invalidate interpreter");
|
||||
waitForSwing();
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
*/
|
||||
package ghidra.app.plugin.core.debug.gui.listing;
|
||||
|
||||
import static ghidra.lifecycle.Unfinished.TODO;
|
||||
import static ghidra.lifecycle.Unfinished.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.awt.Color;
|
||||
|
@ -26,12 +26,14 @@ import java.util.Arrays;
|
|||
import java.util.Set;
|
||||
|
||||
import org.junit.*;
|
||||
import org.junit.experimental.categories.Category;
|
||||
|
||||
import com.google.common.collect.Range;
|
||||
|
||||
import docking.menu.ActionState;
|
||||
import docking.menu.MultiStateDockingAction;
|
||||
import docking.widgets.EventTrigger;
|
||||
import generic.test.category.NightlyCategory;
|
||||
import ghidra.app.plugin.core.debug.DebuggerCoordinates;
|
||||
import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerGUITest;
|
||||
import ghidra.app.plugin.core.debug.gui.DebuggerResources;
|
||||
|
@ -65,6 +67,7 @@ import ghidra.util.exception.CancelledException;
|
|||
import ghidra.util.exception.VersionException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
@Category(NightlyCategory.class)
|
||||
public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUITest {
|
||||
|
||||
protected DebuggerListingPlugin listingPlugin;
|
||||
|
@ -233,8 +236,9 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
|||
createAndOpenTrace();
|
||||
TraceThread thread1;
|
||||
TraceThread thread2;
|
||||
DebuggerListingProvider extraProvider = SwingExecutorService.INSTANCE.submit(
|
||||
() -> listingPlugin.createListingIfMissing(trackPc, true)).get();
|
||||
DebuggerListingProvider extraProvider = SwingExecutorService.INSTANCE
|
||||
.submit(() -> listingPlugin.createListingIfMissing(trackPc, true))
|
||||
.get();
|
||||
try (UndoableTransaction tid = tb.startTransaction()) {
|
||||
DBTraceMemoryManager memory = tb.trace.getMemoryManager();
|
||||
memory.addRegion("exe:.text", Range.atLeast(0L), tb.range(0x00400000, 0x0040ffff),
|
||||
|
@ -301,8 +305,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testFollowsCurrentTraceOnTraceChangeWithoutRegisterTracking()
|
||||
throws Exception {
|
||||
public void testFollowsCurrentTraceOnTraceChangeWithoutRegisterTracking() throws Exception {
|
||||
listingProvider.setTrackingSpec(trackNone);
|
||||
try ( //
|
||||
ToyDBTraceBuilder b1 =
|
||||
|
@ -358,8 +361,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testFollowsCurrentThreadOnThreadChangeWithoutRegisterTracking()
|
||||
throws Exception {
|
||||
public void testFollowsCurrentThreadOnThreadChangeWithoutRegisterTracking() throws Exception {
|
||||
listingProvider.setTrackingSpec(trackNone);
|
||||
try ( //
|
||||
ToyDBTraceBuilder b1 =
|
||||
|
@ -616,8 +618,8 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
|||
|
||||
// While we're here, ensure static view didn't track anywhere
|
||||
assertEquals(cur, codeViewer.getCurrentLocation().getAddress());
|
||||
assertListingBackgroundAt(Color.WHITE,
|
||||
codeViewer.getListingPanel(), ss.getAddress(0x00601234), 0);
|
||||
assertListingBackgroundAt(Color.WHITE, codeViewer.getListingPanel(),
|
||||
ss.getAddress(0x00601234), 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -703,8 +705,8 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
|||
|
||||
assertListingBackgroundAt(DebuggerResources.DEFAULT_COLOR_BACKGROUND_STALE,
|
||||
listingProvider.getListingPanel(), tb.addr(0x00401233), 0);
|
||||
assertListingBackgroundAt(Color.WHITE,
|
||||
listingProvider.getListingPanel(), tb.addr(0x00401234), 0);
|
||||
assertListingBackgroundAt(Color.WHITE, listingProvider.getListingPanel(),
|
||||
tb.addr(0x00401234), 0);
|
||||
assertListingBackgroundAt(DebuggerResources.DEFAULT_COLOR_BACKGROUND_ERROR,
|
||||
listingProvider.getListingPanel(), tb.addr(0x00401235), 0);
|
||||
}
|
||||
|
@ -717,8 +719,8 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
|||
assertEquals(traceManager.getCurrentView(), listingProvider.getProgram());
|
||||
assertEquals("(nowhere)", listingProvider.locationLabel.getText());
|
||||
|
||||
DebuggerListingProvider extraProvider = runSwing(
|
||||
() -> listingPlugin.createListingIfMissing(trackNone, false));
|
||||
DebuggerListingProvider extraProvider =
|
||||
runSwing(() -> listingPlugin.createListingIfMissing(trackNone, false));
|
||||
waitForSwing();
|
||||
assertEquals(traceManager.getCurrentView(), extraProvider.getProgram());
|
||||
assertEquals("(nowhere)", extraProvider.locationLabel.getText());
|
||||
|
@ -765,18 +767,18 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
|||
|
||||
assertTrue(listingProvider.actionGoTo.isEnabled());
|
||||
performAction(listingProvider.actionGoTo, false);
|
||||
DebuggerGoToDialog dialog = waitForDialogComponent(DebuggerGoToDialog.class);
|
||||
DebuggerGoToDialog dialog1 = waitForDialogComponent(DebuggerGoToDialog.class);
|
||||
|
||||
dialog.setExpression("r0");
|
||||
dialog.okCallback();
|
||||
dialog1.setExpression("r0");
|
||||
runSwing(() -> dialog1.okCallback());
|
||||
|
||||
waitForPass(
|
||||
() -> assertEquals(tb.addr(0x00401234), listingProvider.getLocation().getAddress()));
|
||||
|
||||
performAction(listingProvider.actionGoTo, false);
|
||||
dialog = waitForDialogComponent(DebuggerGoToDialog.class);
|
||||
dialog.setExpression("*:4 r0");
|
||||
dialog.okCallback();
|
||||
DebuggerGoToDialog dialog2 = waitForDialogComponent(DebuggerGoToDialog.class);
|
||||
dialog2.setExpression("*:4 r0");
|
||||
runSwing(() -> dialog2.okCallback());
|
||||
|
||||
waitForPass(
|
||||
() -> assertEquals(tb.addr(0x00404321), listingProvider.getLocation().getAddress()));
|
||||
|
@ -844,8 +846,8 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
|||
AddressSpace ss = program.getAddressFactory().getDefaultAddressSpace();
|
||||
try (UndoableTransaction tid = UndoableTransaction.start(program, "Add block", true)) {
|
||||
program.getMemory()
|
||||
.createInitializedBlock(
|
||||
".text", ss.getAddress(0x00600000), 0x10000, (byte) 0, monitor, false);
|
||||
.createInitializedBlock(".text", ss.getAddress(0x00600000), 0x10000, (byte) 0,
|
||||
monitor, false);
|
||||
}
|
||||
try (UndoableTransaction tid = tb.startTransaction()) {
|
||||
DBTraceMemoryManager memory = tb.trace.getMemoryManager();
|
||||
|
@ -905,8 +907,8 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
|||
traceManager.activateThread(thread1);
|
||||
|
||||
// NOTE: Action does not exist for main dynamic listing
|
||||
DebuggerListingProvider extraProvider = runSwing(
|
||||
() -> listingPlugin.createListingIfMissing(trackNone, true));
|
||||
DebuggerListingProvider extraProvider =
|
||||
runSwing(() -> listingPlugin.createListingIfMissing(trackNone, true));
|
||||
waitForSwing();
|
||||
assertTrue(extraProvider.actionFollowsCurrentThread.isEnabled());
|
||||
assertTrue(extraProvider.actionFollowsCurrentThread.isSelected());
|
||||
|
@ -1032,8 +1034,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
|||
assertEquals(readVisROOnce, listingProvider.getAutoReadMemorySpec());
|
||||
assertEquals(readVisROOnce, listingProvider.actionAutoReadMemory.getCurrentUserData());
|
||||
|
||||
listingProvider.actionAutoReadMemory
|
||||
.setCurrentActionStateByUserData(readNone);
|
||||
listingProvider.actionAutoReadMemory.setCurrentActionStateByUserData(readNone);
|
||||
waitForSwing();
|
||||
assertEquals(readNone, listingProvider.getAutoReadMemorySpec());
|
||||
assertEquals(readNone, listingProvider.actionAutoReadMemory.getCurrentUserData());
|
||||
|
@ -1061,8 +1062,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
|||
Set.of(TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE));
|
||||
|
||||
TraceModule bin = tb.trace.getModuleManager()
|
||||
.addLoadedModule("/bin/bash", "/bin/bash",
|
||||
tb.range(0x00400000, 0x0041ffff), 0);
|
||||
.addLoadedModule("/bin/bash", "/bin/bash", tb.range(0x00400000, 0x0041ffff), 0);
|
||||
bin.addSection("bash[.text]", tb.range(0x00400000, 0x0040ffff));
|
||||
|
||||
traceManager.activateTrace(tb.trace);
|
||||
|
@ -1092,8 +1092,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
|||
Set.of(TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE));
|
||||
|
||||
tb.trace.getModuleManager()
|
||||
.addLoadedModule("/bin/bash", "/bin/bash",
|
||||
tb.range(0x00400000, 0x0041ffff), 0);
|
||||
.addLoadedModule("/bin/bash", "/bin/bash", tb.range(0x00400000, 0x0041ffff), 0);
|
||||
|
||||
traceManager.activateTrace(tb.trace);
|
||||
}
|
||||
|
@ -1128,8 +1127,8 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
|||
TraceModule modExe;
|
||||
try (UndoableTransaction tid = tb.startTransaction()) {
|
||||
modExe = tb.trace.getModuleManager()
|
||||
.addModule("modExe", "modExe",
|
||||
tb.range(0x55550000, 0x555501ff), Range.atLeast(0L));
|
||||
.addModule("modExe", "modExe", tb.range(0x55550000, 0x555501ff),
|
||||
Range.atLeast(0L));
|
||||
}
|
||||
waitForDomainObject(tb.trace);
|
||||
waitForPass(() -> assertEquals("modExe", listingProvider.locationLabel.getText()));
|
||||
|
@ -1157,19 +1156,17 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
|||
.createRegion(".text", 0, tb.range(0x00400000, 0x0040ffff),
|
||||
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
||||
thread1 = tb.getOrAddThread("Thread1", 0);
|
||||
tb.exec(0, 0, thread1, java.util.List.of(
|
||||
"RIP = 0x00400000;"));
|
||||
tb.exec(0, 0, thread1, java.util.List.of("RIP = 0x00400000;"));
|
||||
}
|
||||
|
||||
TraceThread thread2;
|
||||
try (UndoableTransaction tid = tb2.startTransaction()) {
|
||||
tb2.trace.getTimeManager().createSnapshot("First");
|
||||
tb2.trace.getMemoryManager()
|
||||
.createRegion(".text", 0, tb2.range(0x200, 0x3ff),
|
||||
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
||||
.createRegion(".text", 0, tb2.range(0x200, 0x3ff), TraceMemoryFlag.READ,
|
||||
TraceMemoryFlag.EXECUTE);
|
||||
thread2 = tb2.getOrAddThread("Thread2", 0);
|
||||
tb2.exec(0, 0, thread2, java.util.List.of(
|
||||
"PC = 0x100;"));
|
||||
tb2.exec(0, 0, thread2, java.util.List.of("PC = 0x100;"));
|
||||
}
|
||||
|
||||
traceManager.openTrace(tb.trace);
|
||||
|
|
|
@ -17,11 +17,15 @@ package ghidra.app.plugin.core.debug.gui.memory;
|
|||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.junit.experimental.categories.Category;
|
||||
|
||||
import generic.test.category.NightlyCategory;
|
||||
import ghidra.dbg.target.schema.SchemaContext;
|
||||
import ghidra.dbg.target.schema.TargetObjectSchema.SchemaName;
|
||||
import ghidra.dbg.target.schema.XmlSchemaContext;
|
||||
import ghidra.util.database.UndoableTransaction;
|
||||
|
||||
@Category(NightlyCategory.class)
|
||||
public class DebuggerRegionsProviderObjectTest extends DebuggerRegionsProviderTest {
|
||||
|
||||
protected SchemaContext ctx;
|
||||
|
|
|
@ -21,10 +21,12 @@ import java.util.*;
|
|||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.experimental.categories.Category;
|
||||
|
||||
import com.google.common.collect.Range;
|
||||
|
||||
import generic.Unique;
|
||||
import generic.test.category.NightlyCategory;
|
||||
import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerGUITest;
|
||||
import ghidra.app.plugin.core.debug.gui.DebuggerBlockChooserDialog;
|
||||
import ghidra.app.plugin.core.debug.gui.DebuggerBlockChooserDialog.MemoryBlockRow;
|
||||
|
@ -41,6 +43,7 @@ import ghidra.trace.model.memory.*;
|
|||
import ghidra.trace.model.modules.TraceStaticMapping;
|
||||
import ghidra.util.database.UndoableTransaction;
|
||||
|
||||
@Category(NightlyCategory.class)
|
||||
public class DebuggerRegionsProviderTest extends AbstractGhidraHeadedDebuggerGUITest {
|
||||
|
||||
DebuggerRegionsProvider provider;
|
||||
|
@ -105,8 +108,7 @@ public class DebuggerRegionsProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
|||
try (UndoableTransaction tid = tb.startTransaction()) {
|
||||
TraceMemoryManager mm = tb.trace.getMemoryManager();
|
||||
region = mm.addRegion("Memory[bin:.text]", Range.atLeast(0L),
|
||||
tb.range(0x00400000, 0x0040ffff),
|
||||
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
||||
tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
||||
}
|
||||
|
||||
traceManager.openTrace(tb.trace);
|
||||
|
@ -134,8 +136,7 @@ public class DebuggerRegionsProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
|||
try (UndoableTransaction tid = tb.startTransaction()) {
|
||||
TraceMemoryManager mm = tb.trace.getMemoryManager();
|
||||
region = mm.addRegion("Memory[bin:.text]", Range.atLeast(0L),
|
||||
tb.range(0x00400000, 0x0040ffff),
|
||||
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
||||
tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
||||
}
|
||||
|
||||
waitForSwing();
|
||||
|
@ -152,8 +153,7 @@ public class DebuggerRegionsProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
|||
try (UndoableTransaction tid = tb.startTransaction()) {
|
||||
TraceMemoryManager mm = tb.trace.getMemoryManager();
|
||||
region = mm.addRegion("Memory[bin:.text]", Range.atLeast(0L),
|
||||
tb.range(0x00400000, 0x0040ffff),
|
||||
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
||||
tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
||||
}
|
||||
|
||||
traceManager.openTrace(tb.trace);
|
||||
|
@ -222,8 +222,7 @@ public class DebuggerRegionsProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
|||
try (UndoableTransaction tid = tb.startTransaction()) {
|
||||
TraceMemoryManager mm = tb.trace.getMemoryManager();
|
||||
region = mm.addRegion("Memory[bin:.text]", Range.atLeast(0L),
|
||||
tb.range(0x00400000, 0x0040ffff),
|
||||
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
||||
tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
||||
}
|
||||
|
||||
traceManager.openTrace(tb.trace);
|
||||
|
@ -338,8 +337,7 @@ public class DebuggerRegionsProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
|||
try (UndoableTransaction tid = tb.startTransaction()) {
|
||||
TraceMemoryManager mm = tb.trace.getMemoryManager();
|
||||
region = mm.addRegion("Memory[bin:.text]", Range.atLeast(0L),
|
||||
tb.range(0x00400000, 0x0040ffff),
|
||||
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
||||
tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
||||
}
|
||||
|
||||
traceManager.openTrace(tb.trace);
|
||||
|
@ -371,8 +369,7 @@ public class DebuggerRegionsProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
|||
try (UndoableTransaction tid = tb.startTransaction()) {
|
||||
TraceMemoryManager mm = tb.trace.getMemoryManager();
|
||||
region = mm.addRegion("Memory[bin:.text]", Range.atLeast(0L),
|
||||
tb.range(0x00400000, 0x0040ffff),
|
||||
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
||||
tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
||||
}
|
||||
|
||||
traceManager.openTrace(tb.trace);
|
||||
|
|
|
@ -17,12 +17,16 @@ package ghidra.app.plugin.core.debug.gui.modules;
|
|||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.junit.experimental.categories.Category;
|
||||
|
||||
import generic.test.category.NightlyCategory;
|
||||
import ghidra.dbg.target.schema.SchemaContext;
|
||||
import ghidra.dbg.target.schema.TargetObjectSchema.SchemaName;
|
||||
import ghidra.trace.model.Trace;
|
||||
import ghidra.dbg.target.schema.XmlSchemaContext;
|
||||
import ghidra.trace.model.Trace;
|
||||
import ghidra.util.database.UndoableTransaction;
|
||||
|
||||
@Category(NightlyCategory.class)
|
||||
public class DebuggerModulesProviderObjectTest extends DebuggerModulesProviderTest {
|
||||
|
||||
protected SchemaContext ctx;
|
||||
|
|
|
@ -23,10 +23,12 @@ import java.util.*;
|
|||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.experimental.categories.Category;
|
||||
|
||||
import com.google.common.collect.Range;
|
||||
|
||||
import generic.Unique;
|
||||
import generic.test.category.NightlyCategory;
|
||||
import ghidra.app.plugin.core.codebrowser.CodeBrowserPlugin;
|
||||
import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerGUITest;
|
||||
import ghidra.app.plugin.core.debug.gui.listing.DebuggerListingPlugin;
|
||||
|
@ -41,6 +43,7 @@ import ghidra.trace.model.modules.TraceStaticMappingManager;
|
|||
import ghidra.util.database.UndoableTransaction;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
@Category(NightlyCategory.class)
|
||||
public class DebuggerStaticMappingProviderTest extends AbstractGhidraHeadedDebuggerGUITest {
|
||||
protected DebuggerStaticMappingPlugin mappingsPlugin;
|
||||
protected DebuggerStaticMappingProvider mappingsProvider;
|
||||
|
|
|
@ -17,12 +17,16 @@ package ghidra.app.plugin.core.debug.gui.thread;
|
|||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.junit.experimental.categories.Category;
|
||||
|
||||
import generic.test.category.NightlyCategory;
|
||||
import ghidra.dbg.target.schema.SchemaContext;
|
||||
import ghidra.dbg.target.schema.TargetObjectSchema.SchemaName;
|
||||
import ghidra.dbg.target.schema.XmlSchemaContext;
|
||||
import ghidra.trace.model.Trace;
|
||||
import ghidra.util.database.UndoableTransaction;
|
||||
|
||||
@Category(NightlyCategory.class)
|
||||
public class DebuggerThreadsProviderObjectTest extends DebuggerThreadsProviderTest {
|
||||
|
||||
protected SchemaContext ctx;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -44,7 +44,7 @@ import util.CollectionUtils;
|
|||
/**
|
||||
* Opens a table chooser allowing the user to select functions from the current
|
||||
* program. The table displayed uses a {@link FunctionTableModel}.
|
||||
*
|
||||
*
|
||||
* @see FunctionComparisonService
|
||||
*/
|
||||
public class OpenFunctionTableAction extends DockingAction {
|
||||
|
@ -64,7 +64,7 @@ public class OpenFunctionTableAction extends DockingAction {
|
|||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
*
|
||||
* @param tool the plugin tool
|
||||
* @param provider the function comparison provider
|
||||
*/
|
||||
|
@ -76,15 +76,14 @@ public class OpenFunctionTableAction extends DockingAction {
|
|||
this.comparisonService = tool.getService(FunctionComparisonService.class);
|
||||
|
||||
setDescription("Add functions to comparison");
|
||||
setPopupMenuData(new MenuData(new String[] { "Add functions" },
|
||||
ADD_TO_COMPARISON_ICON, ADD_COMPARISON_GROUP));
|
||||
setPopupMenuData(new MenuData(new String[] { "Add functions" }, ADD_TO_COMPARISON_ICON,
|
||||
ADD_COMPARISON_GROUP));
|
||||
|
||||
ToolBarData newToolBarData =
|
||||
new ToolBarData(ADD_TO_COMPARISON_ICON, ADD_COMPARISON_GROUP);
|
||||
ToolBarData newToolBarData = new ToolBarData(ADD_TO_COMPARISON_ICON, ADD_COMPARISON_GROUP);
|
||||
setToolBarData(newToolBarData);
|
||||
|
||||
HelpLocation helpLocation = new HelpLocation(MultiFunctionComparisonPanel.HELP_TOPIC,
|
||||
"Add_To_Comparison");
|
||||
HelpLocation helpLocation =
|
||||
new HelpLocation(MultiFunctionComparisonPanel.HELP_TOPIC, "Add_To_Comparison");
|
||||
setHelpLocation(helpLocation);
|
||||
|
||||
KeyBindingData data = new KeyBindingData('A', InputEvent.SHIFT_DOWN_MASK);
|
||||
|
@ -98,19 +97,14 @@ public class OpenFunctionTableAction extends DockingAction {
|
|||
|
||||
@Override
|
||||
public void actionPerformed(ActionContext context) {
|
||||
if (!(context.getComponentProvider() instanceof FunctionComparisonProvider)) {
|
||||
return;
|
||||
}
|
||||
|
||||
FunctionComparisonProvider provider =
|
||||
(FunctionComparisonProvider) context.getComponentProvider();
|
||||
Program currentProgram = programManagerService.getCurrentProgram();
|
||||
FunctionTableModel model = new FunctionTableModel(tool, currentProgram);
|
||||
model.reload(programManagerService.getCurrentProgram());
|
||||
|
||||
TableSelectionDialog<FunctionRowObject> diag =
|
||||
new TableSelectionDialog<>("Select Functions: " + currentProgram.getName(),
|
||||
model, true);
|
||||
TableSelectionDialog<FunctionRowObject> diag = new TableSelectionDialog<>(
|
||||
"Select Functions: " + currentProgram.getName(), model, true);
|
||||
tool.showDialog(diag);
|
||||
List<FunctionRowObject> rows = diag.getSelectionItems();
|
||||
if (CollectionUtils.isBlank(rows)) {
|
||||
|
|
|
@ -40,6 +40,7 @@ import ghidra.program.model.mem.Memory;
|
|||
import ghidra.program.model.symbol.*;
|
||||
import ghidra.program.util.*;
|
||||
import ghidra.util.HelpLocation;
|
||||
import ghidra.util.Swing;
|
||||
import ghidra.util.table.AddressArrayTableModel;
|
||||
|
||||
public class GoToHelper {
|
||||
|
@ -80,6 +81,10 @@ public class GoToHelper {
|
|||
}
|
||||
|
||||
public boolean goTo(final Navigatable navigatable, ProgramLocation loc, Program program) {
|
||||
return Swing.runNow(() -> doGoTo(navigatable, loc, program));
|
||||
}
|
||||
|
||||
private boolean doGoTo(final Navigatable navigatable, ProgramLocation loc, Program program) {
|
||||
if (loc == null || loc.getAddress() == null) {
|
||||
return false;
|
||||
}
|
||||
|
@ -116,17 +121,6 @@ public class GoToHelper {
|
|||
return false;
|
||||
}
|
||||
|
||||
// If we want the goto to request focus then we will need to add a new parameter - you don't always
|
||||
// want to request focus.
|
||||
// // sometimes this gets call directly after creating a new provider window. Need to
|
||||
// // request focus in an invokeLater to give WindowManager a chance to create the component
|
||||
// // hierarchy tree.
|
||||
// SwingUtilities.invokeLater(new Runnable() {
|
||||
// public void run() {
|
||||
// navigatable.requestFocus();
|
||||
// }
|
||||
// });
|
||||
|
||||
saveLocation(navigatable);
|
||||
|
||||
return true;
|
||||
|
@ -148,6 +142,7 @@ public class GoToHelper {
|
|||
if (loc != null) {
|
||||
return loc;
|
||||
}
|
||||
|
||||
if (gotoAddress.isStackAddress() || gotoAddress.isRegisterAddress()) {
|
||||
// Convert stack/register address into variable address
|
||||
Function func = program.getFunctionManager().getFunctionContaining(currentAddress);
|
||||
|
@ -347,7 +342,7 @@ public class GoToHelper {
|
|||
String extProgName = externalLocation.getLibraryName();
|
||||
if (Library.UNKNOWN.equals(extProgName)) {
|
||||
tool.setStatusInfo(" External location refers to " + Library.UNKNOWN +
|
||||
" library. Unable to " + "perform navigation.", true);
|
||||
" library. Unable to perform navigation.", true);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -391,6 +386,7 @@ public class GoToHelper {
|
|||
if (nameStack == null) {
|
||||
return null; // name is not valid for external program
|
||||
}
|
||||
|
||||
StringBuilder buf = new StringBuilder();
|
||||
while (!nameStack.isEmpty()) {
|
||||
buf.append(nameStack.pop());
|
||||
|
@ -439,9 +435,9 @@ public class GoToHelper {
|
|||
if (result == OptionDialog.CANCEL_OPTION) {
|
||||
return;
|
||||
}
|
||||
final DataTreeDialog dialog = new DataTreeDialog(null,
|
||||
"Choose External Program (" + extProgName + ")", DataTreeDialog.OPEN);
|
||||
|
||||
DataTreeDialog dialog = new DataTreeDialog(null,
|
||||
"Choose External Program (" + extProgName + ")", DataTreeDialog.OPEN);
|
||||
dialog.setSearchText(extProgName);
|
||||
dialog.setHelpLocation(new HelpLocation("ReferencesPlugin", "ChooseExternalProgram"));
|
||||
tool.showDialog(dialog);
|
||||
|
|
|
@ -17,7 +17,12 @@ package ghidra.app.plugin.core.progmgr;
|
|||
|
||||
import java.net.URL;
|
||||
import java.rmi.NoSuchObjectException;
|
||||
import java.util.*;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.jdom.Element;
|
||||
|
||||
|
@ -32,30 +37,36 @@ import ghidra.framework.plugintool.util.TransientToolState;
|
|||
import ghidra.framework.protocol.ghidra.GhidraURL;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.SystemUtilities;
|
||||
import ghidra.util.*;
|
||||
import ghidra.util.task.TaskLauncher;
|
||||
|
||||
class MultiProgramManager implements DomainObjectListener, TransactionListener {
|
||||
|
||||
private static int nextProgramInfoInstance = 0;
|
||||
// arbitrary counter for given ProgramInfo objects and ID to use for sorting
|
||||
private static final AtomicInteger nextAvailableId = new AtomicInteger();
|
||||
|
||||
private ProgramManagerPlugin plugin;
|
||||
private PluginTool tool;
|
||||
private ArrayList<ProgramInfo> openProgramList;
|
||||
private HashMap<Program, ProgramInfo> programMap;
|
||||
private ProgramInfo currentInfo;
|
||||
private TransactionMonitor txMonitor;
|
||||
private MyFolderListener folderListener;
|
||||
private Runnable programChangedRunnable;
|
||||
|
||||
private Runnable programChangedRunnable;
|
||||
private boolean hasUnsavedPrograms;
|
||||
|
||||
// These data structures are accessed from multiple threads. Rather than synchronizing all
|
||||
// accesses, we have chosen to be weakly consistent. We assume that any out-of-date checks
|
||||
// for open program state will be self-correcting. For example, if a client checks to see if
|
||||
// a program is open before opening it, then a repeated call to open the program will not
|
||||
// result in a second copy of that program being opened. This is safe because program opens
|
||||
// and closes are all done from the Swing thread.
|
||||
private List<ProgramInfo> openPrograms = new CopyOnWriteArrayList<>();
|
||||
private ConcurrentHashMap<Program, ProgramInfo> programMap = new ConcurrentHashMap<>();
|
||||
|
||||
MultiProgramManager(ProgramManagerPlugin programManagerPlugin) {
|
||||
this.plugin = programManagerPlugin;
|
||||
this.tool = programManagerPlugin.getTool();
|
||||
openProgramList = new ArrayList<>();
|
||||
programMap = new HashMap<>();
|
||||
|
||||
txMonitor = new TransactionMonitor();
|
||||
txMonitor.setName("Transaction Open (Program being modified)");
|
||||
tool.addStatusComponent(txMonitor, true, true);
|
||||
|
@ -72,13 +83,13 @@ class MultiProgramManager implements DomainObjectListener, TransactionListener {
|
|||
}
|
||||
|
||||
void addProgram(Program p, URL ghidraURL, int state) {
|
||||
ProgramInfo oldInfo = programMap.get(p);
|
||||
ProgramInfo oldInfo = getInfo(p);
|
||||
if (oldInfo == null) {
|
||||
p.addConsumer(tool);
|
||||
ProgramInfo info = new ProgramInfo(p, state != ProgramManager.OPEN_HIDDEN);
|
||||
info.ghidraURL = ghidraURL;
|
||||
openProgramList.add(info);
|
||||
Collections.sort(openProgramList);
|
||||
openPrograms.add(info);
|
||||
openPrograms.sort(Comparator.naturalOrder());
|
||||
programMap.put(p, info);
|
||||
|
||||
fireOpenEvents(p);
|
||||
|
@ -100,16 +111,15 @@ class MultiProgramManager implements DomainObjectListener, TransactionListener {
|
|||
void dispose() {
|
||||
tool.getProject().getProjectData().removeDomainFolderChangeListener(folderListener);
|
||||
fireActivatedEvent(null);
|
||||
Iterator<Program> it = programMap.keySet().iterator();
|
||||
while (it.hasNext()) {
|
||||
Program p = it.next();
|
||||
|
||||
for (Program p : programMap.keySet()) {
|
||||
p.removeListener(this);
|
||||
p.removeTransactionListener(this);
|
||||
fireCloseEvents(p);
|
||||
p.release(tool);
|
||||
}
|
||||
programMap.clear();
|
||||
openProgramList.clear();
|
||||
openPrograms.clear();
|
||||
tool.setSubTitle("");
|
||||
tool.removeStatusComponent(txMonitor);
|
||||
tool = null;
|
||||
|
@ -117,38 +127,38 @@ class MultiProgramManager implements DomainObjectListener, TransactionListener {
|
|||
}
|
||||
|
||||
void removeProgram(Program p) {
|
||||
ProgramInfo info = programMap.get(p);
|
||||
if (info != null) {
|
||||
if (info.owner != null) {
|
||||
// persist program
|
||||
info.setVisible(false);
|
||||
if (info == currentInfo) {
|
||||
ProgramInfo newCurrent = findNextCurrent();
|
||||
setCurrentProgram(newCurrent);
|
||||
}
|
||||
ProgramInfo info = getInfo(p);
|
||||
if (info == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (info.owner != null) {
|
||||
// persist program
|
||||
info.setVisible(false);
|
||||
if (info == currentInfo) {
|
||||
ProgramInfo newCurrent = findNextCurrent();
|
||||
setCurrentProgram(newCurrent);
|
||||
}
|
||||
else {
|
||||
p.removeTransactionListener(this);
|
||||
programMap.remove(p);
|
||||
p.removeListener(this);
|
||||
openProgramList.remove(info);
|
||||
if (info == currentInfo) {
|
||||
ProgramInfo newCurrent = findNextCurrent();
|
||||
setCurrentProgram(newCurrent);
|
||||
}
|
||||
fireCloseEvents(p);
|
||||
p.release(tool);
|
||||
if (openProgramList.isEmpty()) {
|
||||
plugin.getTool().clearLastEvents();
|
||||
}
|
||||
}
|
||||
else {
|
||||
p.removeTransactionListener(this);
|
||||
programMap.remove(p);
|
||||
p.removeListener(this);
|
||||
openPrograms.remove(info);
|
||||
if (info == currentInfo) {
|
||||
ProgramInfo newCurrent = findNextCurrent();
|
||||
setCurrentProgram(newCurrent);
|
||||
}
|
||||
fireCloseEvents(p);
|
||||
p.release(tool);
|
||||
if (openPrograms.isEmpty()) {
|
||||
plugin.getTool().clearLastEvents();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ProgramInfo findNextCurrent() {
|
||||
Iterator<ProgramInfo> iter = openProgramList.iterator();
|
||||
while (iter.hasNext()) {
|
||||
ProgramInfo pi = iter.next();
|
||||
for (ProgramInfo pi : openPrograms) {
|
||||
if (pi.visible) {
|
||||
return pi;
|
||||
}
|
||||
|
@ -158,23 +168,17 @@ class MultiProgramManager implements DomainObjectListener, TransactionListener {
|
|||
|
||||
Program[] getOtherPrograms() {
|
||||
Program currentProgram = getCurrentProgram();
|
||||
ArrayList<Program> list = new ArrayList<>();
|
||||
int size = openProgramList.size();
|
||||
for (int index = 0; index < size; index++) {
|
||||
Program program = openProgramList.get(index).program;
|
||||
if (currentProgram != program) {
|
||||
list.add(program);
|
||||
}
|
||||
}
|
||||
List<Program> list = openPrograms.stream()
|
||||
.map(info -> info.program)
|
||||
.filter(program -> program != currentProgram)
|
||||
.collect(Collectors.toList());
|
||||
return list.toArray(new Program[list.size()]);
|
||||
}
|
||||
|
||||
Program[] getAllPrograms() {
|
||||
Program[] programs = new Program[openProgramList.size()];
|
||||
for (int i = 0; i < programs.length; i++) {
|
||||
programs[i] = (openProgramList.get(i)).program;
|
||||
}
|
||||
return programs;
|
||||
List<Program> list =
|
||||
openPrograms.stream().map(info -> info.program).collect(Collectors.toList());
|
||||
return list.toArray(Program[]::new);
|
||||
}
|
||||
|
||||
Program getCurrentProgram() {
|
||||
|
@ -191,16 +195,18 @@ class MultiProgramManager implements DomainObjectListener, TransactionListener {
|
|||
}
|
||||
}
|
||||
|
||||
ProgramInfo info = programMap.get(p);
|
||||
if (p == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
ProgramInfo info = getInfo(p);
|
||||
if (info != null) {
|
||||
setCurrentProgram(info);
|
||||
}
|
||||
}
|
||||
|
||||
Program getProgram(Address addr) {
|
||||
Iterator<ProgramInfo> it = openProgramList.iterator();
|
||||
while (it.hasNext()) {
|
||||
ProgramInfo pi = it.next();
|
||||
for (ProgramInfo pi : openPrograms) {
|
||||
if (pi.program.getMemory().contains(addr)) {
|
||||
return pi.program;
|
||||
}
|
||||
|
@ -257,26 +263,17 @@ class MultiProgramManager implements DomainObjectListener, TransactionListener {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param program
|
||||
*/
|
||||
private void fireOpenEvents(Program program) {
|
||||
plugin.firePluginEvent(new ProgramOpenedPluginEvent("", program));
|
||||
plugin.firePluginEvent(new OpenProgramPluginEvent("", program));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param program
|
||||
*/
|
||||
private void fireCloseEvents(Program program) {
|
||||
plugin.firePluginEvent(new ProgramClosedPluginEvent("", program));
|
||||
plugin.firePluginEvent(new CloseProgramPluginEvent("", program, true));
|
||||
// tool.contextChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param p
|
||||
*/
|
||||
private void fireActivatedEvent(Program newProgram) {
|
||||
plugin.firePluginEvent(new ProgramActivatedPluginEvent("", newProgram));
|
||||
}
|
||||
|
@ -285,14 +282,12 @@ class MultiProgramManager implements DomainObjectListener, TransactionListener {
|
|||
plugin.firePluginEvent(new ProgramVisibilityChangePluginEvent("", program, isVisible));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.framework.model.DomainObjectListener#domainObjectChanged(ghidra.framework.model.DomainObjectChangedEvent)
|
||||
*/
|
||||
@Override
|
||||
public void domainObjectChanged(DomainObjectChangedEvent ev) {
|
||||
if (!(ev.getSource() instanceof Program)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Program program = (Program) ev.getSource();
|
||||
if (ev.containsEvent(DomainObject.DO_DOMAIN_FILE_CHANGED) ||
|
||||
ev.containsEvent(DomainObject.DO_OBJECT_ERROR)) {
|
||||
|
@ -320,7 +315,6 @@ class MultiProgramManager implements DomainObjectListener, TransactionListener {
|
|||
"\nby the local filesystem or server.";
|
||||
}
|
||||
|
||||
//abort();
|
||||
Msg.showError(this, tool.getToolFrame(), "Severe Error Condition", msg);
|
||||
removeProgram(program);
|
||||
return;
|
||||
|
@ -330,64 +324,24 @@ class MultiProgramManager implements DomainObjectListener, TransactionListener {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return openProgramList.isEmpty();
|
||||
return openPrograms.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param program
|
||||
* @return
|
||||
*/
|
||||
public boolean contains(Program program) {
|
||||
return programMap.containsKey(program);
|
||||
}
|
||||
|
||||
private class MyFolderListener extends DomainFolderListenerAdapter {
|
||||
|
||||
@Override
|
||||
public void domainFileObjectReplaced(DomainFile file, DomainObject oldObject) {
|
||||
|
||||
/**
|
||||
* Special handling for when a file is checked-in. The existing program has be moved
|
||||
* to a proxy file (no longer in the project) so that it can be closed and the program
|
||||
* re-opened with the new version after the check-in merge.
|
||||
*/
|
||||
|
||||
if (!programMap.containsKey(oldObject)) {
|
||||
return;
|
||||
}
|
||||
Element dataState = null;
|
||||
if (currentInfo != null && currentInfo.program == oldObject) {
|
||||
// save dataState as though the project state was saved and re-opened to simulate
|
||||
// recovering after closing the program during this swap
|
||||
dataState = tool.saveDataStateToXml(true);
|
||||
}
|
||||
OpenProgramTask openTask = new OpenProgramTask(file, -1, this);
|
||||
openTask.setSilent();
|
||||
// OpenDomainFileTask openTask = new OpenDomainFileTask(file, -1, tool,
|
||||
// plugin, true, dataState != null ? ProgramManager.OPEN_CURRENT : ProgramManager.OPEN_VISIBLE);
|
||||
new TaskLauncher(openTask, tool.getToolFrame());
|
||||
Program openProgram = openTask.getOpenProgram();
|
||||
plugin.openProgram(openProgram,
|
||||
dataState != null ? ProgramManager.OPEN_CURRENT : ProgramManager.OPEN_VISIBLE);
|
||||
openProgram.release(this);
|
||||
removeProgram((Program) oldObject);
|
||||
if (dataState != null) {
|
||||
tool.restoreDataStateFromXml(dataState);
|
||||
}
|
||||
public boolean contains(Program p) {
|
||||
if (p == null) {
|
||||
return false;
|
||||
}
|
||||
return programMap.containsKey(p);
|
||||
}
|
||||
|
||||
boolean isVisible(Program program) {
|
||||
ProgramInfo info = programMap.get(program);
|
||||
boolean isVisible(Program p) {
|
||||
ProgramInfo info = getInfo(p);
|
||||
return info != null ? info.visible : false;
|
||||
}
|
||||
|
||||
void releaseProgram(Program program, Object owner) {
|
||||
ProgramInfo info = programMap.get(program);
|
||||
ProgramInfo info = getInfo(program);
|
||||
if (info != null && info.owner == owner) {
|
||||
info.owner = null;
|
||||
if (!info.visible) {
|
||||
|
@ -403,7 +357,7 @@ class MultiProgramManager implements DomainObjectListener, TransactionListener {
|
|||
}
|
||||
|
||||
boolean setPersistentOwner(Program program, Object owner) {
|
||||
ProgramInfo info = programMap.get(program);
|
||||
ProgramInfo info = getInfo(program);
|
||||
if (info != null && info.owner == null) {
|
||||
info.owner = owner;
|
||||
return true;
|
||||
|
@ -411,37 +365,81 @@ class MultiProgramManager implements DomainObjectListener, TransactionListener {
|
|||
return false;
|
||||
}
|
||||
|
||||
public boolean isPersistent(Program program) {
|
||||
ProgramInfo info = programMap.get(program);
|
||||
boolean isPersistent(Program p) {
|
||||
ProgramInfo info = getInfo(p);
|
||||
return (info != null && info.owner != null);
|
||||
}
|
||||
|
||||
private class ProgramInfo implements Comparable<ProgramInfo> {
|
||||
private ProgramInfo getInfo(Program p) {
|
||||
if (p == null) {
|
||||
return null;
|
||||
}
|
||||
return programMap.get(p);
|
||||
}
|
||||
|
||||
Program program;
|
||||
URL ghidraURL;
|
||||
TransientToolState lastState;
|
||||
private int instance;
|
||||
boolean visible;
|
||||
Object owner;
|
||||
|
||||
ProgramInfo(Program p, boolean visible) {
|
||||
this.program = p;
|
||||
this.visible = visible;
|
||||
synchronized (ProgramInfo.class) {
|
||||
instance = ++nextProgramInfoInstance;
|
||||
Program getOpenProgram(URL ghidraURL) {
|
||||
if (!GhidraURL.isServerRepositoryURL(ghidraURL)) {
|
||||
return null;
|
||||
}
|
||||
URL normalizedURL = GhidraURL.getNormalizedURL(ghidraURL);
|
||||
for (ProgramInfo info : programMap.values()) {
|
||||
URL url = info.ghidraURL;
|
||||
if (url != null && url.equals(normalizedURL)) {
|
||||
return info.program;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setVisible(boolean state) {
|
||||
visible = state;
|
||||
fireVisibilityChangeEvent(program, visible);
|
||||
Program getOpenProgram(DomainFile domainFile, int version) {
|
||||
for (Program program : programMap.keySet()) {
|
||||
DomainFile programDomainFile = program.getDomainFile();
|
||||
if (filesMatch(domainFile, version, programDomainFile)) {
|
||||
return program;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean filesMatch(DomainFile file1, int version, DomainFile file2) {
|
||||
if (!file1.getPathname().equals(file2.getPathname())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(ProgramInfo info) {
|
||||
return instance - info.instance;
|
||||
if (file1.isCheckedOut() != file2.isCheckedOut()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!SystemUtilities.isEqual(file1.getProjectLocator(), file2.getProjectLocator())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int openVersion = file2.isReadOnly() ? file2.getVersion() : -1;
|
||||
return version == openVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if there is at least one program that has unsaved changes.
|
||||
* @return true if there is at least one program that has unsaved changes.
|
||||
*/
|
||||
boolean hasUnsavedPrograms() {
|
||||
return hasUnsavedPrograms;
|
||||
}
|
||||
|
||||
private boolean checkForUnsavedPrograms() {
|
||||
// first check the current program as that is the one most likely to have changes
|
||||
Program currentProgram = getCurrentProgram();
|
||||
if (currentProgram != null && currentProgram.isChanged()) {
|
||||
return true;
|
||||
}
|
||||
// look at all the open programs to see if any have changes
|
||||
for (ProgramInfo programInfo : openPrograms) {
|
||||
if (programInfo.program.isChanged()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -461,80 +459,69 @@ class MultiProgramManager implements DomainObjectListener, TransactionListener {
|
|||
|
||||
@Override
|
||||
public void undoStackChanged(DomainObjectAdapterDB domainObj) {
|
||||
SystemUtilities.runSwingLater(programChangedRunnable);
|
||||
Swing.runLater(programChangedRunnable);
|
||||
}
|
||||
|
||||
public Program getOpenProgram(URL ghidraURL) {
|
||||
if (!GhidraURL.isServerRepositoryURL(ghidraURL)) {
|
||||
return null;
|
||||
}
|
||||
URL normalizedURL = GhidraURL.getNormalizedURL(ghidraURL);
|
||||
for (ProgramInfo info : programMap.values()) {
|
||||
URL url = info.ghidraURL;
|
||||
if (url != null && url.equals(normalizedURL)) {
|
||||
return info.program;
|
||||
//==================================================================================================
|
||||
// Inner Classes
|
||||
//==================================================================================================
|
||||
private class MyFolderListener extends DomainFolderListenerAdapter {
|
||||
|
||||
@Override
|
||||
public void domainFileObjectReplaced(DomainFile file, DomainObject oldObject) {
|
||||
|
||||
/**
|
||||
* Special handling for when a file is checked-in. The existing program has be moved
|
||||
* to a proxy file (no longer in the project) so that it can be closed and the program
|
||||
* re-opened with the new version after the check-in merge.
|
||||
*/
|
||||
|
||||
if (!programMap.containsKey(oldObject)) {
|
||||
return;
|
||||
}
|
||||
Element dataState = null;
|
||||
if (currentInfo != null && currentInfo.program == oldObject) {
|
||||
// save dataState as though the project state was saved and re-opened to simulate
|
||||
// recovering after closing the program during this swap
|
||||
dataState = tool.saveDataStateToXml(true);
|
||||
}
|
||||
OpenProgramTask openTask = new OpenProgramTask(file, -1, this);
|
||||
openTask.setSilent();
|
||||
new TaskLauncher(openTask, tool.getToolFrame());
|
||||
Program openProgram = openTask.getOpenProgram();
|
||||
plugin.openProgram(openProgram,
|
||||
dataState != null ? ProgramManager.OPEN_CURRENT : ProgramManager.OPEN_VISIBLE);
|
||||
openProgram.release(this);
|
||||
removeProgram((Program) oldObject);
|
||||
if (dataState != null) {
|
||||
tool.restoreDataStateFromXml(dataState);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Program getOpenProgram(DomainFile domainFile, int version) {
|
||||
for (Program program : programMap.keySet()) {
|
||||
DomainFile programDomainFile = program.getDomainFile();
|
||||
if (filesMatch(domainFile, version, programDomainFile)) {
|
||||
return program;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
private class ProgramInfo implements Comparable<ProgramInfo> {
|
||||
|
||||
private boolean filesMatch(DomainFile file, int version, DomainFile openFile) {
|
||||
if (!file.getPathname().equals(openFile.getPathname())) {
|
||||
return false;
|
||||
private Program program;
|
||||
private URL ghidraURL;
|
||||
private TransientToolState lastState;
|
||||
private int instance;
|
||||
private boolean visible;
|
||||
private Object owner;
|
||||
|
||||
ProgramInfo(Program p, boolean visible) {
|
||||
this.program = p;
|
||||
this.visible = visible;
|
||||
instance = nextAvailableId.incrementAndGet();
|
||||
}
|
||||
|
||||
if (file.isCheckedOut() != openFile.isCheckedOut()) {
|
||||
return false;
|
||||
public void setVisible(boolean state) {
|
||||
visible = state;
|
||||
fireVisibilityChangeEvent(program, visible);
|
||||
}
|
||||
|
||||
if (!SystemUtilities.isEqual(file.getProjectLocator(), openFile.getProjectLocator())) {
|
||||
return false;
|
||||
@Override
|
||||
public int compareTo(ProgramInfo info) {
|
||||
return instance - info.instance;
|
||||
}
|
||||
|
||||
int openVersion = openFile.isReadOnly() ? openFile.getVersion() : -1;
|
||||
return version == openVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this ProgramManager is managing the given program
|
||||
* @param program the program to check
|
||||
* @return true if this ProgramManager is managing the given programs
|
||||
*/
|
||||
public boolean hasProgram(Program program) {
|
||||
return programMap.containsKey(program);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if there is at least one program that has unsaved changes.
|
||||
* @return true if there is at least one program that has unsaved changes.
|
||||
*/
|
||||
public boolean hasUnsavedPrograms() {
|
||||
return hasUnsavedPrograms;
|
||||
}
|
||||
|
||||
private boolean checkForUnsavedPrograms() {
|
||||
// first check the current program as that is the one most likely to have changes
|
||||
Program currentProgram = getCurrentProgram();
|
||||
if (currentProgram != null && currentProgram.isChanged()) {
|
||||
return true;
|
||||
}
|
||||
// look at all the open programs to see if any have changes
|
||||
for (ProgramInfo programInfo : openProgramList) {
|
||||
if (programInfo.program.isChanged()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,7 +23,6 @@ import java.net.MalformedURLException;
|
|||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import docking.action.DockingAction;
|
||||
import docking.action.builder.ActionBuilder;
|
||||
|
@ -138,17 +137,14 @@ public class ProgramManagerPlugin extends Plugin implements ProgramManager {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Program openProgram(final URL ghidraURL, final int state) {
|
||||
public Program openProgram(URL ghidraURL, int state) {
|
||||
if (locked) {
|
||||
Msg.showError(this, tool.getToolFrame(), "Open Program Failed",
|
||||
"Program manager is locked and cannot open additional programs");
|
||||
return null;
|
||||
}
|
||||
|
||||
AtomicReference<Program> ref = new AtomicReference<>();
|
||||
Runnable r = () -> ref.set(doOpenProgram(ghidraURL, state));
|
||||
SystemUtilities.runSwingNow(r);
|
||||
return ref.get();
|
||||
return Swing.runNow(() -> doOpenProgram(ghidraURL, state));
|
||||
}
|
||||
|
||||
private void messageBadProgramURL(URL ghidraURL) {
|
||||
|
@ -341,7 +337,7 @@ public class ProgramManagerPlugin extends Plugin implements ProgramManager {
|
|||
public boolean closeOtherPrograms(boolean ignoreChanges) {
|
||||
Program[] otherPrograms = programMgr.getOtherPrograms();
|
||||
Runnable r = () -> doCloseAllPrograms(otherPrograms, ignoreChanges);
|
||||
SystemUtilities.runSwingNow(r);
|
||||
Swing.runNow(r);
|
||||
return programMgr.isEmpty();
|
||||
}
|
||||
|
||||
|
@ -349,7 +345,7 @@ public class ProgramManagerPlugin extends Plugin implements ProgramManager {
|
|||
public boolean closeAllPrograms(boolean ignoreChanges) {
|
||||
Program[] openPrograms = programMgr.getAllPrograms();
|
||||
Runnable r = () -> doCloseAllPrograms(openPrograms, ignoreChanges);
|
||||
SystemUtilities.runSwingNow(r);
|
||||
Swing.runNow(r);
|
||||
return programMgr.isEmpty();
|
||||
}
|
||||
|
||||
|
@ -397,7 +393,7 @@ public class ProgramManagerPlugin extends Plugin implements ProgramManager {
|
|||
}
|
||||
Runnable r = () -> {
|
||||
// Note: The tool.canCloseDomainObject() call must come before the
|
||||
// programSaveMgr.canClose()call since plugins may save changes to the program
|
||||
// programSaveMgr.canClose() call since plugins may save changes to the program
|
||||
// so that they can close.
|
||||
if (ignoreChanges || program.isClosed() || programMgr.isPersistent(program) ||
|
||||
(tool.canCloseDomainObject(program) && programSaveMgr.canClose(program))) {
|
||||
|
@ -405,7 +401,7 @@ public class ProgramManagerPlugin extends Plugin implements ProgramManager {
|
|||
contextChanged();
|
||||
}
|
||||
};
|
||||
SystemUtilities.runSwingNow(r);
|
||||
Swing.runNow(r);
|
||||
return !programMgr.contains(program);
|
||||
}
|
||||
|
||||
|
@ -436,7 +432,7 @@ public class ProgramManagerPlugin extends Plugin implements ProgramManager {
|
|||
programMgr.setCurrentProgram(p);
|
||||
contextChanged();
|
||||
};
|
||||
SystemUtilities.runSwingNow(r);
|
||||
Swing.runNow(r);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -476,7 +472,7 @@ public class ProgramManagerPlugin extends Plugin implements ProgramManager {
|
|||
}
|
||||
contextChanged();
|
||||
};
|
||||
SystemUtilities.runSwingNow(r);
|
||||
Swing.runNow(r);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -506,13 +502,13 @@ public class ProgramManagerPlugin extends Plugin implements ProgramManager {
|
|||
|
||||
int subMenuGroup = 1;
|
||||
|
||||
DockingAction openAction = new ActionBuilder("Open File", getName())
|
||||
.menuPath(ToolConstants.MENU_FILE, "&Open...")
|
||||
.menuGroup(OPEN_GROUP, Integer.toString(subMenuGroup++))
|
||||
.keyBinding("ctrl O")
|
||||
.enabledWhen(c -> !locked)
|
||||
.onAction(c -> open())
|
||||
.buildAndInstall(tool);
|
||||
DockingAction openAction =
|
||||
new ActionBuilder("Open File", getName()).menuPath(ToolConstants.MENU_FILE, "&Open...")
|
||||
.menuGroup(OPEN_GROUP, Integer.toString(subMenuGroup++))
|
||||
.keyBinding("ctrl O")
|
||||
.enabledWhen(c -> !locked)
|
||||
.onAction(c -> open())
|
||||
.buildAndInstall(tool);
|
||||
openAction.addToWindowWhen(ProgramActionContext.class);
|
||||
|
||||
tool.addAction(new CloseProgramAction(this, OPEN_GROUP, subMenuGroup++));
|
||||
|
@ -522,7 +518,7 @@ public class ProgramManagerPlugin extends Plugin implements ProgramManager {
|
|||
.enabled(false)
|
||||
.withContext(ProgramActionContext.class)
|
||||
.inWindow(ActionBuilder.When.CONTEXT_MATCHES)
|
||||
.enabledWhen(c -> programMgr.hasProgram(c.getProgram()))
|
||||
.enabledWhen(c -> programMgr.contains(c.getProgram()))
|
||||
.onAction(c -> closeOtherPrograms(false))
|
||||
.buildAndInstall(tool);
|
||||
|
||||
|
|
|
@ -22,12 +22,20 @@ import ghidra.program.model.address.Address;
|
|||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.model.symbol.ExternalLocation;
|
||||
import ghidra.program.util.ProgramLocation;
|
||||
import ghidra.util.Swing;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
/**
|
||||
* The GoToService provides a general service for plugins to generate GoTo
|
||||
* events. The provider of this service will take care of interfacing with
|
||||
* any history service that may be available.
|
||||
* <p>
|
||||
* This class will execute all {@code goTo} calls on the Java Swing thread. This will happen in
|
||||
* a blocking manner if the client calls from any other thread. This has the potential to lead
|
||||
* to deadlocks if the client is using custom synchronization. Care must be taken to not be
|
||||
* holding any lock that will cause the Swing thread to block when using this class from any other
|
||||
* thread. To work around this issue, clients can always call this service from within a
|
||||
* {@link Swing#runLater(Runnable)} call, which will prevent any deadlock issues.
|
||||
*/
|
||||
@ServiceInfo(defaultProvider = GoToServicePlugin.class, description = "Navigate to a program location")
|
||||
public interface GoToService {
|
||||
|
@ -41,7 +49,7 @@ public interface GoToService {
|
|||
/**
|
||||
* Generates a GoTo event and handles any history state that needs to be saved. This method
|
||||
* will attempt to find the program that contains the given ProgramLocation.
|
||||
*
|
||||
*
|
||||
* @param loc location to go to
|
||||
* @return true if the go to was successful
|
||||
* @see #goTo(ProgramLocation, Program)
|
||||
|
@ -49,13 +57,13 @@ public interface GoToService {
|
|||
public boolean goTo(ProgramLocation loc);
|
||||
|
||||
/**
|
||||
* Generates a GoTo event and handles any history state that needs to be saved. This
|
||||
* overloaded version of {@link #goTo(Address)} uses the given program as the program
|
||||
* within which to perform the GoTo. If the given program does not contain the given
|
||||
* address, then the GoTo will not be performed and false will be returned. Passing
|
||||
* <code>null</code> as the <code>program</code> parameter will cause this method to attempt to find
|
||||
* a program that contains the given ProgramLocation.
|
||||
*
|
||||
* Generates a GoTo event and handles any history state that needs to be saved. This
|
||||
* overloaded version of {@link #goTo(Address)} uses the given program as the program within
|
||||
* which to perform the GoTo. If the given program does not contain the given address, then
|
||||
* the GoTo will not be performed and false will be returned. Passing <code>null</code> as the
|
||||
* <code>program</code> parameter will cause this method to attempt to find a program that
|
||||
* contains the given ProgramLocation.
|
||||
*
|
||||
* @param loc location to go to
|
||||
* @param program the program within which to perform the GoTo
|
||||
* @return true if the go to was successful
|
||||
|
@ -63,20 +71,46 @@ public interface GoToService {
|
|||
*/
|
||||
public boolean goTo(ProgramLocation loc, Program program);
|
||||
|
||||
/**
|
||||
* Generates a GoTo event to the given location in the given program.
|
||||
*
|
||||
* @param navigatable the destination navigatable
|
||||
* @param loc the location
|
||||
* @param program program
|
||||
* @return true if the go to was successful
|
||||
*/
|
||||
public boolean goTo(Navigatable navigatable, ProgramLocation loc, Program program);
|
||||
|
||||
/**
|
||||
* Generates a GoTo event to the given address. The refAddress is used to determine if
|
||||
* there is a specific symbol reference from that reference.
|
||||
*
|
||||
* @param navigatable the destination navigatable
|
||||
* @param program program
|
||||
* @param address the destination address
|
||||
* @param refAddress the from reference address
|
||||
* @return true if the go to was successful
|
||||
*/
|
||||
public boolean goTo(Navigatable navigatable, Program program, Address address,
|
||||
Address refAddress);
|
||||
|
||||
/**
|
||||
* Generates a GoTo event to the goToAddress or symbol. The currentAddress is used to
|
||||
* determine if there is a specific symbol reference from the current address.
|
||||
* @param currentAddress the current address
|
||||
* Generates a GoTo event to the given address. The fromAddress is used to determine if
|
||||
* there is a specific symbol reference from the current address.
|
||||
*
|
||||
* @param fromAddress the current address
|
||||
* @param address the address to goto
|
||||
* @return true if the go to was successful
|
||||
*/
|
||||
public boolean goTo(Address fromAddress, Address address);
|
||||
|
||||
/**
|
||||
* Generates a GoTo event to the given address for the specific navigatable.
|
||||
*
|
||||
* @param navigatable the destination navigatable
|
||||
* @param goToAddress the address to goto
|
||||
* @return true if the go to was successful
|
||||
*/
|
||||
public boolean goTo(Address currentAddress, Address goToAddress);
|
||||
|
||||
public boolean goTo(Navigatable navigatable, Address goToAddress);
|
||||
|
||||
/**
|
||||
|
@ -89,12 +123,12 @@ public interface GoToService {
|
|||
|
||||
/**
|
||||
* Generates a GoTo event to the gotoAddress. This overloaded version of
|
||||
* {@link #goTo(Address)} uses the given program as the program within which to
|
||||
* perform the GoTo. If the given program does not contain the given address, then the
|
||||
* GoTo will not be performed and false will be returned. Passing <code>null</code> as the
|
||||
* <code>program</code> parameter will cause this method to attempt to find
|
||||
* a program that contains the given ProgramLocation.
|
||||
*
|
||||
* {@link #goTo(Address)} uses the given program as the program within which to perform the
|
||||
* GoTo. If the given program does not contain the given address, then the GoTo will not be
|
||||
* performed and false will be returned. Passing <code>null</code> as the <code>program</code>
|
||||
* parameter will cause this method to attempt to find a program that contains the given
|
||||
* ProgramLocation.
|
||||
*
|
||||
* @param goToAddress the address to goto
|
||||
* @param program the program within which to perform the GoTo
|
||||
* @return true if the go to was successful
|
||||
|
@ -103,67 +137,82 @@ public interface GoToService {
|
|||
public boolean goTo(Address goToAddress, Program program);
|
||||
|
||||
/**
|
||||
* Navigate to either the external program location or address linkage location.
|
||||
* Specific behavior may vary based upon implementation.
|
||||
|
||||
* Navigate to either the external program location or address linkage location. Specific
|
||||
* behavior may vary based upon implementation.
|
||||
*
|
||||
* @param externalLoc external location
|
||||
* @param checkNavigationOption if true the service navigation
|
||||
* option will be used to determine if navigation to the external program will be
|
||||
* attempted, or if navigation to the external linkage location within the current
|
||||
* program will be attempted. If false, the implementations default behavior
|
||||
* will be performed.
|
||||
* @return true if either navigation to the external program or to a
|
||||
* linkage location was completed successfully.
|
||||
* @param checkNavigationOption if true the service navigation option will be used to determine
|
||||
* if navigation to the external program will be attempted, or if navigation to the
|
||||
* external linkage location within the current program will be attempted. If false, the
|
||||
* implementations default behavior will be performed.
|
||||
* @return true if either navigation to the external program or to a linkage location was
|
||||
* completed successfully.
|
||||
*/
|
||||
public boolean goToExternalLocation(ExternalLocation externalLoc,
|
||||
boolean checkNavigationOption);
|
||||
|
||||
/**
|
||||
* Navigate to either the external program location or address linkage location.
|
||||
* Specific behavior may vary based upon implementation.
|
||||
*
|
||||
* Navigate to either the external program location or address linkage location. Specific
|
||||
* behavior may vary based upon implementation.
|
||||
*
|
||||
* @param navigatable Navigatable
|
||||
* @param externalLoc external location
|
||||
* @param checkNavigationOption if true the service navigation
|
||||
* option will be used to determine if navigation to the external program will be
|
||||
* attempted, or if navigation to the external linkage location within the current
|
||||
* program will be attempted. If false, the implementations default behavior
|
||||
* will be performed.
|
||||
* @return true if either navigation to the external program or to a
|
||||
* linkage location was completed successfully.
|
||||
* @param checkNavigationOption if true the service navigation option will be used to determine
|
||||
* if navigation to the external program will be attempted, or if navigation to the
|
||||
* external linkage location within the current program will be attempted. If false, the
|
||||
* implementations default behavior will be performed.
|
||||
* @return true if either navigation to the external program or to a linkage location was
|
||||
* completed successfully.
|
||||
*/
|
||||
public boolean goToExternalLocation(Navigatable navigatable, ExternalLocation externalLoc,
|
||||
boolean checkNavigationOption);
|
||||
|
||||
/**
|
||||
* Parses the input string as either:
|
||||
* an address/symbol expression (0x1000+5, or LAB1000+5)
|
||||
* a symbol wildcard expression (LAB*, LAB?100)
|
||||
* a symbol lookup
|
||||
* an address lookup
|
||||
*
|
||||
* Generates a GoTo event for the given query.
|
||||
* <p>
|
||||
* If the query results in more than one location, a list of locations will be displayed.
|
||||
* If the query results in only one location, then a goto event will be fired(except for a
|
||||
* If the query results in only one location, then a goto event will be fired(except for a
|
||||
* wildcard query in which case a list will still be displayed.
|
||||
*
|
||||
* <p>
|
||||
* The listener will be notified after query and will indicate the query status.
|
||||
*
|
||||
*
|
||||
* @param fromAddr The address used to determine the scope of the query
|
||||
* @param queryData the query input data
|
||||
* @param listener the listener that will be notified when the query completes.
|
||||
* @param listener the listener that will be notified when the query completes
|
||||
* @param monitor the task monitor
|
||||
* @return true if the queryInput is found or appears to be a wildcard search.
|
||||
* @return true if the queryInput is found or appears to be a wildcard search
|
||||
*/
|
||||
public boolean goToQuery(Address fromAddr, QueryData queryData, GoToServiceListener listener,
|
||||
TaskMonitor monitor);
|
||||
|
||||
/**
|
||||
* Generates a GoTo event for the given query.
|
||||
* <p>
|
||||
* If the query results in more than one location, a list of locations will be displayed.
|
||||
* If the query results in only one location, then a goto event will be fired(except for a
|
||||
* wildcard query in which case a list will still be displayed.
|
||||
* <p>
|
||||
* The listener will be notified after query and will indicate the query status.
|
||||
*
|
||||
* @param navigatable the destination for the go to event
|
||||
* @param fromAddr The address used to determine the scope of the query
|
||||
* @param queryData the query input data
|
||||
* @param listener the listener that will be notified when the query completes
|
||||
* @param monitor the task monitor
|
||||
* @return true if the queryInput is found or appears to be a wildcard search
|
||||
*/
|
||||
public boolean goToQuery(Navigatable navigatable, Address fromAddr, QueryData queryData,
|
||||
GoToServiceListener listener, TaskMonitor monitor);
|
||||
|
||||
public GoToOverrideService getOverrideService();
|
||||
|
||||
public void setOverrideService(GoToOverrideService override);
|
||||
|
||||
/**
|
||||
* Returns the default navigatable that is the destination for GoTo events.
|
||||
* @return the navigatable
|
||||
*/
|
||||
public Navigatable getDefaultNavigatable();
|
||||
|
||||
@Deprecated(forRemoval = true, since = "10.2")
|
||||
public GoToOverrideService getOverrideService();
|
||||
|
||||
@Deprecated(forRemoval = true, since = "10.2")
|
||||
public void setOverrideService(GoToOverrideService override);
|
||||
}
|
||||
|
|
|
@ -29,9 +29,7 @@ import ghidra.program.model.listing.Program;
|
|||
* Service for managing programs. Multiple programs may be open in a tool, but only one is active at
|
||||
* any given time.
|
||||
*/
|
||||
@ServiceInfo(
|
||||
defaultProvider = ProgramManagerPlugin.class,
|
||||
description = "Get the currently open program")
|
||||
@ServiceInfo(defaultProvider = ProgramManagerPlugin.class, description = "Get the currently open program")
|
||||
public interface ProgramManager {
|
||||
|
||||
/**
|
||||
|
@ -53,14 +51,14 @@ public interface ProgramManager {
|
|||
|
||||
/**
|
||||
* Return the program that is currently active.
|
||||
*
|
||||
*
|
||||
* @return may return null if no program is open
|
||||
*/
|
||||
public Program getCurrentProgram();
|
||||
|
||||
/**
|
||||
* Returns true if the specified program is open and considered visible to the user.
|
||||
*
|
||||
*
|
||||
* @param program the program
|
||||
* @return true if the specified program is open and considered visible to the user
|
||||
*/
|
||||
|
@ -68,7 +66,7 @@ public interface ProgramManager {
|
|||
|
||||
/**
|
||||
* Closes the currently active program
|
||||
*
|
||||
*
|
||||
* @return true if the close is successful. false if the close fails or if there is no program
|
||||
* currently active.
|
||||
*/
|
||||
|
@ -76,7 +74,7 @@ public interface ProgramManager {
|
|||
|
||||
/**
|
||||
* Open the program corresponding to the given url.
|
||||
*
|
||||
*
|
||||
* @param ghidraURL valid server-based program URL
|
||||
* @param state initial open state (OPEN_HIDDEN, OPEN_CURRENT, OPEN_VISIBLE). The visibility
|
||||
* states will be ignored if the program is already open.
|
||||
|
@ -88,7 +86,7 @@ public interface ProgramManager {
|
|||
|
||||
/**
|
||||
* Open the program for the given domainFile. Once open it will become the active program.
|
||||
*
|
||||
*
|
||||
* @param domainFile domain file that has the program
|
||||
* @return null if the user canceled the "open" for the new program
|
||||
*/
|
||||
|
@ -96,10 +94,10 @@ public interface ProgramManager {
|
|||
|
||||
/**
|
||||
* Open the program for the given domainFile. Once open it will become the active program.
|
||||
*
|
||||
*
|
||||
* <P>
|
||||
* Note: this method functions exactly as {@link #openProgram(DomainFile)}
|
||||
*
|
||||
*
|
||||
* @param domainFile domain file that has the program
|
||||
* @param dialogParent unused
|
||||
* @return the program
|
||||
|
@ -112,7 +110,7 @@ public interface ProgramManager {
|
|||
/**
|
||||
* Opens the specified version of the program represented by the given DomainFile. This method
|
||||
* should be used for shared DomainFiles. The newly opened file will be made the active program.
|
||||
*
|
||||
*
|
||||
* @param df the DomainFile to open
|
||||
* @param version the version of the Program to open
|
||||
* @return the opened program or null if the given version does not exist.
|
||||
|
@ -121,7 +119,7 @@ public interface ProgramManager {
|
|||
|
||||
/**
|
||||
* Open the program for the given domainFile
|
||||
*
|
||||
*
|
||||
* @param domainFile domain file that has the program
|
||||
* @param version the version of the Program to open. Specify DomainFile.DEFAULT_VERSION for
|
||||
* file update mode.
|
||||
|
@ -135,7 +133,7 @@ public interface ProgramManager {
|
|||
/**
|
||||
* Opens the program to the tool. In this case the program is already open, but this tool may
|
||||
* not have it registered as open. The program is made the active program.
|
||||
*
|
||||
*
|
||||
* @param program the program to register as open with the tool.
|
||||
*/
|
||||
public void openProgram(Program program);
|
||||
|
@ -143,7 +141,7 @@ public interface ProgramManager {
|
|||
/**
|
||||
* Opens the program to the tool. In this case the program is already open, but this tool may
|
||||
* not have it registered as open. The program is made the active program.
|
||||
*
|
||||
*
|
||||
* @param program the program to register as open with the tool.
|
||||
* @param current if true, the program is made the current active program. If false, then the
|
||||
* program is made active only if it the first open program in the tool.
|
||||
|
@ -154,7 +152,7 @@ public interface ProgramManager {
|
|||
|
||||
/**
|
||||
* Open the specified program in the tool.
|
||||
*
|
||||
*
|
||||
* @param program the program
|
||||
* @param state initial open state (OPEN_HIDDEN, OPEN_CURRENT, OPEN_VISIBLE). The visibility
|
||||
* states will be ignored if the program is already open.
|
||||
|
@ -168,7 +166,7 @@ public interface ProgramManager {
|
|||
|
||||
/**
|
||||
* Saves the specified program, possibly prompting the user for a new name.
|
||||
*
|
||||
*
|
||||
* @param program the program
|
||||
*/
|
||||
public void saveProgram(Program program);
|
||||
|
@ -180,7 +178,7 @@ public interface ProgramManager {
|
|||
|
||||
/**
|
||||
* Prompts the user to save the specified program to a selected file.
|
||||
*
|
||||
*
|
||||
* @param program the program
|
||||
*/
|
||||
public void saveProgramAs(Program program);
|
||||
|
@ -188,13 +186,15 @@ public interface ProgramManager {
|
|||
/**
|
||||
* Establish a persistent owner on an open program. This will cause the program manager to imply
|
||||
* make a program hidden if it is closed.
|
||||
*
|
||||
*
|
||||
* @param program the program
|
||||
* @param owner the owner
|
||||
* @return true if program is open and another object is not already the owner, or the specified
|
||||
* owner is already the owner.
|
||||
* @see #releaseProgram(Program, Object)
|
||||
* @deprecated this method is no longer used by the system
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "10.2")
|
||||
public boolean setPersistentOwner(Program program, Object owner);
|
||||
|
||||
/**
|
||||
|
@ -205,10 +205,12 @@ public interface ProgramManager {
|
|||
* to save or keep the program open.
|
||||
* <p>
|
||||
* If persistentOwner is not the correct owner, the method will have no affect.
|
||||
*
|
||||
*
|
||||
* @param program the program
|
||||
* @param persistentOwner the owner defined by {@link #setPersistentOwner(Program, Object)}
|
||||
* @deprecated this method is no longer used by the system
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "10.2")
|
||||
public void releaseProgram(Program program, Object persistentOwner);
|
||||
|
||||
/**
|
||||
|
@ -217,7 +219,7 @@ public interface ProgramManager {
|
|||
* then the program is closed for this tool only and the user is not prompted to save the
|
||||
* program regardless of the ignoreChanges flag. Otherwise, if ignoreChanges is false and
|
||||
* changes have been made, the user is prompted to save the program.
|
||||
*
|
||||
*
|
||||
* @param program the program to close.
|
||||
* @param ignoreChanges if true, the program is closed without saving any changes.
|
||||
* @return true if the program was closed. Returns false if the user canceled the close while
|
||||
|
@ -230,7 +232,7 @@ public interface ProgramManager {
|
|||
* Closes all open programs in this tool except the current program. If this tool is the only
|
||||
* tool with a program open and that program has changes, then the user will be prompted to
|
||||
* close each such file. (Providing the ignoreChanges flag is false)
|
||||
*
|
||||
*
|
||||
* @param ignoreChanges if true, the programs will be closed without saving changes.
|
||||
* @return true if all other programs were closed. Returns false if the user canceled the close
|
||||
* while being prompted to save.
|
||||
|
@ -241,7 +243,7 @@ public interface ProgramManager {
|
|||
* Closes all open programs in this tool. If this tool is the only tool with a program open and
|
||||
* that program has changes, then the user will be prompted to close each such file. (Providing
|
||||
* the ignoreChanges flag is false)
|
||||
*
|
||||
*
|
||||
* @param ignoreChanges if true, the programs will be closed without saving changes.
|
||||
* @return true if all programs were closed. Returns false if the user canceled the close while
|
||||
* being prompted to save.
|
||||
|
@ -250,7 +252,7 @@ public interface ProgramManager {
|
|||
|
||||
/**
|
||||
* Sets the given program to be the current active program in the tool.
|
||||
*
|
||||
*
|
||||
* @param p the program to make active.
|
||||
*/
|
||||
public void setCurrentProgram(Program p);
|
||||
|
@ -260,7 +262,7 @@ public interface ProgramManager {
|
|||
* Programs are searched in the order they were opened within a given priority. Program are
|
||||
* initially opened with the PRIORITY_NORMAL priority, but can be set to have PRIORITY_HIGH or
|
||||
* PRIORITY_LOW.
|
||||
*
|
||||
*
|
||||
* @param addr the address for which to search.
|
||||
* @return the first program that can be found to contain the given address.
|
||||
*/
|
||||
|
@ -268,7 +270,7 @@ public interface ProgramManager {
|
|||
|
||||
/**
|
||||
* Returns a list of all open program.
|
||||
*
|
||||
*
|
||||
* @return the programs
|
||||
*/
|
||||
public Program[] getAllOpenPrograms();
|
||||
|
@ -276,7 +278,7 @@ public interface ProgramManager {
|
|||
/**
|
||||
* Allows program manager state to be locked/unlocked. While locked, the program manager will
|
||||
* not support opening additional programs.
|
||||
*
|
||||
*
|
||||
* @param state locked if true, unlocked if false
|
||||
* @deprecated deprecated for 10.1; removal for 10.3 or later
|
||||
*/
|
||||
|
@ -285,7 +287,7 @@ public interface ProgramManager {
|
|||
|
||||
/**
|
||||
* Returns true if program manager is in the locked state
|
||||
*
|
||||
*
|
||||
* @return true if program manager is in the locked state
|
||||
* @deprecated deprecated for 10.1; removal for 10.3 or later
|
||||
*/
|
||||
|
|
|
@ -42,7 +42,7 @@ import ghidra.program.model.symbol.*;
|
|||
import ghidra.program.util.AddressEvaluator;
|
||||
import ghidra.program.util.ProgramLocation;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.SystemUtilities;
|
||||
import ghidra.util.Swing;
|
||||
import ghidra.util.table.AddressArrayTableModel;
|
||||
import ghidra.util.table.GhidraProgramTableModel;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
@ -187,7 +187,7 @@ public class GoToQuery {
|
|||
return;
|
||||
}
|
||||
|
||||
SystemUtilities.runIfSwingOrPostSwingLater(() -> {
|
||||
Swing.runIfSwingOrRunLater(() -> {
|
||||
model = new AddressArrayTableModel("Goto: ", plugin.getTool(), program, validAddresses,
|
||||
monitor);
|
||||
model.addInitialLoadListener(tableModelListener);
|
||||
|
@ -203,7 +203,7 @@ public class GoToQuery {
|
|||
return;
|
||||
}
|
||||
|
||||
SystemUtilities.runIfSwingOrPostSwingLater(() -> {
|
||||
Swing.runIfSwingOrRunLater(() -> {
|
||||
model = new GoToQueryResultsTableModel(program, plugin.getTool(), locations, monitor);
|
||||
model.addInitialLoadListener(tableModelListener);
|
||||
});
|
||||
|
@ -214,7 +214,7 @@ public class GoToQuery {
|
|||
return false;
|
||||
}
|
||||
|
||||
SystemUtilities.runIfSwingOrPostSwingLater(() -> {
|
||||
Swing.runIfSwingOrRunLater(() -> {
|
||||
model = new GoToQueryResultsTableModel(navigatable.getProgram(), queryData,
|
||||
plugin.getTool(), maxHits, monitor);
|
||||
model.addInitialLoadListener(tableModelListener);
|
||||
|
@ -337,7 +337,7 @@ public class GoToQuery {
|
|||
return false;
|
||||
}
|
||||
|
||||
SystemUtilities.runIfSwingOrPostSwingLater(() -> {
|
||||
Swing.runIfSwingOrRunLater(() -> {
|
||||
Program program = navigatable.getProgram();
|
||||
model = new GoToQueryResultsTableModel(program, cleanupQuery(program, queryData),
|
||||
plugin.getTool(), maxHits, monitor);
|
||||
|
|
|
@ -46,6 +46,7 @@ import ghidra.program.model.listing.*;
|
|||
import ghidra.program.model.symbol.*;
|
||||
import ghidra.program.util.*;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.Swing;
|
||||
import ghidra.util.layout.HorizontalLayout;
|
||||
|
||||
public class ListingPanel extends JPanel implements FieldMouseListener, FieldLocationListener,
|
||||
|
@ -95,7 +96,7 @@ public class ListingPanel extends JPanel implements FieldMouseListener, FieldLoc
|
|||
|
||||
/**
|
||||
* Constructs a new ListingPanel using the given FormatManager and ServiceProvider.
|
||||
*
|
||||
*
|
||||
* @param manager the FormatManager to use.
|
||||
*/
|
||||
public ListingPanel(FormatManager manager) {
|
||||
|
@ -125,7 +126,7 @@ public class ListingPanel extends JPanel implements FieldMouseListener, FieldLoc
|
|||
|
||||
/**
|
||||
* Constructs a new ListingPanel for the given program.
|
||||
*
|
||||
*
|
||||
* @param mgr the FormatManager to use.
|
||||
* @param program the program for which to create a new ListingPanel
|
||||
*/
|
||||
|
@ -136,7 +137,7 @@ public class ListingPanel extends JPanel implements FieldMouseListener, FieldLoc
|
|||
|
||||
/**
|
||||
* Constructs a new ListingPanel with the given FormatManager and ListingLayoutModel
|
||||
*
|
||||
*
|
||||
* @param mgr the FormatManager to use
|
||||
* @param model the ListingLayoutModel to use.
|
||||
*/
|
||||
|
@ -182,7 +183,7 @@ public class ListingPanel extends JPanel implements FieldMouseListener, FieldLoc
|
|||
|
||||
/**
|
||||
* Sets the ProgramLocationListener. Only one listener is supported
|
||||
*
|
||||
*
|
||||
* @param listener the ProgramLocationListener to use.
|
||||
*/
|
||||
public void setProgramLocationListener(ProgramLocationListener listener) {
|
||||
|
@ -191,7 +192,7 @@ public class ListingPanel extends JPanel implements FieldMouseListener, FieldLoc
|
|||
|
||||
/**
|
||||
* Sets the ProgramSelectionListener. Only one listener is supported
|
||||
*
|
||||
*
|
||||
* @param listener the ProgramSelectionListener to use.
|
||||
*/
|
||||
public void setProgramSelectionListener(ProgramSelectionListener listener) {
|
||||
|
@ -204,7 +205,7 @@ public class ListingPanel extends JPanel implements FieldMouseListener, FieldLoc
|
|||
|
||||
/**
|
||||
* Sets the ListingLayoutModel to use.
|
||||
*
|
||||
*
|
||||
* @param newModel the model to use.
|
||||
*/
|
||||
public void setListingModel(ListingModel newModel) {
|
||||
|
@ -224,7 +225,7 @@ public class ListingPanel extends JPanel implements FieldMouseListener, FieldLoc
|
|||
|
||||
/**
|
||||
* Sets whether or not the field header component is visible at the top of the listing panel
|
||||
*
|
||||
*
|
||||
* @param show if true, the header component will be show, otherwise it will be hidden.
|
||||
*/
|
||||
public void showHeader(boolean show) {
|
||||
|
@ -283,7 +284,7 @@ public class ListingPanel extends JPanel implements FieldMouseListener, FieldLoc
|
|||
|
||||
/**
|
||||
* Adds the MarginProvider to this panel
|
||||
*
|
||||
*
|
||||
* @param provider the MarginProvider that will provide components to display in this panel's
|
||||
* left margin area.
|
||||
*/
|
||||
|
@ -375,7 +376,7 @@ public class ListingPanel extends JPanel implements FieldMouseListener, FieldLoc
|
|||
|
||||
/**
|
||||
* Add a change listener to be notified whenever the indexMap changes.
|
||||
*
|
||||
*
|
||||
* @param listener the listener to be added.
|
||||
*/
|
||||
public void addIndexMapChangeListener(ChangeListener listener) {
|
||||
|
@ -384,7 +385,7 @@ public class ListingPanel extends JPanel implements FieldMouseListener, FieldLoc
|
|||
|
||||
/**
|
||||
* Removes the change listener to be notified when the indexMap changes.
|
||||
*
|
||||
*
|
||||
* @param listener the listener to be removed.
|
||||
*/
|
||||
public void removeIndexMapChangeListener(ChangeListener listener) {
|
||||
|
@ -393,7 +394,7 @@ public class ListingPanel extends JPanel implements FieldMouseListener, FieldLoc
|
|||
|
||||
/**
|
||||
* Removes the given margin provider from this panel
|
||||
*
|
||||
*
|
||||
* @param provider the MarginProvider to remove.
|
||||
*/
|
||||
public void removeMarginProvider(MarginProvider provider) {
|
||||
|
@ -403,7 +404,7 @@ public class ListingPanel extends JPanel implements FieldMouseListener, FieldLoc
|
|||
|
||||
/**
|
||||
* Adds the given OverviewProvider with will be displayed in this panels right margin area.
|
||||
*
|
||||
*
|
||||
* @param provider the OverviewProvider to display.
|
||||
*/
|
||||
public void addOverviewProvider(OverviewProvider provider) {
|
||||
|
@ -414,7 +415,7 @@ public class ListingPanel extends JPanel implements FieldMouseListener, FieldLoc
|
|||
|
||||
/**
|
||||
* Removes the given OverviewProvider from this panel
|
||||
*
|
||||
*
|
||||
* @param provider the OverviewProvider to remove.
|
||||
*/
|
||||
public void removeOverviewProvider(OverviewProvider provider) {
|
||||
|
@ -425,7 +426,7 @@ public class ListingPanel extends JPanel implements FieldMouseListener, FieldLoc
|
|||
/**
|
||||
* Adds a ButtonPressedListener to be notified when the user presses the mouse button while over
|
||||
* this panel
|
||||
*
|
||||
*
|
||||
* @param listener the ButtonPressedListener to add.
|
||||
*/
|
||||
public void addButtonPressedListener(ButtonPressedListener listener) {
|
||||
|
@ -436,7 +437,7 @@ public class ListingPanel extends JPanel implements FieldMouseListener, FieldLoc
|
|||
|
||||
/**
|
||||
* Removes the given ButtonPressedListener.
|
||||
*
|
||||
*
|
||||
* @param listener the ButtonPressedListener to remove.
|
||||
*/
|
||||
public void removeButtonPressedListener(ButtonPressedListener listener) {
|
||||
|
@ -508,7 +509,7 @@ public class ListingPanel extends JPanel implements FieldMouseListener, FieldLoc
|
|||
|
||||
/**
|
||||
* Sets the divider location between the left margin areas and the main display.
|
||||
*
|
||||
*
|
||||
* @param dividerLocation the location to set on the divider.
|
||||
*/
|
||||
public void setDividerLocation(int dividerLocation) {
|
||||
|
@ -556,7 +557,7 @@ public class ListingPanel extends JPanel implements FieldMouseListener, FieldLoc
|
|||
/**
|
||||
* Moves the cursor to the given program location and repositions the scrollbar to show that
|
||||
* location in the screen.
|
||||
*
|
||||
*
|
||||
* @param loc the location to move to.
|
||||
*/
|
||||
public boolean goTo(ProgramLocation loc) {
|
||||
|
@ -574,6 +575,9 @@ public class ListingPanel extends JPanel implements FieldMouseListener, FieldLoc
|
|||
* screen will be scrolled only enough to show the cursor.
|
||||
*/
|
||||
public boolean goTo(ProgramLocation loc, boolean centerWhenNotVisible) {
|
||||
|
||||
Swing.assertSwingThread("goTo() must be called on the Swing thread");
|
||||
|
||||
final FieldLocation floc = getFieldLocation(loc);
|
||||
if (floc == null) {
|
||||
return false;
|
||||
|
@ -623,9 +627,6 @@ public class ListingPanel extends JPanel implements FieldMouseListener, FieldLoc
|
|||
if (programAddressSpace != locAddressSpace) {
|
||||
FieldLocation compatibleLocation =
|
||||
getFieldLocationForDifferingAddressSpaces(loc, program);
|
||||
if (compatibleLocation == null) {
|
||||
return null;
|
||||
}
|
||||
return compatibleLocation;
|
||||
}
|
||||
|
||||
|
@ -712,7 +713,7 @@ public class ListingPanel extends JPanel implements FieldMouseListener, FieldLoc
|
|||
|
||||
/**
|
||||
* Positions the ListingPanel to the given address.
|
||||
*
|
||||
*
|
||||
* @param addr the address at which to position the listing.
|
||||
*/
|
||||
public boolean goTo(Address addr) {
|
||||
|
@ -725,7 +726,7 @@ public class ListingPanel extends JPanel implements FieldMouseListener, FieldLoc
|
|||
|
||||
/**
|
||||
* Positions the ListingPanel to the given address.
|
||||
*
|
||||
*
|
||||
* @param currentAddress used to determine which symbol to goto if the goto address has more
|
||||
* than one
|
||||
* @param gotoAddress the address at which to position to listing.
|
||||
|
@ -768,7 +769,7 @@ public class ListingPanel extends JPanel implements FieldMouseListener, FieldLoc
|
|||
|
||||
/**
|
||||
* Sets the program to be displayed by this listing panel
|
||||
*
|
||||
*
|
||||
* @param program the program to display.
|
||||
*/
|
||||
public void setProgram(Program program) {
|
||||
|
@ -802,7 +803,7 @@ public class ListingPanel extends JPanel implements FieldMouseListener, FieldLoc
|
|||
|
||||
/**
|
||||
* Restricts the program's view to the given address set
|
||||
*
|
||||
*
|
||||
* @param view the set of address to include in the view.
|
||||
*/
|
||||
public void setView(AddressSetView view) {
|
||||
|
@ -875,7 +876,7 @@ public class ListingPanel extends JPanel implements FieldMouseListener, FieldLoc
|
|||
|
||||
/**
|
||||
* Get a program location for the given point.
|
||||
*
|
||||
*
|
||||
* @return program location, or null if point does not correspond to a program location
|
||||
*/
|
||||
public ProgramLocation getProgramLocation(Point point) {
|
||||
|
@ -911,7 +912,7 @@ public class ListingPanel extends JPanel implements FieldMouseListener, FieldLoc
|
|||
|
||||
/**
|
||||
* Sets the cursor to the given program location.
|
||||
*
|
||||
*
|
||||
* @param loc the location at which to move the cursor.
|
||||
*/
|
||||
public void setCursorPosition(ProgramLocation loc) {
|
||||
|
@ -920,10 +921,10 @@ public class ListingPanel extends JPanel implements FieldMouseListener, FieldLoc
|
|||
|
||||
/**
|
||||
* Sets the cursor to the given program location with a given trigger
|
||||
*
|
||||
*
|
||||
* This method should only be used in automated testing to programmatically simulate a user
|
||||
* navigating within the listing panel.
|
||||
*
|
||||
*
|
||||
* @param loc the location at which to move the cursor.
|
||||
* @param trigger the event trigger
|
||||
*/
|
||||
|
@ -1040,7 +1041,7 @@ public class ListingPanel extends JPanel implements FieldMouseListener, FieldLoc
|
|||
|
||||
/**
|
||||
* Sets the selection.
|
||||
*
|
||||
*
|
||||
* @param sel the new selection
|
||||
*/
|
||||
public void setSelection(ProgramSelection sel) {
|
||||
|
@ -1082,7 +1083,7 @@ public class ListingPanel extends JPanel implements FieldMouseListener, FieldLoc
|
|||
|
||||
/**
|
||||
* Sets the highlight.
|
||||
*
|
||||
*
|
||||
* @param highlight the new highlight.
|
||||
*/
|
||||
public void setHighlight(ProgramSelection highlight) {
|
||||
|
@ -1125,7 +1126,6 @@ public class ListingPanel extends JPanel implements FieldMouseListener, FieldLoc
|
|||
/**
|
||||
* Returns the currently selected text. The value will only be non-null for selections within a
|
||||
* single field.
|
||||
*
|
||||
* @return the selected text or null
|
||||
*/
|
||||
public String getTextSelection() {
|
||||
|
|
|
@ -37,7 +37,7 @@ import ghidra.program.model.listing.*;
|
|||
import ghidra.program.model.symbol.*;
|
||||
import ghidra.program.util.*;
|
||||
import ghidra.test.*;
|
||||
import ghidra.util.task.TaskMonitorAdapter;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
/**
|
||||
* Tests for tool state history plugin.
|
||||
|
@ -87,7 +87,7 @@ public class NavigationHistoryPluginTest extends AbstractGhidraHeadedIntegration
|
|||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
waitForPostedSwingRunnables();
|
||||
waitForSwing();
|
||||
env.dispose();
|
||||
}
|
||||
|
||||
|
@ -95,8 +95,7 @@ public class NavigationHistoryPluginTest extends AbstractGhidraHeadedIntegration
|
|||
public void testPrevious() throws Exception {
|
||||
// go to sscanf
|
||||
QueryData queryData = new QueryData("sscanf", false);
|
||||
goToService.goToQuery(program.getMinAddress(), queryData, null,
|
||||
TaskMonitorAdapter.DUMMY_MONITOR);
|
||||
goToService.goToQuery(program.getMinAddress(), queryData, null, TaskMonitor.DUMMY);
|
||||
|
||||
assertTrue(plugin.hasPrevious(navigatable));
|
||||
|
||||
|
@ -119,30 +118,29 @@ public class NavigationHistoryPluginTest extends AbstractGhidraHeadedIntegration
|
|||
|
||||
performAction(prevAction, provider, true);
|
||||
cb.updateNow();
|
||||
waitForPostedSwingRunnables();
|
||||
waitForSwing();
|
||||
assertEquals(loc, cb.getCurrentLocation());
|
||||
assertTrue(prevAction.isEnabledForContext(provider.getActionContext(null)));
|
||||
assertTrue(nextAction.isEnabledForContext(provider.getActionContext(null)));
|
||||
|
||||
performAction(prevAction, provider, true);
|
||||
cb.updateNow();
|
||||
waitForPostedSwingRunnables();
|
||||
waitForSwing();
|
||||
assertEquals(program.getMinAddress(), cb.getCurrentAddress());
|
||||
assertTrue(!prevAction.isEnabledForContext(provider.getActionContext(null)));
|
||||
assertFalse(prevAction.isEnabledForContext(provider.getActionContext(null)));
|
||||
assertTrue(nextAction.isEnabledForContext(provider.getActionContext(null)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNext() throws Exception {
|
||||
QueryData queryData = new QueryData("sscanf", false);
|
||||
goToService.goToQuery(program.getMinAddress(), queryData, null,
|
||||
TaskMonitorAdapter.DUMMY_MONITOR);
|
||||
goToService.goToQuery(program.getMinAddress(), queryData, null, TaskMonitor.DUMMY);
|
||||
|
||||
assertTrue(plugin.hasPrevious(navigatable));
|
||||
|
||||
assertNotNull(prevAction);
|
||||
assertTrue(prevAction.isEnabledForContext(provider.getActionContext(null)));
|
||||
assertTrue(!nextAction.isEnabledForContext(provider.getActionContext(null)));
|
||||
assertFalse(nextAction.isEnabledForContext(provider.getActionContext(null)));
|
||||
|
||||
ProgramLocation loc = cb.getCurrentLocation();
|
||||
assertTrue(loc instanceof FunctionSignatureFieldLocation);
|
||||
|
@ -174,17 +172,17 @@ public class NavigationHistoryPluginTest extends AbstractGhidraHeadedIntegration
|
|||
|
||||
performAction(prevAction, provider, true);
|
||||
cb.updateNow();
|
||||
waitForPostedSwingRunnables();
|
||||
waitForSwing();
|
||||
assertEquals(opLoc, cb.getCurrentLocation());
|
||||
|
||||
performAction(prevAction, provider, true);
|
||||
cb.updateNow();
|
||||
waitForPostedSwingRunnables();
|
||||
waitForSwing();
|
||||
assertEquals(xrefLoc, cb.getCurrentLocation());
|
||||
|
||||
performAction(prevAction, provider, true);
|
||||
cb.updateNow();
|
||||
waitForPostedSwingRunnables();
|
||||
waitForSwing();
|
||||
assertEquals(loc, cb.getCurrentLocation());
|
||||
|
||||
assertTrue(prevAction.isEnabledForContext(provider.getActionContext(null)));
|
||||
|
@ -192,18 +190,18 @@ public class NavigationHistoryPluginTest extends AbstractGhidraHeadedIntegration
|
|||
|
||||
performAction(prevAction, provider, true);
|
||||
cb.updateNow();
|
||||
waitForPostedSwingRunnables();
|
||||
waitForSwing();
|
||||
assertEquals(program.getMinAddress(), cb.getCurrentAddress());
|
||||
assertTrue(!prevAction.isEnabledForContext(provider.getActionContext(null)));
|
||||
assertFalse(prevAction.isEnabledForContext(provider.getActionContext(null)));
|
||||
|
||||
performAction(nextAction, provider, true);
|
||||
cb.updateNow();
|
||||
waitForPostedSwingRunnables();
|
||||
waitForSwing();
|
||||
assertEquals(loc, cb.getCurrentLocation());
|
||||
|
||||
performAction(nextAction, provider, true);
|
||||
cb.updateNow();
|
||||
waitForPostedSwingRunnables();
|
||||
waitForSwing();
|
||||
assertEquals(xrefLoc, cb.getCurrentLocation());
|
||||
|
||||
assertTrue(prevAction.isEnabledForContext(provider.getActionContext(null)));
|
||||
|
@ -211,24 +209,23 @@ public class NavigationHistoryPluginTest extends AbstractGhidraHeadedIntegration
|
|||
|
||||
performAction(prevAction, provider, true);
|
||||
performAction(prevAction, provider, true);
|
||||
assertTrue(!prevAction.isEnabledForContext(provider.getActionContext(null)));
|
||||
assertFalse(prevAction.isEnabledForContext(provider.getActionContext(null)));
|
||||
assertTrue(nextAction.isEnabledForContext(provider.getActionContext(null)));
|
||||
|
||||
for (ProgramLocation element : locations) {
|
||||
performAction(nextAction, provider, true);
|
||||
cb.updateNow();
|
||||
waitForPostedSwingRunnables();
|
||||
waitForSwing();
|
||||
assertEquals(element, cb.getCurrentLocation());
|
||||
}
|
||||
assertTrue(!nextAction.isEnabledForContext(provider.getActionContext(null)));
|
||||
assertFalse(nextAction.isEnabledForContext(provider.getActionContext(null)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNavigationInCodeBrowser() throws Exception {
|
||||
QueryData queryData = new QueryData("sscanf", false);
|
||||
|
||||
goToService.goToQuery(program.getMinAddress(), queryData, null,
|
||||
TaskMonitorAdapter.DUMMY_MONITOR);
|
||||
goToService.goToQuery(program.getMinAddress(), queryData, null, TaskMonitor.DUMMY);
|
||||
|
||||
ProgramLocation loc = cb.getCurrentLocation();
|
||||
assertTrue(loc instanceof FunctionSignatureFieldLocation);
|
||||
|
@ -279,8 +276,7 @@ public class NavigationHistoryPluginTest extends AbstractGhidraHeadedIntegration
|
|||
DockingActionIf clearAction = getAction(nextPrevPlugin, "Clear History Buffer");
|
||||
|
||||
QueryData queryData = new QueryData("sscanf", false);
|
||||
goToService.goToQuery(program.getMinAddress(), queryData, null,
|
||||
TaskMonitorAdapter.DUMMY_MONITOR);
|
||||
goToService.goToQuery(program.getMinAddress(), queryData, null, TaskMonitor.DUMMY);
|
||||
|
||||
ProgramLocation loc = cb.getCurrentLocation();
|
||||
|
||||
|
@ -294,8 +290,8 @@ public class NavigationHistoryPluginTest extends AbstractGhidraHeadedIntegration
|
|||
click(cb, 2);
|
||||
|
||||
performAction(clearAction, provider, true);
|
||||
assertTrue(!plugin.hasNext(navigatable));
|
||||
assertTrue(!plugin.hasPrevious(navigatable));
|
||||
assertFalse(plugin.hasNext(navigatable));
|
||||
assertFalse(plugin.hasPrevious(navigatable));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -303,14 +299,13 @@ public class NavigationHistoryPluginTest extends AbstractGhidraHeadedIntegration
|
|||
ProgramLocation initialLoc = cb.getCurrentLocation();
|
||||
|
||||
QueryData queryData = new QueryData("sscanf", false);
|
||||
goToService.goToQuery(program.getMinAddress(), queryData, null,
|
||||
TaskMonitorAdapter.DUMMY_MONITOR);
|
||||
goToService.goToQuery(program.getMinAddress(), queryData, null, TaskMonitor.DUMMY);
|
||||
|
||||
assertTrue(plugin.hasPrevious(navigatable));
|
||||
|
||||
assertNotNull(prevAction);
|
||||
assertTrue(prevAction.isEnabledForContext(provider.getActionContext(null)));
|
||||
assertTrue(!nextAction.isEnabledForContext(provider.getActionContext(null)));
|
||||
assertFalse(nextAction.isEnabledForContext(provider.getActionContext(null)));
|
||||
|
||||
ProgramLocation loc = cb.getCurrentLocation();
|
||||
assertTrue(loc instanceof FunctionSignatureFieldLocation);
|
||||
|
@ -347,10 +342,10 @@ public class NavigationHistoryPluginTest extends AbstractGhidraHeadedIntegration
|
|||
for (int i = locations.length - 1; i >= 0; i--) {
|
||||
performAction(prevAction, provider, true);
|
||||
cb.updateNow();
|
||||
waitForPostedSwingRunnables();
|
||||
waitForSwing();
|
||||
assertEquals(locations[i], cb.getCurrentLocation());
|
||||
}
|
||||
assertTrue(!prevAction.isEnabledForContext(provider.getActionContext(null)));
|
||||
assertFalse(prevAction.isEnabledForContext(provider.getActionContext(null)));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -367,16 +362,17 @@ public class NavigationHistoryPluginTest extends AbstractGhidraHeadedIntegration
|
|||
|
||||
++count;
|
||||
|
||||
goToService.goTo(currentAddr, symbol.getAddress());
|
||||
Address addr = currentAddr;
|
||||
runSwing(() -> goToService.goTo(addr, symbol.getAddress()));
|
||||
cb.updateNow();
|
||||
currentAddr = symbol.getAddress();
|
||||
if (count > NavigationHistoryPlugin.MAX_HISTORY_SIZE) {
|
||||
for (int i = 0; i < NavigationHistoryPlugin.MAX_HISTORY_SIZE - 1; i++) {
|
||||
assertTrue(plugin.hasPrevious(navigatable));
|
||||
plugin.previous(navigatable);
|
||||
runSwing(() -> plugin.previous(navigatable));
|
||||
cb.updateNow();
|
||||
}
|
||||
assertTrue(!plugin.hasPrevious(navigatable));
|
||||
assertFalse(plugin.hasPrevious(navigatable));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -396,7 +392,8 @@ public class NavigationHistoryPluginTest extends AbstractGhidraHeadedIntegration
|
|||
}
|
||||
|
||||
++count;
|
||||
goToService.goTo(currentAddr, symbol.getAddress());
|
||||
Address addr = currentAddr;
|
||||
runSwing(() -> goToService.goTo(addr, symbol.getAddress()));
|
||||
cb.updateNow();
|
||||
currentAddr = symbol.getAddress();
|
||||
if (count > 2 * NavigationHistoryPlugin.MAX_HISTORY_SIZE) {
|
||||
|
@ -413,16 +410,16 @@ public class NavigationHistoryPluginTest extends AbstractGhidraHeadedIntegration
|
|||
|
||||
for (int i = 0; i < NavigationHistoryPlugin.MAX_HISTORY_SIZE - 1; i++) {
|
||||
assertTrue(plugin.hasPrevious(navigatable));
|
||||
plugin.previous(navigatable);
|
||||
runSwing(() -> plugin.previous(navigatable));
|
||||
cb.updateNow();
|
||||
}
|
||||
assertTrue(!plugin.hasPrevious(navigatable));
|
||||
assertFalse(plugin.hasPrevious(navigatable));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNextAfterUndoRedo() throws Exception {
|
||||
//
|
||||
// Note: the addresses used here are arbitrary, except that there is an undefined are
|
||||
// Note: the addresses used here are arbitrary, except that there is an undefined are
|
||||
// we can use to create data
|
||||
//
|
||||
|
||||
|
@ -448,7 +445,7 @@ public class NavigationHistoryPluginTest extends AbstractGhidraHeadedIntegration
|
|||
ProgramLocation loc = cb.getCurrentLocation();
|
||||
assertEquals(addr, loc.getAddress());
|
||||
|
||||
// do the next action and make sure it went to 1001020, which is
|
||||
// do the next action and make sure it went to 1001020, which is
|
||||
// where we were before the undo
|
||||
performAction(prevAction, provider, true);
|
||||
cb.updateNow();
|
||||
|
@ -459,7 +456,7 @@ public class NavigationHistoryPluginTest extends AbstractGhidraHeadedIntegration
|
|||
Address addr3 = getAddr(0x1001030);
|
||||
goToService.goTo(addr3);
|
||||
|
||||
// do the redo and verify we are back to 1001020, which is
|
||||
// do the redo and verify we are back to 1001020, which is
|
||||
// where we were when we did the undo
|
||||
performAction(redoAction, provider, true);
|
||||
cb.updateNow();
|
||||
|
|
|
@ -25,7 +25,6 @@ import javax.swing.tree.TreePath;
|
|||
|
||||
import org.junit.*;
|
||||
|
||||
import docking.ComponentProvider;
|
||||
import docking.action.DockingActionIf;
|
||||
import ghidra.app.events.ProgramSelectionPluginEvent;
|
||||
import ghidra.app.plugin.core.codebrowser.CodeBrowserPlugin;
|
||||
|
@ -33,6 +32,7 @@ import ghidra.app.plugin.core.codebrowser.CodeViewerProvider;
|
|||
import ghidra.app.plugin.core.marker.MarkerManagerPlugin;
|
||||
import ghidra.app.plugin.core.navigation.GoToAddressLabelPlugin;
|
||||
import ghidra.app.plugin.core.programtree.ProgramTreePlugin;
|
||||
import ghidra.app.plugin.core.programtree.ViewManagerComponentProvider;
|
||||
import ghidra.app.plugin.core.select.programtree.ProgramTreeSelectionPlugin;
|
||||
import ghidra.app.services.ProgramManager;
|
||||
import ghidra.framework.plugintool.PluginTool;
|
||||
|
@ -57,7 +57,7 @@ public class QualifiedSelectionPluginTest extends AbstractGhidraHeadedIntegratio
|
|||
private DockingActionIf selectInstructionAction;
|
||||
private DockingActionIf selectUndefinedAction;
|
||||
private ProgramTreePlugin pt;
|
||||
private ComponentProvider programTreeProvider;
|
||||
private ViewManagerComponentProvider programTreeProvider;
|
||||
private DockingActionIf replaceView;
|
||||
private ToyProgramBuilder builder;
|
||||
|
||||
|
@ -94,10 +94,9 @@ public class QualifiedSelectionPluginTest extends AbstractGhidraHeadedIntegratio
|
|||
}
|
||||
|
||||
private void showProgramTree() {
|
||||
|
||||
ProgramTreePlugin ptree = env.getPlugin(ProgramTreePlugin.class);
|
||||
programTreeProvider = (ComponentProvider) getInstanceField("viewProvider", pt);
|
||||
programTreeProvider = (ViewManagerComponentProvider) getInstanceField("viewProvider", pt);
|
||||
tool.showComponentProvider(programTreeProvider, true);
|
||||
waitForComponentProvider(ViewManagerComponentProvider.class);
|
||||
}
|
||||
|
||||
protected void setUpQualifiedSelection(PluginTool tool) throws Exception {
|
||||
|
@ -115,7 +114,7 @@ public class QualifiedSelectionPluginTest extends AbstractGhidraHeadedIntegratio
|
|||
// Select All Instructions.
|
||||
performAction(selectInstructionAction, provider, true);
|
||||
ProgramSelection instructionSet = getCurrentSelection();
|
||||
assertTrue(!instructionSet.isEmpty());
|
||||
assertFalse(instructionSet.isEmpty());
|
||||
|
||||
// Select No Data (because there is a selection of all instructions).
|
||||
performAction(selectDataAction, provider, true);
|
||||
|
@ -124,7 +123,7 @@ public class QualifiedSelectionPluginTest extends AbstractGhidraHeadedIntegratio
|
|||
// Select All Data.
|
||||
performAction(selectDataAction, provider, true);
|
||||
ProgramSelection dataSet = getCurrentSelection();
|
||||
assertTrue(!dataSet.isEmpty());
|
||||
assertFalse(dataSet.isEmpty());
|
||||
|
||||
// Select No Undefined.
|
||||
performAction(selectUndefinedAction, provider, true);
|
||||
|
@ -133,7 +132,7 @@ public class QualifiedSelectionPluginTest extends AbstractGhidraHeadedIntegratio
|
|||
// Select All Undefined.
|
||||
performAction(selectUndefinedAction, provider, true);
|
||||
ProgramSelection undefinedSet = getCurrentSelection();
|
||||
assertTrue(!undefinedSet.isEmpty());
|
||||
assertFalse(undefinedSet.isEmpty());
|
||||
|
||||
// Select No Instructions.
|
||||
performAction(selectInstructionAction, provider, true);
|
||||
|
@ -170,7 +169,7 @@ public class QualifiedSelectionPluginTest extends AbstractGhidraHeadedIntegratio
|
|||
// Select Instructions.
|
||||
performAction(selectInstructionAction, provider, true);
|
||||
ProgramSelection instructionSet = getCurrentSelection();
|
||||
assertTrue(!instructionSet.isEmpty());
|
||||
assertFalse(instructionSet.isEmpty());
|
||||
assertTrue(instructionSet.getMinAddress().compareTo(addr("010012d2")) >= 0);
|
||||
assertTrue(instructionSet.getMaxAddress().compareTo(addr("01001960")) <= 0);
|
||||
|
||||
|
@ -182,7 +181,7 @@ public class QualifiedSelectionPluginTest extends AbstractGhidraHeadedIntegratio
|
|||
performAction(selectDataAction, provider, true);
|
||||
waitForSwing();
|
||||
ProgramSelection dataSet = getCurrentSelection();
|
||||
assertTrue(!dataSet.isEmpty());
|
||||
assertFalse(dataSet.isEmpty());
|
||||
assertTrue(dataSet.getMinAddress().compareTo(addr("010012d2")) >= 0);
|
||||
assertTrue(dataSet.getMaxAddress().compareTo(addr("01001960")) <= 0);
|
||||
|
||||
|
@ -194,7 +193,7 @@ public class QualifiedSelectionPluginTest extends AbstractGhidraHeadedIntegratio
|
|||
performAction(selectUndefinedAction, provider, true);
|
||||
waitForSwing();
|
||||
ProgramSelection undefinedSet = getCurrentSelection();
|
||||
assertTrue(!undefinedSet.isEmpty());
|
||||
assertFalse(undefinedSet.isEmpty());
|
||||
assertTrue(undefinedSet.getMinAddress().compareTo(addr("010012d2")) >= 0);
|
||||
assertTrue(undefinedSet.getMaxAddress().compareTo(addr("01001960")) <= 0);
|
||||
|
||||
|
@ -219,7 +218,8 @@ public class QualifiedSelectionPluginTest extends AbstractGhidraHeadedIntegratio
|
|||
@Test
|
||||
public void testSelectWithView() throws Exception {
|
||||
AddressSet rsrcSet = new AddressSet(addr("0100a000"), addr("0100f3ff"));
|
||||
JTree tree = findComponent(tool.getToolFrame(), JTree.class);
|
||||
|
||||
JTree tree = waitFor(() -> findComponent(tool.getToolFrame(), JTree.class));
|
||||
|
||||
// Replace view with .rsrc
|
||||
selectTreeNodeByText(tree, ".rsrc", true);
|
||||
|
@ -254,12 +254,12 @@ public class QualifiedSelectionPluginTest extends AbstractGhidraHeadedIntegratio
|
|||
performAction(selectDataAction, provider, true);
|
||||
waitForSwing();
|
||||
ProgramSelection rsrcDataSet = getCurrentSelection();
|
||||
assertTrue(!rsrcDataSet.isEmpty());
|
||||
assertFalse(rsrcDataSet.isEmpty());
|
||||
// Change to program view
|
||||
selectTreeNodeByText(tree, "Test", true);
|
||||
performAction(replaceView, provider, true);
|
||||
ProgramSelection dataSet = getCurrentSelection();
|
||||
assertTrue(!dataSet.isEmpty());
|
||||
assertFalse(dataSet.isEmpty());
|
||||
|
||||
// Select No Undefined.
|
||||
performAction(selectUndefinedAction, provider, true);
|
||||
|
@ -274,12 +274,12 @@ public class QualifiedSelectionPluginTest extends AbstractGhidraHeadedIntegratio
|
|||
performAction(selectUndefinedAction, provider, true);
|
||||
waitForSwing();
|
||||
ProgramSelection rsrcUndefinedSet = getCurrentSelection();
|
||||
assertTrue(!rsrcUndefinedSet.isEmpty());
|
||||
assertFalse(rsrcUndefinedSet.isEmpty());
|
||||
// Change to program view
|
||||
selectTreeNodeByText(tree, "Test", true);
|
||||
performAction(replaceView, provider, true);
|
||||
ProgramSelection undefinedSet = getCurrentSelection();
|
||||
assertTrue(!undefinedSet.isEmpty());
|
||||
assertFalse(undefinedSet.isEmpty());
|
||||
|
||||
// Select No Instructions.
|
||||
performAction(selectInstructionAction, provider, true);
|
||||
|
@ -396,9 +396,6 @@ public class QualifiedSelectionPluginTest extends AbstractGhidraHeadedIntegratio
|
|||
}, wait);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param instructionSet
|
||||
*/
|
||||
private void checkForInstructions(ProgramSelection instructionSet) {
|
||||
Listing listing = program.getListing();
|
||||
AddressIterator iter = instructionSet.getAddresses(true);
|
||||
|
@ -409,9 +406,6 @@ public class QualifiedSelectionPluginTest extends AbstractGhidraHeadedIntegratio
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param dataSet
|
||||
*/
|
||||
private void checkForDefinedData(ProgramSelection dataSet) {
|
||||
Listing listing = program.getListing();
|
||||
AddressIterator iter = dataSet.getAddresses(true);
|
||||
|
@ -422,9 +416,6 @@ public class QualifiedSelectionPluginTest extends AbstractGhidraHeadedIntegratio
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param undefinedSet
|
||||
*/
|
||||
private void checkForUndefined(ProgramSelection undefinedSet) {
|
||||
Listing listing = program.getListing();
|
||||
AddressIterator iter = undefinedSet.getAddresses(true);
|
||||
|
|
|
@ -169,14 +169,13 @@ public class CompareFunctionsSlowTest extends AbstractGhidraHeadedIntegrationTes
|
|||
clickComponentProvider(provider);
|
||||
|
||||
DockingActionIf openTableAction = getAction(plugin, "Add Functions To Comparison");
|
||||
performAction(openTableAction, false);
|
||||
performAction(openTableAction, provider, false);
|
||||
|
||||
Window selectWindow = waitForWindowByTitleContaining("Select Functions");
|
||||
assertNotNull(selectWindow);
|
||||
selectWindow.setVisible(false);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void testAddFunctionToExistingCompare() {
|
||||
Set<Function> functions = CompareFunctionsTestUtility.getFunctionsAsSet(foo);
|
||||
|
@ -189,10 +188,12 @@ public class CompareFunctionsSlowTest extends AbstractGhidraHeadedIntegrationTes
|
|||
assertTrue(provider.getModel().getSourceFunctions().contains(foo));
|
||||
|
||||
DockingActionIf openTableAction = getAction(plugin, "Add Functions To Comparison");
|
||||
performAction(openTableAction, false);
|
||||
performAction(openTableAction, provider, false);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
TableSelectionDialog<FunctionTableModel> chooser =
|
||||
waitForDialogComponent(TableSelectionDialog.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
GFilterTable<FunctionRowObject> table =
|
||||
(GFilterTable<FunctionRowObject>) getInstanceField("gFilterTable", chooser);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue