GP-601: Generic configuration + change of base for IDs

This commit is contained in:
d-millar 2021-04-01 18:39:33 -04:00 committed by Dan
parent 314c58e941
commit 92017b9f7d
27 changed files with 602 additions and 111 deletions

View file

@ -0,0 +1,28 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package agent.dbgeng.model.iface1;
import agent.dbgeng.model.iface2.DbgModelTargetObject;
import ghidra.dbg.target.TargetConfigurable;
/**
* An interface which indicates this object is configurable.
*
* @param <T> type for this
*/
public interface DbgModelTargetConfigurable extends DbgModelTargetObject, TargetConfigurable {
}

View file

@ -23,4 +23,6 @@ public interface DbgModelTargetAvailable extends DbgModelTargetObject, TargetAtt
public long getPid();
public void setBase(Object value);
}

View file

@ -22,30 +22,31 @@ import java.util.stream.Collectors;
import org.apache.commons.lang3.tuple.Pair;
import agent.dbgeng.model.iface1.DbgModelTargetConfigurable;
import agent.dbgeng.model.iface2.*;
import ghidra.async.AsyncUtils;
import ghidra.dbg.error.DebuggerIllegalArgumentException;
import ghidra.dbg.target.TargetConfigurable;
import ghidra.dbg.target.TargetObject;
import ghidra.dbg.target.schema.*;
import ghidra.dbg.target.schema.TargetObjectSchema.ResyncMode;
import ghidra.util.datastruct.WeakValueHashMap;
@TargetObjectSchemaInfo(
name = "AvailableContainer",
elements = {
@TargetElementType(type = DbgModelTargetAvailableImpl.class)
},
elementResync = ResyncMode.ALWAYS,
attributes = {
@TargetAttributeType(type = Void.class)
},
canonicalContainer = true)
@TargetObjectSchemaInfo(name = "AvailableContainer", elements = {
@TargetElementType(type = DbgModelTargetAvailableImpl.class) //
}, elementResync = ResyncMode.ALWAYS, attributes = { //
@TargetAttributeType(name = TargetConfigurable.BASE_ATTRIBUTE_NAME, type = Integer.class), //
@TargetAttributeType(type = Void.class) //
}, canonicalContainer = true)
public class DbgModelTargetAvailableContainerImpl extends DbgModelTargetObjectImpl
implements DbgModelTargetAvailableContainer {
implements DbgModelTargetAvailableContainer, DbgModelTargetConfigurable {
protected final Map<Integer, DbgModelTargetAvailable> attachablesById =
new WeakValueHashMap<>();
public DbgModelTargetAvailableContainerImpl(DbgModelTargetRoot root) {
super(root.getModel(), root, "Available", "AvailableContainer");
this.changeAttributes(List.of(), Map.of(BASE_ATTRIBUTE_NAME, 16), "Initialized");
}
@Override
@ -71,4 +72,24 @@ public class DbgModelTargetAvailableContainerImpl extends DbgModelTargetObjectIm
return attachablesById.computeIfAbsent(pid,
i -> new DbgModelTargetAvailableImpl(this, pid));
}
@Override
public CompletableFuture<Void> writeConfigurationOption(String key, Object value) {
switch (key) {
case BASE_ATTRIBUTE_NAME:
if (value instanceof Integer) {
this.changeAttributes(List.of(), Map.of(BASE_ATTRIBUTE_NAME, value),
"Modified");
for (DbgModelTargetAvailable child : attachablesById.values()) {
child.setBase(value);
}
}
else {
throw new DebuggerIllegalArgumentException("Base should be numeric");
}
default:
}
return AsyncUtils.NIL;
}
}

View file

@ -23,23 +23,26 @@ 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)
})
@TargetObjectSchemaInfo(name = "Available", elements = {
@TargetElementType(type = Void.class) }, attributes = {
@TargetAttributeType(type = Void.class) })
public class DbgModelTargetAvailableImpl extends DbgModelTargetObjectImpl
implements DbgModelTargetAvailable {
protected static String indexAttachable(int pid) {
return Integer.toHexString(pid);
protected static String indexAttachable(int pid, Integer base) {
String pidstr = Integer.toString(pid, base);
if (base == 16) {
pidstr = "0x" + pidstr;
}
return pidstr;
}
protected static String keyAttachable(int pid, Integer base) {
return PathUtils.makeKey(indexAttachable(pid, base));
}
protected static String keyAttachable(int pid) {
return PathUtils.makeKey(indexAttachable(pid));
return PathUtils.makeKey(indexAttachable(pid, 16));
}
protected final int pid;
@ -71,4 +74,10 @@ public class DbgModelTargetAvailableImpl extends DbgModelTargetObjectImpl
return pid;
}
public void setBase(Object value) {
this.changeAttributes(List.of(), List.of(), Map.of(//
DISPLAY_ATTRIBUTE_NAME, keyAttachable(pid, (Integer) value) //
), "Initialized");
}
}

View file

@ -22,18 +22,26 @@ import java.util.stream.Collectors;
import agent.dbgeng.dbgeng.*;
import agent.dbgeng.manager.*;
import agent.dbgeng.model.iface1.DbgModelTargetConfigurable;
import agent.dbgeng.model.iface2.*;
import ghidra.async.AsyncUtils;
import ghidra.dbg.error.DebuggerIllegalArgumentException;
import ghidra.dbg.target.TargetConfigurable;
import ghidra.dbg.target.TargetObject;
import ghidra.dbg.target.schema.*;
@TargetObjectSchemaInfo(name = "ProcessContainer", elements = {
@TargetElementType(type = DbgModelTargetProcessImpl.class) }, attributes = {
@TargetAttributeType(type = Void.class) }, canonicalContainer = true)
@TargetObjectSchemaInfo(name = "ProcessContainer", elements = { //
@TargetElementType(type = DbgModelTargetProcessImpl.class) //
}, attributes = { //
@TargetAttributeType(name = TargetConfigurable.BASE_ATTRIBUTE_NAME, type = Integer.class), //
@TargetAttributeType(type = Void.class) //
}, canonicalContainer = true)
public class DbgModelTargetProcessContainerImpl extends DbgModelTargetObjectImpl
implements DbgModelTargetProcessContainer {
implements DbgModelTargetProcessContainer, DbgModelTargetConfigurable {
public DbgModelTargetProcessContainerImpl(DbgModelTargetSession session) {
super(session.getModel(), session, "Processes", "ProcessContainer");
this.changeAttributes(List.of(), Map.of(BASE_ATTRIBUTE_NAME, 16), "Initialized");
getManager().addEventsListener(this);
}
@ -133,4 +141,27 @@ public class DbgModelTargetProcessContainerImpl extends DbgModelTargetObjectImpl
return new DbgModelTargetProcessImpl(this, process);
}
@Override
public CompletableFuture<Void> writeConfigurationOption(String key, Object value) {
switch (key) {
case BASE_ATTRIBUTE_NAME:
if (value instanceof Integer) {
this.changeAttributes(List.of(), Map.of(BASE_ATTRIBUTE_NAME, value),
"Modified");
for (TargetObject child : getCachedElements().values()) {
if (child instanceof DbgModelTargetProcessImpl) {
DbgModelTargetProcessImpl targetProcess =
(DbgModelTargetProcessImpl) child;
targetProcess.setBase(value);
}
}
}
else {
throw new DebuggerIllegalArgumentException("Base should be numeric");
}
default:
}
return AsyncUtils.NIL;
}
}

View file

@ -67,6 +67,8 @@ public class DbgModelTargetProcessImpl extends DbgModelTargetObjectImpl
// Note: not sure section info is available from the dbgeng
//protected final DbgModelTargetProcessSectionContainer sections;
private Integer base = 16;
public DbgModelTargetProcessImpl(DbgModelTargetProcessContainer processes, DbgProcess process) {
super(processes.getModel(), processes, keyProcess(process), "Process");
this.getModel().addModelObject(process, this);
@ -102,7 +104,12 @@ public class DbgModelTargetProcessImpl extends DbgModelTargetObjectImpl
if (getManager().isKernelMode()) {
return "[kernel]";
}
return "[" + process.getId().id + ":0x" + Long.toHexString(process.getPid()) + "]";
String pidstr = Long.toString(process.getPid(), base);
if (base == 16) {
pidstr = "0x" + pidstr;
}
return "[" + process.getId().id + ":" + pidstr + "]";
}
@Override
@ -177,7 +184,7 @@ public class DbgModelTargetProcessImpl extends DbgModelTargetObjectImpl
if (pid != null) {
changeAttributes(List.of(), List.of(), Map.of( //
PID_ATTRIBUTE_NAME, pid, //
DISPLAY_ATTRIBUTE_NAME, "[0x" + Long.toHexString(pid) + "]" //
DISPLAY_ATTRIBUTE_NAME, getDisplay()//
), "Started");
}
setExecutionState(TargetExecutionState.ALIVE, "Started");
@ -221,4 +228,11 @@ public class DbgModelTargetProcessImpl extends DbgModelTargetObjectImpl
public boolean isAccessible() {
return accessible;
}
public void setBase(Object value) {
this.base = (Integer) value;
changeAttributes(List.of(), List.of(), Map.of( //
DISPLAY_ATTRIBUTE_NAME, getDisplay()//
), "Started");
}
}

View file

@ -27,25 +27,17 @@ 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),
@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 {
protected static final String DBG_PROMPT = "(kd)";
private Integer base = 16;
// NB: This should almost certainly always be implemented by the root of the object tree
protected static String indexSession(DebugSessionId debugSystemId) {

View file

@ -23,21 +23,29 @@ import java.util.stream.Collectors;
import agent.dbgeng.dbgeng.DebugThreadId;
import agent.dbgeng.manager.*;
import agent.dbgeng.manager.reason.*;
import agent.dbgeng.model.iface1.DbgModelTargetConfigurable;
import agent.dbgeng.model.iface2.*;
import ghidra.async.AsyncUtils;
import ghidra.dbg.error.DebuggerIllegalArgumentException;
import ghidra.dbg.target.TargetConfigurable;
import ghidra.dbg.target.TargetObject;
import ghidra.dbg.target.schema.*;
@TargetObjectSchemaInfo(name = "ThreadContainer", elements = {
@TargetElementType(type = DbgModelTargetThreadImpl.class) }, attributes = {
@TargetAttributeType(type = Void.class) }, canonicalContainer = true)
@TargetObjectSchemaInfo(name = "ThreadContainer", elements = { //
@TargetElementType(type = DbgModelTargetThreadImpl.class) //
}, attributes = { //
@TargetAttributeType(name = TargetConfigurable.BASE_ATTRIBUTE_NAME, type = Integer.class), //
@TargetAttributeType(type = Void.class) //
}, canonicalContainer = true)
public class DbgModelTargetThreadContainerImpl extends DbgModelTargetObjectImpl
implements DbgModelTargetThreadContainer {
implements DbgModelTargetThreadContainer, DbgModelTargetConfigurable {
protected final DbgProcess process;
public DbgModelTargetThreadContainerImpl(DbgModelTargetProcessImpl process) {
super(process.getModel(), process, "Threads", "ThreadContainer");
this.process = process.process;
this.changeAttributes(List.of(), Map.of(BASE_ATTRIBUTE_NAME, 16), "Initialized");
getManager().addEventsListener(this);
requestElements(false);
@ -126,4 +134,26 @@ public class DbgModelTargetThreadContainerImpl extends DbgModelTargetObjectImpl
return new DbgModelTargetThreadImpl(this, (DbgModelTargetProcess) parent, thread);
}
@Override
public CompletableFuture<Void> writeConfigurationOption(String key, Object value) {
switch (key) {
case BASE_ATTRIBUTE_NAME:
if (value instanceof Integer) {
this.changeAttributes(List.of(), Map.of(BASE_ATTRIBUTE_NAME, value),
"Modified");
for (TargetObject child : getCachedElements().values()) {
if (child instanceof DbgModelTargetThreadImpl) {
DbgModelTargetThreadImpl targetThread =
(DbgModelTargetThreadImpl) child;
targetThread.setBase(value);
}
}
}
else {
throw new DebuggerIllegalArgumentException("Base should be numeric");
}
default:
}
return AsyncUtils.NIL;
}
}

View file

@ -67,6 +67,7 @@ public class DbgModelTargetThreadImpl extends DbgModelTargetObjectImpl
protected final DbgModelTargetStackImpl stack;
private DbgModelTargetProcess process;
private Integer base = 16;
public DbgModelTargetThreadImpl(DbgModelTargetThreadContainer threads,
DbgModelTargetProcess process, DbgThread thread) {
@ -98,7 +99,11 @@ public class DbgModelTargetThreadImpl extends DbgModelTargetObjectImpl
if (getManager().isKernelMode()) {
return "[PR" + thread.getId().id + "]";
}
return "[" + thread.getId().id + ":0x" + Long.toHexString(thread.getTid()) + "]";
String tidstr = Long.toString(thread.getTid(), base);
if (base == 16) {
tidstr = "0x" + tidstr;
}
return "[" + thread.getId().id + ":" + tidstr + "]";
}
@Override
@ -171,4 +176,11 @@ public class DbgModelTargetThreadImpl extends DbgModelTargetObjectImpl
return thread.getExecutingProcessorType().description;
}
public void setBase(Object value) {
this.base = (Integer) value;
changeAttributes(List.of(), List.of(), Map.of( //
DISPLAY_ATTRIBUTE_NAME, getDisplay()//
), "Started");
}
}