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