GP-1158: Added "starti" launch parameter to GDB.

This commit is contained in:
Dan 2021-08-20 09:20:32 -04:00
parent 901f888510
commit f365b95a48
5 changed files with 40 additions and 34 deletions

View file

@ -60,7 +60,6 @@ public class GdbModelImpl extends AbstractDebuggerObjectModel {
new DefaultAddressFactory(new AddressSpace[] { space });
protected final GdbManager gdb;
protected boolean noStarti = false;
protected final GdbModelTargetSession session;
protected final CompletableFuture<GdbModelTargetSession> completedSession;

View file

@ -25,27 +25,13 @@ import ghidra.dbg.util.ShellUtils;
public enum GdbModelImplUtils {
;
public static CompletableFuture<GdbThread> launch(GdbModelImpl impl, GdbInferior inferior,
List<String> args) {
List<String> args, boolean useStarti) {
// Queue all these up to avoid other commands getting between.
CompletableFuture<Void> feas = inferior.fileExecAndSymbols(args.get(0));
CompletableFuture<Void> sargs =
inferior.setVar("args", ShellUtils.generateLine(args.subList(1, args.size())));
CompletableFuture<Void> both = CompletableFuture.allOf(feas, sargs);
if (impl.noStarti) {
return both.thenCombine(inferior.start(), (__, t) -> t);
}
else {
return both.thenCombine(inferior.starti(), (__, t) -> t).exceptionally(ex -> {
impl.noStarti = true;
// TODO: Check that the error is actually Undefined command: "starti"
return null;
}).thenCompose(thread -> {
if (thread == null) {
return inferior.start();
}
return CompletableFuture.completedStage(thread);
});
}
CompletableFuture<GdbThread> start = useStarti ? inferior.starti() : inferior.start();
return feas.thenCombine(sargs, (v1, v2) -> v2).thenCombine(start, (v, t) -> t);
}
public static <V> V noDupMerge(V first, V second) {

View file

@ -26,7 +26,8 @@ import ghidra.async.AsyncFence;
import ghidra.dbg.agent.DefaultTargetObject;
import ghidra.dbg.target.*;
import ghidra.dbg.target.TargetEventScope.TargetEventType;
import ghidra.dbg.target.TargetLauncher.TargetCmdLineLauncher;
import ghidra.dbg.target.TargetMethod.ParameterDescription;
import ghidra.dbg.target.TargetMethod.TargetParameterMap;
import ghidra.dbg.target.schema.*;
import ghidra.dbg.util.PathUtils;
import ghidra.lifecycle.Internal;
@ -40,11 +41,19 @@ import ghidra.lifecycle.Internal;
public class GdbModelTargetInferior
extends DefaultTargetObject<TargetObject, GdbModelTargetInferiorContainer>
implements TargetProcess, TargetAggregate, TargetExecutionStateful, TargetAttacher,
TargetDeletable, TargetDetachable, TargetKillable, TargetCmdLineLauncher, TargetResumable,
TargetDeletable, TargetDetachable, TargetKillable, TargetLauncher, TargetResumable,
TargetSteppable, GdbModelSelectableObject {
public static final String EXIT_CODE_ATTRIBUTE_NAME = PREFIX_INVISIBLE + "exit_code";
public static final ParameterDescription<Boolean> PARAMETER_STARTI =
ParameterDescription.create(Boolean.class, "starti", false, false,
"Break on first instruction (use starti)",
"true to use starti, false to use start. Requires GDB 8.1 or later.");
public static final TargetParameterMap PARAMETERS =
TargetMethod.makeParameters(TargetCmdLineLauncher.PARAMETER_CMDLINE_ARGS, PARAMETER_STARTI);
protected static final TargetAttachKindSet SUPPORTED_KINDS = TargetAttachKindSet.of( //
TargetAttachKind.BY_OBJECT_REF, TargetAttachKind.BY_ID);
@ -108,12 +117,23 @@ public class GdbModelTargetInferior
Map.of( //
STATE_ATTRIBUTE_NAME, state = realState, //
DISPLAY_ATTRIBUTE_NAME, updateDisplay(), //
TargetMethod.PARAMETERS_ATTRIBUTE_NAME, TargetCmdLineLauncher.PARAMETERS, //
TargetMethod.PARAMETERS_ATTRIBUTE_NAME, PARAMETERS, //
SUPPORTED_ATTACH_KINDS_ATTRIBUTE_NAME, SUPPORTED_KINDS, //
SUPPORTED_STEP_KINDS_ATTRIBUTE_NAME, GdbModelTargetThread.SUPPORTED_KINDS), //
"Initialized");
}
protected TargetParameterMap computeParams() {
return TargetMethod.makeParameters(
TargetCmdLineLauncher.PARAMETER_CMDLINE_ARGS,
PARAMETER_STARTI);
}
@Override
public TargetParameterMap getParameters() {
return PARAMETERS;
}
@TargetAttributeType(name = GdbModelTargetEnvironment.NAME, required = true, fixed = true)
public GdbModelTargetEnvironment getEnvironment() {
return environment;
@ -150,9 +170,12 @@ public class GdbModelTargetInferior
}
@Override
public CompletableFuture<Void> launch(List<String> args) {
return impl
.gateFuture(GdbModelImplUtils.launch(impl, inferior, args).thenApply(__ -> null));
public CompletableFuture<Void> launch(Map<String, ?> args) {
List<String> cmdLineArgs =
CmdLineParser.tokenize(TargetCmdLineLauncher.PARAMETER_CMDLINE_ARGS.get(args));
Boolean useStarti = PARAMETER_STARTI.get(args);
return impl.gateFuture(
GdbModelImplUtils.launch(impl, inferior, cmdLineArgs, useStarti).thenApply(__ -> null));
}
@Override

View file

@ -27,7 +27,6 @@ import ghidra.async.AsyncUtils;
import ghidra.dbg.agent.DefaultTargetModelRoot;
import ghidra.dbg.error.DebuggerIllegalArgumentException;
import ghidra.dbg.target.*;
import ghidra.dbg.target.TargetLauncher.TargetCmdLineLauncher;
import ghidra.dbg.target.schema.*;
import ghidra.dbg.util.PathUtils;
import ghidra.util.Msg;
@ -48,7 +47,7 @@ import ghidra.util.Msg;
@TargetAttributeType(type = Void.class) })
public class GdbModelTargetSession extends DefaultTargetModelRoot
implements TargetAccessConditioned, TargetAttacher, TargetInterpreter, TargetInterruptible,
TargetCmdLineLauncher, TargetActiveScope, TargetEventScope, TargetFocusScope,
TargetLauncher, TargetActiveScope, TargetEventScope, TargetFocusScope,
GdbConsoleOutputListener, GdbEventsListenerAdapter {
protected static final String GDB_PROMPT = "(gdb)";
@ -205,9 +204,12 @@ public class GdbModelTargetSession extends DefaultTargetModelRoot
}
@Override
public CompletableFuture<Void> launch(List<String> args) {
public CompletableFuture<Void> launch(Map<String, ?> args) {
List<String> cmdLineArgs =
CmdLineParser.tokenize(TargetCmdLineLauncher.PARAMETER_CMDLINE_ARGS.get(args));
Boolean useStarti = GdbModelTargetInferior.PARAMETER_STARTI.get(args);
return impl.gateFuture(impl.gdb.availableInferior().thenCompose(inf -> {
return GdbModelImplUtils.launch(impl, inf, args);
return GdbModelImplUtils.launch(impl, inf, cmdLineArgs, useStarti);
}).thenApply(__ -> null));
}

View file

@ -18,10 +18,8 @@ package agent.gdb.model;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.util.Map;
import agent.gdb.model.impl.GdbModelTargetInferior;
import ghidra.dbg.target.TargetEnvironment;
import ghidra.dbg.target.TargetMethod.ParameterDescription;
import ghidra.dbg.target.TargetMethod.TargetParameterMap;
import ghidra.dbg.test.AbstractDebuggerModelLauncherTest;
@ -34,9 +32,7 @@ public abstract class AbstractModelForGdbLauncherTest extends AbstractDebuggerMo
@Override
public TargetParameterMap getExpectedLauncherParameters() {
return TargetParameterMap.copyOf(Map.ofEntries(
Map.entry("args", ParameterDescription.create(String.class, "args", true, "",
"Command Line", "space-separated command-line arguments"))));
return GdbModelTargetInferior.PARAMETERS;
}
@Override