mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 19:42:36 +02:00
GP-844: Fixed focus issues, introduced "activation"
This commit is contained in:
parent
62bd317380
commit
997ab4d9a0
71 changed files with 554 additions and 300 deletions
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue