mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-05-30 14:41:07 +08:00
GP-1386: A generic object store in DBTrace for recording the object model tree
This commit is contained in:
+6
-6
@@ -121,28 +121,28 @@ public abstract class AbstractModelForDbgengBreakpointsTest
|
|||||||
@Override
|
@Override
|
||||||
protected void disableViaInterpreter(TargetTogglable t, TargetInterpreter interpreter)
|
protected void disableViaInterpreter(TargetTogglable t, TargetInterpreter interpreter)
|
||||||
throws Throwable {
|
throws Throwable {
|
||||||
String bpId = getBreakPattern().matchIndices(t.getPath()).get(BREAK_ID_POS);
|
String bpId = getBreakPattern().matchKeys(t.getPath()).get(BREAK_ID_POS);
|
||||||
waitOn(interpreter.execute("bd " + bpId));
|
waitOn(interpreter.execute("bd " + bpId));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void enableViaInterpreter(TargetTogglable t, TargetInterpreter interpreter)
|
protected void enableViaInterpreter(TargetTogglable t, TargetInterpreter interpreter)
|
||||||
throws Throwable {
|
throws Throwable {
|
||||||
String bpId = getBreakPattern().matchIndices(t.getPath()).get(BREAK_ID_POS);
|
String bpId = getBreakPattern().matchKeys(t.getPath()).get(BREAK_ID_POS);
|
||||||
waitOn(interpreter.execute("be " + bpId));
|
waitOn(interpreter.execute("be " + bpId));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void deleteViaInterpreter(TargetDeletable d, TargetInterpreter interpreter)
|
protected void deleteViaInterpreter(TargetDeletable d, TargetInterpreter interpreter)
|
||||||
throws Throwable {
|
throws Throwable {
|
||||||
String bpId = getBreakPattern().matchIndices(d.getPath()).get(BREAK_ID_POS);
|
String bpId = getBreakPattern().matchKeys(d.getPath()).get(BREAK_ID_POS);
|
||||||
waitOn(interpreter.execute("bc " + bpId));
|
waitOn(interpreter.execute("bc " + bpId));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void assertLocCoversViaInterpreter(AddressRange range, TargetBreakpointKind kind,
|
protected void assertLocCoversViaInterpreter(AddressRange range, TargetBreakpointKind kind,
|
||||||
TargetBreakpointLocation loc, TargetInterpreter interpreter) throws Throwable {
|
TargetBreakpointLocation loc, TargetInterpreter interpreter) throws Throwable {
|
||||||
String bpId = getBreakPattern().matchIndices(loc.getPath()).get(BREAK_ID_POS);
|
String bpId = getBreakPattern().matchKeys(loc.getPath()).get(BREAK_ID_POS);
|
||||||
String line = waitOn(interpreter.executeCapture("bl " + bpId)).trim();
|
String line = waitOn(interpreter.executeCapture("bl " + bpId)).trim();
|
||||||
assertFalse(line.contains("\n"));
|
assertFalse(line.contains("\n"));
|
||||||
// NB. WinDbg numbers breakpoints in base 10, by default
|
// NB. WinDbg numbers breakpoints in base 10, by default
|
||||||
@@ -153,7 +153,7 @@ public abstract class AbstractModelForDbgengBreakpointsTest
|
|||||||
@Override
|
@Override
|
||||||
protected void assertEnabledViaInterpreter(TargetTogglable t, boolean enabled,
|
protected void assertEnabledViaInterpreter(TargetTogglable t, boolean enabled,
|
||||||
TargetInterpreter interpreter) throws Throwable {
|
TargetInterpreter interpreter) throws Throwable {
|
||||||
String bpId = getBreakPattern().matchIndices(t.getPath()).get(BREAK_ID_POS);
|
String bpId = getBreakPattern().matchKeys(t.getPath()).get(BREAK_ID_POS);
|
||||||
String line = waitOn(interpreter.executeCapture("bl " + bpId)).trim();
|
String line = waitOn(interpreter.executeCapture("bl " + bpId)).trim();
|
||||||
assertFalse(line.contains("\n"));
|
assertFalse(line.contains("\n"));
|
||||||
assertTrue(line.startsWith(bpId));
|
assertTrue(line.startsWith(bpId));
|
||||||
@@ -164,7 +164,7 @@ public abstract class AbstractModelForDbgengBreakpointsTest
|
|||||||
@Override
|
@Override
|
||||||
protected void assertDeletedViaInterpreter(TargetDeletable d, TargetInterpreter interpreter)
|
protected void assertDeletedViaInterpreter(TargetDeletable d, TargetInterpreter interpreter)
|
||||||
throws Throwable {
|
throws Throwable {
|
||||||
String bpId = getBreakPattern().matchIndices(d.getPath()).get(BREAK_ID_POS);
|
String bpId = getBreakPattern().matchKeys(d.getPath()).get(BREAK_ID_POS);
|
||||||
String line = waitOn(interpreter.executeCapture("bl " + bpId)).trim();
|
String line = waitOn(interpreter.executeCapture("bl " + bpId)).trim();
|
||||||
assertEquals("", line);
|
assertEquals("", line);
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -72,7 +72,7 @@ public abstract class AbstractModelForDbgengFrameActivationTest
|
|||||||
String line = waitOn(interpreter.executeCapture(".frame")).trim();
|
String line = waitOn(interpreter.executeCapture(".frame")).trim();
|
||||||
assertFalse(line.contains("\n"));
|
assertFalse(line.contains("\n"));
|
||||||
int frameId = Integer.parseInt(line.split("\\s+")[0], 16);
|
int frameId = Integer.parseInt(line.split("\\s+")[0], 16);
|
||||||
int expId = Integer.decode(getStackPattern().matchIndices(expected.getPath()).get(2));
|
int expId = Integer.decode(getStackPattern().matchKeys(expected.getPath()).get(2));
|
||||||
assertEquals(expId, frameId);
|
assertEquals(expId, frameId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -63,7 +63,7 @@ public abstract class AbstractModelForDbgengProcessActivationTest
|
|||||||
@Override
|
@Override
|
||||||
protected void activateViaInterpreter(TargetObject obj, TargetInterpreter interpreter)
|
protected void activateViaInterpreter(TargetObject obj, TargetInterpreter interpreter)
|
||||||
throws Throwable {
|
throws Throwable {
|
||||||
String id = Unique.assertOne(getProcessPattern().matchIndices(obj.getPath()));
|
String id = Unique.assertOne(getProcessPattern().matchKeys(obj.getPath()));
|
||||||
waitOn(interpreter.execute("|" + id + " s"));
|
waitOn(interpreter.execute("|" + id + " s"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -63,7 +63,7 @@ public abstract class AbstractModelForDbgengThreadActivationTest
|
|||||||
@Override
|
@Override
|
||||||
protected void activateViaInterpreter(TargetObject obj, TargetInterpreter interpreter)
|
protected void activateViaInterpreter(TargetObject obj, TargetInterpreter interpreter)
|
||||||
throws Throwable {
|
throws Throwable {
|
||||||
String threadId = getThreadPattern().matchIndices(obj.getPath()).get(1);
|
String threadId = getThreadPattern().matchKeys(obj.getPath()).get(1);
|
||||||
// TODO: This test is imperfect, since processes are activated as well
|
// TODO: This test is imperfect, since processes are activated as well
|
||||||
waitOn(interpreter.execute("~" + threadId + " s"));
|
waitOn(interpreter.execute("~" + threadId + " s"));
|
||||||
}
|
}
|
||||||
@@ -78,7 +78,7 @@ public abstract class AbstractModelForDbgengThreadActivationTest
|
|||||||
.filter(l -> l.trim().startsWith("."))
|
.filter(l -> l.trim().startsWith("."))
|
||||||
.collect(Collectors.toList())).trim();
|
.collect(Collectors.toList())).trim();
|
||||||
String threadId = getIdFromCapture(line);
|
String threadId = getIdFromCapture(line);
|
||||||
String expId = getThreadPattern().matchIndices(expected.getPath()).get(1);
|
String expId = getThreadPattern().matchKeys(expected.getPath()).get(1);
|
||||||
assertEquals(expId, threadId);
|
assertEquals(expId, threadId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-6
@@ -119,7 +119,7 @@ public abstract class AbstractModelForGdbBreakpointsTest
|
|||||||
protected void disableViaInterpreter(TargetTogglable t, TargetInterpreter interpreter)
|
protected void disableViaInterpreter(TargetTogglable t, TargetInterpreter interpreter)
|
||||||
throws Throwable {
|
throws Throwable {
|
||||||
assert t instanceof TargetBreakpointSpec; // TODO: or Location
|
assert t instanceof TargetBreakpointSpec; // TODO: or Location
|
||||||
String index = Unique.assertOne(BREAK_PATTERN.matchIndices(t.getPath()));
|
String index = Unique.assertOne(BREAK_PATTERN.matchKeys(t.getPath()));
|
||||||
waitOn(interpreter.execute("disable " + index));
|
waitOn(interpreter.execute("disable " + index));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,7 +127,7 @@ public abstract class AbstractModelForGdbBreakpointsTest
|
|||||||
protected void enableViaInterpreter(TargetTogglable t, TargetInterpreter interpreter)
|
protected void enableViaInterpreter(TargetTogglable t, TargetInterpreter interpreter)
|
||||||
throws Throwable {
|
throws Throwable {
|
||||||
assert t instanceof TargetBreakpointSpec; // TODO: or Location
|
assert t instanceof TargetBreakpointSpec; // TODO: or Location
|
||||||
String index = Unique.assertOne(BREAK_PATTERN.matchIndices(t.getPath()));
|
String index = Unique.assertOne(BREAK_PATTERN.matchKeys(t.getPath()));
|
||||||
waitOn(interpreter.execute("enable " + index));
|
waitOn(interpreter.execute("enable " + index));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -135,7 +135,7 @@ public abstract class AbstractModelForGdbBreakpointsTest
|
|||||||
protected void deleteViaInterpreter(TargetDeletable d, TargetInterpreter interpreter)
|
protected void deleteViaInterpreter(TargetDeletable d, TargetInterpreter interpreter)
|
||||||
throws Throwable {
|
throws Throwable {
|
||||||
assert d instanceof TargetBreakpointSpec; // TODO: or Location
|
assert d instanceof TargetBreakpointSpec; // TODO: or Location
|
||||||
String index = Unique.assertOne(BREAK_PATTERN.matchIndices(d.getPath()));
|
String index = Unique.assertOne(BREAK_PATTERN.matchKeys(d.getPath()));
|
||||||
waitOn(interpreter.execute("delete " + index));
|
waitOn(interpreter.execute("delete " + index));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,7 +143,7 @@ public abstract class AbstractModelForGdbBreakpointsTest
|
|||||||
protected void assertLocCoversViaInterpreter(AddressRange range, TargetBreakpointKind kind,
|
protected void assertLocCoversViaInterpreter(AddressRange range, TargetBreakpointKind kind,
|
||||||
TargetBreakpointLocation loc, TargetInterpreter interpreter) throws Throwable {
|
TargetBreakpointLocation loc, TargetInterpreter interpreter) throws Throwable {
|
||||||
String index =
|
String index =
|
||||||
Unique.assertOne(BREAK_PATTERN.matchIndices(loc.getSpecification().getPath()));
|
Unique.assertOne(BREAK_PATTERN.matchKeys(loc.getSpecification().getPath()));
|
||||||
String output = waitOn(interpreter.executeCapture("info break " + index));
|
String output = waitOn(interpreter.executeCapture("info break " + index));
|
||||||
String line = Unique.assertOne(Stream.of(output.split("\n"))
|
String line = Unique.assertOne(Stream.of(output.split("\n"))
|
||||||
.filter(l -> !l.trim().startsWith("Num"))
|
.filter(l -> !l.trim().startsWith("Num"))
|
||||||
@@ -156,7 +156,7 @@ public abstract class AbstractModelForGdbBreakpointsTest
|
|||||||
protected void assertEnabledViaInterpreter(TargetTogglable t, boolean enabled,
|
protected void assertEnabledViaInterpreter(TargetTogglable t, boolean enabled,
|
||||||
TargetInterpreter interpreter) throws Throwable {
|
TargetInterpreter interpreter) throws Throwable {
|
||||||
assert t instanceof TargetBreakpointSpec; // TODO: or Location
|
assert t instanceof TargetBreakpointSpec; // TODO: or Location
|
||||||
String index = Unique.assertOne(BREAK_PATTERN.matchIndices(t.getPath()));
|
String index = Unique.assertOne(BREAK_PATTERN.matchKeys(t.getPath()));
|
||||||
String output = waitOn(interpreter.executeCapture("info break " + index));
|
String output = waitOn(interpreter.executeCapture("info break " + index));
|
||||||
String line = Unique.assertOne(Stream.of(output.split("\n"))
|
String line = Unique.assertOne(Stream.of(output.split("\n"))
|
||||||
.filter(l -> !l.trim().startsWith("Num"))
|
.filter(l -> !l.trim().startsWith("Num"))
|
||||||
@@ -170,7 +170,7 @@ public abstract class AbstractModelForGdbBreakpointsTest
|
|||||||
protected void assertDeletedViaInterpreter(TargetDeletable d, TargetInterpreter interpreter)
|
protected void assertDeletedViaInterpreter(TargetDeletable d, TargetInterpreter interpreter)
|
||||||
throws Throwable {
|
throws Throwable {
|
||||||
assert d instanceof TargetBreakpointSpec; // TODO: or Location
|
assert d instanceof TargetBreakpointSpec; // TODO: or Location
|
||||||
String index = Unique.assertOne(BREAK_PATTERN.matchIndices(d.getPath()));
|
String index = Unique.assertOne(BREAK_PATTERN.matchKeys(d.getPath()));
|
||||||
String output = waitOn(interpreter.executeCapture("info break " + index));
|
String output = waitOn(interpreter.executeCapture("info break " + index));
|
||||||
assertTrue(output.contains("No breakpoint"));
|
assertTrue(output.contains("No breakpoint"));
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -72,7 +72,7 @@ public abstract class AbstractModelForGdbFrameActivationTest
|
|||||||
@Override
|
@Override
|
||||||
protected void activateViaInterpreter(TargetObject obj, TargetInterpreter interpreter)
|
protected void activateViaInterpreter(TargetObject obj, TargetInterpreter interpreter)
|
||||||
throws Throwable {
|
throws Throwable {
|
||||||
String index = Unique.assertOne(STACK_PATTERN.matchIndices(obj.getPath()));
|
String index = Unique.assertOne(STACK_PATTERN.matchKeys(obj.getPath()));
|
||||||
waitOn(interpreter.execute("frame " + index));
|
waitOn(interpreter.execute("frame " + index));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -62,7 +62,7 @@ public abstract class AbstractModelForGdbInferiorActivationTest
|
|||||||
@Override
|
@Override
|
||||||
protected void activateViaInterpreter(TargetObject obj, TargetInterpreter interpreter)
|
protected void activateViaInterpreter(TargetObject obj, TargetInterpreter interpreter)
|
||||||
throws Throwable {
|
throws Throwable {
|
||||||
String index = Unique.assertOne(INF_PATTERN.matchIndices(obj.getPath()));
|
String index = Unique.assertOne(INF_PATTERN.matchKeys(obj.getPath()));
|
||||||
waitOn(interpreter.execute("inferior " + index));
|
waitOn(interpreter.execute("inferior " + index));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -73,7 +73,7 @@ public abstract class AbstractModelForGdbThreadActivationTest
|
|||||||
@Override
|
@Override
|
||||||
protected void activateViaInterpreter(TargetObject obj, TargetInterpreter interpreter)
|
protected void activateViaInterpreter(TargetObject obj, TargetInterpreter interpreter)
|
||||||
throws Throwable {
|
throws Throwable {
|
||||||
String index = Unique.assertOne(Set.copyOf(THREAD_PATTERN.matchIndices(obj.getPath())));
|
String index = Unique.assertOne(Set.copyOf(THREAD_PATTERN.matchKeys(obj.getPath())));
|
||||||
// TODO: This test is imperfect, since inferiors are activated as well
|
// TODO: This test is imperfect, since inferiors are activated as well
|
||||||
waitOn(interpreter.execute("thread " + index + ".1"));
|
waitOn(interpreter.execute("thread " + index + ".1"));
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-6
@@ -145,7 +145,7 @@ public abstract class AbstractModelForLldbBreakpointsTest
|
|||||||
@Override
|
@Override
|
||||||
protected void disableViaInterpreter(TargetTogglable t, TargetInterpreter interpreter)
|
protected void disableViaInterpreter(TargetTogglable t, TargetInterpreter interpreter)
|
||||||
throws Throwable {
|
throws Throwable {
|
||||||
String bpId = getBreakPattern().matchIndices(t.getPath()).get(BREAK_ID_POS);
|
String bpId = getBreakPattern().matchKeys(t.getPath()).get(BREAK_ID_POS);
|
||||||
String type = getTypeFromSpec(t);
|
String type = getTypeFromSpec(t);
|
||||||
waitOn(interpreter.execute(getCommand("disable", type, bpId)));
|
waitOn(interpreter.execute(getCommand("disable", type, bpId)));
|
||||||
}
|
}
|
||||||
@@ -153,7 +153,7 @@ public abstract class AbstractModelForLldbBreakpointsTest
|
|||||||
@Override
|
@Override
|
||||||
protected void enableViaInterpreter(TargetTogglable t, TargetInterpreter interpreter)
|
protected void enableViaInterpreter(TargetTogglable t, TargetInterpreter interpreter)
|
||||||
throws Throwable {
|
throws Throwable {
|
||||||
String bpId = getBreakPattern().matchIndices(t.getPath()).get(BREAK_ID_POS);
|
String bpId = getBreakPattern().matchKeys(t.getPath()).get(BREAK_ID_POS);
|
||||||
String type = getTypeFromSpec(t);
|
String type = getTypeFromSpec(t);
|
||||||
waitOn(interpreter.execute(getCommand("enable", type, bpId)));
|
waitOn(interpreter.execute(getCommand("enable", type, bpId)));
|
||||||
}
|
}
|
||||||
@@ -161,7 +161,7 @@ public abstract class AbstractModelForLldbBreakpointsTest
|
|||||||
@Override
|
@Override
|
||||||
protected void deleteViaInterpreter(TargetDeletable d, TargetInterpreter interpreter)
|
protected void deleteViaInterpreter(TargetDeletable d, TargetInterpreter interpreter)
|
||||||
throws Throwable {
|
throws Throwable {
|
||||||
String bpId = getBreakPattern().matchIndices(d.getPath()).get(BREAK_ID_POS);
|
String bpId = getBreakPattern().matchKeys(d.getPath()).get(BREAK_ID_POS);
|
||||||
String type = getTypeFromSpec(d);
|
String type = getTypeFromSpec(d);
|
||||||
waitOn(interpreter.execute(getCommand("delete", type, bpId)));
|
waitOn(interpreter.execute(getCommand("delete", type, bpId)));
|
||||||
}
|
}
|
||||||
@@ -169,7 +169,7 @@ public abstract class AbstractModelForLldbBreakpointsTest
|
|||||||
@Override
|
@Override
|
||||||
protected void assertLocCoversViaInterpreter(AddressRange range, TargetBreakpointKind kind,
|
protected void assertLocCoversViaInterpreter(AddressRange range, TargetBreakpointKind kind,
|
||||||
TargetBreakpointLocation loc, TargetInterpreter interpreter) throws Throwable {
|
TargetBreakpointLocation loc, TargetInterpreter interpreter) throws Throwable {
|
||||||
List<String> matchIndices = getBreakPattern().matchIndices(loc.getSpecification().getPath());
|
List<String> matchIndices = getBreakPattern().matchKeys(loc.getSpecification().getPath());
|
||||||
String bpId = matchIndices.get(BREAK_ID_POS);
|
String bpId = matchIndices.get(BREAK_ID_POS);
|
||||||
String type = getTypeFromKind(kind);
|
String type = getTypeFromKind(kind);
|
||||||
String line = waitOn(interpreter.executeCapture(getCommand("list", type, bpId))).trim();
|
String line = waitOn(interpreter.executeCapture(getCommand("list", type, bpId))).trim();
|
||||||
@@ -182,7 +182,7 @@ public abstract class AbstractModelForLldbBreakpointsTest
|
|||||||
@Override
|
@Override
|
||||||
protected void assertEnabledViaInterpreter(TargetTogglable t, boolean enabled,
|
protected void assertEnabledViaInterpreter(TargetTogglable t, boolean enabled,
|
||||||
TargetInterpreter interpreter) throws Throwable {
|
TargetInterpreter interpreter) throws Throwable {
|
||||||
String bpId = getBreakPattern().matchIndices(t.getPath()).get(BREAK_ID_POS);
|
String bpId = getBreakPattern().matchKeys(t.getPath()).get(BREAK_ID_POS);
|
||||||
String type = getTypeFromSpec(t);
|
String type = getTypeFromSpec(t);
|
||||||
String line = waitOn(interpreter.executeCapture(getCommand("list", type, bpId))).trim();
|
String line = waitOn(interpreter.executeCapture(getCommand("list", type, bpId))).trim();
|
||||||
assertTrue(line.contains(bpId.substring(1)+":"));
|
assertTrue(line.contains(bpId.substring(1)+":"));
|
||||||
@@ -192,7 +192,7 @@ public abstract class AbstractModelForLldbBreakpointsTest
|
|||||||
@Override
|
@Override
|
||||||
protected void assertDeletedViaInterpreter(TargetDeletable d, TargetInterpreter interpreter)
|
protected void assertDeletedViaInterpreter(TargetDeletable d, TargetInterpreter interpreter)
|
||||||
throws Throwable {
|
throws Throwable {
|
||||||
String bpId = getBreakPattern().matchIndices(d.getPath()).get(BREAK_ID_POS);
|
String bpId = getBreakPattern().matchKeys(d.getPath()).get(BREAK_ID_POS);
|
||||||
String type = getTypeFromSpec(d);
|
String type = getTypeFromSpec(d);
|
||||||
String line = waitOn(interpreter.executeCapture(type + " list ")).trim();
|
String line = waitOn(interpreter.executeCapture(type + " list ")).trim();
|
||||||
assertFalse(line.contains(bpId+":"));
|
assertFalse(line.contains(bpId+":"));
|
||||||
|
|||||||
+2
-2
@@ -57,7 +57,7 @@ public abstract class AbstractModelForLldbFrameActivationTest
|
|||||||
|
|
||||||
protected void activateViaInterpreter(TargetObject obj, TargetInterpreter interpreter)
|
protected void activateViaInterpreter(TargetObject obj, TargetInterpreter interpreter)
|
||||||
throws Throwable {
|
throws Throwable {
|
||||||
String index = getStackPattern().matchIndices(obj.getPath()).get(3);
|
String index = getStackPattern().matchKeys(obj.getPath()).get(3);
|
||||||
waitOn(interpreter.execute("frame select " + index));
|
waitOn(interpreter.execute("frame select " + index));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,7 +70,7 @@ public abstract class AbstractModelForLldbFrameActivationTest
|
|||||||
assertFalse(line.contains("\n"));
|
assertFalse(line.contains("\n"));
|
||||||
String id = getIdFromCapture(line);
|
String id = getIdFromCapture(line);
|
||||||
int frameId = Integer.parseInt(id, 10);
|
int frameId = Integer.parseInt(id, 10);
|
||||||
int expId = Integer.decode(getStackPattern().matchIndices(expected.getPath()).get(3));
|
int expId = Integer.decode(getStackPattern().matchKeys(expected.getPath()).get(3));
|
||||||
assertEquals(expId, frameId);
|
assertEquals(expId, frameId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -94,7 +94,7 @@ public abstract class AbstractModelForLldbProcessActivationTest
|
|||||||
.filter(l -> l.trim().startsWith("*"))
|
.filter(l -> l.trim().startsWith("*"))
|
||||||
.collect(Collectors.toList())).trim();
|
.collect(Collectors.toList())).trim();
|
||||||
String procId = getIdFromCapture(line);
|
String procId = getIdFromCapture(line);
|
||||||
String expId = getProcessPattern().matchIndices(expected.getPath()).get(1);
|
String expId = getProcessPattern().matchKeys(expected.getPath()).get(1);
|
||||||
assertEquals(Long.parseLong(expId, 16), Long.parseLong(procId));
|
assertEquals(Long.parseLong(expId, 16), Long.parseLong(procId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -97,7 +97,7 @@ public abstract class AbstractModelForLldbSessionActivationTest
|
|||||||
.filter(l -> l.trim().startsWith("*"))
|
.filter(l -> l.trim().startsWith("*"))
|
||||||
.collect(Collectors.toList())).trim();
|
.collect(Collectors.toList())).trim();
|
||||||
String procId = getIdFromCapture(line);
|
String procId = getIdFromCapture(line);
|
||||||
String expId = getSessionPattern().matchIndices(expected.getPath()).get(0);
|
String expId = getSessionPattern().matchKeys(expected.getPath()).get(0);
|
||||||
assertEquals(Long.parseLong(expId, 16), Long.parseLong(procId));
|
assertEquals(Long.parseLong(expId, 16), Long.parseLong(procId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -80,7 +80,7 @@ public abstract class AbstractModelForLldbThreadActivationTest
|
|||||||
.filter(l -> l.trim().startsWith("*"))
|
.filter(l -> l.trim().startsWith("*"))
|
||||||
.collect(Collectors.toList())).trim();
|
.collect(Collectors.toList())).trim();
|
||||||
String threadId = getIdFromCapture(line);
|
String threadId = getIdFromCapture(line);
|
||||||
String expId = getThreadPattern().matchIndices(expected.getPath()).get(2);
|
String expId = getThreadPattern().matchKeys(expected.getPath()).get(2);
|
||||||
assertEquals(expId, threadId);
|
assertEquals(expId, threadId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -38,7 +38,8 @@ public class BreakpointLocationRow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isEnabled() {
|
public boolean isEnabled() {
|
||||||
return loc.isEnabled();
|
TraceRecorder recorder = provider.modelService.getRecorder(loc.getTrace());
|
||||||
|
return recorder != null && loc.isEnabled(recorder.getSnap());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setEnabled(boolean enabled) {
|
public void setEnabled(boolean enabled) {
|
||||||
|
|||||||
+2
-2
@@ -210,8 +210,8 @@ public class DebuggerConsoleProvider extends ComponentProviderAdapter
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public java.util.List<LogTableColumns> defaultSortOrder() {
|
public List<LogTableColumns> defaultSortOrder() {
|
||||||
return java.util.List.of(LogTableColumns.ACTIONS, LogTableColumns.TIME);
|
return List.of(LogTableColumns.ACTIONS, LogTableColumns.TIME);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -228,7 +228,7 @@ public class DebuggerCopyPlan {
|
|||||||
Address dest = intoAddress.add(off);
|
Address dest = intoAddress.add(off);
|
||||||
ProgramBreakpoint pb =
|
ProgramBreakpoint pb =
|
||||||
new ProgramBreakpoint(into, dest, bpt.getLength(), bpt.getKinds());
|
new ProgramBreakpoint(into, dest, bpt.getLength(), bpt.getKinds());
|
||||||
if (bpt.isEnabled()) {
|
if (bpt.isEnabled(from.getSnap())) {
|
||||||
pb.enable();
|
pb.enable();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|||||||
+10
@@ -210,6 +210,11 @@ public class DebuggerModulesProvider extends ComponentProviderAdapter {
|
|||||||
public ModuleTableModel() {
|
public ModuleTableModel() {
|
||||||
super("Modules", ModuleTableColumns.class, TraceModule::getObjectKey, ModuleRow::new);
|
super("Modules", ModuleTableColumns.class, TraceModule::getObjectKey, ModuleRow::new);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<ModuleTableColumns> defaultSortOrder() {
|
||||||
|
return List.of(ModuleTableColumns.BASE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static class SectionTableModel
|
protected static class SectionTableModel
|
||||||
@@ -220,6 +225,11 @@ public class DebuggerModulesProvider extends ComponentProviderAdapter {
|
|||||||
super("Sections", SectionTableColumns.class, TraceSection::getObjectKey,
|
super("Sections", SectionTableColumns.class, TraceSection::getObjectKey,
|
||||||
SectionRow::new);
|
SectionRow::new);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<SectionTableColumns> defaultSortOrder() {
|
||||||
|
return List.of(SectionTableColumns.START);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static Set<TraceModule> getSelectedModulesFromModuleContext(
|
protected static Set<TraceModule> getSelectedModulesFromModuleContext(
|
||||||
|
|||||||
+8
-1
@@ -22,6 +22,7 @@ import ghidra.app.services.TraceRecorder;
|
|||||||
import ghidra.dbg.target.TargetExecutionStateful.TargetExecutionState;
|
import ghidra.dbg.target.TargetExecutionStateful.TargetExecutionState;
|
||||||
import ghidra.trace.model.Trace;
|
import ghidra.trace.model.Trace;
|
||||||
import ghidra.trace.model.thread.TraceThread;
|
import ghidra.trace.model.thread.TraceThread;
|
||||||
|
import ghidra.util.Msg;
|
||||||
import ghidra.util.database.UndoableTransaction;
|
import ghidra.util.database.UndoableTransaction;
|
||||||
|
|
||||||
public class ThreadRow {
|
public class ThreadRow {
|
||||||
@@ -109,6 +110,12 @@ public class ThreadRow {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return getName();
|
try {
|
||||||
|
return getName();
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
Msg.error(this, "Error rendering as string: " + e);
|
||||||
|
return "<ERROR>";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -288,7 +288,7 @@ public interface LogicalBreakpointInternal extends LogicalBreakpoint {
|
|||||||
public TraceEnablement computeEnablement() {
|
public TraceEnablement computeEnablement() {
|
||||||
TraceEnablement en = TraceEnablement.MISSING;
|
TraceEnablement en = TraceEnablement.MISSING;
|
||||||
for (IDHashed<TraceBreakpoint> bpt : breakpoints) {
|
for (IDHashed<TraceBreakpoint> bpt : breakpoints) {
|
||||||
en = en.combine(TraceEnablement.fromBool(bpt.obj.isEnabled()));
|
en = en.combine(TraceEnablement.fromBool(bpt.obj.isEnabled(recorder.getSnap())));
|
||||||
if (en == TraceEnablement.MIXED) {
|
if (en == TraceEnablement.MIXED) {
|
||||||
return en;
|
return en;
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -167,7 +167,7 @@ public class DefaultBreakpointRecorder implements ManagedBreakpointRecorder {
|
|||||||
traceBpt.setClearedSnap(snap - 1);
|
traceBpt.setClearedSnap(snap - 1);
|
||||||
}
|
}
|
||||||
breakpointManager.placeBreakpoint(path, snap, range,
|
breakpointManager.placeBreakpoint(path, snap, range,
|
||||||
traceBpt.getThreads(), traceBpt.getKinds(), traceBpt.isEnabled(),
|
traceBpt.getThreads(), traceBpt.getKinds(), traceBpt.isEnabled(snap),
|
||||||
traceBpt.getComment());
|
traceBpt.getComment());
|
||||||
}
|
}
|
||||||
catch (DuplicateNameException e) {
|
catch (DuplicateNameException e) {
|
||||||
|
|||||||
+1
-1
@@ -173,7 +173,7 @@ public class DebuggerBreakpointsPluginScreenShots extends GhidraScreenShotGenera
|
|||||||
assertEquals(3, allBreakpoints.size());
|
assertEquals(3, allBreakpoints.size());
|
||||||
});
|
});
|
||||||
waitForPass(() -> {
|
waitForPass(() -> {
|
||||||
assertFalse(bpt.isEnabled());
|
assertFalse(bpt.isEnabled(0));
|
||||||
});
|
});
|
||||||
/**
|
/**
|
||||||
* TODO: Might be necessary to debounce and wait for service callbacks to settle. Sometimes,
|
* TODO: Might be necessary to debounce and wait for service callbacks to settle. Sometimes,
|
||||||
|
|||||||
+2
-2
@@ -31,9 +31,9 @@ import ghidra.async.AsyncTestUtils;
|
|||||||
import ghidra.test.ToyProgramBuilder;
|
import ghidra.test.ToyProgramBuilder;
|
||||||
import ghidra.trace.database.ToyDBTraceBuilder;
|
import ghidra.trace.database.ToyDBTraceBuilder;
|
||||||
import ghidra.trace.database.memory.DBTraceMemoryManager;
|
import ghidra.trace.database.memory.DBTraceMemoryManager;
|
||||||
import ghidra.trace.database.thread.DBTraceThread;
|
|
||||||
import ghidra.trace.database.time.DBTraceTimeManager;
|
import ghidra.trace.database.time.DBTraceTimeManager;
|
||||||
import ghidra.trace.model.memory.TraceMemoryFlag;
|
import ghidra.trace.model.memory.TraceMemoryFlag;
|
||||||
|
import ghidra.trace.model.thread.TraceThread;
|
||||||
import ghidra.trace.model.time.schedule.TraceSchedule;
|
import ghidra.trace.model.time.schedule.TraceSchedule;
|
||||||
import ghidra.util.Swing;
|
import ghidra.util.Swing;
|
||||||
import ghidra.util.database.UndoableTransaction;
|
import ghidra.util.database.UndoableTransaction;
|
||||||
@@ -105,7 +105,7 @@ public class DebuggerTraceViewDiffPluginScreenShots extends GhidraScreenShotGene
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCaptureDebuggerTimeSelectionDialog() throws Throwable {
|
public void testCaptureDebuggerTimeSelectionDialog() throws Throwable {
|
||||||
DBTraceThread thread;
|
TraceThread thread;
|
||||||
try (UndoableTransaction tid = tb.startTransaction()) {
|
try (UndoableTransaction tid = tb.startTransaction()) {
|
||||||
DBTraceTimeManager tm = tb.trace.getTimeManager();
|
DBTraceTimeManager tm = tb.trace.getTimeManager();
|
||||||
thread = tb.getOrAddThread("main", 0);
|
thread = tb.getOrAddThread("main", 0);
|
||||||
|
|||||||
+1
-2
@@ -30,7 +30,6 @@ import ghidra.framework.model.DomainFolder;
|
|||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.test.ToyProgramBuilder;
|
import ghidra.test.ToyProgramBuilder;
|
||||||
import ghidra.trace.database.ToyDBTraceBuilder;
|
import ghidra.trace.database.ToyDBTraceBuilder;
|
||||||
import ghidra.trace.database.thread.DBTraceThread;
|
|
||||||
import ghidra.trace.model.breakpoint.TraceBreakpointKind;
|
import ghidra.trace.model.breakpoint.TraceBreakpointKind;
|
||||||
import ghidra.trace.model.memory.TraceMemoryFlag;
|
import ghidra.trace.model.memory.TraceMemoryFlag;
|
||||||
import ghidra.trace.model.thread.TraceThread;
|
import ghidra.trace.model.thread.TraceThread;
|
||||||
@@ -80,7 +79,7 @@ public class DebuggerMemviewPluginScreenShots extends GhidraScreenShotGenerator
|
|||||||
|
|
||||||
private void populateTraceAndPrograms() throws Exception {
|
private void populateTraceAndPrograms() throws Exception {
|
||||||
DomainFolder root = tool.getProject().getProjectData().getRootFolder();
|
DomainFolder root = tool.getProject().getProjectData().getRootFolder();
|
||||||
DBTraceThread thread1;
|
TraceThread thread1;
|
||||||
try (UndoableTransaction tid = tb.startTransaction()) {
|
try (UndoableTransaction tid = tb.startTransaction()) {
|
||||||
thread1 = tb.trace.getThreadManager().addThread("[0]", Range.openClosed(0L, 40L));
|
thread1 = tb.trace.getThreadManager().addThread("[0]", Range.openClosed(0L, 40L));
|
||||||
tb.trace.getThreadManager().addThread("[1]", Range.openClosed(3L, 50L));
|
tb.trace.getThreadManager().addThread("[1]", Range.openClosed(3L, 50L));
|
||||||
|
|||||||
+14
-4
@@ -43,8 +43,7 @@ import docking.widgets.tree.GTreeNode;
|
|||||||
import generic.Unique;
|
import generic.Unique;
|
||||||
import ghidra.app.plugin.core.debug.gui.action.*;
|
import ghidra.app.plugin.core.debug.gui.action.*;
|
||||||
import ghidra.app.plugin.core.debug.mapping.*;
|
import ghidra.app.plugin.core.debug.mapping.*;
|
||||||
import ghidra.app.plugin.core.debug.service.model.DebuggerModelServiceInternal;
|
import ghidra.app.plugin.core.debug.service.model.*;
|
||||||
import ghidra.app.plugin.core.debug.service.model.DebuggerModelServiceProxyPlugin;
|
|
||||||
import ghidra.app.plugin.core.debug.service.tracemgr.DebuggerTraceManagerServicePlugin;
|
import ghidra.app.plugin.core.debug.service.tracemgr.DebuggerTraceManagerServicePlugin;
|
||||||
import ghidra.app.services.*;
|
import ghidra.app.services.*;
|
||||||
import ghidra.app.util.viewer.listingpanel.ListingPanel;
|
import ghidra.app.util.viewer.listingpanel.ListingPanel;
|
||||||
@@ -521,6 +520,8 @@ public abstract class AbstractGhidraHeadedDebuggerGUITest
|
|||||||
|
|
||||||
@After
|
@After
|
||||||
public void tearDown() {
|
public void tearDown() {
|
||||||
|
runSwing(() -> traceManager.setSaveTracesByDefault(false));
|
||||||
|
|
||||||
if (tb != null) {
|
if (tb != null) {
|
||||||
if (traceManager != null && traceManager.getOpenTraces().contains(tb.trace)) {
|
if (traceManager != null && traceManager.getOpenTraces().contains(tb.trace)) {
|
||||||
traceManager.closeTrace(tb.trace);
|
traceManager.closeTrace(tb.trace);
|
||||||
@@ -531,8 +532,6 @@ public abstract class AbstractGhidraHeadedDebuggerGUITest
|
|||||||
if (mb != null) {
|
if (mb != null) {
|
||||||
if (mb.testModel != null) {
|
if (mb.testModel != null) {
|
||||||
modelService.removeModel(mb.testModel);
|
modelService.removeModel(mb.testModel);
|
||||||
|
|
||||||
runSwing(() -> traceManager.setSaveTracesByDefault(false));
|
|
||||||
for (TraceRecorder recorder : modelService.getTraceRecorders()) {
|
for (TraceRecorder recorder : modelService.getTraceRecorders()) {
|
||||||
recorder.stopRecording();
|
recorder.stopRecording();
|
||||||
}
|
}
|
||||||
@@ -588,6 +587,17 @@ public abstract class AbstractGhidraHeadedDebuggerGUITest
|
|||||||
tb = new ToyDBTraceBuilder(trace);
|
tb = new ToyDBTraceBuilder(trace);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected DebuggerTargetTraceMapper createTargetTraceMapper(TargetObject target)
|
||||||
|
throws Exception {
|
||||||
|
return new TestDebuggerTargetTraceMapper(target) {
|
||||||
|
@Override
|
||||||
|
public TraceRecorder startRecording(DebuggerModelServicePlugin service, Trace trace) {
|
||||||
|
useTrace(trace);
|
||||||
|
return super.startRecording(service, trace);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
protected void createAndOpenTrace(String langID) throws IOException {
|
protected void createAndOpenTrace(String langID) throws IOException {
|
||||||
createTrace(langID);
|
createTrace(langID);
|
||||||
traceManager.openTrace(tb.trace);
|
traceManager.openTrace(tb.trace);
|
||||||
|
|||||||
+1
-1
@@ -137,7 +137,7 @@ public class DebuggerBreakpointMarkerPluginTest extends AbstractGhidraHeadedDebu
|
|||||||
createTestModel();
|
createTestModel();
|
||||||
mb.createTestProcessesAndThreads();
|
mb.createTestProcessesAndThreads();
|
||||||
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
|
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
|
||||||
new TestDebuggerTargetTraceMapper(mb.testProcess1));
|
createTargetTraceMapper(mb.testProcess1));
|
||||||
Trace trace = recorder.getTrace();
|
Trace trace = recorder.getTrace();
|
||||||
createProgramFromTrace(trace);
|
createProgramFromTrace(trace);
|
||||||
intoProject(trace);
|
intoProject(trace);
|
||||||
|
|||||||
+98
@@ -0,0 +1,98 @@
|
|||||||
|
/* ###
|
||||||
|
* 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.plugin.core.debug.gui.breakpoint;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import ghidra.dbg.target.schema.SchemaContext;
|
||||||
|
import ghidra.dbg.target.schema.TargetObjectSchema.SchemaName;
|
||||||
|
import ghidra.dbg.target.schema.XmlSchemaContext;
|
||||||
|
import ghidra.trace.model.Trace;
|
||||||
|
import ghidra.util.database.UndoableTransaction;
|
||||||
|
|
||||||
|
public class DebuggerBreakpointsProviderObjectTest extends DebuggerBreakpointsProviderTest {
|
||||||
|
|
||||||
|
protected SchemaContext ctx;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void createTrace(String langID) throws IOException {
|
||||||
|
super.createTrace(langID);
|
||||||
|
try {
|
||||||
|
activateObjectsMode();
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
throw new AssertionError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void useTrace(Trace trace) {
|
||||||
|
super.useTrace(trace);
|
||||||
|
try {
|
||||||
|
activateObjectsMode();
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
throw new AssertionError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void activateObjectsMode() throws Exception {
|
||||||
|
// NOTE the use of index='...' allowing object-based managers to ID unique path
|
||||||
|
// TODO: I guess this'll burn down if the naming scheme changes....
|
||||||
|
int index = tb.trace.getName().startsWith("[3]") ? 3 : 1;
|
||||||
|
ctx = XmlSchemaContext.deserialize("" + //
|
||||||
|
"<context>" + //
|
||||||
|
" <schema name='Session' elementResync='NEVER' attributeResync='ONCE'>" + //
|
||||||
|
" <attribute name='Processes' schema='ProcessContainer' />" + //
|
||||||
|
" </schema>" + //
|
||||||
|
" <schema name='ProcessContainer' canonical='yes' elementResync='NEVER' " + //
|
||||||
|
" attributeResync='ONCE'>" + //
|
||||||
|
" <element index='" + index + "' schema='Process' />" + // <---- NOTE HERE
|
||||||
|
" </schema>" + //
|
||||||
|
" <schema name='Process' elementResync='NEVER' attributeResync='ONCE'>" + //
|
||||||
|
" <attribute name='Threads' schema='ThreadContainer' />" + //
|
||||||
|
" <attribute name='Memory' schema='RegionContainer' />" + //
|
||||||
|
" <attribute name='Breakpoints' schema='BreakpointContainer' />" + //
|
||||||
|
" </schema>" + //
|
||||||
|
" <schema name='ThreadContainer' canonical='yes' elementResync='NEVER' " + //
|
||||||
|
" attributeResync='ONCE'>" + //
|
||||||
|
" <element schema='Thread' />" + //
|
||||||
|
" </schema>" + //
|
||||||
|
" <schema name='Thread' elementResync='NEVER' attributeResync='NEVER'>" + //
|
||||||
|
" <interface name='Thread' />" + //
|
||||||
|
" </schema>" + //
|
||||||
|
" <schema name='RegionContainer' canonical='yes' elementResync='NEVER' " + //
|
||||||
|
" attributeResync='ONCE'>" + //
|
||||||
|
" <element schema='Region' />" + //
|
||||||
|
" </schema>" + //
|
||||||
|
" <schema name='Region' elementResync='NEVER' attributeResync='NEVER'>" + //
|
||||||
|
" <interface name='MemoryRegion' />" + //
|
||||||
|
" </schema>" + //
|
||||||
|
" <schema name='BreakpointContainer' canonical='yes' elementResync='NEVER' " + //
|
||||||
|
" attributeResync='ONCE'>" + //
|
||||||
|
" <element schema='Breakpoint' />" + //
|
||||||
|
" </schema>" + //
|
||||||
|
" <schema name='Breakpoint' elementResync='NEVER' attributeResync='NEVER'>" + //
|
||||||
|
" <interface name='BreakpointSpec' />" + //
|
||||||
|
" <interface name='BreakpointLocation' />" + //
|
||||||
|
" </schema>" + //
|
||||||
|
"</context>");
|
||||||
|
|
||||||
|
try (UndoableTransaction tid = tb.startTransaction()) {
|
||||||
|
tb.trace.getObjectManager().createRootObject(ctx.getSchema(new SchemaName("Session")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+9
-6
@@ -121,7 +121,7 @@ public class DebuggerBreakpointsProviderTest extends AbstractGhidraHeadedDebugge
|
|||||||
createTestModel();
|
createTestModel();
|
||||||
mb.createTestProcessesAndThreads();
|
mb.createTestProcessesAndThreads();
|
||||||
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
|
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
|
||||||
new TestDebuggerTargetTraceMapper(mb.testProcess1));
|
createTargetTraceMapper(mb.testProcess1));
|
||||||
Trace trace = recorder.getTrace();
|
Trace trace = recorder.getTrace();
|
||||||
|
|
||||||
addLiveMemoryAndBreakpoint(mb.testProcess1, recorder);
|
addLiveMemoryAndBreakpoint(mb.testProcess1, recorder);
|
||||||
@@ -145,7 +145,7 @@ public class DebuggerBreakpointsProviderTest extends AbstractGhidraHeadedDebugge
|
|||||||
createTestModel();
|
createTestModel();
|
||||||
mb.createTestProcessesAndThreads();
|
mb.createTestProcessesAndThreads();
|
||||||
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
|
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
|
||||||
new TestDebuggerTargetTraceMapper(mb.testProcess1));
|
createTargetTraceMapper(mb.testProcess1));
|
||||||
Trace trace = recorder.getTrace();
|
Trace trace = recorder.getTrace();
|
||||||
|
|
||||||
addLiveMemoryAndBreakpoint(mb.testProcess1, recorder);
|
addLiveMemoryAndBreakpoint(mb.testProcess1, recorder);
|
||||||
@@ -210,7 +210,7 @@ public class DebuggerBreakpointsProviderTest extends AbstractGhidraHeadedDebugge
|
|||||||
createTestModel();
|
createTestModel();
|
||||||
mb.createTestProcessesAndThreads();
|
mb.createTestProcessesAndThreads();
|
||||||
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
|
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
|
||||||
new TestDebuggerTargetTraceMapper(mb.testProcess1));
|
createTargetTraceMapper(mb.testProcess1));
|
||||||
Trace trace = recorder.getTrace();
|
Trace trace = recorder.getTrace();
|
||||||
createProgramFromTrace(trace);
|
createProgramFromTrace(trace);
|
||||||
intoProject(trace);
|
intoProject(trace);
|
||||||
@@ -471,7 +471,7 @@ public class DebuggerBreakpointsProviderTest extends AbstractGhidraHeadedDebugge
|
|||||||
createTestModel();
|
createTestModel();
|
||||||
mb.createTestProcessesAndThreads();
|
mb.createTestProcessesAndThreads();
|
||||||
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
|
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
|
||||||
new TestDebuggerTargetTraceMapper(mb.testProcess1));
|
createTargetTraceMapper(mb.testProcess1));
|
||||||
Trace trace = recorder.getTrace();
|
Trace trace = recorder.getTrace();
|
||||||
createProgramFromTrace(trace);
|
createProgramFromTrace(trace);
|
||||||
intoProject(trace);
|
intoProject(trace);
|
||||||
@@ -512,12 +512,15 @@ public class DebuggerBreakpointsProviderTest extends AbstractGhidraHeadedDebugge
|
|||||||
public void testActionFilters() throws Exception {
|
public void testActionFilters() throws Exception {
|
||||||
createTestModel();
|
createTestModel();
|
||||||
mb.createTestProcessesAndThreads();
|
mb.createTestProcessesAndThreads();
|
||||||
|
|
||||||
TraceRecorder recorder1 = modelService.recordTarget(mb.testProcess1,
|
TraceRecorder recorder1 = modelService.recordTarget(mb.testProcess1,
|
||||||
new TestDebuggerTargetTraceMapper(mb.testProcess1));
|
createTargetTraceMapper(mb.testProcess1));
|
||||||
Trace trace1 = recorder1.getTrace();
|
Trace trace1 = recorder1.getTrace();
|
||||||
|
|
||||||
TraceRecorder recorder3 = modelService.recordTarget(mb.testProcess3,
|
TraceRecorder recorder3 = modelService.recordTarget(mb.testProcess3,
|
||||||
new TestDebuggerTargetTraceMapper(mb.testProcess3));
|
createTargetTraceMapper(mb.testProcess3));
|
||||||
Trace trace3 = recorder3.getTrace();
|
Trace trace3 = recorder3.getTrace();
|
||||||
|
|
||||||
createProgramFromTrace(trace1);
|
createProgramFromTrace(trace1);
|
||||||
intoProject(trace1);
|
intoProject(trace1);
|
||||||
intoProject(trace3);
|
intoProject(trace3);
|
||||||
|
|||||||
+1
-4
@@ -37,7 +37,6 @@ import ghidra.app.plugin.core.debug.gui.listing.DebuggerListingPlugin;
|
|||||||
import ghidra.app.plugin.core.debug.gui.listing.DebuggerListingProvider;
|
import ghidra.app.plugin.core.debug.gui.listing.DebuggerListingProvider;
|
||||||
import ghidra.app.plugin.core.debug.service.modules.DebuggerStaticMappingServicePlugin;
|
import ghidra.app.plugin.core.debug.service.modules.DebuggerStaticMappingServicePlugin;
|
||||||
import ghidra.app.services.DebuggerStaticMappingService;
|
import ghidra.app.services.DebuggerStaticMappingService;
|
||||||
import ghidra.app.services.TraceRecorder;
|
|
||||||
import ghidra.dbg.DebuggerModelListener;
|
import ghidra.dbg.DebuggerModelListener;
|
||||||
import ghidra.dbg.target.TargetObject;
|
import ghidra.dbg.target.TargetObject;
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
@@ -457,9 +456,7 @@ public class DebuggerCopyActionsPluginTest extends AbstractGhidraHeadedDebuggerG
|
|||||||
mb.testModel.addModelListener(listener);
|
mb.testModel.addModelListener(listener);
|
||||||
|
|
||||||
mb.createTestProcessesAndThreads();
|
mb.createTestProcessesAndThreads();
|
||||||
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
|
modelService.recordTarget(mb.testProcess1, createTargetTraceMapper(mb.testProcess1));
|
||||||
new TestDebuggerTargetTraceMapper(mb.testProcess1));
|
|
||||||
useTrace(recorder.getTrace());
|
|
||||||
mb.testProcess1.memory.addRegion(".text", mb.rng(0x55550000, 0x5555ffff), "rx");
|
mb.testProcess1.memory.addRegion(".text", mb.rng(0x55550000, 0x5555ffff), "rx");
|
||||||
mb.testProcess1.memory.setMemory(mb.addr(0x55550000), mb.arr(1, 2, 3, 4, 5, 6, 7, 8));
|
mb.testProcess1.memory.setMemory(mb.addr(0x55550000), mb.arr(1, 2, 3, 4, 5, 6, 7, 8));
|
||||||
waitForPass(() -> {
|
waitForPass(() -> {
|
||||||
|
|||||||
+7
-7
@@ -53,11 +53,11 @@ import ghidra.program.util.ProgramLocation;
|
|||||||
import ghidra.program.util.ProgramSelection;
|
import ghidra.program.util.ProgramSelection;
|
||||||
import ghidra.trace.database.ToyDBTraceBuilder;
|
import ghidra.trace.database.ToyDBTraceBuilder;
|
||||||
import ghidra.trace.database.memory.DBTraceMemoryManager;
|
import ghidra.trace.database.memory.DBTraceMemoryManager;
|
||||||
import ghidra.trace.database.stack.DBTraceStack;
|
|
||||||
import ghidra.trace.database.stack.DBTraceStackManager;
|
import ghidra.trace.database.stack.DBTraceStackManager;
|
||||||
import ghidra.trace.model.*;
|
import ghidra.trace.model.*;
|
||||||
import ghidra.trace.model.memory.*;
|
import ghidra.trace.model.memory.*;
|
||||||
import ghidra.trace.model.modules.TraceModule;
|
import ghidra.trace.model.modules.TraceModule;
|
||||||
|
import ghidra.trace.model.stack.TraceStack;
|
||||||
import ghidra.trace.model.thread.TraceThread;
|
import ghidra.trace.model.thread.TraceThread;
|
||||||
import ghidra.trace.model.time.TraceSnapshot;
|
import ghidra.trace.model.time.TraceSnapshot;
|
||||||
import ghidra.util.database.UndoableTransaction;
|
import ghidra.util.database.UndoableTransaction;
|
||||||
@@ -632,7 +632,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
|||||||
mb.createTestProcessesAndThreads();
|
mb.createTestProcessesAndThreads();
|
||||||
|
|
||||||
TraceRecorder recorder = modelService.recordTargetAndActivateTrace(mb.testProcess1,
|
TraceRecorder recorder = modelService.recordTargetAndActivateTrace(mb.testProcess1,
|
||||||
new TestDebuggerTargetTraceMapper(mb.testProcess1));
|
createTargetTraceMapper(mb.testProcess1));
|
||||||
Trace trace = recorder.getTrace();
|
Trace trace = recorder.getTrace();
|
||||||
|
|
||||||
mb.testProcess1.addRegion("exe:.text", mb.rng(0x55550000, 0x5555ffff), "rx");
|
mb.testProcess1.addRegion("exe:.text", mb.rng(0x55550000, 0x5555ffff), "rx");
|
||||||
@@ -960,7 +960,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
|||||||
mb.createTestProcessesAndThreads();
|
mb.createTestProcessesAndThreads();
|
||||||
|
|
||||||
TraceRecorder recorder = modelService.recordTargetAndActivateTrace(mb.testProcess1,
|
TraceRecorder recorder = modelService.recordTargetAndActivateTrace(mb.testProcess1,
|
||||||
new TestDebuggerTargetTraceMapper(mb.testProcess1));
|
createTargetTraceMapper(mb.testProcess1));
|
||||||
Trace trace = recorder.getTrace();
|
Trace trace = recorder.getTrace();
|
||||||
|
|
||||||
mb.testProcess1.addRegion("exe:.text", mb.rng(0x55550000, 0x555500ff), "rx");
|
mb.testProcess1.addRegion("exe:.text", mb.rng(0x55550000, 0x555500ff), "rx");
|
||||||
@@ -1256,7 +1256,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
|||||||
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
||||||
thread = tb.getOrAddThread("Thread 1", 0);
|
thread = tb.getOrAddThread("Thread 1", 0);
|
||||||
DBTraceStackManager sm = tb.trace.getStackManager();
|
DBTraceStackManager sm = tb.trace.getStackManager();
|
||||||
DBTraceStack stack = sm.getStack(thread, 0, true);
|
TraceStack stack = sm.getStack(thread, 0, true);
|
||||||
stack.getFrame(0, true).setProgramCounter(tb.addr(0x00401234));
|
stack.getFrame(0, true).setProgramCounter(tb.addr(0x00401234));
|
||||||
stack.getFrame(1, true).setProgramCounter(tb.addr(0x00404321));
|
stack.getFrame(1, true).setProgramCounter(tb.addr(0x00404321));
|
||||||
}
|
}
|
||||||
@@ -1318,7 +1318,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
|||||||
regs.setValue(0, new RegisterValue(pc, new BigInteger("00401234", 16)));
|
regs.setValue(0, new RegisterValue(pc, new BigInteger("00401234", 16)));
|
||||||
|
|
||||||
DBTraceStackManager sm = tb.trace.getStackManager();
|
DBTraceStackManager sm = tb.trace.getStackManager();
|
||||||
DBTraceStack stack = sm.getStack(thread, 0, true);
|
TraceStack stack = sm.getStack(thread, 0, true);
|
||||||
stack.getFrame(0, true);
|
stack.getFrame(0, true);
|
||||||
}
|
}
|
||||||
waitForDomainObject(tb.trace);
|
waitForDomainObject(tb.trace);
|
||||||
@@ -1348,7 +1348,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
|||||||
mm.addRegion("exe:.text", Range.atLeast(0L), tb.range(0x00400000, 0x0040ffff),
|
mm.addRegion("exe:.text", Range.atLeast(0L), tb.range(0x00400000, 0x0040ffff),
|
||||||
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
||||||
thread = tb.getOrAddThread("Thread 1", 0);
|
thread = tb.getOrAddThread("Thread 1", 0);
|
||||||
DBTraceStack stack = sm.getStack(thread, 0, true);
|
TraceStack stack = sm.getStack(thread, 0, true);
|
||||||
stack.getFrame(0, true).setProgramCounter(tb.addr(0x00401234));
|
stack.getFrame(0, true).setProgramCounter(tb.addr(0x00401234));
|
||||||
}
|
}
|
||||||
waitForDomainObject(tb.trace);
|
waitForDomainObject(tb.trace);
|
||||||
@@ -1358,7 +1358,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
|||||||
assertEquals(tb.addr(0x00401234), listingProvider.getLocation().getAddress());
|
assertEquals(tb.addr(0x00401234), listingProvider.getLocation().getAddress());
|
||||||
|
|
||||||
try (UndoableTransaction tid = tb.startTransaction()) {
|
try (UndoableTransaction tid = tb.startTransaction()) {
|
||||||
DBTraceStack stack = sm.getStack(thread, 0, true);
|
TraceStack stack = sm.getStack(thread, 0, true);
|
||||||
stack.getFrame(0, true).setProgramCounter(tb.addr(0x00404321));
|
stack.getFrame(0, true).setProgramCounter(tb.addr(0x00404321));
|
||||||
}
|
}
|
||||||
waitForDomainObject(tb.trace);
|
waitForDomainObject(tb.trace);
|
||||||
|
|||||||
+11
-11
@@ -15,7 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.app.plugin.core.debug.gui.memory;
|
package ghidra.app.plugin.core.debug.gui.memory;
|
||||||
|
|
||||||
import static ghidra.lifecycle.Unfinished.*;
|
import static ghidra.lifecycle.Unfinished.TODO;
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
@@ -55,11 +55,11 @@ import ghidra.program.util.ProgramLocation;
|
|||||||
import ghidra.program.util.ProgramSelection;
|
import ghidra.program.util.ProgramSelection;
|
||||||
import ghidra.trace.database.ToyDBTraceBuilder;
|
import ghidra.trace.database.ToyDBTraceBuilder;
|
||||||
import ghidra.trace.database.memory.DBTraceMemoryManager;
|
import ghidra.trace.database.memory.DBTraceMemoryManager;
|
||||||
import ghidra.trace.database.stack.DBTraceStack;
|
|
||||||
import ghidra.trace.database.stack.DBTraceStackManager;
|
import ghidra.trace.database.stack.DBTraceStackManager;
|
||||||
import ghidra.trace.model.Trace;
|
import ghidra.trace.model.Trace;
|
||||||
import ghidra.trace.model.memory.*;
|
import ghidra.trace.model.memory.*;
|
||||||
import ghidra.trace.model.modules.TraceModule;
|
import ghidra.trace.model.modules.TraceModule;
|
||||||
|
import ghidra.trace.model.stack.TraceStack;
|
||||||
import ghidra.trace.model.thread.TraceThread;
|
import ghidra.trace.model.thread.TraceThread;
|
||||||
import ghidra.trace.model.time.TraceSnapshot;
|
import ghidra.trace.model.time.TraceSnapshot;
|
||||||
import ghidra.util.database.UndoableTransaction;
|
import ghidra.util.database.UndoableTransaction;
|
||||||
@@ -468,7 +468,7 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
|
|||||||
mb.createTestProcessesAndThreads();
|
mb.createTestProcessesAndThreads();
|
||||||
|
|
||||||
TraceRecorder recorder = modelService.recordTargetAndActivateTrace(mb.testProcess1,
|
TraceRecorder recorder = modelService.recordTargetAndActivateTrace(mb.testProcess1,
|
||||||
new TestDebuggerTargetTraceMapper(mb.testProcess1));
|
createTargetTraceMapper(mb.testProcess1));
|
||||||
Trace trace = recorder.getTrace();
|
Trace trace = recorder.getTrace();
|
||||||
|
|
||||||
mb.testProcess1.addRegion("exe:.text", mb.rng(0x55550000, 0x5555ffff), "rx");
|
mb.testProcess1.addRegion("exe:.text", mb.rng(0x55550000, 0x5555ffff), "rx");
|
||||||
@@ -762,7 +762,7 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
|
|||||||
mb.createTestProcessesAndThreads();
|
mb.createTestProcessesAndThreads();
|
||||||
|
|
||||||
TraceRecorder recorder = modelService.recordTargetAndActivateTrace(mb.testProcess1,
|
TraceRecorder recorder = modelService.recordTargetAndActivateTrace(mb.testProcess1,
|
||||||
new TestDebuggerTargetTraceMapper(mb.testProcess1));
|
createTargetTraceMapper(mb.testProcess1));
|
||||||
Trace trace = recorder.getTrace();
|
Trace trace = recorder.getTrace();
|
||||||
|
|
||||||
mb.testProcess1.addRegion("exe:.text", mb.rng(0x55550000, 0x555500ff), "rx");
|
mb.testProcess1.addRegion("exe:.text", mb.rng(0x55550000, 0x555500ff), "rx");
|
||||||
@@ -957,7 +957,7 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
|
|||||||
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
||||||
thread = tb.getOrAddThread("Thread 1", 0);
|
thread = tb.getOrAddThread("Thread 1", 0);
|
||||||
DBTraceStackManager sm = tb.trace.getStackManager();
|
DBTraceStackManager sm = tb.trace.getStackManager();
|
||||||
DBTraceStack stack = sm.getStack(thread, 0, true);
|
TraceStack stack = sm.getStack(thread, 0, true);
|
||||||
stack.getFrame(0, true).setProgramCounter(tb.addr(0x00401234));
|
stack.getFrame(0, true).setProgramCounter(tb.addr(0x00401234));
|
||||||
stack.getFrame(1, true).setProgramCounter(tb.addr(0x00404321));
|
stack.getFrame(1, true).setProgramCounter(tb.addr(0x00404321));
|
||||||
}
|
}
|
||||||
@@ -1019,7 +1019,7 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
|
|||||||
regs.setValue(0, new RegisterValue(pc, new BigInteger("00401234", 16)));
|
regs.setValue(0, new RegisterValue(pc, new BigInteger("00401234", 16)));
|
||||||
|
|
||||||
DBTraceStackManager sm = tb.trace.getStackManager();
|
DBTraceStackManager sm = tb.trace.getStackManager();
|
||||||
DBTraceStack stack = sm.getStack(thread, 0, true);
|
TraceStack stack = sm.getStack(thread, 0, true);
|
||||||
stack.getFrame(0, true);
|
stack.getFrame(0, true);
|
||||||
}
|
}
|
||||||
waitForDomainObject(tb.trace);
|
waitForDomainObject(tb.trace);
|
||||||
@@ -1049,7 +1049,7 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
|
|||||||
mm.addRegion("exe:.text", Range.atLeast(0L), tb.range(0x00400000, 0x0040ffff),
|
mm.addRegion("exe:.text", Range.atLeast(0L), tb.range(0x00400000, 0x0040ffff),
|
||||||
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
||||||
thread = tb.getOrAddThread("Thread 1", 0);
|
thread = tb.getOrAddThread("Thread 1", 0);
|
||||||
DBTraceStack stack = sm.getStack(thread, 0, true);
|
TraceStack stack = sm.getStack(thread, 0, true);
|
||||||
stack.getFrame(0, true).setProgramCounter(tb.addr(0x00401234));
|
stack.getFrame(0, true).setProgramCounter(tb.addr(0x00401234));
|
||||||
}
|
}
|
||||||
waitForDomainObject(tb.trace);
|
waitForDomainObject(tb.trace);
|
||||||
@@ -1059,7 +1059,7 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
|
|||||||
assertEquals(tb.addr(0x00401234), memBytesProvider.getLocation().getAddress());
|
assertEquals(tb.addr(0x00401234), memBytesProvider.getLocation().getAddress());
|
||||||
|
|
||||||
try (UndoableTransaction tid = tb.startTransaction()) {
|
try (UndoableTransaction tid = tb.startTransaction()) {
|
||||||
DBTraceStack stack = sm.getStack(thread, 0, true);
|
TraceStack stack = sm.getStack(thread, 0, true);
|
||||||
stack.getFrame(0, true).setProgramCounter(tb.addr(0x00404321));
|
stack.getFrame(0, true).setProgramCounter(tb.addr(0x00404321));
|
||||||
}
|
}
|
||||||
waitForDomainObject(tb.trace);
|
waitForDomainObject(tb.trace);
|
||||||
@@ -1074,7 +1074,7 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
|
|||||||
mb.createTestProcessesAndThreads();
|
mb.createTestProcessesAndThreads();
|
||||||
|
|
||||||
TraceRecorder recorder = modelService.recordTargetAndActivateTrace(mb.testProcess1,
|
TraceRecorder recorder = modelService.recordTargetAndActivateTrace(mb.testProcess1,
|
||||||
new TestDebuggerTargetTraceMapper(mb.testProcess1));
|
createTargetTraceMapper(mb.testProcess1));
|
||||||
Trace trace = recorder.getTrace();
|
Trace trace = recorder.getTrace();
|
||||||
|
|
||||||
mb.testProcess1.addRegion("exe:.text", mb.rng(0x55550000, 0x5555ffff), "rx");
|
mb.testProcess1.addRegion("exe:.text", mb.rng(0x55550000, 0x5555ffff), "rx");
|
||||||
@@ -1106,7 +1106,7 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
|
|||||||
mb.createTestProcessesAndThreads();
|
mb.createTestProcessesAndThreads();
|
||||||
|
|
||||||
TraceRecorder recorder = modelService.recordTargetAndActivateTrace(mb.testProcess1,
|
TraceRecorder recorder = modelService.recordTargetAndActivateTrace(mb.testProcess1,
|
||||||
new TestDebuggerTargetTraceMapper(mb.testProcess1));
|
createTargetTraceMapper(mb.testProcess1));
|
||||||
Trace trace = recorder.getTrace();
|
Trace trace = recorder.getTrace();
|
||||||
|
|
||||||
mb.testProcess1.addRegion("exe:.text", mb.rng(0x55550000, 0x5555ffff), "rx");
|
mb.testProcess1.addRegion("exe:.text", mb.rng(0x55550000, 0x5555ffff), "rx");
|
||||||
@@ -1150,7 +1150,7 @@ public class DebuggerMemoryBytesProviderTest extends AbstractGhidraHeadedDebugge
|
|||||||
mb.createTestProcessesAndThreads();
|
mb.createTestProcessesAndThreads();
|
||||||
|
|
||||||
TraceRecorder recorder = modelService.recordTargetAndActivateTrace(mb.testProcess1,
|
TraceRecorder recorder = modelService.recordTargetAndActivateTrace(mb.testProcess1,
|
||||||
new TestDebuggerTargetTraceMapper(mb.testProcess1));
|
createTargetTraceMapper(mb.testProcess1));
|
||||||
Trace trace = recorder.getTrace();
|
Trace trace = recorder.getTrace();
|
||||||
|
|
||||||
mb.testProcess1.addRegion("exe:.text", mb.rng(0x55550000, 0x5555ffff), "rx");
|
mb.testProcess1.addRegion("exe:.text", mb.rng(0x55550000, 0x5555ffff), "rx");
|
||||||
|
|||||||
+59
@@ -0,0 +1,59 @@
|
|||||||
|
/* ###
|
||||||
|
* 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.plugin.core.debug.gui.memory;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import ghidra.dbg.target.schema.SchemaContext;
|
||||||
|
import ghidra.dbg.target.schema.TargetObjectSchema.SchemaName;
|
||||||
|
import ghidra.dbg.target.schema.XmlSchemaContext;
|
||||||
|
import ghidra.util.database.UndoableTransaction;
|
||||||
|
|
||||||
|
public class DebuggerRegionsProviderObjectTest extends DebuggerRegionsProviderTest {
|
||||||
|
|
||||||
|
protected SchemaContext ctx;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void createTrace(String langID) throws IOException {
|
||||||
|
super.createTrace(langID);
|
||||||
|
try {
|
||||||
|
activateObjectsMode();
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
throw new AssertionError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void activateObjectsMode() throws Exception {
|
||||||
|
ctx = XmlSchemaContext.deserialize("" + //
|
||||||
|
"<context>" + //
|
||||||
|
" <schema name='Session' elementResync='NEVER' attributeResync='ONCE'>" + //
|
||||||
|
" <attribute name='Memory' schema='RegionContainer' />" + //
|
||||||
|
" </schema>" + //
|
||||||
|
" <schema name='RegionContainer' canonical='yes' elementResync='NEVER' " + //
|
||||||
|
" attributeResync='ONCE'>" + //
|
||||||
|
" <element schema='Region' />" + //
|
||||||
|
" </schema>" + //
|
||||||
|
" <schema name='Region' elementResync='NEVER' attributeResync='NEVER'>" + //
|
||||||
|
" <interface name='MemoryRegion' />" + //
|
||||||
|
" </schema>" + //
|
||||||
|
"</context>");
|
||||||
|
|
||||||
|
try (UndoableTransaction tid = tb.startTransaction()) {
|
||||||
|
tb.trace.getObjectManager().createRootObject(ctx.getSchema(new SchemaName("Session")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+19
-13
@@ -62,13 +62,13 @@ public class DebuggerRegionsProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
|||||||
protected void addRegions() throws Exception {
|
protected void addRegions() throws Exception {
|
||||||
TraceMemoryManager mm = tb.trace.getMemoryManager();
|
TraceMemoryManager mm = tb.trace.getMemoryManager();
|
||||||
try (UndoableTransaction tid = tb.startTransaction()) {
|
try (UndoableTransaction tid = tb.startTransaction()) {
|
||||||
regionExeText = mm.createRegion("Regions[/bin/echo 0x55550000]", 0,
|
regionExeText = mm.createRegion("Memory[/bin/echo 0x55550000]", 0,
|
||||||
tb.range(0x55550000, 0x555500ff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
tb.range(0x55550000, 0x555500ff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
||||||
regionExeData = mm.createRegion("Regions[/bin/echo 0x55750000]", 0,
|
regionExeData = mm.createRegion("Memory[/bin/echo 0x55750000]", 0,
|
||||||
tb.range(0x55750000, 0x5575007f), TraceMemoryFlag.READ, TraceMemoryFlag.WRITE);
|
tb.range(0x55750000, 0x5575007f), TraceMemoryFlag.READ, TraceMemoryFlag.WRITE);
|
||||||
regionLibText = mm.createRegion("Regions[/lib/libc.so 0x7f000000]", 0,
|
regionLibText = mm.createRegion("Memory[/lib/libc.so 0x7f000000]", 0,
|
||||||
tb.range(0x7f000000, 0x7f0003ff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
tb.range(0x7f000000, 0x7f0003ff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
||||||
regionLibData = mm.createRegion("Regions[/lib/libc.so 0x7f100000]", 0,
|
regionLibData = mm.createRegion("Memory[/lib/libc.so 0x7f100000]", 0,
|
||||||
tb.range(0x7f100000, 0x7f10003f), TraceMemoryFlag.READ, TraceMemoryFlag.WRITE);
|
tb.range(0x7f100000, 0x7f10003f), TraceMemoryFlag.READ, TraceMemoryFlag.WRITE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -104,7 +104,8 @@ public class DebuggerRegionsProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
|||||||
TraceMemoryRegion region;
|
TraceMemoryRegion region;
|
||||||
try (UndoableTransaction tid = tb.startTransaction()) {
|
try (UndoableTransaction tid = tb.startTransaction()) {
|
||||||
TraceMemoryManager mm = tb.trace.getMemoryManager();
|
TraceMemoryManager mm = tb.trace.getMemoryManager();
|
||||||
region = mm.addRegion("bin:.text", Range.atLeast(0L), tb.range(0x00400000, 0x0040ffff),
|
region = mm.addRegion("Memory[bin:.text]", Range.atLeast(0L),
|
||||||
|
tb.range(0x00400000, 0x0040ffff),
|
||||||
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,7 +115,7 @@ public class DebuggerRegionsProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
|||||||
|
|
||||||
RegionRow row = Unique.assertOne(provider.regionTableModel.getModelData());
|
RegionRow row = Unique.assertOne(provider.regionTableModel.getModelData());
|
||||||
assertEquals(region, row.getRegion());
|
assertEquals(region, row.getRegion());
|
||||||
assertEquals("bin:.text", row.getName());
|
assertEquals("Memory[bin:.text]", row.getName());
|
||||||
assertEquals(tb.addr(0x00400000), row.getMinAddress());
|
assertEquals(tb.addr(0x00400000), row.getMinAddress());
|
||||||
assertEquals(tb.addr(0x0040ffff), row.getMaxAddress());
|
assertEquals(tb.addr(0x0040ffff), row.getMaxAddress());
|
||||||
assertEquals(tb.range(0x00400000, 0x0040ffff), row.getRange());
|
assertEquals(tb.range(0x00400000, 0x0040ffff), row.getRange());
|
||||||
@@ -132,7 +133,8 @@ public class DebuggerRegionsProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
|||||||
TraceMemoryRegion region;
|
TraceMemoryRegion region;
|
||||||
try (UndoableTransaction tid = tb.startTransaction()) {
|
try (UndoableTransaction tid = tb.startTransaction()) {
|
||||||
TraceMemoryManager mm = tb.trace.getMemoryManager();
|
TraceMemoryManager mm = tb.trace.getMemoryManager();
|
||||||
region = mm.addRegion("bin:.text", Range.atLeast(0L), tb.range(0x00400000, 0x0040ffff),
|
region = mm.addRegion("Memory[bin:.text]", Range.atLeast(0L),
|
||||||
|
tb.range(0x00400000, 0x0040ffff),
|
||||||
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,7 +151,8 @@ public class DebuggerRegionsProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
|||||||
TraceMemoryRegion region;
|
TraceMemoryRegion region;
|
||||||
try (UndoableTransaction tid = tb.startTransaction()) {
|
try (UndoableTransaction tid = tb.startTransaction()) {
|
||||||
TraceMemoryManager mm = tb.trace.getMemoryManager();
|
TraceMemoryManager mm = tb.trace.getMemoryManager();
|
||||||
region = mm.addRegion("bin:.text", Range.atLeast(0L), tb.range(0x00400000, 0x0040ffff),
|
region = mm.addRegion("Memory[bin:.text]", Range.atLeast(0L),
|
||||||
|
tb.range(0x00400000, 0x0040ffff),
|
||||||
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,7 +177,7 @@ public class DebuggerRegionsProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
|||||||
|
|
||||||
try (UndoableTransaction tid = tb.startTransaction()) {
|
try (UndoableTransaction tid = tb.startTransaction()) {
|
||||||
TraceMemoryManager mm = tb.trace.getMemoryManager();
|
TraceMemoryManager mm = tb.trace.getMemoryManager();
|
||||||
mm.addRegion("bin:.text", Range.atLeast(0L), tb.range(0x00400000, 0x0040ffff),
|
mm.addRegion("Memory[bin:.text]", Range.atLeast(0L), tb.range(0x00400000, 0x0040ffff),
|
||||||
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -197,7 +200,7 @@ public class DebuggerRegionsProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
|||||||
|
|
||||||
try (UndoableTransaction tid = tb.startTransaction()) {
|
try (UndoableTransaction tid = tb.startTransaction()) {
|
||||||
TraceMemoryManager mm = tb.trace.getMemoryManager();
|
TraceMemoryManager mm = tb.trace.getMemoryManager();
|
||||||
mm.addRegion("bin:.text", Range.atLeast(0L), tb.range(0x00400000, 0x0040ffff),
|
mm.addRegion("Memory[bin:.text]", Range.atLeast(0L), tb.range(0x00400000, 0x0040ffff),
|
||||||
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
||||||
|
|
||||||
waitForDomainObject(tb.trace);
|
waitForDomainObject(tb.trace);
|
||||||
@@ -218,7 +221,8 @@ public class DebuggerRegionsProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
|||||||
TraceMemoryRegion region;
|
TraceMemoryRegion region;
|
||||||
try (UndoableTransaction tid = tb.startTransaction()) {
|
try (UndoableTransaction tid = tb.startTransaction()) {
|
||||||
TraceMemoryManager mm = tb.trace.getMemoryManager();
|
TraceMemoryManager mm = tb.trace.getMemoryManager();
|
||||||
region = mm.addRegion("bin:.text", Range.atLeast(0L), tb.range(0x00400000, 0x0040ffff),
|
region = mm.addRegion("Memory[bin:.text]", Range.atLeast(0L),
|
||||||
|
tb.range(0x00400000, 0x0040ffff),
|
||||||
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -333,7 +337,8 @@ public class DebuggerRegionsProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
|||||||
TraceMemoryRegion region;
|
TraceMemoryRegion region;
|
||||||
try (UndoableTransaction tid = tb.startTransaction()) {
|
try (UndoableTransaction tid = tb.startTransaction()) {
|
||||||
TraceMemoryManager mm = tb.trace.getMemoryManager();
|
TraceMemoryManager mm = tb.trace.getMemoryManager();
|
||||||
region = mm.addRegion("bin:.text", Range.atLeast(0L), tb.range(0x00400000, 0x0040ffff),
|
region = mm.addRegion("Memory[bin:.text]", Range.atLeast(0L),
|
||||||
|
tb.range(0x00400000, 0x0040ffff),
|
||||||
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -365,7 +370,8 @@ public class DebuggerRegionsProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
|||||||
TraceMemoryRegion region;
|
TraceMemoryRegion region;
|
||||||
try (UndoableTransaction tid = tb.startTransaction()) {
|
try (UndoableTransaction tid = tb.startTransaction()) {
|
||||||
TraceMemoryManager mm = tb.trace.getMemoryManager();
|
TraceMemoryManager mm = tb.trace.getMemoryManager();
|
||||||
region = mm.addRegion("bin:.text", Range.atLeast(0L), tb.range(0x00400000, 0x0040ffff),
|
region = mm.addRegion("Memory[bin:.text]", Range.atLeast(0L),
|
||||||
|
tb.range(0x00400000, 0x0040ffff),
|
||||||
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+95
@@ -0,0 +1,95 @@
|
|||||||
|
/* ###
|
||||||
|
* 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.plugin.core.debug.gui.modules;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import ghidra.dbg.target.schema.SchemaContext;
|
||||||
|
import ghidra.dbg.target.schema.TargetObjectSchema.SchemaName;
|
||||||
|
import ghidra.trace.model.Trace;
|
||||||
|
import ghidra.dbg.target.schema.XmlSchemaContext;
|
||||||
|
import ghidra.util.database.UndoableTransaction;
|
||||||
|
|
||||||
|
public class DebuggerModulesProviderObjectTest extends DebuggerModulesProviderTest {
|
||||||
|
|
||||||
|
protected SchemaContext ctx;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void createTrace(String langID) throws IOException {
|
||||||
|
super.createTrace(langID);
|
||||||
|
try {
|
||||||
|
activateObjectsMode();
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
throw new AssertionError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void useTrace(Trace trace) {
|
||||||
|
super.useTrace(trace);
|
||||||
|
try {
|
||||||
|
activateObjectsMode();
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
throw new AssertionError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void activateObjectsMode() throws Exception {
|
||||||
|
// NOTE the use of index='1' allowing object-based managers to ID unique path
|
||||||
|
ctx = XmlSchemaContext.deserialize("" + //
|
||||||
|
"<context>" + //
|
||||||
|
" <schema name='Session' elementResync='NEVER' attributeResync='ONCE'>" + //
|
||||||
|
" <attribute name='Processes' schema='ProcessContainer' />" + //
|
||||||
|
" </schema>" + //
|
||||||
|
" <schema name='ProcessContainer' canonical='yes' elementResync='NEVER' " + //
|
||||||
|
" attributeResync='ONCE'>" + //
|
||||||
|
" <element index='1' schema='Process' />" + // <---- NOTE HERE
|
||||||
|
" </schema>" + //
|
||||||
|
" <schema name='Process' elementResync='NEVER' attributeResync='ONCE'>" + //
|
||||||
|
" <attribute name='Modules' schema='ModuleContainer' />" + //
|
||||||
|
" <attribute name='Memory' schema='RegionContainer' />" + //
|
||||||
|
" </schema>" + //
|
||||||
|
" <schema name='RegionContainer' canonical='yes' elementResync='NEVER' " + //
|
||||||
|
" attributeResync='ONCE'>" + //
|
||||||
|
" <element schema='Region' />" + //
|
||||||
|
" </schema>" + //
|
||||||
|
" <schema name='Region' elementResync='NEVER' attributeResync='NEVER'>" + //
|
||||||
|
" <interface name='MemoryRegion' />" + //
|
||||||
|
" </schema>" + //
|
||||||
|
" <schema name='ModuleContainer' canonical='yes' elementResync='NEVER' " + //
|
||||||
|
" attributeResync='ONCE'>" + //
|
||||||
|
" <element schema='Module' />" + //
|
||||||
|
" </schema>" + //
|
||||||
|
" <schema name='Module' elementResync='NEVER' attributeResync='NEVER'>" + //
|
||||||
|
" <interface name='Module' />" + //
|
||||||
|
" <attribute name='Sections' schema='SectionContainer' />" + //
|
||||||
|
" </schema>" + //
|
||||||
|
" <schema name='SectionContainer' canonical='yes' elementResync='NEVER' " + //
|
||||||
|
" attributeResync='ONCE'>" + //
|
||||||
|
" <element schema='Section' />" + //
|
||||||
|
" </schema>" + //
|
||||||
|
" <schema name='Section' elementResync='NEVER' attributeResync='NEVER'>" + //
|
||||||
|
" <interface name='Section' />" + //
|
||||||
|
" </schema>" + //
|
||||||
|
"</context>");
|
||||||
|
|
||||||
|
try (UndoableTransaction tid = tb.startTransaction()) {
|
||||||
|
tb.trace.getObjectManager().createRootObject(ctx.getSchema(new SchemaName("Session")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+34
-22
@@ -100,7 +100,8 @@ public class DebuggerModulesProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
|||||||
else {
|
else {
|
||||||
throw new AssertionError();
|
throw new AssertionError();
|
||||||
}
|
}
|
||||||
manager.addRegion(module.getName() + ":" + section.getName(),
|
manager.addRegion(
|
||||||
|
"Processes[1].Memory[" + module.getName() + ":" + section.getName() + "]",
|
||||||
module.getLifespan(), section.getRange(), flags);
|
module.getLifespan(), section.getRange(), flags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -110,19 +111,19 @@ public class DebuggerModulesProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
|||||||
protected void addModules() throws Exception {
|
protected void addModules() throws Exception {
|
||||||
TraceModuleManager manager = tb.trace.getModuleManager();
|
TraceModuleManager manager = tb.trace.getModuleManager();
|
||||||
try (UndoableTransaction tid = tb.startTransaction()) {
|
try (UndoableTransaction tid = tb.startTransaction()) {
|
||||||
modExe = manager.addLoadedModule("first_proc", "first_proc",
|
modExe = manager.addLoadedModule("Processes[1].Modules[first_proc]", "first_proc",
|
||||||
tb.range(0x55550000, 0x5575007f), 0);
|
tb.range(0x55550000, 0x5575007f), 0);
|
||||||
secExeText =
|
secExeText = modExe.addSection("Processes[1].Modules[first_proc].Sections[.text]",
|
||||||
modExe.addSection("first_proc[.text]", ".text", tb.range(0x55550000, 0x555500ff));
|
".text", tb.range(0x55550000, 0x555500ff));
|
||||||
secExeData =
|
secExeData = modExe.addSection("Processes[1].Modules[first_proc].Sections[.data]",
|
||||||
modExe.addSection("first_proc[.data]", ".data", tb.range(0x55750000, 0x5575007f));
|
".data", tb.range(0x55750000, 0x5575007f));
|
||||||
|
|
||||||
modLib = manager.addLoadedModule("some_lib", "some_lib",
|
modLib = manager.addLoadedModule("Processes[1].Modules[some_lib]", "some_lib",
|
||||||
tb.range(0x7f000000, 0x7f10003f), 0);
|
tb.range(0x7f000000, 0x7f10003f), 0);
|
||||||
secLibText =
|
secLibText = modLib.addSection("Processes[1].Modules[some_lib].Sections[.text]",
|
||||||
modLib.addSection("some_lib[.text]", ".text", tb.range(0x7f000000, 0x7f0003ff));
|
".text", tb.range(0x7f000000, 0x7f0003ff));
|
||||||
secLibData =
|
secLibData = modLib.addSection("Processes[1].Modules[some_lib].Sections[.data]",
|
||||||
modLib.addSection("some_lib[.data]", ".data", tb.range(0x7f100000, 0x7f10003f));
|
".data", tb.range(0x7f100000, 0x7f10003f));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,8 +145,10 @@ public class DebuggerModulesProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void assertProviderPopulated() {
|
protected void assertProviderPopulated() {
|
||||||
List<ModuleRow> modulesDisplayed = modulesProvider.moduleTableModel.getModelData();
|
List<ModuleRow> modulesDisplayed =
|
||||||
// I should be able to assume this is sorted by base address
|
new ArrayList<>(modulesProvider.moduleTableModel.getModelData());
|
||||||
|
modulesDisplayed.sort(Comparator.comparing(r -> r.getBase()));
|
||||||
|
// I should be able to assume this is sorted by base address. It's the default sort column.
|
||||||
assertEquals(2, modulesDisplayed.size());
|
assertEquals(2, modulesDisplayed.size());
|
||||||
|
|
||||||
ModuleRow execRow = modulesDisplayed.get(0);
|
ModuleRow execRow = modulesDisplayed.get(0);
|
||||||
@@ -156,7 +159,9 @@ public class DebuggerModulesProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
|||||||
ModuleRow libRow = modulesDisplayed.get(1);
|
ModuleRow libRow = modulesDisplayed.get(1);
|
||||||
assertEquals(tb.addr(0x7f000000), libRow.getBase());
|
assertEquals(tb.addr(0x7f000000), libRow.getBase());
|
||||||
|
|
||||||
List<SectionRow> sectionsDisplayed = modulesProvider.sectionTableModel.getModelData();
|
List<SectionRow> sectionsDisplayed =
|
||||||
|
new ArrayList<>(modulesProvider.sectionTableModel.getModelData());
|
||||||
|
sectionsDisplayed.sort(Comparator.comparing(r -> r.getStart()));
|
||||||
assertEquals(4, sectionsDisplayed.size());
|
assertEquals(4, sectionsDisplayed.size());
|
||||||
|
|
||||||
SectionRow execTextRow = sectionsDisplayed.get(0);
|
SectionRow execTextRow = sectionsDisplayed.get(0);
|
||||||
@@ -261,13 +266,17 @@ public class DebuggerModulesProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
|||||||
}
|
}
|
||||||
waitForDomainObject(tb.trace);
|
waitForDomainObject(tb.trace);
|
||||||
|
|
||||||
List<ModuleRow> modulesDisplayed = modulesProvider.moduleTableModel.getModelData();
|
List<ModuleRow> modulesDisplayed =
|
||||||
|
new ArrayList<>(modulesProvider.moduleTableModel.getModelData());
|
||||||
|
modulesDisplayed.sort(Comparator.comparing(r -> r.getBase()));
|
||||||
assertEquals(1, modulesDisplayed.size());
|
assertEquals(1, modulesDisplayed.size());
|
||||||
|
|
||||||
ModuleRow libRow = modulesDisplayed.get(0);
|
ModuleRow libRow = modulesDisplayed.get(0);
|
||||||
assertEquals("some_lib", libRow.getName());
|
assertEquals("some_lib", libRow.getName());
|
||||||
|
|
||||||
List<SectionRow> sectionsDisplayed = modulesProvider.sectionTableModel.getModelData();
|
List<SectionRow> sectionsDisplayed =
|
||||||
|
new ArrayList<>(modulesProvider.sectionTableModel.getModelData());
|
||||||
|
sectionsDisplayed.sort(Comparator.comparing(r -> r.getStart()));
|
||||||
assertEquals(2, sectionsDisplayed.size());
|
assertEquals(2, sectionsDisplayed.size());
|
||||||
|
|
||||||
SectionRow libTextRow = sectionsDisplayed.get(0);
|
SectionRow libTextRow = sectionsDisplayed.get(0);
|
||||||
@@ -543,13 +552,15 @@ public class DebuggerModulesProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
|||||||
mb.createTestProcessesAndThreads();
|
mb.createTestProcessesAndThreads();
|
||||||
|
|
||||||
TraceRecorder recorder = modelService.recordTargetAndActivateTrace(mb.testProcess1,
|
TraceRecorder recorder = modelService.recordTargetAndActivateTrace(mb.testProcess1,
|
||||||
new TestDebuggerTargetTraceMapper(mb.testProcess1));
|
createTargetTraceMapper(mb.testProcess1));
|
||||||
Trace trace = recorder.getTrace();
|
Trace trace = recorder.getTrace();
|
||||||
|
|
||||||
// TODO: A region should not be required first. Just to get a memMapper?
|
// TODO: A region should not be required first. Just to get a memMapper?
|
||||||
mb.testProcess1.addRegion("first_proc:.text", mb.rng(0x55550000, 0x555500ff), "rx");
|
mb.testProcess1.addRegion("Memory[first_proc:.text]", mb.rng(0x55550000, 0x555500ff),
|
||||||
|
"rx");
|
||||||
TestTargetModule module =
|
TestTargetModule module =
|
||||||
mb.testProcess1.modules.addModule("first_proc", mb.rng(0x55550000, 0x555500ff));
|
mb.testProcess1.modules.addModule("Modules[first_proc]",
|
||||||
|
mb.rng(0x55550000, 0x555500ff));
|
||||||
// NOTE: A section should not be required at this point.
|
// NOTE: A section should not be required at this point.
|
||||||
TestTargetTypedefDataType typedef = module.types.addTypedefDataType("myInt",
|
TestTargetTypedefDataType typedef = module.types.addTypedefDataType("myInt",
|
||||||
new DefaultTargetPrimitiveDataType(PrimitiveKind.SINT, 4));
|
new DefaultTargetPrimitiveDataType(PrimitiveKind.SINT, 4));
|
||||||
@@ -577,7 +588,7 @@ public class DebuggerModulesProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
|||||||
conv.convertTargetDataType(typedef).get(DEFAULT_WAIT_TIMEOUT, TimeUnit.MILLISECONDS);
|
conv.convertTargetDataType(typedef).get(DEFAULT_WAIT_TIMEOUT, TimeUnit.MILLISECONDS);
|
||||||
// TODO: Some heuristic or convention to extract the module name, if applicable
|
// TODO: Some heuristic or convention to extract the module name, if applicable
|
||||||
waitForPass(() -> {
|
waitForPass(() -> {
|
||||||
DataType actType = dtm.getDataType("/Processes[1].Modules[first_proc].Types/myInt");
|
DataType actType = dtm.getDataType("/Modules[first_proc].Types/myInt");
|
||||||
assertTypeEquals(expType, actType);
|
assertTypeEquals(expType, actType);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -596,11 +607,12 @@ public class DebuggerModulesProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
|||||||
mb.createTestProcessesAndThreads();
|
mb.createTestProcessesAndThreads();
|
||||||
|
|
||||||
TraceRecorder recorder = modelService.recordTargetAndActivateTrace(mb.testProcess1,
|
TraceRecorder recorder = modelService.recordTargetAndActivateTrace(mb.testProcess1,
|
||||||
new TestDebuggerTargetTraceMapper(mb.testProcess1));
|
createTargetTraceMapper(mb.testProcess1));
|
||||||
Trace trace = recorder.getTrace();
|
Trace trace = recorder.getTrace();
|
||||||
|
|
||||||
// TODO: A region should not be required first. Just to get a memMapper?
|
// TODO: A region should not be required first. Just to get a memMapper?
|
||||||
mb.testProcess1.addRegion("first_proc:.text", mb.rng(0x55550000, 0x555500ff), "rx");
|
mb.testProcess1.addRegion("first_proc:.text", mb.rng(0x55550000, 0x555500ff),
|
||||||
|
"rx");
|
||||||
TestTargetModule module =
|
TestTargetModule module =
|
||||||
mb.testProcess1.modules.addModule("first_proc", mb.rng(0x55550000, 0x555500ff));
|
mb.testProcess1.modules.addModule("first_proc", mb.rng(0x55550000, 0x555500ff));
|
||||||
// NOTE: A section should not be required at this point.
|
// NOTE: A section should not be required at this point.
|
||||||
|
|||||||
+1
-1
@@ -146,7 +146,7 @@ public class DebuggerRegistersProviderTest extends AbstractGhidraHeadedDebuggerG
|
|||||||
Register::isBaseRegister);
|
Register::isBaseRegister);
|
||||||
|
|
||||||
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
|
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
|
||||||
new TestDebuggerTargetTraceMapper(mb.testProcess1));
|
createTargetTraceMapper(mb.testProcess1));
|
||||||
|
|
||||||
waitFor(() -> {
|
waitFor(() -> {
|
||||||
TraceThread thread = recorder.getTraceThread(mb.testThread1);
|
TraceThread thread = recorder.getTraceThread(mb.testThread1);
|
||||||
|
|||||||
+96
@@ -0,0 +1,96 @@
|
|||||||
|
/* ###
|
||||||
|
* 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.plugin.core.debug.gui.stack;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import ghidra.dbg.target.schema.SchemaContext;
|
||||||
|
import ghidra.dbg.target.schema.XmlSchemaContext;
|
||||||
|
import ghidra.dbg.target.schema.TargetObjectSchema.SchemaName;
|
||||||
|
import ghidra.trace.model.Trace;
|
||||||
|
import ghidra.util.database.UndoableTransaction;
|
||||||
|
|
||||||
|
public class DebuggerStackProviderObjectTest extends DebuggerStackProviderTest {
|
||||||
|
|
||||||
|
protected SchemaContext ctx;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void createTrace(String langID) throws IOException {
|
||||||
|
super.createTrace(langID);
|
||||||
|
try {
|
||||||
|
activateObjectsMode();
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
throw new AssertionError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void useTrace(Trace trace) {
|
||||||
|
super.useTrace(trace);
|
||||||
|
try {
|
||||||
|
activateObjectsMode();
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
throw new AssertionError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void activateObjectsMode() throws Exception {
|
||||||
|
// NOTE the use of index='1' allowing object-based managers to ID unique path
|
||||||
|
ctx = XmlSchemaContext.deserialize("" + //
|
||||||
|
"<context>" + //
|
||||||
|
" <schema name='Session' elementResync='NEVER' attributeResync='ONCE'>" + //
|
||||||
|
" <attribute name='Processes' schema='ProcessContainer' />" + //
|
||||||
|
" </schema>" + //
|
||||||
|
" <schema name='ProcessContainer' canonical='yes' elementResync='NEVER' " + //
|
||||||
|
" attributeResync='ONCE'>" + //
|
||||||
|
" <element index='1' schema='Process' />" + // <---- NOTE HERE
|
||||||
|
" </schema>" + //
|
||||||
|
" <schema name='Process' elementResync='NEVER' attributeResync='ONCE'>" + //
|
||||||
|
" <attribute name='Threads' schema='ThreadContainer' />" + //
|
||||||
|
" <attribute name='Memory' schema='RegionContainer' />" + //
|
||||||
|
" </schema>" + //
|
||||||
|
" <schema name='ThreadContainer' canonical='yes' elementResync='NEVER' " + //
|
||||||
|
" attributeResync='ONCE'>" + //
|
||||||
|
" <element schema='Thread' />" + //
|
||||||
|
" </schema>" + //
|
||||||
|
" <schema name='Thread' elementResync='NEVER' attributeResync='NEVER'>" + //
|
||||||
|
" <interface name='Thread' />" + //
|
||||||
|
" <attribute name='Stack' schema='Stack' />" + //
|
||||||
|
" </schema>" + //
|
||||||
|
" <schema name='Stack' canonical='yes' elementResync='NEVER' " + //
|
||||||
|
" attributeResync='ONCE'>" + //
|
||||||
|
" <interface name='Stack' />" + //
|
||||||
|
" <element schema='Frame' />" + //
|
||||||
|
" </schema>" + //
|
||||||
|
" <schema name='Frame' elementResync='NEVER' attributeResync='NEVER'>" + //
|
||||||
|
" <interface name='StackFrame' />" + //
|
||||||
|
" </schema>" + //
|
||||||
|
" <schema name='RegionContainer' canonical='yes' elementResync='NEVER' " + //
|
||||||
|
" attributeResync='ONCE'>" + //
|
||||||
|
" <element schema='Region' />" + //
|
||||||
|
" </schema>" + //
|
||||||
|
" <schema name='Region' elementResync='NEVER' attributeResync='NEVER'>" + //
|
||||||
|
" <interface name='MemoryRegion' />" + //
|
||||||
|
" </schema>" + //
|
||||||
|
"</context>");
|
||||||
|
|
||||||
|
try (UndoableTransaction tid = tb.startTransaction()) {
|
||||||
|
tb.trace.getObjectManager().createRootObject(ctx.getSchema(new SchemaName("Session")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+19
-18
@@ -155,7 +155,7 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerGUITe
|
|||||||
public void testActivateThreadNoStackNoRegsEmpty() throws Exception {
|
public void testActivateThreadNoStackNoRegsEmpty() throws Exception {
|
||||||
createAndOpenTrace();
|
createAndOpenTrace();
|
||||||
|
|
||||||
TraceThread thread = addThread("Thread 1");
|
TraceThread thread = addThread("Processes[1].Threads[1]");
|
||||||
waitForDomainObject(tb.trace);
|
waitForDomainObject(tb.trace);
|
||||||
|
|
||||||
traceManager.activateThread(thread);
|
traceManager.activateThread(thread);
|
||||||
@@ -168,7 +168,7 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerGUITe
|
|||||||
public void testActivateThreadNoStackRegsSynthetic() throws Exception {
|
public void testActivateThreadNoStackRegsSynthetic() throws Exception {
|
||||||
createAndOpenTrace();
|
createAndOpenTrace();
|
||||||
|
|
||||||
TraceThread thread = addThread("Thread 1");
|
TraceThread thread = addThread("Processes[1].Threads[1]");
|
||||||
addRegVals(thread);
|
addRegVals(thread);
|
||||||
waitForDomainObject(tb.trace);
|
waitForDomainObject(tb.trace);
|
||||||
|
|
||||||
@@ -182,7 +182,7 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerGUITe
|
|||||||
public void testActivateThreadRegsThenAddEmptyStackEmpty() throws Exception {
|
public void testActivateThreadRegsThenAddEmptyStackEmpty() throws Exception {
|
||||||
createAndOpenTrace();
|
createAndOpenTrace();
|
||||||
|
|
||||||
TraceThread thread = addThread("Thread 1");
|
TraceThread thread = addThread("Processes[1].Threads[1]");
|
||||||
addRegVals(thread);
|
addRegVals(thread);
|
||||||
addStack(thread);
|
addStack(thread);
|
||||||
waitForDomainObject(tb.trace);
|
waitForDomainObject(tb.trace);
|
||||||
@@ -197,7 +197,7 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerGUITe
|
|||||||
public void testActivateThreadThenAddStackPopulatesProvider() throws Exception {
|
public void testActivateThreadThenAddStackPopulatesProvider() throws Exception {
|
||||||
createAndOpenTrace();
|
createAndOpenTrace();
|
||||||
|
|
||||||
TraceThread thread = addThread("Thread 1");
|
TraceThread thread = addThread("Processes[1].Threads[1]");
|
||||||
traceManager.activateThread(thread);
|
traceManager.activateThread(thread);
|
||||||
TraceStack stack = addStack(thread);
|
TraceStack stack = addStack(thread);
|
||||||
addStackFrames(stack);
|
addStackFrames(stack);
|
||||||
@@ -210,7 +210,7 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerGUITe
|
|||||||
public void testAddStackThenActivateThreadPopulatesProvider() throws Exception {
|
public void testAddStackThenActivateThreadPopulatesProvider() throws Exception {
|
||||||
createAndOpenTrace();
|
createAndOpenTrace();
|
||||||
|
|
||||||
TraceThread thread = addThread("Thread 1");
|
TraceThread thread = addThread("Processes[1].Threads[1]");
|
||||||
TraceStack stack = addStack(thread);
|
TraceStack stack = addStack(thread);
|
||||||
addStackFrames(stack);
|
addStackFrames(stack);
|
||||||
waitForDomainObject(tb.trace);
|
waitForDomainObject(tb.trace);
|
||||||
@@ -225,7 +225,7 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerGUITe
|
|||||||
public void testAppendStackUpdatesProvider() throws Exception {
|
public void testAppendStackUpdatesProvider() throws Exception {
|
||||||
createAndOpenTrace();
|
createAndOpenTrace();
|
||||||
|
|
||||||
TraceThread thread = addThread("Thread 1");
|
TraceThread thread = addThread("Processes[1].Threads[1]");
|
||||||
TraceStack stack = addStack(thread);
|
TraceStack stack = addStack(thread);
|
||||||
addStackFrames(stack);
|
addStackFrames(stack);
|
||||||
waitForDomainObject(tb.trace);
|
waitForDomainObject(tb.trace);
|
||||||
@@ -250,7 +250,7 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerGUITe
|
|||||||
public void testPushStackUpdatesProvider() throws Exception {
|
public void testPushStackUpdatesProvider() throws Exception {
|
||||||
createAndOpenTrace();
|
createAndOpenTrace();
|
||||||
|
|
||||||
TraceThread thread = addThread("Thread 1");
|
TraceThread thread = addThread("Processes[1].Threads[1]");
|
||||||
TraceStack stack = addStack(thread);
|
TraceStack stack = addStack(thread);
|
||||||
addStackFrames(stack);
|
addStackFrames(stack);
|
||||||
waitForDomainObject(tb.trace);
|
waitForDomainObject(tb.trace);
|
||||||
@@ -275,7 +275,7 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerGUITe
|
|||||||
public void testTruncateStackUpdatesProvider() throws Exception {
|
public void testTruncateStackUpdatesProvider() throws Exception {
|
||||||
createAndOpenTrace();
|
createAndOpenTrace();
|
||||||
|
|
||||||
TraceThread thread = addThread("Thread 1");
|
TraceThread thread = addThread("Processes[1].Threads[1]");
|
||||||
TraceStack stack = addStack(thread);
|
TraceStack stack = addStack(thread);
|
||||||
addStackFrames(stack);
|
addStackFrames(stack);
|
||||||
waitForDomainObject(tb.trace);
|
waitForDomainObject(tb.trace);
|
||||||
@@ -298,7 +298,7 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerGUITe
|
|||||||
public void testPopStackUpdatesProvider() throws Exception {
|
public void testPopStackUpdatesProvider() throws Exception {
|
||||||
createAndOpenTrace();
|
createAndOpenTrace();
|
||||||
|
|
||||||
TraceThread thread = addThread("Thread 1");
|
TraceThread thread = addThread("Processes[1].Threads[1]");
|
||||||
TraceStack stack = addStack(thread);
|
TraceStack stack = addStack(thread);
|
||||||
addStackFrames(stack);
|
addStackFrames(stack);
|
||||||
waitForDomainObject(tb.trace);
|
waitForDomainObject(tb.trace);
|
||||||
@@ -321,7 +321,7 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerGUITe
|
|||||||
public void testDeleteStackUpdatesProvider() throws Exception {
|
public void testDeleteStackUpdatesProvider() throws Exception {
|
||||||
createAndOpenTrace();
|
createAndOpenTrace();
|
||||||
|
|
||||||
TraceThread thread = addThread("Thread 1");
|
TraceThread thread = addThread("Processes[1].Threads[1]");
|
||||||
TraceStack stack = addStack(thread);
|
TraceStack stack = addStack(thread);
|
||||||
addStackFrames(stack);
|
addStackFrames(stack);
|
||||||
waitForDomainObject(tb.trace);
|
waitForDomainObject(tb.trace);
|
||||||
@@ -343,8 +343,8 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerGUITe
|
|||||||
public void testActivateOtherThread() throws Exception {
|
public void testActivateOtherThread() throws Exception {
|
||||||
createAndOpenTrace();
|
createAndOpenTrace();
|
||||||
|
|
||||||
TraceThread thread1 = addThread("Thread 1");
|
TraceThread thread1 = addThread("Processes[1].Threads[1]");
|
||||||
TraceThread thread2 = addThread("Thread 2");
|
TraceThread thread2 = addThread("Processes[1].Threads[2]");
|
||||||
TraceStack stack = addStack(thread1);
|
TraceStack stack = addStack(thread1);
|
||||||
addStackFrames(stack);
|
addStackFrames(stack);
|
||||||
waitForDomainObject(tb.trace);
|
waitForDomainObject(tb.trace);
|
||||||
@@ -364,7 +364,7 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerGUITe
|
|||||||
public void testActivateSnap() throws Exception {
|
public void testActivateSnap() throws Exception {
|
||||||
createAndOpenTrace();
|
createAndOpenTrace();
|
||||||
|
|
||||||
TraceThread thread = addThread("Thread 1");
|
TraceThread thread = addThread("Processes[1].Threads[1]");
|
||||||
TraceStack stack = addStack(thread);
|
TraceStack stack = addStack(thread);
|
||||||
addStackFrames(stack);
|
addStackFrames(stack);
|
||||||
waitForDomainObject(tb.trace);
|
waitForDomainObject(tb.trace);
|
||||||
@@ -389,7 +389,7 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerGUITe
|
|||||||
public void testCloseCurrentTraceEmpty() throws Exception {
|
public void testCloseCurrentTraceEmpty() throws Exception {
|
||||||
createAndOpenTrace();
|
createAndOpenTrace();
|
||||||
|
|
||||||
TraceThread thread = addThread("Thread 1");
|
TraceThread thread = addThread("Processes[1].Threads[1]");
|
||||||
TraceStack stack = addStack(thread);
|
TraceStack stack = addStack(thread);
|
||||||
addStackFrames(stack);
|
addStackFrames(stack);
|
||||||
waitForDomainObject(tb.trace);
|
waitForDomainObject(tb.trace);
|
||||||
@@ -410,7 +410,7 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerGUITe
|
|||||||
public void testSelectRowActivatesFrame() throws Exception {
|
public void testSelectRowActivatesFrame() throws Exception {
|
||||||
createAndOpenTrace();
|
createAndOpenTrace();
|
||||||
|
|
||||||
TraceThread thread = addThread("Thread 1");
|
TraceThread thread = addThread("Processes[1].Threads[1]");
|
||||||
TraceStack stack = addStack(thread);
|
TraceStack stack = addStack(thread);
|
||||||
addStackFrames(stack);
|
addStackFrames(stack);
|
||||||
waitForDomainObject(tb.trace);
|
waitForDomainObject(tb.trace);
|
||||||
@@ -435,7 +435,7 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerGUITe
|
|||||||
public void testActivateFrameSelectsRow() throws Exception {
|
public void testActivateFrameSelectsRow() throws Exception {
|
||||||
createAndOpenTrace();
|
createAndOpenTrace();
|
||||||
|
|
||||||
TraceThread thread = addThread("Thread 1");
|
TraceThread thread = addThread("Processes[1].Threads[1]");
|
||||||
TraceStack stack = addStack(thread);
|
TraceStack stack = addStack(thread);
|
||||||
addStackFrames(stack);
|
addStackFrames(stack);
|
||||||
waitForDomainObject(tb.trace);
|
waitForDomainObject(tb.trace);
|
||||||
@@ -467,7 +467,7 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerGUITe
|
|||||||
traceManager.openTrace(tb.trace);
|
traceManager.openTrace(tb.trace);
|
||||||
programManager.openProgram(program);
|
programManager.openProgram(program);
|
||||||
|
|
||||||
TraceThread thread = addThread("Thread 1");
|
TraceThread thread = addThread("Processes[1].Threads[1]");
|
||||||
TraceStack stack = addStack(thread);
|
TraceStack stack = addStack(thread);
|
||||||
addStackFrames(stack);
|
addStackFrames(stack);
|
||||||
waitForDomainObject(tb.trace);
|
waitForDomainObject(tb.trace);
|
||||||
@@ -491,7 +491,8 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerGUITe
|
|||||||
|
|
||||||
try (UndoableTransaction tid = tb.startTransaction()) {
|
try (UndoableTransaction tid = tb.startTransaction()) {
|
||||||
tb.trace.getMemoryManager()
|
tb.trace.getMemoryManager()
|
||||||
.addRegion("bin:.text", Range.atLeast(0L), tb.drng(0x00400000, 0x00400fff),
|
.addRegion("Processes[1].Memory[bin:.text]", Range.atLeast(0L),
|
||||||
|
tb.drng(0x00400000, 0x00400fff),
|
||||||
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
||||||
|
|
||||||
TraceLocation dloc =
|
TraceLocation dloc =
|
||||||
|
|||||||
+79
@@ -0,0 +1,79 @@
|
|||||||
|
/* ###
|
||||||
|
* 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.plugin.core.debug.gui.thread;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import ghidra.dbg.target.schema.SchemaContext;
|
||||||
|
import ghidra.dbg.target.schema.TargetObjectSchema.SchemaName;
|
||||||
|
import ghidra.dbg.target.schema.XmlSchemaContext;
|
||||||
|
import ghidra.trace.model.Trace;
|
||||||
|
import ghidra.util.database.UndoableTransaction;
|
||||||
|
|
||||||
|
public class DebuggerThreadsProviderObjectTest extends DebuggerThreadsProviderTest {
|
||||||
|
|
||||||
|
protected SchemaContext ctx;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void createTrace(String langID) throws IOException {
|
||||||
|
super.createTrace(langID);
|
||||||
|
try {
|
||||||
|
activateObjectsMode();
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
throw new AssertionError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void useTrace(Trace trace) {
|
||||||
|
super.useTrace(trace);
|
||||||
|
try {
|
||||||
|
activateObjectsMode();
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
throw new AssertionError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void activateObjectsMode() throws Exception {
|
||||||
|
// NOTE the use of index='1' allowing object-based managers to ID unique path
|
||||||
|
ctx = XmlSchemaContext.deserialize("" + //
|
||||||
|
"<context>" + //
|
||||||
|
" <schema name='Session' elementResync='NEVER' attributeResync='ONCE'>" + //
|
||||||
|
" <attribute name='Processes' schema='ProcessContainer' />" + //
|
||||||
|
" </schema>" + //
|
||||||
|
" <schema name='ProcessContainer' canonical='yes' elementResync='NEVER' " + //
|
||||||
|
" attributeResync='ONCE'>" + //
|
||||||
|
" <element index='1' schema='Process' />" + // <---- NOTE HERE
|
||||||
|
" </schema>" + //
|
||||||
|
" <schema name='Process' elementResync='NEVER' attributeResync='ONCE'>" + //
|
||||||
|
" <attribute name='Threads' schema='ThreadContainer' />" + //
|
||||||
|
" </schema>" + //
|
||||||
|
" <schema name='ThreadContainer' canonical='yes' elementResync='NEVER' " + //
|
||||||
|
" attributeResync='ONCE'>" + //
|
||||||
|
" <element schema='Thread' />" + //
|
||||||
|
" </schema>" + //
|
||||||
|
" <schema name='Thread' elementResync='NEVER' attributeResync='NEVER'>" + //
|
||||||
|
" <interface name='Thread' />" + //
|
||||||
|
" </schema>" + //
|
||||||
|
"</context>");
|
||||||
|
|
||||||
|
try (UndoableTransaction tid = tb.startTransaction()) {
|
||||||
|
tb.trace.getObjectManager().createRootObject(ctx.getSchema(new SchemaName("Session")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+6
-4
@@ -55,9 +55,9 @@ public class DebuggerThreadsProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
|||||||
protected void addThreads() throws Exception {
|
protected void addThreads() throws Exception {
|
||||||
TraceThreadManager manager = tb.trace.getThreadManager();
|
TraceThreadManager manager = tb.trace.getThreadManager();
|
||||||
try (UndoableTransaction tid = tb.startTransaction()) {
|
try (UndoableTransaction tid = tb.startTransaction()) {
|
||||||
thread1 = manager.addThread("Thread 1", Range.atLeast(0L));
|
thread1 = manager.addThread("Processes[1].Threads[1]", Range.atLeast(0L));
|
||||||
thread1.setComment("A comment");
|
thread1.setComment("A comment");
|
||||||
thread2 = manager.addThread("Thread 2", Range.closed(5L, 10L));
|
thread2 = manager.addThread("Processes[1].Threads[2]", Range.closed(5L, 10L));
|
||||||
thread2.setComment("Another comment");
|
thread2.setComment("Another comment");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -99,7 +99,7 @@ public class DebuggerThreadsProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
|||||||
|
|
||||||
ThreadRow thread1Record = threadsDisplayed.get(0);
|
ThreadRow thread1Record = threadsDisplayed.get(0);
|
||||||
assertEquals(thread1, thread1Record.getThread());
|
assertEquals(thread1, thread1Record.getThread());
|
||||||
assertEquals("Thread 1", thread1Record.getName());
|
assertEquals("Processes[1].Threads[1]", thread1Record.getName());
|
||||||
assertEquals(Range.atLeast(0L), thread1Record.getLifespan());
|
assertEquals(Range.atLeast(0L), thread1Record.getLifespan());
|
||||||
assertEquals(0, thread1Record.getCreationSnap());
|
assertEquals(0, thread1Record.getCreationSnap());
|
||||||
assertEquals("", thread1Record.getDestructionSnap());
|
assertEquals("", thread1Record.getDestructionSnap());
|
||||||
@@ -475,13 +475,15 @@ public class DebuggerThreadsProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
|||||||
// Not live, so no seek
|
// Not live, so no seek
|
||||||
assertEquals(0, traceManager.getCurrentSnap());
|
assertEquals(0, traceManager.getCurrentSnap());
|
||||||
|
|
||||||
|
tb.close();
|
||||||
|
|
||||||
createTestModel();
|
createTestModel();
|
||||||
mb.createTestProcessesAndThreads();
|
mb.createTestProcessesAndThreads();
|
||||||
// Threads needs registers to be recognized by the recorder
|
// Threads needs registers to be recognized by the recorder
|
||||||
mb.createTestThreadRegisterBanks();
|
mb.createTestThreadRegisterBanks();
|
||||||
|
|
||||||
TraceRecorder recorder = modelService.recordTargetAndActivateTrace(mb.testProcess1,
|
TraceRecorder recorder = modelService.recordTargetAndActivateTrace(mb.testProcess1,
|
||||||
new TestDebuggerTargetTraceMapper(mb.testProcess1));
|
createTargetTraceMapper(mb.testProcess1));
|
||||||
Trace trace = recorder.getTrace();
|
Trace trace = recorder.getTrace();
|
||||||
|
|
||||||
// Wait till two threads are observed in the database
|
// Wait till two threads are observed in the database
|
||||||
|
|||||||
+2
-2
@@ -208,7 +208,7 @@ public class DebuggerWatchesProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
|||||||
mb.testProcess1.memory.writeMemory(mb.addr(0x00400000), tb.arr(1, 2, 3, 4));
|
mb.testProcess1.memory.writeMemory(mb.addr(0x00400000), tb.arr(1, 2, 3, 4));
|
||||||
|
|
||||||
recorder = modelService.recordTarget(mb.testProcess1,
|
recorder = modelService.recordTarget(mb.testProcess1,
|
||||||
new TestDebuggerTargetTraceMapper(mb.testProcess1));
|
createTargetTraceMapper(mb.testProcess1));
|
||||||
Trace trace = recorder.getTrace();
|
Trace trace = recorder.getTrace();
|
||||||
TraceThread thread = waitForValue(() -> recorder.getTraceThread(mb.testThread1));
|
TraceThread thread = waitForValue(() -> recorder.getTraceThread(mb.testThread1));
|
||||||
|
|
||||||
@@ -348,7 +348,7 @@ public class DebuggerWatchesProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
|||||||
mb.testProcess1.addRegion(".text", mb.rng(0x00400000, 0x00401000), "rx");
|
mb.testProcess1.addRegion(".text", mb.rng(0x00400000, 0x00401000), "rx");
|
||||||
|
|
||||||
recorder = modelService.recordTarget(mb.testProcess1,
|
recorder = modelService.recordTarget(mb.testProcess1,
|
||||||
new TestDebuggerTargetTraceMapper(mb.testProcess1));
|
createTargetTraceMapper(mb.testProcess1));
|
||||||
Trace trace = recorder.getTrace();
|
Trace trace = recorder.getTrace();
|
||||||
TraceThread thread = waitForValue(() -> recorder.getTraceThread(mb.testThread1));
|
TraceThread thread = waitForValue(() -> recorder.getTraceThread(mb.testThread1));
|
||||||
|
|
||||||
|
|||||||
+99
@@ -0,0 +1,99 @@
|
|||||||
|
/* ###
|
||||||
|
* 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.plugin.core.debug.service.breakpoint;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import ghidra.dbg.target.schema.SchemaContext;
|
||||||
|
import ghidra.dbg.target.schema.XmlSchemaContext;
|
||||||
|
import ghidra.dbg.target.schema.TargetObjectSchema.SchemaName;
|
||||||
|
import ghidra.trace.model.Trace;
|
||||||
|
import ghidra.util.database.UndoableTransaction;
|
||||||
|
|
||||||
|
public class DebuggerLogicalBreakpointServiceObjectTest
|
||||||
|
extends DebuggerLogicalBreakpointServiceTest {
|
||||||
|
|
||||||
|
protected SchemaContext ctx;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void createTrace(String langID) throws IOException {
|
||||||
|
super.createTrace(langID);
|
||||||
|
try {
|
||||||
|
activateObjectsMode();
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
throw new AssertionError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void useTrace(Trace trace) {
|
||||||
|
super.useTrace(trace);
|
||||||
|
try {
|
||||||
|
activateObjectsMode();
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
throw new AssertionError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void activateObjectsMode() throws Exception {
|
||||||
|
// NOTE the use of index='...' allowing object-based managers to ID unique path
|
||||||
|
// TODO: I guess this'll burn down if the naming scheme changes....
|
||||||
|
int index = tb.trace.getName().startsWith("[3]") ? 3 : 1;
|
||||||
|
ctx = XmlSchemaContext.deserialize("" + //
|
||||||
|
"<context>" + //
|
||||||
|
" <schema name='Session' elementResync='NEVER' attributeResync='ONCE'>" + //
|
||||||
|
" <attribute name='Processes' schema='ProcessContainer' />" + //
|
||||||
|
" </schema>" + //
|
||||||
|
" <schema name='ProcessContainer' canonical='yes' elementResync='NEVER' " + //
|
||||||
|
" attributeResync='ONCE'>" + //
|
||||||
|
" <element index='" + index + "' schema='Process' />" + // <---- NOTE HERE
|
||||||
|
" </schema>" + //
|
||||||
|
" <schema name='Process' elementResync='NEVER' attributeResync='ONCE'>" + //
|
||||||
|
" <attribute name='Threads' schema='ThreadContainer' />" + //
|
||||||
|
" <attribute name='Memory' schema='RegionContainer' />" + //
|
||||||
|
" <attribute name='Breakpoints' schema='BreakpointContainer' />" + //
|
||||||
|
" </schema>" + //
|
||||||
|
" <schema name='ThreadContainer' canonical='yes' elementResync='NEVER' " + //
|
||||||
|
" attributeResync='ONCE'>" + //
|
||||||
|
" <element schema='Thread' />" + //
|
||||||
|
" </schema>" + //
|
||||||
|
" <schema name='Thread' elementResync='NEVER' attributeResync='NEVER'>" + //
|
||||||
|
" <interface name='Thread' />" + //
|
||||||
|
" </schema>" + //
|
||||||
|
" <schema name='RegionContainer' canonical='yes' elementResync='NEVER' " + //
|
||||||
|
" attributeResync='ONCE'>" + //
|
||||||
|
" <element schema='Region' />" + //
|
||||||
|
" </schema>" + //
|
||||||
|
" <schema name='Region' elementResync='NEVER' attributeResync='NEVER'>" + //
|
||||||
|
" <interface name='MemoryRegion' />" + //
|
||||||
|
" </schema>" + //
|
||||||
|
" <schema name='BreakpointContainer' canonical='yes' elementResync='NEVER' " + //
|
||||||
|
" attributeResync='ONCE'>" + //
|
||||||
|
" <element schema='Breakpoint' />" + //
|
||||||
|
" </schema>" + //
|
||||||
|
" <schema name='Breakpoint' elementResync='NEVER' attributeResync='NEVER'>" + //
|
||||||
|
" <interface name='BreakpointSpec' />" + //
|
||||||
|
" <interface name='BreakpointLocation' />" + //
|
||||||
|
" </schema>" + //
|
||||||
|
"</context>");
|
||||||
|
|
||||||
|
try (UndoableTransaction tid = tb.startTransaction()) {
|
||||||
|
tb.trace.getObjectManager().createRootObject(ctx.getSchema(new SchemaName("Session")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+4
-3
@@ -74,7 +74,8 @@ public class DebuggerLogicalBreakpointServiceTest extends AbstractGhidraHeadedDe
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void breakpointUpdated(LogicalBreakpoint lb) {
|
public synchronized void breakpointUpdated(LogicalBreakpoint lb) {
|
||||||
Msg.debug(this, "LogicalBreakpoint updated: " + lb);
|
Msg.debug(this,
|
||||||
|
"LogicalBreakpoint updated: (" + System.identityHashCode(lb) + ")" + lb);
|
||||||
assertTrue(current.contains(lb));
|
assertTrue(current.contains(lb));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,12 +166,12 @@ public class DebuggerLogicalBreakpointServiceTest extends AbstractGhidraHeadedDe
|
|||||||
|
|
||||||
public void startRecorder1() throws Throwable {
|
public void startRecorder1() throws Throwable {
|
||||||
recorder1 = modelService.recordTarget(mb.testProcess1,
|
recorder1 = modelService.recordTarget(mb.testProcess1,
|
||||||
new TestDebuggerTargetTraceMapper(mb.testProcess1));
|
createTargetTraceMapper(mb.testProcess1));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void startRecorder3() throws Throwable {
|
public void startRecorder3() throws Throwable {
|
||||||
recorder3 = modelService.recordTarget(mb.testProcess3,
|
recorder3 = modelService.recordTarget(mb.testProcess3,
|
||||||
new TestDebuggerTargetTraceMapper(mb.testProcess3));
|
createTargetTraceMapper(mb.testProcess3));
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
|
|||||||
+15
-15
@@ -213,7 +213,7 @@ public class DebuggerModelServiceTest extends AbstractGhidraHeadedDebuggerGUITes
|
|||||||
|
|
||||||
assertEquals(Set.of(), Set.copyOf(modelService.getTraceRecorders()));
|
assertEquals(Set.of(), Set.copyOf(modelService.getTraceRecorders()));
|
||||||
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
|
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
|
||||||
new TestDebuggerTargetTraceMapper(mb.testProcess1));
|
createTargetTraceMapper(mb.testProcess1));
|
||||||
|
|
||||||
assertEquals(Set.of(recorder), Set.copyOf(modelService.getTraceRecorders()));
|
assertEquals(Set.of(recorder), Set.copyOf(modelService.getTraceRecorders()));
|
||||||
}
|
}
|
||||||
@@ -228,7 +228,7 @@ public class DebuggerModelServiceTest extends AbstractGhidraHeadedDebuggerGUITes
|
|||||||
new CollectionChangeDelegateWrapper<>(recorderChangeListener);
|
new CollectionChangeDelegateWrapper<>(recorderChangeListener);
|
||||||
modelService.addTraceRecordersChangedListener(wrapper);
|
modelService.addTraceRecordersChangedListener(wrapper);
|
||||||
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
|
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
|
||||||
new TestDebuggerTargetTraceMapper(mb.testProcess1));
|
createTargetTraceMapper(mb.testProcess1));
|
||||||
|
|
||||||
new VerificationsInOrder() {
|
new VerificationsInOrder() {
|
||||||
{
|
{
|
||||||
@@ -243,7 +243,7 @@ public class DebuggerModelServiceTest extends AbstractGhidraHeadedDebuggerGUITes
|
|||||||
mb.createTestProcessesAndThreads();
|
mb.createTestProcessesAndThreads();
|
||||||
|
|
||||||
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
|
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
|
||||||
new TestDebuggerTargetTraceMapper(mb.testProcess1));
|
createTargetTraceMapper(mb.testProcess1));
|
||||||
// Strong ref
|
// Strong ref
|
||||||
CollectionChangeDelegateWrapper<TraceRecorder> wrapper =
|
CollectionChangeDelegateWrapper<TraceRecorder> wrapper =
|
||||||
new CollectionChangeDelegateWrapper<>(recorderChangeListener);
|
new CollectionChangeDelegateWrapper<>(recorderChangeListener);
|
||||||
@@ -265,7 +265,7 @@ public class DebuggerModelServiceTest extends AbstractGhidraHeadedDebuggerGUITes
|
|||||||
mb.createTestProcessesAndThreads();
|
mb.createTestProcessesAndThreads();
|
||||||
|
|
||||||
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
|
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
|
||||||
new TestDebuggerTargetTraceMapper(mb.testProcess1));
|
createTargetTraceMapper(mb.testProcess1));
|
||||||
assertNotNull(recorder);
|
assertNotNull(recorder);
|
||||||
waitOn(recorder.init()); // Already initializing, just wait for it to complete
|
waitOn(recorder.init()); // Already initializing, just wait for it to complete
|
||||||
|
|
||||||
@@ -281,7 +281,7 @@ public class DebuggerModelServiceTest extends AbstractGhidraHeadedDebuggerGUITes
|
|||||||
mb.createTestProcessesAndThreads();
|
mb.createTestProcessesAndThreads();
|
||||||
|
|
||||||
modelService.recordTargetAndActivateTrace(mb.testProcess1,
|
modelService.recordTargetAndActivateTrace(mb.testProcess1,
|
||||||
new TestDebuggerTargetTraceMapper(mb.testProcess1));
|
createTargetTraceMapper(mb.testProcess1));
|
||||||
waitForSwing();
|
waitForSwing();
|
||||||
|
|
||||||
Trace trace = traceManager.getCurrentTrace();
|
Trace trace = traceManager.getCurrentTrace();
|
||||||
@@ -290,7 +290,7 @@ public class DebuggerModelServiceTest extends AbstractGhidraHeadedDebuggerGUITes
|
|||||||
traceManager.closeTrace(trace);
|
traceManager.closeTrace(trace);
|
||||||
waitOn(mb.testModel.close());
|
waitOn(mb.testModel.close());
|
||||||
waitForPass(() -> {
|
waitForPass(() -> {
|
||||||
assertEquals(List.of(), trace.getConsumerList());
|
assertEquals(List.of(tb), trace.getConsumerList());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -300,7 +300,7 @@ public class DebuggerModelServiceTest extends AbstractGhidraHeadedDebuggerGUITes
|
|||||||
mb.createTestProcessesAndThreads();
|
mb.createTestProcessesAndThreads();
|
||||||
|
|
||||||
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
|
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
|
||||||
new TestDebuggerTargetTraceMapper(mb.testProcess1));
|
createTargetTraceMapper(mb.testProcess1));
|
||||||
|
|
||||||
assertEquals(recorder, modelService.getRecorder(mb.testProcess1));
|
assertEquals(recorder, modelService.getRecorder(mb.testProcess1));
|
||||||
}
|
}
|
||||||
@@ -311,7 +311,7 @@ public class DebuggerModelServiceTest extends AbstractGhidraHeadedDebuggerGUITes
|
|||||||
mb.createTestProcessesAndThreads();
|
mb.createTestProcessesAndThreads();
|
||||||
|
|
||||||
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
|
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
|
||||||
new TestDebuggerTargetTraceMapper(mb.testProcess1));
|
createTargetTraceMapper(mb.testProcess1));
|
||||||
|
|
||||||
assertEquals(recorder, modelService.getRecorder(recorder.getTrace()));
|
assertEquals(recorder, modelService.getRecorder(recorder.getTrace()));
|
||||||
}
|
}
|
||||||
@@ -322,7 +322,7 @@ public class DebuggerModelServiceTest extends AbstractGhidraHeadedDebuggerGUITes
|
|||||||
mb.createTestProcessesAndThreads();
|
mb.createTestProcessesAndThreads();
|
||||||
|
|
||||||
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
|
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
|
||||||
new TestDebuggerTargetTraceMapper(mb.testProcess1));
|
createTargetTraceMapper(mb.testProcess1));
|
||||||
|
|
||||||
assertEquals(mb.testProcess1, modelService.getTarget(recorder.getTrace()));
|
assertEquals(mb.testProcess1, modelService.getTarget(recorder.getTrace()));
|
||||||
}
|
}
|
||||||
@@ -333,7 +333,7 @@ public class DebuggerModelServiceTest extends AbstractGhidraHeadedDebuggerGUITes
|
|||||||
mb.createTestProcessesAndThreads();
|
mb.createTestProcessesAndThreads();
|
||||||
|
|
||||||
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
|
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
|
||||||
new TestDebuggerTargetTraceMapper(mb.testProcess1));
|
createTargetTraceMapper(mb.testProcess1));
|
||||||
|
|
||||||
assertEquals(recorder.getTrace(), modelService.getTrace(mb.testProcess1));
|
assertEquals(recorder.getTrace(), modelService.getTrace(mb.testProcess1));
|
||||||
}
|
}
|
||||||
@@ -344,7 +344,7 @@ public class DebuggerModelServiceTest extends AbstractGhidraHeadedDebuggerGUITes
|
|||||||
mb.createTestProcessesAndThreads();
|
mb.createTestProcessesAndThreads();
|
||||||
|
|
||||||
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
|
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
|
||||||
new TestDebuggerTargetTraceMapper(mb.testProcess1));
|
createTargetTraceMapper(mb.testProcess1));
|
||||||
|
|
||||||
// The most complicated case, lest I want another dimension in a cross product
|
// The most complicated case, lest I want another dimension in a cross product
|
||||||
mb.createTestThreadStacksAndFramesHaveRegisterBanks();
|
mb.createTestThreadStacksAndFramesHaveRegisterBanks();
|
||||||
@@ -373,7 +373,7 @@ public class DebuggerModelServiceTest extends AbstractGhidraHeadedDebuggerGUITes
|
|||||||
preRec.run();
|
preRec.run();
|
||||||
|
|
||||||
modelService.recordTarget(mb.testProcess1,
|
modelService.recordTarget(mb.testProcess1,
|
||||||
new TestDebuggerTargetTraceMapper(mb.testProcess1));
|
createTargetTraceMapper(mb.testProcess1));
|
||||||
|
|
||||||
postRec.run();
|
postRec.run();
|
||||||
|
|
||||||
@@ -420,7 +420,7 @@ public class DebuggerModelServiceTest extends AbstractGhidraHeadedDebuggerGUITes
|
|||||||
mb.createTestProcessesAndThreads();
|
mb.createTestProcessesAndThreads();
|
||||||
|
|
||||||
modelService.recordTarget(mb.testProcess1,
|
modelService.recordTarget(mb.testProcess1,
|
||||||
new TestDebuggerTargetTraceMapper(mb.testProcess1));
|
createTargetTraceMapper(mb.testProcess1));
|
||||||
|
|
||||||
// The most complicated case, lest I want another dimension in a cross product
|
// The most complicated case, lest I want another dimension in a cross product
|
||||||
mb.createTestThreadStacksAndFramesHaveRegisterBanks();
|
mb.createTestThreadStacksAndFramesHaveRegisterBanks();
|
||||||
@@ -439,9 +439,9 @@ public class DebuggerModelServiceTest extends AbstractGhidraHeadedDebuggerGUITes
|
|||||||
|
|
||||||
// NOTE: getTargetFocus assumes the target is being recorded
|
// NOTE: getTargetFocus assumes the target is being recorded
|
||||||
modelService.recordTarget(mb.testProcess1,
|
modelService.recordTarget(mb.testProcess1,
|
||||||
new TestDebuggerTargetTraceMapper(mb.testProcess1));
|
createTargetTraceMapper(mb.testProcess1));
|
||||||
modelService.recordTarget(mb.testProcess3,
|
modelService.recordTarget(mb.testProcess3,
|
||||||
new TestDebuggerTargetTraceMapper(mb.testProcess3));
|
createTargetTraceMapper(mb.testProcess3));
|
||||||
|
|
||||||
assertNull(modelService.getTargetFocus(mb.testProcess1));
|
assertNull(modelService.getTargetFocus(mb.testProcess1));
|
||||||
assertNull(modelService.getTargetFocus(mb.testProcess3));
|
assertNull(modelService.getTargetFocus(mb.testProcess3));
|
||||||
|
|||||||
+6
-6
@@ -48,7 +48,7 @@ public class DefaultTraceRecorderTest extends AbstractGhidraHeadedDebuggerGUITes
|
|||||||
mb.createTestProcessesAndThreads();
|
mb.createTestProcessesAndThreads();
|
||||||
|
|
||||||
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
|
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
|
||||||
new TestDebuggerTargetTraceMapper(mb.testProcess1));
|
createTargetTraceMapper(mb.testProcess1));
|
||||||
waitForPass(() -> {
|
waitForPass(() -> {
|
||||||
assertNotNull(recorder.getTraceThread(mb.testThread1));
|
assertNotNull(recorder.getTraceThread(mb.testThread1));
|
||||||
assertNotNull(recorder.getTraceThread(mb.testThread2));
|
assertNotNull(recorder.getTraceThread(mb.testThread2));
|
||||||
@@ -61,7 +61,7 @@ public class DefaultTraceRecorderTest extends AbstractGhidraHeadedDebuggerGUITes
|
|||||||
mb.createTestProcessesAndThreads();
|
mb.createTestProcessesAndThreads();
|
||||||
|
|
||||||
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
|
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
|
||||||
new TestDebuggerTargetTraceMapper(mb.testProcess1));
|
createTargetTraceMapper(mb.testProcess1));
|
||||||
Trace trace = recorder.getTrace();
|
Trace trace = recorder.getTrace();
|
||||||
|
|
||||||
TestTargetMemoryRegion targetRegion =
|
TestTargetMemoryRegion targetRegion =
|
||||||
@@ -97,7 +97,7 @@ public class DefaultTraceRecorderTest extends AbstractGhidraHeadedDebuggerGUITes
|
|||||||
mb.createTestProcessesAndThreads();
|
mb.createTestProcessesAndThreads();
|
||||||
|
|
||||||
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
|
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
|
||||||
new TestDebuggerTargetTraceMapper(mb.testProcess1));
|
createTargetTraceMapper(mb.testProcess1));
|
||||||
Trace trace = recorder.getTrace();
|
Trace trace = recorder.getTrace();
|
||||||
Language lang = trace.getBaseLanguage();
|
Language lang = trace.getBaseLanguage();
|
||||||
Register r0 = lang.getRegister("r0");
|
Register r0 = lang.getRegister("r0");
|
||||||
@@ -131,7 +131,7 @@ public class DefaultTraceRecorderTest extends AbstractGhidraHeadedDebuggerGUITes
|
|||||||
mb.createTestProcessesAndThreads();
|
mb.createTestProcessesAndThreads();
|
||||||
|
|
||||||
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
|
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
|
||||||
new TestDebuggerTargetTraceMapper(mb.testProcess1));
|
createTargetTraceMapper(mb.testProcess1));
|
||||||
Trace trace = recorder.getTrace();
|
Trace trace = recorder.getTrace();
|
||||||
Language lang = trace.getBaseLanguage();
|
Language lang = trace.getBaseLanguage();
|
||||||
Register pc = lang.getRegister("pc");
|
Register pc = lang.getRegister("pc");
|
||||||
@@ -180,7 +180,7 @@ public class DefaultTraceRecorderTest extends AbstractGhidraHeadedDebuggerGUITes
|
|||||||
mb.createTestProcessesAndThreads();
|
mb.createTestProcessesAndThreads();
|
||||||
|
|
||||||
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
|
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
|
||||||
new TestDebuggerTargetTraceMapper(mb.testProcess1));
|
createTargetTraceMapper(mb.testProcess1));
|
||||||
Trace trace = recorder.getTrace();
|
Trace trace = recorder.getTrace();
|
||||||
Language lang = trace.getBaseLanguage();
|
Language lang = trace.getBaseLanguage();
|
||||||
Register pc = lang.getRegister("pc");
|
Register pc = lang.getRegister("pc");
|
||||||
@@ -229,7 +229,7 @@ public class DefaultTraceRecorderTest extends AbstractGhidraHeadedDebuggerGUITes
|
|||||||
mb.createTestProcessesAndThreads();
|
mb.createTestProcessesAndThreads();
|
||||||
|
|
||||||
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
|
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
|
||||||
new TestDebuggerTargetTraceMapper(mb.testProcess1));
|
createTargetTraceMapper(mb.testProcess1));
|
||||||
Trace trace = recorder.getTrace();
|
Trace trace = recorder.getTrace();
|
||||||
Language lang = trace.getBaseLanguage();
|
Language lang = trace.getBaseLanguage();
|
||||||
Register pc = lang.getRegister("pc");
|
Register pc = lang.getRegister("pc");
|
||||||
|
|||||||
+4
-5
@@ -31,7 +31,6 @@ import ghidra.dbg.model.TestTargetStack;
|
|||||||
import ghidra.dbg.model.TestTargetStackFrameHasRegisterBank;
|
import ghidra.dbg.model.TestTargetStackFrameHasRegisterBank;
|
||||||
import ghidra.dbg.testutil.DebuggerModelTestUtils;
|
import ghidra.dbg.testutil.DebuggerModelTestUtils;
|
||||||
import ghidra.framework.model.DomainFile;
|
import ghidra.framework.model.DomainFile;
|
||||||
import ghidra.trace.database.thread.DBTraceThread;
|
|
||||||
import ghidra.trace.model.Trace;
|
import ghidra.trace.model.Trace;
|
||||||
import ghidra.trace.model.stack.TraceStack;
|
import ghidra.trace.model.stack.TraceStack;
|
||||||
import ghidra.trace.model.thread.TraceThread;
|
import ghidra.trace.model.thread.TraceThread;
|
||||||
@@ -116,7 +115,7 @@ public class DebuggerTraceManagerServiceTest extends AbstractGhidraHeadedDebugge
|
|||||||
|
|
||||||
assertNull(traceManager.getCurrentThread());
|
assertNull(traceManager.getCurrentThread());
|
||||||
|
|
||||||
DBTraceThread thread;
|
TraceThread thread;
|
||||||
try (UndoableTransaction tid = tb.startTransaction()) {
|
try (UndoableTransaction tid = tb.startTransaction()) {
|
||||||
thread = tb.getOrAddThread("Thread 1", 0);
|
thread = tb.getOrAddThread("Thread 1", 0);
|
||||||
}
|
}
|
||||||
@@ -297,7 +296,7 @@ public class DebuggerTraceManagerServiceTest extends AbstractGhidraHeadedDebugge
|
|||||||
mb.createTestProcessesAndThreads();
|
mb.createTestProcessesAndThreads();
|
||||||
|
|
||||||
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
|
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
|
||||||
new TestDebuggerTargetTraceMapper(mb.testProcess1));
|
createTargetTraceMapper(mb.testProcess1));
|
||||||
Trace trace = recorder.getTrace();
|
Trace trace = recorder.getTrace();
|
||||||
|
|
||||||
traceManager.openTrace(trace);
|
traceManager.openTrace(trace);
|
||||||
@@ -338,7 +337,7 @@ public class DebuggerTraceManagerServiceTest extends AbstractGhidraHeadedDebugge
|
|||||||
mb.createTestProcessesAndThreads();
|
mb.createTestProcessesAndThreads();
|
||||||
|
|
||||||
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
|
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
|
||||||
new TestDebuggerTargetTraceMapper(mb.testProcess1));
|
createTargetTraceMapper(mb.testProcess1));
|
||||||
Trace trace = recorder.getTrace();
|
Trace trace = recorder.getTrace();
|
||||||
|
|
||||||
waitForValue(() -> modelService.getTarget(trace));
|
waitForValue(() -> modelService.getTarget(trace));
|
||||||
@@ -400,7 +399,7 @@ public class DebuggerTraceManagerServiceTest extends AbstractGhidraHeadedDebugge
|
|||||||
mb.createTestProcessesAndThreads();
|
mb.createTestProcessesAndThreads();
|
||||||
|
|
||||||
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
|
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
|
||||||
new TestDebuggerTargetTraceMapper(mb.testProcess1));
|
createTargetTraceMapper(mb.testProcess1));
|
||||||
Trace trace = recorder.getTrace();
|
Trace trace = recorder.getTrace();
|
||||||
|
|
||||||
traceManager.openTrace(trace);
|
traceManager.openTrace(trace);
|
||||||
|
|||||||
+2
-2
@@ -50,7 +50,7 @@ public class TraceRecorderAsyncPcodeExecTest extends AbstractGhidraHeadedDebugge
|
|||||||
"r1", new byte[] { 6 })));
|
"r1", new byte[] { 6 })));
|
||||||
|
|
||||||
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
|
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
|
||||||
new TestDebuggerTargetTraceMapper(mb.testProcess1));
|
createTargetTraceMapper(mb.testProcess1));
|
||||||
|
|
||||||
TraceThread thread = waitForValue(() -> recorder.getTraceThread(mb.testThread1));
|
TraceThread thread = waitForValue(() -> recorder.getTraceThread(mb.testThread1));
|
||||||
Trace trace = recorder.getTrace();
|
Trace trace = recorder.getTrace();
|
||||||
@@ -93,7 +93,7 @@ public class TraceRecorderAsyncPcodeExecTest extends AbstractGhidraHeadedDebugge
|
|||||||
"r1", new byte[] { 6 })));
|
"r1", new byte[] { 6 })));
|
||||||
|
|
||||||
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
|
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
|
||||||
new TestDebuggerTargetTraceMapper(mb.testProcess1));
|
createTargetTraceMapper(mb.testProcess1));
|
||||||
|
|
||||||
TraceThread thread = waitForValue(() -> recorder.getTraceThread(mb.testThread1));
|
TraceThread thread = waitForValue(() -> recorder.getTraceThread(mb.testThread1));
|
||||||
Trace trace = recorder.getTrace();
|
Trace trace = recorder.getTrace();
|
||||||
|
|||||||
+11
@@ -718,6 +718,17 @@ public interface TargetObjectSchema {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the nearest ancestor implementing the given interface along the given path
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* If the given path implements the interface, it is returned, i.e., it is not strictly an
|
||||||
|
* ancestor.
|
||||||
|
*
|
||||||
|
* @param type the interface to search for
|
||||||
|
* @param path the seed path
|
||||||
|
* @return the found path, or {@code null} if no ancestor implements the interface
|
||||||
|
*/
|
||||||
default List<String> searchForAncestor(Class<? extends TargetObject> type, List<String> path) {
|
default List<String> searchForAncestor(Class<? extends TargetObject> type, List<String> path) {
|
||||||
for (; path != null; path = PathUtils.parent(path)) {
|
for (; path != null; path = PathUtils.parent(path)) {
|
||||||
TargetObjectSchema schema = getSuccessorSchema(path);
|
TargetObjectSchema schema = getSuccessorSchema(path);
|
||||||
|
|||||||
@@ -38,6 +38,23 @@ public class PathMatcher implements PathPredicates {
|
|||||||
return String.format("<PathMatcher\n %s\n>", StringUtils.join(patterns, "\n "));
|
return String.format("<PathMatcher\n %s\n>", StringUtils.join(patterns, "\n "));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PathPredicates or(PathPredicates that) {
|
||||||
|
PathMatcher result = new PathMatcher();
|
||||||
|
result.patterns.addAll(this.patterns);
|
||||||
|
if (that instanceof PathMatcher) {
|
||||||
|
PathMatcher matcher = (PathMatcher) that;
|
||||||
|
result.patterns.addAll(matcher.patterns);
|
||||||
|
}
|
||||||
|
else if (that instanceof PathPattern) {
|
||||||
|
result.patterns.add((PathPattern) that);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new AssertionError();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO: We could probably do a lot better, esp. for many patterns, by using a trie.
|
* TODO: We could probably do a lot better, esp. for many patterns, by using a trie.
|
||||||
*/
|
*/
|
||||||
@@ -81,6 +98,23 @@ public class PathMatcher implements PathPredicates {
|
|||||||
return patterns.iterator().next();
|
return patterns.iterator().next();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> getNextKeys(List<String> path) {
|
||||||
|
Set<String> result = new HashSet<>();
|
||||||
|
for (PathPattern pattern : patterns) {
|
||||||
|
result.addAll(pattern.getNextKeys(path));
|
||||||
|
}
|
||||||
|
if (result.contains("")) {
|
||||||
|
result.removeIf(PathUtils::isName);
|
||||||
|
result.add("");
|
||||||
|
}
|
||||||
|
if (result.contains("[]")) {
|
||||||
|
result.removeIf(PathUtils::isIndex);
|
||||||
|
result.add("[]");
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<String> getNextNames(List<String> path) {
|
public Set<String> getNextNames(List<String> path) {
|
||||||
Set<String> result = new HashSet<>();
|
Set<String> result = new HashSet<>();
|
||||||
@@ -111,10 +145,10 @@ public class PathMatcher implements PathPredicates {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PathMatcher applyIndices(List<String> indices) {
|
public PathMatcher applyKeys(List<String> indices) {
|
||||||
PathMatcher result = new PathMatcher();
|
PathMatcher result = new PathMatcher();
|
||||||
for (PathPattern pat : patterns) {
|
for (PathPattern pat : patterns) {
|
||||||
result.addPattern(pat.applyIndices(indices));
|
result.addPattern(pat.applyKeys(indices));
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,26 +62,33 @@ public class PathPattern implements PathPredicates {
|
|||||||
return pattern.hashCode();
|
return pattern.hashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PathPredicates or(PathPredicates that) {
|
||||||
|
if (this.equals(that)) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
PathMatcher result = new PathMatcher();
|
||||||
|
result.addPattern(this);
|
||||||
|
if (that instanceof PathPattern) {
|
||||||
|
result.addPattern(this);
|
||||||
|
}
|
||||||
|
else if (that instanceof PathMatcher) {
|
||||||
|
PathMatcher matcher = (PathMatcher) that;
|
||||||
|
result.patterns.addAll(matcher.patterns);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new AssertionError();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean isWildcard(String pat) {
|
public static boolean isWildcard(String pat) {
|
||||||
return "[]".equals(pat) || "".equals(pat);
|
return "[]".equals(pat) || "".equals(pat);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean keyMatches(String pat, String key) {
|
|
||||||
if (key.equals(pat)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if ("[]".equals(pat) && PathUtils.isIndex(key)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if ("".equals(pat) && PathUtils.isName(key)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean matchesUpTo(List<String> path, int length) {
|
protected boolean matchesUpTo(List<String> path, int length) {
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
if (!keyMatches(pattern.get(i), path.get(i))) {
|
if (!PathPredicates.keyMatches(pattern.get(i), path.get(i))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -144,11 +151,25 @@ public class PathPattern implements PathPredicates {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> getNextKeys(List<String> path) {
|
||||||
|
if (path.size() >= pattern.size()) {
|
||||||
|
return Set.of();
|
||||||
|
}
|
||||||
|
if (!matchesUpTo(path, path.size())) {
|
||||||
|
return Set.of();
|
||||||
|
}
|
||||||
|
return Set.of(pattern.get(path.size()));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<String> getNextNames(List<String> path) {
|
public Set<String> getNextNames(List<String> path) {
|
||||||
if (path.size() >= pattern.size()) {
|
if (path.size() >= pattern.size()) {
|
||||||
return Set.of();
|
return Set.of();
|
||||||
}
|
}
|
||||||
|
if (!matchesUpTo(path, path.size())) {
|
||||||
|
return Set.of();
|
||||||
|
}
|
||||||
String pat = pattern.get(path.size());
|
String pat = pattern.get(path.size());
|
||||||
if (PathUtils.isName(pat)) {
|
if (PathUtils.isName(pat)) {
|
||||||
return Set.of(pat);
|
return Set.of(pat);
|
||||||
@@ -161,6 +182,9 @@ public class PathPattern implements PathPredicates {
|
|||||||
if (path.size() >= pattern.size()) {
|
if (path.size() >= pattern.size()) {
|
||||||
return Set.of();
|
return Set.of();
|
||||||
}
|
}
|
||||||
|
if (!matchesUpTo(path, path.size())) {
|
||||||
|
return Set.of();
|
||||||
|
}
|
||||||
String pat = pattern.get(path.size());
|
String pat = pattern.get(path.size());
|
||||||
if (PathUtils.isIndex(pat)) {
|
if (PathUtils.isIndex(pat)) {
|
||||||
return Set.of(PathUtils.parseIndex(pat));
|
return Set.of(PathUtils.parseIndex(pat));
|
||||||
@@ -174,7 +198,7 @@ public class PathPattern implements PathPredicates {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PathPattern applyIndices(List<String> indices) {
|
public PathPattern applyKeys(List<String> indices) {
|
||||||
List<String> result = new ArrayList<>(pattern.size());
|
List<String> result = new ArrayList<>(pattern.size());
|
||||||
Iterator<String> it = indices.iterator();
|
Iterator<String> it = indices.iterator();
|
||||||
for (String pat : pattern) {
|
for (String pat : pattern) {
|
||||||
@@ -196,18 +220,18 @@ public class PathPattern implements PathPredicates {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the given path matches, extract indices where matched by wildcards
|
* If the given path matches, extract keys where matched by wildcards
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* This is essentially the inverse of {@link #applyIndices(List)}, but can only be asked of one
|
* This is essentially the inverse of {@link #applyKeys(List)}, but can only be asked of one
|
||||||
* pattern. The keys are returned from left to right, in the order matched by the pattern. Only
|
* pattern. The keys are returned from left to right, in the order matched by the pattern. Only
|
||||||
* those keys matched by a wildcard are included in the result. Indices are extracted with the
|
* those keys matched by a wildcard are included in the result. Indices are extracted with the
|
||||||
* brackets {@code []} removed.
|
* brackets {@code []} removed.
|
||||||
*
|
*
|
||||||
* @param path the path to match
|
* @param path the path to match
|
||||||
* @return the list of matched indices or {@code null} if not matched
|
* @return the list of matched keys or {@code null} if not matched
|
||||||
*/
|
*/
|
||||||
public List<String> matchIndices(List<String> path) {
|
public List<String> matchKeys(List<String> path) {
|
||||||
int length = pattern.size();
|
int length = pattern.size();
|
||||||
if (length != path.size()) {
|
if (length != path.size()) {
|
||||||
return null;
|
return null;
|
||||||
@@ -216,7 +240,7 @@ public class PathPattern implements PathPredicates {
|
|||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
String pat = pattern.get(i);
|
String pat = pattern.get(i);
|
||||||
String key = path.get(i);
|
String key = path.get(i);
|
||||||
if (!keyMatches(pat, key)) {
|
if (!PathPredicates.keyMatches(pat, key)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (isWildcard(pat)) {
|
if (isWildcard(pat)) {
|
||||||
|
|||||||
+51
-18
@@ -23,6 +23,38 @@ import ghidra.dbg.target.TargetObject;
|
|||||||
import ghidra.dbg.util.PathUtils.PathComparator;
|
import ghidra.dbg.util.PathUtils.PathComparator;
|
||||||
|
|
||||||
public interface PathPredicates {
|
public interface PathPredicates {
|
||||||
|
|
||||||
|
static boolean keyMatches(String pat, String key) {
|
||||||
|
if (key.equals(pat)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ("[]".equals(pat)) {
|
||||||
|
return PathUtils.isIndex(key);
|
||||||
|
}
|
||||||
|
if ("".equals(pat)) {
|
||||||
|
return PathUtils.isName(key);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean anyMatches(Set<String> pats, String key) {
|
||||||
|
return pats.stream().anyMatch(p -> keyMatches(p, key));
|
||||||
|
}
|
||||||
|
|
||||||
|
static PathPredicates pattern(String... keyPatterns) {
|
||||||
|
return new PathPattern(List.of(keyPatterns));
|
||||||
|
}
|
||||||
|
|
||||||
|
static PathPredicates pattern(List<String> keyPatterns) {
|
||||||
|
return new PathPattern(keyPatterns);
|
||||||
|
}
|
||||||
|
|
||||||
|
static PathPredicates parse(String pattern) {
|
||||||
|
return new PathPattern(PathUtils.parse(pattern));
|
||||||
|
}
|
||||||
|
|
||||||
|
PathPredicates or(PathPredicates that);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the entire path passes
|
* Check if the entire path passes
|
||||||
*
|
*
|
||||||
@@ -59,10 +91,22 @@ public interface PathPredicates {
|
|||||||
boolean ancestorMatches(List<String> path, boolean strict);
|
boolean ancestorMatches(List<String> path, boolean strict);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Assuming a successor of path could match, get the patterns for the next possible key
|
* Get the patterns for the next possible key
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* If the pattern could accept a name next, get all patterns describing those names
|
* If a successor of the given path cannot match this pattern, the empty set is returned.
|
||||||
|
*
|
||||||
|
* @param path the ancestor path
|
||||||
|
* @return a set of patterns where indices are enclosed in brackets ({@code [])
|
||||||
|
*/
|
||||||
|
Set<String> getNextKeys(List<String> path);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the patterns for the next possible name
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* If a successor of the given path cannot match this pattern, the empty set is returned. If the
|
||||||
|
* pattern could accept a name next, get all patterns describing those names
|
||||||
*
|
*
|
||||||
* @param path the ancestor path
|
* @param path the ancestor path
|
||||||
* @return a set of patterns
|
* @return a set of patterns
|
||||||
@@ -73,10 +117,11 @@ public interface PathPredicates {
|
|||||||
* Assuming a successor of path could match, get the patterns for the next possible index
|
* Assuming a successor of path could match, get the patterns for the next possible index
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* If the pattern could accept an index next, get all patterns describing those indices
|
* If a successor of the given path cannot match this pattern, the empty set is returned. If the
|
||||||
|
* pattern could accept an index next, get all patterns describing those indices
|
||||||
*
|
*
|
||||||
* @param path the ancestor path
|
* @param path the ancestor path
|
||||||
* @return a set of patterns, without brack@Override ets ({@code [])
|
* @return a set of patterns, without brackets ({@code [])
|
||||||
*/
|
*/
|
||||||
Set<String> getNextIndices(List<String> path);
|
Set<String> getNextIndices(List<String> path);
|
||||||
|
|
||||||
@@ -94,18 +139,6 @@ public interface PathPredicates {
|
|||||||
*/
|
*/
|
||||||
PathPattern getSingletonPattern();
|
PathPattern getSingletonPattern();
|
||||||
|
|
||||||
static boolean anyMatches(Set<String> pats, String key) {
|
|
||||||
for (String pat : pats) {
|
|
||||||
if ("".equals(pat)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (key.equals(pat)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
default NavigableMap<List<String>, ?> getCachedValues(TargetObject seed) {
|
default NavigableMap<List<String>, ?> getCachedValues(TargetObject seed) {
|
||||||
return getCachedValues(List.of(), seed);
|
return getCachedValues(List.of(), seed);
|
||||||
}
|
}
|
||||||
@@ -259,10 +292,10 @@ public interface PathPredicates {
|
|||||||
* @param indices the indices to substitute
|
* @param indices the indices to substitute
|
||||||
* @return the pattern or matcher with the applied substitutions
|
* @return the pattern or matcher with the applied substitutions
|
||||||
*/
|
*/
|
||||||
PathPredicates applyIndices(List<String> indices);
|
PathPredicates applyKeys(List<String> indices);
|
||||||
|
|
||||||
default PathPredicates applyIndices(String... indices) {
|
default PathPredicates applyIndices(String... indices) {
|
||||||
return applyIndices(List.of(indices));
|
return applyKeys(List.of(indices));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user