mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 02:39:44 +02:00
GP-601: Generic configuration + change of base for IDs
This commit is contained in:
parent
314c58e941
commit
92017b9f7d
27 changed files with 602 additions and 111 deletions
|
@ -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 {
|
||||
|
||||
}
|
|
@ -23,4 +23,6 @@ public interface DbgModelTargetAvailable extends DbgModelTargetObject, TargetAtt
|
|||
|
||||
public long getPid();
|
||||
|
||||
public void setBase(Object value);
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue