GP-1208: Implement linux-x86/-amd64 system call simulators

This commit is contained in:
Dan 2022-05-20 11:05:53 -04:00
parent 4b600847eb
commit b33800ecba
144 changed files with 12712 additions and 804 deletions

View file

@ -36,16 +36,12 @@ public abstract class AbstractCheckedTraceCachedWriteBytesPcodeExecutorState
@Override
public byte[] read(long offset, int size) {
RangeSet<UnsignedLong> uninitialized =
cache.getUninitialized(offset, offset + size - 1);
bytes.getUninitialized(offset, offset + size - 1);
if (!uninitialized.isEmpty()) {
size = checkUninitialized(source, space.getAddress(offset), size,
size = checkUninitialized(backing, space.getAddress(offset), size,
addrSet(uninitialized));
if (source != null) {
readUninitializedFromSource(uninitialized);
}
}
return readCached(offset, size);
return super.read(offset, size);
}
}
@ -55,10 +51,10 @@ public abstract class AbstractCheckedTraceCachedWriteBytesPcodeExecutorState
}
@Override
protected CachedSpace newSpace(AddressSpace space, TraceMemorySpace source, long snap) {
return new CheckedCachedSpace(language, space, source, snap);
protected CachedSpace newSpace(AddressSpace space, TraceMemorySpace backing) {
return new CheckedCachedSpace(language, space, backing, snap);
}
protected abstract int checkUninitialized(TraceMemorySpace source, Address start, int size,
protected abstract int checkUninitialized(TraceMemorySpace backing, Address start, int size,
AddressSet uninitialized);
}

View file

@ -1,26 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.exec.trace;
public interface BytesPcodeExecutorStateMixin<A, T> {
T fromConstant(long constant);
long offsetToLong(A offset);
byte[] toBytes(T val, int size);
T fromBytes(byte[] data);
}

View file

@ -39,16 +39,16 @@ public class RequireIsKnownTraceCachedWriteBytesPcodeExecutorState
}
@Override
protected int checkUninitialized(TraceMemorySpace source, Address start, int size,
protected int checkUninitialized(TraceMemorySpace backing, Address start, int size,
AddressSet uninitialized) {
if (source == null) {
if (backing == null) {
if (!uninitialized.contains(start)) {
return (int) uninitialized.getMinAddress().subtract(start);
}
throw excFor(uninitialized);
}
// TODO: Could find first instead?
AddressSetView unknown = uninitialized.subtract(getKnown(source));
AddressSetView unknown = uninitialized.subtract(getKnown(backing));
if (unknown.isEmpty()) {
return size;
}

View file

@ -16,27 +16,20 @@
package ghidra.pcode.exec.trace;
import java.nio.ByteBuffer;
import java.util.*;
import com.google.common.collect.*;
import com.google.common.primitives.UnsignedLong;
import ghidra.generic.util.datastruct.SemisparseByteArray;
import ghidra.pcode.exec.AbstractLongOffsetPcodeExecutorState;
import ghidra.pcode.exec.BytesPcodeArithmetic;
import ghidra.pcode.exec.AbstractBytesPcodeExecutorState;
import ghidra.pcode.exec.BytesPcodeExecutorStateSpace;
import ghidra.pcode.exec.trace.TraceCachedWriteBytesPcodeExecutorState.CachedSpace;
import ghidra.pcode.utils.Utils;
import ghidra.program.model.address.*;
import ghidra.program.model.address.AddressSet;
import ghidra.program.model.address.AddressSpace;
import ghidra.program.model.lang.Language;
import ghidra.program.model.lang.Register;
import ghidra.program.model.mem.MemBuffer;
import ghidra.program.model.mem.Memory;
import ghidra.trace.model.Trace;
import ghidra.trace.model.memory.TraceMemorySpace;
import ghidra.trace.model.thread.TraceThread;
import ghidra.trace.util.MemBufferAdapter;
import ghidra.util.MathUtilities;
import ghidra.util.Msg;
/**
* A state which reads bytes from a trace, but caches writes internally.
@ -47,41 +40,7 @@ import ghidra.util.Msg;
* later time.
*/
public class TraceCachedWriteBytesPcodeExecutorState
extends AbstractLongOffsetPcodeExecutorState<byte[], CachedSpace> {
protected class StateMemBuffer implements MemBufferAdapter {
protected final Address address;
protected final CachedSpace source;
public StateMemBuffer(Address address, CachedSpace source) {
this.address = address;
this.source = source;
}
@Override
public Address getAddress() {
return address;
}
@Override
public Memory getMemory() {
return null;
}
@Override
public boolean isBigEndian() {
return trace.getBaseLanguage().isBigEndian();
}
@Override
public int getBytes(ByteBuffer buffer, int addressOffset) {
byte[] data = source.read(address.getOffset() + addressOffset, buffer.remaining());
buffer.put(data);
return data.length;
}
}
protected final Map<AddressSpace, CachedSpace> spaces = new HashMap<>();
extends AbstractBytesPcodeExecutorState<TraceMemorySpace, CachedSpace> {
protected final Trace trace;
protected final long snap;
@ -90,136 +49,53 @@ public class TraceCachedWriteBytesPcodeExecutorState
public TraceCachedWriteBytesPcodeExecutorState(Trace trace, long snap, TraceThread thread,
int frame) {
super(trace.getBaseLanguage(), BytesPcodeArithmetic.forLanguage(trace.getBaseLanguage()));
super(trace.getBaseLanguage());
this.trace = trace;
this.snap = snap;
this.thread = thread;
this.frame = frame;
}
protected static class CachedSpace {
protected final SemisparseByteArray cache = new SemisparseByteArray();
public static class CachedSpace extends BytesPcodeExecutorStateSpace<TraceMemorySpace> {
protected final RangeSet<UnsignedLong> written = TreeRangeSet.create();
protected final Language language; // For logging diagnostic
protected final AddressSpace space;
protected final TraceMemorySpace source;
protected final long snap;
public CachedSpace(Language language, AddressSpace space, TraceMemorySpace source,
public CachedSpace(Language language, AddressSpace space, TraceMemorySpace backing,
long snap) {
this.language = language;
this.space = space;
this.source = source;
super(language, space, backing);
this.snap = snap;
}
public void write(long offset, byte[] buffer, int srcOffset, int length) {
cache.putData(offset, buffer, srcOffset, length);
@Override
public void write(long offset, byte[] val, int srcOffset, int length) {
super.write(offset, val, srcOffset, length);
UnsignedLong uLoc = UnsignedLong.fromLongBits(offset);
UnsignedLong uEnd = UnsignedLong.fromLongBits(offset + length);
written.add(Range.closedOpen(uLoc, uEnd));
}
public static long lower(Range<UnsignedLong> rng) {
return rng.lowerBoundType() == BoundType.CLOSED
? rng.lowerEndpoint().longValue()
: rng.lowerEndpoint().longValue() + 1;
}
public static long upper(Range<UnsignedLong> rng) {
return rng.upperBoundType() == BoundType.CLOSED
? rng.upperEndpoint().longValue()
: rng.upperEndpoint().longValue() - 1;
}
protected void readUninitializedFromSource(RangeSet<UnsignedLong> uninitialized) {
@Override
protected void readUninitializedFromBacking(RangeSet<UnsignedLong> uninitialized) {
if (!uninitialized.isEmpty()) {
// TODO: Warn or bail when reading UNKNOWN bytes
// NOTE: Read without regard to gaps
// NOTE: Cannot write those gaps, though!!!
Range<UnsignedLong> toRead = uninitialized.span();
assert toRead.hasUpperBound() && toRead.hasLowerBound();
long lower = lower(toRead);
long upper = upper(toRead);
ByteBuffer buf = ByteBuffer.allocate((int) (upper - lower + 1));
source.getBytes(snap, space.getAddress(lower), buf);
backing.getBytes(snap, space.getAddress(lower), buf);
for (Range<UnsignedLong> rng : uninitialized.asRanges()) {
long l = lower(rng);
long u = upper(rng);
cache.putData(l, buf.array(), (int) (l - lower), (int) (u - l + 1));
bytes.putData(l, buf.array(), (int) (l - lower), (int) (u - l + 1));
}
}
}
protected byte[] readCached(long offset, int size) {
byte[] data = new byte[size];
cache.getData(offset, data);
return data;
}
protected AddressRange addrRng(Range<UnsignedLong> rng) {
Address start = space.getAddress(lower(rng));
Address end = space.getAddress(upper(rng));
return new AddressRangeImpl(start, end);
}
protected AddressSet addrSet(RangeSet<UnsignedLong> set) {
AddressSet result = new AddressSet();
for (Range<UnsignedLong> rng : set.asRanges()) {
result.add(addrRng(rng));
}
return result;
}
protected Set<Register> getRegs(AddressSet set) {
Set<Register> regs = new TreeSet<>();
for (AddressRange rng : set) {
Register r = language.getRegister(rng.getMinAddress(), (int) rng.getLength());
if (r != null) {
regs.add(r);
}
else {
regs.addAll(Arrays.asList(language.getRegisters(rng.getMinAddress())));
}
}
return regs;
}
protected void warnState(AddressSet set, String message) {
Set<Register> regs = getRegs(set);
if (regs.isEmpty()) {
Msg.warn(this, message + ": " + set);
}
else {
Msg.warn(this, message + ": " + set + " (registers " + regs + ")");
}
}
protected void warnUninit(RangeSet<UnsignedLong> uninit) {
AddressSet uninitialized = addrSet(uninit);
Set<Register> regs = getRegs(uninitialized);
if (regs.isEmpty()) {
Msg.warn(this, "Emulator read from uninitialized state: " + uninit);
}
Msg.warn(this, "Emulator read from uninitialized state: " + uninit +
" (includes registers: " + regs + ")");
}
protected void warnUnknown(AddressSet unknown) {
Set<Register> regs = getRegs(unknown);
Msg.warn(this, "Emulator state initialized from UNKNOWN: " + unknown +
"(includes registers: " + regs + ")");
}
public byte[] read(long offset, int size) {
if (source != null) {
// TODO: Warn or bail when reading UNKNOWN bytes
// NOTE: Read without regard to gaps
// NOTE: Cannot write those gaps, though!!!
readUninitializedFromSource(cache.getUninitialized(offset, offset + size - 1));
}
RangeSet<UnsignedLong> stillUninit = cache.getUninitialized(offset, offset + size - 1);
if (!stillUninit.isEmpty()) {
warnUninit(stillUninit);
}
return readCached(offset, size);
warnAddressSet("Emulator state initialized from UNKNOWN", unknown);
}
// Must already have started a transaction
@ -238,7 +114,7 @@ public class TraceCachedWriteBytesPcodeExecutorState
long fullLen = range.upperEndpoint().longValue() - lower;
while (fullLen > 0) {
int len = MathUtilities.unsignedMin(data.length, fullLen);
cache.getData(lower, data, 0, len);
bytes.getData(lower, data, 0, len);
buf.position(0);
buf.limit(len);
mem.putBytes(snap, space.getAddress(lower), buf);
@ -288,47 +164,12 @@ public class TraceCachedWriteBytesPcodeExecutorState
}
@Override
protected long offsetToLong(byte[] offset) {
return Utils.bytesToLong(offset, offset.length, language.isBigEndian());
protected TraceMemorySpace getBacking(AddressSpace space) {
return TraceSleighUtils.getSpaceForExecution(space, trace, thread, frame, false);
}
@Override
public byte[] longToOffset(AddressSpace space, long l) {
return arithmetic.fromConst(l, space.getPointerSize());
}
protected CachedSpace newSpace(AddressSpace space, TraceMemorySpace source, long snap) {
return new CachedSpace(language, space, source, snap);
}
@Override
protected CachedSpace getForSpace(AddressSpace space, boolean toWrite) {
return spaces.computeIfAbsent(space, s -> {
TraceMemorySpace tms = s.isUniqueSpace() ? null
: TraceSleighUtils.getSpaceForExecution(s, trace, thread, frame, false);
return newSpace(s, tms, snap);
});
}
@Override
protected void setInSpace(CachedSpace space, long offset, int size, byte[] val) {
assert size == val.length;
space.write(offset, val, 0, val.length);
}
@Override
protected byte[] getFromSpace(CachedSpace space, long offset, int size) {
byte[] read = space.read(offset, size);
if (read.length != size) {
Address addr = space.space.getAddress(offset);
throw new UnknownStatePcodeExecutionException("Incomplete read (" + read.length +
" of " + size + " bytes)", language, addr.add(read.length), size - read.length);
}
return read;
}
@Override
public MemBuffer getConcreteBuffer(Address address) {
return new StateMemBuffer(address, getForSpace(address.getAddressSpace(), false));
protected CachedSpace newSpace(AddressSpace space, TraceMemorySpace backing) {
return new CachedSpace(language, space, backing, snap);
}
}

View file

@ -59,4 +59,9 @@ public enum TraceMemoryStatePcodeArithmetic implements PcodeArithmetic<TraceMemo
public BigInteger toConcrete(TraceMemoryState value, boolean isContextreg) {
throw new AssertionError("Cannot make TraceMemoryState a 'concrete value'");
}
@Override
public TraceMemoryState sizeOf(TraceMemoryState value) {
throw new AssertionError("Cannot get size of a TraceMemoryState");
}
}

View file

@ -18,10 +18,9 @@ package ghidra.pcode.exec.trace;
import com.google.common.collect.Range;
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
import ghidra.pcode.emu.AbstractPcodeEmulator;
import ghidra.pcode.emu.PcodeEmulator;
import ghidra.pcode.emu.PcodeThread;
import ghidra.pcode.exec.PcodeExecutorState;
import ghidra.pcode.exec.SleighUseropLibrary;
import ghidra.program.model.lang.Language;
import ghidra.trace.model.Trace;
import ghidra.trace.model.stack.TraceStack;
@ -31,7 +30,7 @@ import ghidra.trace.model.thread.TraceThreadManager;
/**
* An emulator that can read initial state from a trace
*/
public class TracePcodeEmulator extends AbstractPcodeEmulator {
public class TracePcodeEmulator extends PcodeEmulator {
private static SleighLanguage assertSleigh(Language language) {
if (!(language instanceof SleighLanguage)) {
throw new IllegalArgumentException("Emulation requires a sleigh language");
@ -42,16 +41,12 @@ public class TracePcodeEmulator extends AbstractPcodeEmulator {
protected final Trace trace;
protected final long snap;
public TracePcodeEmulator(Trace trace, long snap, SleighUseropLibrary<byte[]> library) {
super(assertSleigh(trace.getBaseLanguage()), library);
public TracePcodeEmulator(Trace trace, long snap) {
super(assertSleigh(trace.getBaseLanguage()));
this.trace = trace;
this.snap = snap;
}
public TracePcodeEmulator(Trace trace, long snap) {
this(trace, snap, SleighUseropLibrary.nil());
}
protected PcodeExecutorState<byte[]> newState(TraceThread thread) {
return new TraceCachedWriteBytesPcodeExecutorState(trace, snap, thread, 0);
}

View file

@ -73,7 +73,7 @@ public enum TraceSleighUtils {
paired);
}
public static byte[] evaluateBytes(SleighExpression expr, Trace trace, long snap,
public static byte[] evaluateBytes(PcodeExpression expr, Trace trace, long snap,
TraceThread thread, int frame) {
SleighLanguage language = expr.getLanguage();
if (trace.getBaseLanguage() != language) {
@ -84,14 +84,14 @@ public enum TraceSleighUtils {
return expr.evaluate(executor);
}
public static BigInteger evaluate(SleighExpression expr, Trace trace, long snap,
public static BigInteger evaluate(PcodeExpression expr, Trace trace, long snap,
TraceThread thread, int frame) {
byte[] bytes = evaluateBytes(expr, trace, snap, thread, frame);
return Utils.bytesToBigInteger(bytes, bytes.length, expr.getLanguage().isBigEndian(),
false);
}
public static Pair<byte[], TraceMemoryState> evaluateBytesWithState(SleighExpression expr,
public static Pair<byte[], TraceMemoryState> evaluateBytesWithState(PcodeExpression expr,
Trace trace, long snap, TraceThread thread, int frame) {
SleighLanguage language = expr.getLanguage();
if (trace.getBaseLanguage() != language) {
@ -104,7 +104,7 @@ public enum TraceSleighUtils {
return expr.evaluate(executor);
}
public static Pair<BigInteger, TraceMemoryState> evaluateWithState(SleighExpression expr,
public static Pair<BigInteger, TraceMemoryState> evaluateWithState(PcodeExpression expr,
Trace trace, long snap, TraceThread thread, int frame) {
Pair<byte[], TraceMemoryState> bytesPair =
evaluateBytesWithState(expr, trace, snap, thread, frame);

View file

@ -28,8 +28,7 @@ import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressRangeImpl;
import ghidra.program.model.lang.Register;
import ghidra.program.model.listing.CodeUnit;
import ghidra.program.model.mem.Memory;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.model.mem.*;
import ghidra.program.model.symbol.*;
import ghidra.trace.database.DBTrace;
import ghidra.trace.database.symbol.DBTraceReference;
@ -40,7 +39,6 @@ import ghidra.trace.model.program.TraceProgramView;
import ghidra.trace.model.symbol.TraceReference;
import ghidra.trace.model.symbol.TraceSymbol;
import ghidra.trace.model.thread.TraceThread;
import ghidra.trace.util.MemBufferAdapter;
import ghidra.util.LockHold;
import ghidra.util.Saveable;
import ghidra.util.exception.NoValueException;

View file

@ -20,8 +20,8 @@ import java.nio.ByteOrder;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressOverflowException;
import ghidra.program.model.mem.MemBufferAdapter;
import ghidra.program.model.mem.Memory;
import ghidra.trace.util.MemBufferAdapter;
public class DBTraceMemBuffer implements MemBufferAdapter {
private final DBTraceMemorySpace space;

View file

@ -370,7 +370,7 @@ public class PatchStep implements Step {
protected Map<AddressSpace, SemisparseByteArray> getPatches(Language language) {
PcodeProgram prog = SleighProgramCompiler.compileProgram((SleighLanguage) language,
"schedule", List.of(sleigh + ";"), SleighUseropLibrary.nil());
"schedule", List.of(sleigh + ";"), PcodeUseropLibrary.nil());
// SemisparseArray is a bit overkill, no?
Map<AddressSpace, SemisparseByteArray> result = new TreeMap<>();
for (PcodeOp op : prog.getCode()) {

View file

@ -1,83 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.trace.util;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import org.apache.commons.lang3.ArrayUtils;
import ghidra.program.model.mem.MemBuffer;
import ghidra.program.model.mem.MemoryAccessException;
public interface MemBufferAdapter extends MemBuffer {
int getBytes(ByteBuffer buffer, int addressOffset);
@Override
default byte getByte(int offset) throws MemoryAccessException {
ByteBuffer buffer = ByteBuffer.allocate(1);
if (getBytes(buffer, offset) < 1) {
throw new MemoryAccessException(
"Couldn't get requested byte for " + getClass().getSimpleName());
}
return buffer.get(0);
}
@Override
default int getBytes(byte[] b, int offset) {
return getBytes(ByteBuffer.wrap(b), offset);
}
default ByteBuffer getBytesInFull(int offset, int len) throws MemoryAccessException {
ByteBuffer buf = ByteBuffer.allocate(len);
if (getBytes(buf, offset) != len) {
throw new MemoryAccessException("Could not read enough bytes");
}
if (!isBigEndian()) {
buf.order(ByteOrder.LITTLE_ENDIAN);
}
return buf;
}
@Override
default short getShort(int offset) throws MemoryAccessException {
return getBytesInFull(offset, Short.BYTES).getShort(0);
}
@Override
default int getInt(int offset) throws MemoryAccessException {
return getBytesInFull(offset, Integer.BYTES).getInt(0);
}
@Override
default long getLong(int offset) throws MemoryAccessException {
return getBytesInFull(offset, Long.BYTES).getLong(0);
}
@Override
default BigInteger getBigInteger(int offset, int size, boolean signed)
throws MemoryAccessException {
byte[] buf = getBytesInFull(offset, size).array();
if (!isBigEndian()) {
ArrayUtils.reverse(buf);
}
if (signed) {
return new BigInteger(buf);
}
return new BigInteger(1, buf);
}
}

View file

@ -94,8 +94,8 @@ public class TracePcodeEmulatorTest extends AbstractGhidraHeadlessIntegrationTes
TraceSleighUtils.buildByteExecutor(tb.trace, 0, thread, 0);
PcodeProgram initProg = SleighProgramCompiler.compileProgram(
(SleighLanguage) tb.language, "test", stateInit,
SleighUseropLibrary.nil());
exec.execute(initProg, SleighUseropLibrary.nil());
PcodeUseropLibrary.nil());
exec.execute(initProg, PcodeUseropLibrary.nil());
}
return thread;
}
@ -476,13 +476,13 @@ public class TracePcodeEmulatorTest extends AbstractGhidraHeadlessIntegrationTes
public void testInject() throws Throwable {
try (ToyDBTraceBuilder tb = new ToyDBTraceBuilder("Test", "x86:LE:64:default")) {
final StringBuilder dumped = new StringBuilder();
SleighUseropLibrary<byte[]> library = new AnnotatedSleighUseropLibrary<byte[]>() {
PcodeUseropLibrary<byte[]> hexLib = new AnnotatedPcodeUseropLibrary<byte[]>() {
@Override
protected Lookup getMethodLookup() {
return MethodHandles.lookup();
}
@SleighUserop
@PcodeUserop
public void hexdump(byte[] in) {
dumped.append(NumericUtilities.convertBytesToString(in));
}
@ -495,7 +495,12 @@ public class TracePcodeEmulatorTest extends AbstractGhidraHeadlessIntegrationTes
"PUSH 0xdeadbeef",
"PUSH 0xbaadf00d"));
TracePcodeEmulator emu = new TracePcodeEmulator(tb.trace, 0, library);
TracePcodeEmulator emu = new TracePcodeEmulator(tb.trace, 0) {
@Override
protected PcodeUseropLibrary<byte[]> createUseropLibrary() {
return hexLib;
}
};
emu.inject(tb.addr(0x00400006), List.of("hexdump(RSP);"));
PcodeThread<byte[]> emuThread = emu.newThread(thread.getPath());
emuThread.overrideContextWithDefault();
@ -519,13 +524,13 @@ public class TracePcodeEmulatorTest extends AbstractGhidraHeadlessIntegrationTes
public void testInjectedInterrupt() throws Throwable {
try (ToyDBTraceBuilder tb = new ToyDBTraceBuilder("Test", "x86:LE:64:default")) {
final StringBuilder dumped = new StringBuilder();
SleighUseropLibrary<byte[]> library = new AnnotatedSleighUseropLibrary<byte[]>() {
PcodeUseropLibrary<byte[]> hexLib = new AnnotatedPcodeUseropLibrary<byte[]>() {
@Override
protected Lookup getMethodLookup() {
return MethodHandles.lookup();
}
@SleighUserop
@PcodeUserop
public void hexdump(byte[] in) {
dumped.append(NumericUtilities.convertBytesToString(in));
}
@ -538,7 +543,12 @@ public class TracePcodeEmulatorTest extends AbstractGhidraHeadlessIntegrationTes
"PUSH 0xdeadbeef",
"PUSH 0xbaadf00d"));
TracePcodeEmulator emu = new TracePcodeEmulator(tb.trace, 0, library);
TracePcodeEmulator emu = new TracePcodeEmulator(tb.trace, 0) {
@Override
protected PcodeUseropLibrary<byte[]> createUseropLibrary() {
return hexLib;
}
};
emu.inject(tb.addr(0x00400006), List.of(
"hexdump(RSP);",
"emu_swi();",

View file

@ -214,7 +214,7 @@ public class TraceSleighUtilsTest extends AbstractGhidraHeadlessIntegrationTest
"<else>",
" r1 = 7;",
"<done>"),
SleighUseropLibrary.NIL);
PcodeUseropLibrary.NIL);
TraceThread thread;
try (UndoableTransaction tid = b.startTransaction()) {
thread = b.getOrAddThread("Thread1", 0);
@ -222,7 +222,7 @@ public class TraceSleighUtilsTest extends AbstractGhidraHeadlessIntegrationTest
new PcodeExecutor<>(sp.getLanguage(),
BytesPcodeArithmetic.forLanguage(b.language),
new TraceBytesPcodeExecutorState(b.trace, 0, thread, 0));
sp.execute(executor, SleighUseropLibrary.nil());
sp.execute(executor, PcodeUseropLibrary.nil());
}
Register r1 = b.language.getRegister("r1");

View file

@ -85,9 +85,9 @@ public class ToyDBTraceBuilder implements AutoCloseable {
public void exec(long snap, int frame, TraceThread thread, List<String> sleigh) {
PcodeProgram program = SleighProgramCompiler.compileProgram((SleighLanguage) language,
"builder", sleigh, SleighUseropLibrary.nil());
"builder", sleigh, PcodeUseropLibrary.nil());
TraceSleighUtils.buildByteExecutor(trace, snap, thread, frame)
.execute(program, SleighUseropLibrary.nil());
.execute(program, PcodeUseropLibrary.nil());
}
public Address addr(AddressSpace space, long offset) {

View file

@ -367,7 +367,7 @@ public class TraceScheduleTest extends AbstractGhidraHeadlessIntegrationTest {
@Override
public PcodeExecutor<Void> getExecutor() {
return new PcodeExecutor<>(TOY_BE_64_LANG, machine.getArithmetic(), getState()) {
public PcodeFrame execute(PcodeProgram program, SleighUseropLibrary<Void> library) {
public PcodeFrame execute(PcodeProgram program, PcodeUseropLibrary<Void> library) {
machine.record.add("x:" + name);
// TODO: Verify the actual effect
return null; //super.execute(program, library);
@ -376,7 +376,7 @@ public class TraceScheduleTest extends AbstractGhidraHeadlessIntegrationTest {
}
@Override
public SleighUseropLibrary<Void> getUseropLibrary() {
public PcodeUseropLibrary<Void> getUseropLibrary() {
return null;
}
@ -402,7 +402,7 @@ public class TraceScheduleTest extends AbstractGhidraHeadlessIntegrationTest {
protected final List<String> record = new ArrayList<>();
public TestMachine() {
super(TOY_BE_64_LANG, null, null);
super(TOY_BE_64_LANG, null);
}
@Override
@ -419,6 +419,11 @@ public class TraceScheduleTest extends AbstractGhidraHeadlessIntegrationTest {
protected PcodeExecutorState<Void> createLocalState(PcodeThread<Void> thread) {
return null;
}
@Override
protected PcodeUseropLibrary<Void> createUseropLibrary() {
return PcodeUseropLibrary.nil();
}
}
@Test