GP-1808: Added 'Run to Address'-type actions to right-click menu for some connectors.

This commit is contained in:
Dan 2023-02-07 12:23:16 -05:00
parent 44d7c4f031
commit bde529b4d5
39 changed files with 1663 additions and 136 deletions

View file

@ -123,6 +123,30 @@ public interface GdbThread
*/
CompletableFuture<Void> step(StepCmd suffix);
/**
* Advance the thread to the given location
*
* <p>
* This is equivalent to the CLI command {@code advance}.
*
* <p>
* Note that the command can complete before the thread has finished advancing. The command
* completes as soon as the thread is running. A separate stop event is emitted when the thread
* has stopped.
*
* @param loc the location to stop at, same syntax as breakpoint locations
* @return a future that completes once the thread is running
*/
CompletableFuture<Void> advance(String loc);
/**
* Advance the thread to the given address
*
* @param addr the address
* @see #advance(String)
*/
CompletableFuture<Void> advance(long addr);
/**
* Detach from the entire process
*

View file

@ -45,6 +45,7 @@ public interface GdbBreakpointInsertions {
/**
* Insert a breakpoint (usually a watchpoint) at the given address range
*
* <p>
* Note, this implements the length by casting the address pointer to a
* fixed-length-char-array-pointer where the array has the given length. Support for specific
* lengths may vary by platform.

View file

@ -286,6 +286,17 @@ public class GdbThreadImpl implements GdbThread {
return execute(new GdbStepCommand(manager, id, suffix));
}
@Override
public CompletableFuture<Void> advance(String loc) {
// There's no exec-advance or similar in MI2....
return console("advance " + loc, CompletesWithRunning.MUST);
}
@Override
public CompletableFuture<Void> advance(long addr) {
return advance(String.format("*0x%x", addr));
}
@Override
public CompletableFuture<Void> kill() {
return execute(new GdbKillCommand(manager, id));

View file

@ -192,9 +192,6 @@ public class GdbModelTargetInferior
case SKIP:
case EXTENDED:
throw new UnsupportedOperationException(kind.name());
case ADVANCE: // Why no exec-advance in GDB/MI?
// TODO: This doesn't work, since advance requires a parameter
return model.gateFuture(inferior.console("advance", CompletesWithRunning.MUST));
default:
return model.gateFuture(inferior.step(GdbModelTargetThread.convertToGdb(kind)));
}

View file

@ -15,6 +15,7 @@
*/
package agent.gdb.model.impl;
import java.lang.invoke.MethodHandles;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
@ -24,14 +25,15 @@ import agent.gdb.manager.GdbManager.StepCmd;
import agent.gdb.manager.impl.GdbFrameInfo;
import agent.gdb.manager.impl.GdbThreadInfo;
import agent.gdb.manager.impl.cmd.GdbStateChangeRecord;
import agent.gdb.manager.impl.cmd.GdbConsoleExecCommand.CompletesWithRunning;
import agent.gdb.manager.reason.GdbBreakpointHitReason;
import ghidra.async.AsyncUtils;
import ghidra.dbg.agent.DefaultTargetObject;
import ghidra.dbg.target.*;
import ghidra.dbg.target.TargetMethod.AnnotatedTargetMethod;
import ghidra.dbg.target.schema.*;
import ghidra.dbg.util.PathUtils;
import ghidra.lifecycle.Internal;
import ghidra.program.model.address.Address;
import ghidra.util.Msg;
@TargetObjectSchemaInfo(
@ -44,15 +46,13 @@ public class GdbModelTargetThread
extends DefaultTargetObject<TargetObject, GdbModelTargetThreadContainer> implements
TargetThread, TargetExecutionStateful, TargetSteppable, TargetAggregate,
GdbModelSelectableObject {
protected static final TargetStepKindSet SUPPORTED_KINDS = TargetStepKindSet.of( //
TargetStepKind.ADVANCE, //
TargetStepKind.FINISH, //
TargetStepKind.LINE, //
TargetStepKind.OVER, //
TargetStepKind.OVER_LINE, //
TargetStepKind.RETURN, //
TargetStepKind.UNTIL, //
TargetStepKind.EXTENDED);
protected static final TargetStepKindSet SUPPORTED_KINDS = TargetStepKindSet.of(
TargetStepKind.FINISH,
TargetStepKind.LINE,
TargetStepKind.OVER,
TargetStepKind.OVER_LINE,
TargetStepKind.RETURN,
TargetStepKind.UNTIL);
protected static String indexThread(int threadId) {
return PathUtils.makeIndex(threadId);
@ -87,12 +87,15 @@ public class GdbModelTargetThread
this.stack = new GdbModelTargetStack(this, inferior);
changeAttributes(List.of(), List.of(stack), Map.of( //
STATE_ATTRIBUTE_NAME, state = convertState(thread.getState()), //
SUPPORTED_STEP_KINDS_ATTRIBUTE_NAME, SUPPORTED_KINDS, //
SHORT_DISPLAY_ATTRIBUTE_NAME, shortDisplay = computeShortDisplay(), //
DISPLAY_ATTRIBUTE_NAME, display = computeDisplay() //
), "Initialized");
changeAttributes(List.of(), List.of(),
AnnotatedTargetMethod.collectExports(MethodHandles.lookup(), impl, this),
"Methods");
changeAttributes(List.of(), List.of(stack), Map.of(
STATE_ATTRIBUTE_NAME, state = convertState(thread.getState()),
SUPPORTED_STEP_KINDS_ATTRIBUTE_NAME, SUPPORTED_KINDS,
SHORT_DISPLAY_ATTRIBUTE_NAME, shortDisplay = computeShortDisplay(),
DISPLAY_ATTRIBUTE_NAME, display = computeDisplay()),
"Initialized");
updateInfo().exceptionally(ex -> {
Msg.error(this, "Could not initialize thread info");
@ -214,14 +217,20 @@ public class GdbModelTargetThread
case SKIP:
case EXTENDED:
throw new UnsupportedOperationException(kind.name());
case ADVANCE: // Why no exec-advance in GDB/MI?
// TODO: This doesn't work, since advance requires a parameter
return model.gateFuture(thread.console("advance", CompletesWithRunning.CANNOT));
default:
return model.gateFuture(thread.step(convertToGdb(kind)));
}
}
@TargetMethod.Export("Advance")
public CompletableFuture<Void> advance(
@TargetMethod.Param(
name = "target",
display = "Target",
description = "The address to advance to") Address target) {
return impl.gateFuture(thread.advance(target.getOffset()));
}
protected void invalidateRegisterCaches() {
stack.invalidateRegisterCaches();
}
@ -257,5 +266,4 @@ public class GdbModelTargetThread
this.base = (Integer) value;
updateInfo();
}
}