mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 10:49:34 +02:00
GP-3984: Have gdb connector delay section info until asked.
This commit is contained in:
parent
683dfc6da3
commit
644e2c53e5
22 changed files with 301 additions and 141 deletions
|
@ -23,8 +23,8 @@ import ghidra.debug.api.tracermi.*;
|
|||
import ghidra.trace.model.Trace;
|
||||
|
||||
public record RecordRemoteMethod(TraceRmiHandler handler, String name, ActionName action,
|
||||
String description, Map<String, RemoteParameter> parameters, SchemaName retType)
|
||||
implements RemoteMethod {
|
||||
String display, String description, Map<String, RemoteParameter> parameters,
|
||||
SchemaName retType) implements RemoteMethod {
|
||||
@Override
|
||||
public DefaultRemoteAsyncResult invokeAsync(Map<String, Object> arguments) {
|
||||
Trace trace = validate(arguments);
|
||||
|
|
|
@ -484,10 +484,10 @@ public class TraceRmiHandler implements TraceRmiConnection {
|
|||
RootMessage.Builder dispatch(RootMessage req, RootMessage.Builder rep) throws Exception;
|
||||
|
||||
default RootMessage handle(RootMessage req) {
|
||||
String desc = toString(req);
|
||||
/*String desc = toString(req);
|
||||
if (desc != null) {
|
||||
TimedMsg.debug(this, "HANDLING: " + desc);
|
||||
}
|
||||
}*/
|
||||
RootMessage.Builder rep = RootMessage.newBuilder();
|
||||
try {
|
||||
rep = dispatch(req, rep);
|
||||
|
@ -814,7 +814,7 @@ public class TraceRmiHandler implements TraceRmiConnection {
|
|||
|
||||
protected ReplyActivate handleActivate(RequestActivate req) {
|
||||
OpenTrace open = requireOpenTrace(req.getOid());
|
||||
TraceObject object = open.getObject(req.getObject(), true);
|
||||
TraceObject object = open.getObject(req.getObject(), false);
|
||||
DebuggerCoordinates coords = traceManager.getCurrent();
|
||||
if (coords.getTrace() != open.trace) {
|
||||
coords = DebuggerCoordinates.NOWHERE;
|
||||
|
@ -822,7 +822,7 @@ public class TraceRmiHandler implements TraceRmiConnection {
|
|||
if (open.lastSnapshot != null && followsPresent(open.trace)) {
|
||||
coords = coords.snap(open.lastSnapshot.getKey());
|
||||
}
|
||||
DebuggerCoordinates finalCoords = coords.object(object);
|
||||
DebuggerCoordinates finalCoords = object == null ? coords : coords.object(object);
|
||||
Swing.runLater(() -> {
|
||||
if (!traceManager.getOpenTraces().contains(open.trace)) {
|
||||
traceManager.openTrace(open.trace);
|
||||
|
@ -1031,7 +1031,7 @@ public class TraceRmiHandler implements TraceRmiConnection {
|
|||
}
|
||||
for (Method m : req.getMethodsList()) {
|
||||
RemoteMethod rm = new RecordRemoteMethod(this, m.getName(),
|
||||
ActionName.name(m.getAction()),
|
||||
ActionName.name(m.getAction()), m.getDisplay(),
|
||||
m.getDescription(), m.getParametersList()
|
||||
.stream()
|
||||
.collect(Collectors.toMap(MethodParameter::getName, this::makeParameter)),
|
||||
|
|
|
@ -240,6 +240,16 @@ public class TraceRmiTarget extends AbstractTarget {
|
|||
}
|
||||
}
|
||||
|
||||
protected long computeSpecificity(Map<String, Object> args) {
|
||||
long score = 0;
|
||||
for (Object o : args.values()) {
|
||||
if (o instanceof TraceObject obj) {
|
||||
score += obj.getCanonicalPath().getKeyList().size();
|
||||
}
|
||||
}
|
||||
return score;
|
||||
}
|
||||
|
||||
protected BooleanSupplier chooseEnabler(RemoteMethod method, Map<String, Object> args) {
|
||||
ActionName name = method.action();
|
||||
SchemaContext ctx = getSchemaContext();
|
||||
|
@ -282,7 +292,7 @@ public class TraceRmiTarget extends AbstractTarget {
|
|||
private Map<String, Object> promptArgs(RemoteMethod method, Map<String, Object> defaults) {
|
||||
SchemaContext ctx = getSchemaContext();
|
||||
RemoteMethodInvocationDialog dialog = new RemoteMethodInvocationDialog(tool,
|
||||
method.name(), method.name(), null);
|
||||
method.display(), method.display(), null);
|
||||
while (true) {
|
||||
for (RemoteParameter param : method.parameters().values()) {
|
||||
Object val = defaults.get(param.name());
|
||||
|
@ -325,8 +335,9 @@ public class TraceRmiTarget extends AbstractTarget {
|
|||
Map<String, Object> args = collectArguments(method, context, allowContextObject,
|
||||
allowCoordsObject, allowSuitableObject);
|
||||
boolean requiresPrompt = args.values().contains(Missing.MISSING);
|
||||
return new ActionEntry(method.name(), method.action(), method.description(), requiresPrompt,
|
||||
chooseEnabler(method, args), prompt -> invokeMethod(prompt, method, args));
|
||||
return new ActionEntry(method.display(), method.action(), method.description(),
|
||||
requiresPrompt, computeSpecificity(args), chooseEnabler(method, args),
|
||||
prompt -> invokeMethod(prompt, method, args));
|
||||
}
|
||||
|
||||
protected Map<String, ActionEntry> collectFromMethods(Collection<RemoteMethod> methods,
|
||||
|
@ -415,6 +426,11 @@ public class TraceRmiTarget extends AbstractTarget {
|
|||
return collectByName(ActionName.STEP_EXT, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<String, ActionEntry> collectRefreshActions(ActionContext context) {
|
||||
return collectByName(ActionName.REFRESH, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupportsFocus() {
|
||||
TargetObjectSchema schema = trace.getObjectManager().getRootSchema();
|
||||
|
|
|
@ -22,6 +22,7 @@ import org.apache.commons.lang3.ArrayUtils;
|
|||
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.rmi.trace.TraceRmi.*;
|
||||
import ghidra.util.NumericUtilities;
|
||||
|
||||
public interface ValueDecoder {
|
||||
ValueDecoder DEFAULT = new ValueDecoder() {};
|
||||
|
@ -104,7 +105,8 @@ public interface ValueDecoder {
|
|||
case STRING_VALUE -> value.getStringValue();
|
||||
case BOOL_ARR_VALUE -> ArrayUtils.toPrimitive(
|
||||
value.getBoolArrValue().getArrList().stream().toArray(Boolean[]::new));
|
||||
case BYTES_VALUE -> value.getBytesValue().toByteArray();
|
||||
case BYTES_VALUE -> NumericUtilities
|
||||
.convertBytesToString(value.getBytesValue().toByteArray(), ":");
|
||||
case CHAR_ARR_VALUE -> value.getCharArrValue().toCharArray();
|
||||
case SHORT_ARR_VALUE -> ArrayUtils.toPrimitive(
|
||||
value.getShortArrValue()
|
||||
|
|
|
@ -417,11 +417,12 @@ message MethodArgument {
|
|||
message Method {
|
||||
string name = 1;
|
||||
string action = 2;
|
||||
string description = 3;
|
||||
repeated MethodParameter parameters = 4;
|
||||
string display = 3;
|
||||
string description = 4;
|
||||
repeated MethodParameter parameters = 5;
|
||||
// I'd like to make them all void, but I think executing a command and capturing its output
|
||||
// justifies being able to return a result. It should be used very sparingly.
|
||||
ValueType return_type = 5;
|
||||
ValueType return_type = 6;
|
||||
}
|
||||
|
||||
message RequestNegotiate {
|
||||
|
|
|
@ -425,6 +425,7 @@ class ParamDesc:
|
|||
class RemoteMethod:
|
||||
name: str
|
||||
action: str
|
||||
display: str
|
||||
description: str
|
||||
parameters: List[RemoteParameter]
|
||||
return_schema: sch.Schema
|
||||
|
@ -484,11 +485,14 @@ class MethodRegistry(object):
|
|||
cls._to_display(p.annotation), cls._to_description(p.annotation))
|
||||
|
||||
@classmethod
|
||||
def create_method(cls, function, name=None, action=None, description=None) -> RemoteMethod:
|
||||
def create_method(cls, function, name=None, action=None, display=None,
|
||||
description=None) -> RemoteMethod:
|
||||
if name is None:
|
||||
name = function.__name__
|
||||
if action is None:
|
||||
action = name
|
||||
if display is None:
|
||||
display = name
|
||||
if description is None:
|
||||
description = function.__doc__ or ''
|
||||
sig = inspect.signature(function)
|
||||
|
@ -496,14 +500,16 @@ class MethodRegistry(object):
|
|||
for p in sig.parameters.values():
|
||||
params.append(cls._make_param(p))
|
||||
return_schema = cls._to_schema(sig, sig.return_annotation)
|
||||
return RemoteMethod(name, action, description, params, return_schema, function)
|
||||
return RemoteMethod(name, action, display, description, params,
|
||||
return_schema, function)
|
||||
|
||||
def method(self, func=None, *, name=None, action=None, description='',
|
||||
condition=True):
|
||||
def method(self, func=None, *, name=None, action=None, display=None,
|
||||
description='', condition=True):
|
||||
|
||||
def _method(func):
|
||||
if condition:
|
||||
method = self.create_method(func, name, action, description)
|
||||
method = self.create_method(func, name, action, display,
|
||||
description)
|
||||
self.register_method(method)
|
||||
return func
|
||||
|
||||
|
@ -669,6 +675,7 @@ class Client(object):
|
|||
def _write_method(to: bufs.Method, method: RemoteMethod):
|
||||
to.name = method.name
|
||||
to.action = method.action
|
||||
to.display = method.display
|
||||
to.description = method.description
|
||||
Client._write_parameters(to.parameters, method.parameters)
|
||||
to.return_type.name = method.return_schema.name
|
||||
|
|
|
@ -48,19 +48,19 @@ public class TestTraceRmiConnection implements TraceRmiConnection {
|
|||
}
|
||||
}
|
||||
|
||||
public record TestRemoteMethod(String name, ActionName action, String description,
|
||||
Map<String, RemoteParameter> parameters, SchemaName retType,
|
||||
public record TestRemoteMethod(String name, ActionName action, String display,
|
||||
String description, Map<String, RemoteParameter> parameters, SchemaName retType,
|
||||
AsyncPairingQueue<Map<String, Object>> argQueue, AsyncPairingQueue<Object> retQueue)
|
||||
implements RemoteMethod {
|
||||
public TestRemoteMethod(String name, ActionName action, String description,
|
||||
public TestRemoteMethod(String name, ActionName action, String display, String description,
|
||||
Map<String, RemoteParameter> parameters, SchemaName retType) {
|
||||
this(name, action, description, parameters, retType, new AsyncPairingQueue<>(),
|
||||
this(name, action, display, description, parameters, retType, new AsyncPairingQueue<>(),
|
||||
new AsyncPairingQueue<>());
|
||||
}
|
||||
|
||||
public TestRemoteMethod(String name, ActionName action, String description,
|
||||
public TestRemoteMethod(String name, ActionName action, String display, String description,
|
||||
SchemaName retType, RemoteParameter... parameters) {
|
||||
this(name, action, description, Stream.of(parameters)
|
||||
this(name, action, display, description, Stream.of(parameters)
|
||||
.collect(Collectors.toMap(RemoteParameter::name, p -> p)),
|
||||
retType);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue