mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 19:42:36 +02:00
GP-4847: Unify Debugger param dialogs. Prefixed integers allowed.
This commit is contained in:
parent
e0bf7b4c53
commit
16ff4c4d08
36 changed files with 2842 additions and 1509 deletions
|
@ -0,0 +1,59 @@
|
|||
/* ###
|
||||
* 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.debug.api;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public record ValStr<T>(T val, String str) {
|
||||
|
||||
public interface Decoder<T> {
|
||||
default ValStr<T> decodeValStr(String string) {
|
||||
return new ValStr<>(decode(string), string);
|
||||
}
|
||||
|
||||
T decode(String string);
|
||||
}
|
||||
|
||||
public static ValStr<String> str(String value) {
|
||||
return new ValStr<>(value, value);
|
||||
}
|
||||
|
||||
public static <T> ValStr<T> from(T value) {
|
||||
return new ValStr<>(value, value == null ? "" : value.toString());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> ValStr<T> cast(Class<T> cls, ValStr<?> value) {
|
||||
if (cls.isInstance(value.val)) {
|
||||
return (ValStr<T>) value;
|
||||
}
|
||||
return new ValStr<>(cls.cast(value.val), value.str);
|
||||
}
|
||||
|
||||
public static Map<String, ValStr<?>> fromPlainMap(Map<String, ?> map) {
|
||||
return map.entrySet()
|
||||
.stream()
|
||||
.collect(Collectors.toMap(Entry::getKey, e -> ValStr.from(e.getValue())));
|
||||
}
|
||||
|
||||
public static Map<String, ? super Object> toPlainMap(Map<String, ValStr<?>> map) {
|
||||
return map.entrySet()
|
||||
.stream()
|
||||
.collect(Collectors.toMap(Entry::getKey, e -> e.getValue().val()));
|
||||
}
|
||||
}
|
|
@ -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.
|
||||
|
@ -24,6 +24,7 @@ import ghidra.dbg.DebuggerModelFactory;
|
|||
import ghidra.dbg.DebuggerObjectModel;
|
||||
import ghidra.dbg.target.TargetLauncher;
|
||||
import ghidra.dbg.target.TargetObject;
|
||||
import ghidra.debug.api.ValStr;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
/**
|
||||
|
@ -117,8 +118,8 @@ public interface DebuggerProgramLaunchOffer {
|
|||
* @param relPrompt describes the timing of this callback relative to prompting the user
|
||||
* @return the adjusted arguments
|
||||
*/
|
||||
default Map<String, ?> configureLauncher(TargetLauncher launcher,
|
||||
Map<String, ?> arguments, RelPrompt relPrompt) {
|
||||
default Map<String, ValStr<?>> configureLauncher(TargetLauncher launcher,
|
||||
Map<String, ValStr<?>> arguments, RelPrompt relPrompt) {
|
||||
return arguments;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
/* ###
|
||||
* 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.debug.api.tracermi;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import ghidra.debug.api.ValStr;
|
||||
|
||||
public record LaunchParameter<T>(Class<T> type, String name, String display, String description,
|
||||
boolean required, List<T> choices, ValStr<T> defaultValue, ValStr.Decoder<T> decoder) {
|
||||
|
||||
public static <T> LaunchParameter<T> create(Class<T> type, String name, String display,
|
||||
String description, boolean required, ValStr<T> defaultValue,
|
||||
ValStr.Decoder<T> decoder) {
|
||||
return new LaunchParameter<>(type, name, display, description, required, List.of(),
|
||||
defaultValue, decoder);
|
||||
}
|
||||
|
||||
public static <T> LaunchParameter<T> choices(Class<T> type, String name, String display,
|
||||
String description, Collection<T> choices, ValStr<T> defaultValue) {
|
||||
return new LaunchParameter<>(type, name, display, description, false,
|
||||
List.copyOf(new LinkedHashSet<>(choices)), defaultValue, str -> {
|
||||
for (T t : choices) {
|
||||
if (t.toString().equals(str)) {
|
||||
return t;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
public static Map<String, LaunchParameter<?>> mapOf(Collection<LaunchParameter<?>> parameters) {
|
||||
Map<String, LaunchParameter<?>> result = new LinkedHashMap<>();
|
||||
for (LaunchParameter<?> param : parameters) {
|
||||
LaunchParameter<?> exists = result.put(param.name(), param);
|
||||
if (exists != null) {
|
||||
throw new IllegalArgumentException(
|
||||
"Duplicate names in parameter map: first=%s, second=%s".formatted(exists,
|
||||
param));
|
||||
}
|
||||
}
|
||||
return Collections.unmodifiableMap(result);
|
||||
}
|
||||
|
||||
public static Map<String, ValStr<?>> validateArguments(
|
||||
Map<String, LaunchParameter<?>> parameters, Map<String, ValStr<?>> arguments) {
|
||||
if (!parameters.keySet().containsAll(arguments.keySet())) {
|
||||
Set<String> extraneous = new TreeSet<>(arguments.keySet());
|
||||
extraneous.removeAll(parameters.keySet());
|
||||
throw new IllegalArgumentException("Extraneous parameters: " + extraneous);
|
||||
}
|
||||
|
||||
Map<String, String> typeErrors = null;
|
||||
for (Map.Entry<String, ValStr<?>> ent : arguments.entrySet()) {
|
||||
String name = ent.getKey();
|
||||
ValStr<?> val = ent.getValue();
|
||||
LaunchParameter<?> param = parameters.get(name);
|
||||
if (val.val() != null && !param.type.isAssignableFrom(val.val().getClass())) {
|
||||
if (typeErrors == null) {
|
||||
typeErrors = new LinkedHashMap<>();
|
||||
}
|
||||
typeErrors.put(name, "val '%s' is not a %s".formatted(val.val(), param.type()));
|
||||
}
|
||||
}
|
||||
if (typeErrors != null) {
|
||||
throw new IllegalArgumentException("Type errors: " + typeErrors);
|
||||
}
|
||||
return arguments;
|
||||
}
|
||||
|
||||
public static Map<String, LaunchParameter<?>> mapOf(LaunchParameter<?>... parameters) {
|
||||
return mapOf(Arrays.asList(parameters));
|
||||
}
|
||||
|
||||
public ValStr<T> decode(String string) {
|
||||
return decoder.decodeValStr(string);
|
||||
}
|
||||
|
||||
public ValStr<T> get(Map<String, ValStr<?>> arguments) {
|
||||
if (arguments.containsKey(name)) {
|
||||
return ValStr.cast(type, arguments.get(name));
|
||||
}
|
||||
if (required) {
|
||||
throw new IllegalArgumentException(
|
||||
"Missing required parameter '%s' (%s)".formatted(display, name));
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public void set(Map<String, ValStr<?>> arguments, ValStr<T> value) {
|
||||
arguments.put(name, value);
|
||||
}
|
||||
}
|
|
@ -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.
|
||||
|
@ -20,7 +20,7 @@ import java.util.Map;
|
|||
|
||||
import javax.swing.Icon;
|
||||
|
||||
import ghidra.dbg.target.TargetMethod.ParameterDescription;
|
||||
import ghidra.debug.api.ValStr;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.trace.model.Trace;
|
||||
import ghidra.util.HelpLocation;
|
||||
|
@ -150,8 +150,8 @@ public interface TraceRmiLaunchOffer {
|
|||
* @param relPrompt describes the timing of this callback relative to prompting the user
|
||||
* @return the adjusted arguments
|
||||
*/
|
||||
default Map<String, ?> configureLauncher(TraceRmiLaunchOffer offer,
|
||||
Map<String, ?> arguments, RelPrompt relPrompt) {
|
||||
default Map<String, ValStr<?>> configureLauncher(TraceRmiLaunchOffer offer,
|
||||
Map<String, ValStr<?>> arguments, RelPrompt relPrompt) {
|
||||
return arguments;
|
||||
}
|
||||
}
|
||||
|
@ -293,7 +293,7 @@ public interface TraceRmiLaunchOffer {
|
|||
*
|
||||
* @return the parameters
|
||||
*/
|
||||
Map<String, ParameterDescription<?>> getParameters();
|
||||
Map<String, LaunchParameter<?>> getParameters();
|
||||
|
||||
/**
|
||||
* Check if this offer requires an open program
|
||||
|
|
|
@ -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.
|
||||
|
@ -28,6 +28,7 @@ import ghidra.dbg.target.TargetExecutionStateful.TargetExecutionState;
|
|||
import ghidra.dbg.target.TargetLauncher.TargetCmdLineLauncher;
|
||||
import ghidra.dbg.target.TargetSteppable.TargetStepKind;
|
||||
import ghidra.dbg.util.PathUtils;
|
||||
import ghidra.debug.api.ValStr;
|
||||
import ghidra.debug.api.model.DebuggerProgramLaunchOffer;
|
||||
import ghidra.debug.api.model.DebuggerProgramLaunchOffer.*;
|
||||
import ghidra.debug.api.model.TraceRecorder;
|
||||
|
@ -578,10 +579,10 @@ public interface FlatDebuggerRecorderAPI extends FlatDebuggerAPI {
|
|||
try {
|
||||
return waitOn(offer.launchProgram(monitor, PromptMode.NEVER, new LaunchConfigurator() {
|
||||
@Override
|
||||
public Map<String, ?> configureLauncher(TargetLauncher launcher,
|
||||
Map<String, ?> arguments, RelPrompt relPrompt) {
|
||||
Map<String, Object> adjusted = new HashMap<>(arguments);
|
||||
adjusted.put(TargetCmdLineLauncher.CMDLINE_ARGS_NAME, commandLine);
|
||||
public Map<String, ValStr<?>> configureLauncher(TargetLauncher launcher,
|
||||
Map<String, ValStr<?>> arguments, RelPrompt relPrompt) {
|
||||
Map<String, ValStr<?>> adjusted = new HashMap<>(arguments);
|
||||
adjusted.put(TargetCmdLineLauncher.CMDLINE_ARGS_NAME, ValStr.str(commandLine));
|
||||
return adjusted;
|
||||
}
|
||||
}));
|
||||
|
|
|
@ -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.
|
||||
|
@ -16,8 +16,10 @@
|
|||
package ghidra.debug.flatapi;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import ghidra.app.services.TraceRmiLauncherService;
|
||||
import ghidra.debug.api.ValStr;
|
||||
import ghidra.debug.api.tracermi.TraceRmiLaunchOffer;
|
||||
import ghidra.debug.api.tracermi.TraceRmiLaunchOffer.*;
|
||||
import ghidra.program.model.listing.Program;
|
||||
|
@ -116,13 +118,15 @@ public interface FlatDebuggerRmiAPI extends FlatDebuggerAPI {
|
|||
TaskMonitor monitor) {
|
||||
return offer.launchProgram(monitor, new LaunchConfigurator() {
|
||||
@Override
|
||||
public Map<String, ?> configureLauncher(TraceRmiLaunchOffer offer,
|
||||
Map<String, ?> arguments, RelPrompt relPrompt) {
|
||||
public Map<String, ValStr<?>> configureLauncher(TraceRmiLaunchOffer offer,
|
||||
Map<String, ValStr<?>> arguments, RelPrompt relPrompt) {
|
||||
if (arguments.isEmpty()) {
|
||||
return arguments;
|
||||
}
|
||||
Map<String, Object> args = new HashMap<>(arguments);
|
||||
args.putAll(overrideArgs);
|
||||
Map<String, ValStr<?>> args = new HashMap<>(arguments);
|
||||
for (Entry<String, ?> ent : overrideArgs.entrySet()) {
|
||||
args.put(ent.getKey(), ValStr.from(ent.getValue()));
|
||||
}
|
||||
return args;
|
||||
}
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue