Merge remote-tracking branch

'origin/GP-1866_d-millar_cmdline_consistency--SQUASHED'
(Closes #4106)
This commit is contained in:
Ryan Kurtz 2022-04-01 16:02:36 -04:00
commit 79e5a60d49
8 changed files with 122 additions and 107 deletions

View File

@ -222,9 +222,10 @@ public class DebuggerObjectsProvider extends ComponentProviderAdapter
private MyObjectListener listener = new MyObjectListener();
public DebuggerMethodInvocationDialog configDialog;
public DebuggerMethodInvocationDialog launchDialog;
public DebuggerMethodInvocationDialog methodDialog;
public DebuggerAttachDialog attachDialog;
public DebuggerBreakpointDialog breakpointDialog;
private GenericDebuggerProgramLaunchOffer launchOffer;
DockingAction actionLaunch;
DockingAction actionAddBreakpoint;
@ -271,6 +272,7 @@ public class DebuggerObjectsProvider extends ComponentProviderAdapter
currentProgram = plugin.getActiveProgram();
plugin.addProvider(this);
this.currentModel = model;
launchOffer = new GenericDebuggerProgramLaunchOffer(currentProgram, tool, currentModel);
this.root = container;
this.asTree = asTree;
setIcon(asTree ? ObjectTree.ICON_TREE : ObjectTable.ICON_TABLE);
@ -327,6 +329,7 @@ public class DebuggerObjectsProvider extends ComponentProviderAdapter
public void setModel(DebuggerObjectModel model) {
currentModel = model;
currentModel.addModelListener(getListener(), true);
launchOffer = new GenericDebuggerProgramLaunchOffer(currentProgram, tool, currentModel);
refresh();
}
@ -344,7 +347,7 @@ public class DebuggerObjectsProvider extends ComponentProviderAdapter
addTable(getRoot());
}
launchDialog = new DebuggerMethodInvocationDialog(tool, "Launch", "Launch",
methodDialog = new DebuggerMethodInvocationDialog(tool, "Method", "Method",
DebuggerResources.ICON_LAUNCH);
//attachDialogOld = new DebuggerAttachDialog(this);
attachDialog = new DebuggerAttachDialog(this);
@ -459,6 +462,7 @@ public class DebuggerObjectsProvider extends ComponentProviderAdapter
}
currentProgram = program;
plugin.setActiveProgram(currentProgram);
launchOffer = new GenericDebuggerProgramLaunchOffer(currentProgram, tool, currentModel);
contextChanged();
}
@ -1438,8 +1442,15 @@ public class DebuggerObjectsProvider extends ComponentProviderAdapter
public void performLaunch(ActionContext context) {
performAction(context, true, TargetLauncher.class, launcher -> {
Map<String, ?> args = launchOffer.getLauncherArgs(launcher.getParameters(), true);
if (args == null) {
// Cancelled
return AsyncUtils.NIL;
}
return launcher.launch(args);
/*
String argsKey = TargetCmdLineLauncher.CMDLINE_ARGS_NAME;
// TODO: A generic or pluggable way of deriving the default arguments
String path = (currentProgram != null) ? currentProgram.getExecutablePath() : null;
launchDialog.setCurrentContext(path);
String cmdlineArgs = launchDialog.getMemorizedArgument(argsKey, String.class);
@ -1453,6 +1464,7 @@ public class DebuggerObjectsProvider extends ComponentProviderAdapter
return AsyncUtils.NIL;
}
return launcher.launch(args);
*/
}, "Couldn't launch");
}
@ -1491,10 +1503,11 @@ public class DebuggerObjectsProvider extends ComponentProviderAdapter
list.add(entry.getKey());
}
}
String choice = OptionDialog.showInputChoiceDialog(getComponent(), "Methods", "Methods", list.toArray(new String [] {}), lastMethod, OptionDialog.QUESTION_MESSAGE);
String choice = OptionDialog.showInputChoiceDialog(getComponent(), "Methods", "Methods",
list.toArray(new String[] {}), lastMethod, OptionDialog.QUESTION_MESSAGE);
if (choice != null) {
TargetMethod method = (TargetMethod) attributes.get(choice);
Map<String, ?> args = launchDialog.promptArguments(method.getParameters());
Map<String, ?> args = methodDialog.promptArguments(method.getParameters());
if (args != null) {
String script = (String) args.get("Script");
if (script != null && !script.isEmpty()) {
@ -1508,13 +1521,13 @@ public class DebuggerObjectsProvider extends ComponentProviderAdapter
}
}
private void mapScript(Map<String, ?> args) {
private void mapScript(Map<String, ?> args) {
String name = (String) args.get("Name");
String scriptName = (String) args.get("Script");
if (name.isEmpty() || scriptName.isEmpty()) {
return;
}
ResourceFile sourceFile = GhidraScriptUtil.findScriptByName(scriptName);
if (sourceFile == null) {
Msg.error(this, "Couldn't find script");
@ -1525,12 +1538,13 @@ public class DebuggerObjectsProvider extends ComponentProviderAdapter
Msg.error(this, "Couldn't find script provider");
return;
}
PrintWriter writer = consoleService.getStdOut();
GhidraScript script;
try {
script = provider.getScriptInstance(sourceFile, writer);
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
}
catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
Msg.error(this, e.getMessage());
return;
}
@ -1538,33 +1552,34 @@ public class DebuggerObjectsProvider extends ComponentProviderAdapter
scriptNames.put(name, scriptName);
}
private void fireScript(String key, String [] args) {
private void fireScript(String key, String[] args) {
GhidraScript script = scripts.get(key);
String scriptName = scriptNames.get(key);
if (script == null || scriptName == null) {
return;
}
PluginTool tool = plugin.getTool();
Project project = tool.getProject();
ProgramLocation currentLocation = listingService.getCurrentLocation();
ProgramSelection currentSelection = listingService.getCurrentSelection();
GhidraState state = new GhidraState(tool, project, currentProgram,
currentLocation, currentSelection, null);
PrintWriter writer = consoleService.getStdOut();
TaskMonitor monitor = TaskMonitor.DUMMY;
script.set(state, monitor, writer);
try {
script.runScript(scriptName, args);
} catch (Exception e) {
}
catch (Exception e) {
e.printStackTrace();
}
}
public void startRecording(TargetProcess targetObject, boolean prompt) {
TraceRecorder rec = modelService.getRecorder(targetObject);
if (rec != null) {
@ -1722,7 +1737,7 @@ public class DebuggerObjectsProvider extends ComponentProviderAdapter
}
return object instanceof TargetAccessConditioned;
}
public boolean isStopped(ActionContext context) {
TargetObject object = this.getObjectFromContext(context);
if (object == null) {
@ -1773,7 +1788,7 @@ public class DebuggerObjectsProvider extends ComponentProviderAdapter
}
@Override
public void consoleOutput(TargetObject console, Channel channel, byte [] bytes) {
public void consoleOutput(TargetObject console, Channel channel, byte[] bytes) {
String ret = new String(bytes);
if (ret.contains(TargetMethod.REDIRECT)) {
String[] split = ret.split(TargetMethod.REDIRECT);
@ -1781,7 +1796,7 @@ public class DebuggerObjectsProvider extends ComponentProviderAdapter
String val = split[1];
GhidraScript script = scripts.get(key);
if (script != null) {
String [] args = new String[1];
String[] args = new String[1];
args[0] = val;
fireScript(key, args);
return;
@ -1991,7 +2006,7 @@ public class DebuggerObjectsProvider extends ComponentProviderAdapter
public void writeConfigState(SaveState saveState) {
CONFIG_STATE_HANDLER.writeConfigState(this, saveState);
launchDialog.writeConfigState(saveState);
methodDialog.writeConfigState(saveState);
}
public void readConfigState(SaveState saveState) {
@ -2001,7 +2016,7 @@ public class DebuggerObjectsProvider extends ComponentProviderAdapter
actionToggleHideIntrinsics.setSelected(hideIntrinsics);
actionToggleSelectionOnly.setSelected(selectionOnly);
launchDialog.readConfigState(saveState);
methodDialog.readConfigState(saveState);
}
@Override

View File

@ -51,12 +51,6 @@ public class DebuggerMethodInvocationDialog extends DialogComponentProvider
return new NameTypePair(parameter.name, parameter.type);
}
public static NameTypePair fromParameter(ParameterDescription<?> parameter,
Object context) {
String contextName = addContext(parameter.name, context);
return new NameTypePair(contextName, parameter.type);
}
public static NameTypePair fromString(String name) throws ClassNotFoundException {
String[] parts = name.split(",", 2);
if (parts.length != 2) {
@ -105,7 +99,6 @@ public class DebuggerMethodInvocationDialog extends DialogComponentProvider
// TODO: Not sure this is the best keying, but I think it works.
private Map<NameTypePair, Object> memorized = new HashMap<>();
private Map<String, ?> arguments;
private Object currentContext;
public DebuggerMethodInvocationDialog(PluginTool tool, String title, String buttonText,
Icon buttonIcon) {
@ -117,7 +110,7 @@ public class DebuggerMethodInvocationDialog extends DialogComponentProvider
}
protected Object computeMemorizedValue(ParameterDescription<?> parameter) {
return memorized.computeIfAbsent(NameTypePair.fromParameter(parameter, currentContext),
return memorized.computeIfAbsent(NameTypePair.fromParameter(parameter),
ntp -> parameter.defaultValue);
}
@ -194,7 +187,7 @@ public class DebuggerMethodInvocationDialog extends DialogComponentProvider
return paramEditors.keySet()
.stream()
.collect(Collectors.toMap(param -> param.name,
param -> memorized.get(NameTypePair.fromParameter(param, currentContext))));
param -> memorized.get(NameTypePair.fromParameter(param))));
}
public Map<String, ?> getArguments() {
@ -202,12 +195,12 @@ public class DebuggerMethodInvocationDialog extends DialogComponentProvider
}
public <T> void setMemorizedArgument(String name, Class<T> type, T value) {
name = addContext(name, currentContext);
//name = addContext(name, currentContext);
memorized.put(new NameTypePair(name, type), value);
}
public <T> T getMemorizedArgument(String name, Class<T> type) {
name = addContext(name, currentContext);
//name = addContext(name, currentContext);
return type.cast(memorized.get(new NameTypePair(name, type)));
}
@ -215,7 +208,7 @@ public class DebuggerMethodInvocationDialog extends DialogComponentProvider
public void propertyChange(PropertyChangeEvent evt) {
PropertyEditor editor = (PropertyEditor) evt.getSource();
ParameterDescription<?> param = paramEditors.getKey(editor);
memorized.put(NameTypePair.fromParameter(param, currentContext), editor.getValue());
memorized.put(NameTypePair.fromParameter(param), editor.getValue());
}
public void writeConfigState(SaveState saveState) {
@ -246,15 +239,4 @@ public class DebuggerMethodInvocationDialog extends DialogComponentProvider
}
}
public Object getCurrentContext() {
return currentContext;
}
public void setCurrentContext(Object currentContext) {
this.currentContext = currentContext;
}
static private String addContext(String name, Object context) {
return context == null ? name : name + ":" + context;
}
}

View File

@ -0,0 +1,54 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.plugin.core.debug.gui.objects.components;
import java.util.concurrent.CompletableFuture;
import ghidra.app.plugin.core.debug.service.model.launch.AbstractDebuggerProgramLaunchOffer;
import ghidra.dbg.DebuggerObjectModel;
import ghidra.framework.plugintool.PluginTool;
import ghidra.program.model.listing.Program;
public class GenericDebuggerProgramLaunchOffer extends AbstractDebuggerProgramLaunchOffer {
private DebuggerObjectModel model;
public GenericDebuggerProgramLaunchOffer(Program program, PluginTool tool,
DebuggerObjectModel model) {
super(program, tool, null);
this.model = model;
}
@Override
public String getConfigName() {
return program.getName();
}
@Override
public String getMenuTitle() {
return model.getBrief();
}
@Override
public String getMenuParentTitle() {
return model.getBrief();
}
protected CompletableFuture<DebuggerObjectModel> connect(boolean prompt) {
throw new RuntimeException("Unable to connect using GenericDebuggerProgramLaunchOffer");
}
}

View File

@ -20,8 +20,6 @@ import java.util.*;
import ghidra.app.plugin.core.debug.service.model.launch.*;
import ghidra.app.services.DebuggerModelService;
import ghidra.dbg.DebuggerModelFactory;
import ghidra.dbg.target.TargetLauncher.TargetCmdLineLauncher;
import ghidra.dbg.target.TargetMethod.ParameterDescription;
import ghidra.dbg.util.PathUtils;
import ghidra.framework.plugintool.PluginTool;
import ghidra.program.model.listing.Program;
@ -45,11 +43,6 @@ public class DbgDebuggerProgramLaunchOpinion implements DebuggerProgramLaunchOpi
return PathUtils.parse("");
}
@Override
protected Map<String, ?> generateDefaultLauncherArgs(
Map<String, ParameterDescription<?>> params) {
return Map.of(TargetCmdLineLauncher.CMDLINE_ARGS_NAME, program.getExecutablePath());
}
}
protected class InVmDbgengDebuggerProgramLaunchOffer

View File

@ -20,8 +20,6 @@ import java.util.*;
import ghidra.app.plugin.core.debug.service.model.launch.*;
import ghidra.app.services.DebuggerModelService;
import ghidra.dbg.DebuggerModelFactory;
import ghidra.dbg.target.TargetLauncher.TargetCmdLineLauncher;
import ghidra.dbg.target.TargetMethod.ParameterDescription;
import ghidra.dbg.util.PathUtils;
import ghidra.framework.plugintool.PluginTool;
import ghidra.program.model.listing.Program;
@ -45,11 +43,6 @@ public class FridaDebuggerProgramLaunchOpinion implements DebuggerProgramLaunchO
return PathUtils.parse("");
}
@Override
protected Map<String, ?> generateDefaultLauncherArgs(
Map<String, ParameterDescription<?>> params) {
return Map.of(TargetCmdLineLauncher.CMDLINE_ARGS_NAME, program.getExecutablePath());
}
}
protected class InVmFridaDebuggerProgramLaunchOffer

View File

@ -20,8 +20,6 @@ import java.util.*;
import ghidra.app.plugin.core.debug.service.model.launch.*;
import ghidra.app.services.DebuggerModelService;
import ghidra.dbg.DebuggerModelFactory;
import ghidra.dbg.target.TargetLauncher.TargetCmdLineLauncher;
import ghidra.dbg.target.TargetMethod.ParameterDescription;
import ghidra.dbg.util.ConfigurableFactory.Property;
import ghidra.dbg.util.PathUtils;
import ghidra.framework.plugintool.PluginTool;
@ -46,11 +44,6 @@ public class GdbDebuggerProgramLaunchOpinion implements DebuggerProgramLaunchOpi
return PathUtils.parse("Inferiors[1]");
}
@Override
protected Map<String, ?> generateDefaultLauncherArgs(
Map<String, ParameterDescription<?>> params) {
return Map.of(TargetCmdLineLauncher.CMDLINE_ARGS_NAME, program.getExecutablePath());
}
}
protected class InVmGdbDebuggerProgramLaunchOffer
@ -75,19 +68,19 @@ public class GdbDebuggerProgramLaunchOpinion implements DebuggerProgramLaunchOpi
protected class InVmGdbConPtyDebuggerProgramLaunchOffer
extends AbstractGdbDebuggerProgramLaunchOffer {
private static final String FACTORY_CLS_NAME =
private static final String FACTORY_CLS_NAME =
"agent.gdb.GdbInJvmConPtyDebuggerModelFactory";
public InVmGdbConPtyDebuggerProgramLaunchOffer(Program program, PluginTool tool,
DebuggerModelFactory factory) {
super(program, tool, factory);
}
@Override
public String getConfigName() {
return "IN-VM GDB (Windows)";
}
@Override
public String getMenuTitle() {
return "in GDB locally IN-VM (Windows)";

View File

@ -20,8 +20,6 @@ import java.util.*;
import ghidra.app.plugin.core.debug.service.model.launch.*;
import ghidra.app.services.DebuggerModelService;
import ghidra.dbg.DebuggerModelFactory;
import ghidra.dbg.target.TargetLauncher.TargetCmdLineLauncher;
import ghidra.dbg.target.TargetMethod.ParameterDescription;
import ghidra.dbg.util.PathUtils;
import ghidra.framework.plugintool.PluginTool;
import ghidra.program.model.listing.Program;
@ -45,11 +43,6 @@ public class LldbDebuggerProgramLaunchOpinion implements DebuggerProgramLaunchOp
return PathUtils.parse("");
}
@Override
protected Map<String, ?> generateDefaultLauncherArgs(
Map<String, ParameterDescription<?>> params) {
return Map.of(TargetCmdLineLauncher.CMDLINE_ARGS_NAME, program.getExecutablePath());
}
}
protected class InVmLldbDebuggerProgramLaunchOffer

View File

@ -24,12 +24,12 @@ import org.jdom.Element;
import org.jdom.JDOMException;
import ghidra.app.plugin.core.debug.gui.objects.components.DebuggerMethodInvocationDialog;
import ghidra.app.plugin.core.debug.service.model.DebuggerModelServicePlugin;
import ghidra.app.services.DebuggerModelService;
import ghidra.async.AsyncUtils;
import ghidra.async.SwingExecutorService;
import ghidra.dbg.*;
import ghidra.dbg.target.TargetLauncher;
import ghidra.dbg.target.TargetLauncher.TargetCmdLineLauncher;
import ghidra.dbg.target.TargetMethod.ParameterDescription;
import ghidra.dbg.target.TargetObject;
import ghidra.dbg.target.schema.TargetObjectSchema;
@ -37,11 +37,8 @@ import ghidra.dbg.util.PathUtils;
import ghidra.framework.options.SaveState;
import ghidra.framework.plugintool.AutoConfigState.ConfigStateField;
import ghidra.framework.plugintool.PluginTool;
import ghidra.framework.plugintool.util.PluginUtils;
import ghidra.program.model.address.Address;
import ghidra.program.model.listing.Program;
import ghidra.program.model.listing.ProgramUserData;
import ghidra.program.model.util.StringPropertyMap;
import ghidra.util.Msg;
import ghidra.util.database.UndoableTransaction;
import ghidra.util.task.TaskMonitor;
@ -73,13 +70,11 @@ public abstract class AbstractDebuggerProgramLaunchOffer implements DebuggerProg
val);
}
}
String owner = PluginUtils.getPluginNameFromClass(DebuggerModelServicePlugin.class);
ProgramUserData userData = program.getProgramUserData();
try (UndoableTransaction tid = UndoableTransaction.start(userData)) {
StringPropertyMap stringProperty =
userData.getStringProperty(owner, getConfigName(), true);
Element element = state.saveToXml();
stringProperty.add(Address.NO_ADDRESS, XmlUtilities.toString(element));
userData.setStringProperty(TargetCmdLineLauncher.CMDLINE_ARGS_NAME,
XmlUtilities.toString(element));
}
}
@ -98,8 +93,10 @@ public abstract class AbstractDebuggerProgramLaunchOffer implements DebuggerProg
* @param params the parameters
* @return the default arguments
*/
protected abstract Map<String, ?> generateDefaultLauncherArgs(
Map<String, ParameterDescription<?>> params);
protected Map<String, ?> generateDefaultLauncherArgs(
Map<String, ParameterDescription<?>> params) {
return Map.of(TargetCmdLineLauncher.CMDLINE_ARGS_NAME, program.getExecutablePath());
}
/**
* Prompt the user for arguments, showing those last used or defaults
@ -148,33 +145,28 @@ public abstract class AbstractDebuggerProgramLaunchOffer implements DebuggerProg
* TODO: Supposedly, per-program, per-user config stuff is being generalized for analyzers.
* Re-examine this if/when that gets merged
*/
String owner = PluginUtils.getPluginNameFromClass(DebuggerModelServicePlugin.class);
ProgramUserData userData = program.getProgramUserData();
StringPropertyMap property =
userData.getStringProperty(owner, getConfigName(), false);
String property = userData.getStringProperty(TargetCmdLineLauncher.CMDLINE_ARGS_NAME, null);
if (property != null) {
String xml = property.getString(Address.NO_ADDRESS);
if (xml != null) {
try {
Element element = XmlUtilities.fromString(xml);
SaveState state = new SaveState(element);
Map<String, Object> args = new LinkedHashMap<>();
for (ParameterDescription<?> param : params.values()) {
args.put(param.name,
ConfigStateField.getState(state, param.type, param.name));
}
return args;
try {
Element element = XmlUtilities.fromString(property);
SaveState state = new SaveState(element);
Map<String, Object> args = new LinkedHashMap<>();
for (ParameterDescription<?> param : params.values()) {
args.put(param.name,
ConfigStateField.getState(state, param.type, param.name));
}
catch (JDOMException | IOException e) {
if (!forPrompt) {
throw new RuntimeException(
"Saved launcher args are corrupt, or launcher parameters changed. Not launching.",
e);
}
Msg.error(this,
"Saved launcher args are corrup, or launcher parameters changed. Defaulting.",
return args;
}
catch (JDOMException | IOException e) {
if (!forPrompt) {
throw new RuntimeException(
"Saved launcher args are corrupt, or launcher parameters changed. Not launching.",
e);
}
Msg.error(this,
"Saved launcher args are corrup, or launcher parameters changed. Defaulting.",
e);
}
}
@ -194,7 +186,7 @@ public abstract class AbstractDebuggerProgramLaunchOffer implements DebuggerProg
* @param params the parameters of the model's launcher
* @return the chosen arguments, or null if the user cancels at the prompt
*/
protected Map<String, ?> getLauncherArgs(Map<String, ParameterDescription<?>> params,
public Map<String, ?> getLauncherArgs(Map<String, ParameterDescription<?>> params,
boolean prompt) {
return prompt
? promptLauncherArgs(params)