mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 09:49:23 +02:00
Merge remote-tracking branch 'origin/GP-5737_ryanmkurtz_script-output--SQUASHED'
This commit is contained in:
commit
c224c5d44e
26 changed files with 359 additions and 206 deletions
|
@ -15,8 +15,7 @@
|
|||
*/
|
||||
package ghidra.app.plugin.core.script;
|
||||
|
||||
import ghidra.app.script.GhidraScript;
|
||||
import ghidra.app.script.GhidraState;
|
||||
import ghidra.app.script.*;
|
||||
import ghidra.app.services.ConsoleService;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.util.Msg;
|
||||
|
@ -44,7 +43,7 @@ class RunScriptTask extends Task {
|
|||
Thread.currentThread().setName(scriptName);
|
||||
|
||||
console.addMessage(scriptName, "Running...");
|
||||
script.execute(currentState, monitor, console.getStdOut());
|
||||
script.execute(currentState, new ScriptControls(console, monitor));
|
||||
console.addMessage(scriptName, "Finished!");
|
||||
}
|
||||
catch (CancelledException e) {
|
||||
|
|
|
@ -37,7 +37,8 @@ import ghidra.app.plugin.core.analysis.AnalysisWorker;
|
|||
import ghidra.app.plugin.core.analysis.AutoAnalysisManager;
|
||||
import ghidra.app.plugin.core.colorizer.ColorizingService;
|
||||
import ghidra.app.plugin.core.table.TableComponentProvider;
|
||||
import ghidra.app.services.*;
|
||||
import ghidra.app.services.GoToService;
|
||||
import ghidra.app.services.ProgramManager;
|
||||
import ghidra.app.tablechooser.TableChooserDialog;
|
||||
import ghidra.app.tablechooser.TableChooserExecutor;
|
||||
import ghidra.app.util.demangler.DemangledObject;
|
||||
|
@ -142,6 +143,8 @@ public abstract class GhidraScript extends FlatProgramAPI {
|
|||
protected ResourceFile sourceFile;
|
||||
protected GhidraState state;
|
||||
protected PrintWriter writer;
|
||||
protected PrintWriter errorWriter;
|
||||
protected boolean decorateOutput;
|
||||
protected Address currentAddress;
|
||||
protected ProgramLocation currentLocation;
|
||||
protected ProgramSelection currentSelection;
|
||||
|
@ -192,18 +195,47 @@ public abstract class GhidraScript extends FlatProgramAPI {
|
|||
|
||||
/**
|
||||
* Set the context for this script.
|
||||
* <p>
|
||||
* This method will use the given {@link PrintWriter} for both {@code stdout} and
|
||||
* {@code stderr}.
|
||||
*
|
||||
* @param state state object
|
||||
* @param monitor the monitor to use during run
|
||||
* @param writer the target of script "print" statements
|
||||
* @param writer the target of script "print" statements (may be null)
|
||||
* @deprecated Use {@link #set(GhidraState)} or {@link #set(GhidraState, ScriptControls)}
|
||||
* instead
|
||||
*/
|
||||
@Deprecated(since = "11.5")
|
||||
public final void set(GhidraState state, TaskMonitor monitor, PrintWriter writer) {
|
||||
set(state, new ScriptControls(writer, writer, monitor));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the context for this script.
|
||||
*
|
||||
* @param state the new state
|
||||
*/
|
||||
public final void set(GhidraState state) {
|
||||
this.state = state;
|
||||
this.monitor = monitor;
|
||||
this.writer = writer;
|
||||
loadVariablesFromState();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the state and controls for this script.
|
||||
*
|
||||
* @param state the new state
|
||||
* @param controls new the controls
|
||||
*/
|
||||
public final void set(GhidraState state, ScriptControls controls) {
|
||||
this.state = state;
|
||||
loadVariablesFromState();
|
||||
|
||||
this.writer = controls.getWriter();
|
||||
this.errorWriter = controls.getErrorWriter();
|
||||
this.decorateOutput = controls.shouldDecorateOutput();
|
||||
this.monitor = controls.getMonitor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether the user's previously selected values should be used when showing the various
|
||||
* {@code ask} methods. This is true by default, meaning that previous choices will be shown
|
||||
|
@ -225,17 +257,51 @@ public abstract class GhidraScript extends FlatProgramAPI {
|
|||
|
||||
/**
|
||||
* Execute/run script and {@link #doCleanup} afterwards.
|
||||
* <p>
|
||||
* This method will use the given {@link PrintWriter} for both {@code stdout} and
|
||||
* {@code stderr}.
|
||||
*
|
||||
* @param runState state object
|
||||
* @param runMonitor the monitor to use during run
|
||||
* @param runWriter the target of script "print" statements
|
||||
* @param runWriter the target of script "print" statements (may be null)
|
||||
* @throws Exception if the script excepts
|
||||
* @deprecated Use {@link #execute(GhidraState, ScriptControls)} instead to also set a
|
||||
* {@link PrintWriter} for {@code stderr}
|
||||
*/
|
||||
@Deprecated(since = "11.5")
|
||||
public final void execute(GhidraState runState, TaskMonitor runMonitor, PrintWriter runWriter)
|
||||
throws Exception {
|
||||
execute(runState, new ScriptControls(runWriter, runWriter, runMonitor));
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute/run script with the given {@link GhidraState state} and current
|
||||
* {@link ScriptControls controls} and {@link #doCleanup} afterwards.
|
||||
* <p>
|
||||
* NOTE: This method is not intended to be called by script writers.
|
||||
*
|
||||
* @param runState state object
|
||||
* @throws Exception if the script excepts
|
||||
*/
|
||||
public final void execute(GhidraState runState, TaskMonitor runMonitor, PrintWriter runWriter)
|
||||
public final void execute(GhidraState runState) throws Exception {
|
||||
execute(runState, new ScriptControls(writer, errorWriter, decorateOutput, monitor));
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute/run script with the given {@link GhidraState state} and
|
||||
* {@link ScriptControls controls} and {@link #doCleanup} afterwards.
|
||||
* <p>
|
||||
* NOTE: This method is not intended to be called by script writers.
|
||||
*
|
||||
* @param runState state object
|
||||
* @param runControls controls object
|
||||
* @throws Exception if the script excepts
|
||||
*/
|
||||
public final void execute(GhidraState runState, ScriptControls runControls)
|
||||
throws Exception {
|
||||
boolean success = false;
|
||||
try {
|
||||
doExecute(runState, runMonitor, runWriter);
|
||||
doExecute(runState, runControls);
|
||||
success = true;
|
||||
}
|
||||
finally {
|
||||
|
@ -243,11 +309,13 @@ public abstract class GhidraScript extends FlatProgramAPI {
|
|||
}
|
||||
}
|
||||
|
||||
private void doExecute(GhidraState runState, TaskMonitor runMonitor, PrintWriter runWriter)
|
||||
private void doExecute(GhidraState runState, ScriptControls runControls)
|
||||
throws Exception {
|
||||
this.state = runState;
|
||||
this.monitor = runMonitor;
|
||||
this.writer = runWriter;
|
||||
this.writer = runControls.getWriter();
|
||||
this.errorWriter = runControls.getErrorWriter();
|
||||
this.decorateOutput = runControls.shouldDecorateOutput();
|
||||
this.monitor = runControls.getMonitor();
|
||||
loadVariablesFromState();
|
||||
|
||||
loadPropertiesFile();
|
||||
|
@ -260,7 +328,8 @@ public abstract class GhidraScript extends FlatProgramAPI {
|
|||
executeNormal();
|
||||
}
|
||||
else {
|
||||
executeAsAnalysisWorker(scriptAnalysisMode == AnalysisMode.SUSPENDED, runMonitor);
|
||||
executeAsAnalysisWorker(scriptAnalysisMode == AnalysisMode.SUSPENDED,
|
||||
runControls.getMonitor());
|
||||
}
|
||||
updateStateFromVariables();
|
||||
}
|
||||
|
@ -844,7 +913,7 @@ public abstract class GhidraScript extends FlatProgramAPI {
|
|||
"': unable to run this script type.");
|
||||
}
|
||||
|
||||
GhidraScript script = provider.getScriptInstance(scriptSource, writer);
|
||||
GhidraScript script = provider.getScriptInstance(scriptSource, errorWriter);
|
||||
script.setScriptArgs(scriptArguments);
|
||||
|
||||
if (potentialPropertiesFileLocs.size() > 0) {
|
||||
|
@ -855,7 +924,7 @@ public abstract class GhidraScript extends FlatProgramAPI {
|
|||
updateStateFromVariables();
|
||||
}
|
||||
|
||||
script.execute(scriptState, monitor, writer);
|
||||
script.execute(scriptState);
|
||||
|
||||
if (scriptState == state) {
|
||||
loadVariablesFromState();
|
||||
|
@ -949,74 +1018,44 @@ public abstract class GhidraScript extends FlatProgramAPI {
|
|||
}
|
||||
|
||||
/**
|
||||
* Prints a newline.
|
||||
*
|
||||
* @see #printf(String, Object...)
|
||||
* Prints a newline to this script's {@code stdout} {@link PrintWriter}, which is set by
|
||||
* {@link #set(GhidraState, ScriptControls)}.
|
||||
* <p>
|
||||
* Additionally, the newline is written to Ghidra's log.
|
||||
*/
|
||||
public void println() {
|
||||
println("");
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the message to the console followed by a line feed.
|
||||
* Prints the {@link #decorateOutput optionally} {@link #decorate(String) decorated} message
|
||||
* followed by a line feed to this script's {@code stdout} {@link PrintWriter}, which is set by
|
||||
* {@link #set(GhidraState, ScriptControls)}.
|
||||
* <p>
|
||||
* Additionally, the always {@link #decorate(String) decorated} message is written to Ghidra's
|
||||
* log.
|
||||
*
|
||||
* @param message the message to print
|
||||
* @see #printf(String, Object...)
|
||||
*/
|
||||
public void println(String message) {
|
||||
String decoratedMessage = getScriptName() + "> " + message;
|
||||
String decoratedMessage = decorate(message);
|
||||
|
||||
// note: use a Message object to facilitate script message log filtering
|
||||
Msg.info(GhidraScript.class, new ScriptMessage(decoratedMessage));
|
||||
|
||||
if (isRunningHeadless()) {
|
||||
return;
|
||||
}
|
||||
|
||||
PluginTool tool = state.getTool();
|
||||
if (tool == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
ConsoleService console = tool.getService(ConsoleService.class);
|
||||
if (console == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
console.addMessage(getScriptName(), message);
|
||||
}
|
||||
catch (Exception e) {
|
||||
Msg.error(this, "Script Message: " + message, e);
|
||||
if (writer != null) {
|
||||
writer.println(decorateOutput ? decoratedMessage : message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A convenience method to print a formatted String using Java's <code>printf</code>
|
||||
* feature, which is similar to that of the C programming language.
|
||||
* For a full description on Java's
|
||||
* <code>printf</code> usage, see {@link java.util.Formatter}.
|
||||
* Prints the undecorated {@link java.util.Formatter formatted message} to this script's
|
||||
* {@code stdout} {@link PrintWriter}, which is set by
|
||||
* {@link #set(GhidraState, ScriptControls)}.
|
||||
* <p>
|
||||
* For examples, see the included <code>FormatExampleScript</code>.
|
||||
* <p>
|
||||
* <b><u>Note:</u> This method will not:</b>
|
||||
* <ul>
|
||||
* <li><b>print out the name of the script, as does {@link #println(String)}</b></li>
|
||||
* <li><b>print a newline</b></li>
|
||||
* </ul>
|
||||
* If you would like the name of the script to precede you message, then you must add that
|
||||
* yourself. The {@link #println(String)} does this via the following code:
|
||||
* <pre>
|
||||
* String messageWithSource = getScriptName() + "> " + message;
|
||||
* </pre>
|
||||
* Additionally, the undecorated formatted message is written to Ghidra's log.
|
||||
*
|
||||
* @param message the message to format
|
||||
* @param args formatter arguments (see above)
|
||||
*
|
||||
* @see String#format(String, Object...)
|
||||
* @see java.util.Formatter
|
||||
* @see #print(String)
|
||||
* @see #println(String)
|
||||
* @param args C-like {@code printf} formatter arguments
|
||||
*/
|
||||
public void printf(String message, Object... args) {
|
||||
String formattedString = String.format(message, args);
|
||||
|
@ -1024,20 +1063,12 @@ public abstract class GhidraScript extends FlatProgramAPI {
|
|||
}
|
||||
|
||||
/**
|
||||
* Prints the message to the console - no line feed
|
||||
* Prints the undecorated message with no newline to this script's {@code stdout}
|
||||
* {@link PrintWriter}, which is set by {@link #set(GhidraState, ScriptControls)}.
|
||||
* <p>
|
||||
* <b><u>Note:</u> This method will not print out the name of the script,
|
||||
* as does {@link #println(String)}
|
||||
* </b>
|
||||
* <p>
|
||||
* If you would like the name of the script to precede you message, then you must add that
|
||||
* yourself. The {@link #println(String)} does this via the following code:
|
||||
* <pre>
|
||||
* String messageWithSource = getScriptName() + "> " + message;
|
||||
* </pre>
|
||||
* Additionally, the undecorated message is written to Ghidra's log.
|
||||
*
|
||||
* @param message the message to print
|
||||
* @see #printf(String, Object...)
|
||||
*/
|
||||
public void print(String message) {
|
||||
// clients using print may add their own newline, which interferes with our logging,
|
||||
|
@ -1051,57 +1082,41 @@ public abstract class GhidraScript extends FlatProgramAPI {
|
|||
}
|
||||
Msg.info(GhidraScript.class, new ScriptMessage(strippedMessage));
|
||||
|
||||
if (isRunningHeadless()) {
|
||||
return;
|
||||
}
|
||||
|
||||
PluginTool tool = state.getTool();
|
||||
if (tool == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
ConsoleService console = tool.getService(ConsoleService.class);
|
||||
if (console == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
console.print(message);
|
||||
}
|
||||
catch (Exception e) {
|
||||
Msg.error(this, "Script Message: " + message, e);
|
||||
if (writer != null) {
|
||||
writer.print(message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the error message to the console followed by a line feed.
|
||||
* Prints the {@link #decorateOutput optionally} {@link #decorate(String) decorated} message
|
||||
* followed by a line feed to this script's {@code stderr} {@link PrintWriter}, which is set by
|
||||
* {@link #set(GhidraState, ScriptControls)}.
|
||||
* <p>
|
||||
* Additionally, the always {@link #decorate(String) decorated} message is written to Ghidra's
|
||||
* log as an error.
|
||||
*
|
||||
* @param message the error message to print
|
||||
* @param message the message to print
|
||||
*/
|
||||
public void printerr(String message) {
|
||||
String msgMessage = getScriptName() + "> " + message;
|
||||
Msg.error(GhidraScript.class, new ScriptMessage(msgMessage));
|
||||
String decoratedMessage = decorate(message);
|
||||
|
||||
if (isRunningHeadless()) {
|
||||
return;
|
||||
}
|
||||
Msg.error(GhidraScript.class, new ScriptMessage(decoratedMessage));
|
||||
|
||||
PluginTool tool = state.getTool();
|
||||
if (tool == null) {
|
||||
return;
|
||||
if (errorWriter != null) {
|
||||
errorWriter.println(decorateOutput ? decoratedMessage : message);
|
||||
}
|
||||
}
|
||||
|
||||
ConsoleService console = tool.getService(ConsoleService.class);
|
||||
if (console == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
console.addErrorMessage(getScriptName(), message);
|
||||
}
|
||||
catch (Exception e) {
|
||||
Msg.error(this, "Script Message: " + message, e);
|
||||
}
|
||||
/**
|
||||
* Decorates the given message, which is used by the {@link GhidraScript} "print" methods during
|
||||
* logging and {@link #decorateOutput optionally} when outputting to the
|
||||
* {@link PrintWriter}s.
|
||||
*
|
||||
* @param message The message to decorate
|
||||
* @return The decorated message
|
||||
*/
|
||||
protected String decorate(String message) {
|
||||
return getScriptName() + "> " + message;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -3685,7 +3700,7 @@ public abstract class GhidraScript extends FlatProgramAPI {
|
|||
pm.openProgram(program);
|
||||
end(true);
|
||||
GhidraState newState = new GhidraState(tool, tool.getProject(), program, null, null, null);
|
||||
set(newState, monitor, writer);
|
||||
set(newState);
|
||||
start();
|
||||
}
|
||||
|
||||
|
|
|
@ -87,12 +87,12 @@ public abstract class GhidraScriptProvider
|
|||
* Returns a GhidraScript instance for the specified source file.
|
||||
*
|
||||
* @param sourceFile the source file
|
||||
* @param writer the print writer to write warning/error messages. If the error prevents
|
||||
* @param errorWriter the print writer to write warning/error messages. If the error prevents
|
||||
* success, throw an exception instead. The caller will print the error.
|
||||
* @return a GhidraScript instance for the specified source file
|
||||
* @throws GhidraScriptLoadException when the script instance cannot be created
|
||||
*/
|
||||
public abstract GhidraScript getScriptInstance(ResourceFile sourceFile, PrintWriter writer)
|
||||
public abstract GhidraScript getScriptInstance(ResourceFile sourceFile, PrintWriter errorWriter)
|
||||
throws GhidraScriptLoadException;
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,133 @@
|
|||
/* ###
|
||||
* 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.script;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
import ghidra.app.plugin.core.interpreter.InterpreterConsole;
|
||||
import ghidra.app.services.ConsoleService;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
/**
|
||||
* Class to encapsulate {@link GhidraScript} control mechanisms such as stdout/stderr writers and
|
||||
* other feedback to the user
|
||||
*/
|
||||
public class ScriptControls {
|
||||
|
||||
/**
|
||||
* A {@link ScriptControls} that does nothing
|
||||
*/
|
||||
public static final ScriptControls NONE =
|
||||
new ScriptControls(null, null, false, TaskMonitor.DUMMY);
|
||||
|
||||
private PrintWriter writer;
|
||||
private PrintWriter errorWriter;
|
||||
private boolean decorateOutput;
|
||||
private TaskMonitor monitor;
|
||||
|
||||
/**
|
||||
* Creates a new {@link ScriptControls}
|
||||
*
|
||||
* @param writer The target of script "print" statements (may be null)
|
||||
* @param errorWriter The target of script "printerr" statements (may be null)
|
||||
* @param decorateOutput True to decorate the writer output with a script name prefix;
|
||||
* otherwise, false (see {@link GhidraScript#decorate(String)}
|
||||
* @param monitor A cancellable monitor
|
||||
*/
|
||||
public ScriptControls(PrintWriter writer, PrintWriter errorWriter, boolean decorateOutput,
|
||||
TaskMonitor monitor) {
|
||||
this.writer = writer;
|
||||
this.errorWriter = errorWriter;
|
||||
this.decorateOutput = decorateOutput;
|
||||
this.monitor = monitor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link ScriptControls} with no decorated output
|
||||
*
|
||||
* @param writer The target of script "print" statements (may be null)
|
||||
* @param errorWriter The target of script "printerr" statements (may be null)
|
||||
* otherwise, false (see {@link GhidraScript#decorate(String)}
|
||||
* @param monitor A cancellable monitor
|
||||
*/
|
||||
public ScriptControls(PrintWriter writer, PrintWriter errorWriter, TaskMonitor monitor) {
|
||||
this(writer, errorWriter, false, monitor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link ScriptControls} with no decorated output
|
||||
*
|
||||
* @param stream The target of script "print" statements (may be null)
|
||||
* @param errorStream The target of script "printerr" statements (may be null)
|
||||
* otherwise, false (see {@link GhidraScript#decorate(String)}
|
||||
* @param monitor A cancellable monitor
|
||||
*/
|
||||
public ScriptControls(OutputStream stream, OutputStream errorStream, TaskMonitor monitor) {
|
||||
this(new PrintWriter(stream, true), new PrintWriter(errorStream, true), false, monitor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link ScriptControls} with no decorated output
|
||||
*
|
||||
* @param console The target of script "print" and "printerr" statements
|
||||
* @param monitor A cancellable monitor
|
||||
*/
|
||||
public ScriptControls(ConsoleService console, TaskMonitor monitor) {
|
||||
this(console.getStdOut(), console.getStdErr(), monitor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link ScriptControls} with no decorated output
|
||||
*
|
||||
* @param console The target of script "print" and "printerr" statements
|
||||
* @param monitor A cancellable monitor
|
||||
*/
|
||||
public ScriptControls(InterpreterConsole console, TaskMonitor monitor) {
|
||||
this(console.getStdOut(), console.getStdErr(), monitor);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the target of script "print" statements (may be null)}
|
||||
*/
|
||||
public PrintWriter getWriter() {
|
||||
return writer;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the target of script "printerr" statements (may be null)}
|
||||
*/
|
||||
public PrintWriter getErrorWriter() {
|
||||
return errorWriter;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return True to decorate the writer output with a script name prefix; otherwise, false}
|
||||
*
|
||||
* @see GhidraScript#decorate(String)
|
||||
*/
|
||||
public boolean shouldDecorateOutput() {
|
||||
return decorateOutput;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return A cancellable monitor}
|
||||
*/
|
||||
public TaskMonitor getMonitor() {
|
||||
return monitor;
|
||||
}
|
||||
|
||||
}
|
|
@ -77,10 +77,9 @@ public class GhidraScriptRunner implements GhidraLaunchable {
|
|||
srcFile != null ? srcFile.getAbsolutePath() : (script.getClass().getName() + ".class");
|
||||
|
||||
try {
|
||||
PrintWriter writer = new PrintWriter(System.out);
|
||||
Msg.info(this, "SCRIPT: " + scriptName);
|
||||
script.execute(scriptState, TaskMonitor.DUMMY, writer);
|
||||
writer.flush();
|
||||
ScriptControls controls = new ScriptControls(System.out, System.err, TaskMonitor.DUMMY);
|
||||
script.execute(scriptState, controls);
|
||||
}
|
||||
catch (Exception exc) {
|
||||
Program prog = scriptState.getCurrentProgram();
|
||||
|
@ -107,8 +106,8 @@ public class GhidraScriptRunner implements GhidraLaunchable {
|
|||
"ensure you have installed the necessary plugin.");
|
||||
}
|
||||
|
||||
PrintWriter writer = new PrintWriter(System.out);
|
||||
GhidraScript foundScript = provider.getScriptInstance(scriptSourceFile, writer);
|
||||
PrintWriter errWriter = new PrintWriter(System.err);
|
||||
GhidraScript foundScript = provider.getScriptInstance(scriptSourceFile, errWriter);
|
||||
|
||||
if (propertiesFilePath != null) {
|
||||
// Get basename, assume that it ends in .java, since we've already covered the
|
||||
|
|
|
@ -583,10 +583,11 @@ public class HeadlessAnalyzer {
|
|||
srcFile != null ? srcFile.getAbsolutePath() : (script.getClass().getName() + ".class");
|
||||
|
||||
try {
|
||||
PrintWriter writer = new PrintWriter(System.out);
|
||||
Msg.info(this, "SCRIPT: " + scriptName);
|
||||
script.execute(scriptState, TaskMonitor.DUMMY, writer);
|
||||
writer.flush();
|
||||
|
||||
// Execute the script, but don't directly write to stdout or stderr. The headless
|
||||
// analyzer only uses the logging mechanism to get output to the user.
|
||||
script.execute(scriptState, ScriptControls.NONE);
|
||||
}
|
||||
catch (Exception exc) {
|
||||
String logErrorMsg = "REPORT SCRIPT ERROR: ";
|
||||
|
@ -908,8 +909,8 @@ public class HeadlessAnalyzer {
|
|||
|
||||
// GhidraScriptProvider case
|
||||
GhidraScriptProvider provider = GhidraScriptUtil.getProvider(currScriptFile);
|
||||
PrintWriter writer = new PrintWriter(System.out);
|
||||
currScript = provider.getScriptInstance(currScriptFile, writer);
|
||||
PrintWriter errWriter = new PrintWriter(System.err);
|
||||
currScript = provider.getScriptInstance(currScriptFile, errWriter);
|
||||
currScript.setScriptArgs(scriptArgs);
|
||||
|
||||
if (options.propertiesFilePaths.size() > 0) {
|
||||
|
|
|
@ -405,7 +405,7 @@ public abstract class HeadlessScript extends GhidraScript {
|
|||
"': unable to run this script type.");
|
||||
}
|
||||
|
||||
GhidraScript script = provider.getScriptInstance(scriptSource, writer);
|
||||
GhidraScript script = provider.getScriptInstance(scriptSource, errorWriter);
|
||||
isHeadlessScript = script instanceof HeadlessScript ? true : false;
|
||||
|
||||
if (potentialPropertiesFileLocs.size() > 0) {
|
||||
|
@ -423,7 +423,7 @@ public abstract class HeadlessScript extends GhidraScript {
|
|||
|
||||
script.setScriptArgs(scriptArguments);
|
||||
|
||||
script.execute(scriptState, monitor, writer);
|
||||
script.execute(scriptState);
|
||||
|
||||
if (scriptState == state) {
|
||||
loadVariablesFromState();
|
||||
|
|
|
@ -557,18 +557,18 @@ public class TestEnv {
|
|||
}
|
||||
|
||||
JavaScriptProvider scriptProvider = new JavaScriptProvider();
|
||||
PrintWriter writer = new PrintWriter(System.out);
|
||||
PrintWriter errWriter = new PrintWriter(System.err);
|
||||
ResourceFile resourceFile = new ResourceFile(scriptFile);
|
||||
GhidraScript script = null;
|
||||
try {
|
||||
script = scriptProvider.getScriptInstance(resourceFile, writer);
|
||||
script = scriptProvider.getScriptInstance(resourceFile, errWriter);
|
||||
}
|
||||
catch (GhidraScriptLoadException e) {
|
||||
Msg.error(TestEnv.class, "Problem creating script", e);
|
||||
|
||||
}
|
||||
if (script == null) {
|
||||
writer.flush();
|
||||
errWriter.flush();
|
||||
throw new RuntimeException("Failed to compile script " + scriptFile.getAbsolutePath());
|
||||
}
|
||||
|
||||
|
|
|
@ -1610,16 +1610,14 @@ public abstract class AbstractGhidraScriptMgrPluginTest
|
|||
}
|
||||
|
||||
protected class SpyConsole extends ConsoleComponentProvider {
|
||||
protected StringBuffer apiBuffer;
|
||||
|
||||
protected StringWriter outBuffer = new StringWriter();
|
||||
protected StringWriter errBuffer = new StringWriter();
|
||||
protected PrintWriter out = new PrintWriter(outBuffer);
|
||||
protected PrintWriter err = new PrintWriter(errBuffer);
|
||||
protected PrintWriter out = new PrintWriter(outBuffer, true);
|
||||
protected PrintWriter err = new PrintWriter(errBuffer, true);
|
||||
|
||||
SpyConsole() {
|
||||
super(plugin.getTool(), "Spy Console");
|
||||
this.apiBuffer = new StringBuffer();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1633,25 +1631,24 @@ public abstract class AbstractGhidraScriptMgrPluginTest
|
|||
}
|
||||
|
||||
void clear() {
|
||||
apiBuffer = new StringBuffer();
|
||||
outBuffer = new StringWriter();
|
||||
errBuffer = new StringWriter();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void println(String msg) {
|
||||
apiBuffer.append(msg).append('\n');
|
||||
out.println(msg);
|
||||
Msg.trace(this, "Spy Script Console - println(): " + msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addMessage(String originator, String msg) {
|
||||
apiBuffer.append(msg).append('\n');
|
||||
out.println(msg);
|
||||
Msg.trace(this, "Spy Script Console - addMessage(): " + msg);
|
||||
}
|
||||
|
||||
String getApiOutput() {
|
||||
return apiBuffer.toString();
|
||||
return outBuffer.toString();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -118,7 +118,7 @@ public class BundleStatusManagerTest extends AbstractGhidraScriptMgrPluginTest {
|
|||
//@formatter:off
|
||||
final String EXPECTED_OUTPUT =
|
||||
TEST_SCRIPT_NAME+".java> Running...\n" +
|
||||
TEST_SCRIPT_NAME+".java> Hello from pack2.Klass2\n" +
|
||||
"Hello from pack2.Klass2\n" +
|
||||
TEST_SCRIPT_NAME+".java> Finished!\n";
|
||||
//@formatter:on
|
||||
final File dir1 = new File(getTestDirectoryPath() + "/test_scripts1");
|
||||
|
|
|
@ -54,7 +54,7 @@ public class GhidraScriptMgrPlugin2Test extends AbstractGhidraScriptMgrPluginTes
|
|||
|
||||
String consoleText = getConsoleText();
|
||||
assertTrue("ConsoleText was \"" + consoleText + "\".",
|
||||
consoleText.indexOf("> Hello World") >= 0);
|
||||
consoleText.indexOf("Hello World") >= 0);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -100,7 +100,7 @@ public class GhidraScriptMgrPlugin3Test extends AbstractGhidraScriptMgrPluginTes
|
|||
String scriptOutput = runSelectedScript(script.getName());
|
||||
|
||||
assertTrue("Script output not generated",
|
||||
scriptOutput.contains("> new scripts are neato!"));
|
||||
scriptOutput.contains("new scripts are neato!"));
|
||||
assertFalse("Script output has value from previous test run - did script not get deleted?",
|
||||
scriptOutput.contains("Value == 3368601"));
|
||||
|
||||
|
@ -135,7 +135,7 @@ public class GhidraScriptMgrPlugin3Test extends AbstractGhidraScriptMgrPluginTes
|
|||
String updatedScriptOutput = runSelectedScript(script.getName());
|
||||
|
||||
assertTrue("Script output not updated with new script contents - did recompile work?",
|
||||
StringUtilities.containsAll(updatedScriptOutput, "> new scripts are neato!",
|
||||
StringUtilities.containsAll(updatedScriptOutput, "new scripts are neato!",
|
||||
"Value == 3368601"));
|
||||
|
||||
deleteScriptThroughUI();
|
||||
|
|
|
@ -42,7 +42,6 @@ import ghidra.program.model.listing.Program;
|
|||
import ghidra.program.util.ProgramLocation;
|
||||
import ghidra.test.AbstractGhidraHeadedIntegrationTest;
|
||||
import ghidra.test.TestEnv;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
import utilities.util.FileUtilities;
|
||||
|
||||
public class GhidraScriptAskMethodsTest extends AbstractGhidraHeadedIntegrationTest {
|
||||
|
@ -902,7 +901,7 @@ public class GhidraScriptAskMethodsTest extends AbstractGhidraHeadedIntegrationT
|
|||
// test stub
|
||||
}
|
||||
};
|
||||
script.set(state, TaskMonitor.DUMMY, null);
|
||||
script.set(state, ScriptControls.NONE);
|
||||
|
||||
URL url = GhidraScriptTest.class.getResource("GhidraScriptAsk.properties");
|
||||
assertNotNull("Test cannot run without properties file!", url);
|
||||
|
|
|
@ -31,7 +31,6 @@ import ghidra.program.model.scalar.Scalar;
|
|||
import ghidra.program.model.symbol.*;
|
||||
import ghidra.program.util.ProgramLocation;
|
||||
import ghidra.test.*;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
public class GhidraScriptRealProgramTest extends AbstractGhidraHeadedIntegrationTest {
|
||||
|
||||
|
@ -399,7 +398,7 @@ public class GhidraScriptRealProgramTest extends AbstractGhidraHeadedIntegration
|
|||
// test stub
|
||||
}
|
||||
};
|
||||
script.set(state, TaskMonitor.DUMMY, null);
|
||||
script.set(state, ScriptControls.NONE);
|
||||
return script;
|
||||
}
|
||||
|
||||
|
|
|
@ -44,7 +44,6 @@ import ghidra.test.AbstractGhidraHeadedIntegrationTest;
|
|||
import ghidra.test.TestEnv;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.exception.AssertException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
public class GhidraScriptTest extends AbstractGhidraHeadedIntegrationTest {
|
||||
|
||||
|
@ -773,7 +772,7 @@ public class GhidraScriptTest extends AbstractGhidraHeadedIntegrationTest {
|
|||
// test stub
|
||||
}
|
||||
};
|
||||
script.set(state, TaskMonitor.DUMMY, null);
|
||||
script.set(state, ScriptControls.NONE);
|
||||
return script;
|
||||
}
|
||||
|
||||
|
|
|
@ -329,8 +329,8 @@ public class ShowConstantUse extends GhidraScript {
|
|||
ResourceFile scriptSource = GhidraScriptUtil.findScriptByName(name);
|
||||
if (scriptSource != null) {
|
||||
GhidraScriptProvider provider = GhidraScriptUtil.getProvider(scriptSource);
|
||||
GhidraScript script = provider.getScriptInstance(scriptSource, writer);
|
||||
script.execute(scriptState, monitor, writer);
|
||||
GhidraScript script = provider.getScriptInstance(scriptSource, errorWriter);
|
||||
script.execute(scriptState);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,8 +20,7 @@ import java.nio.file.Path;
|
|||
|
||||
import docking.widgets.filechooser.GhidraFileChooser;
|
||||
import docking.widgets.filechooser.GhidraFileChooserMode;
|
||||
import ghidra.app.script.GhidraScript;
|
||||
import ghidra.app.script.GhidraState;
|
||||
import ghidra.app.script.*;
|
||||
import ghidra.app.services.ConsoleService;
|
||||
import ghidra.framework.options.ToolOptions;
|
||||
import ghidra.framework.plugintool.PluginTool;
|
||||
|
@ -72,7 +71,8 @@ public class RunPCodeExportScriptTask extends Task {
|
|||
script.setScriptArgs(new String[] { facts_directory });
|
||||
|
||||
console.addMessage(scriptName, "Running...");
|
||||
script.execute(currentState, monitor, console.getStdOut());
|
||||
script.execute(currentState,
|
||||
new ScriptControls(console.getStdOut(), console.getStdErr(), false, monitor));
|
||||
console.addMessage(scriptName, "Finished!");
|
||||
}
|
||||
catch (CancelledException e) {
|
||||
|
|
|
@ -34,6 +34,7 @@ import ghidra.app.plugin.ProgramPlugin;
|
|||
import ghidra.app.plugin.core.console.CodeCompletion;
|
||||
import ghidra.app.plugin.core.interpreter.*;
|
||||
import ghidra.app.script.GhidraState;
|
||||
import ghidra.app.script.ScriptControls;
|
||||
import ghidra.framework.options.OptionsChangeListener;
|
||||
import ghidra.framework.options.ToolOptions;
|
||||
import ghidra.framework.plugintool.PluginInfo;
|
||||
|
@ -232,7 +233,7 @@ public class JythonPlugin extends ProgramPlugin
|
|||
interactiveScript.set(
|
||||
new GhidraState(tool, tool.getProject(), getCurrentProgram(), getProgramLocation(),
|
||||
getProgramSelection(), getProgramHighlight()),
|
||||
interactiveTaskMonitor, new PrintWriter(getConsole().getStdOut()));
|
||||
new ScriptControls(console, interactiveTaskMonitor));
|
||||
interpreter.injectScriptHierarchy(interactiveScript);
|
||||
interactiveTaskMonitor = new JythonInteractiveTaskMonitor(console.getStdOut());
|
||||
|
||||
|
@ -288,7 +289,7 @@ public class JythonPlugin extends ProgramPlugin
|
|||
interactiveScript.set(
|
||||
new GhidraState(tool, tool.getProject(), currentProgram, currentLocation,
|
||||
currentSelection, currentHighlight),
|
||||
interactiveTaskMonitor, console.getOutWriter());
|
||||
new ScriptControls(console, interactiveTaskMonitor));
|
||||
|
||||
return interpreter.getCommandCompletions(cmd, includeBuiltins, caretPos);
|
||||
}
|
||||
|
@ -377,7 +378,7 @@ public class JythonPlugin extends ProgramPlugin
|
|||
}
|
||||
|
||||
public JythonInteractiveTaskMonitor(OutputStream stdout) {
|
||||
this(new PrintWriter(stdout));
|
||||
this(new PrintWriter(stdout, true));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -16,14 +16,15 @@
|
|||
package ghidra.jython;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import org.python.core.PyException;
|
||||
|
||||
import db.Transaction;
|
||||
import generic.jar.ResourceFile;
|
||||
import ghidra.app.plugin.core.interpreter.InterpreterConsole;
|
||||
import ghidra.app.script.GhidraState;
|
||||
import ghidra.app.script.ScriptControls;
|
||||
import ghidra.framework.plugintool.PluginTool;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
@ -59,6 +60,7 @@ class JythonPluginExecutionThread extends Thread {
|
|||
TaskMonitor interactiveTaskMonitor = plugin.getInteractiveTaskMonitor();
|
||||
JythonScript interactiveScript = plugin.getInteractiveScript();
|
||||
Program program = plugin.getCurrentProgram();
|
||||
InterpreterConsole console = plugin.getConsole();
|
||||
|
||||
// Setup transaction for the execution.
|
||||
try (Transaction tx = program != null ? program.openTransaction("Jython command") : null) {
|
||||
|
@ -69,7 +71,7 @@ class JythonPluginExecutionThread extends Thread {
|
|||
interactiveScript.set(
|
||||
new GhidraState(tool, tool.getProject(), program, plugin.getProgramLocation(),
|
||||
plugin.getProgramSelection(), plugin.getProgramHighlight()),
|
||||
interactiveTaskMonitor, new PrintWriter(plugin.getConsole().getStdOut()));
|
||||
new ScriptControls(console, interactiveTaskMonitor));
|
||||
|
||||
// Execute the command
|
||||
moreInputWanted.set(false);
|
||||
|
@ -81,14 +83,13 @@ class JythonPluginExecutionThread extends Thread {
|
|||
plugin.reset();
|
||||
}
|
||||
else {
|
||||
plugin.getConsole()
|
||||
.getErrWriter()
|
||||
console.getErrWriter()
|
||||
.println(
|
||||
"Suppressing exception: " + PyException.exceptionClassName(pye.type));
|
||||
}
|
||||
}
|
||||
catch (StackOverflowError soe) {
|
||||
plugin.getConsole().getErrWriter().println("Stack overflow!");
|
||||
console.getErrWriter().println("Stack overflow!");
|
||||
}
|
||||
finally {
|
||||
interactiveScript.end(false); // end any transactions the script may have started
|
||||
|
|
|
@ -62,7 +62,7 @@ public class JythonScript extends GhidraScript {
|
|||
ResourceFile scriptSource = GhidraScriptUtil.findScriptByName(scriptName);
|
||||
if (scriptSource != null) {
|
||||
GhidraScriptProvider provider = GhidraScriptUtil.getProvider(scriptSource);
|
||||
GhidraScript ghidraScript = provider.getScriptInstance(scriptSource, writer);
|
||||
GhidraScript ghidraScript = provider.getScriptInstance(scriptSource, errorWriter);
|
||||
if (ghidraScript == null) {
|
||||
throw new IllegalArgumentException("Script does not exist: " + scriptName);
|
||||
}
|
||||
|
@ -72,12 +72,12 @@ public class JythonScript extends GhidraScript {
|
|||
}
|
||||
|
||||
if (ghidraScript instanceof JythonScript) {
|
||||
ghidraScript.set(scriptState, monitor, writer);
|
||||
ghidraScript.set(scriptState);
|
||||
JythonScript jythonScript = (JythonScript) ghidraScript;
|
||||
interpreter.execFile(jythonScript.getSourceFile(), jythonScript);
|
||||
}
|
||||
else {
|
||||
ghidraScript.execute(scriptState, monitor, writer);
|
||||
ghidraScript.execute(scriptState);
|
||||
}
|
||||
|
||||
if (scriptState == state) {
|
||||
|
|
|
@ -25,8 +25,7 @@ import org.junit.*;
|
|||
import generic.jar.ResourceFile;
|
||||
import ghidra.app.plugin.core.console.ConsolePlugin;
|
||||
import ghidra.app.plugin.core.osgi.BundleHost;
|
||||
import ghidra.app.script.GhidraScriptUtil;
|
||||
import ghidra.app.script.GhidraState;
|
||||
import ghidra.app.script.*;
|
||||
import ghidra.app.services.ConsoleService;
|
||||
import ghidra.framework.Application;
|
||||
import ghidra.framework.plugintool.PluginTool;
|
||||
|
@ -128,7 +127,7 @@ public class JythonScriptTest extends AbstractGhidraHeadedIntegrationTest {
|
|||
JythonScriptProvider scriptProvider = new JythonScriptProvider();
|
||||
PrintWriter writer = new PrintWriter(new ByteArrayOutputStream());
|
||||
JythonScript script = (JythonScript) scriptProvider.getScriptInstance(scriptFile, writer);
|
||||
script.set(state, TaskMonitor.DUMMY, writer);
|
||||
script.set(state, new ScriptControls(writer, writer, TaskMonitor.DUMMY));
|
||||
script.run();
|
||||
|
||||
waitForSwing();
|
||||
|
|
|
@ -93,9 +93,10 @@ public class WindowsResourceReferenceAnalyzer extends AbstractAnalyzer {
|
|||
}
|
||||
|
||||
PrintWriter writer = getOutputMsgStream(tool);
|
||||
PrintWriter errWriter = getErrorMsgStream(tool);
|
||||
|
||||
GhidraScript script = provider.getScriptInstance(sourceFile, writer);
|
||||
script.set(state, monitor, writer);
|
||||
GhidraScript script = provider.getScriptInstance(sourceFile, errWriter);
|
||||
script.set(state, new ScriptControls(writer, errWriter, monitor));
|
||||
|
||||
// This code was added so the analyzer won't print script messages to console
|
||||
// This also adds the ability to pass the option to add or not add bookmarks to the script
|
||||
|
@ -141,6 +142,16 @@ public class WindowsResourceReferenceAnalyzer extends AbstractAnalyzer {
|
|||
return new PrintWriter(System.out);
|
||||
}
|
||||
|
||||
private PrintWriter getErrorMsgStream(PluginTool tool) {
|
||||
if (tool != null) {
|
||||
ConsoleService console = tool.getService(ConsoleService.class);
|
||||
if (console != null) {
|
||||
return console.getStdErr();
|
||||
}
|
||||
}
|
||||
return new PrintWriter(System.err);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removed(Program program, AddressSetView set, TaskMonitor monitor, MessageLog log)
|
||||
throws CancelledException {
|
||||
|
|
|
@ -22,6 +22,7 @@ import ghidra.app.plugin.PluginCategoryNames;
|
|||
import ghidra.app.plugin.ProgramPlugin;
|
||||
import ghidra.app.plugin.core.interpreter.InterpreterPanelService;
|
||||
import ghidra.app.script.GhidraState;
|
||||
import ghidra.app.script.ScriptControls;
|
||||
import ghidra.framework.plugintool.PluginInfo;
|
||||
import ghidra.framework.plugintool.PluginTool;
|
||||
import ghidra.framework.plugintool.util.PluginStatus;
|
||||
|
@ -57,7 +58,7 @@ public class PyGhidraPlugin extends ProgramPlugin {
|
|||
super(tool);
|
||||
GhidraState state = new GhidraState(tool, tool.getProject(), null, null, null, null);
|
||||
// use the copy constructor so this state doesn't fire plugin events
|
||||
script.set(new GhidraState(state), null, null);
|
||||
script.set(new GhidraState(state), ScriptControls.NONE);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -86,13 +86,13 @@ public final class PyGhidraScriptProvider extends AbstractPythonScriptProvider {
|
|||
"currentAddress", "currentLocation", "currentSelection",
|
||||
"currentHighlight", "currentProgram", "monitor",
|
||||
"potentialPropertiesFileLocs", "propertiesFileParams",
|
||||
"sourceFile", "state", "writer"
|
||||
"sourceFile", "state", "writer", "errorWriter"
|
||||
},
|
||||
types = {
|
||||
Address.class, ProgramLocation.class, ProgramSelection.class,
|
||||
ProgramSelection.class, Program.class, TaskMonitor.class,
|
||||
List.class, GhidraScriptProperties.class,
|
||||
ResourceFile.class, GhidraState.class, PrintWriter.class
|
||||
ResourceFile.class, GhidraState.class, PrintWriter.class, PrintWriter.class
|
||||
}
|
||||
)
|
||||
final static class PyGhidraGhidraScript extends GhidraScript
|
||||
|
@ -120,13 +120,13 @@ public final class PyGhidraScriptProvider extends AbstractPythonScriptProvider {
|
|||
"currentAddress", "currentLocation", "currentSelection",
|
||||
"currentHighlight", "currentProgram", "monitor",
|
||||
"potentialPropertiesFileLocs", "propertiesFileParams",
|
||||
"sourceFile", "state", "writer"
|
||||
"sourceFile", "state", "writer", "errorWriter"
|
||||
},
|
||||
types = {
|
||||
Address.class, ProgramLocation.class, ProgramSelection.class,
|
||||
ProgramSelection.class, Program.class, TaskMonitor.class,
|
||||
List.class, GhidraScriptProperties.class,
|
||||
ResourceFile.class, GhidraState.class, PrintWriter.class
|
||||
ResourceFile.class, GhidraState.class, PrintWriter.class, PrintWriter.class
|
||||
}
|
||||
)
|
||||
final static class PyGhidraHeadlessScript extends HeadlessScript
|
||||
|
|
|
@ -17,8 +17,7 @@ package ghidra.pyghidra.interpreter;
|
|||
|
||||
import java.io.PrintWriter;
|
||||
|
||||
import ghidra.app.script.GhidraScript;
|
||||
import ghidra.app.script.GhidraState;
|
||||
import ghidra.app.script.*;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.util.ProgramLocation;
|
||||
|
@ -86,6 +85,6 @@ public final class InterpreterGhidraScript extends GhidraScript {
|
|||
}
|
||||
|
||||
public void set(GhidraState state, PrintWriter writer) {
|
||||
set(state, new InterpreterTaskMonitor(writer), writer);
|
||||
set(state, new ScriptControls(writer, writer, new InterpreterTaskMonitor(writer)));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue