mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 02:39:44 +02:00
GP-1808: Added 'Run to Address'-type actions to right-click menu for some connectors.
This commit is contained in:
parent
44d7c4f031
commit
bde529b4d5
39 changed files with 1663 additions and 136 deletions
|
@ -120,6 +120,22 @@ public interface DbgThread
|
|||
*/
|
||||
CompletableFuture<Void> step(Map<String, ?> args);
|
||||
|
||||
/**
|
||||
* Step (over) the thread until the specified address is reached
|
||||
*
|
||||
* @param address the stop address
|
||||
* @return a future that completes once the thread is running
|
||||
*/
|
||||
CompletableFuture<Void> stepToAddress(String address);
|
||||
|
||||
/**
|
||||
* Trace (step into) the thread until the specified address is reached
|
||||
*
|
||||
* @param address the stop address
|
||||
* @return a future that completes once the thread is running
|
||||
*/
|
||||
CompletableFuture<Void> traceToAddress(String address);
|
||||
|
||||
/**
|
||||
* Detach from the entire process
|
||||
*
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
/* ###
|
||||
* 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 agent.dbgeng.manager.cmd;
|
||||
|
||||
import agent.dbgeng.dbgeng.DebugControl;
|
||||
import agent.dbgeng.dbgeng.DebugThreadId;
|
||||
import agent.dbgeng.manager.DbgEvent;
|
||||
import agent.dbgeng.manager.evt.*;
|
||||
import agent.dbgeng.manager.impl.DbgManagerImpl;
|
||||
import agent.dbgeng.manager.impl.DbgThreadImpl;
|
||||
import ghidra.util.Msg;
|
||||
|
||||
public abstract class AbstractDbgExecToAddressCommand extends AbstractDbgCommand<Void> {
|
||||
|
||||
private final DebugThreadId id;
|
||||
private final String address;
|
||||
|
||||
public AbstractDbgExecToAddressCommand(DbgManagerImpl manager, DebugThreadId id,
|
||||
String address) {
|
||||
super(manager);
|
||||
this.id = id;
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(DbgEvent<?> evt, DbgPendingCommand<?> pending) {
|
||||
if (evt instanceof AbstractDbgCompletedCommandEvent && pending.getCommand().equals(this)) {
|
||||
return evt instanceof DbgCommandErrorEvent ||
|
||||
!pending.findAllOf(DbgRunningEvent.class).isEmpty();
|
||||
}
|
||||
else if (evt instanceof DbgRunningEvent) {
|
||||
// Event happens no matter which interpreter received the command
|
||||
pending.claim(evt);
|
||||
return !pending.findAllOf(AbstractDbgCompletedCommandEvent.class).isEmpty();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected abstract String generateCommand(String address);
|
||||
|
||||
@Override
|
||||
public void invoke() {
|
||||
String cmd = generateCommand(address);
|
||||
String prefix = id == null ? "" : "~" + id.id + " ";
|
||||
DebugControl control = manager.getControl();
|
||||
DbgThreadImpl eventThread = manager.getEventThread();
|
||||
if (eventThread != null && eventThread.getId().equals(id)) {
|
||||
control.execute(cmd);
|
||||
}
|
||||
else {
|
||||
if (manager.isKernelMode()) {
|
||||
Msg.info(this, "Thread-specific steppign is ignored in kernel-mode");
|
||||
control.execute(cmd);
|
||||
}
|
||||
else {
|
||||
control.execute(prefix + cmd);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/* ###
|
||||
* 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 agent.dbgeng.manager.cmd;
|
||||
|
||||
import agent.dbgeng.dbgeng.DebugThreadId;
|
||||
import agent.dbgeng.manager.impl.DbgManagerImpl;
|
||||
|
||||
public class DbgStepToAddressCommand extends AbstractDbgExecToAddressCommand {
|
||||
|
||||
public DbgStepToAddressCommand(DbgManagerImpl manager, DebugThreadId id, String address) {
|
||||
super(manager, id, address);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String generateCommand(String address) {
|
||||
return "pa " + address;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/* ###
|
||||
* 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 agent.dbgeng.manager.cmd;
|
||||
|
||||
import agent.dbgeng.dbgeng.DebugThreadId;
|
||||
import agent.dbgeng.manager.impl.DbgManagerImpl;
|
||||
|
||||
public class DbgTraceToAddressCommand extends AbstractDbgExecToAddressCommand {
|
||||
|
||||
public DbgTraceToAddressCommand(DbgManagerImpl manager, DebugThreadId id, String address) {
|
||||
super(manager, id, address);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String generateCommand(String address) {
|
||||
return "ta " + address;
|
||||
}
|
||||
}
|
|
@ -225,6 +225,20 @@ public class DbgThreadImpl implements DbgThread {
|
|||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> stepToAddress(String address) {
|
||||
return setActive().thenCompose(__ -> {
|
||||
return manager.execute(new DbgStepToAddressCommand(manager, id, address));
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> traceToAddress(String address) {
|
||||
return setActive().thenCompose(__ -> {
|
||||
return manager.execute(new DbgTraceToAddressCommand(manager, id, address));
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> kill() {
|
||||
return setActive().thenCompose(__ -> {
|
||||
|
|
|
@ -61,8 +61,6 @@ public interface DbgModelTargetSteppable extends DbgModelTargetObject, TargetSte
|
|||
switch (kind) {
|
||||
case SKIP:
|
||||
throw new UnsupportedOperationException(kind.name());
|
||||
case ADVANCE: // Why no exec-advance in dbgeng?
|
||||
return thread.console("advance");
|
||||
default:
|
||||
if (this instanceof DbgModelTargetThread) {
|
||||
DbgModelTargetThread targetThread = (DbgModelTargetThread) this;
|
||||
|
|
|
@ -23,11 +23,13 @@ import agent.dbgeng.manager.*;
|
|||
import agent.dbgeng.manager.impl.*;
|
||||
import agent.dbgeng.model.iface1.*;
|
||||
import agent.dbgeng.model.impl.DbgModelTargetStackImpl;
|
||||
import ghidra.dbg.target.TargetThread;
|
||||
import ghidra.dbg.target.*;
|
||||
import ghidra.dbg.util.PathUtils;
|
||||
import ghidra.program.model.address.Address;
|
||||
|
||||
public interface DbgModelTargetThread extends //
|
||||
TargetThread, //
|
||||
TargetAggregate, //
|
||||
DbgModelTargetAccessConditioned, //
|
||||
DbgModelTargetExecutionStateful, //
|
||||
DbgModelTargetSteppable, //
|
||||
|
@ -58,6 +60,24 @@ public interface DbgModelTargetThread extends //
|
|||
}
|
||||
}
|
||||
|
||||
@TargetMethod.Export("Step to Address (pa)")
|
||||
public default CompletableFuture<Void> stepToAddress(
|
||||
@TargetMethod.Param(
|
||||
description = "The target address",
|
||||
display = "StopAddress",
|
||||
name = "address") Address address) {
|
||||
return getModel().gateFuture(getThread().stepToAddress(address.toString(false)));
|
||||
}
|
||||
|
||||
@TargetMethod.Export("Trace to Address (ta)")
|
||||
public default CompletableFuture<Void> traceToAddress(
|
||||
@TargetMethod.Param(
|
||||
description = "The target address",
|
||||
display = "StopAddress",
|
||||
name = "address") Address address) {
|
||||
return getModel().gateFuture(getThread().traceToAddress(address.toString(false)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public default CompletableFuture<Void> setActive() {
|
||||
DbgManagerImpl manager = getManager();
|
||||
|
|
|
@ -183,8 +183,6 @@ public class DbgModelTargetProcessImpl extends DbgModelTargetObjectImpl
|
|||
switch (kind) {
|
||||
case SKIP:
|
||||
throw new UnsupportedOperationException(kind.name());
|
||||
case ADVANCE: // Why no exec-advance in dbgeng?
|
||||
throw new UnsupportedOperationException(kind.name());
|
||||
default:
|
||||
return model.gateFuture(process.step(convertToDbg(kind)));
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
*/
|
||||
package agent.dbgeng.model.impl;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
@ -26,6 +27,7 @@ import agent.dbgeng.model.iface1.DbgModelTargetFocusScope;
|
|||
import agent.dbgeng.model.iface2.*;
|
||||
import ghidra.dbg.target.TargetEnvironment;
|
||||
import ghidra.dbg.target.TargetFocusScope;
|
||||
import ghidra.dbg.target.TargetMethod.AnnotatedTargetMethod;
|
||||
import ghidra.dbg.target.schema.*;
|
||||
import ghidra.dbg.util.PathUtils;
|
||||
|
||||
|
@ -50,7 +52,6 @@ public class DbgModelTargetThreadImpl extends DbgModelTargetObjectImpl
|
|||
implements DbgModelTargetThread {
|
||||
|
||||
public static final TargetStepKindSet SUPPORTED_KINDS = TargetStepKindSet.of( //
|
||||
TargetStepKind.ADVANCE, //
|
||||
TargetStepKind.FINISH, //
|
||||
TargetStepKind.LINE, //
|
||||
TargetStepKind.OVER, //
|
||||
|
@ -90,6 +91,9 @@ public class DbgModelTargetThreadImpl extends DbgModelTargetObjectImpl
|
|||
this.registers = new DbgModelTargetRegisterContainerImpl(this);
|
||||
this.stack = new DbgModelTargetStackImpl(this, process);
|
||||
|
||||
changeAttributes(List.of(), List.of(),
|
||||
AnnotatedTargetMethod.collectExports(MethodHandles.lookup(), threads.getModel(), this),
|
||||
"Methods");
|
||||
changeAttributes(List.of(), List.of( //
|
||||
registers, //
|
||||
stack //
|
||||
|
@ -145,8 +149,6 @@ public class DbgModelTargetThreadImpl extends DbgModelTargetObjectImpl
|
|||
switch (kind) {
|
||||
case SKIP:
|
||||
throw new UnsupportedOperationException(kind.name());
|
||||
case ADVANCE: // Why no exec-advance in GDB/MI?
|
||||
return thread.console("advance");
|
||||
default:
|
||||
return model.gateFuture(thread.step(convertToDbg(kind)));
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue