mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 19:42:36 +02:00
Merge remote-tracking branch 'origin/GP-3084_Dan_hopTraceEventQueueForViews--SQUASHED'
This commit is contained in:
commit
37a0873dc6
6 changed files with 250 additions and 176 deletions
|
@ -26,6 +26,7 @@ import com.google.common.cache.RemovalNotification;
|
|||
import db.DBHandle;
|
||||
import generic.depends.DependentService;
|
||||
import generic.depends.err.ServiceConstructionException;
|
||||
import ghidra.framework.model.DomainObjectChangeRecord;
|
||||
import ghidra.framework.options.Options;
|
||||
import ghidra.lifecycle.Internal;
|
||||
import ghidra.program.model.address.*;
|
||||
|
@ -140,6 +141,8 @@ public class DBTrace extends DBCachedDomainObjectAdapter implements Trace, Trace
|
|||
protected boolean recordChanges = false;
|
||||
|
||||
protected Set<DBTraceTimeViewport> viewports = new WeakHashCowSet<>();
|
||||
protected ListenerSet<DBTraceDirectChangeListener> directListeners =
|
||||
new ListenerSet<>(DBTraceDirectChangeListener.class);
|
||||
protected DBTraceVariableSnapProgramView programView;
|
||||
protected Set<DBTraceVariableSnapProgramView> programViews = new WeakHashCowSet<>();
|
||||
protected Set<TraceProgramView> programViewsView = Collections.unmodifiableSet(programViews);
|
||||
|
@ -586,6 +589,23 @@ public class DBTrace extends DBCachedDomainObjectAdapter implements Trace, Trace
|
|||
fireEvent(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fireEvent(DomainObjectChangeRecord ev) {
|
||||
super.fireEvent(ev);
|
||||
if (directListeners != null) {
|
||||
// Some events fire during construction
|
||||
directListeners.fire.changed(ev);
|
||||
}
|
||||
}
|
||||
|
||||
public void addDirectChangeListener(DBTraceDirectChangeListener listener) {
|
||||
directListeners.add(listener);
|
||||
}
|
||||
|
||||
public void removeDirectChangeListener(DBTraceDirectChangeListener listener) {
|
||||
directListeners.remove(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DBTraceProgramView getFixedProgramView(long snap) {
|
||||
// NOTE: The new viewport will need to read from the time manager during init
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
/* ###
|
||||
* 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.trace.database;
|
||||
|
||||
import ghidra.framework.model.DomainObjectChangeRecord;
|
||||
|
||||
public interface DBTraceDirectChangeListener {
|
||||
void changed(DomainObjectChangeRecord rec);
|
||||
}
|
|
@ -42,8 +42,7 @@ import ghidra.program.model.util.AddressSetPropertyMap;
|
|||
import ghidra.program.model.util.PropertyMapManager;
|
||||
import ghidra.program.util.ChangeManager;
|
||||
import ghidra.program.util.ProgramChangeRecord;
|
||||
import ghidra.trace.database.DBTrace;
|
||||
import ghidra.trace.database.DBTraceTimeViewport;
|
||||
import ghidra.trace.database.*;
|
||||
import ghidra.trace.database.listing.DBTraceCodeSpace;
|
||||
import ghidra.trace.database.listing.DBTraceDefinedUnitsView;
|
||||
import ghidra.trace.database.memory.DBTraceMemorySpace;
|
||||
|
@ -82,7 +81,8 @@ public class DBTraceProgramView implements TraceProgramView {
|
|||
public static final int TIME_INTERVAL = 100;
|
||||
public static final int BUF_SIZE = 1000;
|
||||
|
||||
protected class EventTranslator extends TraceDomainObjectListener {
|
||||
protected class EventTranslator extends TypedEventDispatcher
|
||||
implements DBTraceDirectChangeListener {
|
||||
public EventTranslator() {
|
||||
listenForUntyped(DomainObject.DO_OBJECT_SAVED, this::eventPassthrough);
|
||||
listenForUntyped(DomainObject.DO_DOMAIN_FILE_CHANGED, this::eventPassthrough);
|
||||
|
@ -172,6 +172,11 @@ public class DBTraceProgramView implements TraceProgramView {
|
|||
listenFor(TraceSymbolChangeType.DELETED, this::symbolDeleted);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changed(DomainObjectChangeRecord event) {
|
||||
handleChangeRecord(event);
|
||||
}
|
||||
|
||||
private void eventPassthrough(DomainObjectChangeRecord rec) {
|
||||
fireEventAllViews(rec);
|
||||
}
|
||||
|
@ -1376,7 +1381,7 @@ public class DBTraceProgramView implements TraceProgramView {
|
|||
protected synchronized EventTranslator getEventTranslator() {
|
||||
if (eventTranslator == null) {
|
||||
eventTranslator = new EventTranslator();
|
||||
trace.addListener(eventTranslator);
|
||||
trace.addDirectChangeListener(eventTranslator);
|
||||
}
|
||||
return eventTranslator;
|
||||
}
|
||||
|
|
|
@ -15,164 +15,11 @@
|
|||
*/
|
||||
package ghidra.trace.model;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import ghidra.framework.model.*;
|
||||
import ghidra.trace.util.*;
|
||||
import ghidra.util.TimedMsg;
|
||||
|
||||
public class TraceDomainObjectListener implements DomainObjectListener {
|
||||
|
||||
public interface EventRecordHandler<T, U> {
|
||||
void handle(TraceChangeRecord<T, U> record);
|
||||
}
|
||||
|
||||
public interface FullEventRecordHandler<T, U> extends EventRecordHandler<T, U> {
|
||||
void handle(TraceAddressSpace space, T affectedObject, U oldValue, U newValue);
|
||||
|
||||
@Override
|
||||
default void handle(TraceChangeRecord<T, U> record) {
|
||||
handle(record.getSpace(), record.getAffectedObject(), record.getOldValue(),
|
||||
record.getNewValue());
|
||||
}
|
||||
}
|
||||
|
||||
public interface AffectedObjectHandler<T> extends EventRecordHandler<T, Void> {
|
||||
void handle(TraceAddressSpace space, T affectedObject);
|
||||
|
||||
@Override
|
||||
default void handle(TraceChangeRecord<T, Void> record) {
|
||||
handle(record.getSpace(), record.getAffectedObject());
|
||||
}
|
||||
}
|
||||
|
||||
public interface AffectedObjectOnlyHandler<T> extends EventRecordHandler<T, Void> {
|
||||
void handle(T affectedObject);
|
||||
|
||||
@Override
|
||||
default void handle(TraceChangeRecord<T, Void> record) {
|
||||
handle(record.getAffectedObject());
|
||||
}
|
||||
}
|
||||
|
||||
public interface AffectedAndValuesOnlyHandler<T, U> extends EventRecordHandler<T, U> {
|
||||
void handle(T affectedObject, U oldValue, U newValue);
|
||||
|
||||
@Override
|
||||
default void handle(TraceChangeRecord<T, U> record) {
|
||||
handle(record.getAffectedObject(), record.getOldValue(), record.getNewValue());
|
||||
}
|
||||
}
|
||||
|
||||
public interface SpaceValuesHandler<U> extends EventRecordHandler<Void, U> {
|
||||
void handle(TraceAddressSpace space, U oldValue, U newValue);
|
||||
|
||||
@Override
|
||||
default void handle(TraceChangeRecord<Void, U> record) {
|
||||
handle(record.getSpace(), record.getOldValue(), record.getNewValue());
|
||||
}
|
||||
}
|
||||
|
||||
public interface ValuesOnlyHandler<U> extends EventRecordHandler<Void, U> {
|
||||
void handle(U oldValue, U newValue);
|
||||
|
||||
@Override
|
||||
default void handle(TraceChangeRecord<Void, U> record) {
|
||||
handle(record.getOldValue(), record.getNewValue());
|
||||
}
|
||||
}
|
||||
|
||||
public interface IgnoreValuesHandler extends EventRecordHandler<Object, Object> {
|
||||
void handle(TraceAddressSpace space);
|
||||
|
||||
@Override
|
||||
default void handle(TraceChangeRecord<Object, Object> record) {
|
||||
handle(record.getSpace());
|
||||
}
|
||||
}
|
||||
|
||||
public interface IgnoreAllHandler extends EventRecordHandler<Object, Object> {
|
||||
void handle();
|
||||
|
||||
@Override
|
||||
default void handle(TraceChangeRecord<Object, Object> record) {
|
||||
handle();
|
||||
}
|
||||
}
|
||||
|
||||
private Map<TraceChangeType<?, ?>, EventRecordHandler<?, ?>> typedMap = new HashMap<>();
|
||||
private Map<Integer, Consumer<DomainObjectChangeRecord>> untypedMap = new HashMap<>();
|
||||
private Consumer<DomainObjectChangeRecord> restoredHandler = null;
|
||||
|
||||
protected <T, U> void listenFor(TraceChangeType<T, U> type, EventRecordHandler<T, U> handler) {
|
||||
typedMap.put(type, handler);
|
||||
}
|
||||
|
||||
protected <T, U> void listenFor(TraceChangeType<T, U> type,
|
||||
FullEventRecordHandler<? super T, ? super U> handler) {
|
||||
typedMap.put(type, handler);
|
||||
}
|
||||
|
||||
protected <T, U> void listenFor(TraceChangeType<T, U> type,
|
||||
AffectedObjectHandler<? super T> handler) {
|
||||
typedMap.put(type, handler);
|
||||
}
|
||||
|
||||
protected <T, U> void listenFor(TraceChangeType<T, U> type,
|
||||
AffectedObjectOnlyHandler<? super T> handler) {
|
||||
typedMap.put(type, handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Listen for the given event, taking the affected object, the old value, and the new value
|
||||
*
|
||||
* @param <T> the type of the affected object
|
||||
* @param <U> the type of the values
|
||||
* @param type the event type
|
||||
* @param handler the handler
|
||||
*/
|
||||
protected <T, U> void listenFor(TraceChangeType<T, U> type,
|
||||
AffectedAndValuesOnlyHandler<? super T, ? super U> handler) {
|
||||
typedMap.put(type, handler);
|
||||
}
|
||||
|
||||
protected <T, U> void listenFor(TraceChangeType<T, U> type,
|
||||
ValuesOnlyHandler<? super U> handler) {
|
||||
typedMap.put(type, handler);
|
||||
}
|
||||
|
||||
protected <T, U> void listenFor(TraceChangeType<T, U> type,
|
||||
SpaceValuesHandler<? super U> handler) {
|
||||
typedMap.put(type, handler);
|
||||
}
|
||||
|
||||
protected void listenFor(TraceChangeType<?, ?> type, IgnoreValuesHandler handler) {
|
||||
typedMap.put(type, handler);
|
||||
}
|
||||
|
||||
protected void listenFor(TraceChangeType<?, ?> type, IgnoreAllHandler handler) {
|
||||
typedMap.put(type, handler);
|
||||
}
|
||||
|
||||
protected void listenForUntyped(int type, Consumer<DomainObjectChangeRecord> handler) {
|
||||
if (type == DomainObject.DO_OBJECT_RESTORED) {
|
||||
restoredHandler = handler;
|
||||
}
|
||||
else {
|
||||
untypedMap.put(type, handler);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void handleTraceChangeRecord(TraceChangeRecord<?,?> rec) {
|
||||
@SuppressWarnings("rawtypes")
|
||||
EventRecordHandler handler = typedMap.get(rec.getType());
|
||||
if (handler != null) {
|
||||
handler.handle(rec);
|
||||
}
|
||||
}
|
||||
public class TraceDomainObjectListener extends TypedEventDispatcher
|
||||
implements DomainObjectListener {
|
||||
|
||||
@Override
|
||||
public void domainObjectChanged(DomainObjectChangedEvent ev) {
|
||||
|
@ -189,23 +36,8 @@ public class TraceDomainObjectListener implements DomainObjectListener {
|
|||
}
|
||||
//Map<String, Integer> CountsByType = new TreeMap<>();
|
||||
for (DomainObjectChangeRecord rec : ev) {
|
||||
//String typeName = DefaultTraceChangeType.getName(rec.getEventType());
|
||||
//CountsByType.compute(typeName, (k, v) -> v == null ? 1 : v + 1);
|
||||
if (rec instanceof TraceChangeRecord) {
|
||||
handleTraceChangeRecord((TraceChangeRecord<?, ?>) rec);
|
||||
continue;
|
||||
}
|
||||
Consumer<DomainObjectChangeRecord> handler;
|
||||
if (null != (handler = untypedMap.get(rec.getEventType()))) {
|
||||
handler.accept(rec);
|
||||
continue;
|
||||
}
|
||||
unhandled(rec);
|
||||
handleChangeRecord(rec);
|
||||
}
|
||||
//TimedMsg.info(this, " Done: " + CountsByType);
|
||||
}
|
||||
|
||||
protected void unhandled(DomainObjectChangeRecord rec) {
|
||||
// Extension point
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,195 @@
|
|||
/* ###
|
||||
* 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.trace.model;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import ghidra.framework.model.DomainObject;
|
||||
import ghidra.framework.model.DomainObjectChangeRecord;
|
||||
import ghidra.trace.util.*;
|
||||
|
||||
public class TypedEventDispatcher {
|
||||
|
||||
public interface EventRecordHandler<T, U> {
|
||||
void handle(TraceChangeRecord<T, U> record);
|
||||
}
|
||||
|
||||
public interface FullEventRecordHandler<T, U> extends EventRecordHandler<T, U> {
|
||||
void handle(TraceAddressSpace space, T affectedObject, U oldValue, U newValue);
|
||||
|
||||
@Override
|
||||
default void handle(TraceChangeRecord<T, U> record) {
|
||||
handle(record.getSpace(), record.getAffectedObject(), record.getOldValue(),
|
||||
record.getNewValue());
|
||||
}
|
||||
}
|
||||
|
||||
public interface AffectedObjectHandler<T> extends EventRecordHandler<T, Void> {
|
||||
void handle(TraceAddressSpace space, T affectedObject);
|
||||
|
||||
@Override
|
||||
default void handle(TraceChangeRecord<T, Void> record) {
|
||||
handle(record.getSpace(), record.getAffectedObject());
|
||||
}
|
||||
}
|
||||
|
||||
public interface AffectedObjectOnlyHandler<T> extends EventRecordHandler<T, Void> {
|
||||
void handle(T affectedObject);
|
||||
|
||||
@Override
|
||||
default void handle(TraceChangeRecord<T, Void> record) {
|
||||
handle(record.getAffectedObject());
|
||||
}
|
||||
}
|
||||
|
||||
public interface AffectedAndValuesOnlyHandler<T, U> extends EventRecordHandler<T, U> {
|
||||
void handle(T affectedObject, U oldValue, U newValue);
|
||||
|
||||
@Override
|
||||
default void handle(TraceChangeRecord<T, U> record) {
|
||||
handle(record.getAffectedObject(), record.getOldValue(), record.getNewValue());
|
||||
}
|
||||
}
|
||||
|
||||
public interface SpaceValuesHandler<U> extends EventRecordHandler<Void, U> {
|
||||
void handle(TraceAddressSpace space, U oldValue, U newValue);
|
||||
|
||||
@Override
|
||||
default void handle(TraceChangeRecord<Void, U> record) {
|
||||
handle(record.getSpace(), record.getOldValue(), record.getNewValue());
|
||||
}
|
||||
}
|
||||
|
||||
public interface ValuesOnlyHandler<U> extends EventRecordHandler<Void, U> {
|
||||
void handle(U oldValue, U newValue);
|
||||
|
||||
@Override
|
||||
default void handle(TraceChangeRecord<Void, U> record) {
|
||||
handle(record.getOldValue(), record.getNewValue());
|
||||
}
|
||||
}
|
||||
|
||||
public interface IgnoreValuesHandler extends EventRecordHandler<Object, Object> {
|
||||
void handle(TraceAddressSpace space);
|
||||
|
||||
@Override
|
||||
default void handle(TraceChangeRecord<Object, Object> record) {
|
||||
handle(record.getSpace());
|
||||
}
|
||||
}
|
||||
|
||||
public interface IgnoreAllHandler extends EventRecordHandler<Object, Object> {
|
||||
void handle();
|
||||
|
||||
@Override
|
||||
default void handle(TraceChangeRecord<Object, Object> record) {
|
||||
handle();
|
||||
}
|
||||
}
|
||||
|
||||
private Map<TraceChangeType<?, ?>, EventRecordHandler<?, ?>> typedMap = new HashMap<>();
|
||||
private Map<Integer, Consumer<DomainObjectChangeRecord>> untypedMap = new HashMap<>();
|
||||
protected Consumer<DomainObjectChangeRecord> restoredHandler = null;
|
||||
|
||||
protected <T, U> void listenFor(TraceChangeType<T, U> type, EventRecordHandler<T, U> handler) {
|
||||
typedMap.put(type, handler);
|
||||
}
|
||||
|
||||
protected <T, U> void listenFor(TraceChangeType<T, U> type,
|
||||
FullEventRecordHandler<? super T, ? super U> handler) {
|
||||
typedMap.put(type, handler);
|
||||
}
|
||||
|
||||
protected <T, U> void listenFor(TraceChangeType<T, U> type,
|
||||
AffectedObjectHandler<? super T> handler) {
|
||||
typedMap.put(type, handler);
|
||||
}
|
||||
|
||||
protected <T, U> void listenFor(TraceChangeType<T, U> type,
|
||||
AffectedObjectOnlyHandler<? super T> handler) {
|
||||
typedMap.put(type, handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Listen for the given event, taking the affected object, the old value, and the new value
|
||||
*
|
||||
* @param <T> the type of the affected object
|
||||
* @param <U> the type of the values
|
||||
* @param type the event type
|
||||
* @param handler the handler
|
||||
*/
|
||||
protected <T, U> void listenFor(TraceChangeType<T, U> type,
|
||||
AffectedAndValuesOnlyHandler<? super T, ? super U> handler) {
|
||||
typedMap.put(type, handler);
|
||||
}
|
||||
|
||||
protected <T, U> void listenFor(TraceChangeType<T, U> type,
|
||||
ValuesOnlyHandler<? super U> handler) {
|
||||
typedMap.put(type, handler);
|
||||
}
|
||||
|
||||
protected <T, U> void listenFor(TraceChangeType<T, U> type,
|
||||
SpaceValuesHandler<? super U> handler) {
|
||||
typedMap.put(type, handler);
|
||||
}
|
||||
|
||||
protected void listenFor(TraceChangeType<?, ?> type, IgnoreValuesHandler handler) {
|
||||
typedMap.put(type, handler);
|
||||
}
|
||||
|
||||
protected void listenFor(TraceChangeType<?, ?> type, IgnoreAllHandler handler) {
|
||||
typedMap.put(type, handler);
|
||||
}
|
||||
|
||||
protected void listenForUntyped(int type, Consumer<DomainObjectChangeRecord> handler) {
|
||||
if (type == DomainObject.DO_OBJECT_RESTORED) {
|
||||
restoredHandler = handler;
|
||||
}
|
||||
else {
|
||||
untypedMap.put(type, handler);
|
||||
}
|
||||
}
|
||||
|
||||
public void handleChangeRecord(DomainObjectChangeRecord rec) {
|
||||
//String typeName = DefaultTraceChangeType.getName(rec.getEventType());
|
||||
//CountsByType.compute(typeName, (k, v) -> v == null ? 1 : v + 1);
|
||||
if (rec instanceof TraceChangeRecord) {
|
||||
handleTraceChangeRecord((TraceChangeRecord<?, ?>) rec);
|
||||
return;
|
||||
}
|
||||
Consumer<DomainObjectChangeRecord> handler;
|
||||
if (null != (handler = untypedMap.get(rec.getEventType()))) {
|
||||
handler.accept(rec);
|
||||
return;
|
||||
}
|
||||
unhandled(rec);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void handleTraceChangeRecord(TraceChangeRecord<?, ?> rec) {
|
||||
@SuppressWarnings("rawtypes")
|
||||
EventRecordHandler handler = typedMap.get(rec.getType());
|
||||
if (handler != null) {
|
||||
handler.handle(rec);
|
||||
}
|
||||
}
|
||||
|
||||
protected void unhandled(DomainObjectChangeRecord rec) {
|
||||
// Extension point
|
||||
}
|
||||
}
|
|
@ -65,7 +65,7 @@ class DomainObjectChangeSupport {
|
|||
this.timer =
|
||||
GhidraTimerFactory.getGhidraTimer(timeInterval, timeInterval, this::sendEventNow);
|
||||
timer.setInitialDelay(25);
|
||||
timer.setDelay(500);
|
||||
timer.setDelay(timeInterval);
|
||||
timer.setRepeats(true);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue