mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2024-10-23 13:41:04 +00:00
GP-571: dbgeng schema implementation
This commit is contained in:
parent
eb66a90f6c
commit
c81a17405d
|
@ -26,8 +26,14 @@ import agent.dbgeng.manager.breakpoint.DbgBreakpointType;
|
|||
import ghidra.async.AsyncFence;
|
||||
import ghidra.dbg.target.TargetBreakpointContainer;
|
||||
import ghidra.dbg.target.TargetBreakpointSpec.TargetBreakpointKind;
|
||||
import ghidra.dbg.target.schema.*;
|
||||
import ghidra.program.model.address.AddressRange;
|
||||
|
||||
@TargetObjectSchemaInfo(name = "BreakpointContainer", elements = {
|
||||
@TargetElementType(type = DbgModelTargetBreakpointSpec.class)
|
||||
}, attributes = {
|
||||
@TargetAttributeType(type = Void.class)
|
||||
}, canonicalContainer = true)
|
||||
public interface DbgModelTargetBreakpointContainer extends DbgModelTargetObject,
|
||||
TargetBreakpointContainer<DbgModelTargetBreakpointContainer>, DbgEventsListenerAdapter {
|
||||
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
*/
|
||||
package agent.dbgeng.model.iface2;
|
||||
|
||||
public interface DbgModelTargetDebugContainer extends
|
||||
DbgModelTargetObject {
|
||||
public interface DbgModelTargetDebugContainer extends DbgModelTargetObject {
|
||||
|
||||
}
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
*/
|
||||
package agent.dbgeng.model.iface2;
|
||||
|
||||
public interface DbgModelTargetModuleSectionContainer
|
||||
extends DbgModelTargetObject {
|
||||
public interface DbgModelTargetModuleSectionContainer extends DbgModelTargetObject {
|
||||
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
package agent.dbgeng.model.impl;
|
||||
|
||||
import ghidra.dbg.target.TargetAggregate;
|
||||
import ghidra.dbg.target.schema.TargetObjectSchema;
|
||||
|
||||
public class DbgModelDefaultTargetModelRoot extends DbgModelTargetObjectImpl
|
||||
implements TargetAggregate {
|
||||
|
@ -23,4 +24,10 @@ public class DbgModelDefaultTargetModelRoot extends DbgModelTargetObjectImpl
|
|||
public DbgModelDefaultTargetModelRoot(DbgModelImpl model, String typeHint) {
|
||||
super(model, null, null, typeHint);
|
||||
}
|
||||
|
||||
public DbgModelDefaultTargetModelRoot(DbgModelImpl model, String typeHint,
|
||||
TargetObjectSchema schema) {
|
||||
super(model, null, null, typeHint, schema);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -26,6 +26,8 @@ import agent.dbgeng.model.AbstractDbgModel;
|
|||
import agent.dbgeng.model.iface2.DbgModelTargetSession;
|
||||
import agent.dbgeng.model.iface2.DbgModelTargetSessionContainer;
|
||||
import ghidra.dbg.target.TargetObject;
|
||||
import ghidra.dbg.target.schema.AnnotatedSchemaContext;
|
||||
import ghidra.dbg.target.schema.TargetObjectSchema;
|
||||
import ghidra.program.model.address.*;
|
||||
|
||||
public class DbgModelImpl extends AbstractDbgModel {
|
||||
|
@ -33,6 +35,10 @@ public class DbgModelImpl extends AbstractDbgModel {
|
|||
// The model must convert to and from Ghidra's address space names
|
||||
protected static final String SPACE_NAME = "ram";
|
||||
|
||||
protected static final AnnotatedSchemaContext SCHEMA_CTX = new AnnotatedSchemaContext();
|
||||
protected static final TargetObjectSchema ROOT_SCHEMA =
|
||||
SCHEMA_CTX.getSchemaForClass(DbgModelTargetRootImpl.class);
|
||||
|
||||
// Don't make this static, so each model has a unique "GDB" space
|
||||
protected final AddressSpace space =
|
||||
new GenericAddressSpace(SPACE_NAME, 64, AddressSpace.TYPE_RAM, 0);
|
||||
|
@ -47,7 +53,8 @@ public class DbgModelImpl extends AbstractDbgModel {
|
|||
|
||||
public DbgModelImpl() {
|
||||
this.dbg = DbgManager.newInstance();
|
||||
this.root = new DbgModelTargetRootImpl(this);
|
||||
//System.out.println(XmlSchemaContext.serialize(SCHEMA_CTX));
|
||||
this.root = new DbgModelTargetRootImpl(this, ROOT_SCHEMA);
|
||||
this.completedRoot = CompletableFuture.completedFuture(root);
|
||||
DbgSessionImpl s = new DbgSessionImpl((DbgManagerImpl) dbg, new DebugSessionId(0));
|
||||
s.add();
|
||||
|
|
|
@ -24,8 +24,14 @@ import org.apache.commons.lang3.tuple.Pair;
|
|||
|
||||
import agent.dbgeng.model.iface2.*;
|
||||
import ghidra.dbg.target.TargetObject;
|
||||
import ghidra.dbg.target.schema.*;
|
||||
import ghidra.util.datastruct.WeakValueHashMap;
|
||||
|
||||
@TargetObjectSchemaInfo(name = "AvailableContainer", elements = { //
|
||||
@TargetElementType(type = DbgModelTargetAvailableImpl.class) //
|
||||
}, attributes = { //
|
||||
@TargetAttributeType(type = Void.class) //
|
||||
}, canonicalContainer = true)
|
||||
public class DbgModelTargetAvailableContainerImpl extends DbgModelTargetObjectImpl
|
||||
implements DbgModelTargetAvailableContainer {
|
||||
|
||||
|
|
|
@ -20,8 +20,14 @@ import java.util.Map;
|
|||
|
||||
import agent.dbgeng.model.iface2.DbgModelTargetAvailable;
|
||||
import agent.dbgeng.model.iface2.DbgModelTargetAvailableContainer;
|
||||
import ghidra.dbg.target.schema.*;
|
||||
import ghidra.dbg.util.PathUtils;
|
||||
|
||||
@TargetObjectSchemaInfo(name = "Available", elements = { //
|
||||
@TargetElementType(type = Void.class) //
|
||||
}, attributes = { //
|
||||
@TargetAttributeType(type = Void.class) //
|
||||
})
|
||||
public class DbgModelTargetAvailableImpl extends DbgModelTargetObjectImpl
|
||||
implements DbgModelTargetAvailable {
|
||||
|
||||
|
@ -44,7 +50,7 @@ public class DbgModelTargetAvailableImpl extends DbgModelTargetObjectImpl
|
|||
this.pid = pid;
|
||||
|
||||
this.changeAttributes(List.of(), List.of(), Map.of(//
|
||||
PID_ATTRIBUTE_NAME, pid, //
|
||||
PID_ATTRIBUTE_NAME, (long) pid, //
|
||||
DISPLAY_ATTRIBUTE_NAME, keyAttachable(pid) + " : " + name.trim(),
|
||||
UPDATE_MODE_ATTRIBUTE_NAME, TargetUpdateMode.FIXED //
|
||||
), "Initialized");
|
||||
|
@ -61,6 +67,7 @@ public class DbgModelTargetAvailableImpl extends DbgModelTargetObjectImpl
|
|||
), "Initialized");
|
||||
}
|
||||
|
||||
@TargetAttributeType(name = PID_ATTRIBUTE_NAME, hidden = true)
|
||||
@Override
|
||||
public long getPid() {
|
||||
return pid;
|
||||
|
|
|
@ -26,8 +26,14 @@ import agent.dbgeng.manager.impl.DbgManagerImpl;
|
|||
import agent.dbgeng.model.iface2.*;
|
||||
import ghidra.dbg.target.TargetBreakpointSpec.TargetBreakpointKind;
|
||||
import ghidra.dbg.target.TargetObject;
|
||||
import ghidra.dbg.target.schema.*;
|
||||
import ghidra.util.datastruct.WeakValueHashMap;
|
||||
|
||||
@TargetObjectSchemaInfo(name = "BreakpointContainer", elements = { //
|
||||
@TargetElementType(type = DbgModelTargetBreakpointSpecImpl.class) //
|
||||
}, attributes = { //
|
||||
@TargetAttributeType(type = Void.class) //
|
||||
}, canonicalContainer = true)
|
||||
public class DbgModelTargetBreakpointContainerImpl extends DbgModelTargetObjectImpl
|
||||
implements DbgModelTargetBreakpointContainer {
|
||||
|
||||
|
|
|
@ -22,9 +22,14 @@ import agent.dbgeng.manager.breakpoint.DbgBreakpointInfo;
|
|||
import agent.dbgeng.model.iface2.DbgModelTargetBreakpointContainer;
|
||||
import agent.dbgeng.model.iface2.DbgModelTargetBreakpointSpec;
|
||||
import ghidra.dbg.target.TargetObject;
|
||||
import ghidra.dbg.target.schema.TargetAttributeType;
|
||||
import ghidra.dbg.target.schema.TargetObjectSchemaInfo;
|
||||
import ghidra.dbg.util.PathUtils;
|
||||
import ghidra.util.datastruct.ListenerSet;
|
||||
|
||||
@TargetObjectSchemaInfo(name = "BreakpointSpec", attributes = { //
|
||||
@TargetAttributeType(type = Void.class) //
|
||||
}, canonicalContainer = true)
|
||||
public class DbgModelTargetBreakpointSpecImpl extends DbgModelTargetObjectImpl
|
||||
implements DbgModelTargetBreakpointSpec {
|
||||
|
||||
|
|
|
@ -20,7 +20,16 @@ import java.util.Map;
|
|||
|
||||
import agent.dbgeng.model.iface2.DbgModelTargetConnector;
|
||||
import agent.dbgeng.model.iface2.DbgModelTargetRoot;
|
||||
import ghidra.dbg.target.schema.TargetAttributeType;
|
||||
import ghidra.dbg.target.schema.TargetObjectSchemaInfo;
|
||||
|
||||
@TargetObjectSchemaInfo(name = "ConnectorContainer", attributes = { //
|
||||
@TargetAttributeType(name = "Launch process", type = DbgModelTargetProcessLaunchConnectorImpl.class, required = true, fixed = true), //
|
||||
@TargetAttributeType(name = "Attach to process", type = DbgModelTargetProcessAttachConnectorImpl.class, required = true, fixed = true), //
|
||||
@TargetAttributeType(name = "Load trace/dump", type = DbgModelTargetTraceOrDumpConnectorImpl.class, required = true, fixed = true), //
|
||||
@TargetAttributeType(name = "Attach to kernel", type = DbgModelTargetKernelConnectorImpl.class, required = true, fixed = true), //
|
||||
@TargetAttributeType(type = Void.class) //
|
||||
}, canonicalContainer = true)
|
||||
public class DbgModelTargetConnectorContainerImpl extends DbgModelTargetObjectImpl {
|
||||
|
||||
protected final DbgModelTargetRoot root;
|
||||
|
|
|
@ -20,7 +20,13 @@ import java.util.Map;
|
|||
|
||||
import agent.dbgeng.model.iface2.DbgModelTargetDebugContainer;
|
||||
import agent.dbgeng.model.iface2.DbgModelTargetProcess;
|
||||
import ghidra.dbg.target.schema.TargetAttributeType;
|
||||
import ghidra.dbg.target.schema.TargetObjectSchemaInfo;
|
||||
|
||||
@TargetObjectSchemaInfo(name = "DebugContainer", attributes = { //
|
||||
@TargetAttributeType(name = "Breakpoints", type = DbgModelTargetBreakpointContainerImpl.class, required = true, fixed = true), //
|
||||
@TargetAttributeType(type = Void.class) //
|
||||
}, canonicalContainer = true)
|
||||
public class DbgModelTargetDebugContainerImpl extends DbgModelTargetObjectImpl
|
||||
implements DbgModelTargetDebugContainer {
|
||||
|
||||
|
|
|
@ -26,7 +26,13 @@ import ghidra.dbg.error.DebuggerUserException;
|
|||
import ghidra.dbg.target.TargetMethod;
|
||||
import ghidra.dbg.target.TargetMethod.ParameterDescription;
|
||||
import ghidra.dbg.target.TargetMethod.TargetParameterMap;
|
||||
import ghidra.dbg.target.schema.*;
|
||||
|
||||
@TargetObjectSchemaInfo(name = "KernelConnector", elements = { //
|
||||
@TargetElementType(type = Void.class) //
|
||||
}, attributes = { //
|
||||
@TargetAttributeType(type = Void.class) //
|
||||
})
|
||||
public class DbgModelTargetKernelConnectorImpl extends DbgModelTargetObjectImpl
|
||||
implements DbgModelTargetConnector {
|
||||
|
||||
|
|
|
@ -31,9 +31,15 @@ import ghidra.dbg.error.DebuggerMemoryAccessException;
|
|||
import ghidra.dbg.error.DebuggerModelAccessException;
|
||||
import ghidra.dbg.target.TargetAccessConditioned.TargetAccessibility;
|
||||
import ghidra.dbg.target.TargetObject;
|
||||
import ghidra.dbg.target.schema.*;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.util.datastruct.WeakValueHashMap;
|
||||
|
||||
@TargetObjectSchemaInfo(name = "Memory", elements = { //
|
||||
@TargetElementType(type = DbgModelTargetMemoryRegionImpl.class) //
|
||||
}, attributes = { //
|
||||
@TargetAttributeType(type = Void.class) //
|
||||
}, canonicalContainer = true)
|
||||
public class DbgModelTargetMemoryContainerImpl extends DbgModelTargetObjectImpl
|
||||
implements DbgModelTargetMemoryContainer {
|
||||
|
||||
|
|
|
@ -21,9 +21,23 @@ import java.util.Map;
|
|||
import agent.dbgeng.manager.DbgModuleMemory;
|
||||
import agent.dbgeng.model.iface2.DbgModelTargetMemoryContainer;
|
||||
import agent.dbgeng.model.iface2.DbgModelTargetMemoryRegion;
|
||||
import ghidra.dbg.target.schema.*;
|
||||
import ghidra.dbg.util.PathUtils;
|
||||
import ghidra.program.model.address.*;
|
||||
|
||||
@TargetObjectSchemaInfo(name = "MemoryRegion", elements = { //
|
||||
@TargetElementType(type = Void.class) //
|
||||
}, attributes = { //
|
||||
@TargetAttributeType(name = "BaseAddress", type = Address.class), //
|
||||
@TargetAttributeType(name = "EndAddress", type = Address.class), //
|
||||
@TargetAttributeType(name = "RegionSize", type = String.class), //
|
||||
@TargetAttributeType(name = "AllocationBase", type = Address.class), //
|
||||
@TargetAttributeType(name = "AllocationProtect", type = String.class), //
|
||||
@TargetAttributeType(name = "Protect", type = String.class), //
|
||||
@TargetAttributeType(name = "State", type = String.class), //
|
||||
@TargetAttributeType(name = "Type", type = String.class), //
|
||||
@TargetAttributeType(type = Void.class) //
|
||||
})
|
||||
public class DbgModelTargetMemoryRegionImpl extends DbgModelTargetObjectImpl
|
||||
implements DbgModelTargetMemoryRegion {
|
||||
|
||||
|
|
|
@ -26,9 +26,15 @@ import ghidra.async.AsyncFence;
|
|||
import ghidra.async.AsyncLazyMap;
|
||||
import ghidra.dbg.target.TargetModule;
|
||||
import ghidra.dbg.target.TargetObject;
|
||||
import ghidra.dbg.target.schema.*;
|
||||
import ghidra.lifecycle.Internal;
|
||||
import ghidra.util.Msg;
|
||||
|
||||
@TargetObjectSchemaInfo(name = "ModuleContainer", elements = { //
|
||||
@TargetElementType(type = DbgModelTargetModuleImpl.class) //
|
||||
}, attributes = { //
|
||||
@TargetAttributeType(type = Void.class) //
|
||||
}, canonicalContainer = true)
|
||||
public class DbgModelTargetModuleContainerImpl extends DbgModelTargetObjectImpl
|
||||
implements DbgModelTargetModuleContainer {
|
||||
// NOTE: -file-list-shared-libraries omits the main module and system-supplied DSO.
|
||||
|
|
|
@ -20,9 +20,20 @@ import java.util.Map;
|
|||
|
||||
import agent.dbgeng.manager.*;
|
||||
import agent.dbgeng.model.iface2.DbgModelTargetModule;
|
||||
import ghidra.dbg.target.schema.*;
|
||||
import ghidra.dbg.util.PathUtils;
|
||||
import ghidra.program.model.address.*;
|
||||
|
||||
@TargetObjectSchemaInfo(name = "Module", elements = { //
|
||||
@TargetElementType(type = Void.class) //
|
||||
}, attributes = { //
|
||||
@TargetAttributeType(name = "Symbols", type = DbgModelTargetSymbolContainerImpl.class, required = true, fixed = true), //
|
||||
@TargetAttributeType(name = "BaseAddress", type = Address.class), //
|
||||
@TargetAttributeType(name = "ImageName", type = String.class), //
|
||||
@TargetAttributeType(name = "TimeStamp", type = Integer.class), //
|
||||
@TargetAttributeType(name = "Len", type = String.class), //
|
||||
@TargetAttributeType(type = Void.class) //
|
||||
})
|
||||
public class DbgModelTargetModuleImpl extends DbgModelTargetObjectImpl
|
||||
implements DbgModelTargetModule {
|
||||
protected static String indexModule(DbgModule module) {
|
||||
|
|
|
@ -21,8 +21,14 @@ import java.util.concurrent.CompletableFuture;
|
|||
import agent.dbgeng.manager.DbgModule;
|
||||
import agent.dbgeng.manager.DbgModuleSection;
|
||||
import agent.dbgeng.model.iface2.*;
|
||||
import ghidra.dbg.target.schema.*;
|
||||
import ghidra.util.datastruct.WeakValueHashMap;
|
||||
|
||||
@TargetObjectSchemaInfo(name = "SectionContainer", elements = { //
|
||||
@TargetElementType(type = DbgModelTargetModuleSectionImpl.class) //
|
||||
}, attributes = { //
|
||||
@TargetAttributeType(type = Void.class) //
|
||||
}, canonicalContainer = true)
|
||||
public class DbgModelTargetModuleSectionContainerImpl extends DbgModelTargetObjectImpl
|
||||
implements DbgModelTargetModuleSectionContainer {
|
||||
|
||||
|
|
|
@ -20,8 +20,14 @@ import java.util.Map;
|
|||
|
||||
import agent.dbgeng.manager.DbgModuleSection;
|
||||
import agent.dbgeng.model.iface2.DbgModelTargetModuleSection;
|
||||
import ghidra.dbg.target.schema.*;
|
||||
import ghidra.program.model.address.*;
|
||||
|
||||
@TargetObjectSchemaInfo(name = "Section", elements = { //
|
||||
@TargetElementType(type = Void.class) //
|
||||
}, attributes = { //
|
||||
@TargetAttributeType(type = Void.class) //
|
||||
})
|
||||
public class DbgModelTargetModuleSectionImpl extends DbgModelTargetObjectImpl
|
||||
implements DbgModelTargetModuleSection {
|
||||
protected static final String OBJFILE_ATTRIBUTE_NAME = PREFIX_INVISIBLE + "objfile";
|
||||
|
@ -46,6 +52,7 @@ public class DbgModelTargetModuleSectionImpl extends DbgModelTargetObjectImpl
|
|||
), "Initialized");
|
||||
}
|
||||
|
||||
@TargetAttributeType(name = RANGE_ATTRIBUTE_NAME)
|
||||
@Override
|
||||
public AddressRange getRange() {
|
||||
return range;
|
||||
|
|
|
@ -29,6 +29,7 @@ import ghidra.dbg.target.*;
|
|||
import ghidra.dbg.target.TargetAccessConditioned.TargetAccessibility;
|
||||
import ghidra.dbg.target.TargetAccessConditioned.TargetAccessibilityListener;
|
||||
import ghidra.dbg.target.TargetExecutionStateful.TargetExecutionState;
|
||||
import ghidra.dbg.target.schema.TargetObjectSchema;
|
||||
|
||||
public class DbgModelTargetObjectImpl extends DefaultTargetObject<TargetObject, TargetObject>
|
||||
implements DbgModelTargetObject {
|
||||
|
@ -43,6 +44,12 @@ public class DbgModelTargetObjectImpl extends DefaultTargetObject<TargetObject,
|
|||
getManager().addStateListener(accessListener);
|
||||
}
|
||||
|
||||
public DbgModelTargetObjectImpl(AbstractDbgModel impl, TargetObject parent, String name,
|
||||
String typeHint, TargetObjectSchema schema) {
|
||||
super(impl, parent, name, typeHint, schema);
|
||||
getManager().addStateListener(accessListener);
|
||||
}
|
||||
|
||||
public void setAttribute(String key, String value) {
|
||||
changeAttributes(List.of(), List.of(), Map.of( //
|
||||
key, value), "Initialized");
|
||||
|
|
|
@ -27,7 +27,13 @@ import ghidra.dbg.error.DebuggerUserException;
|
|||
import ghidra.dbg.target.TargetMethod;
|
||||
import ghidra.dbg.target.TargetMethod.ParameterDescription;
|
||||
import ghidra.dbg.target.TargetMethod.TargetParameterMap;
|
||||
import ghidra.dbg.target.schema.*;
|
||||
|
||||
@TargetObjectSchemaInfo(name = "ProcessAttachConnector", elements = { //
|
||||
@TargetElementType(type = Void.class) //
|
||||
}, attributes = { //
|
||||
@TargetAttributeType(type = Void.class) //
|
||||
})
|
||||
public class DbgModelTargetProcessAttachConnectorImpl extends DbgModelTargetObjectImpl
|
||||
implements DbgModelTargetConnector {
|
||||
|
||||
|
|
|
@ -25,9 +25,15 @@ import agent.dbgeng.dbgeng.DebugThreadId;
|
|||
import agent.dbgeng.manager.*;
|
||||
import agent.dbgeng.model.iface2.*;
|
||||
import ghidra.dbg.target.TargetAccessConditioned.TargetAccessibility;
|
||||
import ghidra.dbg.target.schema.*;
|
||||
import ghidra.dbg.target.TargetObject;
|
||||
import ghidra.util.datastruct.WeakValueHashMap;
|
||||
|
||||
@TargetObjectSchemaInfo(name = "ProcessContainer", elements = { //
|
||||
@TargetElementType(type = DbgModelTargetProcessImpl.class) //
|
||||
}, attributes = { //
|
||||
@TargetAttributeType(type = Void.class) //
|
||||
}, canonicalContainer = true)
|
||||
public class DbgModelTargetProcessContainerImpl extends DbgModelTargetObjectImpl
|
||||
implements DbgModelTargetProcessContainer {
|
||||
|
||||
|
|
|
@ -33,14 +33,27 @@ import ghidra.dbg.DebuggerObjectModel;
|
|||
import ghidra.dbg.attributes.TargetObjectRef;
|
||||
import ghidra.dbg.attributes.TypedTargetObjectRef;
|
||||
import ghidra.dbg.target.*;
|
||||
import ghidra.dbg.target.schema.*;
|
||||
import ghidra.dbg.util.PathUtils;
|
||||
|
||||
@TargetObjectSchemaInfo(name = "Process", elements = { //
|
||||
@TargetElementType(type = Void.class) //
|
||||
}, attributes = { //
|
||||
@TargetAttributeType(name = "Debug", type = DbgModelTargetDebugContainerImpl.class, required = true, fixed = true), //
|
||||
@TargetAttributeType(name = "Memory", type = DbgModelTargetMemoryContainerImpl.class, required = true, fixed = true), //
|
||||
@TargetAttributeType(name = "Modules", type = DbgModelTargetModuleContainerImpl.class, required = true, fixed = true), //
|
||||
@TargetAttributeType(name = "Threads", type = DbgModelTargetThreadContainerImpl.class, required = true, fixed = true), //
|
||||
@TargetAttributeType(type = Void.class) //
|
||||
})
|
||||
public class DbgModelTargetProcessImpl extends DbgModelTargetObjectImpl
|
||||
implements DbgModelTargetProcess {
|
||||
|
||||
public static final String PID_ATTRIBUTE_NAME = PREFIX_INVISIBLE + "pid";
|
||||
public static final String EXIT_CODE_ATTRIBUTE_NAME = PREFIX_INVISIBLE + "exit_code";
|
||||
|
||||
protected static final TargetAttachKindSet SUPPORTED_KINDS = TargetAttachKindSet.of( //
|
||||
TargetAttachKind.BY_OBJECT_REF, TargetAttachKind.BY_ID);
|
||||
|
||||
protected static String indexProcess(DebugProcessId debugProcessId) {
|
||||
return PathUtils.makeIndex(debugProcessId.id);
|
||||
}
|
||||
|
@ -79,8 +92,11 @@ public class DbgModelTargetProcessImpl extends DbgModelTargetObjectImpl
|
|||
//sections, //
|
||||
threads //
|
||||
), Map.of( //
|
||||
ACCESSIBLE_ATTRIBUTE_NAME, false, //
|
||||
DISPLAY_ATTRIBUTE_NAME, getDisplay(), //
|
||||
TargetMethod.PARAMETERS_ATTRIBUTE_NAME, PARAMETERS //
|
||||
TargetMethod.PARAMETERS_ATTRIBUTE_NAME, PARAMETERS, //
|
||||
SUPPORTED_ATTACH_KINDS_ATTRIBUTE_NAME, SUPPORTED_KINDS, //
|
||||
SUPPORTED_STEP_KINDS_ATTRIBUTE_NAME, DbgModelTargetThreadImpl.SUPPORTED_KINDS //
|
||||
), "Initialized");
|
||||
setExecutionState(TargetExecutionState.ALIVE, "Initialized");
|
||||
|
||||
|
|
|
@ -25,7 +25,13 @@ import ghidra.dbg.error.DebuggerUserException;
|
|||
import ghidra.dbg.target.TargetMethod;
|
||||
import ghidra.dbg.target.TargetMethod.ParameterDescription;
|
||||
import ghidra.dbg.target.TargetMethod.TargetParameterMap;
|
||||
import ghidra.dbg.target.schema.*;
|
||||
|
||||
@TargetObjectSchemaInfo(name = "ProcessLaunchConnector", elements = { //
|
||||
@TargetElementType(type = Void.class) //
|
||||
}, attributes = { //
|
||||
@TargetAttributeType(type = Void.class) //
|
||||
})
|
||||
public class DbgModelTargetProcessLaunchConnectorImpl extends DbgModelTargetObjectImpl
|
||||
implements DbgModelTargetConnector {
|
||||
|
||||
|
|
|
@ -31,8 +31,14 @@ import ghidra.dbg.error.DebuggerRegisterAccessException;
|
|||
import ghidra.dbg.target.TargetAccessConditioned.TargetAccessibility;
|
||||
import ghidra.dbg.target.TargetObject;
|
||||
import ghidra.dbg.target.TargetRegisterBank;
|
||||
import ghidra.dbg.target.schema.*;
|
||||
import ghidra.dbg.util.ConversionUtils;
|
||||
|
||||
@TargetObjectSchemaInfo(name = "RegisterContainer", elements = { //
|
||||
@TargetElementType(type = DbgModelTargetRegisterImpl.class) //
|
||||
}, attributes = { //
|
||||
@TargetAttributeType(type = Void.class) //
|
||||
}, canonicalContainer = true)
|
||||
public class DbgModelTargetRegisterContainerImpl extends DbgModelTargetObjectImpl
|
||||
implements DbgModelTargetRegisterContainerAndBank {
|
||||
|
||||
|
|
|
@ -21,8 +21,14 @@ import java.util.Map;
|
|||
import agent.dbgeng.manager.impl.DbgRegister;
|
||||
import agent.dbgeng.model.iface2.DbgModelTargetRegister;
|
||||
import agent.dbgeng.model.iface2.DbgModelTargetRegisterContainerAndBank;
|
||||
import ghidra.dbg.target.schema.*;
|
||||
import ghidra.dbg.util.PathUtils;
|
||||
|
||||
@TargetObjectSchemaInfo(name = "RegisterDescriptor", elements = { //
|
||||
@TargetElementType(type = Void.class) //
|
||||
}, attributes = { //
|
||||
@TargetAttributeType(type = Void.class) //
|
||||
})
|
||||
public class DbgModelTargetRegisterImpl extends DbgModelTargetObjectImpl
|
||||
implements DbgModelTargetRegister {
|
||||
|
||||
|
|
|
@ -27,7 +27,16 @@ import ghidra.async.AsyncUtils;
|
|||
import ghidra.async.TypeSpec;
|
||||
import ghidra.dbg.error.DebuggerUserException;
|
||||
import ghidra.dbg.target.*;
|
||||
import ghidra.dbg.target.schema.*;
|
||||
|
||||
@TargetObjectSchemaInfo(name = "Debugger", elements = { //
|
||||
@TargetElementType(type = Void.class) //
|
||||
}, attributes = { //
|
||||
@TargetAttributeType(name = "Available", type = DbgModelTargetAvailableContainerImpl.class, required = true, fixed = true), //
|
||||
@TargetAttributeType(name = "Connectors", type = DbgModelTargetConnectorContainerImpl.class, required = true, fixed = true), //
|
||||
@TargetAttributeType(name = "Sessions", type = DbgModelTargetSessionContainerImpl.class, required = true, fixed = true), //
|
||||
@TargetAttributeType(type = Void.class) //
|
||||
})
|
||||
public class DbgModelTargetRootImpl extends DbgModelDefaultTargetModelRoot
|
||||
implements DbgModelTargetRoot {
|
||||
|
||||
|
@ -39,8 +48,8 @@ public class DbgModelTargetRootImpl extends DbgModelDefaultTargetModelRoot
|
|||
|
||||
protected DbgModelSelectableObject focus;
|
||||
|
||||
public DbgModelTargetRootImpl(DbgModelImpl impl) {
|
||||
super(impl, "Debugger");
|
||||
public DbgModelTargetRootImpl(DbgModelImpl impl, TargetObjectSchema schema) {
|
||||
super(impl, "Debugger", schema);
|
||||
|
||||
this.available = new DbgModelTargetAvailableContainerImpl(this);
|
||||
this.connectors = new DbgModelTargetConnectorContainerImpl(this);
|
||||
|
|
|
@ -21,7 +21,14 @@ import java.util.concurrent.CompletableFuture;
|
|||
|
||||
import agent.dbgeng.model.iface2.DbgModelTargetSession;
|
||||
import agent.dbgeng.model.iface2.DbgModelTargetSessionAttributes;
|
||||
import ghidra.dbg.target.schema.*;
|
||||
|
||||
@TargetObjectSchemaInfo(name = "SessionAttributes", elements = { //
|
||||
@TargetElementType(type = Void.class) //
|
||||
}, attributes = { //
|
||||
@TargetAttributeType(name = "Machine", type = DbgModelTargetSessionAttributesMachineImpl.class, fixed = true), //
|
||||
@TargetAttributeType(type = Void.class) //
|
||||
})
|
||||
public class DbgModelTargetSessionAttributesImpl extends DbgModelTargetObjectImpl
|
||||
implements DbgModelTargetSessionAttributes {
|
||||
|
||||
|
|
|
@ -28,13 +28,23 @@ import agent.dbgeng.model.iface2.DbgModelTargetSessionAttributes;
|
|||
import agent.dbgeng.model.iface2.DbgModelTargetSessionAttributesMachine;
|
||||
import ghidra.async.AsyncUtils;
|
||||
import ghidra.async.TypeSpec;
|
||||
import ghidra.dbg.target.schema.*;
|
||||
|
||||
@TargetObjectSchemaInfo(name = "SessionAttributesMachine", elements = { //
|
||||
@TargetElementType(type = Void.class) //
|
||||
}, attributes = { //
|
||||
@TargetAttributeType(name = "Arch", type = String.class), //
|
||||
@TargetAttributeType(name = "Debugger", type = String.class), //
|
||||
@TargetAttributeType(name = "OS", type = String.class), //
|
||||
@TargetAttributeType(name = "Mode", type = String.class), //
|
||||
@TargetAttributeType(type = Void.class) //
|
||||
})
|
||||
public class DbgModelTargetSessionAttributesMachineImpl extends DbgModelTargetObjectImpl
|
||||
implements DbgModelTargetSessionAttributesMachine {
|
||||
|
||||
String ARCH_ATTRIBUTE_NAME = "Arch";
|
||||
String DEBUGGER_ATTRIBUTE_NAME = "Debugger";
|
||||
String OS_ATTRIBUTE_NAME = "OS";
|
||||
static String ARCH_ATTRIBUTE_NAME = "Arch";
|
||||
static String DEBUGGER_ATTRIBUTE_NAME = "Debugger";
|
||||
static String OS_ATTRIBUTE_NAME = "OS";
|
||||
|
||||
public DbgModelTargetSessionAttributesMachineImpl(DbgModelTargetSessionAttributes attributes) {
|
||||
super(attributes.getModel(), attributes, "Machine", "SessionMachineAttributes");
|
||||
|
|
|
@ -23,8 +23,14 @@ import agent.dbgeng.dbgeng.DebugSessionId;
|
|||
import agent.dbgeng.manager.DbgCause;
|
||||
import agent.dbgeng.manager.DbgSession;
|
||||
import agent.dbgeng.model.iface2.*;
|
||||
import ghidra.dbg.target.schema.*;
|
||||
import ghidra.util.datastruct.WeakValueHashMap;
|
||||
|
||||
@TargetObjectSchemaInfo(name = "SessionContainer", elements = { //
|
||||
@TargetElementType(type = DbgModelTargetSessionImpl.class) //
|
||||
}, attributes = { //
|
||||
@TargetAttributeType(type = Void.class) //
|
||||
}, canonicalContainer = true)
|
||||
public class DbgModelTargetSessionContainerImpl extends DbgModelTargetObjectImpl
|
||||
implements DbgModelTargetSessionContainer {
|
||||
|
||||
|
|
|
@ -24,8 +24,16 @@ import agent.dbgeng.manager.*;
|
|||
import agent.dbgeng.model.iface1.DbgModelSelectableObject;
|
||||
import agent.dbgeng.model.iface2.DbgModelTargetProcessContainer;
|
||||
import agent.dbgeng.model.iface2.DbgModelTargetSession;
|
||||
import ghidra.dbg.target.schema.*;
|
||||
import ghidra.dbg.util.PathUtils;
|
||||
|
||||
@TargetObjectSchemaInfo(name = "Session", elements = { //
|
||||
@TargetElementType(type = Void.class) //
|
||||
}, attributes = { //
|
||||
@TargetAttributeType(name = "Attributes", type = DbgModelTargetSessionAttributesImpl.class, fixed = true), //
|
||||
@TargetAttributeType(name = "Processes", type = DbgModelTargetProcessContainerImpl.class, required = true, fixed = true), //
|
||||
@TargetAttributeType(type = Void.class) //
|
||||
})
|
||||
public class DbgModelTargetSessionImpl extends DbgModelTargetObjectImpl
|
||||
implements DbgModelTargetSession {
|
||||
|
||||
|
@ -61,8 +69,9 @@ public class DbgModelTargetSessionImpl extends DbgModelTargetObjectImpl
|
|||
attributes, //
|
||||
processes //
|
||||
), Map.of( //
|
||||
ACCESSIBLE_ATTRIBUTE_NAME, true, //
|
||||
PROMPT_ATTRIBUTE_NAME, DBG_PROMPT, //
|
||||
//STATE_ATTRIBUTE_NAME, TargetExecutionState.RUNNING, //
|
||||
STATE_ATTRIBUTE_NAME, TargetExecutionState.ALIVE, //
|
||||
UPDATE_MODE_ATTRIBUTE_NAME, TargetUpdateMode.FIXED //
|
||||
), "Initialized");
|
||||
|
||||
|
|
|
@ -30,9 +30,26 @@ import ghidra.async.AsyncUtils;
|
|||
import ghidra.async.TypeSpec;
|
||||
import ghidra.dbg.DebugModelConventions;
|
||||
import ghidra.dbg.attributes.TargetObjectRef;
|
||||
import ghidra.dbg.target.schema.*;
|
||||
import ghidra.dbg.util.PathUtils;
|
||||
import ghidra.program.model.address.Address;
|
||||
|
||||
@TargetObjectSchemaInfo(name = "StackFrame", elements = { //
|
||||
@TargetElementType(type = Void.class) //
|
||||
}, attributes = { //
|
||||
@TargetAttributeType(name = DbgModelTargetStackFrame.FUNC_ATTRIBUTE_NAME, type = String.class), //
|
||||
@TargetAttributeType(name = DbgModelTargetStackFrame.FUNC_TABLE_ENTRY_ATTRIBUTE_NAME, type = String.class), //
|
||||
@TargetAttributeType(name = DbgModelTargetStackFrame.INST_OFFSET_ATTRIBUTE_NAME, type = String.class), //
|
||||
@TargetAttributeType(name = DbgModelTargetStackFrame.FRAME_OFFSET_ATTRIBUTE_NAME, type = String.class), //
|
||||
@TargetAttributeType(name = DbgModelTargetStackFrame.RETURN_OFFSET_ATTRIBUTE_NAME, type = String.class), //
|
||||
@TargetAttributeType(name = DbgModelTargetStackFrame.STACK_OFFSET_ATTRIBUTE_NAME, type = String.class), //
|
||||
@TargetAttributeType(name = DbgModelTargetStackFrame.VIRTUAL_ATTRIBUTE_NAME, type = Boolean.class), //
|
||||
@TargetAttributeType(name = DbgModelTargetStackFrame.PARAM0_ATTRIBUTE_NAME, type = String.class), //
|
||||
@TargetAttributeType(name = DbgModelTargetStackFrame.PARAM1_ATTRIBUTE_NAME, type = String.class), //
|
||||
@TargetAttributeType(name = DbgModelTargetStackFrame.PARAM2_ATTRIBUTE_NAME, type = String.class), //
|
||||
@TargetAttributeType(name = DbgModelTargetStackFrame.PARAM3_ATTRIBUTE_NAME, type = String.class), //
|
||||
@TargetAttributeType(type = Void.class) //
|
||||
})
|
||||
public class DbgModelTargetStackFrameImpl extends DbgModelTargetObjectImpl
|
||||
implements DbgModelTargetStackFrame {
|
||||
|
||||
|
|
|
@ -24,19 +24,27 @@ import agent.dbgeng.manager.DbgStackFrame;
|
|||
import agent.dbgeng.model.iface2.*;
|
||||
import ghidra.dbg.target.TargetAccessConditioned.TargetAccessibility;
|
||||
import ghidra.dbg.target.TargetObject;
|
||||
import ghidra.dbg.target.schema.*;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.datastruct.WeakValueHashMap;
|
||||
|
||||
@TargetObjectSchemaInfo(name = "Stack", elements = { //
|
||||
@TargetElementType(type = DbgModelTargetStackFrameImpl.class) //
|
||||
}, attributes = { //
|
||||
@TargetAttributeType(type = Void.class) //
|
||||
}, canonicalContainer = true)
|
||||
public class DbgModelTargetStackImpl extends DbgModelTargetObjectImpl
|
||||
implements DbgModelTargetStack {
|
||||
|
||||
protected final DbgModelTargetThread thread;
|
||||
|
||||
public static final String NAME = "Stack";
|
||||
|
||||
protected final Map<Integer, DbgModelTargetStackFrameImpl> framesByLevel =
|
||||
new WeakValueHashMap<>();
|
||||
|
||||
public DbgModelTargetStackImpl(DbgModelTargetThread thread, DbgModelTargetProcess process) {
|
||||
super(thread.getModel(), thread, "Stack", "Stack");
|
||||
super(thread.getModel(), thread, NAME, "Stack");
|
||||
this.thread = thread;
|
||||
}
|
||||
|
||||
|
|
|
@ -23,8 +23,14 @@ import java.util.stream.Collectors;
|
|||
import agent.dbgeng.manager.impl.DbgMinimalSymbol;
|
||||
import agent.dbgeng.model.iface2.DbgModelTargetSymbolContainer;
|
||||
import ghidra.dbg.target.TargetObject;
|
||||
import ghidra.dbg.target.schema.*;
|
||||
import ghidra.util.datastruct.WeakValueHashMap;
|
||||
|
||||
@TargetObjectSchemaInfo(name = "SymbolContainer", elements = { //
|
||||
@TargetElementType(type = DbgModelTargetSymbolImpl.class) //
|
||||
}, attributes = { //
|
||||
@TargetAttributeType(type = Void.class) //
|
||||
}, canonicalContainer = true)
|
||||
public class DbgModelTargetSymbolContainerImpl extends DbgModelTargetObjectImpl
|
||||
implements DbgModelTargetSymbolContainer {
|
||||
|
||||
|
|
|
@ -20,9 +20,15 @@ import java.util.Map;
|
|||
|
||||
import agent.dbgeng.manager.impl.DbgMinimalSymbol;
|
||||
import agent.dbgeng.model.iface2.DbgModelTargetSymbol;
|
||||
import ghidra.dbg.target.schema.*;
|
||||
import ghidra.dbg.util.PathUtils;
|
||||
import ghidra.program.model.address.Address;
|
||||
|
||||
@TargetObjectSchemaInfo(name = "Symbol", elements = { //
|
||||
@TargetElementType(type = Void.class) //
|
||||
}, attributes = { //
|
||||
@TargetAttributeType(type = Void.class) //
|
||||
})
|
||||
public class DbgModelTargetSymbolImpl extends DbgModelTargetObjectImpl
|
||||
implements DbgModelTargetSymbol {
|
||||
protected static String indexSymbol(DbgMinimalSymbol symbol) {
|
||||
|
|
|
@ -25,9 +25,14 @@ import agent.dbgeng.manager.*;
|
|||
import agent.dbgeng.manager.reason.*;
|
||||
import agent.dbgeng.model.iface2.*;
|
||||
import ghidra.dbg.target.TargetObject;
|
||||
import ghidra.dbg.target.schema.*;
|
||||
import ghidra.util.datastruct.WeakValueHashMap;
|
||||
|
||||
// TODO: Should TargetThreadContainer be a thing?
|
||||
@TargetObjectSchemaInfo(name = "ThreadContainer", elements = { //
|
||||
@TargetElementType(type = DbgModelTargetThreadImpl.class) //
|
||||
}, attributes = { //
|
||||
@TargetAttributeType(type = Void.class) //
|
||||
}, canonicalContainer = true)
|
||||
public class DbgModelTargetThreadContainerImpl extends DbgModelTargetObjectImpl
|
||||
implements DbgModelTargetThreadContainer {
|
||||
|
||||
|
|
|
@ -31,8 +31,17 @@ import ghidra.async.AsyncUtils;
|
|||
import ghidra.async.TypeSpec;
|
||||
import ghidra.dbg.DebugModelConventions;
|
||||
import ghidra.dbg.target.TargetEnvironment;
|
||||
import ghidra.dbg.target.schema.*;
|
||||
import ghidra.dbg.util.PathUtils;
|
||||
|
||||
@TargetObjectSchemaInfo(name = "Thread", elements = { //
|
||||
@TargetElementType(type = Void.class) //
|
||||
}, attributes = { //
|
||||
@TargetAttributeType(name = "Registers", type = DbgModelTargetRegisterContainerImpl.class, required = true, fixed = true), //
|
||||
@TargetAttributeType(name = "Stack", type = DbgModelTargetStackImpl.class, required = true, fixed = true), //
|
||||
@TargetAttributeType(name = TargetEnvironment.ARCH_ATTRIBUTE_NAME, type = String.class), //
|
||||
@TargetAttributeType(type = Void.class) //
|
||||
})
|
||||
public class DbgModelTargetThreadImpl extends DbgModelTargetObjectImpl
|
||||
implements DbgModelTargetThread {
|
||||
|
||||
|
@ -72,6 +81,7 @@ public class DbgModelTargetThreadImpl extends DbgModelTargetObjectImpl
|
|||
registers, //
|
||||
stack //
|
||||
), Map.of( //
|
||||
ACCESSIBLE_ATTRIBUTE_NAME, false, //
|
||||
DISPLAY_ATTRIBUTE_NAME, getDisplay(), //
|
||||
SUPPORTED_STEP_KINDS_ATTRIBUTE_NAME, SUPPORTED_KINDS //
|
||||
), "Initialized");
|
||||
|
|
|
@ -25,7 +25,13 @@ import ghidra.dbg.error.DebuggerUserException;
|
|||
import ghidra.dbg.target.TargetMethod;
|
||||
import ghidra.dbg.target.TargetMethod.ParameterDescription;
|
||||
import ghidra.dbg.target.TargetMethod.TargetParameterMap;
|
||||
import ghidra.dbg.target.schema.*;
|
||||
|
||||
@TargetObjectSchemaInfo(name = "TraceOrDumpConnector", elements = { //
|
||||
@TargetElementType(type = Void.class) //
|
||||
}, attributes = { //
|
||||
@TargetAttributeType(type = Void.class) //
|
||||
})
|
||||
public class DbgModelTargetTraceOrDumpConnectorImpl extends DbgModelTargetObjectImpl
|
||||
implements DbgModelTargetConnector {
|
||||
|
||||
|
|
|
@ -45,6 +45,8 @@ import ghidra.dbg.target.TargetConsole.Channel;
|
|||
import ghidra.dbg.target.TargetFocusScope.TargetFocusScopeListener;
|
||||
import ghidra.dbg.target.TargetLauncher.TargetCmdLineLauncher;
|
||||
import ghidra.dbg.target.TargetObject.TargetObjectListener;
|
||||
import ghidra.dbg.target.schema.TargetObjectSchema;
|
||||
import ghidra.dbg.target.schema.XmlSchemaContext;
|
||||
import ghidra.dbg.util.AllTargetObjectListenerAdapter;
|
||||
import ghidra.dbg.util.PathUtils;
|
||||
import ghidra.program.model.address.Address;
|
||||
|
@ -1067,4 +1069,22 @@ public abstract class AbstractModelForDbgTest
|
|||
}).finish());
|
||||
}
|
||||
}
|
||||
|
||||
protected void init(ModelHost m) throws Throwable {
|
||||
waitOn(m.init());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSerializeSchema() throws Throwable {
|
||||
try (ModelHost m = modelHost()) {
|
||||
DebuggerObjectModel model = m.getModel();
|
||||
init(m);
|
||||
|
||||
TargetObjectSchema rootSchema = model.getRootSchema();
|
||||
String serialized = XmlSchemaContext.serialize(rootSchema.getContext());
|
||||
System.out.println(serialized);
|
||||
|
||||
assertEquals("Debugger", rootSchema.getName().toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,7 +24,6 @@ import ghidra.dbg.agent.DefaultTargetObject;
|
|||
import ghidra.dbg.target.TargetEnvironment;
|
||||
import ghidra.dbg.target.TargetObject;
|
||||
import ghidra.dbg.target.schema.*;
|
||||
import ghidra.util.Msg;
|
||||
|
||||
@TargetObjectSchemaInfo(name = "Environment", elements = {
|
||||
@TargetElementType(type = Void.class)
|
||||
|
@ -36,6 +35,10 @@ public class GdbModelTargetEnvironment
|
|||
implements TargetEnvironment<GdbModelTargetEnvironment> {
|
||||
public static final String NAME = "Environment";
|
||||
|
||||
public static final String VISIBLE_ARCH_ATTRIBUTE_NAME = "arch";
|
||||
public static final String VISIBLE_OS_ATTRIBUTE_NAME = "os";
|
||||
public static final String VISIBLE_ENDIAN_ATTRIBUTE_NAME = "endian";
|
||||
|
||||
protected final GdbModelImpl impl;
|
||||
|
||||
protected String arch = "(unknown)";
|
||||
|
@ -96,7 +99,7 @@ public class GdbModelTargetEnvironment
|
|||
// But, that may also be (perhaps more) version dependent
|
||||
this.arch = arch;
|
||||
}).exceptionally(e -> {
|
||||
Msg.error(this, "Could not get target architecture", e);
|
||||
model.reportError(this, "Could not get target architecture", e);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
@ -130,7 +133,7 @@ public class GdbModelTargetEnvironment
|
|||
// Would need to ignore "auto", "default", and "none"?
|
||||
this.os = os;
|
||||
}).exceptionally(e -> {
|
||||
Msg.error(this, "Could not get target os", e);
|
||||
model.reportError(this, "Could not get target os", e);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
@ -148,7 +151,7 @@ public class GdbModelTargetEnvironment
|
|||
endian = "(unknown)";
|
||||
}
|
||||
}).exceptionally(e -> {
|
||||
Msg.error(this, "Could not get target endian", e);
|
||||
model.reportError(this, "Could not get target endian", e);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
@ -170,21 +173,18 @@ public class GdbModelTargetEnvironment
|
|||
});
|
||||
}
|
||||
|
||||
@TargetAttributeType(name = ARCH_ATTRIBUTE_NAME, hidden = true)
|
||||
@Deprecated(forRemoval = true)
|
||||
public String getInvisibleArch() {
|
||||
@TargetAttributeType(name = VISIBLE_ARCH_ATTRIBUTE_NAME)
|
||||
public String getVisibleArch() {
|
||||
return arch;
|
||||
}
|
||||
|
||||
@TargetAttributeType(name = OS_ATTRIBUTE_NAME, hidden = true)
|
||||
@Deprecated(forRemoval = true)
|
||||
public String getInvisibleOs() {
|
||||
@TargetAttributeType(name = VISIBLE_OS_ATTRIBUTE_NAME)
|
||||
public String getVisibleOs() {
|
||||
return os;
|
||||
}
|
||||
|
||||
@TargetAttributeType(name = ENDIAN_ATTRIBUTE_NAME, hidden = true)
|
||||
@Deprecated(forRemoval = true)
|
||||
public String getInvisibleEndian() {
|
||||
@TargetAttributeType(name = VISIBLE_ENDIAN_ATTRIBUTE_NAME)
|
||||
public String getVisibleEndian() {
|
||||
return endian;
|
||||
}
|
||||
|
||||
|
|
|
@ -37,6 +37,9 @@ import ghidra.util.Msg;
|
|||
public class GdbModelTargetModule
|
||||
extends DefaultTargetObject<TargetObject, GdbModelTargetModuleContainer>
|
||||
implements TargetModule<GdbModelTargetModule> {
|
||||
|
||||
public static final String VISIBLE_RANGE_ATTRIBUTE_NAME = "range";
|
||||
|
||||
protected static String indexModule(GdbModule module) {
|
||||
return module.getName();
|
||||
}
|
||||
|
@ -124,9 +127,10 @@ public class GdbModelTargetModule
|
|||
return range;
|
||||
}
|
||||
|
||||
@Deprecated(forRemoval = true)
|
||||
@TargetAttributeType(name = RANGE_ATTRIBUTE_NAME)
|
||||
public AddressRange getInvisibleRange() {
|
||||
// TODO: Consider a way to override the "hidden" field of an attribute
|
||||
// Otherwise, this information is duplicated in memory and on the wire
|
||||
@TargetAttributeType(name = VISIBLE_RANGE_ATTRIBUTE_NAME)
|
||||
public AddressRange getVisibleRange() {
|
||||
return range;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,6 +34,9 @@ import ghidra.program.model.address.*;
|
|||
public class GdbModelTargetSection
|
||||
extends DefaultTargetObject<TargetObject, GdbModelTargetSectionContainer>
|
||||
implements TargetSection<GdbModelTargetSection> {
|
||||
|
||||
public static final String VISIBLE_RANGE_ATTRIBUTE_NAME = "range";
|
||||
|
||||
protected static String indexSection(GdbModuleSection section) {
|
||||
return section.getName();
|
||||
}
|
||||
|
@ -85,9 +88,8 @@ public class GdbModelTargetSection
|
|||
return range;
|
||||
}
|
||||
|
||||
@Deprecated(forRemoval = true)
|
||||
@TargetAttributeType(name = RANGE_ATTRIBUTE_NAME)
|
||||
public AddressRange getInvisibleRange() {
|
||||
@TargetAttributeType(name = VISIBLE_RANGE_ATTRIBUTE_NAME)
|
||||
public AddressRange getVisibleRange() {
|
||||
return range;
|
||||
}
|
||||
|
||||
|
|
|
@ -230,7 +230,7 @@ public class GdbModelTargetThread
|
|||
protected CompletableFuture<?> updateStack() {
|
||||
Msg.debug(this, "Updating stack for " + this);
|
||||
return stack.update().thenCompose(__ -> updateInfo()).exceptionally(ex -> {
|
||||
Msg.error(this, "Could not update stack for thread " + this, ex);
|
||||
model.reportError(this, "Could not update stack for thread " + this, ex);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1993,6 +1993,7 @@ public class DefaultTraceRecorder implements TraceRecorder {
|
|||
protected synchronized void removeProcessModule(TargetModule<?> module) {
|
||||
String path = PathUtils.toString(module.getPath());
|
||||
long snap = snapshot.getKey();
|
||||
TraceThread eventThread = snapshot.getEventThread();
|
||||
TraceModule traceModule = moduleManager.getLoadedModuleByPath(snap, path);
|
||||
if (traceModule == null) {
|
||||
Msg.warn(this, "unloaded " + path + " is not in the trace");
|
||||
|
@ -2000,6 +2001,11 @@ public class DefaultTraceRecorder implements TraceRecorder {
|
|||
}
|
||||
try (PermanentTransaction tid =
|
||||
PermanentTransaction.start(trace, "Module " + path + " unloaded")) {
|
||||
if (traceModule.getLoadedSnap() == snap) {
|
||||
Msg.warn(this, "Observed module unload in the same snap as its load");
|
||||
createSnapshot("WARN: Module removed", eventThread, tid);
|
||||
snap = snapshot.getKey();
|
||||
}
|
||||
traceModule.setUnloadedSnap(snap - 1);
|
||||
}
|
||||
catch (DuplicateNameException e) {
|
||||
|
|
|
@ -22,14 +22,14 @@ import java.util.concurrent.CompletableFuture;
|
|||
import ghidra.async.AsyncUtils;
|
||||
import ghidra.async.TypeSpec;
|
||||
import ghidra.dbg.attributes.TargetObjectRef;
|
||||
import ghidra.dbg.error.DebuggerModelNoSuchPathException;
|
||||
import ghidra.dbg.error.DebuggerModelTypeException;
|
||||
import ghidra.dbg.error.*;
|
||||
import ghidra.dbg.target.TargetMemory;
|
||||
import ghidra.dbg.target.TargetObject;
|
||||
import ghidra.dbg.target.schema.EnumerableTargetObjectSchema;
|
||||
import ghidra.dbg.target.schema.TargetObjectSchema;
|
||||
import ghidra.dbg.util.PathUtils;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.util.Msg;
|
||||
|
||||
/**
|
||||
* A debugger model, often a connection to an external debugger
|
||||
|
@ -220,6 +220,7 @@ public interface DebuggerObjectModel {
|
|||
/**
|
||||
* Create a reference to the given path in this model
|
||||
*
|
||||
* <p>
|
||||
* Note that the path is not checked until the object is fetched. Thus, it is possible for a
|
||||
* reference to refer to a non-existent object.
|
||||
*
|
||||
|
@ -238,6 +239,7 @@ public interface DebuggerObjectModel {
|
|||
/**
|
||||
* Fetch the attributes of a given model path
|
||||
*
|
||||
* <p>
|
||||
* Giving an empty path will retrieve the attributes of the root object. If the path does not
|
||||
* exist, the future completes with {@code null}.
|
||||
*
|
||||
|
@ -269,6 +271,7 @@ public interface DebuggerObjectModel {
|
|||
/**
|
||||
* Fetch the elements of a given model path
|
||||
*
|
||||
* <p>
|
||||
* Giving an empty path will retrieve all the top-level objects, i.e., elements of the root. If
|
||||
* the path does not exist, the future completes with {@code null}.
|
||||
*
|
||||
|
@ -300,6 +303,7 @@ public interface DebuggerObjectModel {
|
|||
/**
|
||||
* Fetch the root object of the model
|
||||
*
|
||||
* <p>
|
||||
* The root is a virtual object to contain all the top-level objects of the model tree. This
|
||||
* object represents the debugger itself.
|
||||
*
|
||||
|
@ -310,7 +314,6 @@ public interface DebuggerObjectModel {
|
|||
/**
|
||||
* Fetch the value at the given path
|
||||
*
|
||||
*
|
||||
* @param path the path of the value
|
||||
* @return a future completing with the value or with {@code null} if the path does not exist
|
||||
*/
|
||||
|
@ -462,6 +465,7 @@ public interface DebuggerObjectModel {
|
|||
/**
|
||||
* Invalidate the caches for every object known locally.
|
||||
*
|
||||
* <p>
|
||||
* Unlike, {@link TargetObject#invalidateCaches()}, this does not push the request to a remote
|
||||
* object. If the objects are proxies, just the proxies' caches are cleared. Again, this does
|
||||
* not apply to caches for the objects' children.
|
||||
|
@ -471,10 +475,30 @@ public interface DebuggerObjectModel {
|
|||
/**
|
||||
* Close the session and dispose the model
|
||||
*
|
||||
* <p>
|
||||
* For local sessions, terminate the debugger. For client sessions, disconnect.
|
||||
*
|
||||
* @return a future which completes when the session is closed
|
||||
*/
|
||||
public CompletableFuture<Void> close();
|
||||
|
||||
/**
|
||||
* A convenience for reporting errors conditionally
|
||||
*
|
||||
* <p>
|
||||
* If the message is ignorable, e.g., a {@link DebuggerModelTerminatingException}, then the
|
||||
* report will be reduced to a stack-free warning.
|
||||
*
|
||||
* @param origin the object producing the error
|
||||
* @param message the error message
|
||||
* @param ex the exception
|
||||
*/
|
||||
default void reportError(Object origin, String message, Throwable ex) {
|
||||
if (ex == null || DebuggerModelTerminatingException.isIgnorable(ex)) {
|
||||
Msg.warn(origin, message + ": " + ex);
|
||||
}
|
||||
else {
|
||||
Msg.error(origin, message, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,9 +50,6 @@ public interface TargetEnvironment<T extends TargetEnvironment<T>> extends Typed
|
|||
String DEBUGGER_ATTRIBUTE_NAME = PREFIX_INVISIBLE + "debugger";
|
||||
String OS_ATTRIBUTE_NAME = PREFIX_INVISIBLE + "os";
|
||||
String ENDIAN_ATTRIBUTE_NAME = PREFIX_INVISIBLE + "endian";
|
||||
String VISIBLE_ARCH_ATTRIBUTE_NAME = "arch";
|
||||
String VISIBLE_OS_ATTRIBUTE_NAME = "os";
|
||||
String VISIBLE_ENDIAN_ATTRIBUTE_NAME = "endian";
|
||||
|
||||
/**
|
||||
* Get a description of the target architecture
|
||||
|
@ -66,9 +63,9 @@ public interface TargetEnvironment<T extends TargetEnvironment<T>> extends Typed
|
|||
*
|
||||
* @return the target architecture
|
||||
*/
|
||||
@TargetAttributeType(name = VISIBLE_ARCH_ATTRIBUTE_NAME)
|
||||
@TargetAttributeType(name = ARCH_ATTRIBUTE_NAME, hidden = true)
|
||||
default String getArchitecture() {
|
||||
return getTypedAttributeNowByName(VISIBLE_ARCH_ATTRIBUTE_NAME, String.class, "");
|
||||
return getTypedAttributeNowByName(ARCH_ATTRIBUTE_NAME, String.class, "");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -101,9 +98,9 @@ public interface TargetEnvironment<T extends TargetEnvironment<T>> extends Typed
|
|||
*
|
||||
* @return the target operating system
|
||||
*/
|
||||
@TargetAttributeType(name = VISIBLE_OS_ATTRIBUTE_NAME)
|
||||
@TargetAttributeType(name = OS_ATTRIBUTE_NAME, hidden = true)
|
||||
default String getOperatingSystem() {
|
||||
return getTypedAttributeNowByName(VISIBLE_OS_ATTRIBUTE_NAME, String.class, "");
|
||||
return getTypedAttributeNowByName(OS_ATTRIBUTE_NAME, String.class, "");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -116,9 +113,9 @@ public interface TargetEnvironment<T extends TargetEnvironment<T>> extends Typed
|
|||
*
|
||||
* @return the target endianness
|
||||
*/
|
||||
@TargetAttributeType(name = VISIBLE_ENDIAN_ATTRIBUTE_NAME)
|
||||
@TargetAttributeType(name = ENDIAN_ATTRIBUTE_NAME, hidden = true)
|
||||
default String getEndian() {
|
||||
return getTypedAttributeNowByName(VISIBLE_ENDIAN_ATTRIBUTE_NAME, String.class, "");
|
||||
return getTypedAttributeNowByName(ENDIAN_ATTRIBUTE_NAME, String.class, "");
|
||||
}
|
||||
|
||||
// TODO: Devices? File System?
|
||||
|
|
|
@ -39,7 +39,6 @@ public interface TargetModule<T extends TargetModule<T>> extends TypedTargetObje
|
|||
Class<Private.Cls> tclass = (Class) TargetModule.class;
|
||||
TypeSpec<TargetModule<?>> TYPE = TypeSpec.auto();
|
||||
|
||||
String VISIBLE_RANGE_ATTRIBUTE_NAME = "range";
|
||||
String RANGE_ATTRIBUTE_NAME = PREFIX_INVISIBLE + "range";
|
||||
String MODULE_NAME_ATTRIBUTE_NAME = PREFIX_INVISIBLE + "module_name";
|
||||
|
||||
|
@ -54,9 +53,9 @@ public interface TargetModule<T extends TargetModule<T>> extends TypedTargetObje
|
|||
*
|
||||
* @return the base address, or {@code null}
|
||||
*/
|
||||
@TargetAttributeType(name = VISIBLE_RANGE_ATTRIBUTE_NAME, required = true)
|
||||
@TargetAttributeType(name = RANGE_ATTRIBUTE_NAME, required = true, hidden = true)
|
||||
public default AddressRange getRange() {
|
||||
return getTypedAttributeNowByName(VISIBLE_RANGE_ATTRIBUTE_NAME, AddressRange.class, null);
|
||||
return getTypedAttributeNowByName(RANGE_ATTRIBUTE_NAME, AddressRange.class, null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -221,7 +221,12 @@ public interface TargetObject extends TargetObjectRef {
|
|||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
/**
|
||||
* A conventional prefix of hidden attributes defined by the {@code TargetObject} interfaces
|
||||
*
|
||||
* <p>
|
||||
* When the "hidden" field of attributes can be overridden, this prefix should be removed
|
||||
*/
|
||||
String PREFIX_INVISIBLE = "_";
|
||||
|
||||
String DISPLAY_ATTRIBUTE_NAME = PREFIX_INVISIBLE + "display";
|
||||
|
|
|
@ -45,7 +45,6 @@ public interface TargetSection<T extends TargetSection<T>> extends TypedTargetOb
|
|||
|
||||
String MODULE_ATTRIBUTE_NAME = PREFIX_INVISIBLE + "module";
|
||||
String RANGE_ATTRIBUTE_NAME = PREFIX_INVISIBLE + "range";
|
||||
String VISIBLE_RANGE_ATTRIBUTE_NAME = "range";
|
||||
|
||||
/**
|
||||
* Get the module to which this section belongs
|
||||
|
@ -66,9 +65,9 @@ public interface TargetSection<T extends TargetSection<T>> extends TypedTargetOb
|
|||
*
|
||||
* @return the range
|
||||
*/
|
||||
@TargetAttributeType(name = VISIBLE_RANGE_ATTRIBUTE_NAME, required = true, fixed = true)
|
||||
@TargetAttributeType(name = RANGE_ATTRIBUTE_NAME, required = true, fixed = true)
|
||||
public default AddressRange getRange() {
|
||||
return getTypedAttributeNowByName(VISIBLE_RANGE_ATTRIBUTE_NAME, AddressRange.class, null);
|
||||
return getTypedAttributeNowByName(RANGE_ATTRIBUTE_NAME, AddressRange.class, null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -31,6 +31,7 @@ import ghidra.dbg.target.TargetObject;
|
|||
import ghidra.dbg.target.schema.DefaultTargetObjectSchema.DefaultAttributeSchema;
|
||||
import ghidra.dbg.target.schema.TargetObjectSchema.AttributeSchema;
|
||||
import ghidra.dbg.target.schema.TargetObjectSchema.SchemaName;
|
||||
import ghidra.util.Msg;
|
||||
import utilities.util.reflection.ReflectionUtilities;
|
||||
|
||||
public class AnnotatedSchemaContext extends DefaultSchemaContext {
|
||||
|
@ -115,8 +116,7 @@ public class AnnotatedSchemaContext extends DefaultSchemaContext {
|
|||
return Set.of(TargetObject.class);
|
||||
}
|
||||
throw new IllegalArgumentException("Getter " + getter +
|
||||
" for attribute must return primitive or subclass of " +
|
||||
TargetObjectRef.class);
|
||||
" for attribute must return primitive or subclass of " + TargetObjectRef.class);
|
||||
}
|
||||
|
||||
protected final Map<Class<? extends TargetObject>, SchemaName> namesByClass =
|
||||
|
@ -126,13 +126,14 @@ public class AnnotatedSchemaContext extends DefaultSchemaContext {
|
|||
|
||||
protected SchemaName nameFromAnnotatedClass(Class<? extends TargetObject> cls) {
|
||||
synchronized (namesByClass) {
|
||||
TargetObjectSchemaInfo info = cls.getAnnotation(TargetObjectSchemaInfo.class);
|
||||
if (info == null) {
|
||||
// TODO: Compile-time validation?
|
||||
Msg.warn(this, "Class " + cls + " is not annotated with @" +
|
||||
TargetObjectSchemaInfo.class.getSimpleName());
|
||||
return EnumerableTargetObjectSchema.OBJECT.getName();
|
||||
}
|
||||
return namesByClass.computeIfAbsent(cls, c -> {
|
||||
TargetObjectSchemaInfo info = cls.getAnnotation(TargetObjectSchemaInfo.class);
|
||||
if (info == null) {
|
||||
// TODO: Compile-time validation?
|
||||
throw new IllegalArgumentException("Class " + cls + " is not annotated with @" +
|
||||
TargetObjectSchemaInfo.class.getSimpleName());
|
||||
}
|
||||
String name = info.name();
|
||||
if (name.equals("")) {
|
||||
return new SchemaName(cls.getSimpleName());
|
||||
|
@ -166,8 +167,7 @@ public class AnnotatedSchemaContext extends DefaultSchemaContext {
|
|||
|
||||
AttributeSchema attrSchema;
|
||||
try {
|
||||
attrSchema =
|
||||
attributeSchemaFromAnnotatedMethod(declCls, method, at);
|
||||
attrSchema = attributeSchemaFromAnnotatedMethod(declCls, method, at);
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
throw new IllegalArgumentException(
|
||||
|
@ -209,7 +209,7 @@ public class AnnotatedSchemaContext extends DefaultSchemaContext {
|
|||
if (bounds.size() != 1) {
|
||||
// TODO: Compile-time validation?
|
||||
throw new IllegalArgumentException(
|
||||
"Could not identify unique element class: " + bounds);
|
||||
"Could not identify unique element class (" + bounds + ") for " + cls);
|
||||
}
|
||||
else {
|
||||
Class<? extends TargetObject> bound = bounds.iterator().next();
|
||||
|
@ -219,8 +219,8 @@ public class AnnotatedSchemaContext extends DefaultSchemaContext {
|
|||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
throw new IllegalArgumentException(
|
||||
"Could not get schema name from bound " + bound + " of " +
|
||||
cls + ".fetchElements()",
|
||||
"Could not get schema name from bound " + bound + " of " + cls +
|
||||
".fetchElements()",
|
||||
e);
|
||||
}
|
||||
builder.setDefaultElementSchema(schemaName);
|
||||
|
@ -245,30 +245,27 @@ public class AnnotatedSchemaContext extends DefaultSchemaContext {
|
|||
}
|
||||
|
||||
protected String attributeNameFromBean(String beanName, boolean isBool) {
|
||||
beanName = isBool
|
||||
? StringUtils.removeStartIgnoreCase(beanName, "is")
|
||||
beanName = isBool ? StringUtils.removeStartIgnoreCase(beanName, "is")
|
||||
: StringUtils.removeStartIgnoreCase(beanName, "get");
|
||||
if (beanName.equals("")) {
|
||||
throw new IllegalArgumentException("Attribute getter must have a name");
|
||||
}
|
||||
return beanName
|
||||
.replaceAll("([A-Z]+)([A-Z][a-z])", "$1_$2")
|
||||
return beanName.replaceAll("([A-Z]+)([A-Z][a-z])", "$1_$2")
|
||||
.replaceAll("([a-z])([A-Z])", "$1_$2")
|
||||
.toLowerCase();
|
||||
}
|
||||
|
||||
protected AttributeSchema attributeSchemaFromAnnotation(TargetAttributeType at) {
|
||||
return new DefaultAttributeSchema(at.name(), nameFromClass(at.type()),
|
||||
at.required(), at.fixed(), at.hidden());
|
||||
return new DefaultAttributeSchema(at.name(), nameFromClass(at.type()), at.required(),
|
||||
at.fixed(), at.hidden());
|
||||
}
|
||||
|
||||
protected AttributeSchema attributeSchemaFromAnnotatedMethod(Class<? extends TargetObject> cls,
|
||||
Method method, TargetAttributeType at) {
|
||||
if (method.getParameterCount() != 0) {
|
||||
// TODO: Compile-time validation?
|
||||
throw new IllegalArgumentException(
|
||||
"Non-getter method " + method + " is annotated with @" +
|
||||
TargetAttributeType.class.getSimpleName());
|
||||
throw new IllegalArgumentException("Non-getter method " + method +
|
||||
" is annotated with @" + TargetAttributeType.class.getSimpleName());
|
||||
}
|
||||
String name = at.name();
|
||||
Class<?> ret = method.getReturnType();
|
||||
|
@ -276,11 +273,10 @@ public class AnnotatedSchemaContext extends DefaultSchemaContext {
|
|||
name = attributeNameFromBean(method.getName(),
|
||||
EnumerableTargetObjectSchema.BOOL.getTypes().contains(ret));
|
||||
}
|
||||
SchemaName primitiveName =
|
||||
EnumerableTargetObjectSchema.nameForPrimitive(ret);
|
||||
SchemaName primitiveName = EnumerableTargetObjectSchema.nameForPrimitive(ret);
|
||||
if (primitiveName != null) {
|
||||
return new DefaultAttributeSchema(name, primitiveName,
|
||||
at.required(), at.fixed(), at.hidden());
|
||||
return new DefaultAttributeSchema(name, primitiveName, at.required(), at.fixed(),
|
||||
at.hidden());
|
||||
}
|
||||
Set<Class<? extends TargetObject>> bounds = getBoundsOfObjectAttributeGetter(cls, method);
|
||||
if (bounds.size() != 1) {
|
||||
|
|
Loading…
Reference in New Issue
Block a user