GP-844: Fixed focus issues, introduced "activation"

This commit is contained in:
Dan 2021-04-12 10:15:48 -04:00
parent 62bd317380
commit 997ab4d9a0
71 changed files with 554 additions and 300 deletions

View file

@ -813,6 +813,26 @@ public enum DebugModelConventions {
return collectAncestors.thenApply(AllRequiredAccess::new);
}
/**
* Request activation of the given object in its nearest active scope
*
* <p>
* Note if the object has no suitable active scope, this method fails silently.
*
* @param obj the object on which to request activation
* @return a future which completes when activation is granted, or exceptionally
*/
public static CompletableFuture<Void> requestActivation(TargetObject obj) {
CompletableFuture<? extends TargetActiveScope> futureActivator =
DebugModelConventions.findSuitable(TargetActiveScope.class, obj);
return futureActivator.thenCompose(activator -> {
if (activator == null) {
return AsyncUtils.NIL;
}
return activator.requestActivation(obj);
});
}
/**
* Request focus on the given object in its nearest focus scope
*

View file

@ -0,0 +1,38 @@
/* ###
* 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.dbg.target;
import java.util.concurrent.CompletableFuture;
import ghidra.dbg.DebuggerTargetObjectIface;
/**
* An object made active
*
* "Active" here describes which object in a given class the target should operate on
*/
@DebuggerTargetObjectIface("ActiveScope")
public interface TargetActiveScope extends TargetObject {
/**
* Set the given object as the target's active object for the given type
*
* @param obj the object to setActive
* @return a future which completes upon successfully changing focus.
*/
CompletableFuture<Void> requestActivation(TargetObject obj);
}

View file

@ -27,8 +27,7 @@ import ghidra.dbg.target.schema.TargetAttributeType;
@DebuggerTargetObjectIface("EventScope")
public interface TargetEventScope extends TargetObject {
String EVENT_PROCESS_ATTRIBUTE_NAME = PREFIX_INVISIBLE + "event_process";
String EVENT_THREAD_ATTRIBUTE_NAME = PREFIX_INVISIBLE + "event_thread";
String EVENT_OBJECT_ATTRIBUTE_NAME = PREFIX_INVISIBLE + "event_thread";
public enum TargetEventType {
/**
@ -116,33 +115,13 @@ public interface TargetEventScope extends TargetObject {
}
}
/**
* If applicable, get the process producing the last reported event
*
* <p>
* TODO: This is currently the hexadecimal PID. It should really be a ref to the process object.
*
* <p>
* TODO: Since the event thread will be a successor of the event process, this may not be
* needed, but perhaps keep it for convenience.
*
* @return the process or reference
*/
@TargetAttributeType(name = EVENT_PROCESS_ATTRIBUTE_NAME, hidden = true)
public default /*TODO: TargetProcess*/ String getEventProcess() {
return getTypedAttributeNowByName(EVENT_PROCESS_ATTRIBUTE_NAME, String.class, null);
}
/**
* If applicable, get the thread producing the last reported event
*
* <p>
* TODO: This is currently the hexadecimal TID. It should really be a ref to the thread object.
*
* @return the thread or reference
*/
@TargetAttributeType(name = EVENT_THREAD_ATTRIBUTE_NAME, hidden = true)
public default /*TODO: TargetThread*/ String getEventThread() {
return getTypedAttributeNowByName(EVENT_THREAD_ATTRIBUTE_NAME, String.class, null);
@TargetAttributeType(name = EVENT_OBJECT_ATTRIBUTE_NAME, hidden = true)
public default TargetThread getEventThread() {
return getTypedAttributeNowByName(EVENT_OBJECT_ATTRIBUTE_NAME, TargetThread.class, null);
}
}

View file

@ -158,20 +158,21 @@ import ghidra.lifecycle.Internal;
*/
public interface TargetObject extends Comparable<TargetObject> {
Set<Class<? extends TargetObject>> ALL_INTERFACES = Set.of(TargetAccessConditioned.class,
TargetAggregate.class, TargetAttachable.class, TargetAttacher.class,
TargetBreakpointLocation.class, TargetBreakpointLocationContainer.class,
TargetBreakpointSpec.class, TargetBreakpointSpecContainer.class, TargetConsole.class,
TargetDataTypeMember.class, TargetDataTypeNamespace.class, TargetDeletable.class,
TargetDetachable.class, TargetEnvironment.class, TargetEventScope.class,
TargetExecutionStateful.class, TargetFocusScope.class, TargetInterpreter.class,
TargetInterruptible.class, TargetKillable.class, TargetLauncher.class, TargetMemory.class,
TargetMemoryRegion.class, TargetMethod.class, TargetModule.class,
TargetModuleContainer.class, TargetNamedDataType.class, TargetProcess.class,
TargetRegister.class, TargetRegisterBank.class, TargetRegisterContainer.class,
TargetResumable.class, TargetSection.class, TargetSectionContainer.class, TargetStack.class,
TargetStackFrame.class, TargetSteppable.class, TargetSymbol.class,
TargetSymbolNamespace.class, TargetThread.class, TargetTogglable.class);
Set<Class<? extends TargetObject>> ALL_INTERFACES =
Set.of(TargetAccessConditioned.class, TargetAggregate.class, TargetAttachable.class,
TargetAttacher.class, TargetBreakpointLocation.class,
TargetBreakpointLocationContainer.class, TargetBreakpointSpec.class,
TargetBreakpointSpecContainer.class, TargetConsole.class, TargetDataTypeMember.class,
TargetDataTypeNamespace.class, TargetDeletable.class, TargetDetachable.class,
TargetEnvironment.class, TargetEventScope.class, TargetExecutionStateful.class,
TargetActiveScope.class, TargetFocusScope.class, TargetInterpreter.class,
TargetInterruptible.class, TargetKillable.class, TargetLauncher.class,
TargetMemory.class, TargetMemoryRegion.class, TargetMethod.class, TargetModule.class,
TargetModuleContainer.class, TargetNamedDataType.class, TargetProcess.class,
TargetRegister.class, TargetRegisterBank.class, TargetRegisterContainer.class,
TargetResumable.class, TargetSection.class, TargetSectionContainer.class,
TargetStack.class, TargetStackFrame.class, TargetSteppable.class, TargetSymbol.class,
TargetSymbolNamespace.class, TargetThread.class, TargetTogglable.class);
Map<String, Class<? extends TargetObject>> INTERFACES_BY_NAME = initInterfacesByName();
/**
@ -300,8 +301,7 @@ public interface TargetObject extends Comparable<TargetObject> {
return false;
}
TargetObject that = (TargetObject) obj;
return this.getModel() == that.getModel() &&
Objects.equals(this.getPath(), that.getPath());
return this.getModel() == that.getModel() && Objects.equals(this.getPath(), that.getPath());
}
/**
@ -371,8 +371,7 @@ public interface TargetObject extends Comparable<TargetObject> {
}
int result = thisModel.toString().compareTo(thatModel.toString());
if (result == 0) {
return Integer.compare(
System.identityHashCode(thisModel),
return Integer.compare(System.identityHashCode(thisModel),
System.identityHashCode(thatModel));
}
return result;
@ -707,8 +706,7 @@ public interface TargetObject extends Comparable<TargetObject> {
* interface
*/
public default <T extends TargetObject> //
CompletableFuture<? extends Map<String, ? extends T>> fetchChildrenSupporting(
Class<T> iface) {
CompletableFuture<? extends Map<String, ? extends T>> fetchChildrenSupporting(Class<T> iface) {
return fetchChildren().thenApply(m -> m.entrySet()
.stream()
.filter(e -> iface.isAssignableFrom(e.getValue().getClass()))
@ -793,8 +791,7 @@ public interface TargetObject extends Comparable<TargetObject> {
/**
* @see #fetchSubAttributes(List)
*/
public default CompletableFuture<? extends Map<String, ?>> fetchSubAttributes(
String... sub) {
public default CompletableFuture<? extends Map<String, ?>> fetchSubAttributes(String... sub) {
return fetchSubAttributes(List.of(sub));
}