mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-05-27 23:17:03 +08:00
Merge remote-tracking branch 'origin/Ghidra_11.0'
This commit is contained in:
@@ -18,16 +18,11 @@ package ghidra.app.events;
|
|||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
|
|
||||||
import ghidra.framework.plugintool.PluginEvent;
|
import ghidra.framework.plugintool.PluginEvent;
|
||||||
import ghidra.framework.plugintool.ToolEventName;
|
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Event for telling a tool to open a program
|
* Event for telling a tool to close a program
|
||||||
* <p>
|
|
||||||
* This event shares a common tool-event name with the {@link OpenProgramPluginEvent}
|
|
||||||
* so that they have a single shared tool connection.
|
|
||||||
*/
|
*/
|
||||||
@ToolEventName(OpenProgramPluginEvent.TOOL_EVENT_NAME) // this allows the event to be considered for tool connection
|
|
||||||
public class CloseProgramPluginEvent extends PluginEvent {
|
public class CloseProgramPluginEvent extends PluginEvent {
|
||||||
|
|
||||||
static final String NAME = "Close Program";
|
static final String NAME = "Close Program";
|
||||||
|
|||||||
-76
@@ -1,76 +0,0 @@
|
|||||||
/* ###
|
|
||||||
* IP: GHIDRA
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package ghidra.app.events;
|
|
||||||
|
|
||||||
import ghidra.framework.plugintool.PluginEvent;
|
|
||||||
import ghidra.framework.plugintool.ToolEventName;
|
|
||||||
import ghidra.program.model.listing.Program;
|
|
||||||
import ghidra.program.util.ProgramLocation;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This plugin event class provides program location information for
|
|
||||||
* plugins that send information to two or more tools containing associated addresses.
|
|
||||||
*/
|
|
||||||
@ToolEventName(DualProgramLocationPluginEvent.NAME) // this allows the event to be considered for tool connection
|
|
||||||
public final class DualProgramLocationPluginEvent extends PluginEvent {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Name of this plugin event.
|
|
||||||
*/
|
|
||||||
public static final String NAME = "DualProgramLocation";
|
|
||||||
|
|
||||||
private ProgramLocation loc;
|
|
||||||
private String programName;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct a new DualProgramLocationPluginEvent.
|
|
||||||
* @param src the name of the plugin that generated this event.
|
|
||||||
* @param loc the ProgramLocation object that contains the new location.
|
|
||||||
* @param programName the name of the program for which the loc object refers.
|
|
||||||
*/
|
|
||||||
public DualProgramLocationPluginEvent(String src, ProgramLocation loc, String programName) {
|
|
||||||
super(src, NAME);
|
|
||||||
this.loc = loc;
|
|
||||||
this.programName = programName;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct a new DualProgramLocationPluginEvent.
|
|
||||||
* @param src the name of the plugin that generated this event.
|
|
||||||
* @param loc the ProgramLocation object that contains the new location.
|
|
||||||
* @param program the program for which the loc object refers.
|
|
||||||
*/
|
|
||||||
public DualProgramLocationPluginEvent(String src, ProgramLocation loc, Program program) {
|
|
||||||
super(src, NAME);
|
|
||||||
this.loc = loc;
|
|
||||||
this.programName = program.getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the ProgramLocation stored in this event.
|
|
||||||
*/
|
|
||||||
public ProgramLocation getLocation() {
|
|
||||||
return loc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the Program object that the location refers to.
|
|
||||||
*/
|
|
||||||
public String getProgramName() {
|
|
||||||
return programName;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -18,20 +18,14 @@ package ghidra.app.events;
|
|||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
|
|
||||||
import ghidra.framework.plugintool.PluginEvent;
|
import ghidra.framework.plugintool.PluginEvent;
|
||||||
import ghidra.framework.plugintool.ToolEventName;
|
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Event for telling a tool to open a program
|
* Event for telling a tool to open a program
|
||||||
* <p>
|
|
||||||
* This event shares a common tool-event name with the {@link OpenProgramPluginEvent}
|
|
||||||
* so that they have a single shared tool connection.
|
|
||||||
*/
|
*/
|
||||||
@ToolEventName(OpenProgramPluginEvent.TOOL_EVENT_NAME) // this allows the event to be considered for tool connection
|
|
||||||
public class OpenProgramPluginEvent extends PluginEvent {
|
public class OpenProgramPluginEvent extends PluginEvent {
|
||||||
|
|
||||||
static final String NAME = "Open Program";
|
static final String NAME = "Open Program";
|
||||||
static final String TOOL_EVENT_NAME = "Open/Close Program";
|
|
||||||
|
|
||||||
private WeakReference<Program> programRef;
|
private WeakReference<Program> programRef;
|
||||||
|
|
||||||
|
|||||||
+13
-5
@@ -20,7 +20,7 @@ import java.util.HashMap;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import ghidra.framework.data.DomainObjectFileListener;
|
import ghidra.framework.data.DomainObjectFileListener;
|
||||||
import ghidra.framework.model.DomainObject;
|
import ghidra.framework.model.*;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.util.timer.GTimerCache;
|
import ghidra.util.timer.GTimerCache;
|
||||||
|
|
||||||
@@ -66,6 +66,7 @@ class ProgramCache extends GTimerCache<ProgramLocator, Program> {
|
|||||||
program.addConsumer(this);
|
program.addConsumer(this);
|
||||||
ProgramFileListener listener = new ProgramFileListener(key);
|
ProgramFileListener listener = new ProgramFileListener(key);
|
||||||
program.addDomainFileListener(listener);
|
program.addDomainFileListener(listener);
|
||||||
|
program.addListener(listener);
|
||||||
listenerMap.put(program, listener);
|
listenerMap.put(program, listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,9 +74,10 @@ class ProgramCache extends GTimerCache<ProgramLocator, Program> {
|
|||||||
protected void valueRemoved(ProgramLocator locator, Program program) {
|
protected void valueRemoved(ProgramLocator locator, Program program) {
|
||||||
// whenever programs are removed from the cache, we need to remove the cache as a consumer
|
// whenever programs are removed from the cache, we need to remove the cache as a consumer
|
||||||
// and remove the file changed listener
|
// and remove the file changed listener
|
||||||
program.release(this);
|
|
||||||
ProgramFileListener listener = listenerMap.remove(program);
|
ProgramFileListener listener = listenerMap.remove(program);
|
||||||
program.removeDomainFileListener(listener);
|
program.removeDomainFileListener(listener);
|
||||||
|
program.removeListener(listener);
|
||||||
|
program.release(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -92,9 +94,11 @@ class ProgramCache extends GTimerCache<ProgramLocator, Program> {
|
|||||||
* DomainObjectFileListener for programs in the cache. If a program instance has its DomainFile
|
* DomainObjectFileListener for programs in the cache. If a program instance has its DomainFile
|
||||||
* changed (e.g., 'Save As' action), then the cache mapping is incorrect as it sill has the
|
* changed (e.g., 'Save As' action), then the cache mapping is incorrect as it sill has the
|
||||||
* program instance associated with its old DomainFile. So we need to add a listener to
|
* program instance associated with its old DomainFile. So we need to add a listener to
|
||||||
* recognize when this occurs. If it does, we simply remove the entry from the cache.
|
* recognize when this occurs. If it does, we simply remove the entry from the cache. Also,
|
||||||
|
* we need to remove any programs from the cache if changes are made to avoid questions about
|
||||||
|
* who is responsible for saving changed programs that only live in the cache.
|
||||||
*/
|
*/
|
||||||
class ProgramFileListener implements DomainObjectFileListener {
|
class ProgramFileListener implements DomainObjectFileListener, DomainObjectListener {
|
||||||
private ProgramLocator key;
|
private ProgramLocator key;
|
||||||
|
|
||||||
ProgramFileListener(ProgramLocator key) {
|
ProgramFileListener(ProgramLocator key) {
|
||||||
@@ -105,6 +109,10 @@ class ProgramCache extends GTimerCache<ProgramLocator, Program> {
|
|||||||
public void domainFileChanged(DomainObject object) {
|
public void domainFileChanged(DomainObject object) {
|
||||||
remove(key);
|
remove(key);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void domainObjectChanged(DomainObjectChangedEvent ev) {
|
||||||
|
remove(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-1
@@ -304,7 +304,13 @@ public class ProgramManagerPlugin extends Plugin implements ProgramManager, Opti
|
|||||||
program = programMgr.getOpenProgram(locator);
|
program = programMgr.getOpenProgram(locator);
|
||||||
if (program != null) {
|
if (program != null) {
|
||||||
program.addConsumer(consumer);
|
program.addConsumer(consumer);
|
||||||
programCache.put(locator, program);
|
if (!program.isChanged()) {
|
||||||
|
// Don't put modified programs into the cache.
|
||||||
|
// NOTE: This will prevent upgraded programs from being added to the cache
|
||||||
|
// which are already open in the tool. This could be improved if we could
|
||||||
|
// distinguish between upgrade and non-upgrade changes.
|
||||||
|
programCache.put(locator, program);
|
||||||
|
}
|
||||||
return program;
|
return program;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -341,6 +347,7 @@ public class ProgramManagerPlugin extends Plugin implements ProgramManager, Opti
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
|
programCache.clear();
|
||||||
programMgr.dispose();
|
programMgr.dispose();
|
||||||
tool.clearLastEvents();
|
tool.clearLastEvents();
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-11
@@ -66,8 +66,7 @@ class ProgramSaveManager {
|
|||||||
* the user
|
* the user
|
||||||
*/
|
*/
|
||||||
boolean canClose(Program program) {
|
boolean canClose(Program program) {
|
||||||
if (program == null ||
|
if (!isOnlyToolConsumer(program)) {
|
||||||
(program.getDomainFile().getConsumers().size() > 1 && !tool.hasToolListeners())) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (acquireSaveLock(program, "Close")) {
|
if (acquireSaveLock(program, "Close")) {
|
||||||
@@ -105,9 +104,7 @@ class ProgramSaveManager {
|
|||||||
return saveChangedPrograms(saveList);
|
return saveChangedPrograms(saveList);
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
Iterator<Program> it = lockList.iterator();
|
for (Program p : lockList) {
|
||||||
while (it.hasNext()) {
|
|
||||||
Program p = it.next();
|
|
||||||
p.unlock();
|
p.unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -378,10 +375,9 @@ class ProgramSaveManager {
|
|||||||
"The Program is currently being modified by the following actions/tasks:\n ");
|
"The Program is currently being modified by the following actions/tasks:\n ");
|
||||||
TransactionInfo t = program.getCurrentTransactionInfo();
|
TransactionInfo t = program.getCurrentTransactionInfo();
|
||||||
List<String> list = t.getOpenSubTransactions();
|
List<String> list = t.getOpenSubTransactions();
|
||||||
Iterator<String> it = list.iterator();
|
for (String element : list) {
|
||||||
while (it.hasNext()) {
|
|
||||||
buf.append("\n ");
|
buf.append("\n ");
|
||||||
buf.append(it.next());
|
buf.append(element);
|
||||||
}
|
}
|
||||||
buf.append("\n \n");
|
buf.append("\n \n");
|
||||||
buf.append("WARNING! The above task(s) should be cancelled before attempting a " +
|
buf.append("WARNING! The above task(s) should be cancelled before attempting a " +
|
||||||
@@ -412,10 +408,9 @@ class ProgramSaveManager {
|
|||||||
"The Program is currently being modified by the following actions/tasks:\n ");
|
"The Program is currently being modified by the following actions/tasks:\n ");
|
||||||
TransactionInfo t = program.getCurrentTransactionInfo();
|
TransactionInfo t = program.getCurrentTransactionInfo();
|
||||||
List<String> list = t.getOpenSubTransactions();
|
List<String> list = t.getOpenSubTransactions();
|
||||||
Iterator<String> it = list.iterator();
|
for (String element : list) {
|
||||||
while (it.hasNext()) {
|
|
||||||
buf.append("\n ");
|
buf.append("\n ");
|
||||||
buf.append(it.next());
|
buf.append(element);
|
||||||
}
|
}
|
||||||
buf.append("\n \n");
|
buf.append("\n \n");
|
||||||
buf.append(
|
buf.append(
|
||||||
|
|||||||
+7
-3
@@ -130,10 +130,14 @@ public class GhidraScriptAskMethodsTest extends AbstractGhidraHeadedIntegrationT
|
|||||||
public void testAskProgram_SCR8486() throws Exception {
|
public void testAskProgram_SCR8486() throws Exception {
|
||||||
createScript();
|
createScript();
|
||||||
|
|
||||||
Program[] container = new Program[1];
|
AtomicReference<Program> container = new AtomicReference<>();
|
||||||
runSwing(() -> {
|
runSwing(() -> {
|
||||||
try {
|
try {
|
||||||
container[0] = script.askProgram("Test - Pick Program");
|
Program p = script.askProgram("Test - Pick Program");
|
||||||
|
container.set(p);
|
||||||
|
if (p != null) {
|
||||||
|
p.release(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ioe) {
|
catch (Exception ioe) {
|
||||||
failWithException("Caught unexepected during askProgram()", ioe);
|
failWithException("Caught unexepected during askProgram()", ioe);
|
||||||
@@ -146,7 +150,7 @@ public class GhidraScriptAskMethodsTest extends AbstractGhidraHeadedIntegrationT
|
|||||||
runSwing(() -> okButton.doClick());
|
runSwing(() -> okButton.doClick());
|
||||||
|
|
||||||
// this test will fail if we encountered an exception
|
// this test will fail if we encountered an exception
|
||||||
assertNull(container[0]);
|
assertNull(container.get());
|
||||||
|
|
||||||
runSwing(() -> dtd.close());
|
runSwing(() -> dtd.close());
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user