mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-09-28 17:11:11 -09:00
GP-1161: Refactoring legacy state modification glue to abstract class.
This commit is contained in:
@@ -22,9 +22,7 @@ import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import ghidra.pcode.emu.AbstractPcodeMachine;
|
||||
import ghidra.pcode.emu.AbstractPcodeMachine.ThreadPcodeExecutorState;
|
||||
import ghidra.pcode.emu.PcodeThread;
|
||||
import ghidra.pcode.emu.*;
|
||||
import ghidra.pcode.exec.*;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.lang.RegisterValue;
|
||||
|
||||
@@ -0,0 +1,194 @@
|
||||
/* ###
|
||||
* 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.emu;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
|
||||
import ghidra.pcode.emulate.*;
|
||||
import ghidra.pcode.exec.*;
|
||||
import ghidra.pcode.memstate.MemoryState;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressSpace;
|
||||
import ghidra.program.model.lang.*;
|
||||
import ghidra.program.model.pcode.PcodeOp;
|
||||
import ghidra.util.Msg;
|
||||
|
||||
/**
|
||||
* A p-code thread which incorporates per-architecture state modifiers on concrete bytes
|
||||
*/
|
||||
public abstract class AbstractModifiedPcodeThread<T> extends DefaultPcodeThread<T> {
|
||||
|
||||
protected class GlueEmulate extends Emulate {
|
||||
public GlueEmulate(SleighLanguage lang, MemoryState s, BreakTable b) {
|
||||
super(lang, s, b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Language getLanguage() {
|
||||
return language;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setExecuteAddress(Address addr) {
|
||||
overrideCounter(addr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Address getExecuteAddress() {
|
||||
return getCounter();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setContextRegisterValue(RegisterValue regValue) {
|
||||
overrideContext(regValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RegisterValue getContextRegisterValue() {
|
||||
return getContext();
|
||||
}
|
||||
}
|
||||
|
||||
protected class GlueMemoryState extends MemoryState {
|
||||
public GlueMemoryState(Language language) {
|
||||
super(language);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getChunk(byte[] res, AddressSpace spc, long off, int size,
|
||||
boolean stopOnUnintialized) {
|
||||
return getBytesChunk(res, spc, off, size, stopOnUnintialized);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setChunk(byte[] val, AddressSpace spc, long off, int size) {
|
||||
setBytesChunk(val, spc, off, size);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInitialized(boolean initialized, AddressSpace spc, long off, int size) {
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
|
||||
protected class GluePcodeThreadExecutor extends PcodeThreadExecutor {
|
||||
public GluePcodeThreadExecutor(Language language, PcodeArithmetic<T> arithmetic,
|
||||
PcodeExecutorStatePiece<T, T> state) {
|
||||
super(language, arithmetic, state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executeCallother(PcodeOp op, PcodeFrame frame,
|
||||
SleighUseropLibrary<T> library) {
|
||||
// Prefer one in the library. Fall-back to state modifier's impl
|
||||
try {
|
||||
super.executeCallother(op, frame, library);
|
||||
}
|
||||
catch (SleighLinkException e) {
|
||||
if (modifier == null || !modifier.executeCallOther(op)) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Part of the glue that makes existing state modifiers work in new emulation framework
|
||||
protected final EmulateInstructionStateModifier modifier;
|
||||
protected final Emulate emulate;
|
||||
|
||||
protected Address savedCounter;
|
||||
|
||||
public AbstractModifiedPcodeThread(String name, AbstractPcodeMachine<T> machine) {
|
||||
super(name, machine);
|
||||
|
||||
/**
|
||||
* These two exist as a way to integrate the language-specific injects that are already
|
||||
* written for the established concrete emulator.
|
||||
*/
|
||||
emulate = new GlueEmulate(language, new GlueMemoryState(language),
|
||||
new BreakTableCallBack(language));
|
||||
modifier = createModifier();
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a modifier for the given language
|
||||
*
|
||||
* @return the state modifier
|
||||
*/
|
||||
protected EmulateInstructionStateModifier createModifier() {
|
||||
String classname = language
|
||||
.getProperty(GhidraLanguagePropertyKeys.EMULATE_INSTRUCTION_STATE_MODIFIER_CLASS);
|
||||
if (classname == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
Class<?> c = Class.forName(classname);
|
||||
if (!EmulateInstructionStateModifier.class.isAssignableFrom(c)) {
|
||||
Msg.error(this,
|
||||
"Language " + language.getLanguageID() + " does not specify a valid " +
|
||||
GhidraLanguagePropertyKeys.EMULATE_INSTRUCTION_STATE_MODIFIER_CLASS);
|
||||
throw new RuntimeException(classname + " does not implement interface " +
|
||||
EmulateInstructionStateModifier.class.getName());
|
||||
}
|
||||
Constructor<?> constructor = c.getConstructor(Emulate.class);
|
||||
return (EmulateInstructionStateModifier) constructor.newInstance(emulate);
|
||||
}
|
||||
catch (Exception e) {
|
||||
Msg.error(this, "Language " + language.getLanguageID() + " does not specify a valid " +
|
||||
GhidraLanguagePropertyKeys.EMULATE_INSTRUCTION_STATE_MODIFIER_CLASS);
|
||||
throw new RuntimeException(
|
||||
"Failed to instantiate " + classname + " for language " + language.getLanguageID(),
|
||||
e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PcodeThreadExecutor createExecutor() {
|
||||
return new GluePcodeThreadExecutor(language, arithmetic, state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the legacy state modifier to retrieve concrete bytes from the thread's state
|
||||
*
|
||||
* @see {@link MemoryState#getChunk(byte[], AddressSpace, long, int, boolean)}
|
||||
*/
|
||||
protected abstract int getBytesChunk(byte[] res, AddressSpace spc, long off, int size,
|
||||
boolean stopOnUnintialized);
|
||||
|
||||
/**
|
||||
* Called by the legacy state modifier to set concrete bytes in the thread's state
|
||||
*
|
||||
* @see {@link MemoryState#setChunk(byte[], AddressSpace, long, int)}
|
||||
*/
|
||||
protected abstract void setBytesChunk(byte[] val, AddressSpace spc, long off, int size);
|
||||
|
||||
@Override
|
||||
protected void preExecuteInstruction() {
|
||||
if (modifier != null) {
|
||||
savedCounter = getCounter();
|
||||
modifier.initialExecuteCallback(emulate, savedCounter, getContext());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void postExecuteInstruction() {
|
||||
if (modifier != null) {
|
||||
modifier.postExecuteCallback(emulate, savedCounter, frame.copyCode(),
|
||||
frame.getBranched(), getCounter());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -30,6 +30,6 @@ public abstract class AbstractPcodeEmulator extends AbstractPcodeMachine<byte[]>
|
||||
|
||||
@Override
|
||||
protected BytesPcodeThread createThread(String name) {
|
||||
return new BytesPcodeThread(name, this, library);
|
||||
return new BytesPcodeThread(name, this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,71 +20,13 @@ import java.util.*;
|
||||
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
|
||||
import ghidra.pcode.exec.*;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressSpace;
|
||||
import ghidra.program.model.lang.Language;
|
||||
import ghidra.program.model.mem.MemBuffer;
|
||||
import ghidra.util.classfinder.ClassSearcher;
|
||||
|
||||
/**
|
||||
* An abstract implementation of {@link PcodeMachine} suitable as a base for most implementations
|
||||
*/
|
||||
public abstract class AbstractPcodeMachine<T> implements PcodeMachine<T> {
|
||||
public static class ThreadPcodeExecutorState<T> implements PcodeExecutorState<T> {
|
||||
protected final PcodeExecutorState<T> memoryState;
|
||||
protected final PcodeExecutorState<T> registerState;
|
||||
|
||||
public ThreadPcodeExecutorState(PcodeExecutorState<T> memoryState,
|
||||
PcodeExecutorState<T> registerState) {
|
||||
this.memoryState = memoryState;
|
||||
this.registerState = registerState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T longToOffset(AddressSpace space, long l) {
|
||||
if (space.isRegisterSpace()) {
|
||||
return registerState.longToOffset(space, l);
|
||||
}
|
||||
else {
|
||||
return memoryState.longToOffset(space, l);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVar(AddressSpace space, T offset, int size, boolean truncateAddressableUnit,
|
||||
T val) {
|
||||
if (space.isRegisterSpace()) {
|
||||
registerState.setVar(space, offset, size, truncateAddressableUnit, val);
|
||||
}
|
||||
else {
|
||||
memoryState.setVar(space, offset, size, truncateAddressableUnit, val);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public T getVar(AddressSpace space, T offset, int size, boolean truncateAddressableUnit) {
|
||||
if (space.isRegisterSpace()) {
|
||||
return registerState.getVar(space, offset, size, truncateAddressableUnit);
|
||||
}
|
||||
else {
|
||||
return memoryState.getVar(space, offset, size, truncateAddressableUnit);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public MemBuffer getConcreteBuffer(Address address) {
|
||||
assert !address.getAddressSpace().isRegisterSpace();
|
||||
return memoryState.getConcreteBuffer(address);
|
||||
}
|
||||
|
||||
public PcodeExecutorState<T> getMemoryState() {
|
||||
return memoryState;
|
||||
}
|
||||
|
||||
public PcodeExecutorState<T> getRegisterState() {
|
||||
return registerState;
|
||||
}
|
||||
}
|
||||
|
||||
protected final SleighLanguage language;
|
||||
protected final PcodeArithmetic<T> arithmetic;
|
||||
protected final SleighUseropLibrary<T> library;
|
||||
@@ -128,7 +70,7 @@ public abstract class AbstractPcodeMachine<T> implements PcodeMachine<T> {
|
||||
* @return the new thread
|
||||
*/
|
||||
protected PcodeThread<T> createThread(String name) {
|
||||
return new DefaultPcodeThread<>(name, this, library);
|
||||
return new DefaultPcodeThread<>(name, this);
|
||||
}
|
||||
|
||||
protected static PcodeStateInitializer getPluggableInitializer(Language language) {
|
||||
|
||||
@@ -1,183 +1,22 @@
|
||||
/* ###
|
||||
* 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.emu;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
|
||||
import ghidra.pcode.emulate.*;
|
||||
import ghidra.pcode.exec.*;
|
||||
import ghidra.pcode.memstate.MemoryState;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressSpace;
|
||||
import ghidra.program.model.lang.*;
|
||||
import ghidra.program.model.pcode.PcodeOp;
|
||||
import ghidra.util.Msg;
|
||||
|
||||
/**
|
||||
* A p-code thread which executes on concrete bytes and incorporates per-architecture state
|
||||
* modifiers
|
||||
*/
|
||||
public class BytesPcodeThread extends DefaultPcodeThread<byte[]> {
|
||||
|
||||
protected class GlueEmulate extends Emulate {
|
||||
public GlueEmulate(SleighLanguage lang, MemoryState s, BreakTable b) {
|
||||
super(lang, s, b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Language getLanguage() {
|
||||
return language;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setExecuteAddress(Address addr) {
|
||||
overrideCounter(addr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Address getExecuteAddress() {
|
||||
return getCounter();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setContextRegisterValue(RegisterValue regValue) {
|
||||
overrideContext(regValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RegisterValue getContextRegisterValue() {
|
||||
return getContext();
|
||||
}
|
||||
}
|
||||
|
||||
protected class GlueMemoryState extends MemoryState {
|
||||
public GlueMemoryState(Language language) {
|
||||
super(language);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getChunk(byte[] res, AddressSpace spc, long off, int size,
|
||||
boolean stopOnUnintialized) {
|
||||
byte[] var = state.getVar(spc, off, size, true);
|
||||
System.arraycopy(var, 0, res, 0, var.length);
|
||||
return var.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setChunk(byte[] val, AddressSpace spc, long off, int size) {
|
||||
state.setVar(spc, off, size, true, val);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInitialized(boolean initialized, AddressSpace spc, long off, int size) {
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
|
||||
protected class GluePcodeThreadExecutor extends PcodeThreadExecutor {
|
||||
public GluePcodeThreadExecutor(Language language, PcodeArithmetic<byte[]> arithmetic,
|
||||
PcodeExecutorStatePiece<byte[], byte[]> state) {
|
||||
super(language, arithmetic, state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executeCallother(PcodeOp op, PcodeFrame frame,
|
||||
SleighUseropLibrary<byte[]> library) {
|
||||
// Prefer one in the library. Fall-back to state modifier's impl
|
||||
try {
|
||||
super.executeCallother(op, frame, library);
|
||||
}
|
||||
catch (SleighLinkException e) {
|
||||
if (modifier == null || !modifier.executeCallOther(op)) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Part of the glue that makes existing state modifiers work in new emulation framework
|
||||
protected final EmulateInstructionStateModifier modifier;
|
||||
protected final Emulate emulate;
|
||||
|
||||
protected Address savedCounter;
|
||||
|
||||
public BytesPcodeThread(String name, AbstractPcodeMachine<byte[]> machine,
|
||||
SleighUseropLibrary<byte[]> library) {
|
||||
super(name, machine, library);
|
||||
|
||||
/**
|
||||
* These two exist as a way to integrate the language-specific injects that are already
|
||||
* written for the established concrete emulator.
|
||||
*/
|
||||
emulate = new GlueEmulate(language, new GlueMemoryState(language),
|
||||
new BreakTableCallBack(language));
|
||||
modifier = createModifier();
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a modifier for the given language
|
||||
*
|
||||
* @return the state modifier
|
||||
*/
|
||||
protected EmulateInstructionStateModifier createModifier() {
|
||||
String classname = language
|
||||
.getProperty(GhidraLanguagePropertyKeys.EMULATE_INSTRUCTION_STATE_MODIFIER_CLASS);
|
||||
if (classname == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
Class<?> c = Class.forName(classname);
|
||||
if (!EmulateInstructionStateModifier.class.isAssignableFrom(c)) {
|
||||
Msg.error(this,
|
||||
"Language " + language.getLanguageID() + " does not specify a valid " +
|
||||
GhidraLanguagePropertyKeys.EMULATE_INSTRUCTION_STATE_MODIFIER_CLASS);
|
||||
throw new RuntimeException(classname + " does not implement interface " +
|
||||
EmulateInstructionStateModifier.class.getName());
|
||||
}
|
||||
Constructor<?> constructor = c.getConstructor(Emulate.class);
|
||||
return (EmulateInstructionStateModifier) constructor.newInstance(emulate);
|
||||
}
|
||||
catch (Exception e) {
|
||||
Msg.error(this, "Language " + language.getLanguageID() + " does not specify a valid " +
|
||||
GhidraLanguagePropertyKeys.EMULATE_INSTRUCTION_STATE_MODIFIER_CLASS);
|
||||
throw new RuntimeException(
|
||||
"Failed to instantiate " + classname + " for language " + language.getLanguageID(),
|
||||
e);
|
||||
}
|
||||
public class BytesPcodeThread extends AbstractModifiedPcodeThread<byte[]> {
|
||||
public BytesPcodeThread(String name, AbstractPcodeMachine<byte[]> machine) {
|
||||
super(name, machine);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PcodeThreadExecutor createExecutor() {
|
||||
return new GluePcodeThreadExecutor(language, arithmetic, state);
|
||||
protected int getBytesChunk(byte[] res, AddressSpace spc, long off, int size,
|
||||
boolean stopOnUnintialized) {
|
||||
byte[] var = state.getVar(spc, off, size, true);
|
||||
System.arraycopy(var, 0, res, 0, var.length);
|
||||
return var.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void preExecuteInstruction() {
|
||||
if (modifier != null) {
|
||||
savedCounter = getCounter();
|
||||
modifier.initialExecuteCallback(emulate, savedCounter, getContext());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void postExecuteInstruction() {
|
||||
if (modifier != null) {
|
||||
modifier.postExecuteCallback(emulate, savedCounter, frame.copyCode(),
|
||||
frame.getBranched(), getCounter());
|
||||
}
|
||||
protected void setBytesChunk(byte[] val, AddressSpace spc, long off, int size) {
|
||||
state.setVar(spc, off, size, true, val);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@ import java.math.BigInteger;
|
||||
import java.util.*;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
|
||||
import ghidra.pcode.emu.AbstractPcodeMachine.ThreadPcodeExecutorState;
|
||||
import ghidra.pcode.exec.*;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.lang.*;
|
||||
@@ -110,8 +109,7 @@ public class DefaultPcodeThread<T> implements PcodeThread<T> {
|
||||
protected final ProgramContextImpl defaultContext;
|
||||
protected final Map<Address, PcodeProgram> injects = new HashMap<>();
|
||||
|
||||
public DefaultPcodeThread(String name, AbstractPcodeMachine<T> machine,
|
||||
SleighUseropLibrary<T> library) {
|
||||
public DefaultPcodeThread(String name, AbstractPcodeMachine<T> machine) {
|
||||
this.name = name;
|
||||
this.machine = machine;
|
||||
this.language = machine.language;
|
||||
@@ -119,8 +117,8 @@ public class DefaultPcodeThread<T> implements PcodeThread<T> {
|
||||
PcodeExecutorState<T> memoryState = machine.getMemoryState();
|
||||
PcodeExecutorState<T> registerState = machine.createRegisterState(this);
|
||||
this.state = new ThreadPcodeExecutorState<>(memoryState, registerState);
|
||||
this.decoder = new SleighInstructionDecoder(language, memoryState);
|
||||
this.library = new SleighEmulationLibrary<>(this).compose(library);
|
||||
this.decoder = createInstructionDecoder(memoryState);
|
||||
this.library = createUseropLibrary();
|
||||
|
||||
this.executor = createExecutor();
|
||||
this.pc = language.getProgramCounter();
|
||||
@@ -137,6 +135,14 @@ public class DefaultPcodeThread<T> implements PcodeThread<T> {
|
||||
this.reInitialize();
|
||||
}
|
||||
|
||||
protected SleighInstructionDecoder createInstructionDecoder(PcodeExecutorState<T> memoryState) {
|
||||
return new SleighInstructionDecoder(language, memoryState);
|
||||
}
|
||||
|
||||
protected SleighUseropLibrary<T> createUseropLibrary() {
|
||||
return new SleighEmulationLibrary<>(this).compose(machine.library);
|
||||
}
|
||||
|
||||
protected PcodeThreadExecutor createExecutor() {
|
||||
return new PcodeThreadExecutor(language, arithmetic, state);
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ package ghidra.pcode.emu;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import ghidra.pcode.emu.AbstractPcodeMachine.ThreadPcodeExecutorState;
|
||||
import ghidra.pcode.emu.DefaultPcodeThread.SleighEmulationLibrary;
|
||||
import ghidra.pcode.exec.*;
|
||||
import ghidra.program.model.address.Address;
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
package ghidra.pcode.emu;
|
||||
|
||||
import ghidra.pcode.exec.PcodeExecutorState;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressSpace;
|
||||
import ghidra.program.model.mem.MemBuffer;
|
||||
|
||||
public class ThreadPcodeExecutorState<T> implements PcodeExecutorState<T> {
|
||||
protected final PcodeExecutorState<T> memoryState;
|
||||
protected final PcodeExecutorState<T> registerState;
|
||||
|
||||
public ThreadPcodeExecutorState(PcodeExecutorState<T> memoryState,
|
||||
PcodeExecutorState<T> registerState) {
|
||||
this.memoryState = memoryState;
|
||||
this.registerState = registerState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T longToOffset(AddressSpace space, long l) {
|
||||
if (space.isRegisterSpace()) {
|
||||
return registerState.longToOffset(space, l);
|
||||
}
|
||||
else {
|
||||
return memoryState.longToOffset(space, l);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVar(AddressSpace space, T offset, int size, boolean truncateAddressableUnit,
|
||||
T val) {
|
||||
if (space.isRegisterSpace()) {
|
||||
registerState.setVar(space, offset, size, truncateAddressableUnit, val);
|
||||
}
|
||||
else {
|
||||
memoryState.setVar(space, offset, size, truncateAddressableUnit, val);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public T getVar(AddressSpace space, T offset, int size, boolean truncateAddressableUnit) {
|
||||
if (space.isRegisterSpace()) {
|
||||
return registerState.getVar(space, offset, size, truncateAddressableUnit);
|
||||
}
|
||||
else {
|
||||
return memoryState.getVar(space, offset, size, truncateAddressableUnit);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public MemBuffer getConcreteBuffer(Address address) {
|
||||
assert !address.getAddressSpace().isRegisterSpace();
|
||||
return memoryState.getConcreteBuffer(address);
|
||||
}
|
||||
|
||||
public PcodeExecutorState<T> getMemoryState() {
|
||||
return memoryState;
|
||||
}
|
||||
|
||||
public PcodeExecutorState<T> getRegisterState() {
|
||||
return registerState;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user