mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 18:29:37 +02:00
GP-2676: Breakpoints can now be placed in emulator with Sleigh injections or custom conditions.
This commit is contained in:
parent
df0274a4d7
commit
888c8c911d
116 changed files with 5676 additions and 1993 deletions
|
@ -59,7 +59,7 @@ public enum TraceSleighUtils {
|
|||
new DirectBytesTracePcodeExecutorState(platform, snap, thread, frame);
|
||||
Language language = platform.getLanguage();
|
||||
if (!(language instanceof SleighLanguage)) {
|
||||
throw new IllegalArgumentException("TracePlatform must use a SLEIGH language");
|
||||
throw new IllegalArgumentException("TracePlatform must use a Sleigh language");
|
||||
}
|
||||
return new PcodeExecutor<>((SleighLanguage) language,
|
||||
BytesPcodeArithmetic.forLanguage(language), state, Reason.INSPECT);
|
||||
|
@ -99,7 +99,7 @@ public enum TraceSleighUtils {
|
|||
PcodeExecutorState<Pair<byte[], TraceMemoryState>> paired = state.withMemoryState();
|
||||
Language language = platform.getLanguage();
|
||||
if (!(language instanceof SleighLanguage)) {
|
||||
throw new IllegalArgumentException("TracePlatform must use a SLEIGH language");
|
||||
throw new IllegalArgumentException("TracePlatform must use a Sleigh language");
|
||||
}
|
||||
return new PcodeExecutor<>((SleighLanguage) language, new PairedPcodeArithmetic<>(
|
||||
BytesPcodeArithmetic.forLanguage(language), TraceMemoryStatePcodeArithmetic.INSTANCE),
|
||||
|
|
|
@ -19,6 +19,7 @@ import java.io.IOException;
|
|||
import java.util.*;
|
||||
|
||||
import db.DBRecord;
|
||||
import ghidra.pcode.exec.SleighUtils;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.trace.database.DBTrace;
|
||||
import ghidra.trace.database.DBTraceUtils;
|
||||
|
@ -38,19 +39,21 @@ import ghidra.util.database.DBObjectColumn;
|
|||
import ghidra.util.database.annot.*;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
|
||||
@DBAnnotatedObjectInfo(version = 0)
|
||||
@DBAnnotatedObjectInfo(version = 1)
|
||||
public class DBTraceBreakpoint
|
||||
extends AbstractDBTraceAddressSnapRangePropertyMapData<DBTraceBreakpoint>
|
||||
implements TraceBreakpoint {
|
||||
protected static final String TABLE_NAME = "Breakpoints";
|
||||
|
||||
private static final byte ENABLED_MASK = (byte) (1 << 7);
|
||||
private static final byte EMU_ENABLED_MASK = (byte) (1 << 6);
|
||||
|
||||
static final String PATH_COLUMN_NAME = "Path";
|
||||
static final String NAME_COLUMN_NAME = "Name";
|
||||
static final String THREADS_COLUMN_NAME = "Threads";
|
||||
static final String FLAGS_COLUMN_NAME = "Flags";
|
||||
static final String COMMENT_COLUMN_NAME = "Comment";
|
||||
static final String SLEIGH_COLUMN_NAME = "Sleigh";
|
||||
|
||||
@DBAnnotatedColumn(PATH_COLUMN_NAME)
|
||||
static DBObjectColumn PATH_COLUMN;
|
||||
|
@ -62,6 +65,8 @@ public class DBTraceBreakpoint
|
|||
static DBObjectColumn FLAGS_COLUMN;
|
||||
@DBAnnotatedColumn(COMMENT_COLUMN_NAME)
|
||||
static DBObjectColumn COMMENT_COLUMN;
|
||||
@DBAnnotatedColumn(SLEIGH_COLUMN_NAME)
|
||||
static DBObjectColumn SLEIGH_COLUMN;
|
||||
|
||||
protected static String tableName(AddressSpace space, long threadKey) {
|
||||
return DBTraceUtils.tableName(TABLE_NAME, space, threadKey, 0);
|
||||
|
@ -77,10 +82,13 @@ public class DBTraceBreakpoint
|
|||
private byte flagsByte;
|
||||
@DBAnnotatedField(column = COMMENT_COLUMN_NAME)
|
||||
private String comment;
|
||||
@DBAnnotatedField(column = SLEIGH_COLUMN_NAME)
|
||||
private String emuSleigh;
|
||||
|
||||
private final Set<TraceBreakpointKind> kinds = EnumSet.noneOf(TraceBreakpointKind.class);
|
||||
private final Set<TraceBreakpointKind> kindsView = Collections.unmodifiableSet(kinds);
|
||||
private boolean enabled;
|
||||
private boolean emuEnabled;
|
||||
|
||||
protected final DBTraceBreakpointSpace space;
|
||||
|
||||
|
@ -108,7 +116,7 @@ public class DBTraceBreakpoint
|
|||
}
|
||||
}
|
||||
enabled = (flagsByte & ENABLED_MASK) != 0;
|
||||
// Msg.debug(this, "trace: breakpoint " + this + " enabled=" + enabled + ", because doFresh");
|
||||
emuEnabled = (flagsByte & EMU_ENABLED_MASK) != 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -127,7 +135,8 @@ public class DBTraceBreakpoint
|
|||
}
|
||||
|
||||
public void set(String path, String name, Collection<TraceThread> threads,
|
||||
Collection<TraceBreakpointKind> kinds, boolean enabled, String comment) {
|
||||
Collection<TraceBreakpointKind> kinds, boolean enabled, boolean emuEnabled,
|
||||
String comment) {
|
||||
// TODO: Check that the threads exist and that each's lifespan covers the breakpoint's
|
||||
// TODO: This would require additional validation any time those are updated
|
||||
// TODO: For efficiency, would also require index of breakpoints by thread
|
||||
|
@ -150,9 +159,13 @@ public class DBTraceBreakpoint
|
|||
if (enabled) {
|
||||
this.flagsByte |= ENABLED_MASK;
|
||||
}
|
||||
if (emuEnabled) {
|
||||
this.flagsByte |= EMU_ENABLED_MASK;
|
||||
}
|
||||
this.comment = comment;
|
||||
update(PATH_COLUMN, NAME_COLUMN, THREADS_COLUMN, FLAGS_COLUMN, COMMENT_COLUMN);
|
||||
this.enabled = enabled;
|
||||
this.emuEnabled = emuEnabled;
|
||||
// Msg.debug(this, "trace: breakpoint " + this + " enabled=" + enabled + ", because set");
|
||||
}
|
||||
|
||||
|
@ -360,6 +373,17 @@ public class DBTraceBreakpoint
|
|||
update(FLAGS_COLUMN);
|
||||
}
|
||||
|
||||
protected void doSetEmuEnabled(boolean emuEnabled) {
|
||||
this.emuEnabled = emuEnabled;
|
||||
if (emuEnabled) {
|
||||
flagsByte |= EMU_ENABLED_MASK;
|
||||
}
|
||||
else {
|
||||
flagsByte &= ~EMU_ENABLED_MASK;
|
||||
}
|
||||
update(FLAGS_COLUMN);
|
||||
}
|
||||
|
||||
protected void doSetKinds(Collection<TraceBreakpointKind> kinds) {
|
||||
for (TraceBreakpointKind k : TraceBreakpointKind.values()) {
|
||||
if (kinds.contains(k)) {
|
||||
|
@ -391,6 +415,23 @@ public class DBTraceBreakpoint
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEmuEnabled(boolean enabled) {
|
||||
try (LockHold hold = LockHold.lock(space.lock.writeLock())) {
|
||||
doSetEmuEnabled(enabled);
|
||||
}
|
||||
space.trace.setChanged(new TraceChangeRecord<>(TraceBreakpointChangeType.CHANGED,
|
||||
space, this));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmuEnabled(long snap) {
|
||||
// NB. Only object mode support per-snap emu-enablement
|
||||
try (LockHold hold = LockHold.lock(space.lock.readLock())) {
|
||||
return emuEnabled;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setKinds(Collection<TraceBreakpointKind> kinds) {
|
||||
try (LockHold hold = LockHold.lock(space.lock.writeLock())) {
|
||||
|
@ -424,6 +465,29 @@ public class DBTraceBreakpoint
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEmuSleigh(String emuSleigh) {
|
||||
try (LockHold hold = LockHold.lock(space.lock.writeLock())) {
|
||||
if (emuSleigh == null || SleighUtils.UNCONDITIONAL_BREAK.equals(emuSleigh)) {
|
||||
this.emuSleigh = null;
|
||||
}
|
||||
else {
|
||||
this.emuSleigh = emuSleigh.trim();
|
||||
}
|
||||
update(SLEIGH_COLUMN);
|
||||
}
|
||||
space.trace.setChanged(new TraceChangeRecord<>(TraceBreakpointChangeType.CHANGED,
|
||||
space, this));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEmuSleigh() {
|
||||
try (LockHold hold = LockHold.lock(space.lock.readLock())) {
|
||||
return emuSleigh == null || emuSleigh.isBlank() ? SleighUtils.UNCONDITIONAL_BREAK
|
||||
: emuSleigh;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete() {
|
||||
space.deleteBreakpoint(this);
|
||||
|
|
|
@ -100,7 +100,7 @@ public class DBTraceBreakpointSpace implements DBTraceSpaceBased {
|
|||
}
|
||||
DBTraceBreakpoint breakpoint =
|
||||
breakpointMapSpace.put(new ImmutableTraceAddressSnapRange(range, lifespan), null);
|
||||
breakpoint.set(path, path, threads, kinds, enabled, comment);
|
||||
breakpoint.set(path, path, threads, kinds, enabled, true, comment);
|
||||
trace.setChanged(
|
||||
new TraceChangeRecord<>(TraceBreakpointChangeType.ADDED, this, breakpoint));
|
||||
return breakpoint;
|
||||
|
|
|
@ -15,13 +15,13 @@
|
|||
*/
|
||||
package ghidra.trace.database.breakpoint;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import ghidra.dbg.target.*;
|
||||
import ghidra.dbg.target.schema.TargetObjectSchema;
|
||||
import ghidra.dbg.util.PathMatcher;
|
||||
import ghidra.pcode.exec.SleighUtils;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressRange;
|
||||
import ghidra.trace.database.target.*;
|
||||
|
@ -208,6 +208,11 @@ public class DBTraceObjectBreakpointLocation
|
|||
object.setValue(Lifespan.span(snap, getClearedSnap()),
|
||||
TargetBreakpointSpec.ENABLED_ATTRIBUTE_NAME, enabled);
|
||||
}
|
||||
Set<TraceBreakpointKind> asSet =
|
||||
kinds instanceof Set<TraceBreakpointKind> yes ? yes : Set.copyOf(kinds);
|
||||
if (!Objects.equals(asSet, getKinds())) {
|
||||
this.setKinds(Lifespan.span(snap, getClearedSnap()), asSet);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
@ -297,8 +302,55 @@ public class DBTraceObjectBreakpointLocation
|
|||
|
||||
@Override
|
||||
public String getComment() {
|
||||
return TraceObjectInterfaceUtils.getValue(object, getPlacedSnap(), KEY_COMMENT,
|
||||
String.class, "");
|
||||
try (LockHold hold = object.getTrace().lockRead()) {
|
||||
return TraceObjectInterfaceUtils.getValue(object, getPlacedSnap(), KEY_COMMENT,
|
||||
String.class, "");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEmuEnabled(Lifespan lifespan, boolean emuEnabled) {
|
||||
object.setValue(lifespan, KEY_EMU_ENABLED, emuEnabled ? null : false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEmuEnabled(boolean emuEnabled) {
|
||||
try (LockHold hold = object.getTrace().lockWrite()) {
|
||||
setEmuEnabled(getLifespan(), emuEnabled);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmuEnabled(long snap) {
|
||||
try (LockHold hold = object.getTrace().lockRead()) {
|
||||
return TraceObjectInterfaceUtils.getValue(object, getPlacedSnap(), KEY_EMU_ENABLED,
|
||||
Boolean.class, true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEmuSleigh(Lifespan lifespan, String sleigh) {
|
||||
if (sleigh == null || SleighUtils.UNCONDITIONAL_BREAK.equals(sleigh)) {
|
||||
object.setValue(lifespan, KEY_EMU_SLEIGH, null);
|
||||
}
|
||||
else {
|
||||
object.setValue(lifespan, KEY_EMU_SLEIGH, sleigh.trim());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEmuSleigh(String sleigh) {
|
||||
try (LockHold hold = object.getTrace().lockWrite()) {
|
||||
setEmuSleigh(getLifespan(), sleigh);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEmuSleigh() {
|
||||
try (LockHold hold = object.getTrace().lockRead()) {
|
||||
return TraceObjectInterfaceUtils.getValue(object, getPlacedSnap(), KEY_EMU_SLEIGH,
|
||||
String.class, SleighUtils.UNCONDITIONAL_BREAK);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -131,7 +131,8 @@ public class DBTraceObjectBreakpointSpec
|
|||
@Override
|
||||
public void setEnabled(boolean enabled) {
|
||||
try (LockHold hold = object.getTrace().lockWrite()) {
|
||||
object.setValue(getLifespan(), TargetBreakpointSpec.ENABLED_ATTRIBUTE_NAME, enabled);
|
||||
object.setValue(getLifespan(), TargetBreakpointSpec.ENABLED_ATTRIBUTE_NAME,
|
||||
enabled ? true : null);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -190,6 +191,26 @@ public class DBTraceObjectBreakpointSpec
|
|||
throw new UnsupportedOperationException("Ask a location instead");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEmuEnabled(boolean enabled) {
|
||||
throw new UnsupportedOperationException("Set on a location instead");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmuEnabled(long snap) {
|
||||
throw new UnsupportedOperationException("Ask a location instead");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEmuSleigh(String sleigh) {
|
||||
throw new UnsupportedOperationException("Set on a location instead");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEmuSleigh() {
|
||||
throw new UnsupportedOperationException("Ask a location instead");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete() {
|
||||
try (LockHold hold = object.getTrace().lockWrite()) {
|
||||
|
|
|
@ -53,6 +53,16 @@ import resources.ResourceManager;
|
|||
public interface Trace extends DataTypeManagerDomainObject {
|
||||
ImageIcon TRACE_ICON = ResourceManager.loadImage("images/video-x-generic16.png");
|
||||
|
||||
/**
|
||||
* TEMPORARY: An a/b switch while both table- (legacy) and object-mode traces are supported
|
||||
*
|
||||
* @param trace the trace, or null
|
||||
* @return true if the trace is non-null and has no root schema
|
||||
*/
|
||||
public static boolean isLegacy(Trace trace) {
|
||||
return trace != null && trace.getObjectManager().getRootSchema() == null;
|
||||
}
|
||||
|
||||
public static final class TraceObjectChangeType<T, U>
|
||||
extends DefaultTraceChangeType<T, U> {
|
||||
/**
|
||||
|
|
|
@ -28,7 +28,6 @@ import ghidra.util.exception.DuplicateNameException;
|
|||
* A breakpoint in a trace
|
||||
*/
|
||||
public interface TraceBreakpoint extends TraceUniqueObject {
|
||||
|
||||
/**
|
||||
* Get the trace containing this breakpoint
|
||||
*
|
||||
|
@ -161,10 +160,30 @@ public interface TraceBreakpoint extends TraceUniqueObject {
|
|||
/**
|
||||
* Check whether this breakpoint is enabled or disabled at the given snap
|
||||
*
|
||||
* @param snap the snap
|
||||
* @return true if enabled, false if disabled
|
||||
*/
|
||||
boolean isEnabled(long snap);
|
||||
|
||||
/**
|
||||
* Set whether this breakpoint is enabled or disabled for emulation
|
||||
*
|
||||
* <p>
|
||||
* This change applies to the entire lifespan of the record. It's not intended to record a
|
||||
* history, but to toggle the breakpoint in the integrated emulator.
|
||||
*
|
||||
* @param enabled true if enabled, false if disabled
|
||||
*/
|
||||
void setEmuEnabled(boolean enabled);
|
||||
|
||||
/**
|
||||
* Check whether this breakpoint is enabled or disabled for emulation at the given snap
|
||||
*
|
||||
* @param snap the snap
|
||||
* @return true if enabled, false if disabled
|
||||
*/
|
||||
boolean isEmuEnabled(long snap);
|
||||
|
||||
/**
|
||||
* Set the kinds included in this breakpoint
|
||||
*
|
||||
|
@ -213,6 +232,36 @@ public interface TraceBreakpoint extends TraceUniqueObject {
|
|||
*/
|
||||
String getComment();
|
||||
|
||||
/**
|
||||
* Set Sleigh source to replace the breakpointed instruction in emulation
|
||||
*
|
||||
* <p>
|
||||
* The default is simply "<code>{@link PcodeEmulationLibrary#emu_swi() emu_swi()};
|
||||
* {@link PcodeEmulationLibrary#emu_exec_decoded() emu_exec_decoded()};</code>", effectively a
|
||||
* non-conditional breakpoint followed by execution of the actual instruction. Modifying this
|
||||
* allows clients to create conditional breakpoints or simply override or inject additional
|
||||
* logic into an emulated target.
|
||||
*
|
||||
* <p>
|
||||
* <b>NOTE:</b> This current has no effect on access breakpoints, but only execution
|
||||
* breakpoints.
|
||||
*
|
||||
* <p>
|
||||
* If the specified source fails to compile during emulator set-up, this will fall back to
|
||||
* {@link PcodeEmulationLibrary#emu_err
|
||||
*
|
||||
* @see #DEFAULT_SLEIGH
|
||||
* @param sleigh the Sleigh source
|
||||
*/
|
||||
void setEmuSleigh(String sleigh);
|
||||
|
||||
/**
|
||||
* Get the Sleigh source that replaces the breakpointed instruction in emulation
|
||||
*
|
||||
* @return the Sleigh source
|
||||
*/
|
||||
String getEmuSleigh();
|
||||
|
||||
/**
|
||||
* Delete this breakpoint from the trace
|
||||
*/
|
||||
|
|
|
@ -37,6 +37,8 @@ public enum TraceBreakpointKind {
|
|||
HW_EXECUTE(1 << 2),
|
||||
SW_EXECUTE(1 << 3);
|
||||
|
||||
public static final int COUNT = values().length;
|
||||
|
||||
public static class TraceBreakpointKindSet extends AbstractSetDecorator<TraceBreakpointKind> {
|
||||
public static final TraceBreakpointKindSet SW_EXECUTE = of(TraceBreakpointKind.SW_EXECUTE);
|
||||
public static final TraceBreakpointKindSet HW_EXECUTE = of(TraceBreakpointKind.HW_EXECUTE);
|
||||
|
|
|
@ -32,9 +32,12 @@ import ghidra.util.exception.DuplicateNameException;
|
|||
TargetObject.DISPLAY_ATTRIBUTE_NAME,
|
||||
TargetBreakpointLocation.RANGE_ATTRIBUTE_NAME,
|
||||
TraceObjectBreakpointLocation.KEY_COMMENT,
|
||||
TraceObjectBreakpointLocation.KEY_EMU_ENABLED,
|
||||
})
|
||||
public interface TraceObjectBreakpointLocation extends TraceBreakpoint, TraceObjectInterface {
|
||||
String KEY_COMMENT = "_comment";
|
||||
String KEY_EMU_ENABLED = "_emu_enabled";
|
||||
String KEY_EMU_SLEIGH = "_emu_sleigh";
|
||||
|
||||
TraceObjectBreakpointSpec getSpecification();
|
||||
|
||||
|
@ -48,5 +51,9 @@ public interface TraceObjectBreakpointLocation extends TraceBreakpoint, TraceObj
|
|||
|
||||
void setEnabled(Lifespan lifespan, boolean enabled);
|
||||
|
||||
void setEmuEnabled(Lifespan lifespan, boolean emuEnabled);
|
||||
|
||||
void setEmuSleigh(Lifespan lifespan, String sleigh);
|
||||
|
||||
void setComment(Lifespan lifespan, String comment);
|
||||
}
|
||||
|
|
|
@ -132,14 +132,16 @@ public interface Scheduler {
|
|||
}
|
||||
catch (PcodeExecutionException e) {
|
||||
completedSteps = completedSteps.steppedForward(eventThread, completedTicks);
|
||||
if (emuThread.getInstruction() == null) {
|
||||
PcodeFrame frame = emuThread.getFrame();
|
||||
if (frame == null) {
|
||||
return new RecordRunResult(completedSteps, e);
|
||||
}
|
||||
PcodeFrame frame = e.getFrame();
|
||||
// Rewind one so stepping retries the op causing the error
|
||||
int count = frame.count() - 1;
|
||||
if (frame == null || count == 0) {
|
||||
// If we've decoded, but could execute the first op, just drop the p-code steps
|
||||
frame.stepBack();
|
||||
int count = frame.count();
|
||||
if (count == 0) {
|
||||
// If we've decoded, but could not execute the first op, just drop the p-code steps
|
||||
emuThread.dropInstruction();
|
||||
return new RecordRunResult(completedSteps, e);
|
||||
}
|
||||
// The +1 accounts for the decode step
|
||||
|
|
|
@ -18,6 +18,7 @@ package ghidra.trace.model.time.schedule;
|
|||
import java.util.*;
|
||||
|
||||
import ghidra.pcode.emu.PcodeMachine;
|
||||
import ghidra.pcode.emu.PcodeMachine.SwiMode;
|
||||
import ghidra.program.model.lang.Language;
|
||||
import ghidra.trace.model.Trace;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
|
@ -25,9 +26,18 @@ import ghidra.trace.model.time.TraceSnapshot;
|
|||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
/**
|
||||
* A sequence of emulator stepping commands, essentially comprising a "point in time."
|
||||
*/
|
||||
public class TraceSchedule implements Comparable<TraceSchedule> {
|
||||
public static final TraceSchedule ZERO = TraceSchedule.snap(0);
|
||||
|
||||
/**
|
||||
* Create a schedule that consists solely of a snapshot
|
||||
*
|
||||
* @param snap the snapshot key
|
||||
* @return the schedule
|
||||
*/
|
||||
public static final TraceSchedule snap(long snap) {
|
||||
return new TraceSchedule(snap, new Sequence(), new Sequence());
|
||||
}
|
||||
|
@ -337,11 +347,10 @@ public class TraceSchedule implements Comparable<TraceSchedule> {
|
|||
*/
|
||||
public void execute(Trace trace, PcodeMachine<?> machine, TaskMonitor monitor)
|
||||
throws CancelledException {
|
||||
machine.setSoftwareInterruptMode(SwiMode.IGNORE_ALL);
|
||||
TraceThread lastThread = getEventThread(trace);
|
||||
lastThread =
|
||||
steps.execute(trace, lastThread, machine, Stepper.instruction(), monitor);
|
||||
lastThread =
|
||||
pSteps.execute(trace, lastThread, machine, Stepper.pcode(), monitor);
|
||||
lastThread = steps.execute(trace, lastThread, machine, Stepper.instruction(), monitor);
|
||||
lastThread = pSteps.execute(trace, lastThread, machine, Stepper.pcode(), monitor);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -380,6 +389,7 @@ public class TraceSchedule implements Comparable<TraceSchedule> {
|
|||
TaskMonitor monitor) throws CancelledException {
|
||||
TraceThread lastThread = position.getLastThread(trace);
|
||||
Sequence remains = steps.relativize(position.steps);
|
||||
machine.setSoftwareInterruptMode(SwiMode.IGNORE_ALL);
|
||||
if (remains.isNop()) {
|
||||
Sequence pRemains = this.pSteps.relativize(position.pSteps);
|
||||
lastThread =
|
||||
|
@ -388,8 +398,7 @@ public class TraceSchedule implements Comparable<TraceSchedule> {
|
|||
else {
|
||||
lastThread =
|
||||
remains.execute(trace, lastThread, machine, Stepper.instruction(), monitor);
|
||||
lastThread =
|
||||
pSteps.execute(trace, lastThread, machine, Stepper.pcode(), monitor);
|
||||
lastThread = pSteps.execute(trace, lastThread, machine, Stepper.pcode(), monitor);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -46,8 +46,8 @@ public class AbstractTracePcodeEmulatorTest extends AbstractGhidraHeadlessIntegr
|
|||
* <p>
|
||||
* This creates a relatively bare-bones trace with initial state for testing trace
|
||||
* emulation/interpolation. It adds ".text" and "stack" regions, creates a thread, assembles
|
||||
* given instructions, and then executes the given SLEIGH source (in the context of the new
|
||||
* thread) to finish initializing the trace. Note, though given first, the SLEIGH is executed
|
||||
* given instructions, and then executes the given Sleigh source (in the context of the new
|
||||
* thread) to finish initializing the trace. Note, though given first, the Sleigh is executed
|
||||
* after assembly. Thus, it can be used to modify the resulting machine code by modifying the
|
||||
* memory where it was assembled.
|
||||
*
|
||||
|
|
|
@ -312,7 +312,7 @@ public class BytesTracePcodeEmulatorTest extends AbstractTracePcodeEmulatorTest
|
|||
* This may not reflect the semantics of an actual processor in these situations, since they may
|
||||
* have instruction caching. Emulating such semantics is TODO, if at all. NB. This also tests
|
||||
* that PC-relative addressing works, since internally the emulator advances the counter after
|
||||
* execution of each instruction. Addressing is computed by the SLEIGH instruction parser and
|
||||
* execution of each instruction. Addressing is computed by the Sleigh instruction parser and
|
||||
* encoded as a constant deref in the p-code.
|
||||
*/
|
||||
@Test
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue