mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 17:59:46 +02:00
GP-4390 Collapse DomainObject Undoable interfaces and refactor Command processing.
This commit is contained in:
parent
136b933af2
commit
445494ba25
214 changed files with 2862 additions and 3813 deletions
|
@ -322,8 +322,7 @@ public class TraceRmiHandler implements TraceRmiConnection {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected DomainFolder getOrCreateNewTracesFolder()
|
protected DomainFolder getOrCreateNewTracesFolder() throws InvalidNameException, IOException {
|
||||||
throws InvalidNameException, IOException {
|
|
||||||
return getOrCreateFolder(plugin.getTool().getProject().getProjectData().getRootFolder(),
|
return getOrCreateFolder(plugin.getTool().getProject().getProjectData().getRootFolder(),
|
||||||
"New Traces");
|
"New Traces");
|
||||||
}
|
}
|
||||||
|
@ -494,10 +493,8 @@ public class TraceRmiHandler implements TraceRmiConnection {
|
||||||
return rep == null ? null : rep.build();
|
return rep == null ? null : rep.build();
|
||||||
}
|
}
|
||||||
catch (Throwable e) {
|
catch (Throwable e) {
|
||||||
return rep
|
return rep.setError(ReplyError.newBuilder()
|
||||||
.setError(ReplyError.newBuilder()
|
.setMessage(e.getMessage() + "\n" + ExceptionUtils.getStackTrace(e)))
|
||||||
.setMessage(
|
|
||||||
e.getMessage() + "\n" + ExceptionUtils.getStackTrace(e)))
|
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -509,8 +506,8 @@ public class TraceRmiHandler implements TraceRmiConnection {
|
||||||
req.getRequestActivate().getOid().getId(),
|
req.getRequestActivate().getOid().getId(),
|
||||||
req.getRequestActivate().getObject().getId(),
|
req.getRequestActivate().getObject().getId(),
|
||||||
req.getRequestActivate().getObject().getPath().getPath());
|
req.getRequestActivate().getObject().getPath().getPath());
|
||||||
case REQUEST_END_TX -> "endTx(%d)".formatted(
|
case REQUEST_END_TX -> "endTx(%d)"
|
||||||
req.getRequestEndTx().getTxid().getId());
|
.formatted(req.getRequestEndTx().getTxid().getId());
|
||||||
case REQUEST_START_TX -> "startTx(%d,%s)".formatted(
|
case REQUEST_START_TX -> "startTx(%d,%s)".formatted(
|
||||||
req.getRequestStartTx().getTxid().getId(),
|
req.getRequestStartTx().getTxid().getId(),
|
||||||
req.getRequestStartTx().getDescription());
|
req.getRequestStartTx().getDescription());
|
||||||
|
@ -530,49 +527,40 @@ public class TraceRmiHandler implements TraceRmiConnection {
|
||||||
}
|
}
|
||||||
|
|
||||||
final Dispatcher dispatchNegotiate = (req, rep) -> switch (req.getMsgCase()) {
|
final Dispatcher dispatchNegotiate = (req, rep) -> switch (req.getMsgCase()) {
|
||||||
case REQUEST_NEGOTIATE -> rep
|
case REQUEST_NEGOTIATE -> rep.setReplyNegotiate(handleNegotiate(req.getRequestNegotiate()));
|
||||||
.setReplyNegotiate(handleNegotiate(req.getRequestNegotiate()));
|
|
||||||
default -> throw new InvalidRequestError(req);
|
default -> throw new InvalidRequestError(req);
|
||||||
};
|
};
|
||||||
|
|
||||||
final Dispatcher dispatchNominal = (req, rep) -> switch (req.getMsgCase()) {
|
final Dispatcher dispatchNominal = (req, rep) -> switch (req.getMsgCase()) {
|
||||||
case REQUEST_ACTIVATE -> rep
|
case REQUEST_ACTIVATE -> rep.setReplyActivate(handleActivate(req.getRequestActivate()));
|
||||||
.setReplyActivate(handleActivate(req.getRequestActivate()));
|
|
||||||
case REQUEST_CLOSE_TRACE -> rep
|
case REQUEST_CLOSE_TRACE -> rep
|
||||||
.setReplyCloseTrace(handleCloseTrace(req.getRequestCloseTrace()));
|
.setReplyCloseTrace(handleCloseTrace(req.getRequestCloseTrace()));
|
||||||
case REQUEST_CREATE_OBJECT -> rep
|
case REQUEST_CREATE_OBJECT -> rep
|
||||||
.setReplyCreateObject(handleCreateObject(req.getRequestCreateObject()));
|
.setReplyCreateObject(handleCreateObject(req.getRequestCreateObject()));
|
||||||
case REQUEST_CREATE_OVERLAY -> rep
|
case REQUEST_CREATE_OVERLAY -> rep
|
||||||
.setReplyCreateOverlay(
|
.setReplyCreateOverlay(handleCreateOverlay(req.getRequestCreateOverlay()));
|
||||||
handleCreateOverlay(req.getRequestCreateOverlay()));
|
|
||||||
case REQUEST_CREATE_ROOT_OBJECT -> rep
|
case REQUEST_CREATE_ROOT_OBJECT -> rep
|
||||||
.setReplyCreateObject(
|
.setReplyCreateObject(handleCreateRootObject(req.getRequestCreateRootObject()));
|
||||||
handleCreateRootObject(req.getRequestCreateRootObject()));
|
|
||||||
case REQUEST_CREATE_TRACE -> rep
|
case REQUEST_CREATE_TRACE -> rep
|
||||||
.setReplyCreateTrace(handleCreateTrace(req.getRequestCreateTrace()));
|
.setReplyCreateTrace(handleCreateTrace(req.getRequestCreateTrace()));
|
||||||
case REQUEST_DELETE_BYTES -> rep
|
case REQUEST_DELETE_BYTES -> rep
|
||||||
.setReplyDeleteBytes(handleDeleteBytes(req.getRequestDeleteBytes()));
|
.setReplyDeleteBytes(handleDeleteBytes(req.getRequestDeleteBytes()));
|
||||||
case REQUEST_DELETE_REGISTER_VALUE -> rep
|
case REQUEST_DELETE_REGISTER_VALUE -> rep.setReplyDeleteRegisterValue(
|
||||||
.setReplyDeleteRegisterValue(
|
|
||||||
handleDeleteRegisterValue(req.getRequestDeleteRegisterValue()));
|
handleDeleteRegisterValue(req.getRequestDeleteRegisterValue()));
|
||||||
case REQUEST_DISASSEMBLE -> rep
|
case REQUEST_DISASSEMBLE -> rep
|
||||||
.setReplyDisassemble(handleDisassemble(req.getRequestDisassemble()));
|
.setReplyDisassemble(handleDisassemble(req.getRequestDisassemble()));
|
||||||
case REQUEST_END_TX -> rep
|
case REQUEST_END_TX -> rep.setReplyEndTx(handleEndTx(req.getRequestEndTx()));
|
||||||
.setReplyEndTx(handleEndTx(req.getRequestEndTx()));
|
|
||||||
case REQUEST_GET_OBJECT -> rep
|
case REQUEST_GET_OBJECT -> rep
|
||||||
.setReplyGetObject(handleGetObject(req.getRequestGetObject()));
|
.setReplyGetObject(handleGetObject(req.getRequestGetObject()));
|
||||||
case REQUEST_GET_VALUES -> rep
|
case REQUEST_GET_VALUES -> rep
|
||||||
.setReplyGetValues(handleGetValues(req.getRequestGetValues()));
|
.setReplyGetValues(handleGetValues(req.getRequestGetValues()));
|
||||||
case REQUEST_GET_VALUES_INTERSECTING -> rep
|
case REQUEST_GET_VALUES_INTERSECTING -> rep.setReplyGetValues(
|
||||||
.setReplyGetValues(
|
|
||||||
handleGetValuesIntersecting(req.getRequestGetValuesIntersecting()));
|
handleGetValuesIntersecting(req.getRequestGetValuesIntersecting()));
|
||||||
case REQUEST_INSERT_OBJECT -> rep
|
case REQUEST_INSERT_OBJECT -> rep
|
||||||
.setReplyInsertObject(handleInsertObject(req.getRequestInsertObject()));
|
.setReplyInsertObject(handleInsertObject(req.getRequestInsertObject()));
|
||||||
case REQUEST_PUT_BYTES -> rep
|
case REQUEST_PUT_BYTES -> rep.setReplyPutBytes(handlePutBytes(req.getRequestPutBytes()));
|
||||||
.setReplyPutBytes(handlePutBytes(req.getRequestPutBytes()));
|
|
||||||
case REQUEST_PUT_REGISTER_VALUE -> rep
|
case REQUEST_PUT_REGISTER_VALUE -> rep
|
||||||
.setReplyPutRegisterValue(
|
.setReplyPutRegisterValue(handlePutRegisterValue(req.getRequestPutRegisterValue()));
|
||||||
handlePutRegisterValue(req.getRequestPutRegisterValue()));
|
|
||||||
case REQUEST_REMOVE_OBJECT -> rep
|
case REQUEST_REMOVE_OBJECT -> rep
|
||||||
.setReplyRemoveObject(handleRemoveObject(req.getRequestRemoveObject()));
|
.setReplyRemoveObject(handleRemoveObject(req.getRequestRemoveObject()));
|
||||||
case REQUEST_RETAIN_VALUES -> rep
|
case REQUEST_RETAIN_VALUES -> rep
|
||||||
|
@ -580,14 +568,10 @@ public class TraceRmiHandler implements TraceRmiConnection {
|
||||||
case REQUEST_SAVE_TRACE -> rep
|
case REQUEST_SAVE_TRACE -> rep
|
||||||
.setReplySaveTrace(handleSaveTrace(req.getRequestSaveTrace()));
|
.setReplySaveTrace(handleSaveTrace(req.getRequestSaveTrace()));
|
||||||
case REQUEST_SET_MEMORY_STATE -> rep
|
case REQUEST_SET_MEMORY_STATE -> rep
|
||||||
.setReplySetMemoryState(
|
.setReplySetMemoryState(handleSetMemoryState(req.getRequestSetMemoryState()));
|
||||||
handleSetMemoryState(req.getRequestSetMemoryState()));
|
case REQUEST_SET_VALUE -> rep.setReplySetValue(handleSetValue(req.getRequestSetValue()));
|
||||||
case REQUEST_SET_VALUE -> rep
|
case REQUEST_SNAPSHOT -> rep.setReplySnapshot(handleSnapshot(req.getRequestSnapshot()));
|
||||||
.setReplySetValue(handleSetValue(req.getRequestSetValue()));
|
case REQUEST_START_TX -> rep.setReplyStartTx(handleStartTx(req.getRequestStartTx()));
|
||||||
case REQUEST_SNAPSHOT -> rep
|
|
||||||
.setReplySnapshot(handleSnapshot(req.getRequestSnapshot()));
|
|
||||||
case REQUEST_START_TX -> rep
|
|
||||||
.setReplyStartTx(handleStartTx(req.getRequestStartTx()));
|
|
||||||
case XREPLY_INVOKE_METHOD -> handleXInvokeMethod(req.getXreplyInvokeMethod());
|
case XREPLY_INVOKE_METHOD -> handleXInvokeMethod(req.getXreplyInvokeMethod());
|
||||||
default -> throw new InvalidRequestError(req);
|
default -> throw new InvalidRequestError(req);
|
||||||
};
|
};
|
||||||
|
@ -666,15 +650,11 @@ public class TraceRmiHandler implements TraceRmiConnection {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static ObjSpec makeObjSpec(TraceObject object) {
|
protected static ObjSpec makeObjSpec(TraceObject object) {
|
||||||
return ObjSpec.newBuilder()
|
return ObjSpec.newBuilder().setId(object.getKey()).build();
|
||||||
.setId(object.getKey())
|
|
||||||
.build();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static ObjPath makeObjPath(TraceObjectKeyPath path) {
|
protected static ObjPath makeObjPath(TraceObjectKeyPath path) {
|
||||||
return ObjPath.newBuilder()
|
return ObjPath.newBuilder().setPath(path.toString()).build();
|
||||||
.setPath(path.toString())
|
|
||||||
.build();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static ObjDesc makeObjDesc(TraceObject object) {
|
protected static ObjDesc makeObjDesc(TraceObject object) {
|
||||||
|
@ -767,15 +747,13 @@ public class TraceRmiHandler implements TraceRmiConnection {
|
||||||
if (value instanceof int[] ia) {
|
if (value instanceof int[] ia) {
|
||||||
return Value.newBuilder()
|
return Value.newBuilder()
|
||||||
.setIntArrValue(
|
.setIntArrValue(
|
||||||
IntArr.newBuilder()
|
IntArr.newBuilder().addAllArr(IntStream.of(ia).mapToObj(i -> i).toList()))
|
||||||
.addAllArr(IntStream.of(ia).mapToObj(i -> i).toList()))
|
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
if (value instanceof long[] la) {
|
if (value instanceof long[] la) {
|
||||||
return Value.newBuilder()
|
return Value.newBuilder()
|
||||||
.setLongArrValue(
|
.setLongArrValue(
|
||||||
LongArr.newBuilder()
|
LongArr.newBuilder().addAllArr(LongStream.of(la).mapToObj(l -> l).toList()))
|
||||||
.addAllArr(LongStream.of(la).mapToObj(l -> l).toList()))
|
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
if (value instanceof String[] sa) {
|
if (value instanceof String[] sa) {
|
||||||
|
@ -847,8 +825,7 @@ public class TraceRmiHandler implements TraceRmiConnection {
|
||||||
|
|
||||||
protected ReplyCreateObject handleCreateObject(RequestCreateObject req) {
|
protected ReplyCreateObject handleCreateObject(RequestCreateObject req) {
|
||||||
OpenTrace open = requireOpenTrace(req.getOid());
|
OpenTrace open = requireOpenTrace(req.getOid());
|
||||||
TraceObject object =
|
TraceObject object = open.trace.getObjectManager().createObject(toKeyPath(req.getPath()));
|
||||||
open.trace.getObjectManager().createObject(toKeyPath(req.getPath()));
|
|
||||||
return ReplyCreateObject.newBuilder().setObject(makeObjSpec(object)).build();
|
return ReplyCreateObject.newBuilder().setObject(makeObjSpec(object)).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -904,8 +881,7 @@ public class TraceRmiHandler implements TraceRmiConnection {
|
||||||
return ReplyDeleteBytes.getDefaultInstance();
|
return ReplyDeleteBytes.getDefaultInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ReplyDeleteRegisterValue handleDeleteRegisterValue(
|
protected ReplyDeleteRegisterValue handleDeleteRegisterValue(RequestDeleteRegisterValue req) {
|
||||||
RequestDeleteRegisterValue req) {
|
|
||||||
OpenTrace open = requireOpenTrace(req.getOid());
|
OpenTrace open = requireOpenTrace(req.getOid());
|
||||||
long snap = req.getSnap().getSnap();
|
long snap = req.getSnap().getSnap();
|
||||||
AddressSpace space = open.trace.getBaseAddressFactory().getAddressSpace(req.getSpace());
|
AddressSpace space = open.trace.getBaseAddressFactory().getAddressSpace(req.getSpace());
|
||||||
|
@ -932,15 +908,13 @@ public class TraceRmiHandler implements TraceRmiConnection {
|
||||||
|
|
||||||
// Want addresses satisfying {@code known | (readOnly & everKnown)}
|
// Want addresses satisfying {@code known | (readOnly & everKnown)}
|
||||||
TraceMemoryManager memoryManager = open.trace.getMemoryManager();
|
TraceMemoryManager memoryManager = open.trace.getMemoryManager();
|
||||||
AddressSetView readOnly =
|
AddressSetView readOnly = memoryManager.getRegionsAddressSetWith(snap, r -> !r.isWrite());
|
||||||
memoryManager.getRegionsAddressSetWith(snap, r -> !r.isWrite());
|
|
||||||
AddressSetView everKnown = memoryManager.getAddressesWithState(Lifespan.since(snap),
|
AddressSetView everKnown = memoryManager.getAddressesWithState(Lifespan.since(snap),
|
||||||
s -> s == TraceMemoryState.KNOWN);
|
s -> s == TraceMemoryState.KNOWN);
|
||||||
AddressSetView roEverKnown = new IntersectionAddressSetView(readOnly, everKnown);
|
AddressSetView roEverKnown = new IntersectionAddressSetView(readOnly, everKnown);
|
||||||
AddressSetView known =
|
AddressSetView known =
|
||||||
memoryManager.getAddressesWithState(snap, s -> s == TraceMemoryState.KNOWN);
|
memoryManager.getAddressesWithState(snap, s -> s == TraceMemoryState.KNOWN);
|
||||||
AddressSetView disassemblable =
|
AddressSetView disassemblable = new AddressSet(new UnionAddressSetView(known, roEverKnown));
|
||||||
new AddressSet(new UnionAddressSetView(known, roEverKnown));
|
|
||||||
|
|
||||||
Address start = open.toAddress(req.getStart(), true);
|
Address start = open.toAddress(req.getStart(), true);
|
||||||
TracePlatform host = open.trace.getPlatformManager().getHostPlatform();
|
TracePlatform host = open.trace.getPlatformManager().getHostPlatform();
|
||||||
|
@ -950,7 +924,7 @@ public class TraceRmiHandler implements TraceRmiConnection {
|
||||||
host.getLanguage(), host.getLanguage().getLanguageID(), start));
|
host.getLanguage(), host.getLanguage().getLanguageID(), start));
|
||||||
|
|
||||||
try (CloseableTaskMonitor monitor = plugin.createMonitor()) {
|
try (CloseableTaskMonitor monitor = plugin.createMonitor()) {
|
||||||
dis.applyToTyped(open.trace.getFixedProgramView(snap), monitor);
|
dis.applyTo(open.trace.getFixedProgramView(snap), monitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ReplyDisassemble.newBuilder()
|
return ReplyDisassemble.newBuilder()
|
||||||
|
@ -988,21 +962,19 @@ public class TraceRmiHandler implements TraceRmiConnection {
|
||||||
OpenTrace open = requireOpenTrace(req.getOid());
|
OpenTrace open = requireOpenTrace(req.getOid());
|
||||||
return ReplyGetValues.newBuilder()
|
return ReplyGetValues.newBuilder()
|
||||||
.addAllValues(open.trace.getObjectManager()
|
.addAllValues(open.trace.getObjectManager()
|
||||||
.getValuePaths(toLifespan(req.getSpan()),
|
.getValuePaths(toLifespan(req.getSpan()), toPathPattern(req.getPattern()))
|
||||||
toPathPattern(req.getPattern()))
|
|
||||||
.map(TraceRmiHandler::makeValDesc)
|
.map(TraceRmiHandler::makeValDesc)
|
||||||
.sorted(Comparator.comparing(ValDesc::getKey))
|
.sorted(Comparator.comparing(ValDesc::getKey))
|
||||||
.toList())
|
.toList())
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ReplyGetValues handleGetValuesIntersecting(
|
protected ReplyGetValues handleGetValuesIntersecting(RequestGetValuesIntersecting req)
|
||||||
RequestGetValuesIntersecting req) throws AddressOverflowException {
|
throws AddressOverflowException {
|
||||||
OpenTrace open = requireOpenTrace(req.getOid());
|
OpenTrace open = requireOpenTrace(req.getOid());
|
||||||
AddressRange range = open.toRange(req.getBox().getRange(), false);
|
AddressRange range = open.toRange(req.getBox().getRange(), false);
|
||||||
String key = req.getKey() == "" ? null : req.getKey();
|
String key = req.getKey() == "" ? null : req.getKey();
|
||||||
Collection<? extends TraceObjectValue> col = range == null
|
Collection<? extends TraceObjectValue> col = range == null ? List.of()
|
||||||
? List.of()
|
|
||||||
: open.trace.getObjectManager()
|
: open.trace.getObjectManager()
|
||||||
.getValuesIntersecting(toLifespan(req.getBox().getSpan()), range, key);
|
.getValuesIntersecting(toLifespan(req.getBox().getSpan()), range, key);
|
||||||
return ReplyGetValues.newBuilder()
|
return ReplyGetValues.newBuilder()
|
||||||
|
@ -1018,9 +990,7 @@ public class TraceRmiHandler implements TraceRmiConnection {
|
||||||
.stream()
|
.stream()
|
||||||
.map(TraceObjectValue::getLifespan)
|
.map(TraceObjectValue::getLifespan)
|
||||||
.reduce(Lifespan.ALL, Lifespan::intersect);
|
.reduce(Lifespan.ALL, Lifespan::intersect);
|
||||||
return ReplyInsertObject.newBuilder()
|
return ReplyInsertObject.newBuilder().setSpan(makeSpan(span)).build();
|
||||||
.setSpan(makeSpan(span))
|
|
||||||
.build();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ReplyNegotiate handleNegotiate(RequestNegotiate req) {
|
protected ReplyNegotiate handleNegotiate(RequestNegotiate req) {
|
||||||
|
@ -1031,8 +1001,8 @@ public class TraceRmiHandler implements TraceRmiConnection {
|
||||||
}
|
}
|
||||||
for (Method m : req.getMethodsList()) {
|
for (Method m : req.getMethodsList()) {
|
||||||
RemoteMethod rm = new RecordRemoteMethod(this, m.getName(),
|
RemoteMethod rm = new RecordRemoteMethod(this, m.getName(),
|
||||||
ActionName.name(m.getAction()), m.getDisplay(),
|
ActionName.name(m.getAction()), m.getDisplay(), m.getDescription(),
|
||||||
m.getDescription(), m.getParametersList()
|
m.getParametersList()
|
||||||
.stream()
|
.stream()
|
||||||
.collect(Collectors.toMap(MethodParameter::getName, this::makeParameter)),
|
.collect(Collectors.toMap(MethodParameter::getName, this::makeParameter)),
|
||||||
new SchemaName(m.getReturnType().getName()));
|
new SchemaName(m.getReturnType().getName()));
|
||||||
|
@ -1141,8 +1111,7 @@ public class TraceRmiHandler implements TraceRmiConnection {
|
||||||
return ReplySetMemoryState.getDefaultInstance();
|
return ReplySetMemoryState.getDefaultInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ReplySetValue handleSetValue(RequestSetValue req)
|
protected ReplySetValue handleSetValue(RequestSetValue req) throws AddressOverflowException {
|
||||||
throws AddressOverflowException {
|
|
||||||
ValSpec value = req.getValue();
|
ValSpec value = req.getValue();
|
||||||
OpenTrace open = requireOpenTrace(req.getOid());
|
OpenTrace open = requireOpenTrace(req.getOid());
|
||||||
Object objVal = open.toValue(value.getValue());
|
Object objVal = open.toValue(value.getValue());
|
||||||
|
@ -1152,8 +1121,8 @@ public class TraceRmiHandler implements TraceRmiConnection {
|
||||||
return ReplySetValue.newBuilder().setSpan(makeSpan(Lifespan.EMPTY)).build();
|
return ReplySetValue.newBuilder().setSpan(makeSpan(Lifespan.EMPTY)).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
TraceObjectValue val = object.setValue(toLifespan(value.getSpan()), value.getKey(),
|
TraceObjectValue val = object.setValue(toLifespan(value.getSpan()), value.getKey(), objVal,
|
||||||
objVal, toResolution(req.getResolution()));
|
toResolution(req.getResolution()));
|
||||||
return ReplySetValue.newBuilder()
|
return ReplySetValue.newBuilder()
|
||||||
.setSpan(makeSpan(val == null ? Lifespan.EMPTY : val.getLifespan()))
|
.setSpan(makeSpan(val == null ? Lifespan.EMPTY : val.getLifespan()))
|
||||||
.build();
|
.build();
|
||||||
|
|
|
@ -22,7 +22,7 @@ import ghidra.app.services.DebuggerTraceManagerService;
|
||||||
import ghidra.debug.api.platform.DebuggerPlatformMapper;
|
import ghidra.debug.api.platform.DebuggerPlatformMapper;
|
||||||
import ghidra.debug.api.platform.DisassemblyResult;
|
import ghidra.debug.api.platform.DisassemblyResult;
|
||||||
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
||||||
import ghidra.framework.cmd.TypedBackgroundCommand;
|
import ghidra.framework.cmd.BackgroundCommand;
|
||||||
import ghidra.framework.plugintool.PluginTool;
|
import ghidra.framework.plugintool.PluginTool;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.address.AddressSetView;
|
import ghidra.program.model.address.AddressSetView;
|
||||||
|
@ -33,7 +33,7 @@ import ghidra.trace.model.thread.TraceThread;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
|
||||||
public final class CurrentPlatformTraceDisassembleCommand
|
public final class CurrentPlatformTraceDisassembleCommand
|
||||||
extends TypedBackgroundCommand<TraceProgramView> {
|
extends BackgroundCommand<TraceProgramView> {
|
||||||
public static final String NAME = "Disassemble";
|
public static final String NAME = "Disassemble";
|
||||||
|
|
||||||
public record Reqs(DebuggerPlatformMapper mapper, TraceThread thread, TraceObject object,
|
public record Reqs(DebuggerPlatformMapper mapper, TraceThread thread, TraceObject object,
|
||||||
|
@ -48,8 +48,7 @@ public final class CurrentPlatformTraceDisassembleCommand
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
Trace trace = view.getTrace();
|
Trace trace = view.getTrace();
|
||||||
DebuggerCoordinates current = traceManager == null
|
DebuggerCoordinates current = traceManager == null ? DebuggerCoordinates.NOWHERE
|
||||||
? DebuggerCoordinates.NOWHERE
|
|
||||||
: traceManager.getCurrentFor(trace);
|
: traceManager.getCurrentFor(trace);
|
||||||
TraceThread thread = current.getThread();
|
TraceThread thread = current.getThread();
|
||||||
TraceObject object = current.getObject();
|
TraceObject object = current.getObject();
|
||||||
|
@ -74,8 +73,8 @@ public final class CurrentPlatformTraceDisassembleCommand
|
||||||
private final Reqs reqs;
|
private final Reqs reqs;
|
||||||
private final Address address;
|
private final Address address;
|
||||||
|
|
||||||
public CurrentPlatformTraceDisassembleCommand(PluginTool tool, AddressSetView set,
|
public CurrentPlatformTraceDisassembleCommand(PluginTool tool, AddressSetView set, Reqs reqs,
|
||||||
Reqs reqs, Address address) {
|
Address address) {
|
||||||
super(NAME, true, true, false);
|
super(NAME, true, true, false);
|
||||||
this.tool = tool;
|
this.tool = tool;
|
||||||
this.set = set;
|
this.set = set;
|
||||||
|
@ -84,9 +83,9 @@ public final class CurrentPlatformTraceDisassembleCommand
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applyToTyped(TraceProgramView view, TaskMonitor monitor) {
|
public boolean applyTo(TraceProgramView view, TaskMonitor monitor) {
|
||||||
DisassemblyResult result = reqs.mapper.disassemble(
|
DisassemblyResult result = reqs.mapper.disassemble(reqs.thread, reqs.object, address, set,
|
||||||
reqs.thread, reqs.object, address, set, view.getSnap(), monitor);
|
view.getSnap(), monitor);
|
||||||
if (!result.isSuccess()) {
|
if (!result.isSuccess()) {
|
||||||
tool.setStatusInfo(result.getErrorMessage(), true);
|
tool.setStatusInfo(result.getErrorMessage(), true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.plugin.core.debug.disassemble;
|
package ghidra.app.plugin.core.debug.disassemble;
|
||||||
|
|
||||||
import ghidra.framework.cmd.TypedBackgroundCommand;
|
import ghidra.framework.cmd.BackgroundCommand;
|
||||||
import ghidra.program.disassemble.Disassembler;
|
import ghidra.program.disassemble.Disassembler;
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.lang.*;
|
import ghidra.program.model.lang.*;
|
||||||
|
@ -27,7 +27,7 @@ import ghidra.trace.model.program.TraceProgramView;
|
||||||
import ghidra.util.MathUtilities;
|
import ghidra.util.MathUtilities;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
|
||||||
public class TraceDisassembleCommand extends TypedBackgroundCommand<TraceProgramView> {
|
public class TraceDisassembleCommand extends BackgroundCommand<TraceProgramView> {
|
||||||
|
|
||||||
protected final TracePlatform platform;
|
protected final TracePlatform platform;
|
||||||
protected final Address start;
|
protected final Address start;
|
||||||
|
@ -76,7 +76,7 @@ public class TraceDisassembleCommand extends TypedBackgroundCommand<TraceProgram
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applyToTyped(TraceProgramView view, TaskMonitor monitor) {
|
public boolean applyTo(TraceProgramView view, TaskMonitor monitor) {
|
||||||
Disassembler disassembler = getDisassembler(view, monitor);
|
Disassembler disassembler = getDisassembler(view, monitor);
|
||||||
MemBuffer buffer = getBuffer(view);
|
MemBuffer buffer = getBuffer(view);
|
||||||
if (buffer == null) {
|
if (buffer == null) {
|
||||||
|
|
|
@ -73,8 +73,8 @@ public abstract class AbstractDebuggerPlatformMapper implements DebuggerPlatform
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DisassemblyResult disassemble(TraceThread thread, TraceObject object,
|
public DisassemblyResult disassemble(TraceThread thread, TraceObject object, Address start,
|
||||||
Address start, AddressSetView restricted, long snap, TaskMonitor monitor) {
|
AddressSetView restricted, long snap, TaskMonitor monitor) {
|
||||||
if (isCancelSilently(start, snap)) {
|
if (isCancelSilently(start, snap)) {
|
||||||
return DisassemblyResult.CANCELLED;
|
return DisassemblyResult.CANCELLED;
|
||||||
}
|
}
|
||||||
|
@ -86,7 +86,7 @@ public abstract class AbstractDebuggerPlatformMapper implements DebuggerPlatform
|
||||||
for (DisassemblyInject i : injects) {
|
for (DisassemblyInject i : injects) {
|
||||||
i.pre(tool, dis, platform, snap, thread, startSet, restricted);
|
i.pre(tool, dis, platform, snap, thread, startSet, restricted);
|
||||||
}
|
}
|
||||||
boolean result = dis.applyToTyped(trace.getFixedProgramView(snap), monitor);
|
boolean result = dis.applyTo(trace.getFixedProgramView(snap), monitor);
|
||||||
if (!result) {
|
if (!result) {
|
||||||
return DisassemblyResult.failed(dis.getStatusMsg());
|
return DisassemblyResult.failed(dis.getStatusMsg());
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,8 +24,8 @@ import org.apache.commons.lang3.concurrent.BasicThreadFactory;
|
||||||
import ghidra.app.plugin.core.debug.utils.DefaultTransactionCoalescer;
|
import ghidra.app.plugin.core.debug.utils.DefaultTransactionCoalescer;
|
||||||
import ghidra.app.plugin.core.debug.utils.TransactionCoalescer;
|
import ghidra.app.plugin.core.debug.utils.TransactionCoalescer;
|
||||||
import ghidra.app.plugin.core.debug.utils.TransactionCoalescer.CoalescedTx;
|
import ghidra.app.plugin.core.debug.utils.TransactionCoalescer.CoalescedTx;
|
||||||
|
import ghidra.framework.model.DomainObject;
|
||||||
import ghidra.framework.model.DomainObjectException;
|
import ghidra.framework.model.DomainObjectException;
|
||||||
import ghidra.framework.model.UndoableDomainObject;
|
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
import ghidra.util.exception.ClosedException;
|
import ghidra.util.exception.ClosedException;
|
||||||
|
|
||||||
|
@ -33,16 +33,16 @@ public class PermanentTransactionExecutor {
|
||||||
|
|
||||||
private final TransactionCoalescer txc;
|
private final TransactionCoalescer txc;
|
||||||
private final ExecutorService[] threads;
|
private final ExecutorService[] threads;
|
||||||
private final UndoableDomainObject obj;
|
private final DomainObject obj;
|
||||||
|
|
||||||
public PermanentTransactionExecutor(UndoableDomainObject obj, String name, int threadCount,
|
public PermanentTransactionExecutor(DomainObject obj, String name, int threadCount,
|
||||||
int delayMs) {
|
int delayMs) {
|
||||||
this.obj = obj;
|
this.obj = obj;
|
||||||
txc = new DefaultTransactionCoalescer<>(obj, RecorderPermanentTransaction::start, delayMs);
|
txc = new DefaultTransactionCoalescer<>(obj, RecorderPermanentTransaction::start, delayMs);
|
||||||
this.threads = new ExecutorService[threadCount];
|
this.threads = new ExecutorService[threadCount];
|
||||||
for (int i = 0; i < threadCount; i++) {
|
for (int i = 0; i < threadCount; i++) {
|
||||||
ThreadFactory factory = new BasicThreadFactory.Builder()
|
ThreadFactory factory =
|
||||||
.namingPattern(name + "thread-" + i + "-%d")
|
new BasicThreadFactory.Builder().namingPattern(name + "thread-" + i + "-%d")
|
||||||
.build();
|
.build();
|
||||||
threads[i] = Executors.newSingleThreadExecutor(factory);
|
threads[i] = Executors.newSingleThreadExecutor(factory);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,19 +16,19 @@
|
||||||
package ghidra.app.plugin.core.debug.service.model;
|
package ghidra.app.plugin.core.debug.service.model;
|
||||||
|
|
||||||
import db.Transaction;
|
import db.Transaction;
|
||||||
import ghidra.framework.model.UndoableDomainObject;
|
import ghidra.framework.model.DomainObject;
|
||||||
|
|
||||||
public class RecorderPermanentTransaction implements AutoCloseable {
|
public class RecorderPermanentTransaction implements AutoCloseable {
|
||||||
|
|
||||||
public static RecorderPermanentTransaction start(UndoableDomainObject obj, String description) {
|
public static RecorderPermanentTransaction start(DomainObject obj, String description) {
|
||||||
Transaction tx = obj.openTransaction(description);
|
Transaction tx = obj.openTransaction(description);
|
||||||
return new RecorderPermanentTransaction(obj, tx);
|
return new RecorderPermanentTransaction(obj, tx);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final UndoableDomainObject obj;
|
private final DomainObject obj;
|
||||||
private final Transaction tx;
|
private final Transaction tx;
|
||||||
|
|
||||||
public RecorderPermanentTransaction(UndoableDomainObject obj, Transaction tx) {
|
public RecorderPermanentTransaction(DomainObject obj, Transaction tx) {
|
||||||
this.obj = obj;
|
this.obj = obj;
|
||||||
this.tx = tx;
|
this.tx = tx;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,11 +20,11 @@ import java.util.Collection;
|
||||||
import ghidra.app.services.DebuggerStaticMappingService;
|
import ghidra.app.services.DebuggerStaticMappingService;
|
||||||
import ghidra.debug.api.modules.ModuleMapProposal.ModuleMapEntry;
|
import ghidra.debug.api.modules.ModuleMapProposal.ModuleMapEntry;
|
||||||
import ghidra.framework.cmd.BackgroundCommand;
|
import ghidra.framework.cmd.BackgroundCommand;
|
||||||
import ghidra.framework.model.DomainObject;
|
import ghidra.trace.model.Trace;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
|
||||||
public class MapModulesBackgroundCommand extends BackgroundCommand {
|
public class MapModulesBackgroundCommand extends BackgroundCommand<Trace> {
|
||||||
private final DebuggerStaticMappingService service;
|
private final DebuggerStaticMappingService service;
|
||||||
private final Collection<ModuleMapEntry> entries;
|
private final Collection<ModuleMapEntry> entries;
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ public class MapModulesBackgroundCommand extends BackgroundCommand {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applyTo(DomainObject obj, TaskMonitor monitor) {
|
public boolean applyTo(Trace trace, TaskMonitor monitor) {
|
||||||
try {
|
try {
|
||||||
service.addModuleMappings(entries, monitor, true);
|
service.addModuleMappings(entries, monitor, true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,11 +20,11 @@ import java.util.Collection;
|
||||||
import ghidra.app.services.DebuggerStaticMappingService;
|
import ghidra.app.services.DebuggerStaticMappingService;
|
||||||
import ghidra.debug.api.modules.RegionMapProposal.RegionMapEntry;
|
import ghidra.debug.api.modules.RegionMapProposal.RegionMapEntry;
|
||||||
import ghidra.framework.cmd.BackgroundCommand;
|
import ghidra.framework.cmd.BackgroundCommand;
|
||||||
import ghidra.framework.model.DomainObject;
|
import ghidra.trace.model.Trace;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
|
||||||
public class MapRegionsBackgroundCommand extends BackgroundCommand {
|
public class MapRegionsBackgroundCommand extends BackgroundCommand<Trace> {
|
||||||
private final DebuggerStaticMappingService service;
|
private final DebuggerStaticMappingService service;
|
||||||
private final Collection<RegionMapEntry> entries;
|
private final Collection<RegionMapEntry> entries;
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ public class MapRegionsBackgroundCommand extends BackgroundCommand {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applyTo(DomainObject obj, TaskMonitor monitor) {
|
public boolean applyTo(Trace trace, TaskMonitor monitor) {
|
||||||
try {
|
try {
|
||||||
service.addRegionMappings(entries, monitor, true);
|
service.addRegionMappings(entries, monitor, true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,11 +20,11 @@ import java.util.Collection;
|
||||||
import ghidra.app.services.DebuggerStaticMappingService;
|
import ghidra.app.services.DebuggerStaticMappingService;
|
||||||
import ghidra.debug.api.modules.SectionMapProposal.SectionMapEntry;
|
import ghidra.debug.api.modules.SectionMapProposal.SectionMapEntry;
|
||||||
import ghidra.framework.cmd.BackgroundCommand;
|
import ghidra.framework.cmd.BackgroundCommand;
|
||||||
import ghidra.framework.model.DomainObject;
|
import ghidra.trace.model.Trace;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
|
||||||
public class MapSectionsBackgroundCommand extends BackgroundCommand {
|
public class MapSectionsBackgroundCommand extends BackgroundCommand<Trace> {
|
||||||
private final DebuggerStaticMappingService service;
|
private final DebuggerStaticMappingService service;
|
||||||
private final Collection<SectionMapEntry> entries;
|
private final Collection<SectionMapEntry> entries;
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ public class MapSectionsBackgroundCommand extends BackgroundCommand {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applyTo(DomainObject obj, TaskMonitor monitor) {
|
public boolean applyTo(Trace trace, TaskMonitor monitor) {
|
||||||
try {
|
try {
|
||||||
service.addSectionMappings(entries, monitor, true);
|
service.addSectionMappings(entries, monitor, true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
package ghidra.app.plugin.core.debug.stack;
|
package ghidra.app.plugin.core.debug.stack;
|
||||||
|
|
||||||
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
||||||
import ghidra.framework.cmd.TypedBackgroundCommand;
|
import ghidra.framework.cmd.BackgroundCommand;
|
||||||
import ghidra.framework.plugintool.PluginTool;
|
import ghidra.framework.plugintool.PluginTool;
|
||||||
import ghidra.pcode.exec.DebuggerPcodeUtils.WatchValue;
|
import ghidra.pcode.exec.DebuggerPcodeUtils.WatchValue;
|
||||||
import ghidra.trace.model.Trace;
|
import ghidra.trace.model.Trace;
|
||||||
|
@ -27,7 +27,7 @@ import ghidra.util.task.TaskMonitor;
|
||||||
* A command to unwind as much of the stack as possible and annotate the resulting frame in the
|
* A command to unwind as much of the stack as possible and annotate the resulting frame in the
|
||||||
* dynamic listing
|
* dynamic listing
|
||||||
*/
|
*/
|
||||||
public class UnwindStackCommand extends TypedBackgroundCommand<Trace> {
|
public class UnwindStackCommand extends BackgroundCommand<Trace> {
|
||||||
|
|
||||||
private final PluginTool tool;
|
private final PluginTool tool;
|
||||||
private final DebuggerCoordinates where;
|
private final DebuggerCoordinates where;
|
||||||
|
@ -39,7 +39,7 @@ public class UnwindStackCommand extends TypedBackgroundCommand<Trace> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applyToTyped(Trace obj, TaskMonitor monitor) {
|
public boolean applyTo(Trace obj, TaskMonitor monitor) {
|
||||||
try {
|
try {
|
||||||
StackUnwinder unwinder = new StackUnwinder(tool, where.getPlatform());
|
StackUnwinder unwinder = new StackUnwinder(tool, where.getPlatform());
|
||||||
int prevParamSize = 0;
|
int prevParamSize = 0;
|
||||||
|
|
|
@ -25,7 +25,6 @@ import org.apache.commons.lang3.exception.ExceptionUtils;
|
||||||
import ghidra.async.AsyncUtils;
|
import ghidra.async.AsyncUtils;
|
||||||
import ghidra.framework.cmd.BackgroundCommand;
|
import ghidra.framework.cmd.BackgroundCommand;
|
||||||
import ghidra.framework.model.DomainObject;
|
import ghidra.framework.model.DomainObject;
|
||||||
import ghidra.framework.model.UndoableDomainObject;
|
|
||||||
import ghidra.framework.plugintool.PluginTool;
|
import ghidra.framework.plugintool.PluginTool;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
import ghidra.util.Swing;
|
import ghidra.util.Swing;
|
||||||
|
@ -35,8 +34,8 @@ import ghidra.util.task.*;
|
||||||
public enum BackgroundUtils {
|
public enum BackgroundUtils {
|
||||||
;
|
;
|
||||||
|
|
||||||
public static class AsyncBackgroundCommand<T extends UndoableDomainObject>
|
public static class AsyncBackgroundCommand<T extends DomainObject>
|
||||||
extends BackgroundCommand {
|
extends BackgroundCommand<T> {
|
||||||
private CompletableFuture<?> promise;
|
private CompletableFuture<?> promise;
|
||||||
|
|
||||||
private final CancelledListener cancelledListener = this::cancelled;
|
private final CancelledListener cancelledListener = this::cancelled;
|
||||||
|
@ -53,9 +52,8 @@ public enum BackgroundUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("unchecked")
|
public boolean applyTo(T obj, TaskMonitor monitor) {
|
||||||
public boolean applyTo(DomainObject obj, TaskMonitor monitor) {
|
promise = futureProducer.apply(obj, monitor);
|
||||||
promise = futureProducer.apply((T) obj, monitor);
|
|
||||||
monitor.addCancelledListener(cancelledListener);
|
monitor.addCancelledListener(cancelledListener);
|
||||||
try {
|
try {
|
||||||
promise.get();
|
promise.get();
|
||||||
|
@ -103,8 +101,8 @@ public enum BackgroundUtils {
|
||||||
* @param futureProducer a function to start the task
|
* @param futureProducer a function to start the task
|
||||||
* @return a future which completes when the task is finished.
|
* @return a future which completes when the task is finished.
|
||||||
*/
|
*/
|
||||||
public static <T extends UndoableDomainObject> AsyncBackgroundCommand<T> async(PluginTool tool,
|
public static <T extends DomainObject> AsyncBackgroundCommand<T> async(PluginTool tool, T obj,
|
||||||
T obj, String name, boolean hasProgress, boolean canCancel, boolean isModal,
|
String name, boolean hasProgress, boolean canCancel, boolean isModal,
|
||||||
BiFunction<T, TaskMonitor, CompletableFuture<?>> futureProducer) {
|
BiFunction<T, TaskMonitor, CompletableFuture<?>> futureProducer) {
|
||||||
AsyncBackgroundCommand<T> cmd =
|
AsyncBackgroundCommand<T> cmd =
|
||||||
new AsyncBackgroundCommand<>(name, hasProgress, canCancel, isModal, futureProducer);
|
new AsyncBackgroundCommand<>(name, hasProgress, canCancel, isModal, futureProducer);
|
||||||
|
@ -119,7 +117,7 @@ public enum BackgroundUtils {
|
||||||
* The returned future includes error handling, so even if the task completes in error, the
|
* The returned future includes error handling, so even if the task completes in error, the
|
||||||
* returned future will just complete with null. If further error handling is required, then the
|
* returned future will just complete with null. If further error handling is required, then the
|
||||||
* {@code futureProducer} should make the future available. This differs from
|
* {@code futureProducer} should make the future available. This differs from
|
||||||
* {@link #async(PluginTool, UndoableDomainObject, String, boolean, boolean, boolean, BiFunction)}
|
* {@link #async(PluginTool, DomainObject, String, boolean, boolean, boolean, BiFunction)}
|
||||||
* in that it doesn't use the tool's task manager, so it can run in parallel with other tasks.
|
* in that it doesn't use the tool's task manager, so it can run in parallel with other tasks.
|
||||||
* There is not currently a supported method to run multiple non-modal tasks concurrently, since
|
* There is not currently a supported method to run multiple non-modal tasks concurrently, since
|
||||||
* they would have to share a single task monitor component.
|
* they would have to share a single task monitor component.
|
||||||
|
@ -172,14 +170,14 @@ public enum BackgroundUtils {
|
||||||
|
|
||||||
private final PluginTool tool;
|
private final PluginTool tool;
|
||||||
private final String name;
|
private final String name;
|
||||||
private final UndoableDomainObject obj;
|
private final DomainObject obj;
|
||||||
private final int delay;
|
private final int delay;
|
||||||
private final EnumSet<TaskOpt> opts;
|
private final EnumSet<TaskOpt> opts;
|
||||||
|
|
||||||
private TaskMonitor lastMonitor;
|
private TaskMonitor lastMonitor;
|
||||||
|
|
||||||
public PluginToolExecutorService(PluginTool tool, String name, UndoableDomainObject obj,
|
public PluginToolExecutorService(PluginTool tool, String name, DomainObject obj, int delay,
|
||||||
int delay, TaskOpt... opts) {
|
TaskOpt... opts) {
|
||||||
this.tool = tool;
|
this.tool = tool;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.obj = obj;
|
this.obj = obj;
|
||||||
|
@ -223,10 +221,8 @@ public enum BackgroundUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void executeForeground(Runnable command) {
|
protected void executeForeground(Runnable command) {
|
||||||
Task task = new Task(name,
|
Task task = new Task(name, opts.contains(TaskOpt.CAN_CANCEL),
|
||||||
opts.contains(TaskOpt.CAN_CANCEL),
|
opts.contains(TaskOpt.HAS_PROGRESS), opts.contains(TaskOpt.IS_MODAL)) {
|
||||||
opts.contains(TaskOpt.HAS_PROGRESS),
|
|
||||||
opts.contains(TaskOpt.IS_MODAL)) {
|
|
||||||
@Override
|
@Override
|
||||||
public void run(TaskMonitor monitor) throws CancelledException {
|
public void run(TaskMonitor monitor) throws CancelledException {
|
||||||
lastMonitor = monitor;
|
lastMonitor = monitor;
|
||||||
|
@ -237,10 +233,8 @@ public enum BackgroundUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void executeBackground(Runnable command) {
|
protected void executeBackground(Runnable command) {
|
||||||
BackgroundCommand cmd = new BackgroundCommand(name,
|
BackgroundCommand cmd = new BackgroundCommand(name, opts.contains(TaskOpt.HAS_PROGRESS),
|
||||||
opts.contains(TaskOpt.HAS_PROGRESS),
|
opts.contains(TaskOpt.CAN_CANCEL), opts.contains(TaskOpt.IS_MODAL)) {
|
||||||
opts.contains(TaskOpt.CAN_CANCEL),
|
|
||||||
opts.contains(TaskOpt.IS_MODAL)) {
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applyTo(DomainObject obj, TaskMonitor monitor) {
|
public boolean applyTo(DomainObject obj, TaskMonitor monitor) {
|
||||||
lastMonitor = monitor;
|
lastMonitor = monitor;
|
||||||
|
|
|
@ -17,10 +17,10 @@ package ghidra.app.plugin.core.debug.utils;
|
||||||
|
|
||||||
import ghidra.async.AsyncDebouncer;
|
import ghidra.async.AsyncDebouncer;
|
||||||
import ghidra.async.AsyncTimer;
|
import ghidra.async.AsyncTimer;
|
||||||
import ghidra.framework.model.UndoableDomainObject;
|
import ghidra.framework.model.DomainObject;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
|
|
||||||
public class DefaultTransactionCoalescer<T extends UndoableDomainObject, U extends AutoCloseable>
|
public class DefaultTransactionCoalescer<T extends DomainObject, U extends AutoCloseable>
|
||||||
implements TransactionCoalescer {
|
implements TransactionCoalescer {
|
||||||
|
|
||||||
protected class Coalescer {
|
protected class Coalescer {
|
||||||
|
|
|
@ -17,11 +17,10 @@ package ghidra.app.plugin.core.debug.utils;
|
||||||
|
|
||||||
import java.util.function.BiFunction;
|
import java.util.function.BiFunction;
|
||||||
|
|
||||||
import ghidra.framework.model.UndoableDomainObject;
|
import ghidra.framework.model.DomainObject;
|
||||||
|
|
||||||
public interface TransactionCoalescer {
|
public interface TransactionCoalescer {
|
||||||
public interface TxFactory<T extends UndoableDomainObject, U>
|
public interface TxFactory<T extends DomainObject, U> extends BiFunction<T, String, U> {
|
||||||
extends BiFunction<T, String, U> {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface CoalescedTx extends AutoCloseable {
|
public interface CoalescedTx extends AutoCloseable {
|
||||||
|
|
|
@ -197,9 +197,8 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest {
|
||||||
|
|
||||||
DBTraceMemoryManager memory = tb.trace.getMemoryManager();
|
DBTraceMemoryManager memory = tb.trace.getMemoryManager();
|
||||||
if (pcInStack) {
|
if (pcInStack) {
|
||||||
DBTraceObject objFrame =
|
DBTraceObject objFrame = objects
|
||||||
objects.createObject(
|
.createObject(TraceObjectKeyPath.parse("Targets[0].Threads[0].Stack[0]"));
|
||||||
TraceObjectKeyPath.parse("Targets[0].Threads[0].Stack[0]"));
|
|
||||||
objFrame.insert(zeroOn, ConflictResolution.DENY);
|
objFrame.insert(zeroOn, ConflictResolution.DENY);
|
||||||
TraceObjectStackFrame frame = objFrame.queryInterface(TraceObjectStackFrame.class);
|
TraceObjectStackFrame frame = objFrame.queryInterface(TraceObjectStackFrame.class);
|
||||||
frame.setProgramCounter(zeroOn, tb.addr(offset));
|
frame.setProgramCounter(zeroOn, tb.addr(offset));
|
||||||
|
@ -208,8 +207,8 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest {
|
||||||
objects.createObject(
|
objects.createObject(
|
||||||
TraceObjectKeyPath.parse("Targets[0].Threads[0].Stack[0].Registers"))
|
TraceObjectKeyPath.parse("Targets[0].Threads[0].Stack[0].Registers"))
|
||||||
.insert(zeroOn, ConflictResolution.DENY);
|
.insert(zeroOn, ConflictResolution.DENY);
|
||||||
TraceObjectThread thread = objects.getObjectByCanonicalPath(
|
TraceObjectThread thread = objects
|
||||||
TraceObjectKeyPath.parse("Targets[0].Threads[0]"))
|
.getObjectByCanonicalPath(TraceObjectKeyPath.parse("Targets[0].Threads[0]"))
|
||||||
.queryInterface(TraceObjectThread.class);
|
.queryInterface(TraceObjectThread.class);
|
||||||
traceManager.activateThread(thread);
|
traceManager.activateThread(thread);
|
||||||
DBTraceMemorySpace regs =
|
DBTraceMemorySpace regs =
|
||||||
|
@ -248,8 +247,8 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void createLegacyTrace(String langID, long offset,
|
protected void createLegacyTrace(String langID, long offset, Supplier<ByteBuffer> byteSupplier)
|
||||||
Supplier<ByteBuffer> byteSupplier) throws Throwable {
|
throws Throwable {
|
||||||
createAndOpenTrace(langID);
|
createAndOpenTrace(langID);
|
||||||
|
|
||||||
try (Transaction tx = tb.startTransaction()) {
|
try (Transaction tx = tb.startTransaction()) {
|
||||||
|
@ -358,8 +357,8 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest {
|
||||||
try (Transaction tx = program.openTransaction("Load")) {
|
try (Transaction tx = program.openTransaction("Load")) {
|
||||||
start = program.getAddressFactory().getDefaultAddressSpace().getAddress(0x00400000);
|
start = program.getAddressFactory().getDefaultAddressSpace().getAddress(0x00400000);
|
||||||
program.getMemory()
|
program.getMemory()
|
||||||
.createInitializedBlock(".text", start,
|
.createInitializedBlock(".text", start, new ByteArrayInputStream(arr("ebffc0")),
|
||||||
new ByteArrayInputStream(arr("ebffc0")), 3, monitor, false);
|
3, monitor, false);
|
||||||
}
|
}
|
||||||
intoProject(program);
|
intoProject(program);
|
||||||
|
|
||||||
|
@ -654,7 +653,7 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest {
|
||||||
new AddressSet(start, start.addWrap(1)));
|
new AddressSet(start, start.addWrap(1)));
|
||||||
dis.setInitialContext(DebuggerDisassemblerPlugin.deriveAlternativeDefaultContext(
|
dis.setInitialContext(DebuggerDisassemblerPlugin.deriveAlternativeDefaultContext(
|
||||||
tb.language, new LanguageID("ARM:LE:32:v8T"), start));
|
tb.language, new LanguageID("ARM:LE:32:v8T"), start));
|
||||||
dis.applyToTyped(tb.trace.getProgramView(), TaskMonitor.DUMMY);
|
dis.applyTo(tb.trace.getProgramView(), TaskMonitor.DUMMY);
|
||||||
}
|
}
|
||||||
waitForDomainObject(tb.trace);
|
waitForDomainObject(tb.trace);
|
||||||
|
|
||||||
|
@ -715,11 +714,11 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest {
|
||||||
TraceGuestPlatform guest =
|
TraceGuestPlatform guest =
|
||||||
Unique.assertOne(tb.trace.getPlatformManager().getGuestPlatforms());
|
Unique.assertOne(tb.trace.getPlatformManager().getGuestPlatforms());
|
||||||
try (Transaction tx = tb.startTransaction()) {
|
try (Transaction tx = tb.startTransaction()) {
|
||||||
TraceDisassembleCommand dis = new TraceDisassembleCommand(guest, start,
|
TraceDisassembleCommand dis =
|
||||||
new AddressSet(start, start.addWrap(1)));
|
new TraceDisassembleCommand(guest, start, new AddressSet(start, start.addWrap(1)));
|
||||||
dis.setInitialContext(DebuggerDisassemblerPlugin.deriveAlternativeDefaultContext(
|
dis.setInitialContext(DebuggerDisassemblerPlugin.deriveAlternativeDefaultContext(
|
||||||
guest.getLanguage(), new LanguageID("ARM:LE:32:v8T"), start));
|
guest.getLanguage(), new LanguageID("ARM:LE:32:v8T"), start));
|
||||||
dis.applyToTyped(tb.trace.getProgramView(), TaskMonitor.DUMMY);
|
dis.applyTo(tb.trace.getProgramView(), TaskMonitor.DUMMY);
|
||||||
}
|
}
|
||||||
waitForDomainObject(tb.trace);
|
waitForDomainObject(tb.trace);
|
||||||
|
|
||||||
|
|
|
@ -190,8 +190,7 @@ public class StackUnwinderTest extends AbstractGhidraHeadedDebuggerTest {
|
||||||
|
|
||||||
function.updateFunction("__cdecl",
|
function.updateFunction("__cdecl",
|
||||||
new ReturnParameterImpl(IntegerDataType.dataType, program),
|
new ReturnParameterImpl(IntegerDataType.dataType, program),
|
||||||
List.of(
|
List.of(new ParameterImpl("n", IntegerDataType.dataType, program)),
|
||||||
new ParameterImpl("n", IntegerDataType.dataType, program)),
|
|
||||||
FunctionUpdateType.DYNAMIC_STORAGE_FORMAL_PARAMS, true, SourceType.ANALYSIS);
|
FunctionUpdateType.DYNAMIC_STORAGE_FORMAL_PARAMS, true, SourceType.ANALYSIS);
|
||||||
function.addLocalVariable(
|
function.addLocalVariable(
|
||||||
new LocalVariableImpl("i", IntegerDataType.dataType, -8, program),
|
new LocalVariableImpl("i", IntegerDataType.dataType, -8, program),
|
||||||
|
@ -263,14 +262,12 @@ public class StackUnwinderTest extends AbstractGhidraHeadedDebuggerTest {
|
||||||
|
|
||||||
function.updateFunction("__cdecl",
|
function.updateFunction("__cdecl",
|
||||||
new ReturnParameterImpl(UnsignedIntegerDataType.dataType, program),
|
new ReturnParameterImpl(UnsignedIntegerDataType.dataType, program),
|
||||||
List.of(
|
List.of(new ParameterImpl("n", UnsignedIntegerDataType.dataType, program)),
|
||||||
new ParameterImpl("n", UnsignedIntegerDataType.dataType, program)),
|
|
||||||
FunctionUpdateType.DYNAMIC_STORAGE_FORMAL_PARAMS, true, SourceType.ANALYSIS);
|
FunctionUpdateType.DYNAMIC_STORAGE_FORMAL_PARAMS, true, SourceType.ANALYSIS);
|
||||||
// NOTE: The decompiler doesn't actually use sum.... For some reason, it re-uses n
|
// NOTE: The decompiler doesn't actually use sum.... For some reason, it re-uses n
|
||||||
// Still, in the tests, I can use uVar1 (EAX) as a register variable
|
// Still, in the tests, I can use uVar1 (EAX) as a register variable
|
||||||
function.addLocalVariable(
|
function.addLocalVariable(new LocalVariableImpl("sum", 0,
|
||||||
new LocalVariableImpl("sum", 0, UnsignedIntegerDataType.dataType, register("EDX"),
|
UnsignedIntegerDataType.dataType, register("EDX"), program),
|
||||||
program),
|
|
||||||
SourceType.USER_DEFINED);
|
SourceType.USER_DEFINED);
|
||||||
|
|
||||||
Instruction ins = program.getListing().getInstructionAt(stackRefInstr);
|
Instruction ins = program.getListing().getInstructionAt(stackRefInstr);
|
||||||
|
@ -501,18 +498,15 @@ public class StackUnwinderTest extends AbstractGhidraHeadedDebuggerTest {
|
||||||
.createFunction("fillStruct", funcInstr,
|
.createFunction("fillStruct", funcInstr,
|
||||||
new AddressSet(funcInstr, end.previous()), SourceType.USER_DEFINED);
|
new AddressSet(funcInstr, end.previous()), SourceType.USER_DEFINED);
|
||||||
funFillStruct.updateFunction("__cdecl", null,
|
funFillStruct.updateFunction("__cdecl", null,
|
||||||
List.of(
|
List.of(new ParameterImpl("s", new PointerDataType(structure), program)),
|
||||||
new ParameterImpl("s", new PointerDataType(structure), program)),
|
|
||||||
FunctionUpdateType.DYNAMIC_STORAGE_FORMAL_PARAMS, true, SourceType.ANALYSIS);
|
FunctionUpdateType.DYNAMIC_STORAGE_FORMAL_PARAMS, true, SourceType.ANALYSIS);
|
||||||
|
|
||||||
Function main = program.getFunctionManager()
|
Function main = program.getFunctionManager()
|
||||||
.createFunction("main", entry, new AddressSet(entry, funcInstr.previous()),
|
.createFunction("main", entry, new AddressSet(entry, funcInstr.previous()),
|
||||||
SourceType.USER_DEFINED);
|
SourceType.USER_DEFINED);
|
||||||
main.updateFunction("__cdecl",
|
main.updateFunction("__cdecl", new ReturnParameterImpl(DWordDataType.dataType, program),
|
||||||
new ReturnParameterImpl(DWordDataType.dataType, program),
|
|
||||||
FunctionUpdateType.DYNAMIC_STORAGE_FORMAL_PARAMS, true, SourceType.ANALYSIS);
|
FunctionUpdateType.DYNAMIC_STORAGE_FORMAL_PARAMS, true, SourceType.ANALYSIS);
|
||||||
main.addLocalVariable(
|
main.addLocalVariable(new LocalVariableImpl("myStack", structure, -8, program),
|
||||||
new LocalVariableImpl("myStack", structure, -8, program),
|
|
||||||
SourceType.ANALYSIS);
|
SourceType.ANALYSIS);
|
||||||
return main;
|
return main;
|
||||||
}
|
}
|
||||||
|
@ -581,16 +575,14 @@ public class StackUnwinderTest extends AbstractGhidraHeadedDebuggerTest {
|
||||||
.createFunction("fillStruct", funcInstr,
|
.createFunction("fillStruct", funcInstr,
|
||||||
new AddressSet(funcInstr, end.previous()), SourceType.USER_DEFINED);
|
new AddressSet(funcInstr, end.previous()), SourceType.USER_DEFINED);
|
||||||
funFillStruct.updateFunction("__cdecl", null,
|
funFillStruct.updateFunction("__cdecl", null,
|
||||||
List.of(
|
List.of(new ParameterImpl("s", new PointerDataType(structure), program),
|
||||||
new ParameterImpl("s", new PointerDataType(structure), program),
|
|
||||||
new ParameterImpl("i", IntegerDataType.dataType, program)),
|
new ParameterImpl("i", IntegerDataType.dataType, program)),
|
||||||
FunctionUpdateType.DYNAMIC_STORAGE_FORMAL_PARAMS, true, SourceType.ANALYSIS);
|
FunctionUpdateType.DYNAMIC_STORAGE_FORMAL_PARAMS, true, SourceType.ANALYSIS);
|
||||||
|
|
||||||
Function main = program.getFunctionManager()
|
Function main = program.getFunctionManager()
|
||||||
.createFunction("main", entry, new AddressSet(entry, funcInstr.previous()),
|
.createFunction("main", entry, new AddressSet(entry, funcInstr.previous()),
|
||||||
SourceType.USER_DEFINED);
|
SourceType.USER_DEFINED);
|
||||||
main.updateFunction("__cdecl",
|
main.updateFunction("__cdecl", new ReturnParameterImpl(DWordDataType.dataType, program),
|
||||||
new ReturnParameterImpl(DWordDataType.dataType, program),
|
|
||||||
FunctionUpdateType.DYNAMIC_STORAGE_FORMAL_PARAMS, true, SourceType.ANALYSIS);
|
FunctionUpdateType.DYNAMIC_STORAGE_FORMAL_PARAMS, true, SourceType.ANALYSIS);
|
||||||
return main;
|
return main;
|
||||||
}
|
}
|
||||||
|
@ -614,10 +606,7 @@ public class StackUnwinderTest extends AbstractGhidraHeadedDebuggerTest {
|
||||||
|
|
||||||
UnwindInfo infoAtBody = ua.computeUnwindInfo(bodyInstr, monitor);
|
UnwindInfo infoAtBody = ua.computeUnwindInfo(bodyInstr, monitor);
|
||||||
assertEquals(new UnwindInfo(function, -20L, 4L, stack(0),
|
assertEquals(new UnwindInfo(function, -20L, 4L, stack(0),
|
||||||
Map.of(
|
Map.of(register("EBP"), stack(-4)), new StackUnwindWarningSet(), null), infoAtBody);
|
||||||
register("EBP"), stack(-4)),
|
|
||||||
new StackUnwindWarningSet(), null),
|
|
||||||
infoAtBody);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -640,11 +629,9 @@ public class StackUnwinderTest extends AbstractGhidraHeadedDebuggerTest {
|
||||||
infoAtEntry);
|
infoAtEntry);
|
||||||
|
|
||||||
UnwindInfo infoAtBody = ua.computeUnwindInfo(bodyInstr, monitor);
|
UnwindInfo infoAtBody = ua.computeUnwindInfo(bodyInstr, monitor);
|
||||||
assertEquals(new UnwindInfo(function, -20L, 4L, stack(0),
|
assertEquals(
|
||||||
Map.of(
|
new UnwindInfo(function, -20L, 4L, stack(0), Map.of(register("EBP"), stack(-4)),
|
||||||
register("EBP"), stack(-4)),
|
new StackUnwindWarningSet(new UnspecifiedConventionStackUnwindWarning(myExtern),
|
||||||
new StackUnwindWarningSet(
|
|
||||||
new UnspecifiedConventionStackUnwindWarning(myExtern),
|
|
||||||
new UnknownPurgeStackUnwindWarning(myExtern)),
|
new UnknownPurgeStackUnwindWarning(myExtern)),
|
||||||
null),
|
null),
|
||||||
infoAtBody);
|
infoAtBody);
|
||||||
|
@ -670,11 +657,8 @@ public class StackUnwinderTest extends AbstractGhidraHeadedDebuggerTest {
|
||||||
UnwindInfo infoAtBody = ua.computeUnwindInfo(bodyInstr, monitor);
|
UnwindInfo infoAtBody = ua.computeUnwindInfo(bodyInstr, monitor);
|
||||||
DataType ptr2Undef = new PointerDataType(DataType.DEFAULT, program.getDataTypeManager());
|
DataType ptr2Undef = new PointerDataType(DataType.DEFAULT, program.getDataTypeManager());
|
||||||
assertEquals(new UnwindInfo(function, -20L, 4L, stack(0),
|
assertEquals(new UnwindInfo(function, -20L, 4L, stack(0),
|
||||||
Map.of(
|
Map.of(register("EBP"), stack(-4)),
|
||||||
register("EBP"), stack(-4)),
|
new StackUnwindWarningSet(new UnexpectedTargetTypeStackUnwindWarning(ptr2Undef)), null),
|
||||||
new StackUnwindWarningSet(
|
|
||||||
new UnexpectedTargetTypeStackUnwindWarning(ptr2Undef)),
|
|
||||||
null),
|
|
||||||
infoAtBody);
|
infoAtBody);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -684,8 +668,7 @@ public class StackUnwinderTest extends AbstractGhidraHeadedDebuggerTest {
|
||||||
addPlugin(tool, DebuggerListingPlugin.class);
|
addPlugin(tool, DebuggerListingPlugin.class);
|
||||||
addPlugin(tool, DisassemblerPlugin.class);
|
addPlugin(tool, DisassemblerPlugin.class);
|
||||||
addPlugin(tool, DecompilePlugin.class);
|
addPlugin(tool, DecompilePlugin.class);
|
||||||
DebuggerControlService editingService =
|
DebuggerControlService editingService = addPlugin(tool, DebuggerControlServicePlugin.class);
|
||||||
addPlugin(tool, DebuggerControlServicePlugin.class);
|
|
||||||
DebuggerEmulationService emuService = addPlugin(tool, DebuggerEmulationServicePlugin.class);
|
DebuggerEmulationService emuService = addPlugin(tool, DebuggerEmulationServicePlugin.class);
|
||||||
|
|
||||||
Function function = createSumSquaresProgramX86_32();
|
Function function = createSumSquaresProgramX86_32();
|
||||||
|
@ -744,8 +727,7 @@ public class StackUnwinderTest extends AbstractGhidraHeadedDebuggerTest {
|
||||||
addPlugin(tool, DebuggerListingPlugin.class);
|
addPlugin(tool, DebuggerListingPlugin.class);
|
||||||
addPlugin(tool, DisassemblerPlugin.class);
|
addPlugin(tool, DisassemblerPlugin.class);
|
||||||
addPlugin(tool, DecompilePlugin.class);
|
addPlugin(tool, DecompilePlugin.class);
|
||||||
DebuggerControlService editingService =
|
DebuggerControlService editingService = addPlugin(tool, DebuggerControlServicePlugin.class);
|
||||||
addPlugin(tool, DebuggerControlServicePlugin.class);
|
|
||||||
DebuggerEmulationService emuService = addPlugin(tool, DebuggerEmulationServicePlugin.class);
|
DebuggerEmulationService emuService = addPlugin(tool, DebuggerEmulationServicePlugin.class);
|
||||||
|
|
||||||
Function function = createFibonacciProgramX86_32();
|
Function function = createFibonacciProgramX86_32();
|
||||||
|
@ -775,13 +757,12 @@ public class StackUnwinderTest extends AbstractGhidraHeadedDebuggerTest {
|
||||||
TraceBreakpoint bptUnwind;
|
TraceBreakpoint bptUnwind;
|
||||||
try (Transaction tx = tb.startTransaction()) {
|
try (Transaction tx = tb.startTransaction()) {
|
||||||
bptUnwind = tb.trace.getBreakpointManager()
|
bptUnwind = tb.trace.getBreakpointManager()
|
||||||
.addBreakpoint("Breakpoints[0]", Lifespan.nowOn(0), retInstr,
|
.addBreakpoint("Breakpoints[0]", Lifespan.nowOn(0), retInstr, Set.of(),
|
||||||
Set.of(),
|
|
||||||
Set.of(TraceBreakpointKind.SW_EXECUTE), true, "unwind stack");
|
Set.of(TraceBreakpointKind.SW_EXECUTE), true, "unwind stack");
|
||||||
tb.trace.getBreakpointManager()
|
tb.trace.getBreakpointManager()
|
||||||
.addBreakpoint("Breakpoints[1]", Lifespan.nowOn(0), tb.addr(0xdeadbeef),
|
.addBreakpoint("Breakpoints[1]", Lifespan.nowOn(0), tb.addr(0xdeadbeef),
|
||||||
Set.of(),
|
Set.of(), Set.of(TraceBreakpointKind.SW_EXECUTE), true,
|
||||||
Set.of(TraceBreakpointKind.SW_EXECUTE), true, "capture return value");
|
"capture return value");
|
||||||
}
|
}
|
||||||
|
|
||||||
EmulationResult result = emuService.run(atSetup.getPlatform(), atSetup.getTime(), monitor,
|
EmulationResult result = emuService.run(atSetup.getPlatform(), atSetup.getTime(), monitor,
|
||||||
|
@ -916,8 +897,7 @@ public class StackUnwinderTest extends AbstractGhidraHeadedDebuggerTest {
|
||||||
|
|
||||||
try (Transaction tx = tb.startTransaction()) {
|
try (Transaction tx = tb.startTransaction()) {
|
||||||
tb.trace.getBreakpointManager()
|
tb.trace.getBreakpointManager()
|
||||||
.addBreakpoint("Breakpoints[0]", Lifespan.nowOn(0), retInstr,
|
.addBreakpoint("Breakpoints[0]", Lifespan.nowOn(0), retInstr, Set.of(),
|
||||||
Set.of(),
|
|
||||||
Set.of(TraceBreakpointKind.SW_EXECUTE), true, "unwind stack");
|
Set.of(TraceBreakpointKind.SW_EXECUTE), true, "unwind stack");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -957,8 +937,7 @@ public class StackUnwinderTest extends AbstractGhidraHeadedDebuggerTest {
|
||||||
|
|
||||||
try (Transaction tx = tb.startTransaction()) {
|
try (Transaction tx = tb.startTransaction()) {
|
||||||
tb.trace.getBreakpointManager()
|
tb.trace.getBreakpointManager()
|
||||||
.addBreakpoint("Breakpoints[0]", Lifespan.nowOn(0), retInstr,
|
.addBreakpoint("Breakpoints[0]", Lifespan.nowOn(0), retInstr, Set.of(),
|
||||||
Set.of(),
|
|
||||||
Set.of(TraceBreakpointKind.SW_EXECUTE), true, "unwind stack");
|
Set.of(TraceBreakpointKind.SW_EXECUTE), true, "unwind stack");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -999,8 +978,7 @@ public class StackUnwinderTest extends AbstractGhidraHeadedDebuggerTest {
|
||||||
|
|
||||||
try (Transaction tx = tb.startTransaction()) {
|
try (Transaction tx = tb.startTransaction()) {
|
||||||
tb.trace.getBreakpointManager()
|
tb.trace.getBreakpointManager()
|
||||||
.addBreakpoint("Breakpoints[0]", Lifespan.nowOn(0), retInstr,
|
.addBreakpoint("Breakpoints[0]", Lifespan.nowOn(0), retInstr, Set.of(),
|
||||||
Set.of(),
|
|
||||||
Set.of(TraceBreakpointKind.SW_EXECUTE), true, "unwind stack");
|
Set.of(TraceBreakpointKind.SW_EXECUTE), true, "unwind stack");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1041,8 +1019,7 @@ public class StackUnwinderTest extends AbstractGhidraHeadedDebuggerTest {
|
||||||
|
|
||||||
try (Transaction tx = tb.startTransaction()) {
|
try (Transaction tx = tb.startTransaction()) {
|
||||||
tb.trace.getBreakpointManager()
|
tb.trace.getBreakpointManager()
|
||||||
.addBreakpoint("Breakpoints[0]", Lifespan.nowOn(0), retInstr,
|
.addBreakpoint("Breakpoints[0]", Lifespan.nowOn(0), retInstr, Set.of(),
|
||||||
Set.of(),
|
|
||||||
Set.of(TraceBreakpointKind.SW_EXECUTE), true, "unwind stack");
|
Set.of(TraceBreakpointKind.SW_EXECUTE), true, "unwind stack");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1166,8 +1143,8 @@ public class StackUnwinderTest extends AbstractGhidraHeadedDebuggerTest {
|
||||||
FieldLocation fieldLocation, Field field) throws Throwable {
|
FieldLocation fieldLocation, Field field) throws Throwable {
|
||||||
VariableValueTable table = new VariableValueTable();
|
VariableValueTable table = new VariableValueTable();
|
||||||
StackUnwindWarningSet warnings = new StackUnwindWarningSet();
|
StackUnwindWarningSet warnings = new StackUnwindWarningSet();
|
||||||
waitOn(valuesService.fillVariableValueTable(table, programLocation, current,
|
waitOn(valuesService.fillVariableValueTable(table, programLocation, current, fieldLocation,
|
||||||
fieldLocation, field, warnings));
|
field, warnings));
|
||||||
table.add(new WarningsRow(warnings));
|
table.add(new WarningsRow(warnings));
|
||||||
return table;
|
return table;
|
||||||
}
|
}
|
||||||
|
@ -1182,16 +1159,12 @@ public class StackUnwinderTest extends AbstractGhidraHeadedDebuggerTest {
|
||||||
VariableValueTable table = getVariableValueTable(valuesService, loc.pLoc,
|
VariableValueTable table = getVariableValueTable(valuesService, loc.pLoc,
|
||||||
traceManager.getCurrent(), loc.fLoc, loc.field);
|
traceManager.getCurrent(), loc.fLoc, loc.field);
|
||||||
|
|
||||||
assertTable(Map.of(
|
assertTable(Map.of(RowKey.NAME, "Name: n", RowKey.FRAME,
|
||||||
RowKey.NAME, "Name: n",
|
"Frame: 0 fib pc=0040002c sp=00004ff4 base=00004ff4", RowKey.STORAGE,
|
||||||
RowKey.FRAME, "Frame: 0 fib pc=0040002c sp=00004ff4 base=00004ff4",
|
"Storage: Stack[0x4]:4", RowKey.TYPE, "Type: uint", RowKey.LOCATION,
|
||||||
RowKey.STORAGE, "Storage: Stack[0x4]:4",
|
"Location: 00004ff8:4", RowKey.BYTES, "Bytes: (KNOWN) 01 00 00 00", RowKey.INTEGER,
|
||||||
RowKey.TYPE, "Type: uint",
|
"Integer: (KNOWN) 1", RowKey.VALUE, "Value: (KNOWN) 1h", RowKey.WARNINGS, "IGNORED"),
|
||||||
RowKey.LOCATION, "Location: 00004ff8:4",
|
table);
|
||||||
RowKey.BYTES, "Bytes: (KNOWN) 01 00 00 00",
|
|
||||||
RowKey.INTEGER, "Integer: (KNOWN) 1",
|
|
||||||
RowKey.VALUE, "Value: (KNOWN) 1h",
|
|
||||||
RowKey.WARNINGS, "IGNORED"), table);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -1204,15 +1177,11 @@ public class StackUnwinderTest extends AbstractGhidraHeadedDebuggerTest {
|
||||||
VariableValueTable table = getVariableValueTable(valuesService, loc.pLoc,
|
VariableValueTable table = getVariableValueTable(valuesService, loc.pLoc,
|
||||||
traceManager.getCurrent(), loc.fLoc, loc.field);
|
traceManager.getCurrent(), loc.fLoc, loc.field);
|
||||||
|
|
||||||
assertTable(Map.of(
|
assertTable(Map.of(RowKey.NAME, "Name: sum", RowKey.FRAME,
|
||||||
RowKey.NAME, "Name: sum",
|
"Frame: 0 fib pc=0040002c sp=00004ff4 base=00004ff4", RowKey.STORAGE, "Storage: EDX:4",
|
||||||
RowKey.FRAME, "Frame: 0 fib pc=0040002c sp=00004ff4 base=00004ff4",
|
RowKey.TYPE, "Type: uint", RowKey.LOCATION, "Location: EDX:4", RowKey.INTEGER,
|
||||||
RowKey.STORAGE, "Storage: EDX:4",
|
"Integer: (UNKNOWN) 0", RowKey.VALUE, "Value: (UNKNOWN) 0h", RowKey.WARNINGS,
|
||||||
RowKey.TYPE, "Type: uint",
|
"IGNORED"), table);
|
||||||
RowKey.LOCATION, "Location: EDX:4",
|
|
||||||
RowKey.INTEGER, "Integer: (UNKNOWN) 0",
|
|
||||||
RowKey.VALUE, "Value: (UNKNOWN) 0h",
|
|
||||||
RowKey.WARNINGS, "IGNORED"), table);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -1225,15 +1194,11 @@ public class StackUnwinderTest extends AbstractGhidraHeadedDebuggerTest {
|
||||||
VariableValueTable table = getVariableValueTable(valuesService, loc.pLoc,
|
VariableValueTable table = getVariableValueTable(valuesService, loc.pLoc,
|
||||||
traceManager.getCurrent(), loc.fLoc, loc.field);
|
traceManager.getCurrent(), loc.fLoc, loc.field);
|
||||||
|
|
||||||
assertTable(Map.of(
|
assertTable(Map.of(RowKey.NAME, "Name: <RETURN>", RowKey.FRAME,
|
||||||
RowKey.NAME, "Name: <RETURN>",
|
"Frame: 0 fib pc=0040002c sp=00004ff4 base=00004ff4", RowKey.STORAGE, "Storage: EAX:4",
|
||||||
RowKey.FRAME, "Frame: 0 fib pc=0040002c sp=00004ff4 base=00004ff4",
|
RowKey.TYPE, "Type: uint", RowKey.LOCATION, "Location: EAX:4", RowKey.INTEGER,
|
||||||
RowKey.STORAGE, "Storage: EAX:4",
|
"Integer: (KNOWN) 1", RowKey.VALUE, "Value: (KNOWN) 1h", RowKey.WARNINGS, "IGNORED"),
|
||||||
RowKey.TYPE, "Type: uint",
|
table);
|
||||||
RowKey.LOCATION, "Location: EAX:4",
|
|
||||||
RowKey.INTEGER, "Integer: (KNOWN) 1",
|
|
||||||
RowKey.VALUE, "Value: (KNOWN) 1h",
|
|
||||||
RowKey.WARNINGS, "IGNORED"), table);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -1247,16 +1212,11 @@ public class StackUnwinderTest extends AbstractGhidraHeadedDebuggerTest {
|
||||||
VariableValueTable table = getVariableValueTable(valuesService, loc.pLoc,
|
VariableValueTable table = getVariableValueTable(valuesService, loc.pLoc,
|
||||||
traceManager.getCurrent(), loc.fLoc, loc.field);
|
traceManager.getCurrent(), loc.fLoc, loc.field);
|
||||||
|
|
||||||
assertTable(Map.of(
|
assertTable(Map.of(RowKey.NAME, "Name: myGlobal", RowKey.STORAGE, "Storage: 00600000:4",
|
||||||
RowKey.NAME, "Name: myGlobal",
|
RowKey.TYPE, "Type: int", RowKey.LOCATION, "Location: 00600000:4", RowKey.BYTES,
|
||||||
RowKey.STORAGE, "Storage: 00600000:4",
|
"Bytes: (KNOWN) ef be ad de", RowKey.INTEGER, """
|
||||||
RowKey.TYPE, "Type: int",
|
|
||||||
RowKey.LOCATION, "Location: 00600000:4",
|
|
||||||
RowKey.BYTES, "Bytes: (KNOWN) ef be ad de",
|
|
||||||
RowKey.INTEGER, """
|
|
||||||
Integer: (KNOWN) 3735928559, 0xdeadbeef
|
Integer: (KNOWN) 3735928559, 0xdeadbeef
|
||||||
-559038737, -0x21524111""",
|
-559038737, -0x21524111""", RowKey.VALUE, "Value: (KNOWN) DEADBEEFh",
|
||||||
RowKey.VALUE, "Value: (KNOWN) DEADBEEFh",
|
|
||||||
RowKey.WARNINGS, "IGNORED"), table);
|
RowKey.WARNINGS, "IGNORED"), table);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1269,17 +1229,17 @@ public class StackUnwinderTest extends AbstractGhidraHeadedDebuggerTest {
|
||||||
Address dynamicAddress = dynLoc.getAddress();
|
Address dynamicAddress = dynLoc.getAddress();
|
||||||
try (Transaction tx = tb.startTransaction()) {
|
try (Transaction tx = tb.startTransaction()) {
|
||||||
int length = stIns.getLength();
|
int length = stIns.getLength();
|
||||||
assertEquals(length, tb.trace.getMemoryManager()
|
assertEquals(length,
|
||||||
|
tb.trace.getMemoryManager()
|
||||||
.putBytes(current.getSnap(), dynamicAddress,
|
.putBytes(current.getSnap(), dynamicAddress,
|
||||||
ByteBuffer.wrap(stIns.getBytes())));
|
ByteBuffer.wrap(stIns.getBytes())));
|
||||||
new TraceDisassembleCommand(current.getPlatform(), dynamicAddress,
|
new TraceDisassembleCommand(current.getPlatform(), dynamicAddress,
|
||||||
new AddressSet(dynamicAddress, dynamicAddress.add(length - 1)))
|
new AddressSet(dynamicAddress, dynamicAddress.add(length - 1)))
|
||||||
.applyToTyped(current.getView(), monitor);
|
.applyTo(current.getView(), monitor);
|
||||||
}
|
}
|
||||||
waitForDomainObject(tb.trace);
|
waitForDomainObject(tb.trace);
|
||||||
return Objects.requireNonNull(tb.trace.getCodeManager()
|
return Objects.requireNonNull(
|
||||||
.instructions()
|
tb.trace.getCodeManager().instructions().getAt(current.getViewSnap(), dynamicAddress));
|
||||||
.getAt(current.getViewSnap(), dynamicAddress));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -1295,16 +1255,11 @@ public class StackUnwinderTest extends AbstractGhidraHeadedDebuggerTest {
|
||||||
VariableValueTable table = getVariableValueTable(valuesService, loc.pLoc,
|
VariableValueTable table = getVariableValueTable(valuesService, loc.pLoc,
|
||||||
traceManager.getCurrent(), loc.fLoc, loc.field);
|
traceManager.getCurrent(), loc.fLoc, loc.field);
|
||||||
|
|
||||||
assertTable(Map.of(
|
assertTable(Map.of(RowKey.NAME, "Name: myGlobal", RowKey.STORAGE, "Storage: 00600000:4",
|
||||||
RowKey.NAME, "Name: myGlobal",
|
RowKey.TYPE, "Type: int", RowKey.LOCATION, "Location: 00600000:4", RowKey.BYTES,
|
||||||
RowKey.STORAGE, "Storage: 00600000:4",
|
"Bytes: (KNOWN) ef be ad de", RowKey.INTEGER, """
|
||||||
RowKey.TYPE, "Type: int",
|
|
||||||
RowKey.LOCATION, "Location: 00600000:4",
|
|
||||||
RowKey.BYTES, "Bytes: (KNOWN) ef be ad de",
|
|
||||||
RowKey.INTEGER, """
|
|
||||||
Integer: (KNOWN) 3735928559, 0xdeadbeef
|
Integer: (KNOWN) 3735928559, 0xdeadbeef
|
||||||
-559038737, -0x21524111""",
|
-559038737, -0x21524111""", RowKey.VALUE, "Value: (KNOWN) DEADBEEFh",
|
||||||
RowKey.VALUE, "Value: (KNOWN) DEADBEEFh",
|
|
||||||
RowKey.WARNINGS, "IGNORED"), table);
|
RowKey.WARNINGS, "IGNORED"), table);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1319,16 +1274,12 @@ public class StackUnwinderTest extends AbstractGhidraHeadedDebuggerTest {
|
||||||
VariableValueTable table = getVariableValueTable(valuesService, loc.pLoc,
|
VariableValueTable table = getVariableValueTable(valuesService, loc.pLoc,
|
||||||
traceManager.getCurrent(), loc.fLoc, loc.field);
|
traceManager.getCurrent(), loc.fLoc, loc.field);
|
||||||
|
|
||||||
assertTable(Map.of(
|
assertTable(Map.of(RowKey.NAME, "Name: n", RowKey.FRAME,
|
||||||
RowKey.NAME, "Name: n",
|
"Frame: 0 fib pc=0040002c sp=00004ff4 base=00004ff4", RowKey.STORAGE,
|
||||||
RowKey.FRAME, "Frame: 0 fib pc=0040002c sp=00004ff4 base=00004ff4",
|
"Storage: Stack[0x4]:4", RowKey.TYPE, "Type: uint", RowKey.LOCATION,
|
||||||
RowKey.STORAGE, "Storage: Stack[0x4]:4",
|
"Location: 00004ff8:4", RowKey.BYTES, "Bytes: (KNOWN) 01 00 00 00", RowKey.INTEGER,
|
||||||
RowKey.TYPE, "Type: uint",
|
"Integer: (KNOWN) 1", RowKey.VALUE, "Value: (KNOWN) 1h", RowKey.WARNINGS, "IGNORED"),
|
||||||
RowKey.LOCATION, "Location: 00004ff8:4",
|
table);
|
||||||
RowKey.BYTES, "Bytes: (KNOWN) 01 00 00 00",
|
|
||||||
RowKey.INTEGER, "Integer: (KNOWN) 1",
|
|
||||||
RowKey.VALUE, "Value: (KNOWN) 1h",
|
|
||||||
RowKey.WARNINGS, "IGNORED"), table);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -1342,15 +1293,11 @@ public class StackUnwinderTest extends AbstractGhidraHeadedDebuggerTest {
|
||||||
VariableValueTable table = getVariableValueTable(valuesService, loc.pLoc,
|
VariableValueTable table = getVariableValueTable(valuesService, loc.pLoc,
|
||||||
traceManager.getCurrent(), loc.fLoc, loc.field);
|
traceManager.getCurrent(), loc.fLoc, loc.field);
|
||||||
|
|
||||||
assertTable(Map.of(
|
assertTable(Map.of(RowKey.NAME, "Name: sum", RowKey.FRAME,
|
||||||
RowKey.NAME, "Name: sum",
|
"Frame: 0 fib pc=0040002c sp=00004ff4 base=00004ff4", RowKey.STORAGE, "Storage: EDX:4",
|
||||||
RowKey.FRAME, "Frame: 0 fib pc=0040002c sp=00004ff4 base=00004ff4",
|
RowKey.TYPE, "Type: uint", RowKey.LOCATION, "Location: EDX:4", RowKey.INTEGER,
|
||||||
RowKey.STORAGE, "Storage: EDX:4",
|
"Integer: (UNKNOWN) 0", RowKey.VALUE, "Value: (UNKNOWN) 0h", RowKey.WARNINGS,
|
||||||
RowKey.TYPE, "Type: uint",
|
"IGNORED"), table);
|
||||||
RowKey.LOCATION, "Location: EDX:4",
|
|
||||||
RowKey.INTEGER, "Integer: (UNKNOWN) 0",
|
|
||||||
RowKey.VALUE, "Value: (UNKNOWN) 0h",
|
|
||||||
RowKey.WARNINGS, "IGNORED"), table);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -1367,11 +1314,9 @@ public class StackUnwinderTest extends AbstractGhidraHeadedDebuggerTest {
|
||||||
VariableValueTable table = getVariableValueTable(valuesService, loc.pLoc,
|
VariableValueTable table = getVariableValueTable(valuesService, loc.pLoc,
|
||||||
traceManager.getCurrent(), loc.fLoc, loc.field);
|
traceManager.getCurrent(), loc.fLoc, loc.field);
|
||||||
|
|
||||||
assertTable(Map.of(
|
assertTable(Map.of(RowKey.NAME, "Name: EBP", RowKey.FRAME,
|
||||||
RowKey.NAME, "Name: EBP",
|
"Frame: 2 fib pc=00400013 sp=00004ff8 base=00005000", RowKey.LOCATION,
|
||||||
RowKey.FRAME, "Frame: 2 fib pc=00400013 sp=00004ff8 base=00005000",
|
"Location: 00004ff0:4", RowKey.INTEGER, "Integer: (KNOWN) 20476, 0x4ffc",
|
||||||
RowKey.LOCATION, "Location: 00004ff0:4",
|
|
||||||
RowKey.INTEGER, "Integer: (KNOWN) 20476, 0x4ffc",
|
|
||||||
RowKey.WARNINGS, "IGNORED"), table);
|
RowKey.WARNINGS, "IGNORED"), table);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1388,9 +1333,7 @@ public class StackUnwinderTest extends AbstractGhidraHeadedDebuggerTest {
|
||||||
VariableValueTable table = getVariableValueTable(valuesService, loc.pLoc,
|
VariableValueTable table = getVariableValueTable(valuesService, loc.pLoc,
|
||||||
traceManager.getCurrent(), loc.fLoc, loc.field);
|
traceManager.getCurrent(), loc.fLoc, loc.field);
|
||||||
|
|
||||||
assertTable(Map.of(
|
assertTable(Map.of(RowKey.NAME, "Name: EDX", RowKey.INTEGER, "Integer: (UNKNOWN) 0",
|
||||||
RowKey.NAME, "Name: EDX",
|
|
||||||
RowKey.INTEGER, "Integer: (UNKNOWN) 0",
|
|
||||||
RowKey.WARNINGS, "IGNORED"), table);
|
RowKey.WARNINGS, "IGNORED"), table);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1495,16 +1438,11 @@ public class StackUnwinderTest extends AbstractGhidraHeadedDebuggerTest {
|
||||||
VariableValueTable table = getVariableValueTable(valuesService, loc.pLoc,
|
VariableValueTable table = getVariableValueTable(valuesService, loc.pLoc,
|
||||||
traceManager.getCurrent(), loc.fLoc, loc.field);
|
traceManager.getCurrent(), loc.fLoc, loc.field);
|
||||||
|
|
||||||
assertTable(Map.of(
|
assertTable(Map.of(RowKey.NAME, "Name: myGlobal", RowKey.STORAGE, "Storage: 00600000:4",
|
||||||
RowKey.NAME, "Name: myGlobal",
|
RowKey.TYPE, "Type: int", RowKey.LOCATION, "Location: 00600000:4", RowKey.BYTES,
|
||||||
RowKey.STORAGE, "Storage: 00600000:4",
|
"Bytes: (KNOWN) ef be ad de", RowKey.INTEGER, """
|
||||||
RowKey.TYPE, "Type: int",
|
|
||||||
RowKey.LOCATION, "Location: 00600000:4",
|
|
||||||
RowKey.BYTES, "Bytes: (KNOWN) ef be ad de",
|
|
||||||
RowKey.INTEGER, """
|
|
||||||
Integer: (KNOWN) 3735928559, 0xdeadbeef
|
Integer: (KNOWN) 3735928559, 0xdeadbeef
|
||||||
-559038737, -0x21524111""",
|
-559038737, -0x21524111""", RowKey.VALUE, "Value: (KNOWN) DEADBEEFh",
|
||||||
RowKey.VALUE, "Value: (KNOWN) DEADBEEFh",
|
|
||||||
RowKey.WARNINGS, "IGNORED"), table);
|
RowKey.WARNINGS, "IGNORED"), table);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1518,16 +1456,12 @@ public class StackUnwinderTest extends AbstractGhidraHeadedDebuggerTest {
|
||||||
VariableValueTable table = getVariableValueTable(valuesService, loc.pLoc,
|
VariableValueTable table = getVariableValueTable(valuesService, loc.pLoc,
|
||||||
traceManager.getCurrent(), loc.fLoc, loc.field);
|
traceManager.getCurrent(), loc.fLoc, loc.field);
|
||||||
|
|
||||||
assertTable(Map.of(
|
assertTable(Map.of(RowKey.NAME, "Name: n", RowKey.FRAME,
|
||||||
RowKey.NAME, "Name: n",
|
"Frame: 0 fib pc=0040002c sp=00004ff4 base=00004ff4", RowKey.STORAGE,
|
||||||
RowKey.FRAME, "Frame: 0 fib pc=0040002c sp=00004ff4 base=00004ff4",
|
"Storage: Stack[0x4]:4", RowKey.TYPE, "Type: uint", RowKey.LOCATION,
|
||||||
RowKey.STORAGE, "Storage: Stack[0x4]:4",
|
"Location: 00004ff8:4", RowKey.BYTES, "Bytes: (KNOWN) 01 00 00 00", RowKey.INTEGER,
|
||||||
RowKey.TYPE, "Type: uint",
|
"Integer: (KNOWN) 1", RowKey.VALUE, "Value: (KNOWN) 1h", RowKey.WARNINGS, "IGNORED"),
|
||||||
RowKey.LOCATION, "Location: 00004ff8:4",
|
table);
|
||||||
RowKey.BYTES, "Bytes: (KNOWN) 01 00 00 00",
|
|
||||||
RowKey.INTEGER, "Integer: (KNOWN) 1",
|
|
||||||
RowKey.VALUE, "Value: (KNOWN) 1h",
|
|
||||||
RowKey.WARNINGS, "IGNORED"), table);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -1541,15 +1475,11 @@ public class StackUnwinderTest extends AbstractGhidraHeadedDebuggerTest {
|
||||||
VariableValueTable table = getVariableValueTable(valuesService, loc.pLoc,
|
VariableValueTable table = getVariableValueTable(valuesService, loc.pLoc,
|
||||||
traceManager.getCurrent(), loc.fLoc, loc.field);
|
traceManager.getCurrent(), loc.fLoc, loc.field);
|
||||||
|
|
||||||
assertTable(Map.of(
|
assertTable(Map.of(RowKey.NAME, "Name: uVar1", RowKey.FRAME,
|
||||||
RowKey.NAME, "Name: uVar1",
|
"Frame: 0 fib pc=0040002c sp=00004ff4 base=00004ff4", RowKey.STORAGE, "Storage: EAX:4",
|
||||||
RowKey.FRAME, "Frame: 0 fib pc=0040002c sp=00004ff4 base=00004ff4",
|
RowKey.TYPE, "Type: uint", RowKey.LOCATION, "Location: EAX:4", RowKey.INTEGER,
|
||||||
RowKey.STORAGE, "Storage: EAX:4",
|
"Integer: (KNOWN) 1", RowKey.VALUE, "Value: (KNOWN) 1h", RowKey.WARNINGS, "IGNORED"),
|
||||||
RowKey.TYPE, "Type: uint",
|
table);
|
||||||
RowKey.LOCATION, "Location: EAX:4",
|
|
||||||
RowKey.INTEGER, "Integer: (KNOWN) 1",
|
|
||||||
RowKey.VALUE, "Value: (KNOWN) 1h",
|
|
||||||
RowKey.WARNINGS, "IGNORED"), table);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -1566,15 +1496,10 @@ public class StackUnwinderTest extends AbstractGhidraHeadedDebuggerTest {
|
||||||
VariableValueTable table = getVariableValueTable(valuesService, loc.pLoc,
|
VariableValueTable table = getVariableValueTable(valuesService, loc.pLoc,
|
||||||
traceManager.getCurrent(), loc.fLoc, loc.field);
|
traceManager.getCurrent(), loc.fLoc, loc.field);
|
||||||
|
|
||||||
assertTable(Map.of(
|
assertTable(Map.of(RowKey.NAME, "Name: myGlobal", RowKey.STORAGE, "Storage: 00600000:4",
|
||||||
RowKey.NAME, "Name: myGlobal",
|
RowKey.TYPE, "Type: MyStruct", RowKey.LOCATION, "Location: 00600000:4", RowKey.BYTES,
|
||||||
RowKey.STORAGE, "Storage: 00600000:4",
|
"Bytes: (KNOWN) e6 07 0c 09", RowKey.INTEGER, "Integer: (KNOWN) 151783398, 0x90c07e6",
|
||||||
RowKey.TYPE, "Type: MyStruct",
|
RowKey.VALUE, "Value: (KNOWN) ", RowKey.WARNINGS, "IGNORED"), table);
|
||||||
RowKey.LOCATION, "Location: 00600000:4",
|
|
||||||
RowKey.BYTES, "Bytes: (KNOWN) e6 07 0c 09",
|
|
||||||
RowKey.INTEGER, "Integer: (KNOWN) 151783398, 0x90c07e6",
|
|
||||||
RowKey.VALUE, "Value: (KNOWN) ",
|
|
||||||
RowKey.WARNINGS, "IGNORED"), table);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -1591,14 +1516,10 @@ public class StackUnwinderTest extends AbstractGhidraHeadedDebuggerTest {
|
||||||
VariableValueTable table = getVariableValueTable(valuesService, loc.pLoc,
|
VariableValueTable table = getVariableValueTable(valuesService, loc.pLoc,
|
||||||
traceManager.getCurrent(), loc.fLoc, loc.field);
|
traceManager.getCurrent(), loc.fLoc, loc.field);
|
||||||
|
|
||||||
assertTable(Map.of(
|
assertTable(Map.of(RowKey.NAME, "Name: m", RowKey.TYPE, "Type: byte", RowKey.LOCATION,
|
||||||
RowKey.NAME, "Name: m",
|
"Location: 00600002:1", RowKey.BYTES, "Bytes: (KNOWN) 0c", RowKey.INTEGER,
|
||||||
RowKey.TYPE, "Type: byte",
|
"Integer: (KNOWN) 12, 0xc", RowKey.VALUE, "Value: (KNOWN) Ch", RowKey.WARNINGS,
|
||||||
RowKey.LOCATION, "Location: 00600002:1",
|
"IGNORED"), table);
|
||||||
RowKey.BYTES, "Bytes: (KNOWN) 0c",
|
|
||||||
RowKey.INTEGER, "Integer: (KNOWN) 12, 0xc",
|
|
||||||
RowKey.VALUE, "Value: (KNOWN) Ch",
|
|
||||||
RowKey.WARNINGS, "IGNORED"), table);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -1615,16 +1536,12 @@ public class StackUnwinderTest extends AbstractGhidraHeadedDebuggerTest {
|
||||||
VariableValueTable table = getVariableValueTable(valuesService, loc.pLoc,
|
VariableValueTable table = getVariableValueTable(valuesService, loc.pLoc,
|
||||||
traceManager.getCurrent(), loc.fLoc, loc.field);
|
traceManager.getCurrent(), loc.fLoc, loc.field);
|
||||||
|
|
||||||
assertTable(Map.of(
|
assertTable(Map.of(RowKey.NAME, "Name: myStack", RowKey.FRAME,
|
||||||
RowKey.NAME, "Name: myStack",
|
"Frame: 1 main pc=00400012 sp=00004fe4 base=00004ff0", RowKey.STORAGE,
|
||||||
RowKey.FRAME, "Frame: 1 main pc=00400012 sp=00004fe4 base=00004ff0",
|
"Storage: Stack[-0x8]:4", RowKey.TYPE, "Type: MyStruct", RowKey.LOCATION,
|
||||||
RowKey.STORAGE, "Storage: Stack[-0x8]:4",
|
"Location: 00004fe8:4", RowKey.BYTES, "Bytes: (UNKNOWN) 00 00 00 00", RowKey.INTEGER,
|
||||||
RowKey.TYPE, "Type: MyStruct",
|
"Integer: (UNKNOWN) 0", RowKey.VALUE, "Value: (UNKNOWN) ", RowKey.WARNINGS, "IGNORED"),
|
||||||
RowKey.LOCATION, "Location: 00004fe8:4",
|
table);
|
||||||
RowKey.BYTES, "Bytes: (UNKNOWN) 00 00 00 00",
|
|
||||||
RowKey.INTEGER, "Integer: (UNKNOWN) 0",
|
|
||||||
RowKey.VALUE, "Value: (UNKNOWN) ",
|
|
||||||
RowKey.WARNINGS, "IGNORED"), table);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -1641,14 +1558,10 @@ public class StackUnwinderTest extends AbstractGhidraHeadedDebuggerTest {
|
||||||
VariableValueTable table = getVariableValueTable(valuesService, loc.pLoc,
|
VariableValueTable table = getVariableValueTable(valuesService, loc.pLoc,
|
||||||
traceManager.getCurrent(), loc.fLoc, loc.field);
|
traceManager.getCurrent(), loc.fLoc, loc.field);
|
||||||
|
|
||||||
assertTable(Map.of(
|
assertTable(Map.of(RowKey.NAME, "Name: y", RowKey.FRAME,
|
||||||
RowKey.NAME, "Name: y",
|
"Frame: 1 main pc=00400012 sp=00004fe4 base=00004ff0", RowKey.TYPE, "Type: word",
|
||||||
RowKey.FRAME, "Frame: 1 main pc=00400012 sp=00004fe4 base=00004ff0",
|
RowKey.LOCATION, "Location: 00004fe8:2", RowKey.BYTES, "Bytes: (UNKNOWN) 00 00",
|
||||||
RowKey.TYPE, "Type: word",
|
RowKey.INTEGER, "Integer: (UNKNOWN) 0", RowKey.VALUE, "Value: (UNKNOWN) 0h",
|
||||||
RowKey.LOCATION, "Location: 00004fe8:2",
|
|
||||||
RowKey.BYTES, "Bytes: (UNKNOWN) 00 00",
|
|
||||||
RowKey.INTEGER, "Integer: (UNKNOWN) 0",
|
|
||||||
RowKey.VALUE, "Value: (UNKNOWN) 0h",
|
|
||||||
RowKey.WARNINGS, "IGNORED"), table);
|
RowKey.WARNINGS, "IGNORED"), table);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1666,16 +1579,13 @@ public class StackUnwinderTest extends AbstractGhidraHeadedDebuggerTest {
|
||||||
VariableValueTable table = getVariableValueTable(valuesService, loc.pLoc,
|
VariableValueTable table = getVariableValueTable(valuesService, loc.pLoc,
|
||||||
traceManager.getCurrent(), loc.fLoc, loc.field);
|
traceManager.getCurrent(), loc.fLoc, loc.field);
|
||||||
|
|
||||||
assertTable(Map.of(
|
assertTable(Map.of(RowKey.NAME, "Name: s", RowKey.FRAME,
|
||||||
RowKey.NAME, "Name: s",
|
"Frame: 0 fillStruct pc=00400041 sp=00004fe0 base=00004fe0", RowKey.STORAGE,
|
||||||
RowKey.FRAME, "Frame: 0 fillStruct pc=00400041 sp=00004fe0 base=00004fe0",
|
"Storage: Stack[0x4]:4", RowKey.TYPE, "Type: MyStruct *", RowKey.LOCATION,
|
||||||
RowKey.STORAGE, "Storage: Stack[0x4]:4",
|
"Location: 00004fe4:4",
|
||||||
RowKey.TYPE, "Type: MyStruct *",
|
|
||||||
RowKey.LOCATION, "Location: 00004fe4:4",
|
|
||||||
// NOTE: Value is the pointer, not the struct
|
// NOTE: Value is the pointer, not the struct
|
||||||
RowKey.BYTES, "Bytes: (KNOWN) 00 00 60 00",
|
RowKey.BYTES, "Bytes: (KNOWN) 00 00 60 00", RowKey.INTEGER,
|
||||||
RowKey.INTEGER, "Integer: (KNOWN) 6291456, 0x600000",
|
"Integer: (KNOWN) 6291456, 0x600000", RowKey.VALUE, "Value: (KNOWN) 00600000",
|
||||||
RowKey.VALUE, "Value: (KNOWN) 00600000",
|
|
||||||
RowKey.WARNINGS, "IGNORED"), table);
|
RowKey.WARNINGS, "IGNORED"), table);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1693,14 +1603,10 @@ public class StackUnwinderTest extends AbstractGhidraHeadedDebuggerTest {
|
||||||
VariableValueTable table = getVariableValueTable(valuesService, loc.pLoc,
|
VariableValueTable table = getVariableValueTable(valuesService, loc.pLoc,
|
||||||
traceManager.getCurrent(), loc.fLoc, loc.field);
|
traceManager.getCurrent(), loc.fLoc, loc.field);
|
||||||
|
|
||||||
assertTable(Map.of(
|
assertTable(Map.of(RowKey.NAME, "Name: y", RowKey.FRAME,
|
||||||
RowKey.NAME, "Name: y",
|
"Frame: 0 fillStruct pc=00400041 sp=00004fe0 base=00004fe0", RowKey.TYPE, "Type: word",
|
||||||
RowKey.FRAME, "Frame: 0 fillStruct pc=00400041 sp=00004fe0 base=00004fe0",
|
RowKey.LOCATION, "Location: 00600000:2", RowKey.BYTES, "Bytes: (KNOWN) e6 07",
|
||||||
RowKey.TYPE, "Type: word",
|
RowKey.INTEGER, "Integer: (KNOWN) 2022, 0x7e6", RowKey.VALUE, "Value: (KNOWN) 7E6h",
|
||||||
RowKey.LOCATION, "Location: 00600000:2",
|
|
||||||
RowKey.BYTES, "Bytes: (KNOWN) e6 07",
|
|
||||||
RowKey.INTEGER, "Integer: (KNOWN) 2022, 0x7e6",
|
|
||||||
RowKey.VALUE, "Value: (KNOWN) 7E6h",
|
|
||||||
RowKey.WARNINGS, "IGNORED"), table);
|
RowKey.WARNINGS, "IGNORED"), table);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1718,14 +1624,10 @@ public class StackUnwinderTest extends AbstractGhidraHeadedDebuggerTest {
|
||||||
VariableValueTable table = getVariableValueTable(valuesService, loc.pLoc,
|
VariableValueTable table = getVariableValueTable(valuesService, loc.pLoc,
|
||||||
traceManager.getCurrent(), loc.fLoc, loc.field);
|
traceManager.getCurrent(), loc.fLoc, loc.field);
|
||||||
|
|
||||||
assertTable(Map.of(
|
assertTable(Map.of(RowKey.NAME, "Name: m", RowKey.FRAME,
|
||||||
RowKey.NAME, "Name: m",
|
"Frame: 0 fillStruct pc=0040002e sp=00004fe0 base=00004fe0", RowKey.TYPE, "Type: byte",
|
||||||
RowKey.FRAME, "Frame: 0 fillStruct pc=0040002e sp=00004fe0 base=00004fe0",
|
RowKey.LOCATION, "Location: 0060000a:1", RowKey.BYTES, "Bytes: (KNOWN) 0c",
|
||||||
RowKey.TYPE, "Type: byte",
|
RowKey.INTEGER, "Integer: (KNOWN) 12, 0xc", RowKey.VALUE, "Value: (KNOWN) Ch",
|
||||||
RowKey.LOCATION, "Location: 0060000a:1",
|
|
||||||
RowKey.BYTES, "Bytes: (KNOWN) 0c",
|
|
||||||
RowKey.INTEGER, "Integer: (KNOWN) 12, 0xc",
|
|
||||||
RowKey.VALUE, "Value: (KNOWN) Ch",
|
|
||||||
RowKey.WARNINGS, "IGNORED"), table);
|
RowKey.WARNINGS, "IGNORED"), table);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,42 +0,0 @@
|
||||||
/* ###
|
|
||||||
* 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 ghidra.framework.cmd;
|
|
||||||
|
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.framework.model.UndoableDomainObject;
|
|
||||||
import ghidra.framework.plugintool.PluginTool;
|
|
||||||
import ghidra.util.task.TaskMonitor;
|
|
||||||
|
|
||||||
public abstract class TypedBackgroundCommand<T extends UndoableDomainObject>
|
|
||||||
extends BackgroundCommand {
|
|
||||||
|
|
||||||
public TypedBackgroundCommand(String name, boolean hasProgress, boolean canCancel,
|
|
||||||
boolean isModal) {
|
|
||||||
super(name, hasProgress, canCancel, isModal);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public boolean applyTo(DomainObject obj, TaskMonitor monitor) {
|
|
||||||
return applyToTyped((T) obj, monitor);
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract boolean applyToTyped(T obj, TaskMonitor monitor);
|
|
||||||
|
|
||||||
public void run(PluginTool tool, T obj) {
|
|
||||||
tool.executeBackgroundCommand(this, obj);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -23,7 +23,6 @@ import ghidra.app.cmd.module.CreateDefaultTreeCmd;
|
||||||
import ghidra.app.plugin.PluginCategoryNames;
|
import ghidra.app.plugin.PluginCategoryNames;
|
||||||
import ghidra.app.plugin.ProgramPlugin;
|
import ghidra.app.plugin.ProgramPlugin;
|
||||||
import ghidra.framework.cmd.BackgroundCommand;
|
import ghidra.framework.cmd.BackgroundCommand;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.framework.plugintool.PluginInfo;
|
import ghidra.framework.plugintool.PluginInfo;
|
||||||
import ghidra.framework.plugintool.PluginTool;
|
import ghidra.framework.plugintool.PluginTool;
|
||||||
import ghidra.framework.plugintool.util.PluginStatus;
|
import ghidra.framework.plugintool.util.PluginStatus;
|
||||||
|
@ -53,7 +52,6 @@ import ghidra.util.task.TaskMonitor;
|
||||||
)
|
)
|
||||||
//@formatter:on
|
//@formatter:on
|
||||||
public class SampleProgramTreePlugin extends ProgramPlugin {
|
public class SampleProgramTreePlugin extends ProgramPlugin {
|
||||||
private Listing listing;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a new SampleProgramTreePlugin.
|
* Construct a new SampleProgramTreePlugin.
|
||||||
|
@ -90,8 +88,7 @@ public class SampleProgramTreePlugin extends ProgramPlugin {
|
||||||
* Method Modularize.
|
* Method Modularize.
|
||||||
*/
|
*/
|
||||||
private void modularize() {
|
private void modularize() {
|
||||||
BackgroundCommand cmd = new ModularizeCommand();
|
ModularizeCommand cmd = new ModularizeCommand();
|
||||||
|
|
||||||
tool.executeBackgroundCommand(cmd, currentProgram);
|
tool.executeBackgroundCommand(cmd, currentProgram);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,7 +96,7 @@ public class SampleProgramTreePlugin extends ProgramPlugin {
|
||||||
* Background command that will create the new tree and organize it.
|
* Background command that will create the new tree and organize it.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
class ModularizeCommand extends BackgroundCommand {
|
static class ModularizeCommand extends BackgroundCommand<Program> {
|
||||||
private int fragment_count = 0;
|
private int fragment_count = 0;
|
||||||
private String programTreeName = "Sample Tree";
|
private String programTreeName = "Sample Tree";
|
||||||
|
|
||||||
|
@ -108,10 +105,9 @@ public class SampleProgramTreePlugin extends ProgramPlugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applyTo(DomainObject obj, TaskMonitor monitor) {
|
public boolean applyTo(Program program, TaskMonitor monitor) {
|
||||||
Program program = (Program) obj;
|
|
||||||
|
|
||||||
listing = program.getListing();
|
Listing listing = program.getListing();
|
||||||
|
|
||||||
createDefaultTreeView(program, programTreeName);
|
createDefaultTreeView(program, programTreeName);
|
||||||
|
|
||||||
|
@ -145,8 +141,8 @@ public class SampleProgramTreePlugin extends ProgramPlugin {
|
||||||
|
|
||||||
monitor.setMessage("Module " + start + " : " + mod_name);
|
monitor.setMessage("Module " + start + " : " + mod_name);
|
||||||
|
|
||||||
ProgramModule mod = make_module(mod_name, frags);
|
ProgramModule mod = make_module(listing, mod_name, frags);
|
||||||
makeFragment(start, end, "frag_" + fragment_count, mod);
|
makeFragment(listing, start, end, "frag_" + fragment_count, mod);
|
||||||
fragment_count++;
|
fragment_count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,24 +152,17 @@ public class SampleProgramTreePlugin extends ProgramPlugin {
|
||||||
private void createDefaultTreeView(Program program, String defaultTreeName) {
|
private void createDefaultTreeView(Program program, String defaultTreeName) {
|
||||||
String treeName = defaultTreeName;
|
String treeName = defaultTreeName;
|
||||||
int oneUp = 1;
|
int oneUp = 1;
|
||||||
|
Listing listing = program.getListing();
|
||||||
while (listing.getRootModule(treeName) != null) {
|
while (listing.getRootModule(treeName) != null) {
|
||||||
treeName = defaultTreeName + "_" + oneUp;
|
treeName = defaultTreeName + "_" + oneUp;
|
||||||
oneUp++;
|
oneUp++;
|
||||||
}
|
}
|
||||||
CreateDefaultTreeCmd cmd = new CreateDefaultTreeCmd(defaultTreeName);
|
CreateDefaultTreeCmd cmd = new CreateDefaultTreeCmd(defaultTreeName);
|
||||||
if (tool.execute(cmd, program)) {
|
cmd.applyTo(program);
|
||||||
tool.setStatusInfo(cmd.getStatusMsg());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private ProgramModule make_module(Listing listing, String moduleName,
|
||||||
* Method make_module.
|
ProgramModule parent) {
|
||||||
* @param start
|
|
||||||
* @param entry_address
|
|
||||||
* @param prev_name
|
|
||||||
* @param code
|
|
||||||
*/
|
|
||||||
private ProgramModule make_module(String moduleName, ProgramModule parent) {
|
|
||||||
String modName = moduleName;
|
String modName = moduleName;
|
||||||
|
|
||||||
int oneUp = 1;
|
int oneUp = 1;
|
||||||
|
@ -183,6 +172,7 @@ public class SampleProgramTreePlugin extends ProgramPlugin {
|
||||||
newMod = parent.createModule(modName);
|
newMod = parent.createModule(modName);
|
||||||
}
|
}
|
||||||
catch (DuplicateNameException e) {
|
catch (DuplicateNameException e) {
|
||||||
|
// ignore
|
||||||
}
|
}
|
||||||
modName = moduleName + "_" + oneUp;
|
modName = moduleName + "_" + oneUp;
|
||||||
oneUp++;
|
oneUp++;
|
||||||
|
@ -190,19 +180,14 @@ public class SampleProgramTreePlugin extends ProgramPlugin {
|
||||||
return newMod;
|
return newMod;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private ProgramFragment makeFragment(Listing listing, Address start, Address end,
|
||||||
* Method make_frag.
|
String fragmentName, ProgramModule parent) {
|
||||||
* @param start
|
|
||||||
* @param entry_address
|
|
||||||
* @param prev_name
|
|
||||||
*/
|
|
||||||
private ProgramFragment makeFragment(Address start, Address end, String fragmentName,
|
|
||||||
ProgramModule parent) {
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
parent.createFragment(fragmentName);
|
parent.createFragment(fragmentName);
|
||||||
}
|
}
|
||||||
catch (DuplicateNameException e) {
|
catch (DuplicateNameException e) {
|
||||||
|
// ignore
|
||||||
}
|
}
|
||||||
ProgramFragment frag = listing.getFragment(programTreeName, fragmentName);
|
ProgramFragment frag = listing.getFragment(programTreeName, fragmentName);
|
||||||
|
|
||||||
|
|
|
@ -15,10 +15,12 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.cmd.analysis;
|
package ghidra.app.cmd.analysis;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import ghidra.app.cmd.disassemble.SetFlowOverrideCmd;
|
import ghidra.app.cmd.disassemble.SetFlowOverrideCmd;
|
||||||
import ghidra.app.plugin.core.analysis.AutoAnalysisManager;
|
import ghidra.app.plugin.core.analysis.AutoAnalysisManager;
|
||||||
import ghidra.framework.cmd.BackgroundCommand;
|
import ghidra.framework.cmd.BackgroundCommand;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.*;
|
||||||
import ghidra.program.model.symbol.*;
|
import ghidra.program.model.symbol.*;
|
||||||
|
@ -26,14 +28,11 @@ import ghidra.util.exception.AssertException;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Identifies functions to which Jump references exist and converts
|
* Identifies functions to which Jump references exist and converts
|
||||||
* the associated branching instruction flow to a CALL-RETURN
|
* the associated branching instruction flow to a CALL-RETURN
|
||||||
*/
|
*/
|
||||||
public class SharedReturnAnalysisCmd extends BackgroundCommand {
|
public class SharedReturnAnalysisCmd extends BackgroundCommand<Program> {
|
||||||
|
|
||||||
private AddressSetView set;
|
private AddressSetView set;
|
||||||
private boolean assumeContiguousFunctions = false;
|
private boolean assumeContiguousFunctions = false;
|
||||||
|
@ -58,9 +57,7 @@ public class SharedReturnAnalysisCmd extends BackgroundCommand {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applyTo(DomainObject obj, TaskMonitor monitor) {
|
public boolean applyTo(Program program, TaskMonitor monitor) {
|
||||||
|
|
||||||
Program program = (Program) obj;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
|
@ -180,8 +177,8 @@ public class SharedReturnAnalysisCmd extends BackgroundCommand {
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we have not passed lastFunctionAfter then no change to lastFunctionBefore
|
// if we have not passed lastFunctionAfter then no change to lastFunctionBefore
|
||||||
if (functionBeforeSrc != null &&
|
if (functionBeforeSrc != null && (functionAfterSrc == Address.NO_ADDRESS ||
|
||||||
(functionAfterSrc == Address.NO_ADDRESS || srcAddr.compareTo(functionAfterSrc) < 0)) {
|
srcAddr.compareTo(functionAfterSrc) < 0)) {
|
||||||
// we have not passed lastFunctionAfterSrc - no change to lastFunctionBeforeSrc
|
// we have not passed lastFunctionAfterSrc - no change to lastFunctionBeforeSrc
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -276,7 +273,7 @@ public class SharedReturnAnalysisCmd extends BackgroundCommand {
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean checkIfCouldHaveFallThruTo(Program program, Address location) {
|
private boolean checkIfCouldHaveFallThruTo(Program program, Address location) {
|
||||||
Instruction instr= program.getListing().getInstructionAt(location);
|
Instruction instr = program.getListing().getInstructionAt(location);
|
||||||
if (instr == null) {
|
if (instr == null) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -342,39 +339,39 @@ public class SharedReturnAnalysisCmd extends BackgroundCommand {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkAllJumpReferences(Program program, TaskMonitor monitor)
|
// private void checkAllJumpReferences(Program program, TaskMonitor monitor)
|
||||||
throws CancelledException {
|
// throws CancelledException {
|
||||||
|
//
|
||||||
SymbolTable symbolTable = program.getSymbolTable();
|
// SymbolTable symbolTable = program.getSymbolTable();
|
||||||
|
//
|
||||||
InstructionIterator instructionIter = program.getListing().getInstructions(set, true);
|
// InstructionIterator instructionIter = program.getListing().getInstructions(set, true);
|
||||||
while (instructionIter.hasNext()) {
|
// while (instructionIter.hasNext()) {
|
||||||
monitor.checkCancelled();
|
// monitor.checkCancelled();
|
||||||
Instruction instr = instructionIter.next();
|
// Instruction instr = instructionIter.next();
|
||||||
FlowType ft = instr.getFlowType();
|
// FlowType ft = instr.getFlowType();
|
||||||
if (!ft.isJump()) {
|
// if (!ft.isJump()) {
|
||||||
continue;
|
// continue;
|
||||||
}
|
// }
|
||||||
Reference ref = getSingleFlowReferenceFrom(instr);
|
// Reference ref = getSingleFlowReferenceFrom(instr);
|
||||||
if (ref == null) {
|
// if (ref == null) {
|
||||||
continue;
|
// continue;
|
||||||
}
|
// }
|
||||||
// if there is a function at this address, this is a thunk
|
// // if there is a function at this address, this is a thunk
|
||||||
// Handle differently
|
// // Handle differently
|
||||||
if (program.getFunctionManager().getFunctionAt(instr.getMinAddress()) != null) {
|
// if (program.getFunctionManager().getFunctionAt(instr.getMinAddress()) != null) {
|
||||||
continue;
|
// continue;
|
||||||
}
|
// }
|
||||||
Symbol s = symbolTable.getPrimarySymbol(ref.getToAddress());
|
// Symbol s = symbolTable.getPrimarySymbol(ref.getToAddress());
|
||||||
if (s != null && s.getSymbolType() == SymbolType.FUNCTION) {
|
// if (s != null && s.getSymbolType() == SymbolType.FUNCTION) {
|
||||||
if (instr.getFlowOverride() != FlowOverride.NONE) {
|
// if (instr.getFlowOverride() != FlowOverride.NONE) {
|
||||||
continue;
|
// continue;
|
||||||
}
|
// }
|
||||||
SetFlowOverrideCmd cmd =
|
// SetFlowOverrideCmd cmd =
|
||||||
new SetFlowOverrideCmd(instr.getMinAddress(), FlowOverride.CALL_RETURN);
|
// new SetFlowOverrideCmd(instr.getMinAddress(), FlowOverride.CALL_RETURN);
|
||||||
cmd.applyTo(program);
|
// cmd.applyTo(program);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
private void processFunctionJumpReferences(Program program, Address entry, TaskMonitor monitor)
|
private void processFunctionJumpReferences(Program program, Address entry, TaskMonitor monitor)
|
||||||
throws CancelledException {
|
throws CancelledException {
|
||||||
|
|
|
@ -16,14 +16,13 @@
|
||||||
package ghidra.app.cmd.comments;
|
package ghidra.app.cmd.comments;
|
||||||
|
|
||||||
import ghidra.framework.cmd.Command;
|
import ghidra.framework.cmd.Command;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Command to append a specific type of comment on a code unit.
|
* Command to append a specific type of comment on a code unit.
|
||||||
*/
|
*/
|
||||||
public class AppendCommentCmd implements Command {
|
public class AppendCommentCmd implements Command<Program> {
|
||||||
|
|
||||||
private Address address;
|
private Address address;
|
||||||
private int commentType;
|
private int commentType;
|
||||||
|
@ -49,23 +48,16 @@ public class AppendCommentCmd implements Command {
|
||||||
cmdName = "Append Comment";
|
cmdName = "Append Comment";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.framework.cmd.Command#getName()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return cmdName;
|
return cmdName;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.framework.cmd.Command#applyTo(ghidra.framework.model.DomainObject)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applyTo(DomainObject obj) {
|
public boolean applyTo(Program program) {
|
||||||
CodeUnit cu = getCodeUnit((Program) obj);
|
CodeUnit cu = getCodeUnit(program);
|
||||||
if (cu == null) {
|
if (cu == null) {
|
||||||
message =
|
message = "No Instruction or Data found for address " + address.toString() +
|
||||||
"No Instruction or Data found for address " + address.toString() +
|
|
||||||
" Is this address valid?";
|
" Is this address valid?";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -95,9 +87,6 @@ public class AppendCommentCmd implements Command {
|
||||||
return cu;
|
return cu;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.framework.cmd.Command#getStatusMsg()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public String getStatusMsg() {
|
public String getStatusMsg() {
|
||||||
return message;
|
return message;
|
||||||
|
|
|
@ -20,7 +20,6 @@ import java.util.List;
|
||||||
|
|
||||||
import ghidra.app.util.CodeUnitInfo;
|
import ghidra.app.util.CodeUnitInfo;
|
||||||
import ghidra.framework.cmd.Command;
|
import ghidra.framework.cmd.Command;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.*;
|
||||||
import ghidra.program.model.pcode.Varnode;
|
import ghidra.program.model.pcode.Varnode;
|
||||||
|
@ -33,7 +32,7 @@ import ghidra.util.exception.InvalidInputException;
|
||||||
* Undoable edit for pasting code unit information at a location.
|
* Undoable edit for pasting code unit information at a location.
|
||||||
* This class actually does the work of the "paste."
|
* This class actually does the work of the "paste."
|
||||||
*/
|
*/
|
||||||
public class CodeUnitInfoPasteCmd implements Command {
|
public class CodeUnitInfoPasteCmd implements Command<Program> {
|
||||||
|
|
||||||
// TODO: should refactor to handle all variables in a consistent fashion
|
// TODO: should refactor to handle all variables in a consistent fashion
|
||||||
|
|
||||||
|
@ -48,6 +47,8 @@ public class CodeUnitInfoPasteCmd implements Command {
|
||||||
* Creates a new command for pasting comments/labels.
|
* Creates a new command for pasting comments/labels.
|
||||||
* @param startAddr starting address for info
|
* @param startAddr starting address for info
|
||||||
* @param infoList list of CodeUnitInfo objects that will be applied
|
* @param infoList list of CodeUnitInfo objects that will be applied
|
||||||
|
* @param pasteLabels true if labels should be applied, else false
|
||||||
|
* @param pasteComments true if comments should be applied, else false
|
||||||
*/
|
*/
|
||||||
public CodeUnitInfoPasteCmd(Address startAddr, List<CodeUnitInfo> infoList, boolean pasteLabels,
|
public CodeUnitInfoPasteCmd(Address startAddr, List<CodeUnitInfo> infoList, boolean pasteLabels,
|
||||||
boolean pasteComments) {
|
boolean pasteComments) {
|
||||||
|
@ -65,19 +66,14 @@ public class CodeUnitInfoPasteCmd implements Command {
|
||||||
return "Paste Labels/Comments";
|
return "Paste Labels/Comments";
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see ghidra.framework.cmd.Command#applyTo(ghidra.framework.model.DomainObject)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applyTo(DomainObject obj) {
|
public boolean applyTo(Program program) {
|
||||||
|
|
||||||
Program program = (Program) obj;
|
|
||||||
SymbolTable symTable = program.getSymbolTable();
|
SymbolTable symTable = program.getSymbolTable();
|
||||||
Listing listing = program.getListing();
|
Listing listing = program.getListing();
|
||||||
boolean offCutExists = false;
|
boolean offCutExists = false;
|
||||||
|
|
||||||
for (int i = 0; i < infoList.size(); i++) {
|
for (CodeUnitInfo info : infoList) {
|
||||||
CodeUnitInfo info = infoList.get(i);
|
|
||||||
Address a = startAddr.add(info.getIndex());
|
Address a = startAddr.add(info.getIndex());
|
||||||
CodeUnit cu = listing.getCodeUnitAt(a);
|
CodeUnit cu = listing.getCodeUnitAt(a);
|
||||||
if (cu == null) {
|
if (cu == null) {
|
||||||
|
@ -133,8 +129,8 @@ public class CodeUnitInfoPasteCmd implements Command {
|
||||||
function.setName(fnName, info.getPrimarySymbolSource());
|
function.setName(fnName, info.getPrimarySymbolSource());
|
||||||
}
|
}
|
||||||
catch (DuplicateNameException e) {
|
catch (DuplicateNameException e) {
|
||||||
messages.append("Could not set function name--duplicate name: " + fnName).append(
|
messages.append("Could not set function name--duplicate name: " + fnName)
|
||||||
'\n');
|
.append('\n');
|
||||||
}
|
}
|
||||||
catch (InvalidInputException e) {
|
catch (InvalidInputException e) {
|
||||||
// shouldn't happen
|
// shouldn't happen
|
||||||
|
@ -175,8 +171,8 @@ public class CodeUnitInfoPasteCmd implements Command {
|
||||||
}
|
}
|
||||||
catch (DuplicateNameException e) {
|
catch (DuplicateNameException e) {
|
||||||
messages.append(
|
messages.append(
|
||||||
"Could not set stack variable name--duplicate name: " + fnName).append(
|
"Could not set stack variable name--duplicate name: " + fnName)
|
||||||
'\n');
|
.append('\n');
|
||||||
}
|
}
|
||||||
catch (InvalidInputException e) {
|
catch (InvalidInputException e) {
|
||||||
// shouldn't happen
|
// shouldn't happen
|
||||||
|
@ -204,8 +200,8 @@ public class CodeUnitInfoPasteCmd implements Command {
|
||||||
var.setName(varNames[i], varSources[i]);
|
var.setName(varNames[i], varSources[i]);
|
||||||
}
|
}
|
||||||
catch (DuplicateNameException e) {
|
catch (DuplicateNameException e) {
|
||||||
messages.append(
|
messages.append("Could not set variable name--duplicate name: " + fnName)
|
||||||
"Could not set variable name--duplicate name: " + fnName).append('\n');
|
.append('\n');
|
||||||
}
|
}
|
||||||
catch (InvalidInputException e) {
|
catch (InvalidInputException e) {
|
||||||
// shouldn't happen
|
// shouldn't happen
|
||||||
|
@ -219,8 +215,7 @@ public class CodeUnitInfoPasteCmd implements Command {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Variable findStackVar(Variable[] stackVars, int stackOffset, int firstUseOffset) {
|
private Variable findStackVar(Variable[] stackVars, int stackOffset, int firstUseOffset) {
|
||||||
for (int k = 0; k < stackVars.length; k++) {
|
for (Variable var : stackVars) {
|
||||||
Variable var = stackVars[k];
|
|
||||||
if (stackOffset == var.getStackOffset() && firstUseOffset == var.getFirstUseOffset()) {
|
if (stackOffset == var.getStackOffset() && firstUseOffset == var.getFirstUseOffset()) {
|
||||||
return var;
|
return var;
|
||||||
}
|
}
|
||||||
|
@ -229,8 +224,7 @@ public class CodeUnitInfoPasteCmd implements Command {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Variable findVar(Variable[] vars, Address storageAddr, int firstUseOffset) {
|
private Variable findVar(Variable[] vars, Address storageAddr, int firstUseOffset) {
|
||||||
for (int k = 0; k < vars.length; k++) {
|
for (Variable var : vars) {
|
||||||
Variable var = vars[k];
|
|
||||||
Varnode varnode = var.getVariableStorage().getFirstVarnode();
|
Varnode varnode = var.getVariableStorage().getFirstVarnode();
|
||||||
if (varnode != null && firstUseOffset == var.getFirstUseOffset() &&
|
if (varnode != null && firstUseOffset == var.getFirstUseOffset() &&
|
||||||
storageAddr.equals(varnode.getAddress())) {
|
storageAddr.equals(varnode.getAddress())) {
|
||||||
|
@ -277,8 +271,8 @@ public class CodeUnitInfoPasteCmd implements Command {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (DuplicateNameException e) {
|
catch (DuplicateNameException e) {
|
||||||
messages.append("Could not set label name--duplicate name: " + primaryName).append(
|
messages.append("Could not set label name--duplicate name: " + primaryName)
|
||||||
'\n');
|
.append('\n');
|
||||||
}
|
}
|
||||||
catch (InvalidInputException e) {
|
catch (InvalidInputException e) {
|
||||||
// should not happen
|
// should not happen
|
||||||
|
@ -359,12 +353,12 @@ public class CodeUnitInfoPasteCmd implements Command {
|
||||||
private String[] appendComment(String[] comment1, String[] comment2) {
|
private String[] appendComment(String[] comment1, String[] comment2) {
|
||||||
// first check for duplicate comments
|
// first check for duplicate comments
|
||||||
ArrayList<String> list = new ArrayList<String>();
|
ArrayList<String> list = new ArrayList<String>();
|
||||||
for (int i = 0; i < comment2.length; i++) {
|
for (String element : comment2) {
|
||||||
list.add(comment2[i]);
|
list.add(element);
|
||||||
}
|
}
|
||||||
for (int i = 0; i < comment1.length; i++) {
|
for (String element : comment1) {
|
||||||
for (int j = 0; j < list.size(); j++) {
|
for (int j = 0; j < list.size(); j++) {
|
||||||
if (comment1[i].equals(list.get(j))) {
|
if (element.equals(list.get(j))) {
|
||||||
list.remove(j);
|
list.remove(j);
|
||||||
--j;
|
--j;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,14 +17,13 @@ package ghidra.app.cmd.comments;
|
||||||
|
|
||||||
import ghidra.app.util.viewer.field.CommentUtils;
|
import ghidra.app.util.viewer.field.CommentUtils;
|
||||||
import ghidra.framework.cmd.Command;
|
import ghidra.framework.cmd.Command;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Command to set a specific type of comment on a code unit.
|
* Command to set a specific type of comment on a code unit.
|
||||||
*/
|
*/
|
||||||
public class SetCommentCmd implements Command {
|
public class SetCommentCmd implements Command<Program> {
|
||||||
|
|
||||||
private Address address;
|
private Address address;
|
||||||
private int commentType;
|
private int commentType;
|
||||||
|
@ -67,8 +66,7 @@ public class SetCommentCmd implements Command {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applyTo(DomainObject obj) {
|
public boolean applyTo(Program program) {
|
||||||
Program program = (Program) obj;
|
|
||||||
CodeUnit cu = getCodeUnit(program);
|
CodeUnit cu = getCodeUnit(program);
|
||||||
if (cu == null) {
|
if (cu == null) {
|
||||||
message = "No Instruction or Data found for address " + address.toString() +
|
message = "No Instruction or Data found for address " + address.toString() +
|
||||||
|
|
|
@ -17,14 +17,13 @@ package ghidra.app.cmd.comments;
|
||||||
|
|
||||||
import ghidra.app.util.viewer.field.CommentUtils;
|
import ghidra.app.util.viewer.field.CommentUtils;
|
||||||
import ghidra.framework.cmd.Command;
|
import ghidra.framework.cmd.Command;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Command for editing and removing comments at an address.
|
* Command for editing and removing comments at an address.
|
||||||
*/
|
*/
|
||||||
public class SetCommentsCmd implements Command {
|
public class SetCommentsCmd implements Command<Program> {
|
||||||
|
|
||||||
private Address address;
|
private Address address;
|
||||||
private String preComment;
|
private String preComment;
|
||||||
|
@ -79,13 +78,8 @@ public class SetCommentsCmd implements Command {
|
||||||
return !oldValue.equals(newValue);
|
return !oldValue.equals(newValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see ghidra.framework.cmd.Command#applyTo(ghidra.framework.model.DomainObject)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applyTo(DomainObject obj) {
|
public boolean applyTo(Program program) {
|
||||||
Program program = (Program) obj;
|
|
||||||
CodeUnit cu = getCodeUnit(program);
|
CodeUnit cu = getCodeUnit(program);
|
||||||
|
|
||||||
if (cu != null) {
|
if (cu != null) {
|
||||||
|
@ -138,9 +132,6 @@ public class SetCommentsCmd implements Command {
|
||||||
return cu;
|
return cu;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.framework.cmd.Command#getStatusMsg()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public String getStatusMsg() {
|
public String getStatusMsg() {
|
||||||
return msg;
|
return msg;
|
||||||
|
|
|
@ -16,8 +16,6 @@
|
||||||
package ghidra.app.cmd.data;
|
package ghidra.app.cmd.data;
|
||||||
|
|
||||||
import ghidra.framework.cmd.Command;
|
import ghidra.framework.cmd.Command;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.data.DataType;
|
import ghidra.program.model.data.DataType;
|
||||||
import ghidra.program.model.data.Structure;
|
import ghidra.program.model.data.Structure;
|
||||||
|
@ -26,13 +24,10 @@ import ghidra.program.model.listing.Program;
|
||||||
/**
|
/**
|
||||||
* A base class to hold duplicate information for commands that create
|
* A base class to hold duplicate information for commands that create
|
||||||
* structures. This class implements the logic of the
|
* structures. This class implements the logic of the
|
||||||
* {@link #applyTo(DomainObject)} method so that child implementations need
|
* {@link #applyTo(Program)} method so that child implementations need
|
||||||
* only to implement the abstract methods.
|
* only to implement the abstract methods.
|
||||||
*
|
|
||||||
*
|
|
||||||
* @since Tracker Id 383
|
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractCreateStructureCmd implements Command {
|
public abstract class AbstractCreateStructureCmd implements Command<Program> {
|
||||||
|
|
||||||
private String statusMessage;
|
private String statusMessage;
|
||||||
private String structureName;
|
private String structureName;
|
||||||
|
@ -41,34 +36,24 @@ public abstract class AbstractCreateStructureCmd implements Command {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the this class to create a structure with the given name
|
* Initializes the this class to create a structure with the given name
|
||||||
* and address when the {@link #applyTo(DomainObject)} is called.
|
* and address when the {@link #applyTo(Program)} is called.
|
||||||
*
|
*
|
||||||
* @param name The name of the structure to create.
|
* @param name The name of the structure to create.
|
||||||
* @param address The address of the structure.
|
* @param address The address of the structure.
|
||||||
*/
|
*/
|
||||||
/*package*/ AbstractCreateStructureCmd( String name, Address address ){
|
/*package*/ AbstractCreateStructureCmd(String name, Address address) {
|
||||||
structureAddress = address;
|
structureAddress = address;
|
||||||
structureName = name;
|
structureName = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Applies this command to the given domain object.
|
public boolean applyTo(Program program) {
|
||||||
* <p>
|
|
||||||
* This method is a Form Template method in that child subclasses do not
|
|
||||||
* need to override the method, but only need to implement the methods
|
|
||||||
* that this method calls.
|
|
||||||
*
|
|
||||||
* @param domainObject The domain object that is associated with this
|
|
||||||
* command
|
|
||||||
* @see Command#applyTo(DomainObject)
|
|
||||||
*/
|
|
||||||
public boolean applyTo(DomainObject domainObject) {
|
|
||||||
try {
|
try {
|
||||||
Program program = (Program) domainObject;
|
Structure structure = createStructure(structureAddress, program);
|
||||||
Structure structure = createStructure( structureAddress, program );
|
setNewDataType(initializeStructureData(program, structure));
|
||||||
setNewDataType( initializeStructureData( program, structure ) );
|
}
|
||||||
} catch (IllegalArgumentException iae) {
|
catch (IllegalArgumentException iae) {
|
||||||
setStatusMsg( iae.getMessage() );
|
setStatusMsg(iae.getMessage());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,8 +71,7 @@ public abstract class AbstractCreateStructureCmd implements Command {
|
||||||
* @throws IllegalArgumentException If the data at the given address is
|
* @throws IllegalArgumentException If the data at the given address is
|
||||||
* not valid for creating a structure.
|
* not valid for creating a structure.
|
||||||
*/
|
*/
|
||||||
/*package*/ abstract Structure createStructure( Address address,
|
/*package*/ abstract Structure createStructure(Address address, Program program)
|
||||||
Program program )
|
|
||||||
throws IllegalArgumentException;
|
throws IllegalArgumentException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -96,19 +80,19 @@ public abstract class AbstractCreateStructureCmd implements Command {
|
||||||
* structure with data and then returning the data type object that
|
* structure with data and then returning the data type object that
|
||||||
* represents the newly created structure.
|
* represents the newly created structure.
|
||||||
*
|
*
|
||||||
* @param structureInfo The structure info object that describes the newly
|
* @param program program to be modified
|
||||||
|
* @param structure The structure definition that describes the newly
|
||||||
* created structure.
|
* created structure.
|
||||||
* @return The new data type that represents the created structure.
|
* @return The new data type that represents the created structure.
|
||||||
*/
|
*/
|
||||||
/*package*/ abstract DataType initializeStructureData(
|
/*package*/ abstract DataType initializeStructureData(Program program, Structure structure);
|
||||||
Program program, Structure structure );
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the new data type of this command.
|
* Sets the new data type of this command.
|
||||||
*
|
*
|
||||||
* @param dataType The new data type.
|
* @param dataType The new data type.
|
||||||
*/
|
*/
|
||||||
/*package*/ void setNewDataType( DataType dataType ){
|
/*package*/ void setNewDataType(DataType dataType) {
|
||||||
newDataType = dataType;
|
newDataType = dataType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,7 +104,7 @@ public abstract class AbstractCreateStructureCmd implements Command {
|
||||||
return newDataType;
|
return newDataType;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*package*/ Address getStructureAddress(){
|
/*package*/ Address getStructureAddress() {
|
||||||
return structureAddress;
|
return structureAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,25 +113,21 @@ public abstract class AbstractCreateStructureCmd implements Command {
|
||||||
*
|
*
|
||||||
* @param message The value of the command.
|
* @param message The value of the command.
|
||||||
*/
|
*/
|
||||||
/*package*/ void setStatusMsg( String message ){
|
/*package*/ void setStatusMsg(String message) {
|
||||||
statusMessage = message;
|
statusMessage = message;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* @see ghidra.framework.cmd.Command#getStatusMsg()
|
public String getStatusMsg() {
|
||||||
*/
|
|
||||||
public String getStatusMsg(){
|
|
||||||
return statusMessage;
|
return statusMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*package*/ String getStructureName(){
|
/*package*/ String getStructureName() {
|
||||||
return structureName;
|
return structureName;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* @see ghidra.framework.cmd.Command#getName()
|
public String getName() {
|
||||||
*/
|
|
||||||
public String getName(){
|
|
||||||
return "Create Structure";
|
return "Create Structure";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
package ghidra.app.cmd.data;
|
package ghidra.app.cmd.data;
|
||||||
|
|
||||||
import ghidra.framework.cmd.Command;
|
import ghidra.framework.cmd.Command;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.data.*;
|
import ghidra.program.model.data.*;
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.*;
|
||||||
|
@ -27,7 +26,7 @@ import ghidra.util.Msg;
|
||||||
* Command to create an array. All conflicting data will be cleared.
|
* Command to create an array. All conflicting data will be cleared.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class CreateArrayCmd implements Command {
|
public class CreateArrayCmd implements Command<Program> {
|
||||||
private String msg;
|
private String msg;
|
||||||
private Address addr;
|
private Address addr;
|
||||||
private int numElements;
|
private int numElements;
|
||||||
|
@ -51,8 +50,7 @@ public class CreateArrayCmd implements Command {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applyTo(DomainObject obj) {
|
public boolean applyTo(Program program) {
|
||||||
Program program = (Program)obj;
|
|
||||||
Listing listing = program.getListing();
|
Listing listing = program.getListing();
|
||||||
try {
|
try {
|
||||||
ArrayDataType adt = new ArrayDataType(dataType, numElements, elementLength,
|
ArrayDataType adt = new ArrayDataType(dataType, numElements, elementLength,
|
||||||
|
@ -68,7 +66,8 @@ public class CreateArrayCmd implements Command {
|
||||||
}
|
}
|
||||||
listing.clearCodeUnits(addr, endAddr, false);
|
listing.clearCodeUnits(addr, endAddr, false);
|
||||||
listing.createData(addr, adt, adt.getLength());
|
listing.createData(addr, adt, adt.getLength());
|
||||||
} catch (AddressOverflowException e1) {
|
}
|
||||||
|
catch (AddressOverflowException e1) {
|
||||||
msg = "Can't create data because length exceeds address space";
|
msg = "Can't create data because length exceeds address space";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
package ghidra.app.cmd.data;
|
package ghidra.app.cmd.data;
|
||||||
|
|
||||||
import ghidra.framework.cmd.Command;
|
import ghidra.framework.cmd.Command;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.data.*;
|
import ghidra.program.model.data.*;
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.*;
|
||||||
|
@ -27,7 +26,7 @@ import ghidra.util.Msg;
|
||||||
* within the targeted structure will be replaced with the new array component.
|
* within the targeted structure will be replaced with the new array component.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class CreateArrayInStructureCmd implements Command {
|
public class CreateArrayInStructureCmd implements Command<Program> {
|
||||||
private String msg;
|
private String msg;
|
||||||
private Address addr;
|
private Address addr;
|
||||||
private int numElements;
|
private int numElements;
|
||||||
|
@ -50,8 +49,7 @@ public class CreateArrayInStructureCmd implements Command {
|
||||||
* the array should be created. The component path is an array of integers where each integer
|
* the array should be created. The component path is an array of integers where each integer
|
||||||
* is a component index of the component above it.
|
* is a component index of the component above it.
|
||||||
*/
|
*/
|
||||||
public CreateArrayInStructureCmd(Address addr, int numElements, DataType dt,
|
public CreateArrayInStructureCmd(Address addr, int numElements, DataType dt, int[] compPath) {
|
||||||
int[] compPath) {
|
|
||||||
this.addr = addr;
|
this.addr = addr;
|
||||||
this.numElements = numElements;
|
this.numElements = numElements;
|
||||||
this.dataType = dt;
|
this.dataType = dt;
|
||||||
|
@ -59,8 +57,7 @@ public class CreateArrayInStructureCmd implements Command {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applyTo(DomainObject obj) {
|
public boolean applyTo(Program program) {
|
||||||
Program program = (Program)obj;
|
|
||||||
Listing listing = program.getListing();
|
Listing listing = program.getListing();
|
||||||
|
|
||||||
Data data = listing.getDataContaining(addr);
|
Data data = listing.getDataContaining(addr);
|
||||||
|
@ -78,7 +75,7 @@ public class CreateArrayInStructureCmd implements Command {
|
||||||
msg = "Data not in a structure";
|
msg = "Data not in a structure";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Structure struct = (Structure)parentDataType;
|
Structure struct = (Structure) parentDataType;
|
||||||
|
|
||||||
DataType baseDt = dataType;
|
DataType baseDt = dataType;
|
||||||
if (dataType instanceof TypeDef) {
|
if (dataType instanceof TypeDef) {
|
||||||
|
@ -114,8 +111,8 @@ public class CreateArrayInStructureCmd implements Command {
|
||||||
|
|
||||||
private void clearStruct(Structure struct, int offset, int length) {
|
private void clearStruct(Structure struct, int offset, int length) {
|
||||||
DataTypeComponent[] comps = struct.getDefinedComponents();
|
DataTypeComponent[] comps = struct.getDefinedComponents();
|
||||||
int endOffset = offset+length;
|
int endOffset = offset + length;
|
||||||
for(int i=comps.length-1;i>=0;i--) {
|
for (int i = comps.length - 1; i >= 0; i--) {
|
||||||
if (comps[i].getOffset() >= offset && comps[i].getOffset() < endOffset) {
|
if (comps[i].getOffset() >= offset && comps[i].getOffset() < endOffset) {
|
||||||
struct.clearComponent(comps[i].getOrdinal());
|
struct.clearComponent(comps[i].getOrdinal());
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
package ghidra.app.cmd.data;
|
package ghidra.app.cmd.data;
|
||||||
|
|
||||||
import ghidra.framework.cmd.BackgroundCommand;
|
import ghidra.framework.cmd.BackgroundCommand;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.data.DataType;
|
import ghidra.program.model.data.DataType;
|
||||||
import ghidra.program.model.data.DataUtilities;
|
import ghidra.program.model.data.DataUtilities;
|
||||||
|
@ -37,8 +36,7 @@ import ghidra.util.task.TaskMonitor;
|
||||||
* of a pointer, then a pointer to dataType will only be created if there are
|
* of a pointer, then a pointer to dataType will only be created if there are
|
||||||
* enough undefined bytes following to make a pointer.
|
* enough undefined bytes following to make a pointer.
|
||||||
*/
|
*/
|
||||||
public class CreateDataBackgroundCmd extends BackgroundCommand {
|
public class CreateDataBackgroundCmd extends BackgroundCommand<Program> {
|
||||||
private static final int EVENT_LIMIT = 1000;
|
|
||||||
|
|
||||||
private AddressSetView addrSet;
|
private AddressSetView addrSet;
|
||||||
private DataType newDataType;
|
private DataType newDataType;
|
||||||
|
@ -76,12 +74,7 @@ public class CreateDataBackgroundCmd extends BackgroundCommand {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applyTo(DomainObject obj, TaskMonitor monitor) {
|
public boolean applyTo(Program program, TaskMonitor monitor) {
|
||||||
return doApplyTo(obj, monitor);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean doApplyTo(DomainObject obj, TaskMonitor monitor) {
|
|
||||||
Program program = (Program) obj;
|
|
||||||
Listing listing = program.getListing();
|
Listing listing = program.getListing();
|
||||||
InstructionIterator iter = listing.getInstructions(addrSet, true);
|
InstructionIterator iter = listing.getInstructions(addrSet, true);
|
||||||
if (iter.hasNext()) {
|
if (iter.hasNext()) {
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
package ghidra.app.cmd.data;
|
package ghidra.app.cmd.data;
|
||||||
|
|
||||||
import ghidra.framework.cmd.Command;
|
import ghidra.framework.cmd.Command;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.data.DataType;
|
import ghidra.program.model.data.DataType;
|
||||||
import ghidra.program.model.data.DataUtilities;
|
import ghidra.program.model.data.DataUtilities;
|
||||||
|
@ -33,7 +32,7 @@ import ghidra.program.model.listing.Program;
|
||||||
*
|
*
|
||||||
* @see DataUtilities#createData(Program, Address, DataType, int, boolean, DataUtilities.ClearDataMode)
|
* @see DataUtilities#createData(Program, Address, DataType, int, boolean, DataUtilities.ClearDataMode)
|
||||||
*/
|
*/
|
||||||
public class CreateDataCmd implements Command {
|
public class CreateDataCmd implements Command<Program> {
|
||||||
|
|
||||||
private Address addr;
|
private Address addr;
|
||||||
private DataType newDataType;
|
private DataType newDataType;
|
||||||
|
@ -119,10 +118,9 @@ public class CreateDataCmd implements Command {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applyTo(DomainObject obj) {
|
public boolean applyTo(Program program) {
|
||||||
try {
|
try {
|
||||||
DataUtilities.createData((Program) obj, addr, newDataType, -1, stackPointers,
|
DataUtilities.createData(program, addr, newDataType, -1, stackPointers, clearMode);
|
||||||
clearMode);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
package ghidra.app.cmd.data;
|
package ghidra.app.cmd.data;
|
||||||
|
|
||||||
import ghidra.framework.cmd.BackgroundCommand;
|
import ghidra.framework.cmd.BackgroundCommand;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.data.*;
|
import ghidra.program.model.data.*;
|
||||||
import ghidra.program.model.listing.Data;
|
import ghidra.program.model.listing.Data;
|
||||||
|
@ -28,7 +27,7 @@ import ghidra.util.task.TaskMonitor;
|
||||||
* Background command to create data across a selection inside of a structure.
|
* Background command to create data across a selection inside of a structure.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class CreateDataInStructureBackgroundCmd extends BackgroundCommand {
|
public class CreateDataInStructureBackgroundCmd extends BackgroundCommand<Program> {
|
||||||
|
|
||||||
// TODO: Not sure any of this will work for a packed structure which does not support
|
// TODO: Not sure any of this will work for a packed structure which does not support
|
||||||
// offset-based component manipulation (see GP-3740)
|
// offset-based component manipulation (see GP-3740)
|
||||||
|
@ -81,9 +80,8 @@ public class CreateDataInStructureBackgroundCmd extends BackgroundCommand {
|
||||||
* @see ghidra.framework.cmd.BackgroundCommand#applyTo(ghidra.framework.model.DomainObject, ghidra.util.task.TaskMonitor)
|
* @see ghidra.framework.cmd.BackgroundCommand#applyTo(ghidra.framework.model.DomainObject, ghidra.util.task.TaskMonitor)
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean applyTo(DomainObject obj, TaskMonitor monitor) {
|
public boolean applyTo(Program program, TaskMonitor monitor) {
|
||||||
|
|
||||||
Program program = (Program) obj;
|
|
||||||
Data data = program.getListing().getDefinedDataContaining(addr);
|
Data data = program.getListing().getDefinedDataContaining(addr);
|
||||||
Data startData = data.getComponent(startPath);
|
Data startData = data.getComponent(startPath);
|
||||||
if (startData == null) {
|
if (startData == null) {
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
package ghidra.app.cmd.data;
|
package ghidra.app.cmd.data;
|
||||||
|
|
||||||
import ghidra.framework.cmd.Command;
|
import ghidra.framework.cmd.Command;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.data.*;
|
import ghidra.program.model.data.*;
|
||||||
import ghidra.program.model.listing.Data;
|
import ghidra.program.model.listing.Data;
|
||||||
|
@ -25,7 +24,7 @@ import ghidra.program.model.listing.Program;
|
||||||
/**
|
/**
|
||||||
* Command to Create data inside of a structure.
|
* Command to Create data inside of a structure.
|
||||||
*/
|
*/
|
||||||
public class CreateDataInStructureCmd implements Command {
|
public class CreateDataInStructureCmd implements Command<Program> {
|
||||||
|
|
||||||
// TODO: Not sure any of this will work for a packed structure which does not support
|
// TODO: Not sure any of this will work for a packed structure which does not support
|
||||||
// offset-based component manipulation (see GP-3740)
|
// offset-based component manipulation (see GP-3740)
|
||||||
|
@ -69,12 +68,8 @@ public class CreateDataInStructureCmd implements Command {
|
||||||
this.stackPointers = stackPointers;
|
this.stackPointers = stackPointers;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.framework.cmd.Command#applyTo(ghidra.framework.model.DomainObject)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applyTo(DomainObject obj) {
|
public boolean applyTo(Program program) {
|
||||||
Program program = (Program) obj;
|
|
||||||
Data data = program.getListing().getDefinedDataContaining(addr);
|
Data data = program.getListing().getDefinedDataContaining(addr);
|
||||||
Data dataComp = data.getComponent(componentPath);
|
Data dataComp = data.getComponent(componentPath);
|
||||||
if (dataComp == null) {
|
if (dataComp == null) {
|
||||||
|
@ -142,17 +137,11 @@ public class CreateDataInStructureCmd implements Command {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.framework.cmd.Command#getStatusMsg()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public String getStatusMsg() {
|
public String getStatusMsg() {
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.framework.cmd.Command#getName()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "Create " + newDataType.getDisplayName() + " component";
|
return "Create " + newDataType.getDisplayName() + " component";
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
package ghidra.app.cmd.data;
|
package ghidra.app.cmd.data;
|
||||||
|
|
||||||
import ghidra.framework.cmd.Command;
|
import ghidra.framework.cmd.Command;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.data.*;
|
import ghidra.program.model.data.*;
|
||||||
import ghidra.program.model.data.DataUtilities.ClearDataMode;
|
import ghidra.program.model.data.DataUtilities.ClearDataMode;
|
||||||
|
@ -27,7 +26,7 @@ import ghidra.program.model.util.CodeUnitInsertionException;
|
||||||
* Command to create a String and optionally label it.
|
* Command to create a String and optionally label it.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class CreateStringCmd implements Command {
|
public class CreateStringCmd implements Command<Program> {
|
||||||
private final Address addr;
|
private final Address addr;
|
||||||
private final AbstractStringDataType stringDataType;
|
private final AbstractStringDataType stringDataType;
|
||||||
private int length = -1;
|
private int length = -1;
|
||||||
|
@ -39,6 +38,14 @@ public class CreateStringCmd implements Command {
|
||||||
: (length > 0) ? new StringDataType() : new TerminatedStringDataType();
|
: (length > 0) ? new StringDataType() : new TerminatedStringDataType();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct command for creating string Data
|
||||||
|
* @param addr address where string should be created.
|
||||||
|
* @param stringDataType string datatype
|
||||||
|
* @param length maximum string length (treatment is specific to specified datatype).
|
||||||
|
* @param clearMode {@link ClearDataMode} which indicates how existing Data conflicts
|
||||||
|
* should be handled.
|
||||||
|
*/
|
||||||
public CreateStringCmd(Address addr, AbstractStringDataType stringDataType, int length,
|
public CreateStringCmd(Address addr, AbstractStringDataType stringDataType, int length,
|
||||||
ClearDataMode clearMode) {
|
ClearDataMode clearMode) {
|
||||||
this.addr = addr;
|
this.addr = addr;
|
||||||
|
@ -48,41 +55,49 @@ public class CreateStringCmd implements Command {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new command for creating strings.
|
* Construct command for creating fixed-length ASCII or Unicode string Data
|
||||||
|
* @param addr address where string should be created.
|
||||||
|
* @param length byte-length of string
|
||||||
|
* @param unicode if true Unicode string will be created, else ASCII
|
||||||
|
* @param clearMode {@link ClearDataMode} which indicates how existing Data conflicts
|
||||||
|
* should be handled.
|
||||||
*/
|
*/
|
||||||
public CreateStringCmd(Address addr, int length, boolean unicode, ClearDataMode clearMode) {
|
public CreateStringCmd(Address addr, int length, boolean unicode, ClearDataMode clearMode) {
|
||||||
this(addr, getStringDataType(unicode, length), length, clearMode);
|
this(addr, getStringDataType(unicode, length), length, clearMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new command for creating strings.
|
* Construct command for creating fixed-length ASCII or Unicode string Data.
|
||||||
|
* Current Data at addr will be cleared if it already exists.
|
||||||
|
* @param addr address where string should be created.
|
||||||
|
* @param length byte-length of string
|
||||||
|
* @param unicode if true Unicode string will be created, else ASCII
|
||||||
*/
|
*/
|
||||||
public CreateStringCmd(Address addr, int length, boolean unicode) {
|
public CreateStringCmd(Address addr, int length, boolean unicode) {
|
||||||
this(addr, getStringDataType(unicode, length), length, ClearDataMode.CLEAR_SINGLE_DATA);
|
this(addr, getStringDataType(unicode, length), length, ClearDataMode.CLEAR_SINGLE_DATA);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new command for creating strings.
|
* Construct command for creating null-terminated ASCII string Data.
|
||||||
|
* Current Data at addr will be cleared if it already exists.
|
||||||
|
* @param addr address where string should be created.
|
||||||
*/
|
*/
|
||||||
public CreateStringCmd(Address addr) {
|
public CreateStringCmd(Address addr) {
|
||||||
this(addr, -1, false);
|
this(addr, -1, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new command for creating strings.
|
* Construct command for creating fixed-length ASCII string Data.
|
||||||
|
* Current Data at addr will be cleared if it already exists.
|
||||||
|
* @param addr address where string should be created.
|
||||||
|
* @param length byte-length of string
|
||||||
*/
|
*/
|
||||||
public CreateStringCmd(Address addr, int length) {
|
public CreateStringCmd(Address addr, int length) {
|
||||||
this(addr, length, false);
|
this(addr, length, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see ghidra.framework.cmd.Command#applyTo(ghidra.framework.model.DomainObject)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applyTo(DomainObject obj) {
|
public boolean applyTo(Program program) {
|
||||||
Program program = (Program) obj;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
DataUtilities.createData(program, addr, stringDataType, length, clearMode);
|
DataUtilities.createData(program, addr, stringDataType, length, clearMode);
|
||||||
}
|
}
|
||||||
|
@ -94,17 +109,11 @@ public class CreateStringCmd implements Command {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.framework.cmd.Command#getStatusMsg()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public String getStatusMsg() {
|
public String getStatusMsg() {
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.framework.cmd.Command#getName()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "Create String";
|
return "Create String";
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,7 +15,9 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.cmd.data;
|
package ghidra.app.cmd.data;
|
||||||
|
|
||||||
import ghidra.framework.model.DomainObject;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.data.*;
|
import ghidra.program.model.data.*;
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.*;
|
||||||
|
@ -24,12 +25,10 @@ import ghidra.program.model.symbol.Reference;
|
||||||
import ghidra.program.model.symbol.ReferenceManager;
|
import ghidra.program.model.symbol.ReferenceManager;
|
||||||
import ghidra.program.model.util.CodeUnitInsertionException;
|
import ghidra.program.model.util.CodeUnitInsertionException;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Command to create a structure.
|
* Command to create a structure.
|
||||||
*/
|
*/
|
||||||
public class CreateStructureCmd extends AbstractCreateStructureCmd{
|
public class CreateStructureCmd extends AbstractCreateStructureCmd {
|
||||||
private int structureDataLength;
|
private int structureDataLength;
|
||||||
private Structure structure;
|
private Structure structure;
|
||||||
|
|
||||||
|
@ -43,8 +42,8 @@ public class CreateStructureCmd extends AbstractCreateStructureCmd{
|
||||||
* @param length the number of undefined bytes to consume in the new
|
* @param length the number of undefined bytes to consume in the new
|
||||||
* structure.
|
* structure.
|
||||||
*/
|
*/
|
||||||
public CreateStructureCmd( Address address, int length ){
|
public CreateStructureCmd(Address address, int length) {
|
||||||
this( StructureFactory.DEFAULT_STRUCTURE_NAME, address, length );
|
this(StructureFactory.DEFAULT_STRUCTURE_NAME, address, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -55,21 +54,21 @@ public class CreateStructureCmd extends AbstractCreateStructureCmd{
|
||||||
* @param length the number of undefined bytes to consume in the new
|
* @param length the number of undefined bytes to consume in the new
|
||||||
* structure.
|
* structure.
|
||||||
*/
|
*/
|
||||||
public CreateStructureCmd( String name, Address address, int length ) {
|
public CreateStructureCmd(String name, Address address, int length) {
|
||||||
super( name, address );
|
super(name, address);
|
||||||
structureDataLength = length;
|
structureDataLength = length;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new structure by using the provided structure and attaching
|
* Creates a new structure by using the provided structure and attaching
|
||||||
* it to the program passed in the {@link #applyTo(DomainObject)} method.
|
* it to the program passed in the {@link #applyTo(Program)} method.
|
||||||
*
|
*
|
||||||
* @param newStructure The new structure to attach to the program
|
* @param newStructure The new structure to attach to the program
|
||||||
* provided in the {@link #applyTo(DomainObject)} method.
|
* provided in the {@link #applyTo(Program)} method.
|
||||||
* @param address the address at which to create the new structure.
|
* @param address the address at which to create the new structure.
|
||||||
*/
|
*/
|
||||||
public CreateStructureCmd( Structure newStructure, Address address ){
|
public CreateStructureCmd(Structure newStructure, Address address) {
|
||||||
super( newStructure.getName(), address );
|
super(newStructure.getName(), address);
|
||||||
structure = newStructure;
|
structure = newStructure;
|
||||||
structureDataLength = structure.getLength();
|
structureDataLength = structure.getLength();
|
||||||
}
|
}
|
||||||
|
@ -78,13 +77,11 @@ public class CreateStructureCmd extends AbstractCreateStructureCmd{
|
||||||
* @see AbstractCreateStructureCmd#createStructure(Address, Program)
|
* @see AbstractCreateStructureCmd#createStructure(Address, Program)
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
Structure createStructure( Address address,
|
Structure createStructure(Address address, Program program) {
|
||||||
Program program ){
|
|
||||||
|
|
||||||
if ( structure == null ){
|
if (structure == null) {
|
||||||
structure =
|
structure = StructureFactory.createStructureDataType(program, address,
|
||||||
StructureFactory.createStructureDataType( program, address,
|
structureDataLength, getStructureName(), true);
|
||||||
structureDataLength, getStructureName(), true );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return structure;
|
return structure;
|
||||||
|
@ -94,54 +91,54 @@ public class CreateStructureCmd extends AbstractCreateStructureCmd{
|
||||||
* @see AbstractCreateStructureCmd#initializeStructureData(Program, Structure)
|
* @see AbstractCreateStructureCmd#initializeStructureData(Program, Structure)
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
DataType initializeStructureData( Program program, Structure localStructure ){
|
DataType initializeStructureData(Program program, Structure localStructure) {
|
||||||
|
|
||||||
Listing listing = program.getListing();
|
Listing listing = program.getListing();
|
||||||
|
|
||||||
Address endAddress;
|
Address endAddress;
|
||||||
try {
|
try {
|
||||||
endAddress = getStructureAddress().addNoWrap(structureDataLength - 1);
|
endAddress = getStructureAddress().addNoWrap(structureDataLength - 1);
|
||||||
} catch (AddressOverflowException e1){
|
}
|
||||||
|
catch (AddressOverflowException e1) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"Can't create structure because length exceeds address " +
|
"Can't create structure because length exceeds address " + "space" +
|
||||||
"space" + structureDataLength );
|
structureDataLength);
|
||||||
}
|
}
|
||||||
ReferenceManager refMgr = program.getReferenceManager();
|
ReferenceManager refMgr = program.getReferenceManager();
|
||||||
Reference[] refs = findExistingRefs( refMgr, program.getAddressFactory(), getStructureAddress(),
|
Reference[] refs = findExistingRefs(refMgr, program.getAddressFactory(),
|
||||||
endAddress );
|
getStructureAddress(), endAddress);
|
||||||
listing.clearCodeUnits( getStructureAddress(), endAddress, false );
|
listing.clearCodeUnits(getStructureAddress(), endAddress, false);
|
||||||
|
|
||||||
Data data = null;
|
Data data = null;
|
||||||
try{
|
try {
|
||||||
listing.createData(getStructureAddress(), localStructure,
|
listing.createData(getStructureAddress(), localStructure, localStructure.getLength());
|
||||||
localStructure.getLength());
|
refMgr.removeAllReferencesFrom(getStructureAddress(), endAddress);
|
||||||
refMgr.removeAllReferencesFrom( getStructureAddress(), endAddress );
|
addRefs(program, refMgr, refs);
|
||||||
addRefs( program, refMgr, refs );
|
data = listing.getDataAt(getStructureAddress());
|
||||||
data = listing.getDataAt( getStructureAddress() );
|
}
|
||||||
} catch(CodeUnitInsertionException e){
|
catch (CodeUnitInsertionException e) {
|
||||||
throw new IllegalArgumentException( e.getMessage() );
|
throw new IllegalArgumentException(e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
return data.getDataType();
|
return data.getDataType();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Reference[] findExistingRefs(ReferenceManager refMgr, AddressFactory af, Address start, Address end) {
|
private Reference[] findExistingRefs(ReferenceManager refMgr, AddressFactory af, Address start,
|
||||||
|
Address end) {
|
||||||
ArrayList<Reference> list = new ArrayList<Reference>();
|
ArrayList<Reference> list = new ArrayList<Reference>();
|
||||||
AddressIterator it = refMgr.getReferenceSourceIterator(new AddressSet(start, end), true);
|
AddressIterator it = refMgr.getReferenceSourceIterator(new AddressSet(start, end), true);
|
||||||
while(it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
Address addr = it.next();
|
Address addr = it.next();
|
||||||
Reference[] refs = refMgr.getReferencesFrom(addr);
|
Reference[] refs = refMgr.getReferencesFrom(addr);
|
||||||
for(int i=0;i<refs.length;i++) {
|
Collections.addAll(list, refs);
|
||||||
list.add(refs[i]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Reference[] refList = new Reference[list.size()];
|
Reference[] refList = new Reference[list.size()];
|
||||||
return list.toArray(refList);
|
return list.toArray(refList);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addRefs(Program p, ReferenceManager refMgr, Reference[] refs) {
|
private void addRefs(Program p, ReferenceManager refMgr, Reference[] refs) {
|
||||||
for(int i=0;i<refs.length;i++) {
|
for (Reference ref : refs) {
|
||||||
refMgr.addReference(refs[i]);
|
refMgr.addReference(ref);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ import ghidra.program.model.listing.Program;
|
||||||
* Command to create a structure inside of another structure.
|
* Command to create a structure inside of another structure.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class CreateStructureInStructureCmd extends AbstractCreateStructureCmd{
|
public class CreateStructureInStructureCmd extends AbstractCreateStructureCmd {
|
||||||
private int[] fromPath;
|
private int[] fromPath;
|
||||||
private int[] toPath;
|
private int[] toPath;
|
||||||
private Structure structure;
|
private Structure structure;
|
||||||
|
@ -37,8 +37,8 @@ public class CreateStructureInStructureCmd extends AbstractCreateStructureCmd{
|
||||||
* @param toPath the componentPath of the second component to be consumed in the
|
* @param toPath the componentPath of the second component to be consumed in the
|
||||||
* the new structure.
|
* the new structure.
|
||||||
*/
|
*/
|
||||||
public CreateStructureInStructureCmd( Address address, int[] fromPath, int[] toPath ){
|
public CreateStructureInStructureCmd(Address address, int[] fromPath, int[] toPath) {
|
||||||
this( StructureFactory.DEFAULT_STRUCTURE_NAME, address, fromPath, toPath );
|
this(StructureFactory.DEFAULT_STRUCTURE_NAME, address, fromPath, toPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -51,15 +51,15 @@ public class CreateStructureInStructureCmd extends AbstractCreateStructureCmd{
|
||||||
* @param toPath the componentPath of the second component to be consumed in the
|
* @param toPath the componentPath of the second component to be consumed in the
|
||||||
* the new structure.
|
* the new structure.
|
||||||
*/
|
*/
|
||||||
public CreateStructureInStructureCmd( String name, Address addr, int[] fromPath, int[] toPath){
|
public CreateStructureInStructureCmd(String name, Address addr, int[] fromPath, int[] toPath) {
|
||||||
super( name, addr );
|
super(name, addr);
|
||||||
this.fromPath = fromPath;
|
this.fromPath = fromPath;
|
||||||
this.toPath = toPath;
|
this.toPath = toPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CreateStructureInStructureCmd( Structure newStructure,
|
public CreateStructureInStructureCmd(Structure newStructure, Address address, int[] fromPath,
|
||||||
Address address, int[] fromPath, int[] toPath ){
|
int[] toPath) {
|
||||||
this( address, fromPath, toPath );
|
this(address, fromPath, toPath);
|
||||||
structure = newStructure;
|
structure = newStructure;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,12 +67,11 @@ public class CreateStructureInStructureCmd extends AbstractCreateStructureCmd{
|
||||||
* @see AbstractCreateStructureCmd#createStructure(Address, Program)
|
* @see AbstractCreateStructureCmd#createStructure(Address, Program)
|
||||||
*/
|
*/
|
||||||
/*package*/ @Override
|
/*package*/ @Override
|
||||||
Structure createStructure( Address address,
|
Structure createStructure(Address address, Program program) {
|
||||||
Program program ){
|
|
||||||
|
|
||||||
if ( structure == null ){
|
if (structure == null) {
|
||||||
structure = StructureFactory.createStructureDataTypeInStrucuture(
|
structure = StructureFactory.createStructureDataTypeInStrucuture(program, address,
|
||||||
program, address, fromPath, toPath, getStructureName(), true );
|
fromPath, toPath, getStructureName(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return structure;
|
return structure;
|
||||||
|
@ -82,36 +81,33 @@ public class CreateStructureInStructureCmd extends AbstractCreateStructureCmd{
|
||||||
* @see AbstractCreateStructureCmd#initializeStructureData(StructureInfo)
|
* @see AbstractCreateStructureCmd#initializeStructureData(StructureInfo)
|
||||||
*/
|
*/
|
||||||
/*package*/ @Override
|
/*package*/ @Override
|
||||||
DataType initializeStructureData( Program program, Structure localStructure ){
|
DataType initializeStructureData(Program program, Structure localStructure) {
|
||||||
|
|
||||||
Data data = program.getListing().getDataContaining(
|
Data data = program.getListing().getDataContaining(getStructureAddress());
|
||||||
getStructureAddress() );
|
Data comp1 = data.getComponent(fromPath);
|
||||||
Data comp1 = data.getComponent( fromPath );
|
|
||||||
Data comp2 = data.getComponent(toPath);
|
Data comp2 = data.getComponent(toPath);
|
||||||
int dataLength = (comp2.getParentOffset() + comp2.getLength())
|
int dataLength = (comp2.getParentOffset() + comp2.getLength()) - comp1.getParentOffset();
|
||||||
- comp1.getParentOffset();
|
|
||||||
|
|
||||||
DataType parentDataType = comp1.getParent().getBaseDataType();
|
DataType parentDataType = comp1.getParent().getBaseDataType();
|
||||||
if ( !(parentDataType instanceof Structure) ){
|
if (!(parentDataType instanceof Structure)) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException("Data not in a structure");
|
||||||
"Data not in a structure");
|
|
||||||
}
|
}
|
||||||
Structure originalStructure = (Structure) parentDataType;
|
Structure originalStructure = (Structure) parentDataType;
|
||||||
|
|
||||||
// clear and initialize the original structure and then get the new
|
// clear and initialize the original structure and then get the new
|
||||||
// data
|
// data
|
||||||
clearStruct(originalStructure, comp1.getParentOffset(), dataLength );
|
clearStruct(originalStructure, comp1.getParentOffset(), dataLength);
|
||||||
originalStructure.replace(comp1.getComponentIndex(),
|
originalStructure.replace(comp1.getComponentIndex(), localStructure,
|
||||||
localStructure, localStructure.getLength());
|
localStructure.getLength());
|
||||||
comp1 = data.getComponent( fromPath );
|
comp1 = data.getComponent(fromPath);
|
||||||
|
|
||||||
return comp1.getDataType();
|
return comp1.getDataType();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void clearStruct(Structure struct, int offset, int length) {
|
private void clearStruct(Structure struct, int offset, int length) {
|
||||||
DataTypeComponent[] comps = struct.getDefinedComponents();
|
DataTypeComponent[] comps = struct.getDefinedComponents();
|
||||||
int endOffset = offset+length;
|
int endOffset = offset + length;
|
||||||
for(int i=comps.length-1;i>=0;i--) {
|
for (int i = comps.length - 1; i >= 0; i--) {
|
||||||
if (comps[i].getOffset() >= offset && comps[i].getOffset() < endOffset) {
|
if (comps[i].getOffset() >= offset && comps[i].getOffset() < endOffset) {
|
||||||
struct.clearComponent(comps[i].getOrdinal());
|
struct.clearComponent(comps[i].getOrdinal());
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -17,16 +16,15 @@
|
||||||
package ghidra.app.cmd.data;
|
package ghidra.app.cmd.data;
|
||||||
|
|
||||||
import ghidra.framework.cmd.Command;
|
import ghidra.framework.cmd.Command;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.program.model.data.DataTypeComponent;
|
import ghidra.program.model.data.DataTypeComponent;
|
||||||
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Command to rename a component in a data type.
|
* Command to rename a component in a data type.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class RenameDataFieldCmd implements Command {
|
public class RenameDataFieldCmd implements Command<Program> {
|
||||||
|
|
||||||
private DataTypeComponent comp;
|
private DataTypeComponent comp;
|
||||||
private String newName;
|
private String newName;
|
||||||
|
@ -43,11 +41,8 @@ public class RenameDataFieldCmd implements Command {
|
||||||
this.newName = newName;
|
this.newName = newName;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
@Override
|
||||||
* (non-Javadoc)
|
public boolean applyTo(Program program) {
|
||||||
* @see ghidra.framework.cmd.Command#applyTo(ghidra.framework.model.DomainObject)
|
|
||||||
*/
|
|
||||||
public boolean applyTo(DomainObject obj) {
|
|
||||||
if (comp == null) {
|
if (comp == null) {
|
||||||
statusMsg = "Null data type";
|
statusMsg = "Null data type";
|
||||||
return false;
|
return false;
|
||||||
|
@ -55,7 +50,8 @@ public class RenameDataFieldCmd implements Command {
|
||||||
try {
|
try {
|
||||||
comp.setFieldName(newName);
|
comp.setFieldName(newName);
|
||||||
return true;
|
return true;
|
||||||
} catch(DuplicateNameException e) {
|
}
|
||||||
|
catch (DuplicateNameException e) {
|
||||||
statusMsg = "Type name already exists: " + newName;
|
statusMsg = "Type name already exists: " + newName;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -65,6 +61,7 @@ public class RenameDataFieldCmd implements Command {
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
* @see ghidra.framework.cmd.Command#getStatusMsg()
|
* @see ghidra.framework.cmd.Command#getStatusMsg()
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public String getStatusMsg() {
|
public String getStatusMsg() {
|
||||||
return statusMsg;
|
return statusMsg;
|
||||||
}
|
}
|
||||||
|
@ -73,6 +70,7 @@ public class RenameDataFieldCmd implements Command {
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
* @see ghidra.framework.cmd.Command#getName()
|
* @see ghidra.framework.cmd.Command#getName()
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "Rename Data Field";
|
return "Rename Data Field";
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,8 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.cmd.disassemble;
|
package ghidra.app.cmd.disassemble;
|
||||||
|
|
||||||
import ghidra.framework.model.DomainObject;
|
import java.math.BigInteger;
|
||||||
|
|
||||||
import ghidra.program.disassemble.DisassemblerContextImpl;
|
import ghidra.program.disassemble.DisassemblerContextImpl;
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.lang.Register;
|
import ghidra.program.model.lang.Register;
|
||||||
|
@ -24,8 +25,6 @@ import ghidra.program.model.listing.Program;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
|
||||||
import java.math.BigInteger;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Command object for performing Arm/Thumb disassembly
|
* Command object for performing Arm/Thumb disassembly
|
||||||
*/
|
*/
|
||||||
|
@ -70,8 +69,7 @@ public class ArmDisassembleCommand extends DisassembleCommand {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
synchronized public boolean applyTo(DomainObject obj, TaskMonitor monitor) {
|
synchronized public boolean applyTo(Program program, TaskMonitor monitor) {
|
||||||
Program program = (Program) obj;
|
|
||||||
|
|
||||||
disassemblyPerformed = false;
|
disassemblyPerformed = false;
|
||||||
unalignedStart = false;
|
unalignedStart = false;
|
||||||
|
|
|
@ -17,10 +17,10 @@ package ghidra.app.cmd.disassemble;
|
||||||
|
|
||||||
import ghidra.app.plugin.core.analysis.AutoAnalysisManager;
|
import ghidra.app.plugin.core.analysis.AutoAnalysisManager;
|
||||||
import ghidra.framework.cmd.BackgroundCommand;
|
import ghidra.framework.cmd.BackgroundCommand;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.program.disassemble.*;
|
import ghidra.program.disassemble.*;
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.lang.*;
|
import ghidra.program.model.lang.Register;
|
||||||
|
import ghidra.program.model.lang.RegisterValue;
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.*;
|
||||||
import ghidra.program.model.mem.Memory;
|
import ghidra.program.model.mem.Memory;
|
||||||
import ghidra.program.model.mem.MemoryBlock;
|
import ghidra.program.model.mem.MemoryBlock;
|
||||||
|
@ -30,7 +30,7 @@ import ghidra.util.task.TaskMonitor;
|
||||||
/**
|
/**
|
||||||
* Command object for performing disassembly
|
* Command object for performing disassembly
|
||||||
*/
|
*/
|
||||||
public class DisassembleCommand extends BackgroundCommand {
|
public class DisassembleCommand extends BackgroundCommand<Program> {
|
||||||
|
|
||||||
protected AddressSetView startSet;
|
protected AddressSetView startSet;
|
||||||
protected boolean useDefaultRepeatPatternBehavior = false;
|
protected boolean useDefaultRepeatPatternBehavior = false;
|
||||||
|
@ -78,6 +78,8 @@ public class DisassembleCommand extends BackgroundCommand {
|
||||||
* @param startSet set of addresses to be the start of a disassembly. The Command object will
|
* @param startSet set of addresses to be the start of a disassembly. The Command object will
|
||||||
* attempt to start a disassembly at each address in this set.
|
* attempt to start a disassembly at each address in this set.
|
||||||
* @param restrictedSet addresses that can be disassembled. a null set implies no restrictions
|
* @param restrictedSet addresses that can be disassembled. a null set implies no restrictions
|
||||||
|
* @param followFlow follow all flows within restricted set if true, otherwise limit to using
|
||||||
|
* startSet for flows.
|
||||||
*/
|
*/
|
||||||
public DisassembleCommand(AddressSetView startSet, AddressSetView restrictedSet,
|
public DisassembleCommand(AddressSetView startSet, AddressSetView restrictedSet,
|
||||||
boolean followFlow) {
|
boolean followFlow) {
|
||||||
|
@ -125,7 +127,7 @@ public class DisassembleCommand extends BackgroundCommand {
|
||||||
* Set code analysis enablement. By default new instructions will be submitted for
|
* Set code analysis enablement. By default new instructions will be submitted for
|
||||||
* auto-analysis.
|
* auto-analysis.
|
||||||
*
|
*
|
||||||
* @param enable
|
* @param enable true if incremental code analysis should be done, else false to prevent this.
|
||||||
*/
|
*/
|
||||||
public void enableCodeAnalysis(boolean enable) {
|
public void enableCodeAnalysis(boolean enable) {
|
||||||
this.enableAnalysis = enable;
|
this.enableAnalysis = enable;
|
||||||
|
@ -150,8 +152,7 @@ public class DisassembleCommand extends BackgroundCommand {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
synchronized public boolean applyTo(DomainObject obj, TaskMonitor monitor) {
|
synchronized public boolean applyTo(Program program, TaskMonitor monitor) {
|
||||||
Program program = (Program) obj;
|
|
||||||
return doDisassembly(monitor, program, program.getLanguage().getInstructionAlignment());
|
return doDisassembly(monitor, program, program.getLanguage().getInstructionAlignment());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -317,7 +318,7 @@ public class DisassembleCommand extends BackgroundCommand {
|
||||||
*
|
*
|
||||||
* @param disassembler disassembler to use
|
* @param disassembler disassembler to use
|
||||||
* @param seedSet set of addresses to be disassembled
|
* @param seedSet set of addresses to be disassembled
|
||||||
* @param mgr
|
* @param mgr auto analysis manager
|
||||||
*
|
*
|
||||||
* @return addresses actually disassembled
|
* @return addresses actually disassembled
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -17,7 +17,6 @@ package ghidra.app.cmd.disassemble;
|
||||||
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.program.disassemble.DisassemblerContextImpl;
|
import ghidra.program.disassemble.DisassemblerContextImpl;
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.lang.Register;
|
import ghidra.program.model.lang.Register;
|
||||||
|
@ -70,8 +69,7 @@ public class Hcs12DisassembleCommand extends DisassembleCommand {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
synchronized public boolean applyTo(DomainObject obj, TaskMonitor monitor) {
|
synchronized public boolean applyTo(Program program, TaskMonitor monitor) {
|
||||||
Program program = (Program) obj;
|
|
||||||
|
|
||||||
disassemblyPerformed = false;
|
disassemblyPerformed = false;
|
||||||
unalignedStart = false;
|
unalignedStart = false;
|
||||||
|
|
|
@ -17,7 +17,6 @@ package ghidra.app.cmd.disassemble;
|
||||||
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.program.disassemble.DisassemblerContextImpl;
|
import ghidra.program.disassemble.DisassemblerContextImpl;
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.lang.Register;
|
import ghidra.program.model.lang.Register;
|
||||||
|
@ -75,8 +74,7 @@ public class MipsDisassembleCommand extends DisassembleCommand {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
synchronized public boolean applyTo(DomainObject obj, TaskMonitor monitor) {
|
synchronized public boolean applyTo(Program program, TaskMonitor monitor) {
|
||||||
Program program = (Program) obj;
|
|
||||||
|
|
||||||
disassemblyPerformed = false;
|
disassemblyPerformed = false;
|
||||||
unalignedStart = false;
|
unalignedStart = false;
|
||||||
|
@ -90,7 +88,7 @@ public class MipsDisassembleCommand extends DisassembleCommand {
|
||||||
setStatusMsg("MIPS16 mode not supported");
|
setStatusMsg("MIPS16 mode not supported");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return super.applyTo(obj, monitor);
|
return super.applyTo(program, monitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
RegisterValue m16modeValue =
|
RegisterValue m16modeValue =
|
||||||
|
|
|
@ -17,7 +17,6 @@ package ghidra.app.cmd.disassemble;
|
||||||
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.program.disassemble.DisassemblerContextImpl;
|
import ghidra.program.disassemble.DisassemblerContextImpl;
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.lang.Register;
|
import ghidra.program.model.lang.Register;
|
||||||
|
@ -77,8 +76,7 @@ public class PowerPCDisassembleCommand extends DisassembleCommand {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
synchronized public boolean applyTo(DomainObject obj, TaskMonitor monitor) {
|
synchronized public boolean applyTo(Program program, TaskMonitor monitor) {
|
||||||
Program program = (Program) obj;
|
|
||||||
|
|
||||||
disassemblyPerformed = false;
|
disassemblyPerformed = false;
|
||||||
unalignedStart = false;
|
unalignedStart = false;
|
||||||
|
@ -92,7 +90,7 @@ public class PowerPCDisassembleCommand extends DisassembleCommand {
|
||||||
setStatusMsg("PowerISA VLE mode not supported");
|
setStatusMsg("PowerISA VLE mode not supported");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return super.applyTo(obj, monitor);
|
return super.applyTo(program, monitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
RegisterValue vlemodeValue =
|
RegisterValue vlemodeValue =
|
||||||
|
|
|
@ -16,14 +16,13 @@
|
||||||
package ghidra.app.cmd.disassemble;
|
package ghidra.app.cmd.disassemble;
|
||||||
|
|
||||||
import ghidra.framework.cmd.BackgroundCommand;
|
import ghidra.framework.cmd.BackgroundCommand;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.program.disassemble.ReDisassembler;
|
import ghidra.program.disassemble.ReDisassembler;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
|
||||||
public class ReDisassembleCommand extends BackgroundCommand {
|
public class ReDisassembleCommand extends BackgroundCommand<Program> {
|
||||||
private final Address seed;
|
private final Address seed;
|
||||||
|
|
||||||
public ReDisassembleCommand(Address seed) {
|
public ReDisassembleCommand(Address seed) {
|
||||||
|
@ -31,8 +30,8 @@ public class ReDisassembleCommand extends BackgroundCommand {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applyTo(DomainObject obj, TaskMonitor monitor) {
|
public boolean applyTo(Program program, TaskMonitor monitor) {
|
||||||
ReDisassembler dis = new ReDisassembler((Program) obj);
|
ReDisassembler dis = new ReDisassembler(program);
|
||||||
try {
|
try {
|
||||||
dis.disasemble(seed, monitor);
|
dis.disasemble(seed, monitor);
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -17,7 +16,6 @@
|
||||||
package ghidra.app.cmd.disassemble;
|
package ghidra.app.cmd.disassemble;
|
||||||
|
|
||||||
import ghidra.framework.cmd.BackgroundCommand;
|
import ghidra.framework.cmd.BackgroundCommand;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.address.AddressSetView;
|
import ghidra.program.model.address.AddressSetView;
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.*;
|
||||||
|
@ -26,7 +24,7 @@ import ghidra.util.task.TaskMonitor;
|
||||||
/**
|
/**
|
||||||
* Command for setting the fallthrough property on an instruction.
|
* Command for setting the fallthrough property on an instruction.
|
||||||
*/
|
*/
|
||||||
public class SetFlowOverrideCmd extends BackgroundCommand {
|
public class SetFlowOverrideCmd extends BackgroundCommand<Program> {
|
||||||
Address instAddr;
|
Address instAddr;
|
||||||
AddressSetView set;
|
AddressSetView set;
|
||||||
FlowOverride flowOverride;
|
FlowOverride flowOverride;
|
||||||
|
@ -60,9 +58,7 @@ public class SetFlowOverrideCmd extends BackgroundCommand {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applyTo(DomainObject obj, TaskMonitor monitor) {
|
public boolean applyTo(Program program, TaskMonitor monitor) {
|
||||||
|
|
||||||
Program program = (Program) obj;
|
|
||||||
|
|
||||||
if (set != null) {
|
if (set != null) {
|
||||||
int cnt = 0;
|
int cnt = 0;
|
||||||
|
|
|
@ -19,10 +19,10 @@ import java.math.BigInteger;
|
||||||
|
|
||||||
import javax.help.UnsupportedOperationException;
|
import javax.help.UnsupportedOperationException;
|
||||||
|
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.program.disassemble.DisassemblerContextImpl;
|
import ghidra.program.disassemble.DisassemblerContextImpl;
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.lang.*;
|
import ghidra.program.model.lang.Register;
|
||||||
|
import ghidra.program.model.lang.RegisterValue;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.program.model.listing.ProgramContext;
|
import ghidra.program.model.listing.ProgramContext;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
|
@ -91,8 +91,7 @@ public class X86_64DisassembleCommand extends DisassembleCommand {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static AddressSet alignSet(int alignment, AddressSetView set)
|
public static AddressSet alignSet(int alignment, AddressSetView set) {
|
||||||
throws CancelledException {
|
|
||||||
AddressSet result = new AddressSet();
|
AddressSet result = new AddressSet();
|
||||||
for (AddressRange range : set) {
|
for (AddressRange range : set) {
|
||||||
Address min = range.getMinAddress();
|
Address min = range.getMinAddress();
|
||||||
|
@ -115,8 +114,7 @@ public class X86_64DisassembleCommand extends DisassembleCommand {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
synchronized public boolean applyTo(DomainObject obj, TaskMonitor monitor) {
|
synchronized public boolean applyTo(Program program, TaskMonitor monitor) {
|
||||||
Program program = (Program) obj;
|
|
||||||
|
|
||||||
disassemblyPerformed = false;
|
disassemblyPerformed = false;
|
||||||
unalignedStart = false;
|
unalignedStart = false;
|
||||||
|
@ -130,8 +128,8 @@ public class X86_64DisassembleCommand extends DisassembleCommand {
|
||||||
languageError = "Requires x86:LE:64:default";
|
languageError = "Requires x86:LE:64:default";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
RegisterValue ctx = new RegisterValue(context.getBaseContextRegister())
|
RegisterValue ctx = new RegisterValue(context.getBaseContextRegister()).assign(longModeReg,
|
||||||
.assign(longModeReg, size32Mode ? BigInteger.ZERO : BigInteger.ONE);
|
size32Mode ? BigInteger.ZERO : BigInteger.ONE);
|
||||||
|
|
||||||
super.setInitialContext(ctx);
|
super.setInitialContext(ctx);
|
||||||
|
|
||||||
|
|
|
@ -16,13 +16,12 @@
|
||||||
package ghidra.app.cmd.equate;
|
package ghidra.app.cmd.equate;
|
||||||
|
|
||||||
import ghidra.framework.cmd.Command;
|
import ghidra.framework.cmd.Command;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.program.model.symbol.Equate;
|
import ghidra.program.model.symbol.Equate;
|
||||||
import ghidra.program.model.symbol.EquateTable;
|
import ghidra.program.model.symbol.EquateTable;
|
||||||
|
|
||||||
public class ClearEquateCmd implements Command {
|
public class ClearEquateCmd implements Command<Program> {
|
||||||
|
|
||||||
private String equateName;
|
private String equateName;
|
||||||
private Address addr;
|
private Address addr;
|
||||||
|
@ -42,8 +41,8 @@ public class ClearEquateCmd implements Command {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applyTo(DomainObject obj) {
|
public boolean applyTo(Program program) {
|
||||||
EquateTable equateTable = ((Program) obj).getEquateTable();
|
EquateTable equateTable = program.getEquateTable();
|
||||||
Equate equate = equateTable.getEquate(equateName);
|
Equate equate = equateTable.getEquate(equateName);
|
||||||
|
|
||||||
clearEquate(equate, equateTable);
|
clearEquate(equate, equateTable);
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
package ghidra.app.cmd.equate;
|
package ghidra.app.cmd.equate;
|
||||||
|
|
||||||
import ghidra.framework.cmd.Command;
|
import ghidra.framework.cmd.Command;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.program.model.symbol.Equate;
|
import ghidra.program.model.symbol.Equate;
|
||||||
|
@ -27,7 +26,7 @@ import ghidra.util.exception.InvalidInputException;
|
||||||
/**
|
/**
|
||||||
* Command for setting an equate at a location.
|
* Command for setting an equate at a location.
|
||||||
*/
|
*/
|
||||||
public class SetEquateCmd implements Command {
|
public class SetEquateCmd implements Command<Program> {
|
||||||
|
|
||||||
private String equateName;
|
private String equateName;
|
||||||
private Address addr;
|
private Address addr;
|
||||||
|
@ -52,23 +51,18 @@ public class SetEquateCmd implements Command {
|
||||||
this.equateValue = equateValue;
|
this.equateValue = equateValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* The name of the edit action.
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "Set Equate";
|
return "Set Equate";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applyTo(DomainObject obj) {
|
public boolean applyTo(Program program) {
|
||||||
EquateTable equateTable = ((Program) obj).getEquateTable();
|
EquateTable equateTable = program.getEquateTable();
|
||||||
equate = equateTable.getEquate(equateName);
|
equate = equateTable.getEquate(equateName);
|
||||||
|
|
||||||
|
|
||||||
if (existsWithDifferentValue(equate)) {
|
if (existsWithDifferentValue(equate)) {
|
||||||
msg =
|
msg = "Equate named " + equateName + " already exists with value of " +
|
||||||
"Equate named " + equateName + " already exists with value of " +
|
|
||||||
equate.getValue() + ".";
|
equate.getValue() + ".";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -101,9 +95,6 @@ public class SetEquateCmd implements Command {
|
||||||
return equate;
|
return equate;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.framework.cmd.Command#getStatusMsg()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public String getStatusMsg() {
|
public String getStatusMsg() {
|
||||||
return msg;
|
return msg;
|
||||||
|
|
|
@ -16,17 +16,14 @@
|
||||||
package ghidra.app.cmd.function;
|
package ghidra.app.cmd.function;
|
||||||
|
|
||||||
import ghidra.framework.cmd.Command;
|
import ghidra.framework.cmd.Command;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.program.database.ProgramDB;
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.listing.Function;
|
import ghidra.program.model.listing.*;
|
||||||
import ghidra.program.model.listing.FunctionManager;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Command for assigning a tag to a function. Executing this will pop up a dialog
|
* Command for assigning a tag to a function. Executing this will pop up a dialog
|
||||||
* allowing the user to assign tags to a function.
|
* allowing the user to assign tags to a function.
|
||||||
*/
|
*/
|
||||||
public class AddFunctionTagCmd implements Command {
|
public class AddFunctionTagCmd implements Command<Program> {
|
||||||
|
|
||||||
private Address entryPoint;
|
private Address entryPoint;
|
||||||
private String tagName;
|
private String tagName;
|
||||||
|
@ -44,8 +41,7 @@ public class AddFunctionTagCmd implements Command {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applyTo(DomainObject obj) {
|
public boolean applyTo(Program program) {
|
||||||
ProgramDB program = (ProgramDB) obj;
|
|
||||||
FunctionManager functionManager = program.getFunctionManager();
|
FunctionManager functionManager = program.getFunctionManager();
|
||||||
Function function = functionManager.getFunctionAt(entryPoint);
|
Function function = functionManager.getFunctionAt(entryPoint);
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -24,12 +23,16 @@ import ghidra.util.exception.InvalidInputException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A command to create a new function memory parameter.
|
* A command to create a new function memory parameter.
|
||||||
|
*
|
||||||
|
* @deprecated function signatures should be modified in their entirety using
|
||||||
|
* either {@link UpdateFunctionCommand} or {@link ApplyFunctionSignatureCmd}.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated(since = "11.1")
|
||||||
public class AddMemoryParameterCommand extends AddParameterCommand {
|
public class AddMemoryParameterCommand extends AddParameterCommand {
|
||||||
|
|
||||||
private Address memAddr;
|
private final Address memAddr;
|
||||||
private String name;
|
private final String name;
|
||||||
private DataType dataType;
|
private final DataType dataType;
|
||||||
|
|
||||||
public AddMemoryParameterCommand(Function function, Address memAddr, String name,
|
public AddMemoryParameterCommand(Function function, Address memAddr, String name,
|
||||||
DataType dataType, int ordinal, SourceType source) {
|
DataType dataType, int ordinal, SourceType source) {
|
||||||
|
@ -37,7 +40,6 @@ public class AddMemoryParameterCommand extends AddParameterCommand {
|
||||||
this.memAddr = memAddr;
|
this.memAddr = memAddr;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.dataType = dataType;
|
this.dataType = dataType;
|
||||||
this.ordinal = ordinal;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -45,9 +47,6 @@ public class AddMemoryParameterCommand extends AddParameterCommand {
|
||||||
return new ParameterImpl(name, dataType, memAddr, program);
|
return new ParameterImpl(name, dataType, memAddr, program);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.framework.cmd.Command#getName()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "Create Memory Parameter";
|
return "Create Memory Parameter";
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -17,7 +16,6 @@
|
||||||
package ghidra.app.cmd.function;
|
package ghidra.app.cmd.function;
|
||||||
|
|
||||||
import ghidra.framework.cmd.Command;
|
import ghidra.framework.cmd.Command;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.data.DataType;
|
import ghidra.program.model.data.DataType;
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.*;
|
||||||
|
@ -28,8 +26,8 @@ import ghidra.util.exception.InvalidInputException;
|
||||||
/**
|
/**
|
||||||
* Command to add a memory variable to a function.
|
* Command to add a memory variable to a function.
|
||||||
*/
|
*/
|
||||||
public class AddMemoryVarCmd implements Command {
|
public class AddMemoryVarCmd implements Command<Program> {
|
||||||
private Program program;
|
|
||||||
private Address memAddr;
|
private Address memAddr;
|
||||||
private Address firstUseAddr;
|
private Address firstUseAddr;
|
||||||
private String name;
|
private String name;
|
||||||
|
@ -68,13 +66,8 @@ public class AddMemoryVarCmd implements Command {
|
||||||
this.source = source;
|
this.source = source;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see ghidra.framework.cmd.Command#applyTo(ghidra.framework.model.DomainObject)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applyTo(DomainObject obj) {
|
public boolean applyTo(Program program) {
|
||||||
program = (Program) obj;
|
|
||||||
|
|
||||||
Function f = program.getListing().getFunctionContaining(firstUseAddr);
|
Function f = program.getListing().getFunctionContaining(firstUseAddr);
|
||||||
if (f == null) {
|
if (f == null) {
|
||||||
|
@ -100,17 +93,11 @@ public class AddMemoryVarCmd implements Command {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.framework.cmd.Command#getName()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "Create Memory Variable";
|
return "Create Memory Variable";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.framework.cmd.Command#getStatusMsg()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public String getStatusMsg() {
|
public String getStatusMsg() {
|
||||||
return errMsg;
|
return errMsg;
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -17,7 +16,6 @@
|
||||||
package ghidra.app.cmd.function;
|
package ghidra.app.cmd.function;
|
||||||
|
|
||||||
import ghidra.framework.cmd.Command;
|
import ghidra.framework.cmd.Command;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.*;
|
||||||
import ghidra.program.model.symbol.SourceType;
|
import ghidra.program.model.symbol.SourceType;
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
|
@ -29,17 +27,23 @@ import ghidra.util.exception.InvalidInputException;
|
||||||
* Note: If no ordinal is provided to this class at construction time, then
|
* Note: If no ordinal is provided to this class at construction time, then
|
||||||
* the ordinal of hte given parameter will be used.
|
* the ordinal of hte given parameter will be used.
|
||||||
*
|
*
|
||||||
|
* @see AddRegisterParameterCommand
|
||||||
|
* @see AddStackParameterCommand
|
||||||
|
* @see AddMemoryParameterCommand
|
||||||
*
|
*
|
||||||
* @see ghidra.app.cmd.function.AddRegisterParameterCommand
|
* @deprecated function signatures should be modified in their entirety using
|
||||||
* @see ghidra.app.cmd.function.AddStackParameterCommand
|
* either {@link UpdateFunctionCommand} or {@link ApplyFunctionSignatureCmd}.
|
||||||
*/
|
*/
|
||||||
public class AddParameterCommand implements Command {
|
@Deprecated(since = "11.1")
|
||||||
|
public class AddParameterCommand implements Command<Program> {
|
||||||
|
|
||||||
|
protected final Function function;
|
||||||
|
protected final int ordinal;
|
||||||
|
protected final SourceType source;
|
||||||
|
|
||||||
|
private final Parameter parameter;
|
||||||
|
|
||||||
protected Function function;
|
|
||||||
protected Parameter parameter;
|
|
||||||
protected String statusMessage;
|
protected String statusMessage;
|
||||||
protected int ordinal;
|
|
||||||
protected SourceType source;
|
|
||||||
|
|
||||||
public AddParameterCommand(Function function, Parameter parameter, int ordinal,
|
public AddParameterCommand(Function function, Parameter parameter, int ordinal,
|
||||||
SourceType source) {
|
SourceType source) {
|
||||||
|
@ -49,31 +53,32 @@ public class AddParameterCommand implements Command {
|
||||||
this.source = source;
|
this.source = source;
|
||||||
}
|
}
|
||||||
|
|
||||||
// // lets this be usable by code that already has a parameter
|
|
||||||
// public AddParameterCommand(Function function, Parameter parameter) {
|
|
||||||
// this(function, parameter, parameter.getOrdinal());
|
|
||||||
// }
|
|
||||||
|
|
||||||
// allows subclasses to use this class without having to already have
|
// allows subclasses to use this class without having to already have
|
||||||
// a parameter created
|
// a parameter created
|
||||||
protected AddParameterCommand(Function function, int ordinal, SourceType source) {
|
protected AddParameterCommand(Function function, int ordinal, SourceType source) {
|
||||||
this(function, null, ordinal, source);
|
this(function, null, ordinal, source);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get parameter to be added
|
||||||
|
* @param program target program
|
||||||
|
* @return parameter to be added
|
||||||
|
* @throws InvalidInputException if unable to generate parameter due to invalid data
|
||||||
|
*/
|
||||||
protected Parameter getParameter(Program program) throws InvalidInputException {
|
protected Parameter getParameter(Program program) throws InvalidInputException {
|
||||||
return parameter;
|
return parameter;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.framework.cmd.Command#applyTo(ghidra.framework.model.DomainObject)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applyTo(DomainObject obj) {
|
public final boolean applyTo(Program program) {
|
||||||
|
if (program != function.getProgram()) {
|
||||||
|
throw new AssertionError("Program instance mismatch");
|
||||||
|
}
|
||||||
String name = null;
|
String name = null;
|
||||||
try {
|
try {
|
||||||
Parameter parameter2add = getParameter((Program) obj);
|
Parameter param = getParameter(program);
|
||||||
name = parameter2add.getName();
|
name = param.getName();
|
||||||
if (function.insertParameter(ordinal, parameter2add, source) == null) {
|
if (function.insertParameter(ordinal, param, source) == null) {
|
||||||
statusMessage = "Create parameter failed";
|
statusMessage = "Create parameter failed";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -102,17 +107,11 @@ public class AddParameterCommand implements Command {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.framework.cmd.Command#getStatusMsg()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public String getStatusMsg() {
|
public String getStatusMsg() {
|
||||||
return statusMessage;
|
return statusMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.framework.cmd.Command#getName()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "Add Parameter Command";
|
return "Add Parameter Command";
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -25,14 +24,15 @@ import ghidra.util.exception.InvalidInputException;
|
||||||
/**
|
/**
|
||||||
* A command to create a new function register parameter.
|
* A command to create a new function register parameter.
|
||||||
*
|
*
|
||||||
*
|
* @deprecated function signatures should be modified in their entirety using
|
||||||
* @since Tracker Id 526
|
* either {@link UpdateFunctionCommand} or {@link ApplyFunctionSignatureCmd}.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated(since = "11.1")
|
||||||
public class AddRegisterParameterCommand extends AddParameterCommand {
|
public class AddRegisterParameterCommand extends AddParameterCommand {
|
||||||
|
|
||||||
private Register register;
|
private final Register register;
|
||||||
private String name;
|
private final String name;
|
||||||
private DataType dataType;
|
private final DataType dataType;
|
||||||
|
|
||||||
public AddRegisterParameterCommand(Function function, Register register, String name,
|
public AddRegisterParameterCommand(Function function, Register register, String name,
|
||||||
DataType dataType, int ordinal, SourceType source) {
|
DataType dataType, int ordinal, SourceType source) {
|
||||||
|
@ -40,7 +40,6 @@ public class AddRegisterParameterCommand extends AddParameterCommand {
|
||||||
this.register = register;
|
this.register = register;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.dataType = dataType;
|
this.dataType = dataType;
|
||||||
this.ordinal = ordinal;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -48,9 +47,6 @@ public class AddRegisterParameterCommand extends AddParameterCommand {
|
||||||
return new ParameterImpl(name, dataType, register, program);
|
return new ParameterImpl(name, dataType, register, program);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.framework.cmd.Command#getName()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "Create Register Parameter";
|
return "Create Register Parameter";
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -17,7 +16,6 @@
|
||||||
package ghidra.app.cmd.function;
|
package ghidra.app.cmd.function;
|
||||||
|
|
||||||
import ghidra.framework.cmd.Command;
|
import ghidra.framework.cmd.Command;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.data.DataType;
|
import ghidra.program.model.data.DataType;
|
||||||
import ghidra.program.model.lang.Register;
|
import ghidra.program.model.lang.Register;
|
||||||
|
@ -30,9 +28,8 @@ import ghidra.util.exception.InvalidInputException;
|
||||||
* Command to add a register variable to a function.
|
* Command to add a register variable to a function.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class AddRegisterVarCmd implements Command {
|
public class AddRegisterVarCmd implements Command<Program> {
|
||||||
|
|
||||||
private Program program;
|
|
||||||
private Address addr;
|
private Address addr;
|
||||||
private Register reg;
|
private Register reg;
|
||||||
private String name;
|
private String name;
|
||||||
|
@ -71,13 +68,8 @@ public class AddRegisterVarCmd implements Command {
|
||||||
this.source = source;
|
this.source = source;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see ghidra.framework.cmd.Command#applyTo(ghidra.framework.model.DomainObject)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applyTo(DomainObject obj) {
|
public boolean applyTo(Program program) {
|
||||||
program = (Program) obj;
|
|
||||||
|
|
||||||
Function f = program.getListing().getFunctionContaining(addr);
|
Function f = program.getListing().getFunctionContaining(addr);
|
||||||
if (f == null) {
|
if (f == null) {
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -24,14 +23,15 @@ import ghidra.util.exception.InvalidInputException;
|
||||||
/**
|
/**
|
||||||
* A command to create a new function stack parameter.
|
* A command to create a new function stack parameter.
|
||||||
*
|
*
|
||||||
*
|
* @deprecated function signatures should be modified in their entirety using
|
||||||
* @since Tracker Id 526
|
* either {@link UpdateFunctionCommand} or {@link ApplyFunctionSignatureCmd}.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated(since = "11.1")
|
||||||
public class AddStackParameterCommand extends AddParameterCommand {
|
public class AddStackParameterCommand extends AddParameterCommand {
|
||||||
|
|
||||||
private int stackOffset;
|
private final int stackOffset;
|
||||||
private String name;
|
private final String name;
|
||||||
private DataType dataType;
|
private final DataType dataType;
|
||||||
|
|
||||||
public AddStackParameterCommand(Function function, int stackOffset, String name,
|
public AddStackParameterCommand(Function function, int stackOffset, String name,
|
||||||
DataType dataType, int ordinal, SourceType source) {
|
DataType dataType, int ordinal, SourceType source) {
|
||||||
|
@ -39,8 +39,6 @@ public class AddStackParameterCommand extends AddParameterCommand {
|
||||||
this.stackOffset = stackOffset;
|
this.stackOffset = stackOffset;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.dataType = dataType;
|
this.dataType = dataType;
|
||||||
this.ordinal = ordinal;
|
|
||||||
this.source = source;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -17,7 +16,6 @@
|
||||||
package ghidra.app.cmd.function;
|
package ghidra.app.cmd.function;
|
||||||
|
|
||||||
import ghidra.framework.cmd.Command;
|
import ghidra.framework.cmd.Command;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.data.DataType;
|
import ghidra.program.model.data.DataType;
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.*;
|
||||||
|
@ -28,8 +26,8 @@ import ghidra.util.exception.InvalidInputException;
|
||||||
/**
|
/**
|
||||||
* Command to add a stack variable to a function.
|
* Command to add a stack variable to a function.
|
||||||
*/
|
*/
|
||||||
public class AddStackVarCmd implements Command {
|
public class AddStackVarCmd implements Command<Program> {
|
||||||
private Program program;
|
|
||||||
private Address addr;
|
private Address addr;
|
||||||
private int stackOffset;
|
private int stackOffset;
|
||||||
private String name;
|
private String name;
|
||||||
|
@ -37,7 +35,6 @@ public class AddStackVarCmd implements Command {
|
||||||
private SourceType source;
|
private SourceType source;
|
||||||
private String errMsg = "";
|
private String errMsg = "";
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new command to add a stack variable to a function.
|
* Constructs a new command to add a stack variable to a function.
|
||||||
* @param addr initial declaration point of variable.
|
* @param addr initial declaration point of variable.
|
||||||
|
@ -46,7 +43,8 @@ public class AddStackVarCmd implements Command {
|
||||||
* @param dataType variable data-type or null for a default data type of minimal size
|
* @param dataType variable data-type or null for a default data type of minimal size
|
||||||
* @param source the source of this stack variable
|
* @param source the source of this stack variable
|
||||||
*/
|
*/
|
||||||
public AddStackVarCmd(Address addr, int stackOffset, String name, DataType dataType, SourceType source) {
|
public AddStackVarCmd(Address addr, int stackOffset, String name, DataType dataType,
|
||||||
|
SourceType source) {
|
||||||
this.addr = addr;
|
this.addr = addr;
|
||||||
this.stackOffset = stackOffset;
|
this.stackOffset = stackOffset;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
@ -54,18 +52,14 @@ public class AddStackVarCmd implements Command {
|
||||||
this.source = source;
|
this.source = source;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
*
|
public boolean applyTo(Program program) {
|
||||||
* @see ghidra.framework.cmd.Command#applyTo(ghidra.framework.model.DomainObject)
|
|
||||||
*/
|
|
||||||
public boolean applyTo(DomainObject obj) {
|
|
||||||
program = (Program)obj;
|
|
||||||
if (dataType != null) {
|
if (dataType != null) {
|
||||||
dataType = dataType.clone(program.getDataTypeManager());
|
dataType = dataType.clone(program.getDataTypeManager());
|
||||||
}
|
}
|
||||||
Function f = program.getListing().getFunctionContaining(addr);
|
Function f = program.getListing().getFunctionContaining(addr);
|
||||||
if (f == null) {
|
if (f == null) {
|
||||||
errMsg="Address not contained within function: " +addr;
|
errMsg = "Address not contained within function: " + addr;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
StackFrame sf = f.getStackFrame();
|
StackFrame sf = f.getStackFrame();
|
||||||
|
@ -77,26 +71,24 @@ public class AddStackVarCmd implements Command {
|
||||||
errMsg = "Create stack variable failed";
|
errMsg = "Create stack variable failed";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} catch (DuplicateNameException e) {
|
}
|
||||||
|
catch (DuplicateNameException e) {
|
||||||
errMsg = "Variable named " + name + " already exists";
|
errMsg = "Variable named " + name + " already exists";
|
||||||
return false;
|
return false;
|
||||||
} catch (InvalidInputException e) {
|
}
|
||||||
|
catch (InvalidInputException e) {
|
||||||
errMsg = e.getMessage();
|
errMsg = e.getMessage();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* @see ghidra.framework.cmd.Command#getName()
|
|
||||||
*/
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "Create Stack Variable";
|
return "Create Stack Variable";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* @see ghidra.framework.cmd.Command#getStatusMsg()
|
|
||||||
*/
|
|
||||||
public String getStatusMsg() {
|
public String getStatusMsg() {
|
||||||
return errMsg;
|
return errMsg;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,6 @@ import java.util.*;
|
||||||
import ghidra.app.cmd.disassemble.DisassembleCommand;
|
import ghidra.app.cmd.disassemble.DisassembleCommand;
|
||||||
import ghidra.app.util.PseudoDisassembler;
|
import ghidra.app.util.PseudoDisassembler;
|
||||||
import ghidra.framework.cmd.BackgroundCommand;
|
import ghidra.framework.cmd.BackgroundCommand;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.address.AddressSetView;
|
import ghidra.program.model.address.AddressSetView;
|
||||||
import ghidra.program.model.data.*;
|
import ghidra.program.model.data.*;
|
||||||
|
@ -36,7 +35,7 @@ import ghidra.util.task.TaskMonitor;
|
||||||
* any user defined label that has the same name as the function
|
* any user defined label that has the same name as the function
|
||||||
* signature.
|
* signature.
|
||||||
*/
|
*/
|
||||||
public class ApplyFunctionDataTypesCmd extends BackgroundCommand {
|
public class ApplyFunctionDataTypesCmd extends BackgroundCommand<Program> {
|
||||||
private Program program;
|
private Program program;
|
||||||
private BookmarkManager bookmarkMgr;
|
private BookmarkManager bookmarkMgr;
|
||||||
private List<Category> sourceCategories;
|
private List<Category> sourceCategories;
|
||||||
|
@ -83,8 +82,8 @@ public class ApplyFunctionDataTypesCmd extends BackgroundCommand {
|
||||||
* @param createBookmarksEnabled true to create a bookmark when a function signature
|
* @param createBookmarksEnabled true to create a bookmark when a function signature
|
||||||
* has been applied.
|
* has been applied.
|
||||||
*/
|
*/
|
||||||
public ApplyFunctionDataTypesCmd(Category sourceCategory, AddressSetView set,
|
public ApplyFunctionDataTypesCmd(Category sourceCategory, AddressSetView set, SourceType source,
|
||||||
SourceType source, boolean alwaysReplace, boolean createBookmarksEnabled) {
|
boolean alwaysReplace, boolean createBookmarksEnabled) {
|
||||||
super("Apply Function Data Types", true, false, false);
|
super("Apply Function Data Types", true, false, false);
|
||||||
this.sourceCategories = List.of(sourceCategory);
|
this.sourceCategories = List.of(sourceCategory);
|
||||||
this.addresses = set;
|
this.addresses = set;
|
||||||
|
@ -102,8 +101,8 @@ public class ApplyFunctionDataTypesCmd extends BackgroundCommand {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applyTo(DomainObject obj, TaskMonitor monitor) {
|
public boolean applyTo(Program p, TaskMonitor monitor) {
|
||||||
program = (Program) obj;
|
program = p;
|
||||||
bookmarkMgr = program.getBookmarkManager();
|
bookmarkMgr = program.getBookmarkManager();
|
||||||
|
|
||||||
monitor.setMessage("Applying Function Signatures");
|
monitor.setMessage("Applying Function Signatures");
|
||||||
|
@ -179,8 +178,8 @@ public class ApplyFunctionDataTypesCmd extends BackgroundCommand {
|
||||||
* @param symbolMap symbol map where possible function definitions may be applied
|
* @param symbolMap symbol map where possible function definitions may be applied
|
||||||
* @throws CancelledException if task cancelled
|
* @throws CancelledException if task cancelled
|
||||||
*/
|
*/
|
||||||
private void applyFunctionDefinitions(TaskMonitor monitor,
|
private void applyFunctionDefinitions(TaskMonitor monitor, Map<String, List<Symbol>> symbolMap)
|
||||||
Map<String, List<Symbol>> symbolMap) throws CancelledException {
|
throws CancelledException {
|
||||||
|
|
||||||
Map<String, FunctionDefinition> functionNameMap = new HashMap<>();
|
Map<String, FunctionDefinition> functionNameMap = new HashMap<>();
|
||||||
for (Category cat : sourceCategories) {
|
for (Category cat : sourceCategories) {
|
||||||
|
@ -399,7 +398,7 @@ public class ApplyFunctionDataTypesCmd extends BackgroundCommand {
|
||||||
*
|
*
|
||||||
* @param symbolMap map of symbol names to all matching symbols
|
* @param symbolMap map of symbol names to all matching symbols
|
||||||
* @param prefix optional prefix on symbol to lookup
|
* @param prefix optional prefix on symbol to lookup
|
||||||
* @param fdef function definition
|
* @param functionName function name
|
||||||
* @return symbol definition; null if no symbol is found for the given name
|
* @return symbol definition; null if no symbol is found for the given name
|
||||||
*/
|
*/
|
||||||
private List<Symbol> lookupSymbol(Map<String, List<Symbol>> symbolMap, String prefix,
|
private List<Symbol> lookupSymbol(Map<String, List<Symbol>> symbolMap, String prefix,
|
||||||
|
|
|
@ -19,7 +19,6 @@ import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import ghidra.framework.cmd.BackgroundCommand;
|
import ghidra.framework.cmd.BackgroundCommand;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.data.*;
|
import ghidra.program.model.data.*;
|
||||||
import ghidra.program.model.lang.CompilerSpec;
|
import ghidra.program.model.lang.CompilerSpec;
|
||||||
|
@ -37,9 +36,11 @@ import ghidra.util.task.TaskMonitor;
|
||||||
/**
|
/**
|
||||||
* Command to create apply a function signature at an address.
|
* Command to create apply a function signature at an address.
|
||||||
*
|
*
|
||||||
*
|
* {@link Function} signature changes are applied using
|
||||||
|
* {@link Function#updateFunction(String, Variable, List, FunctionUpdateType, boolean, SourceType)}
|
||||||
|
* with an update type of {@link FunctionUpdateType#DYNAMIC_STORAGE_FORMAL_PARAMS}.
|
||||||
*/
|
*/
|
||||||
public class ApplyFunctionSignatureCmd extends BackgroundCommand {
|
public class ApplyFunctionSignatureCmd extends BackgroundCommand<Program> {
|
||||||
private Address entryPt;
|
private Address entryPt;
|
||||||
private SourceType source;
|
private SourceType source;
|
||||||
private FunctionRenameOption functionRenameOption;
|
private FunctionRenameOption functionRenameOption;
|
||||||
|
@ -159,8 +160,8 @@ public class ApplyFunctionSignatureCmd extends BackgroundCommand {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applyTo(DomainObject obj, TaskMonitor monitor) {
|
public boolean applyTo(Program p, TaskMonitor monitor) {
|
||||||
program = (Program) obj;
|
this.program = p;
|
||||||
|
|
||||||
Function func = program.getListing().getFunctionContaining(entryPt);
|
Function func = program.getListing().getFunctionContaining(entryPt);
|
||||||
|
|
||||||
|
|
|
@ -15,16 +15,17 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.cmd.function;
|
package ghidra.app.cmd.function;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.block.CodeBlock;
|
import ghidra.program.model.block.CodeBlock;
|
||||||
import ghidra.program.model.lang.*;
|
import ghidra.program.model.lang.ProcessorContext;
|
||||||
|
import ghidra.program.model.lang.Register;
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.*;
|
||||||
import ghidra.program.model.pcode.*;
|
import ghidra.program.model.pcode.*;
|
||||||
import ghidra.program.model.scalar.Scalar;
|
import ghidra.program.model.scalar.Scalar;
|
||||||
import ghidra.program.model.symbol.FlowType;
|
import ghidra.program.model.symbol.FlowType;
|
||||||
import ghidra.program.model.symbol.Reference;
|
|
||||||
import ghidra.program.model.util.*;
|
import ghidra.program.model.util.*;
|
||||||
import ghidra.program.util.*;
|
import ghidra.program.util.*;
|
||||||
import ghidra.program.util.SymbolicPropogator.Value;
|
import ghidra.program.util.SymbolicPropogator.Value;
|
||||||
|
@ -33,13 +34,6 @@ import ghidra.util.exception.*;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CallDepthChangeInfo.java
|
|
||||||
*
|
|
||||||
* Date: Feb 6, 2003
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Given a function in a program or the start of a function, record information
|
* Given a function in a program or the start of a function, record information
|
||||||
* about the change to a stack pointer from a subroutine call. The routine
|
* about the change to a stack pointer from a subroutine call. The routine
|
||||||
* getCallChange() can be called with the address of a call instruction. If the
|
* getCallChange() can be called with the address of a call instruction. If the
|
||||||
|
@ -49,10 +43,7 @@ import ghidra.util.task.TaskMonitor;
|
||||||
* The computation is based on a set of equations that are generated and solved.
|
* The computation is based on a set of equations that are generated and solved.
|
||||||
* Each equation represents the stack change for a given basic flow block or
|
* Each equation represents the stack change for a given basic flow block or
|
||||||
* call instruction within the function.
|
* call instruction within the function.
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class CallDepthChangeInfo {
|
public class CallDepthChangeInfo {
|
||||||
|
|
||||||
Program program;
|
Program program;
|
||||||
|
@ -142,17 +133,10 @@ public class CallDepthChangeInfo {
|
||||||
public CallDepthChangeInfo(Program program, Address addr, AddressSetView restrictSet,
|
public CallDepthChangeInfo(Program program, Address addr, AddressSetView restrictSet,
|
||||||
Register frameReg, TaskMonitor monitor) throws CancelledException {
|
Register frameReg, TaskMonitor monitor) throws CancelledException {
|
||||||
Function func = program.getFunctionManager().getFunctionContaining(addr);
|
Function func = program.getFunctionManager().getFunctionContaining(addr);
|
||||||
Register stackReg = program.getCompilerSpec().getStackPointer();
|
Register stackPtrReg = program.getCompilerSpec().getStackPointer();
|
||||||
initialize(func, restrictSet, stackReg, monitor);
|
initialize(func, restrictSet, stackPtrReg, monitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* initialize codeblocks and call locations.
|
|
||||||
*
|
|
||||||
* @param addressSetView
|
|
||||||
* @param monitor
|
|
||||||
* @throws CancelledException
|
|
||||||
*/
|
|
||||||
private void initialize(Function func, AddressSetView restrictSet, Register reg,
|
private void initialize(Function func, AddressSetView restrictSet, Register reg,
|
||||||
TaskMonitor monitor) throws CancelledException {
|
TaskMonitor monitor) throws CancelledException {
|
||||||
changeMap = new DefaultIntPropertyMap("change");
|
changeMap = new DefaultIntPropertyMap("change");
|
||||||
|
@ -177,6 +161,7 @@ public class CallDepthChangeInfo {
|
||||||
i = changeMap.getInt(addr);
|
i = changeMap.getInt(addr);
|
||||||
}
|
}
|
||||||
catch (NoValueException exc) {
|
catch (NoValueException exc) {
|
||||||
|
// ignore
|
||||||
}
|
}
|
||||||
|
|
||||||
return i;
|
return i;
|
||||||
|
@ -196,6 +181,7 @@ public class CallDepthChangeInfo {
|
||||||
depth = depthMap.getInt(addr);
|
depth = depthMap.getInt(addr);
|
||||||
}
|
}
|
||||||
catch (NoValueException exc) {
|
catch (NoValueException exc) {
|
||||||
|
// ignore
|
||||||
}
|
}
|
||||||
return depth;
|
return depth;
|
||||||
}
|
}
|
||||||
|
@ -221,6 +207,8 @@ public class CallDepthChangeInfo {
|
||||||
* unknown.
|
* unknown.
|
||||||
*
|
*
|
||||||
* @param instr instruction to analyze
|
* @param instr instruction to analyze
|
||||||
|
* @param procContext
|
||||||
|
* @param currentStackDepth
|
||||||
*
|
*
|
||||||
* @return int change to stack depth if it can be determined,
|
* @return int change to stack depth if it can be determined,
|
||||||
* Function.UNKNOWN_STACK_DEPTH_CHANGE otherwise.
|
* Function.UNKNOWN_STACK_DEPTH_CHANGE otherwise.
|
||||||
|
@ -396,7 +384,6 @@ public class CallDepthChangeInfo {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the stack depth change value that has been set at the indicated address.
|
* Gets the stack depth change value that has been set at the indicated address.
|
||||||
*
|
*
|
||||||
|
@ -475,7 +462,6 @@ public class CallDepthChangeInfo {
|
||||||
return ipm.getPropertyIterator(addressSet);
|
return ipm.getPropertyIterator(addressSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Follow the flows of the subroutine, accumulating information about the
|
* Follow the flows of the subroutine, accumulating information about the
|
||||||
* stack pointer and any other register the stack pointer is assigned to.
|
* stack pointer and any other register the stack pointer is assigned to.
|
||||||
|
@ -512,7 +498,8 @@ public class CallDepthChangeInfo {
|
||||||
try {
|
try {
|
||||||
stackValue = context.getValue(stackRegVarnode, true, this);
|
stackValue = context.getValue(stackRegVarnode, true, this);
|
||||||
|
|
||||||
if (stackValue != null && context.isSymbol(stackValue) && context.isStackSymbolicSpace(stackValue)) {
|
if (stackValue != null && context.isSymbol(stackValue) &&
|
||||||
|
context.isStackSymbolicSpace(stackValue)) {
|
||||||
int stackPointerDepth = (int) stackValue.getOffset();
|
int stackPointerDepth = (int) stackValue.getOffset();
|
||||||
setDepth(instr, stackPointerDepth);
|
setDepth(instr, stackPointerDepth);
|
||||||
}
|
}
|
||||||
|
@ -580,7 +567,6 @@ public class CallDepthChangeInfo {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public int getStackPurge() {
|
public int getStackPurge() {
|
||||||
return stackPurge;
|
return stackPurge;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
package ghidra.app.cmd.function;
|
package ghidra.app.cmd.function;
|
||||||
|
|
||||||
import ghidra.framework.cmd.BackgroundCommand;
|
import ghidra.framework.cmd.BackgroundCommand;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.program.model.address.AddressSetView;
|
import ghidra.program.model.address.AddressSetView;
|
||||||
import ghidra.program.model.data.*;
|
import ghidra.program.model.data.*;
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.*;
|
||||||
|
@ -27,8 +26,8 @@ import ghidra.util.task.TaskMonitor;
|
||||||
* Capture all selected function signature data types from the current program and put them
|
* Capture all selected function signature data types from the current program and put them
|
||||||
* in the data type manager.
|
* in the data type manager.
|
||||||
*/
|
*/
|
||||||
public class CaptureFunctionDataTypesCmd extends BackgroundCommand {
|
public class CaptureFunctionDataTypesCmd extends BackgroundCommand<Program> {
|
||||||
private Program program;
|
|
||||||
private DataTypeManager dtm;
|
private DataTypeManager dtm;
|
||||||
private AddressSetView set;
|
private AddressSetView set;
|
||||||
private CaptureFunctionDataTypesListener listener;
|
private CaptureFunctionDataTypesListener listener;
|
||||||
|
@ -40,6 +39,7 @@ public class CaptureFunctionDataTypesCmd extends BackgroundCommand {
|
||||||
* @param dtm data type manager containing the function signature data types
|
* @param dtm data type manager containing the function signature data types
|
||||||
* @param set set of addresses containing the entry points of the functions whose signatures
|
* @param set set of addresses containing the entry points of the functions whose signatures
|
||||||
* are to be turned into data types.
|
* are to be turned into data types.
|
||||||
|
* @param listener
|
||||||
*/
|
*/
|
||||||
public CaptureFunctionDataTypesCmd(DataTypeManager dtm, AddressSetView set,
|
public CaptureFunctionDataTypesCmd(DataTypeManager dtm, AddressSetView set,
|
||||||
CaptureFunctionDataTypesListener listener) {
|
CaptureFunctionDataTypesListener listener) {
|
||||||
|
@ -49,13 +49,8 @@ public class CaptureFunctionDataTypesCmd extends BackgroundCommand {
|
||||||
this.listener = listener;
|
this.listener = listener;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see ghidra.framework.cmd.BackgroundCommand#applyTo(ghidra.framework.model.DomainObject, ghidra.util.task.TaskMonitor)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applyTo(DomainObject obj, TaskMonitor monitor) {
|
public boolean applyTo(Program program, TaskMonitor monitor) {
|
||||||
program = (Program) obj;
|
|
||||||
|
|
||||||
monitor.setMessage("Capturing Function Data Types");
|
monitor.setMessage("Capturing Function Data Types");
|
||||||
boolean success = false;
|
boolean success = false;
|
||||||
|
|
|
@ -16,14 +16,12 @@
|
||||||
package ghidra.app.cmd.function;
|
package ghidra.app.cmd.function;
|
||||||
|
|
||||||
import ghidra.framework.cmd.Command;
|
import ghidra.framework.cmd.Command;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.program.database.ProgramDB;
|
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the name or comment field for a given function tag
|
* Updates the name or comment field for a given function tag
|
||||||
*/
|
*/
|
||||||
public class ChangeFunctionTagCmd implements Command {
|
public class ChangeFunctionTagCmd implements Command<Program> {
|
||||||
|
|
||||||
private final int field;
|
private final int field;
|
||||||
private final String tagName;
|
private final String tagName;
|
||||||
|
@ -51,8 +49,8 @@ public class ChangeFunctionTagCmd implements Command {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applyTo(DomainObject obj) {
|
public boolean applyTo(Program program) {
|
||||||
ProgramDB program = (ProgramDB) obj;
|
|
||||||
FunctionManager functionManager = program.getFunctionManager();
|
FunctionManager functionManager = program.getFunctionManager();
|
||||||
FunctionTagManager tagManager = functionManager.getFunctionTagManager();
|
FunctionTagManager tagManager = functionManager.getFunctionTagManager();
|
||||||
FunctionTag tag = tagManager.getFunctionTag(tagName);
|
FunctionTag tag = tagManager.getFunctionTag(tagName);
|
||||||
|
|
|
@ -16,14 +16,13 @@
|
||||||
package ghidra.app.cmd.function;
|
package ghidra.app.cmd.function;
|
||||||
|
|
||||||
import ghidra.framework.cmd.Command;
|
import ghidra.framework.cmd.Command;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.*;
|
||||||
import ghidra.program.model.symbol.*;
|
import ghidra.program.model.symbol.*;
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
import ghidra.util.exception.InvalidInputException;
|
import ghidra.util.exception.InvalidInputException;
|
||||||
|
|
||||||
public class CreateExternalFunctionCmd implements Command {
|
public class CreateExternalFunctionCmd implements Command<Program> {
|
||||||
|
|
||||||
private Symbol extSymbol;
|
private Symbol extSymbol;
|
||||||
|
|
||||||
|
@ -53,6 +52,7 @@ public class CreateExternalFunctionCmd implements Command {
|
||||||
* @param libraryName library name, if null the UNKNOWN library will be used
|
* @param libraryName library name, if null the UNKNOWN library will be used
|
||||||
* @param name function name (required)
|
* @param name function name (required)
|
||||||
* @param address the address of the function's entry point in the external library (optional)
|
* @param address the address of the function's entry point in the external library (optional)
|
||||||
|
* @param source the source type for this external function
|
||||||
*/
|
*/
|
||||||
public CreateExternalFunctionCmd(String libraryName, String name, Address address,
|
public CreateExternalFunctionCmd(String libraryName, String name, Address address,
|
||||||
SourceType source) {
|
SourceType source) {
|
||||||
|
@ -94,8 +94,8 @@ public class CreateExternalFunctionCmd implements Command {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applyTo(DomainObject obj) {
|
public boolean applyTo(Program program) {
|
||||||
Program program = (Program) obj;
|
|
||||||
if (extSymbol == null) {
|
if (extSymbol == null) {
|
||||||
return createExternalFunction(program);
|
return createExternalFunction(program);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,16 +16,17 @@
|
||||||
package ghidra.app.cmd.function;
|
package ghidra.app.cmd.function;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
import ghidra.framework.cmd.BackgroundCommand;
|
import ghidra.framework.cmd.BackgroundCommand;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.program.database.function.OverlappingFunctionException;
|
import ghidra.program.database.function.OverlappingFunctionException;
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.block.*;
|
import ghidra.program.model.block.FollowFlow;
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.*;
|
||||||
import ghidra.program.model.symbol.*;
|
import ghidra.program.model.symbol.*;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
import ghidra.util.exception.*;
|
import ghidra.util.exception.CancelledException;
|
||||||
|
import ghidra.util.exception.InvalidInputException;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -33,7 +34,7 @@ import ghidra.util.task.TaskMonitor;
|
||||||
* parameters used to create the function (Selection or just an address) and
|
* parameters used to create the function (Selection or just an address) and
|
||||||
* create the function on redo and clear on undo.
|
* create the function on redo and clear on undo.
|
||||||
*/
|
*/
|
||||||
public class CreateFunctionCmd extends BackgroundCommand {
|
public class CreateFunctionCmd extends BackgroundCommand<Program> {
|
||||||
|
|
||||||
private AddressSetView origEntries;
|
private AddressSetView origEntries;
|
||||||
private AddressSetView origBody;
|
private AddressSetView origBody;
|
||||||
|
@ -143,13 +144,9 @@ public class CreateFunctionCmd extends BackgroundCommand {
|
||||||
this(null, entry, null, SourceType.DEFAULT, findEntryPoint, false);
|
this(null, entry, null, SourceType.DEFAULT, findEntryPoint, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see ghidra.framework.cmd.BackgroundCommand#applyTo(ghidra.framework.model.DomainObject, ghidra.util.task.TaskMonitor)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applyTo(DomainObject obj, TaskMonitor monitor) {
|
public boolean applyTo(Program p, TaskMonitor monitor) {
|
||||||
program = (Program) obj;
|
program = p;
|
||||||
|
|
||||||
Namespace globalNameSpace = program.getGlobalNamespace();
|
Namespace globalNameSpace = program.getGlobalNamespace();
|
||||||
|
|
||||||
|
@ -181,7 +178,7 @@ public class CreateFunctionCmd extends BackgroundCommand {
|
||||||
extFunc = ((ExternalLocation) symObj).createFunction();
|
extFunc = ((ExternalLocation) symObj).createFunction();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Msg.error(this, "Unexpected external symbol object: " + obj.getClass());
|
Msg.error(this, "Unexpected external symbol object: " + symObj.getClass());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (funcName != null) {
|
if (funcName != null) {
|
||||||
|
@ -215,7 +212,8 @@ public class CreateFunctionCmd extends BackgroundCommand {
|
||||||
try {
|
try {
|
||||||
didCreate = createFunction(monitor, funcName, nameSpace, origEntry,
|
didCreate = createFunction(monitor, funcName, nameSpace, origEntry,
|
||||||
origBody, tmpSource);
|
origBody, tmpSource);
|
||||||
} catch (OverlappingFunctionException e) {
|
}
|
||||||
|
catch (OverlappingFunctionException e) {
|
||||||
// try to create again, sometimes thunks can get resolved that
|
// try to create again, sometimes thunks can get resolved that
|
||||||
// can't be detected, for example a thunk->function->thunk
|
// can't be detected, for example a thunk->function->thunk
|
||||||
// where the final thunk gets created
|
// where the final thunk gets created
|
||||||
|
@ -274,10 +272,9 @@ public class CreateFunctionCmd extends BackgroundCommand {
|
||||||
* @throws OverlappingFunctionException if new function overlaps with existing and couldn't fix
|
* @throws OverlappingFunctionException if new function overlaps with existing and couldn't fix
|
||||||
* @throws InvalidInputException bad characters in function name
|
* @throws InvalidInputException bad characters in function name
|
||||||
*/
|
*/
|
||||||
private boolean createFunction(TaskMonitor monitor, String funcName,
|
private boolean createFunction(TaskMonitor monitor, String funcName, Namespace nameSpace,
|
||||||
Namespace nameSpace, Address entry, AddressSetView body,
|
Address entry, AddressSetView body, SourceType nameSource)
|
||||||
SourceType nameSource) throws InvalidInputException,
|
throws InvalidInputException, OverlappingFunctionException, CancelledException {
|
||||||
OverlappingFunctionException, CancelledException {
|
|
||||||
|
|
||||||
FunctionManager functionMgr = program.getFunctionManager();
|
FunctionManager functionMgr = program.getFunctionManager();
|
||||||
|
|
||||||
|
@ -356,8 +353,7 @@ public class CreateFunctionCmd extends BackgroundCommand {
|
||||||
*/
|
*/
|
||||||
private boolean createFunction(Namespace nameSpace, String funcName, Address entry,
|
private boolean createFunction(Namespace nameSpace, String funcName, Address entry,
|
||||||
AddressSetView body, SourceType nameSource, Map<Function, AddressSetView> bodyChangeMap,
|
AddressSetView body, SourceType nameSource, Map<Function, AddressSetView> bodyChangeMap,
|
||||||
TaskMonitor monitor)
|
TaskMonitor monitor) throws OverlappingFunctionException, InvalidInputException {
|
||||||
throws OverlappingFunctionException, InvalidInputException {
|
|
||||||
|
|
||||||
Listing listing = program.getListing();
|
Listing listing = program.getListing();
|
||||||
|
|
||||||
|
@ -408,9 +404,9 @@ public class CreateFunctionCmd extends BackgroundCommand {
|
||||||
* @throws CancelledException user cancelled
|
* @throws CancelledException user cancelled
|
||||||
* @throws OverlappingFunctionException existing functions overlap and couldn't reconcile
|
* @throws OverlappingFunctionException existing functions overlap and couldn't reconcile
|
||||||
*/
|
*/
|
||||||
private static AddressSetView subtractBodyFromExisting(Program program, Address entry, AddressSetView newFuncBody,
|
private static AddressSetView subtractBodyFromExisting(Program program, Address entry,
|
||||||
Map<Function, AddressSetView> bodyChangeMap, TaskMonitor monitor)
|
AddressSetView newFuncBody, Map<Function, AddressSetView> bodyChangeMap,
|
||||||
throws CancelledException, OverlappingFunctionException {
|
TaskMonitor monitor) throws CancelledException, OverlappingFunctionException {
|
||||||
// get all functions that overlap new function body
|
// get all functions that overlap new function body
|
||||||
Iterator<Function> iter = program.getFunctionManager().getFunctionsOverlapping(newFuncBody);
|
Iterator<Function> iter = program.getFunctionManager().getFunctionsOverlapping(newFuncBody);
|
||||||
|
|
||||||
|
@ -437,19 +433,22 @@ public class CreateFunctionCmd extends BackgroundCommand {
|
||||||
if (overlapEntryPoint.compareTo(entry) < 0) {
|
if (overlapEntryPoint.compareTo(entry) < 0) {
|
||||||
// overlap function is before, subtract from entry to end of new function
|
// overlap function is before, subtract from entry to end of new function
|
||||||
overlapEndAddr = newFuncBody.getMaxAddress();
|
overlapEndAddr = newFuncBody.getMaxAddress();
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
// overlap function is after, subtract from entry to entry of overlapping function
|
// overlap function is after, subtract from entry to entry of overlapping function
|
||||||
overlapEndAddr = overlapEntryPoint.previous();
|
overlapEndAddr = overlapEntryPoint.previous();
|
||||||
}
|
}
|
||||||
AddressSet overlapAddrsShouldBeInNewFunction = new AddressSet(entry,overlapEndAddr);
|
AddressSet overlapAddrsShouldBeInNewFunction = new AddressSet(entry, overlapEndAddr);
|
||||||
AddressSetView newOverlapFuncBody = overlapFuncBody.subtract(overlapAddrsShouldBeInNewFunction);
|
AddressSetView newOverlapFuncBody =
|
||||||
|
overlapFuncBody.subtract(overlapAddrsShouldBeInNewFunction);
|
||||||
try {
|
try {
|
||||||
if (!overlapFuncBody.equals(newOverlapFuncBody)) {
|
if (!overlapFuncBody.equals(newOverlapFuncBody)) {
|
||||||
overlapFunc.setBody(newOverlapFuncBody); // set overlap body with new function body addresses removed
|
overlapFunc.setBody(newOverlapFuncBody); // set overlap body with new function body addresses removed
|
||||||
bodyChangeMap.put(overlapFunc, overlapFuncBody); // save old overlap body
|
bodyChangeMap.put(overlapFunc, overlapFuncBody); // save old overlap body
|
||||||
}
|
}
|
||||||
overlapFuncBody = newOverlapFuncBody;
|
overlapFuncBody = newOverlapFuncBody;
|
||||||
} catch (OverlappingFunctionException oe) {
|
}
|
||||||
|
catch (OverlappingFunctionException oe) {
|
||||||
// do nothing, will just subtract entire overlapping body from new function body
|
// do nothing, will just subtract entire overlapping body from new function body
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -524,9 +523,7 @@ public class CreateFunctionCmd extends BackgroundCommand {
|
||||||
*/
|
*/
|
||||||
private static void restoreOriginalBodies(Map<Function, AddressSetView> bodyChangeMap) {
|
private static void restoreOriginalBodies(Map<Function, AddressSetView> bodyChangeMap) {
|
||||||
Set<Map.Entry<Function, AddressSetView>> entries = bodyChangeMap.entrySet();
|
Set<Map.Entry<Function, AddressSetView>> entries = bodyChangeMap.entrySet();
|
||||||
Iterator<Map.Entry<Function, AddressSetView>> iter = entries.iterator();
|
for (Entry<Function, AddressSetView> entry : entries) {
|
||||||
while (iter.hasNext()) {
|
|
||||||
Map.Entry<Function, AddressSetView> entry = iter.next();
|
|
||||||
try {
|
try {
|
||||||
entry.getKey().setBody(entry.getValue());
|
entry.getKey().setBody(entry.getValue());
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,6 @@ package ghidra.app.cmd.function;
|
||||||
|
|
||||||
import ghidra.app.services.DataTypeManagerService;
|
import ghidra.app.services.DataTypeManagerService;
|
||||||
import ghidra.framework.cmd.Command;
|
import ghidra.framework.cmd.Command;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.framework.plugintool.ServiceProvider;
|
import ghidra.framework.plugintool.ServiceProvider;
|
||||||
import ghidra.framework.store.FileSystem;
|
import ghidra.framework.store.FileSystem;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
|
@ -28,7 +27,7 @@ import ghidra.program.model.listing.*;
|
||||||
* Command for creating a function definition data type based on the
|
* Command for creating a function definition data type based on the
|
||||||
* function signature for a function at an address.
|
* function signature for a function at an address.
|
||||||
*/
|
*/
|
||||||
public class CreateFunctionDefinitionCmd implements Command {
|
public class CreateFunctionDefinitionCmd implements Command<Program> {
|
||||||
private Address entry;
|
private Address entry;
|
||||||
private final ServiceProvider serviceProvider;
|
private final ServiceProvider serviceProvider;
|
||||||
private String statusMsg = "";
|
private String statusMsg = "";
|
||||||
|
@ -37,28 +36,23 @@ public class CreateFunctionDefinitionCmd implements Command {
|
||||||
* Constructs a new command for creating a function definition.
|
* Constructs a new command for creating a function definition.
|
||||||
* @param entry entry point address for the function whose signature is to
|
* @param entry entry point address for the function whose signature is to
|
||||||
* be used to create the function defintion data type.
|
* be used to create the function defintion data type.
|
||||||
|
* @param serviceProvider optional service provider (may be null). If specified and the
|
||||||
|
* {@link DataTypeManagerService} is found, the newly created function definition
|
||||||
|
* will be selected within the GUI.
|
||||||
*/
|
*/
|
||||||
public CreateFunctionDefinitionCmd(Address entry, ServiceProvider serviceProvider) {
|
public CreateFunctionDefinitionCmd(Address entry, ServiceProvider serviceProvider) {
|
||||||
this.entry = entry;
|
this.entry = entry;
|
||||||
this.serviceProvider = serviceProvider;
|
this.serviceProvider = serviceProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see ghidra.framework.cmd.Command#getName()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "Create Function Definition";
|
return "Create Function Definition";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see ghidra.framework.cmd.Command#applyTo(ghidra.framework.model.DomainObject)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applyTo(DomainObject obj) {
|
public boolean applyTo(Program program) {
|
||||||
Program program = (Program) obj;
|
|
||||||
// save off the function signature
|
// save off the function signature
|
||||||
// get the body, comment, stack, return type
|
// get the body, comment, stack, return type
|
||||||
Listing listing = program.getListing();
|
Listing listing = program.getListing();
|
||||||
|
@ -83,17 +77,16 @@ public class CreateFunctionDefinitionCmd implements Command {
|
||||||
FunctionDefinitionDataType functionDef = new FunctionDefinitionDataType(sig);
|
FunctionDefinitionDataType functionDef = new FunctionDefinitionDataType(sig);
|
||||||
DataType newType = dtm.resolve(functionDef, null);
|
DataType newType = dtm.resolve(functionDef, null);
|
||||||
|
|
||||||
DataTypeManagerService service = serviceProvider.getService(DataTypeManagerService.class);
|
if (serviceProvider != null) {
|
||||||
|
DataTypeManagerService service =
|
||||||
|
serviceProvider.getService(DataTypeManagerService.class);
|
||||||
if (service != null) {
|
if (service != null) {
|
||||||
service.setDataTypeSelected(newType);
|
service.setDataTypeSelected(newType);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.framework.cmd.Command#getStatusMsg()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public String getStatusMsg() {
|
public String getStatusMsg() {
|
||||||
return statusMsg;
|
return statusMsg;
|
||||||
|
|
|
@ -16,15 +16,12 @@
|
||||||
package ghidra.app.cmd.function;
|
package ghidra.app.cmd.function;
|
||||||
|
|
||||||
import ghidra.framework.cmd.Command;
|
import ghidra.framework.cmd.Command;
|
||||||
import ghidra.framework.model.DomainObject;
|
import ghidra.program.model.listing.*;
|
||||||
import ghidra.program.database.ProgramDB;
|
|
||||||
import ghidra.program.model.listing.FunctionManager;
|
|
||||||
import ghidra.program.model.listing.FunctionTagManager;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Command for assigning a tag to a function
|
* Command for assigning a tag to a function
|
||||||
*/
|
*/
|
||||||
public class CreateFunctionTagCmd implements Command {
|
public class CreateFunctionTagCmd implements Command<Program> {
|
||||||
|
|
||||||
private String name;
|
private String name;
|
||||||
private String comment;
|
private String comment;
|
||||||
|
@ -51,8 +48,7 @@ public class CreateFunctionTagCmd implements Command {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applyTo(DomainObject obj) {
|
public boolean applyTo(Program program) {
|
||||||
ProgramDB program = (ProgramDB) obj;
|
|
||||||
FunctionManager functionManager = program.getFunctionManager();
|
FunctionManager functionManager = program.getFunctionManager();
|
||||||
FunctionTagManager tagManager = functionManager.getFunctionTagManager();
|
FunctionTagManager tagManager = functionManager.getFunctionTagManager();
|
||||||
tagManager.createFunctionTag(name, comment);
|
tagManager.createFunctionTag(name, comment);
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
package ghidra.app.cmd.function;
|
package ghidra.app.cmd.function;
|
||||||
|
|
||||||
import ghidra.framework.cmd.BackgroundCommand;
|
import ghidra.framework.cmd.BackgroundCommand;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.*;
|
||||||
import ghidra.program.model.symbol.SourceType;
|
import ghidra.program.model.symbol.SourceType;
|
||||||
|
@ -31,9 +30,8 @@ import ghidra.util.task.TaskMonitor;
|
||||||
* also discarded.
|
* also discarded.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class CreateMultipleFunctionsCmd extends BackgroundCommand {
|
public class CreateMultipleFunctionsCmd extends BackgroundCommand<Program> {
|
||||||
|
|
||||||
private Program program;
|
|
||||||
private AddressSetView selection;
|
private AddressSetView selection;
|
||||||
private SourceType source;
|
private SourceType source;
|
||||||
|
|
||||||
|
@ -44,8 +42,7 @@ public class CreateMultipleFunctionsCmd extends BackgroundCommand {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applyTo(DomainObject obj, TaskMonitor monitor) {
|
public boolean applyTo(Program program, TaskMonitor monitor) {
|
||||||
program = (Program) obj;
|
|
||||||
|
|
||||||
Listing listing = program.getListing();
|
Listing listing = program.getListing();
|
||||||
AddressSet addressSet = new AddressSet(selection);
|
AddressSet addressSet = new AddressSet(selection);
|
||||||
|
@ -60,8 +57,10 @@ public class CreateMultipleFunctionsCmd extends BackgroundCommand {
|
||||||
Function function = listing.getFunctionContaining(address);
|
Function function = listing.getFunctionContaining(address);
|
||||||
if (function == null) {
|
if (function == null) {
|
||||||
// Create the next function.
|
// Create the next function.
|
||||||
Function createdFunction = createFunction(address, program, monitor);
|
CreateFunctionCmd createFunctionCmd =
|
||||||
if (createdFunction != null) {
|
new CreateFunctionCmd(null, address, null, source);
|
||||||
|
if (createFunctionCmd.applyTo(program, monitor)) {
|
||||||
|
function = createFunctionCmd.getFunction();
|
||||||
functionsCreated++;
|
functionsCreated++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -83,19 +82,4 @@ public class CreateMultipleFunctionsCmd extends BackgroundCommand {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a function at entry point in the specified program.
|
|
||||||
* @param entryPoint the entry point of the function
|
|
||||||
* @param currentProgram the program where the function should be created
|
|
||||||
* @param monitor the task monitor that allows the user to cancel
|
|
||||||
* @return the new function or null if the function was not created
|
|
||||||
*/
|
|
||||||
public final Function createFunction(Address entryPoint, Program currentProgram,
|
|
||||||
TaskMonitor monitor) {
|
|
||||||
CreateFunctionCmd cmd = new CreateFunctionCmd(null, entryPoint, null, source);
|
|
||||||
if (cmd.applyTo(currentProgram, monitor)) {
|
|
||||||
return currentProgram.getListing().getFunctionAt(entryPoint);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,6 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
import ghidra.app.util.PseudoDisassembler;
|
import ghidra.app.util.PseudoDisassembler;
|
||||||
import ghidra.framework.cmd.BackgroundCommand;
|
import ghidra.framework.cmd.BackgroundCommand;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.program.database.function.OverlappingFunctionException;
|
import ghidra.program.database.function.OverlappingFunctionException;
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.block.*;
|
import ghidra.program.model.block.*;
|
||||||
|
@ -40,7 +39,7 @@ import ghidra.util.task.TaskMonitor;
|
||||||
/**
|
/**
|
||||||
* Command for creating a thunk function at an address.
|
* Command for creating a thunk function at an address.
|
||||||
*/
|
*/
|
||||||
public class CreateThunkFunctionCmd extends BackgroundCommand {
|
public class CreateThunkFunctionCmd extends BackgroundCommand<Program> {
|
||||||
private Address entry;
|
private Address entry;
|
||||||
private AddressSetView body;
|
private AddressSetView body;
|
||||||
private Address referencedFunctionAddr;
|
private Address referencedFunctionAddr;
|
||||||
|
@ -144,8 +143,7 @@ public class CreateThunkFunctionCmd extends BackgroundCommand {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applyTo(DomainObject obj, TaskMonitor monitor) {
|
public boolean applyTo(Program program, TaskMonitor monitor) {
|
||||||
Program program = (Program) obj;
|
|
||||||
|
|
||||||
FunctionManager functionMgr = program.getFunctionManager();
|
FunctionManager functionMgr = program.getFunctionManager();
|
||||||
|
|
||||||
|
@ -401,7 +399,8 @@ public class CreateThunkFunctionCmd extends BackgroundCommand {
|
||||||
return destRef.getDestinationAddress();
|
return destRef.getDestinationAddress();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (CancelledException e) {
|
}
|
||||||
|
catch (CancelledException e) {
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -468,7 +467,8 @@ public class CreateThunkFunctionCmd extends BackgroundCommand {
|
||||||
new ContextEvaluatorAdapter() {
|
new ContextEvaluatorAdapter() {
|
||||||
@Override
|
@Override
|
||||||
public boolean evaluateReference(VarnodeContext context, Instruction instr,
|
public boolean evaluateReference(VarnodeContext context, Instruction instr,
|
||||||
int pcodeop, Address address, int size, DataType dataType, RefType refType) {
|
int pcodeop, Address address, int size, DataType dataType,
|
||||||
|
RefType refType) {
|
||||||
// go ahead and place the reference, since it is a constant.
|
// go ahead and place the reference, since it is a constant.
|
||||||
if (refType.isComputed() && refType.isFlow() &&
|
if (refType.isComputed() && refType.isFlow() &&
|
||||||
program.getMemory().contains(address)) {
|
program.getMemory().contains(address)) {
|
||||||
|
@ -494,8 +494,7 @@ public class CreateThunkFunctionCmd extends BackgroundCommand {
|
||||||
if (value != null && program.getListing().getInstructionAt(addr) == null) {
|
if (value != null && program.getListing().getInstructionAt(addr) == null) {
|
||||||
try {
|
try {
|
||||||
program.getProgramContext()
|
program.getProgramContext()
|
||||||
.setValue(isaModeRegister, addr, addr,
|
.setValue(isaModeRegister, addr, addr, value);
|
||||||
value);
|
|
||||||
}
|
}
|
||||||
catch (ContextChangeException e) {
|
catch (ContextChangeException e) {
|
||||||
// ignore
|
// ignore
|
||||||
|
|
|
@ -16,14 +16,13 @@
|
||||||
package ghidra.app.cmd.function;
|
package ghidra.app.cmd.function;
|
||||||
|
|
||||||
import ghidra.framework.cmd.Command;
|
import ghidra.framework.cmd.Command;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Command for clearing a function at an address.
|
* Command for clearing a function at an address.
|
||||||
*/
|
*/
|
||||||
public class DeleteFunctionCmd implements Command {
|
public class DeleteFunctionCmd implements Command<Program> {
|
||||||
private Address entry;
|
private Address entry;
|
||||||
private boolean ignoreMissingFunction;
|
private boolean ignoreMissingFunction;
|
||||||
|
|
||||||
|
@ -40,21 +39,14 @@ public class DeleteFunctionCmd implements Command {
|
||||||
this.ignoreMissingFunction = ignoreMissingFunction;
|
this.ignoreMissingFunction = ignoreMissingFunction;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see ghidra.framework.cmd.Command#getName()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "Delete Function";
|
return "Delete Function";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.framework.cmd.Command#applyTo(ghidra.framework.model.DomainObject)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applyTo(DomainObject obj) {
|
public boolean applyTo(Program program) {
|
||||||
Program program = (Program) obj;
|
|
||||||
// save off the function signature
|
// save off the function signature
|
||||||
// get the body, comment, stack, return type
|
// get the body, comment, stack, return type
|
||||||
Listing listing = program.getListing();
|
Listing listing = program.getListing();
|
||||||
|
@ -75,9 +67,6 @@ public class DeleteFunctionCmd implements Command {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.framework.cmd.Command#getStatusMsg()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public String getStatusMsg() {
|
public String getStatusMsg() {
|
||||||
return "";
|
return "";
|
||||||
|
|
|
@ -16,16 +16,13 @@
|
||||||
package ghidra.app.cmd.function;
|
package ghidra.app.cmd.function;
|
||||||
|
|
||||||
import ghidra.framework.cmd.BackgroundCommand;
|
import ghidra.framework.cmd.BackgroundCommand;
|
||||||
import ghidra.framework.model.DomainObject;
|
import ghidra.program.model.listing.*;
|
||||||
import ghidra.program.database.ProgramDB;
|
|
||||||
import ghidra.program.model.listing.FunctionManager;
|
|
||||||
import ghidra.program.model.listing.FunctionTag;
|
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Command for deleting a tag from the system
|
* Command for deleting a tag from the system
|
||||||
*/
|
*/
|
||||||
public class DeleteFunctionTagCmd extends BackgroundCommand {
|
public class DeleteFunctionTagCmd extends BackgroundCommand<Program> {
|
||||||
|
|
||||||
private String tagName;
|
private String tagName;
|
||||||
|
|
||||||
|
@ -39,9 +36,7 @@ public class DeleteFunctionTagCmd extends BackgroundCommand {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applyTo(DomainObject obj, TaskMonitor monitor) {
|
public boolean applyTo(Program program, TaskMonitor monitor) {
|
||||||
|
|
||||||
ProgramDB program = (ProgramDB) obj;
|
|
||||||
FunctionManager functionManager = program.getFunctionManager();
|
FunctionManager functionManager = program.getFunctionManager();
|
||||||
FunctionTag tag = functionManager.getFunctionTagManager().getFunctionTag(tagName);
|
FunctionTag tag = functionManager.getFunctionTagManager().getFunctionTag(tagName);
|
||||||
if (tag != null) {
|
if (tag != null) {
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -17,13 +16,12 @@
|
||||||
package ghidra.app.cmd.function;
|
package ghidra.app.cmd.function;
|
||||||
|
|
||||||
import ghidra.framework.cmd.Command;
|
import ghidra.framework.cmd.Command;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Command for deleting a variable in a function.
|
* Command for deleting a variable in a function.
|
||||||
*/
|
*/
|
||||||
public class DeleteVariableCmd implements Command {
|
public class DeleteVariableCmd implements Command<Program> {
|
||||||
|
|
||||||
private Variable var;
|
private Variable var;
|
||||||
|
|
||||||
|
@ -35,6 +33,7 @@ public class DeleteVariableCmd implements Command {
|
||||||
*
|
*
|
||||||
* @see ghidra.framework.cmd.Command#getName()
|
* @see ghidra.framework.cmd.Command#getName()
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "Delete " + (var instanceof Parameter ? "Parameter" : "Variable");
|
return "Delete " + (var instanceof Parameter ? "Parameter" : "Variable");
|
||||||
}
|
}
|
||||||
|
@ -43,17 +42,20 @@ public class DeleteVariableCmd implements Command {
|
||||||
*
|
*
|
||||||
* @see ghidra.framework.cmd.Command#applyTo(ghidra.framework.model.DomainObject)
|
* @see ghidra.framework.cmd.Command#applyTo(ghidra.framework.model.DomainObject)
|
||||||
*/
|
*/
|
||||||
public boolean applyTo(DomainObject obj) {
|
@Override
|
||||||
|
public boolean applyTo(Program program) {
|
||||||
Function f = var.getFunction();
|
Function f = var.getFunction();
|
||||||
|
if (f == null || f.getProgram() != program) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
f.removeVariable(var);
|
f.removeVariable(var);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see ghidra.framework.cmd.Command#getStatusMsg()
|
* @see ghidra.framework.cmd.Command#getStatusMsg()
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public String getStatusMsg() {
|
public String getStatusMsg() {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
package ghidra.app.cmd.function;
|
package ghidra.app.cmd.function;
|
||||||
|
|
||||||
import ghidra.framework.cmd.BackgroundCommand;
|
import ghidra.framework.cmd.BackgroundCommand;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.lang.Processor;
|
import ghidra.program.model.lang.Processor;
|
||||||
import ghidra.program.model.lang.PrototypeModel;
|
import ghidra.program.model.lang.PrototypeModel;
|
||||||
|
@ -32,7 +31,7 @@ import ghidra.util.task.TaskMonitor;
|
||||||
/**
|
/**
|
||||||
* Command for analyzing the Stack; the command is run in the background.
|
* Command for analyzing the Stack; the command is run in the background.
|
||||||
*/
|
*/
|
||||||
public class FunctionPurgeAnalysisCmd extends BackgroundCommand {
|
public class FunctionPurgeAnalysisCmd extends BackgroundCommand<Program> {
|
||||||
private AddressSetView entryPoints;
|
private AddressSetView entryPoints;
|
||||||
private Program program;
|
private Program program;
|
||||||
private PrototypeModel[] nearFarModels = null;
|
private PrototypeModel[] nearFarModels = null;
|
||||||
|
@ -52,13 +51,9 @@ public class FunctionPurgeAnalysisCmd extends BackgroundCommand {
|
||||||
entryPoints = entries;
|
entryPoints = entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see ghidra.framework.cmd.BackgroundCommand#applyTo(ghidra.framework.model.DomainObject, ghidra.util.task.TaskMonitor)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applyTo(DomainObject obj, TaskMonitor monitor) {
|
public boolean applyTo(Program p, TaskMonitor monitor) {
|
||||||
program = (Program) obj;
|
program = p;
|
||||||
|
|
||||||
Processor processor = program.getLanguage().getProcessor();
|
Processor processor = program.getLanguage().getProcessor();
|
||||||
AddressSpace defaultSpace = program.getLanguage().getDefaultSpace();
|
AddressSpace defaultSpace = program.getLanguage().getDefaultSpace();
|
||||||
|
|
|
@ -18,7 +18,6 @@ package ghidra.app.cmd.function;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import ghidra.framework.cmd.BackgroundCommand;
|
import ghidra.framework.cmd.BackgroundCommand;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.data.DataType;
|
import ghidra.program.model.data.DataType;
|
||||||
import ghidra.program.model.data.Undefined;
|
import ghidra.program.model.data.Undefined;
|
||||||
|
@ -31,12 +30,11 @@ import ghidra.util.Msg;
|
||||||
import ghidra.util.exception.*;
|
import ghidra.util.exception.*;
|
||||||
import ghidra.util.state.*;
|
import ghidra.util.state.*;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
import ghidra.util.task.TaskMonitorAdapter;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Command for analyzing the Stack; the command is run in the background.
|
* Command for analyzing the Stack; the command is run in the background.
|
||||||
*/
|
*/
|
||||||
public class FunctionResultStateStackAnalysisCmd extends BackgroundCommand {
|
public class FunctionResultStateStackAnalysisCmd extends BackgroundCommand<Program> {
|
||||||
private AddressSet entryPoints = new AddressSet();
|
private AddressSet entryPoints = new AddressSet();
|
||||||
private boolean forceProcessing = false;
|
private boolean forceProcessing = false;
|
||||||
private boolean dontCreateNewVariables = false;
|
private boolean dontCreateNewVariables = false;
|
||||||
|
@ -65,13 +63,8 @@ public class FunctionResultStateStackAnalysisCmd extends BackgroundCommand {
|
||||||
this(new AddressSet(entry, entry), forceProcessing);
|
this(new AddressSet(entry, entry), forceProcessing);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see ghidra.framework.cmd.BackgroundCommand#applyTo(ghidra.framework.model.DomainObject, ghidra.util.task.TaskMonitor)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applyTo(DomainObject obj, TaskMonitor monitor) {
|
public boolean applyTo(Program program, TaskMonitor monitor) {
|
||||||
Program program = (Program) obj;
|
|
||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
monitor.initialize(entryPoints.getNumAddresses());
|
monitor.initialize(entryPoints.getNumAddresses());
|
||||||
|
@ -335,13 +328,10 @@ public class FunctionResultStateStackAnalysisCmd extends BackgroundCommand {
|
||||||
for (SequenceNumber seq : results.getReturnAddresses()) {
|
for (SequenceNumber seq : results.getReturnAddresses()) {
|
||||||
ContextState returnState = results.getContextStates(seq).next();
|
ContextState returnState = results.getContextStates(seq).next();
|
||||||
Varnode varnode =
|
Varnode varnode =
|
||||||
returnState.get(results.getStackPointerVarnode(),
|
returnState.get(results.getStackPointerVarnode(), TaskMonitor.DUMMY);
|
||||||
TaskMonitor.DUMMY);
|
Varnode zero = new Varnode(addrFactory.getConstantSpace().getAddress(0),
|
||||||
Varnode zero =
|
|
||||||
new Varnode(addrFactory.getConstantSpace().getAddress(0),
|
|
||||||
stackReg.getMinimumByteSize());
|
stackReg.getMinimumByteSize());
|
||||||
varnode =
|
varnode = replaceInputVarnodes(varnode, results.getStackPointerVarnode(), zero, 4,
|
||||||
replaceInputVarnodes(varnode, results.getStackPointerVarnode(), zero, 4,
|
|
||||||
monitor);
|
monitor);
|
||||||
if (varnode == null) {
|
if (varnode == null) {
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -15,8 +15,10 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.cmd.function;
|
package ghidra.app.cmd.function;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Stack;
|
||||||
|
|
||||||
import ghidra.framework.cmd.BackgroundCommand;
|
import ghidra.framework.cmd.BackgroundCommand;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.data.*;
|
import ghidra.program.model.data.*;
|
||||||
import ghidra.program.model.lang.Register;
|
import ghidra.program.model.lang.Register;
|
||||||
|
@ -28,14 +30,11 @@ import ghidra.util.Msg;
|
||||||
import ghidra.util.exception.*;
|
import ghidra.util.exception.*;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Stack;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Command for analyzing the Stack; the command is run in the background.
|
* Command for analyzing the Stack; the command is run in the background.
|
||||||
* NOTE: referenced thunk-functions should be created prior to this command
|
* NOTE: referenced thunk-functions should be created prior to this command
|
||||||
*/
|
*/
|
||||||
public class FunctionStackAnalysisCmd extends BackgroundCommand {
|
public class FunctionStackAnalysisCmd extends BackgroundCommand<Program> {
|
||||||
private AddressSet entryPoints = new AddressSet();
|
private AddressSet entryPoints = new AddressSet();
|
||||||
private Program program;
|
private Program program;
|
||||||
private boolean forceProcessing = false;
|
private boolean forceProcessing = false;
|
||||||
|
@ -76,13 +75,9 @@ public class FunctionStackAnalysisCmd extends BackgroundCommand {
|
||||||
doLocals = doLocalAnalysis;
|
doLocals = doLocalAnalysis;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see ghidra.framework.cmd.BackgroundCommand#applyTo(ghidra.framework.model.DomainObject, ghidra.util.task.TaskMonitor)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applyTo(DomainObject obj, TaskMonitor monitor) {
|
public boolean applyTo(Program p, TaskMonitor monitor) {
|
||||||
program = (Program) obj;
|
program = p;
|
||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
monitor.initialize(entryPoints.getNumAddresses());
|
monitor.initialize(entryPoints.getNumAddresses());
|
||||||
|
@ -285,7 +280,8 @@ public class FunctionStackAnalysisCmd extends BackgroundCommand {
|
||||||
// return true;
|
// return true;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
private void defineFuncVariable(Function func, Instruction instr, int opIndex, int stackOffset) {
|
private void defineFuncVariable(Function func, Instruction instr, int opIndex,
|
||||||
|
int stackOffset) {
|
||||||
|
|
||||||
ReferenceManager refMgr = program.getReferenceManager();
|
ReferenceManager refMgr = program.getReferenceManager();
|
||||||
|
|
||||||
|
@ -365,8 +361,7 @@ public class FunctionStackAnalysisCmd extends BackgroundCommand {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// only create variables at locations where a variable doesn't exist
|
// only create variables at locations where a variable doesn't exist
|
||||||
var =
|
var = frame.createVariable(null, frameLoc, Undefined.getUndefinedDataType(refSize),
|
||||||
frame.createVariable(null, frameLoc, Undefined.getUndefinedDataType(refSize),
|
|
||||||
SourceType.ANALYSIS);
|
SourceType.ANALYSIS);
|
||||||
}
|
}
|
||||||
catch (DuplicateNameException e) {
|
catch (DuplicateNameException e) {
|
||||||
|
|
|
@ -19,7 +19,6 @@ import java.math.BigInteger;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import ghidra.framework.cmd.BackgroundCommand;
|
import ghidra.framework.cmd.BackgroundCommand;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.data.DataType;
|
import ghidra.program.model.data.DataType;
|
||||||
import ghidra.program.model.data.Undefined;
|
import ghidra.program.model.data.Undefined;
|
||||||
|
@ -39,7 +38,7 @@ import ghidra.util.task.TaskMonitor;
|
||||||
* Command for analyzing the Stack; the command is run in the background.
|
* Command for analyzing the Stack; the command is run in the background.
|
||||||
* NOTE: referenced thunk-functions should be created prior to this command
|
* NOTE: referenced thunk-functions should be created prior to this command
|
||||||
*/
|
*/
|
||||||
public class NewFunctionStackAnalysisCmd extends BackgroundCommand {
|
public class NewFunctionStackAnalysisCmd extends BackgroundCommand<Program> {
|
||||||
|
|
||||||
private static final int MAX_PARAM_OFFSET = 2048; // max size of param reference space
|
private static final int MAX_PARAM_OFFSET = 2048; // max size of param reference space
|
||||||
private static final int MAX_LOCAL_OFFSET = -(64 * 1024); // max size of local reference space
|
private static final int MAX_LOCAL_OFFSET = -(64 * 1024); // max size of local reference space
|
||||||
|
@ -86,13 +85,9 @@ public class NewFunctionStackAnalysisCmd extends BackgroundCommand {
|
||||||
doLocals = doLocalAnalysis;
|
doLocals = doLocalAnalysis;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see ghidra.framework.cmd.BackgroundCommand#applyTo(ghidra.framework.model.DomainObject, ghidra.util.task.TaskMonitor)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applyTo(DomainObject obj, TaskMonitor monitor) {
|
public boolean applyTo(Program p, TaskMonitor monitor) {
|
||||||
program = (Program) obj;
|
program = p;
|
||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
long numAddresses = entryPoints.getNumAddresses();
|
long numAddresses = entryPoints.getNumAddresses();
|
||||||
|
@ -133,7 +128,7 @@ public class NewFunctionStackAnalysisCmd extends BackgroundCommand {
|
||||||
/**
|
/**
|
||||||
* Analyze a function to build a stack frame based on stack references.
|
* Analyze a function to build a stack frame based on stack references.
|
||||||
*
|
*
|
||||||
* @param entry The address of the entry point for the new function
|
* @param f function to analyze
|
||||||
* @param monitor the task monitor that is checked to see if the command has
|
* @param monitor the task monitor that is checked to see if the command has
|
||||||
* been cancelled.
|
* been cancelled.
|
||||||
* @throws CancelledException if the user canceled this command
|
* @throws CancelledException if the user canceled this command
|
||||||
|
@ -164,9 +159,8 @@ public class NewFunctionStackAnalysisCmd extends BackgroundCommand {
|
||||||
// Later this should change to stack locked.
|
// Later this should change to stack locked.
|
||||||
Variable[] variables = func.getVariables(VariableFilter.STACK_VARIABLE_FILTER);
|
Variable[] variables = func.getVariables(VariableFilter.STACK_VARIABLE_FILTER);
|
||||||
boolean hasReferences = false;
|
boolean hasReferences = false;
|
||||||
for (int i = 0; i < variables.length; i++) {
|
for (Variable variable : variables) {
|
||||||
Reference[] referencesTo =
|
Reference[] referencesTo = program.getReferenceManager().getReferencesTo(variable);
|
||||||
program.getReferenceManager().getReferencesTo(variables[i]);
|
|
||||||
if (referencesTo.length != 0) {
|
if (referencesTo.length != 0) {
|
||||||
hasReferences = true;
|
hasReferences = true;
|
||||||
break;
|
break;
|
||||||
|
@ -599,13 +593,13 @@ public class NewFunctionStackAnalysisCmd extends BackgroundCommand {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* Checks the indicated function in the program to determine if it is a jump thunk
|
// * Checks the indicated function in the program to determine if it is a jump thunk
|
||||||
* through a function pointer.
|
// * through a function pointer.
|
||||||
* @param func the function to check
|
// * @param func the function to check
|
||||||
* @param monitor status monitor for indicating progress and allowing cancel.
|
// * @param monitor status monitor for indicating progress and allowing cancel.
|
||||||
* @returntrue if check if this is a jump thunk through a function pointer
|
// * @returntrue if check if this is a jump thunk through a function pointer
|
||||||
*/
|
// */
|
||||||
// private boolean checkThunk(Function func, TaskMonitor monitor) {
|
// private boolean checkThunk(Function func, TaskMonitor monitor) {
|
||||||
// Instruction instr = program.getListing().getInstructionAt(func.getEntryPoint());
|
// Instruction instr = program.getListing().getInstructionAt(func.getEntryPoint());
|
||||||
// if (instr == null) {
|
// if (instr == null) {
|
||||||
|
|
|
@ -16,16 +16,13 @@
|
||||||
package ghidra.app.cmd.function;
|
package ghidra.app.cmd.function;
|
||||||
|
|
||||||
import ghidra.framework.cmd.Command;
|
import ghidra.framework.cmd.Command;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.program.database.ProgramDB;
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.listing.Function;
|
import ghidra.program.model.listing.*;
|
||||||
import ghidra.program.model.listing.FunctionManager;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Command for removing a tag from a function
|
* Command for removing a tag from a function
|
||||||
*/
|
*/
|
||||||
public class RemoveFunctionTagCmd implements Command {
|
public class RemoveFunctionTagCmd implements Command<Program> {
|
||||||
|
|
||||||
private Address entryPoint;
|
private Address entryPoint;
|
||||||
private String tagName;
|
private String tagName;
|
||||||
|
@ -42,8 +39,7 @@ public class RemoveFunctionTagCmd implements Command {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applyTo(DomainObject obj) {
|
public boolean applyTo(Program program) {
|
||||||
ProgramDB program = (ProgramDB) obj;
|
|
||||||
FunctionManager functionManager = program.getFunctionManager();
|
FunctionManager functionManager = program.getFunctionManager();
|
||||||
Function function = functionManager.getFunctionAt(entryPoint);
|
Function function = functionManager.getFunctionAt(entryPoint);
|
||||||
function.removeTag(tagName);
|
function.removeTag(tagName);
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -17,28 +16,28 @@
|
||||||
package ghidra.app.cmd.function;
|
package ghidra.app.cmd.function;
|
||||||
|
|
||||||
import ghidra.framework.cmd.Command;
|
import ghidra.framework.cmd.Command;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
|
|
||||||
public class RemoveStackDepthChangeCommand implements Command {
|
public class RemoveStackDepthChangeCommand implements Command<Program> {
|
||||||
|
|
||||||
private Program program;
|
|
||||||
private Address address;
|
private Address address;
|
||||||
|
|
||||||
public RemoveStackDepthChangeCommand(Program program, Address address) {
|
public RemoveStackDepthChangeCommand(Address address) {
|
||||||
this.program = program;
|
|
||||||
this.address = address;
|
this.address = address;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean applyTo(DomainObject obj) {
|
@Override
|
||||||
|
public boolean applyTo(Program program) {
|
||||||
return CallDepthChangeInfo.removeStackDepthChange(program, address);
|
return CallDepthChangeInfo.removeStackDepthChange(program, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "Remove Stack Depth Change";
|
return "Remove Stack Depth Change";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public String getStatusMsg() {
|
public String getStatusMsg() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -17,7 +16,6 @@
|
||||||
package ghidra.app.cmd.function;
|
package ghidra.app.cmd.function;
|
||||||
|
|
||||||
import ghidra.framework.cmd.Command;
|
import ghidra.framework.cmd.Command;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.listing.Function;
|
import ghidra.program.model.listing.Function;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
|
@ -26,11 +24,12 @@ import ghidra.program.model.symbol.SourceType;
|
||||||
/**
|
/**
|
||||||
* Command to set the name of a function.
|
* Command to set the name of a function.
|
||||||
*/
|
*/
|
||||||
public class SetFunctionNameCmd implements Command {
|
public class SetFunctionNameCmd implements Command<Program> {
|
||||||
private Address entry;
|
private Address entry;
|
||||||
private String name;
|
private String name;
|
||||||
private String msg;
|
private String msg;
|
||||||
private SourceType source;
|
private SourceType source;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new command for setting the name of a function.
|
* Constructs a new command for setting the name of a function.
|
||||||
* @param entry the address of the function to be renamed.
|
* @param entry the address of the function to be renamed.
|
||||||
|
@ -42,12 +41,9 @@ public class SetFunctionNameCmd implements Command {
|
||||||
this.name = newName;
|
this.name = newName;
|
||||||
this.source = source;
|
this.source = source;
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
*
|
@Override
|
||||||
* @see ghidra.framework.cmd.Command#applyTo(ghidra.framework.model.DomainObject)
|
public boolean applyTo(Program program) {
|
||||||
*/
|
|
||||||
public boolean applyTo(DomainObject obj) {
|
|
||||||
Program program = (Program)obj;
|
|
||||||
|
|
||||||
if (name.length() <= 0) {
|
if (name.length() <= 0) {
|
||||||
name = null;
|
name = null;
|
||||||
|
@ -68,18 +64,12 @@ public class SetFunctionNameCmd implements Command {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
*
|
|
||||||
* @see ghidra.framework.cmd.Command#getName()
|
|
||||||
*/
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "Rename Function";
|
return "Rename Function";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
/**
|
|
||||||
* @see ghidra.framework.cmd.Command#getStatusMsg()
|
|
||||||
*/
|
|
||||||
public String getStatusMsg() {
|
public String getStatusMsg() {
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -17,8 +16,8 @@
|
||||||
package ghidra.app.cmd.function;
|
package ghidra.app.cmd.function;
|
||||||
|
|
||||||
import ghidra.framework.cmd.Command;
|
import ghidra.framework.cmd.Command;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.program.model.listing.Function;
|
import ghidra.program.model.listing.Function;
|
||||||
|
import ghidra.program.model.listing.Program;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A simple command to set the stack purge size of a function.
|
* A simple command to set the stack purge size of a function.
|
||||||
|
@ -26,7 +25,7 @@ import ghidra.program.model.listing.Function;
|
||||||
*
|
*
|
||||||
* @since Tracker Id 548
|
* @since Tracker Id 548
|
||||||
*/
|
*/
|
||||||
public class SetFunctionPurgeCommand implements Command {
|
public class SetFunctionPurgeCommand implements Command<Program> {
|
||||||
private Function function;
|
private Function function;
|
||||||
private int functionPurge;
|
private int functionPurge;
|
||||||
|
|
||||||
|
@ -37,29 +36,23 @@ public class SetFunctionPurgeCommand implements Command {
|
||||||
* @param function The function on which to set the purge size.
|
* @param function The function on which to set the purge size.
|
||||||
* @param newPurge The new stack purge size.
|
* @param newPurge The new stack purge size.
|
||||||
*/
|
*/
|
||||||
public SetFunctionPurgeCommand( Function function, int newPurge ) {
|
public SetFunctionPurgeCommand(Function function, int newPurge) {
|
||||||
this.function = function;
|
this.function = function;
|
||||||
this.functionPurge = newPurge;
|
this.functionPurge = newPurge;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* @see ghidra.framework.cmd.Command#applyTo(ghidra.framework.model.DomainObject)
|
public boolean applyTo(Program program) {
|
||||||
*/
|
function.setStackPurgeSize(functionPurge);
|
||||||
public boolean applyTo(DomainObject obj) {
|
|
||||||
function.setStackPurgeSize( functionPurge );
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* @see ghidra.framework.cmd.Command#getStatusMsg()
|
|
||||||
*/
|
|
||||||
public String getStatusMsg() {
|
public String getStatusMsg() {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* @see ghidra.framework.cmd.Command#getName()
|
|
||||||
*/
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "Set Function Purge";
|
return "Set Function Purge";
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -17,7 +16,6 @@
|
||||||
package ghidra.app.cmd.function;
|
package ghidra.app.cmd.function;
|
||||||
|
|
||||||
import ghidra.framework.cmd.Command;
|
import ghidra.framework.cmd.Command;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.listing.Function;
|
import ghidra.program.model.listing.Function;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
|
@ -25,7 +23,7 @@ import ghidra.program.model.listing.Program;
|
||||||
/**
|
/**
|
||||||
* Command to set the Function's Repeatable Comment.
|
* Command to set the Function's Repeatable Comment.
|
||||||
*/
|
*/
|
||||||
public class SetFunctionRepeatableCommentCmd implements Command {
|
public class SetFunctionRepeatableCommentCmd implements Command<Program> {
|
||||||
private Address entry;
|
private Address entry;
|
||||||
private String newRepeatableComment;
|
private String newRepeatableComment;
|
||||||
|
|
||||||
|
@ -39,20 +37,13 @@ public class SetFunctionRepeatableCommentCmd implements Command {
|
||||||
this.newRepeatableComment = newRepeatableComment;
|
this.newRepeatableComment = newRepeatableComment;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
*
|
|
||||||
* @see ghidra.framework.cmd.Command#getName()
|
|
||||||
*/
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "Set Function Repeatable Comment";
|
return "Set Function Repeatable Comment";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
*
|
public boolean applyTo(Program program) {
|
||||||
* @see ghidra.framework.cmd.Command#applyTo(ghidra.framework.model.DomainObject)
|
|
||||||
*/
|
|
||||||
public boolean applyTo(DomainObject obj) {
|
|
||||||
Program program = (Program)obj;
|
|
||||||
Function f = program.getListing().getFunctionAt(entry);
|
Function f = program.getListing().getFunctionAt(entry);
|
||||||
if (f != null) {
|
if (f != null) {
|
||||||
f.setRepeatableComment(newRepeatableComment);
|
f.setRepeatableComment(newRepeatableComment);
|
||||||
|
@ -60,9 +51,7 @@ public class SetFunctionRepeatableCommentCmd implements Command {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* @see ghidra.framework.cmd.Command#getStatusMsg()
|
|
||||||
*/
|
|
||||||
public String getStatusMsg() {
|
public String getStatusMsg() {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -17,13 +16,13 @@
|
||||||
package ghidra.app.cmd.function;
|
package ghidra.app.cmd.function;
|
||||||
|
|
||||||
import ghidra.framework.cmd.Command;
|
import ghidra.framework.cmd.Command;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.program.model.listing.Function;
|
import ghidra.program.model.listing.Function;
|
||||||
|
import ghidra.program.model.listing.Program;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A simple command to set whether or not a function has VarArgs.
|
* A simple command to set whether or not a function has VarArgs.
|
||||||
*/
|
*/
|
||||||
public class SetFunctionVarArgsCommand implements Command {
|
public class SetFunctionVarArgsCommand implements Command<Program> {
|
||||||
private Function function;
|
private Function function;
|
||||||
private boolean hasVarArgs;
|
private boolean hasVarArgs;
|
||||||
|
|
||||||
|
@ -34,29 +33,23 @@ public class SetFunctionVarArgsCommand implements Command {
|
||||||
* @param function The function on which to set whether or not there are VarArgs.
|
* @param function The function on which to set whether or not there are VarArgs.
|
||||||
* @param hasVarArgs true if you want to set this function to have VarArgs.
|
* @param hasVarArgs true if you want to set this function to have VarArgs.
|
||||||
*/
|
*/
|
||||||
public SetFunctionVarArgsCommand( Function function, boolean hasVarArgs ) {
|
public SetFunctionVarArgsCommand(Function function, boolean hasVarArgs) {
|
||||||
this.function = function;
|
this.function = function;
|
||||||
this.hasVarArgs = hasVarArgs;
|
this.hasVarArgs = hasVarArgs;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* @see ghidra.framework.cmd.Command#applyTo(ghidra.framework.model.DomainObject)
|
public boolean applyTo(Program program) {
|
||||||
*/
|
function.setVarArgs(hasVarArgs);
|
||||||
public boolean applyTo(DomainObject obj) {
|
|
||||||
function.setVarArgs( hasVarArgs );
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* @see ghidra.framework.cmd.Command#getStatusMsg()
|
|
||||||
*/
|
|
||||||
public String getStatusMsg() {
|
public String getStatusMsg() {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* @see ghidra.framework.cmd.Command#getName()
|
|
||||||
*/
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "Set Function VarArgs";
|
return "Set Function VarArgs";
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -17,7 +16,6 @@
|
||||||
package ghidra.app.cmd.function;
|
package ghidra.app.cmd.function;
|
||||||
|
|
||||||
import ghidra.framework.cmd.Command;
|
import ghidra.framework.cmd.Command;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.data.DataType;
|
import ghidra.program.model.data.DataType;
|
||||||
import ghidra.program.model.listing.Function;
|
import ghidra.program.model.listing.Function;
|
||||||
|
@ -28,7 +26,7 @@ import ghidra.util.exception.InvalidInputException;
|
||||||
/**
|
/**
|
||||||
* Command for setting a function's return type.
|
* Command for setting a function's return type.
|
||||||
*/
|
*/
|
||||||
public class SetReturnDataTypeCmd implements Command {
|
public class SetReturnDataTypeCmd implements Command<Program> {
|
||||||
private Address entry;
|
private Address entry;
|
||||||
private DataType dataType;
|
private DataType dataType;
|
||||||
private String status;
|
private String status;
|
||||||
|
@ -46,22 +44,13 @@ public class SetReturnDataTypeCmd implements Command {
|
||||||
this.source = source;
|
this.source = source;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see ghidra.framework.cmd.Command#getName()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "Set Return Data Type";
|
return "Set Return Data Type";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see ghidra.framework.cmd.Command#applyTo(ghidra.framework.model.DomainObject)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applyTo(DomainObject obj) {
|
public boolean applyTo(Program program) {
|
||||||
Program program = (Program) obj;
|
|
||||||
Function function = program.getListing().getFunctionAt(entry);
|
Function function = program.getListing().getFunctionAt(entry);
|
||||||
try {
|
try {
|
||||||
function.setReturnType(dataType, source);
|
function.setReturnType(dataType, source);
|
||||||
|
@ -76,9 +65,6 @@ public class SetReturnDataTypeCmd implements Command {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.framework.cmd.Command#getStatusMsg()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public String getStatusMsg() {
|
public String getStatusMsg() {
|
||||||
return status;
|
return status;
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -17,40 +16,41 @@
|
||||||
package ghidra.app.cmd.function;
|
package ghidra.app.cmd.function;
|
||||||
|
|
||||||
import ghidra.framework.cmd.Command;
|
import ghidra.framework.cmd.Command;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
|
|
||||||
public class SetStackDepthChangeCommand implements Command {
|
public class SetStackDepthChangeCommand implements Command<Program> {
|
||||||
|
|
||||||
private Program program;
|
|
||||||
private Address address;
|
private Address address;
|
||||||
private int stackDepthChange;
|
private int stackDepthChange;
|
||||||
private String errMsg = null;
|
private String errMsg = null;
|
||||||
|
|
||||||
public SetStackDepthChangeCommand(Program program, Address address, int newStackDepthChange) {
|
public SetStackDepthChangeCommand(Address address, int newStackDepthChange) {
|
||||||
this.program = program;
|
|
||||||
this.address = address;
|
this.address = address;
|
||||||
this.stackDepthChange = newStackDepthChange;
|
this.stackDepthChange = newStackDepthChange;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean applyTo(DomainObject obj) {
|
@Override
|
||||||
|
public boolean applyTo(Program program) {
|
||||||
try {
|
try {
|
||||||
CallDepthChangeInfo.setStackDepthChange(program, address, stackDepthChange);
|
CallDepthChangeInfo.setStackDepthChange(program, address, stackDepthChange);
|
||||||
return true;
|
return true;
|
||||||
} catch (DuplicateNameException e) {
|
}
|
||||||
|
catch (DuplicateNameException e) {
|
||||||
errMsg = e.getMessage();
|
errMsg = e.getMessage();
|
||||||
Msg.error(this, "Unexpected Exception: " + e.getMessage(), e);
|
Msg.error(this, "Unexpected Exception: " + e.getMessage(), e);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "Set Stack Depth Change";
|
return "Set Stack Depth Change";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public String getStatusMsg() {
|
public String getStatusMsg() {
|
||||||
return errMsg;
|
return errMsg;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -17,14 +16,13 @@
|
||||||
package ghidra.app.cmd.function;
|
package ghidra.app.cmd.function;
|
||||||
|
|
||||||
import ghidra.framework.cmd.Command;
|
import ghidra.framework.cmd.Command;
|
||||||
import ghidra.framework.model.DomainObject;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.program.model.listing.Variable;
|
import ghidra.program.model.listing.Variable;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Command to set the comment on a function varible.
|
* Command to set the comment on a function varible.
|
||||||
*/
|
*/
|
||||||
public class SetVariableCommentCmd implements Command {
|
public class SetVariableCommentCmd implements Command<Program> {
|
||||||
private Variable var;
|
private Variable var;
|
||||||
private String comment;
|
private String comment;
|
||||||
private String msg;
|
private String msg;
|
||||||
|
@ -39,27 +37,18 @@ public class SetVariableCommentCmd implements Command {
|
||||||
this.comment = newComment;
|
this.comment = newComment;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
*
|
|
||||||
* @see ghidra.framework.cmd.Command#getName()
|
|
||||||
*/
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "Set Variable Comment";
|
return "Set Variable Comment";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
*
|
public boolean applyTo(Program program) {
|
||||||
* @see ghidra.framework.cmd.Command#applyTo(ghidra.framework.model.DomainObject)
|
|
||||||
*/
|
|
||||||
public boolean applyTo(DomainObject obj) {
|
|
||||||
var.setComment(comment);
|
var.setComment(comment);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
/**
|
|
||||||
* @see ghidra.framework.cmd.Command#getStatusMsg()
|
|
||||||
*/
|
|
||||||
public String getStatusMsg() {
|
public String getStatusMsg() {
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
package ghidra.app.cmd.function;
|
package ghidra.app.cmd.function;
|
||||||
|
|
||||||
import ghidra.framework.cmd.Command;
|
import ghidra.framework.cmd.Command;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.data.*;
|
import ghidra.program.model.data.*;
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.*;
|
||||||
|
@ -27,7 +26,7 @@ import ghidra.util.exception.InvalidInputException;
|
||||||
/**
|
/**
|
||||||
* Command to set the datatype on a stack variable.
|
* Command to set the datatype on a stack variable.
|
||||||
*/
|
*/
|
||||||
public class SetVariableDataTypeCmd implements Command {
|
public class SetVariableDataTypeCmd implements Command<Program> {
|
||||||
|
|
||||||
private final Address fnEntry;
|
private final Address fnEntry;
|
||||||
private final String varName;
|
private final String varName;
|
||||||
|
@ -86,10 +85,6 @@ public class SetVariableDataTypeCmd implements Command {
|
||||||
this.source = source;
|
this.source = source;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see ghidra.framework.cmd.Command#getName()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "Set " + (isParm ? "Parameter" : "Variable") + " Data Type";
|
return "Set " + (isParm ? "Parameter" : "Variable") + " Data Type";
|
||||||
|
@ -100,21 +95,16 @@ public class SetVariableDataTypeCmd implements Command {
|
||||||
* @see ghidra.framework.cmd.Command#applyTo(ghidra.framework.model.DomainObject)
|
* @see ghidra.framework.cmd.Command#applyTo(ghidra.framework.model.DomainObject)
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean applyTo(DomainObject obj) {
|
public boolean applyTo(Program program) {
|
||||||
if (!(obj instanceof Program)) {
|
Function f = program.getFunctionManager().getFunctionAt(fnEntry);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Program p = (Program) obj;
|
|
||||||
|
|
||||||
Function f = p.getFunctionManager().getFunctionAt(fnEntry);
|
|
||||||
if (f == null) {
|
if (f == null) {
|
||||||
status = "Function not found";
|
status = "Function not found";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Symbol s = p.getSymbolTable().getParameterSymbol(varName, f);
|
Symbol s = program.getSymbolTable().getParameterSymbol(varName, f);
|
||||||
if (s == null) {
|
if (s == null) {
|
||||||
s = p.getSymbolTable().getLocalVariableSymbol(varName, f);
|
s = program.getSymbolTable().getLocalVariableSymbol(varName, f);
|
||||||
}
|
}
|
||||||
if (s == null) {
|
if (s == null) {
|
||||||
status = "Variable not found";
|
status = "Variable not found";
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
package ghidra.app.cmd.function;
|
package ghidra.app.cmd.function;
|
||||||
|
|
||||||
import ghidra.framework.cmd.Command;
|
import ghidra.framework.cmd.Command;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.*;
|
||||||
import ghidra.program.model.symbol.SourceType;
|
import ghidra.program.model.symbol.SourceType;
|
||||||
|
@ -27,7 +26,7 @@ import ghidra.util.exception.InvalidInputException;
|
||||||
/**
|
/**
|
||||||
* Command to rename a stack variable.
|
* Command to rename a stack variable.
|
||||||
*/
|
*/
|
||||||
public class SetVariableNameCmd implements Command {
|
public class SetVariableNameCmd implements Command<Program> {
|
||||||
|
|
||||||
private Address fnEntry;
|
private Address fnEntry;
|
||||||
private String varName;
|
private String varName;
|
||||||
|
@ -64,27 +63,18 @@ public class SetVariableNameCmd implements Command {
|
||||||
this.source = source;
|
this.source = source;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see ghidra.framework.cmd.Command#applyTo(ghidra.framework.model.DomainObject)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applyTo(DomainObject obj) {
|
public boolean applyTo(Program program) {
|
||||||
|
|
||||||
if (!(obj instanceof Program)) {
|
Function f = program.getFunctionManager().getFunctionAt(fnEntry);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Program p = (Program) obj;
|
|
||||||
|
|
||||||
Function f = p.getFunctionManager().getFunctionAt(fnEntry);
|
|
||||||
if (f == null) {
|
if (f == null) {
|
||||||
status = "Function not found";
|
status = "Function not found";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Symbol s = p.getSymbolTable().getParameterSymbol(varName, f);
|
Symbol s = program.getSymbolTable().getParameterSymbol(varName, f);
|
||||||
if (s == null) {
|
if (s == null) {
|
||||||
s = p.getSymbolTable().getLocalVariableSymbol(varName, f);
|
s = program.getSymbolTable().getLocalVariableSymbol(varName, f);
|
||||||
}
|
}
|
||||||
if (s == null) {
|
if (s == null) {
|
||||||
status = "Variable not found";
|
status = "Variable not found";
|
||||||
|
@ -106,17 +96,11 @@ public class SetVariableNameCmd implements Command {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.framework.cmd.Command#getStatusMsg()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public String getStatusMsg() {
|
public String getStatusMsg() {
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.framework.cmd.Command#getName()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "Rename " + (isParm ? "Parameter" : "Variable");
|
return "Rename " + (isParm ? "Parameter" : "Variable");
|
||||||
|
|
|
@ -0,0 +1,101 @@
|
||||||
|
/* ###
|
||||||
|
* 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 ghidra.app.cmd.function;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import ghidra.framework.cmd.Command;
|
||||||
|
import ghidra.program.model.listing.*;
|
||||||
|
import ghidra.program.model.listing.Function.FunctionUpdateType;
|
||||||
|
import ghidra.program.model.symbol.SourceType;
|
||||||
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
|
import ghidra.util.exception.InvalidInputException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A command to update {@link Function} signature in its entirety including optional
|
||||||
|
* custom storage.
|
||||||
|
*
|
||||||
|
* If the function does not rely on custom storage the use of {@link ApplyFunctionSignatureCmd}
|
||||||
|
* may be more appropriate.
|
||||||
|
*/
|
||||||
|
public class UpdateFunctionCommand implements Command<Program> {
|
||||||
|
|
||||||
|
private final Function function;
|
||||||
|
private final FunctionUpdateType updateType;
|
||||||
|
private final String callingConvention;
|
||||||
|
private final Variable returnVar;
|
||||||
|
private final List<? extends Variable> params;
|
||||||
|
private final SourceType source;
|
||||||
|
private final boolean force;
|
||||||
|
|
||||||
|
private String statusMessage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct command to update a {@link Function} signature including optional custom storage.
|
||||||
|
* {@link VariableStorage#UNASSIGNED_STORAGE} should be specified when not using custom storage
|
||||||
|
* or storage is unknown.
|
||||||
|
*
|
||||||
|
* @param function function to be modified
|
||||||
|
* @param updateType indicates how function should be updated including the use of custom or
|
||||||
|
* non-custom storage.
|
||||||
|
* @param callingConvention a valid calling convention name or null if no change is required.
|
||||||
|
* Calling conventions are limited to {@value Function#DEFAULT_CALLING_CONVENTION_STRING},
|
||||||
|
* {@value Function#UNKNOWN_CALLING_CONVENTION_STRING} or those defined by the associated
|
||||||
|
* compiler specification.
|
||||||
|
* @param returnVar function return type and storage.
|
||||||
|
* @param params function parameter list (specifics depend on specified
|
||||||
|
* {@link FunctionUpdateType updateType}).
|
||||||
|
* @param source the source of these parameters which will be applied to the parameter
|
||||||
|
* symbols and overall function signature source. If parameter names are null, or a default
|
||||||
|
* name, a {@link SourceType#DEFAULT} will be applied to the corresponding parameter symbol.
|
||||||
|
* @param force if true any conflicting local parameters will be removed
|
||||||
|
*/
|
||||||
|
public UpdateFunctionCommand(Function function, FunctionUpdateType updateType,
|
||||||
|
String callingConvention, Variable returnVar, List<? extends Variable> params,
|
||||||
|
SourceType source, boolean force) {
|
||||||
|
this.function = function;
|
||||||
|
this.updateType = updateType;
|
||||||
|
this.callingConvention = callingConvention;
|
||||||
|
this.returnVar = returnVar;
|
||||||
|
this.params = params;
|
||||||
|
this.source = source;
|
||||||
|
this.force = force;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean applyTo(Program obj) {
|
||||||
|
try {
|
||||||
|
function.updateFunction(callingConvention, returnVar, params, updateType, force,
|
||||||
|
source);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (InvalidInputException | DuplicateNameException e) {
|
||||||
|
statusMessage = e.getMessage();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getStatusMsg() {
|
||||||
|
return statusMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "Update Function";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -16,7 +16,6 @@
|
||||||
package ghidra.app.cmd.label;
|
package ghidra.app.cmd.label;
|
||||||
|
|
||||||
import ghidra.framework.cmd.Command;
|
import ghidra.framework.cmd.Command;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.program.model.symbol.*;
|
import ghidra.program.model.symbol.*;
|
||||||
|
@ -25,7 +24,7 @@ import ghidra.util.exception.InvalidInputException;
|
||||||
/**
|
/**
|
||||||
* Command to add a label.
|
* Command to add a label.
|
||||||
*/
|
*/
|
||||||
public class AddLabelCmd implements Command {
|
public class AddLabelCmd implements Command<Program> {
|
||||||
private Address addr;
|
private Address addr;
|
||||||
private String name;
|
private String name;
|
||||||
private Namespace namespace;
|
private Namespace namespace;
|
||||||
|
@ -76,13 +75,9 @@ public class AddLabelCmd implements Command {
|
||||||
this(addr, name, null, source);
|
this(addr, name, null, source);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see ghidra.framework.cmd.Command#applyTo(ghidra.framework.model.DomainObject)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applyTo(DomainObject obj) {
|
public boolean applyTo(Program program) {
|
||||||
SymbolTable st = ((Program) obj).getSymbolTable();
|
SymbolTable st = program.getSymbolTable();
|
||||||
if (namespace == null && useLocalNamespace) {
|
if (namespace == null && useLocalNamespace) {
|
||||||
namespace = st.getNamespace(addr);
|
namespace = st.getNamespace(addr);
|
||||||
}
|
}
|
||||||
|
@ -103,17 +98,11 @@ public class AddLabelCmd implements Command {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.framework.cmd.Command#getStatusMsg()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public String getStatusMsg() {
|
public String getStatusMsg() {
|
||||||
return errorMsg;
|
return errorMsg;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.framework.cmd.Command#getName()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "Add Label";
|
return "Add Label";
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
package ghidra.app.cmd.label;
|
package ghidra.app.cmd.label;
|
||||||
|
|
||||||
import ghidra.framework.cmd.Command;
|
import ghidra.framework.cmd.Command;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.program.model.symbol.*;
|
import ghidra.program.model.symbol.*;
|
||||||
|
@ -29,7 +28,7 @@ import ghidra.util.exception.InvalidInputException;
|
||||||
* @deprecated The need for this class is now unnecessary since duplicate labels are permitted
|
* @deprecated The need for this class is now unnecessary since duplicate labels are permitted
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public class AddUniqueLabelCmd implements Command {
|
public class AddUniqueLabelCmd implements Command<Program> {
|
||||||
private Address address;
|
private Address address;
|
||||||
private String name;
|
private String name;
|
||||||
private Namespace namespace;
|
private Namespace namespace;
|
||||||
|
@ -52,12 +51,9 @@ public class AddUniqueLabelCmd implements Command {
|
||||||
this.source = source;
|
this.source = source;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.framework.cmd.Command#applyTo(ghidra.framework.model.DomainObject)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applyTo(DomainObject obj) {
|
public boolean applyTo(Program program) {
|
||||||
SymbolTable symbolTable = ((Program) obj).getSymbolTable();
|
SymbolTable symbolTable = program.getSymbolTable();
|
||||||
try {
|
try {
|
||||||
newSymbol = symbolTable.createLabel(address, name, namespace, source);
|
newSymbol = symbolTable.createLabel(address, name, namespace, source);
|
||||||
return true;//symbol already exist at this address, just complete
|
return true;//symbol already exist at this address, just complete
|
||||||
|
@ -76,17 +72,11 @@ public class AddUniqueLabelCmd implements Command {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.framework.cmd.Command#getStatusMsg()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public String getStatusMsg() {
|
public String getStatusMsg() {
|
||||||
return errorMsg;
|
return errorMsg;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.framework.cmd.Command#getName()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "Add Unique Label";
|
return "Add Unique Label";
|
||||||
|
|
|
@ -17,7 +17,6 @@ package ghidra.app.cmd.label;
|
||||||
|
|
||||||
import ghidra.app.util.NamespaceUtils;
|
import ghidra.app.util.NamespaceUtils;
|
||||||
import ghidra.framework.cmd.Command;
|
import ghidra.framework.cmd.Command;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.program.model.symbol.Namespace;
|
import ghidra.program.model.symbol.Namespace;
|
||||||
import ghidra.program.model.symbol.SourceType;
|
import ghidra.program.model.symbol.SourceType;
|
||||||
|
@ -43,7 +42,7 @@ import ghidra.util.exception.InvalidInputException;
|
||||||
* @since Tracker Id 619
|
* @since Tracker Id 619
|
||||||
* @see NamespaceUtils
|
* @see NamespaceUtils
|
||||||
*/
|
*/
|
||||||
public class CreateNamespacesCmd implements Command {
|
public class CreateNamespacesCmd implements Command<Program> {
|
||||||
|
|
||||||
private String statusMsg;
|
private String statusMsg;
|
||||||
|
|
||||||
|
@ -83,11 +82,12 @@ public class CreateNamespacesCmd implements Command {
|
||||||
* @see <a href="#examples">example format</a>
|
* @see <a href="#examples">example format</a>
|
||||||
* @see <a href="#assumptions">assumptions</a>
|
* @see <a href="#assumptions">assumptions</a>
|
||||||
*/
|
*/
|
||||||
public CreateNamespacesCmd(String namespacesString, Namespace parentNamespace, SourceType source) {
|
public CreateNamespacesCmd(String namespacesString, Namespace parentNamespace,
|
||||||
|
SourceType source) {
|
||||||
|
|
||||||
if (namespacesString == null) {
|
if (namespacesString == null) {
|
||||||
throw new NullPointerException("Cannot create namespaces from a "
|
throw new NullPointerException(
|
||||||
+ "null namespacesString value.");
|
"Cannot create namespaces from a " + "null namespacesString value.");
|
||||||
}
|
}
|
||||||
|
|
||||||
this.namespacesString = namespacesString;
|
this.namespacesString = namespacesString;
|
||||||
|
@ -95,16 +95,12 @@ public class CreateNamespacesCmd implements Command {
|
||||||
this.source = source;
|
this.source = source;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.framework.cmd.Command#applyTo(ghidra.framework.model.DomainObject)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applyTo(DomainObject obj) {
|
public boolean applyTo(Program program) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
leafNamespace =
|
leafNamespace = NamespaceUtils.createNamespaceHierarchy(namespacesString, rootNamespace,
|
||||||
NamespaceUtils.createNamespaceHierarchy(namespacesString, rootNamespace,
|
program, source);
|
||||||
(Program) obj, source);
|
|
||||||
|
|
||||||
if (leafNamespace != null) {
|
if (leafNamespace != null) {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -17,7 +16,6 @@
|
||||||
package ghidra.app.cmd.label;
|
package ghidra.app.cmd.label;
|
||||||
|
|
||||||
import ghidra.framework.cmd.Command;
|
import ghidra.framework.cmd.Command;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.program.model.symbol.*;
|
import ghidra.program.model.symbol.*;
|
||||||
|
@ -25,7 +23,7 @@ import ghidra.program.model.symbol.*;
|
||||||
/**
|
/**
|
||||||
* Command to delete a label
|
* Command to delete a label
|
||||||
*/
|
*/
|
||||||
public class DeleteLabelCmd implements Command {
|
public class DeleteLabelCmd implements Command<Program> {
|
||||||
|
|
||||||
private Address addr;
|
private Address addr;
|
||||||
private String name;
|
private String name;
|
||||||
|
@ -54,13 +52,9 @@ public class DeleteLabelCmd implements Command {
|
||||||
this(addr, name, null);
|
this(addr, name, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see ghidra.framework.cmd.Command#applyTo(ghidra.framework.model.DomainObject)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applyTo(DomainObject obj) {
|
public boolean applyTo(Program program) {
|
||||||
SymbolTable st = ((Program) obj).getSymbolTable();
|
SymbolTable st = program.getSymbolTable();
|
||||||
Symbol s = st.getSymbol(name, addr, scope);
|
Symbol s = st.getSymbol(name, addr, scope);
|
||||||
if (s == null) {
|
if (s == null) {
|
||||||
errorMsg = "Symbol " + name + " not found!";
|
errorMsg = "Symbol " + name + " not found!";
|
||||||
|
@ -74,7 +68,7 @@ public class DeleteLabelCmd implements Command {
|
||||||
if (s.isExternalEntryPoint() && s.isPrimary()) {
|
if (s.isExternalEntryPoint() && s.isPrimary()) {
|
||||||
if (st.getSymbols(s.getAddress()).length == 1) {
|
if (st.getSymbols(s.getAddress()).length == 1) {
|
||||||
externalEntryCmd = new ExternalEntryCmd(addr, false);
|
externalEntryCmd = new ExternalEntryCmd(addr, false);
|
||||||
externalEntryCmd.applyTo(obj);
|
externalEntryCmd.applyTo(program);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
boolean success = st.removeSymbolSpecial(s);
|
boolean success = st.removeSymbolSpecial(s);
|
||||||
|
@ -84,17 +78,11 @@ public class DeleteLabelCmd implements Command {
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.framework.cmd.Command#getName()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "Delete Label";
|
return "Delete Label";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.framework.cmd.Command#getStatusMsg()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public String getStatusMsg() {
|
public String getStatusMsg() {
|
||||||
return errorMsg;
|
return errorMsg;
|
||||||
|
|
|
@ -19,7 +19,6 @@ import java.util.List;
|
||||||
|
|
||||||
import ghidra.app.util.demangler.*;
|
import ghidra.app.util.demangler.*;
|
||||||
import ghidra.framework.cmd.BackgroundCommand;
|
import ghidra.framework.cmd.BackgroundCommand;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.program.model.symbol.SymbolUtilities;
|
import ghidra.program.model.symbol.SymbolUtilities;
|
||||||
|
@ -27,7 +26,7 @@ import ghidra.util.Msg;
|
||||||
import ghidra.util.classfinder.ClassSearcher;
|
import ghidra.util.classfinder.ClassSearcher;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
|
||||||
public class DemanglerCmd extends BackgroundCommand {
|
public class DemanglerCmd extends BackgroundCommand<Program> {
|
||||||
|
|
||||||
private Address addr;
|
private Address addr;
|
||||||
private String mangled;
|
private String mangled;
|
||||||
|
@ -49,10 +48,9 @@ public class DemanglerCmd extends BackgroundCommand {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applyTo(DomainObject obj, TaskMonitor monitor) {
|
public boolean applyTo(Program prog, TaskMonitor monitor) {
|
||||||
|
|
||||||
// search until we find a demangler that can handle the given mangled input
|
// search until we find a demangler that can handle the given mangled input
|
||||||
Program prog = (Program) obj;
|
|
||||||
for (Demangler demangler : getDemanglers()) {
|
for (Demangler demangler : getDemanglers()) {
|
||||||
if (!demangler.canDemangle(prog)) {
|
if (!demangler.canDemangle(prog)) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -114,8 +112,7 @@ public class DemanglerCmd extends BackgroundCommand {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
setStatusMsg(
|
setStatusMsg("Failed to apply mangled symbol at " + addr + "; name: " + mangled + " (" +
|
||||||
"Failed to apply mangled symbol at " + addr + "; name: " + mangled + " (" +
|
|
||||||
demangler.getClass().getName() + "/" + demangledObject.getClass().getName() + ")");
|
demangler.getClass().getName() + "/" + demangledObject.getClass().getName() + ")");
|
||||||
return false; // error
|
return false; // error
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -17,7 +16,6 @@
|
||||||
package ghidra.app.cmd.label;
|
package ghidra.app.cmd.label;
|
||||||
|
|
||||||
import ghidra.framework.cmd.Command;
|
import ghidra.framework.cmd.Command;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.program.model.symbol.SymbolTable;
|
import ghidra.program.model.symbol.SymbolTable;
|
||||||
|
@ -25,12 +23,11 @@ import ghidra.program.model.symbol.SymbolTable;
|
||||||
/**
|
/**
|
||||||
* Command for setting/unsetting an external entry point.
|
* Command for setting/unsetting an external entry point.
|
||||||
*/
|
*/
|
||||||
public class ExternalEntryCmd implements Command {
|
public class ExternalEntryCmd implements Command<Program> {
|
||||||
private SymbolTable st;
|
|
||||||
private Address addr;
|
private Address addr;
|
||||||
private boolean isEntry;
|
private boolean isEntry;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a new command for setting/unsetting an external entry point
|
* Construct a new command for setting/unsetting an external entry point
|
||||||
* @param addr address to set or unset as an external entry point.
|
* @param addr address to set or unset as an external entry point.
|
||||||
|
@ -41,13 +38,9 @@ public class ExternalEntryCmd implements Command {
|
||||||
this.isEntry = isEntry;
|
this.isEntry = isEntry;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
*
|
public boolean applyTo(Program program) {
|
||||||
* @see ghidra.framework.cmd.Command#applyTo(ghidra.framework.model.DomainObject)
|
SymbolTable st = program.getSymbolTable();
|
||||||
*/
|
|
||||||
public boolean applyTo(DomainObject obj) {
|
|
||||||
st = ((Program)obj).getSymbolTable();
|
|
||||||
|
|
||||||
if (isEntry) {
|
if (isEntry) {
|
||||||
st.addExternalEntryPoint(addr);
|
st.addExternalEntryPoint(addr);
|
||||||
}
|
}
|
||||||
|
@ -57,18 +50,12 @@ public class ExternalEntryCmd implements Command {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.framework.cmd.Command#getName()
|
|
||||||
*/
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "Set External" +isEntry;
|
return "Set External" + isEntry;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* @see ghidra.framework.cmd.Command#getStatusMsg()
|
|
||||||
*/
|
|
||||||
public String getStatusMsg() {
|
public String getStatusMsg() {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,13 +16,12 @@
|
||||||
package ghidra.app.cmd.label;
|
package ghidra.app.cmd.label;
|
||||||
|
|
||||||
import ghidra.framework.cmd.Command;
|
import ghidra.framework.cmd.Command;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.program.model.symbol.Symbol;
|
import ghidra.program.model.symbol.Symbol;
|
||||||
import ghidra.program.model.symbol.SymbolTable;
|
import ghidra.program.model.symbol.SymbolTable;
|
||||||
|
|
||||||
public class PinSymbolCmd implements Command {
|
public class PinSymbolCmd implements Command<Program> {
|
||||||
|
|
||||||
private Address addr;
|
private Address addr;
|
||||||
private String name;
|
private String name;
|
||||||
|
@ -36,8 +35,8 @@ public class PinSymbolCmd implements Command {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applyTo(DomainObject obj) {
|
public boolean applyTo(Program program) {
|
||||||
SymbolTable symbolTable = ((Program) obj).getSymbolTable();
|
SymbolTable symbolTable = program.getSymbolTable();
|
||||||
Symbol symbol = symbolTable.getGlobalSymbol(name, addr);
|
Symbol symbol = symbolTable.getGlobalSymbol(name, addr);
|
||||||
if (symbol == null) {
|
if (symbol == null) {
|
||||||
message = "Could not find symbol named " + name + " at address " + addr;
|
message = "Could not find symbol named " + name + " at address " + addr;
|
||||||
|
|
|
@ -22,7 +22,6 @@ import org.apache.commons.lang3.StringUtils;
|
||||||
import ghidra.app.util.NamespaceUtils;
|
import ghidra.app.util.NamespaceUtils;
|
||||||
import ghidra.app.util.SymbolPath;
|
import ghidra.app.util.SymbolPath;
|
||||||
import ghidra.framework.cmd.Command;
|
import ghidra.framework.cmd.Command;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.listing.CircularDependencyException;
|
import ghidra.program.model.listing.CircularDependencyException;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
|
@ -34,7 +33,7 @@ import ghidra.util.exception.InvalidInputException;
|
||||||
* Command for renaming labels. Handles converting back and forth between default and named labels
|
* Command for renaming labels. Handles converting back and forth between default and named labels
|
||||||
* as well.
|
* as well.
|
||||||
*/
|
*/
|
||||||
public class RenameLabelCmd implements Command {
|
public class RenameLabelCmd implements Command<Program> {
|
||||||
|
|
||||||
private Address addr;
|
private Address addr;
|
||||||
private String oldName;
|
private String oldName;
|
||||||
|
@ -123,9 +122,8 @@ public class RenameLabelCmd implements Command {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applyTo(DomainObject obj) {
|
public boolean applyTo(Program program) {
|
||||||
|
|
||||||
Program program = (Program) obj;
|
|
||||||
if (currentNamespace == null) {
|
if (currentNamespace == null) {
|
||||||
currentNamespace = program.getGlobalNamespace();
|
currentNamespace = program.getGlobalNamespace();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -17,23 +16,19 @@
|
||||||
package ghidra.app.cmd.label;
|
package ghidra.app.cmd.label;
|
||||||
|
|
||||||
import ghidra.framework.cmd.Command;
|
import ghidra.framework.cmd.Command;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.listing.CircularDependencyException;
|
import ghidra.program.model.listing.CircularDependencyException;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.program.model.symbol.*;
|
import ghidra.program.model.symbol.*;
|
||||||
import ghidra.program.model.symbol.Symbol;
|
|
||||||
import ghidra.program.model.symbol.SymbolTable;
|
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
import ghidra.util.exception.InvalidInputException;
|
import ghidra.util.exception.InvalidInputException;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Command for changing the scope of a label.
|
* Command for changing the scope of a label.
|
||||||
* The scope is the namespace that the label is associated with.
|
* The scope is the namespace that the label is associated with.
|
||||||
*/
|
*/
|
||||||
public class SetLabelNamespaceCmd implements Command {
|
public class SetLabelNamespaceCmd implements Command<Program> {
|
||||||
private SymbolTable st;
|
|
||||||
private Address addr;
|
private Address addr;
|
||||||
private String name;
|
private String name;
|
||||||
private Namespace oldNamespace;
|
private Namespace oldNamespace;
|
||||||
|
@ -47,51 +42,46 @@ public class SetLabelNamespaceCmd implements Command {
|
||||||
* @param oldNamespace the current scope of the label that will be changed.
|
* @param oldNamespace the current scope of the label that will be changed.
|
||||||
* @param newNamespace the new scope of the label.
|
* @param newNamespace the new scope of the label.
|
||||||
*/
|
*/
|
||||||
public SetLabelNamespaceCmd(Address addr, String name,
|
public SetLabelNamespaceCmd(Address addr, String name, Namespace oldNamespace,
|
||||||
Namespace oldNamespace, Namespace newNamespace) {
|
Namespace newNamespace) {
|
||||||
this.addr = addr;
|
this.addr = addr;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.oldNamespace = oldNamespace;
|
this.oldNamespace = oldNamespace;
|
||||||
this.newNamespace = newNamespace;
|
this.newNamespace = newNamespace;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
*
|
public boolean applyTo(Program program) {
|
||||||
* @see ghidra.framework.cmd.Command#applyTo(ghidra.framework.model.DomainObject)
|
SymbolTable st = program.getSymbolTable();
|
||||||
*/
|
|
||||||
public boolean applyTo(DomainObject obj) {
|
|
||||||
st = ((Program)obj).getSymbolTable();
|
|
||||||
|
|
||||||
Symbol s = st.getSymbol(name, addr, oldNamespace);
|
Symbol s = st.getSymbol(name, addr, oldNamespace);
|
||||||
if (s == null) {
|
if (s == null) {
|
||||||
errorMsg = "No symbol named "+name+" found at address "+addr+
|
errorMsg = "No symbol named " + name + " found at address " + addr + " in namespace " +
|
||||||
" in namespace "+oldNamespace;
|
oldNamespace;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
s.setNamespace(newNamespace);
|
s.setNamespace(newNamespace);
|
||||||
return true;
|
return true;
|
||||||
}catch (DuplicateNameException e) {
|
}
|
||||||
errorMsg = "Symbol named "+name+" already exists in namespace "+newNamespace;
|
catch (DuplicateNameException e) {
|
||||||
} catch (InvalidInputException e) {
|
errorMsg = "Symbol named " + name + " already exists in namespace " + newNamespace;
|
||||||
|
}
|
||||||
|
catch (InvalidInputException e) {
|
||||||
errorMsg = e.getMessage();
|
errorMsg = e.getMessage();
|
||||||
} catch (CircularDependencyException e) {
|
}
|
||||||
|
catch (CircularDependencyException e) {
|
||||||
errorMsg = e.getMessage();
|
errorMsg = e.getMessage();
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
/**
|
|
||||||
* @see ghidra.framework.cmd.Command#getName()
|
|
||||||
*/
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "Set Namespace";
|
return "Set Namespace";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* @see ghidra.framework.cmd.Command#getStatusMsg()
|
|
||||||
*/
|
|
||||||
public String getStatusMsg() {
|
public String getStatusMsg() {
|
||||||
return errorMsg;
|
return errorMsg;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
package ghidra.app.cmd.label;
|
package ghidra.app.cmd.label;
|
||||||
|
|
||||||
import ghidra.framework.cmd.Command;
|
import ghidra.framework.cmd.Command;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.listing.CircularDependencyException;
|
import ghidra.program.model.listing.CircularDependencyException;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
|
@ -29,8 +28,8 @@ import ghidra.util.exception.InvalidInputException;
|
||||||
* makes sense if there is more than one label at the address - otherwise
|
* makes sense if there is more than one label at the address - otherwise
|
||||||
* the label will already be primary.
|
* the label will already be primary.
|
||||||
*/
|
*/
|
||||||
public class SetLabelPrimaryCmd implements Command {
|
public class SetLabelPrimaryCmd implements Command<Program> {
|
||||||
private SymbolTable st;
|
|
||||||
private Address addr;
|
private Address addr;
|
||||||
private String name;
|
private String name;
|
||||||
private Namespace namespace;
|
private Namespace namespace;
|
||||||
|
@ -50,14 +49,9 @@ public class SetLabelPrimaryCmd implements Command {
|
||||||
this.namespace = namespace;
|
this.namespace = namespace;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see ghidra.framework.cmd.Command#applyTo(ghidra.framework.model.DomainObject)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applyTo(DomainObject obj) {
|
public boolean applyTo(Program program) {
|
||||||
Program program = (Program) obj;
|
SymbolTable st = program.getSymbolTable();
|
||||||
st = program.getSymbolTable();
|
|
||||||
Symbol oldSymbol = st.getPrimarySymbol(addr);
|
Symbol oldSymbol = st.getPrimarySymbol(addr);
|
||||||
|
|
||||||
if (oldSymbol == null) {
|
if (oldSymbol == null) {
|
||||||
|
@ -75,10 +69,8 @@ public class SetLabelPrimaryCmd implements Command {
|
||||||
// change the state of the symbol, like changing the namespace of a default symbol,
|
// change the state of the symbol, like changing the namespace of a default symbol,
|
||||||
// which has no effect
|
// which has no effect
|
||||||
if (!oldSymbol.isDynamic()) {
|
if (!oldSymbol.isDynamic()) {
|
||||||
errorMsg =
|
errorMsg = "Symbol " + name + " does not exist in namespace " + namespace +
|
||||||
"Symbol " + name + " does not exist in namespace " + namespace +
|
" at address " + addr;
|
||||||
" at address " +
|
|
||||||
addr;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -103,7 +95,8 @@ public class SetLabelPrimaryCmd implements Command {
|
||||||
oldSymbol.setNameAndNamespace(name, namespace, symbolSource);
|
oldSymbol.setNameAndNamespace(name, namespace, symbolSource);
|
||||||
symbol = oldSymbol;
|
symbol = oldSymbol;
|
||||||
// If renamed oldSymbol is now Default source don't keep old name (handles special Thunk rename case)
|
// If renamed oldSymbol is now Default source don't keep old name (handles special Thunk rename case)
|
||||||
if (oldSource != SourceType.DEFAULT && oldSymbol.getSource() != SourceType.DEFAULT) {
|
if (oldSource != SourceType.DEFAULT &&
|
||||||
|
oldSymbol.getSource() != SourceType.DEFAULT) {
|
||||||
// put the other symbol back using the old namespace and old source
|
// put the other symbol back using the old namespace and old source
|
||||||
st.createLabel(addr, oldName, oldParent, oldSource);
|
st.createLabel(addr, oldName, oldParent, oldSource);
|
||||||
}
|
}
|
||||||
|
@ -127,17 +120,11 @@ public class SetLabelPrimaryCmd implements Command {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.framework.cmd.Command#getStatusMsg()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public String getStatusMsg() {
|
public String getStatusMsg() {
|
||||||
return errorMsg;
|
return errorMsg;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.framework.cmd.Command#getName()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "Set Primary Label";
|
return "Set Primary Label";
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
package ghidra.app.cmd.memory;
|
package ghidra.app.cmd.memory;
|
||||||
|
|
||||||
import ghidra.framework.cmd.Command;
|
import ghidra.framework.cmd.Command;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.framework.store.LockException;
|
import ghidra.framework.store.LockException;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.address.AddressOverflowException;
|
import ghidra.program.model.address.AddressOverflowException;
|
||||||
|
@ -28,7 +27,8 @@ import ghidra.util.exception.*;
|
||||||
/**
|
/**
|
||||||
* Base command class for adding memory blocks.
|
* Base command class for adding memory blocks.
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractAddMemoryBlockCmd implements Command {
|
public abstract class AbstractAddMemoryBlockCmd implements Command<Program> {
|
||||||
|
|
||||||
protected String message;
|
protected String message;
|
||||||
protected final String name;
|
protected final String name;
|
||||||
protected final String comment;
|
protected final String comment;
|
||||||
|
@ -82,8 +82,7 @@ public abstract class AbstractAddMemoryBlockCmd implements Command {
|
||||||
MemoryConflictException, AddressOverflowException, CancelledException;
|
MemoryConflictException, AddressOverflowException, CancelledException;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applyTo(DomainObject obj) {
|
public boolean applyTo(Program program) {
|
||||||
Program program = (Program) obj;
|
|
||||||
try {
|
try {
|
||||||
Memory memory = program.getMemory();
|
Memory memory = program.getMemory();
|
||||||
MemoryBlock block = createMemoryBlock(memory);
|
MemoryBlock block = createMemoryBlock(memory);
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
package ghidra.app.cmd.memory;
|
package ghidra.app.cmd.memory;
|
||||||
|
|
||||||
import ghidra.framework.cmd.BackgroundCommand;
|
import ghidra.framework.cmd.BackgroundCommand;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.framework.store.LockException;
|
import ghidra.framework.store.LockException;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
|
@ -29,7 +28,7 @@ import ghidra.util.task.TaskMonitor;
|
||||||
* Command that runs in the background to delete a memory block, as
|
* Command that runs in the background to delete a memory block, as
|
||||||
* the delete may be a time consuming operation.
|
* the delete may be a time consuming operation.
|
||||||
*/
|
*/
|
||||||
public class DeleteBlockCmd extends BackgroundCommand {
|
public class DeleteBlockCmd extends BackgroundCommand<Program> {
|
||||||
private Address[] blockAddresses;
|
private Address[] blockAddresses;
|
||||||
private DeleteBlockListener listener;
|
private DeleteBlockListener listener;
|
||||||
private boolean status;
|
private boolean status;
|
||||||
|
@ -51,8 +50,8 @@ public class DeleteBlockCmd extends BackgroundCommand {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applyTo(DomainObject obj, TaskMonitor monitor) {
|
public boolean applyTo(Program program, TaskMonitor monitor) {
|
||||||
Program program = (Program) obj;
|
|
||||||
Memory mem = program.getMemory();
|
Memory mem = program.getMemory();
|
||||||
|
|
||||||
if (!program.hasExclusiveAccess()) {
|
if (!program.hasExclusiveAccess()) {
|
||||||
|
|
|
@ -19,7 +19,6 @@ import java.util.*;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import ghidra.framework.cmd.BackgroundCommand;
|
import ghidra.framework.cmd.BackgroundCommand;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.graph.GDirectedGraph;
|
import ghidra.graph.GDirectedGraph;
|
||||||
import ghidra.graph.GraphFactory;
|
import ghidra.graph.GraphFactory;
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
|
@ -33,7 +32,7 @@ import ghidra.util.Msg;
|
||||||
import ghidra.util.exception.*;
|
import ghidra.util.exception.*;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
|
||||||
public abstract class AbstractModularizationCmd extends BackgroundCommand {
|
public abstract class AbstractModularizationCmd extends BackgroundCommand<Program> {
|
||||||
protected Program program;
|
protected Program program;
|
||||||
private GroupPath groupPath;
|
private GroupPath groupPath;
|
||||||
private String treeName;
|
private String treeName;
|
||||||
|
@ -60,9 +59,9 @@ public abstract class AbstractModularizationCmd extends BackgroundCommand {
|
||||||
protected abstract void applyModel() throws CancelledException;
|
protected abstract void applyModel() throws CancelledException;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applyTo(DomainObject obj, TaskMonitor taskMonitor) {
|
public boolean applyTo(Program p, TaskMonitor taskMonitor) {
|
||||||
|
|
||||||
program = (Program) obj;
|
program = p;
|
||||||
monitor = taskMonitor;
|
monitor = taskMonitor;
|
||||||
monitor.setIndeterminate(true);
|
monitor.setIndeterminate(true);
|
||||||
ProgramModule rootModule = program.getListing().getRootModule(treeName);
|
ProgramModule rootModule = program.getListing().getRootModule(treeName);
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
package ghidra.app.cmd.module;
|
package ghidra.app.cmd.module;
|
||||||
|
|
||||||
import ghidra.framework.cmd.Command;
|
import ghidra.framework.cmd.Command;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.*;
|
||||||
import ghidra.program.model.mem.MemoryBlock;
|
import ghidra.program.model.mem.MemoryBlock;
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
|
@ -28,7 +27,7 @@ import ghidra.util.exception.DuplicateNameException;
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class CreateDefaultTreeCmd implements Command {
|
public class CreateDefaultTreeCmd implements Command<Program> {
|
||||||
|
|
||||||
private String treeName;
|
private String treeName;
|
||||||
private String statusMsg;
|
private String statusMsg;
|
||||||
|
@ -41,18 +40,15 @@ public class CreateDefaultTreeCmd implements Command {
|
||||||
this.treeName = treeName;
|
this.treeName = treeName;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
*
|
public boolean applyTo(Program program) {
|
||||||
* @see ghidra.framework.cmd.Command#applyTo(ghidra.framework.model.DomainObject)
|
|
||||||
*/
|
|
||||||
public boolean applyTo(DomainObject obj) {
|
|
||||||
Program program = (Program)obj;
|
|
||||||
Listing listing = program.getListing();
|
Listing listing = program.getListing();
|
||||||
try {
|
try {
|
||||||
listing.createRootModule(treeName);
|
listing.createRootModule(treeName);
|
||||||
renameFragments(program, treeName);
|
renameFragments(program, treeName);
|
||||||
return true;
|
return true;
|
||||||
} catch (DuplicateNameException e) {
|
}
|
||||||
|
catch (DuplicateNameException e) {
|
||||||
statusMsg = e.getMessage();
|
statusMsg = e.getMessage();
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -80,26 +76,23 @@ public class CreateDefaultTreeCmd implements Command {
|
||||||
private static void renameFragments(Program program, String treeName) {
|
private static void renameFragments(Program program, String treeName) {
|
||||||
Listing listing = program.getListing();
|
Listing listing = program.getListing();
|
||||||
MemoryBlock[] blocks = program.getMemory().getBlocks();
|
MemoryBlock[] blocks = program.getMemory().getBlocks();
|
||||||
for (int i=0; i<blocks.length; i++) {
|
for (MemoryBlock block : blocks) {
|
||||||
ProgramFragment fragment = listing.getFragment(treeName,
|
ProgramFragment fragment = listing.getFragment(treeName, block.getStart());
|
||||||
blocks[i].getStart());
|
|
||||||
try {
|
try {
|
||||||
fragment.setName(blocks[i].getName());
|
fragment.setName(block.getName());
|
||||||
} catch (DuplicateNameException e) {
|
}
|
||||||
|
catch (DuplicateNameException e) {
|
||||||
|
// ignore
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* @see ghidra.framework.cmd.Command#getStatusMsg()
|
|
||||||
*/
|
|
||||||
public String getStatusMsg() {
|
public String getStatusMsg() {
|
||||||
return statusMsg;
|
return statusMsg;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* @see ghidra.framework.cmd.Command#getName()
|
|
||||||
*/
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "Create Tree " + treeName;
|
return "Create Tree " + treeName;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,14 +16,13 @@
|
||||||
package ghidra.app.cmd.module;
|
package ghidra.app.cmd.module;
|
||||||
|
|
||||||
import ghidra.framework.cmd.Command;
|
import ghidra.framework.cmd.Command;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.*;
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Command to create a folder in a program tree.
|
* Command to create a folder in a program tree.
|
||||||
*/
|
*/
|
||||||
public class CreateFolderCommand implements Command {
|
public class CreateFolderCommand implements Command<Program> {
|
||||||
|
|
||||||
private String name;
|
private String name;
|
||||||
private String statusMsg;
|
private String statusMsg;
|
||||||
|
@ -41,11 +40,8 @@ public class CreateFolderCommand implements Command {
|
||||||
this.parentName = parentName;
|
this.parentName = parentName;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* @see ghidra.framework.cmd.Command#applyTo(ghidra.framework.model.DomainObject)
|
public boolean applyTo(Program program) {
|
||||||
*/
|
|
||||||
public boolean applyTo(DomainObject obj) {
|
|
||||||
Program program = (Program)obj;
|
|
||||||
Listing listing = program.getListing();
|
Listing listing = program.getListing();
|
||||||
ProgramModule m = listing.getModule(treeName, parentName);
|
ProgramModule m = listing.getModule(treeName, parentName);
|
||||||
if (m == null) {
|
if (m == null) {
|
||||||
|
@ -56,7 +52,8 @@ public class CreateFolderCommand implements Command {
|
||||||
try {
|
try {
|
||||||
m.createModule(name);
|
m.createModule(name);
|
||||||
return true;
|
return true;
|
||||||
} catch (DuplicateNameException e) {
|
}
|
||||||
|
catch (DuplicateNameException e) {
|
||||||
statusMsg = name + " already exists";
|
statusMsg = name + " already exists";
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -65,6 +62,7 @@ public class CreateFolderCommand implements Command {
|
||||||
/**
|
/**
|
||||||
* @see ghidra.framework.cmd.Command#getStatusMsg()
|
* @see ghidra.framework.cmd.Command#getStatusMsg()
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public String getStatusMsg() {
|
public String getStatusMsg() {
|
||||||
return statusMsg;
|
return statusMsg;
|
||||||
}
|
}
|
||||||
|
@ -72,6 +70,7 @@ public class CreateFolderCommand implements Command {
|
||||||
/**
|
/**
|
||||||
* @see ghidra.framework.cmd.Command#getName()
|
* @see ghidra.framework.cmd.Command#getName()
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "Create Folder";
|
return "Create Folder";
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
package ghidra.app.cmd.module;
|
package ghidra.app.cmd.module;
|
||||||
|
|
||||||
import ghidra.framework.cmd.Command;
|
import ghidra.framework.cmd.Command;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.*;
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
|
|
||||||
|
@ -25,7 +24,7 @@ import ghidra.util.exception.DuplicateNameException;
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class CreateFragmentCmd implements Command {
|
public class CreateFragmentCmd implements Command<Program> {
|
||||||
|
|
||||||
private String name;
|
private String name;
|
||||||
private String statusMsg;
|
private String statusMsg;
|
||||||
|
@ -50,8 +49,8 @@ public class CreateFragmentCmd implements Command {
|
||||||
* @return false if the fragment was not created
|
* @return false if the fragment was not created
|
||||||
* @see ghidra.framework.cmd.Command#applyTo(ghidra.framework.model.DomainObject)
|
* @see ghidra.framework.cmd.Command#applyTo(ghidra.framework.model.DomainObject)
|
||||||
*/
|
*/
|
||||||
public boolean applyTo(DomainObject obj) {
|
@Override
|
||||||
Program program = (Program)obj;
|
public boolean applyTo(Program program) {
|
||||||
Listing listing = program.getListing();
|
Listing listing = program.getListing();
|
||||||
ProgramModule m = listing.getModule(treeName, parentName);
|
ProgramModule m = listing.getModule(treeName, parentName);
|
||||||
if (m == null) {
|
if (m == null) {
|
||||||
|
@ -62,22 +61,19 @@ public class CreateFragmentCmd implements Command {
|
||||||
try {
|
try {
|
||||||
m.createFragment(name);
|
m.createFragment(name);
|
||||||
return true;
|
return true;
|
||||||
} catch (DuplicateNameException e) {
|
}
|
||||||
|
catch (DuplicateNameException e) {
|
||||||
statusMsg = name + " already exists";
|
statusMsg = name + " already exists";
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* @see ghidra.framework.cmd.Command#getStatusMsg()
|
|
||||||
*/
|
|
||||||
public String getStatusMsg() {
|
public String getStatusMsg() {
|
||||||
return statusMsg;
|
return statusMsg;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* @see ghidra.framework.cmd.Command#getName()
|
|
||||||
*/
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "Create Fragment";
|
return "Create Fragment";
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -17,7 +16,6 @@
|
||||||
package ghidra.app.cmd.module;
|
package ghidra.app.cmd.module;
|
||||||
|
|
||||||
import ghidra.framework.cmd.Command;
|
import ghidra.framework.cmd.Command;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -25,7 +23,7 @@ import ghidra.program.model.listing.Program;
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class DeleteTreeCmd implements Command {
|
public class DeleteTreeCmd implements Command<Program> {
|
||||||
private String treeName;
|
private String treeName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -36,25 +34,17 @@ public class DeleteTreeCmd implements Command {
|
||||||
this.treeName = treeName;
|
this.treeName = treeName;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
*
|
public boolean applyTo(Program program) {
|
||||||
* @see ghidra.framework.cmd.Command#applyTo(ghidra.framework.model.DomainObject)
|
|
||||||
*/
|
|
||||||
public boolean applyTo(DomainObject obj) {
|
|
||||||
Program program = (Program)obj;
|
|
||||||
return program.getListing().removeTree(treeName);
|
return program.getListing().removeTree(treeName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* @see ghidra.framework.cmd.Command#getStatusMsg()
|
|
||||||
*/
|
|
||||||
public String getStatusMsg() {
|
public String getStatusMsg() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* @see ghidra.framework.cmd.Command#getName()
|
|
||||||
*/
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "Delete " + treeName;
|
return "Delete " + treeName;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
package ghidra.app.cmd.module;
|
package ghidra.app.cmd.module;
|
||||||
|
|
||||||
import ghidra.framework.cmd.Command;
|
import ghidra.framework.cmd.Command;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.*;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
import ghidra.util.exception.NotEmptyException;
|
import ghidra.util.exception.NotEmptyException;
|
||||||
|
@ -28,7 +27,7 @@ import ghidra.util.exception.NotFoundException;
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class MergeFolderCmd implements Command {
|
public class MergeFolderCmd implements Command<Program> {
|
||||||
|
|
||||||
private String treeName;
|
private String treeName;
|
||||||
private String folderName;
|
private String folderName;
|
||||||
|
@ -49,13 +48,9 @@ public class MergeFolderCmd implements Command {
|
||||||
this.parentName = parentName;
|
this.parentName = parentName;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see ghidra.framework.cmd.Command#applyTo(ghidra.framework.model.DomainObject)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applyTo(DomainObject obj) {
|
public boolean applyTo(Program program) {
|
||||||
|
|
||||||
Program program = (Program) obj;
|
|
||||||
Listing listing = program.getListing();
|
Listing listing = program.getListing();
|
||||||
|
|
||||||
ProgramModule parentModule = listing.getModule(treeName, parentName);
|
ProgramModule parentModule = listing.getModule(treeName, parentName);
|
||||||
|
@ -66,12 +61,12 @@ public class MergeFolderCmd implements Command {
|
||||||
}
|
}
|
||||||
Group[] groups = module.getChildren();
|
Group[] groups = module.getChildren();
|
||||||
|
|
||||||
for (int i = 0; i < groups.length; i++) {
|
for (Group group : groups) {
|
||||||
|
|
||||||
// first check to make sure that the parent module
|
// first check to make sure that the parent module
|
||||||
// does not alreay contain tree group
|
// does not alreay contain tree group
|
||||||
|
|
||||||
String name = groups[i].getName();
|
String name = group.getName();
|
||||||
ProgramModule m = listing.getModule(treeName, name);
|
ProgramModule m = listing.getModule(treeName, name);
|
||||||
ProgramFragment f = null;
|
ProgramFragment f = null;
|
||||||
try {
|
try {
|
||||||
|
@ -100,8 +95,8 @@ public class MergeFolderCmd implements Command {
|
||||||
try {
|
try {
|
||||||
ProgramModule m = listing.getModule(treeName, folderName);
|
ProgramModule m = listing.getModule(treeName, folderName);
|
||||||
ProgramModule[] parents = m.getParents();
|
ProgramModule[] parents = m.getParents();
|
||||||
for (int i = 0; i < parents.length; i++) {
|
for (ProgramModule parent : parents) {
|
||||||
parents[i].removeChild(folderName);
|
parent.removeChild(folderName);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -111,17 +106,11 @@ public class MergeFolderCmd implements Command {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see ghidra.framework.cmd.Command#getStatusMsg()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public String getStatusMsg() {
|
public String getStatusMsg() {
|
||||||
return errMsg;
|
return errMsg;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see ghidra.framework.cmd.Command#getName()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "Merge " + folderName + " with Parent";
|
return "Merge " + folderName + " with Parent";
|
||||||
|
|
|
@ -19,7 +19,6 @@ import java.util.*;
|
||||||
|
|
||||||
import ghidra.app.services.BlockModelService;
|
import ghidra.app.services.BlockModelService;
|
||||||
import ghidra.framework.cmd.BackgroundCommand;
|
import ghidra.framework.cmd.BackgroundCommand;
|
||||||
import ghidra.framework.model.DomainObject;
|
|
||||||
import ghidra.framework.plugintool.PluginTool;
|
import ghidra.framework.plugintool.PluginTool;
|
||||||
import ghidra.program.model.address.AddressRange;
|
import ghidra.program.model.address.AddressRange;
|
||||||
import ghidra.program.model.address.AddressRangeIterator;
|
import ghidra.program.model.address.AddressRangeIterator;
|
||||||
|
@ -37,11 +36,8 @@ import ghidra.util.task.TaskMonitor;
|
||||||
* Creates a folder for each code block in the iterator.
|
* Creates a folder for each code block in the iterator.
|
||||||
* For each code block, gets an iterator over code blocks containing the code block.
|
* For each code block, gets an iterator over code blocks containing the code block.
|
||||||
* For each of these code blocks, create a fragment and move the code units to the fragment.
|
* For each of these code blocks, create a fragment and move the code units to the fragment.
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class ModuleAlgorithmCmd extends BackgroundCommand {
|
public class ModuleAlgorithmCmd extends BackgroundCommand<Program> {
|
||||||
|
|
||||||
private static final String NEW_MODULE_SUFFIX = " [Subroutine Tree]";
|
private static final String NEW_MODULE_SUFFIX = " [Subroutine Tree]";
|
||||||
private static final String PROGRAM_CHANGED_MESSAGE =
|
private static final String PROGRAM_CHANGED_MESSAGE =
|
||||||
|
@ -71,14 +67,9 @@ public class ModuleAlgorithmCmd extends BackgroundCommand {
|
||||||
this.partitioningModelName = partitioningModelName;
|
this.partitioningModelName = partitioningModelName;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see ghidra.framework.cmd.BackgroundCommand#applyTo(ghidra.framework.model.DomainObject, ghidra.util.task.TaskMonitor)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applyTo(DomainObject obj, TaskMonitor monitor) {
|
public boolean applyTo(Program program, TaskMonitor monitor) {
|
||||||
|
|
||||||
Program program = (Program) obj;
|
|
||||||
ProgramModule root = program.getListing().getRootModule(treeName);
|
ProgramModule root = program.getListing().getRootModule(treeName);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -103,13 +94,6 @@ public class ModuleAlgorithmCmd extends BackgroundCommand {
|
||||||
this.tool = tool;
|
this.tool = tool;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param monitor
|
|
||||||
* @throws NotFoundException
|
|
||||||
* @throws NotEmptyException
|
|
||||||
* @throws DuplicateNameException
|
|
||||||
*/
|
|
||||||
private boolean applyModel(Program program, ProgramModule root, TaskMonitor monitor)
|
private boolean applyModel(Program program, ProgramModule root, TaskMonitor monitor)
|
||||||
throws NotFoundException, NotEmptyException, DuplicateNameException {
|
throws NotFoundException, NotEmptyException, DuplicateNameException {
|
||||||
|
|
||||||
|
@ -125,9 +109,8 @@ public class ModuleAlgorithmCmd extends BackgroundCommand {
|
||||||
(SubroutineBlockModel) blockModelService.getActiveSubroutineModel(program);
|
(SubroutineBlockModel) blockModelService.getActiveSubroutineModel(program);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
partitioningModel =
|
partitioningModel = (SubroutineBlockModel) blockModelService
|
||||||
(SubroutineBlockModel) blockModelService.getNewModelByName(partitioningModelName,
|
.getNewModelByName(partitioningModelName, program);
|
||||||
program);
|
|
||||||
}
|
}
|
||||||
SubroutineBlockModel baseModel = partitioningModel.getBaseSubroutineModel();
|
SubroutineBlockModel baseModel = partitioningModel.getBaseSubroutineModel();
|
||||||
|
|
||||||
|
@ -315,6 +298,7 @@ public class ModuleAlgorithmCmd extends BackgroundCommand {
|
||||||
module.setName(baseName + numKidsPrefix + module.getNumChildren() + "]");
|
module.setName(baseName + numKidsPrefix + module.getNumChildren() + "]");
|
||||||
}
|
}
|
||||||
catch (DuplicateNameException e) {
|
catch (DuplicateNameException e) {
|
||||||
|
// ignore
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue