mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-06-01 14:54:29 +08:00
Merge remote-tracking branch 'origin/GP-3571_Dan_emuCtx' into patch
This commit is contained in:
+37
-1
@@ -940,8 +940,44 @@ public class BytesTracePcodeEmulatorTest extends AbstractTracePcodeEmulatorTest
|
|||||||
|
|
||||||
assertEquals(BigInteger.valueOf(0x0010fff8),
|
assertEquals(BigInteger.valueOf(0x0010fff8),
|
||||||
regs.getValue(x64, 1, tb.reg(x64, "RSP")).getUnsignedValue());
|
regs.getValue(x64, 1, tb.reg(x64, "RSP")).getUnsignedValue());
|
||||||
assertEquals(new BigInteger("efbeed0d00000000",16), // Guest is LE, host is BE
|
assertEquals(new BigInteger("efbeed0d00000000", 16), // Guest is LE, host is BE
|
||||||
TraceSleighUtils.evaluate(changedExpr, tb.trace, 1, thread, 0));
|
TraceSleighUtils.evaluate(changedExpr, tb.trace, 1, thread, 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testITECC_VMOVCCF32() throws Throwable {
|
||||||
|
try (ToyDBTraceBuilder tb = new ToyDBTraceBuilder("Test", "ARM:LE:32:v8T")) {
|
||||||
|
TraceThread thread = initTrace(tb, """
|
||||||
|
pc = 0x00400000;
|
||||||
|
sp = 0x00110000;
|
||||||
|
s1 = 0x12341234;
|
||||||
|
CY = 1;
|
||||||
|
""",
|
||||||
|
List.of(
|
||||||
|
"ite cc"));
|
||||||
|
//"vmov.cc.f32 s1,0xbf000000"));
|
||||||
|
|
||||||
|
try (Transaction tx = tb.startTransaction()) {
|
||||||
|
tb.trace.getMemoryManager()
|
||||||
|
.putBytes(0, tb.addr(0x00400002), tb.buf(0xfe, 0xee, 0x00, 0x0a));
|
||||||
|
}
|
||||||
|
|
||||||
|
BytesTracePcodeEmulator emu = new BytesTracePcodeEmulator(tb.host, 0);
|
||||||
|
PcodeThread<byte[]> emuThread = emu.newThread(thread.getPath());
|
||||||
|
emuThread.stepInstruction();
|
||||||
|
emuThread.stepPcodeOp(); // decode
|
||||||
|
assertEquals("vmov.cc.f32 s1,0xbf000000", emuThread.getInstruction().toString());
|
||||||
|
emuThread.finishInstruction();
|
||||||
|
|
||||||
|
try (Transaction tx = tb.startTransaction()) {
|
||||||
|
emu.writeDown(tb.host, 1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(BigInteger.valueOf(0x00400006),
|
||||||
|
TraceSleighUtils.evaluate("pc", tb.trace, 1, thread, 0));
|
||||||
|
assertEquals(BigInteger.valueOf(0x12341234), // Unaffected
|
||||||
|
TraceSleighUtils.evaluate("s1", tb.trace, 1, thread, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ import java.util.*;
|
|||||||
|
|
||||||
import ghidra.app.emulator.Emulator;
|
import ghidra.app.emulator.Emulator;
|
||||||
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
|
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
|
||||||
|
import ghidra.app.plugin.processors.sleigh.SleighParserContext;
|
||||||
|
import ghidra.app.util.PseudoInstruction;
|
||||||
import ghidra.pcode.exec.*;
|
import ghidra.pcode.exec.*;
|
||||||
import ghidra.pcode.exec.PcodeArithmetic.Purpose;
|
import ghidra.pcode.exec.PcodeArithmetic.Purpose;
|
||||||
import ghidra.pcode.exec.PcodeExecutorStatePiece.Reason;
|
import ghidra.pcode.exec.PcodeExecutorStatePiece.Reason;
|
||||||
@@ -27,6 +29,7 @@ import ghidra.program.model.address.Address;
|
|||||||
import ghidra.program.model.address.AddressSpace;
|
import ghidra.program.model.address.AddressSpace;
|
||||||
import ghidra.program.model.lang.*;
|
import ghidra.program.model.lang.*;
|
||||||
import ghidra.program.model.listing.Instruction;
|
import ghidra.program.model.listing.Instruction;
|
||||||
|
import ghidra.program.model.mem.MemoryAccessException;
|
||||||
import ghidra.program.model.pcode.PcodeOp;
|
import ghidra.program.model.pcode.PcodeOp;
|
||||||
import ghidra.program.util.ProgramContextImpl;
|
import ghidra.program.util.ProgramContextImpl;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
@@ -457,6 +460,33 @@ public class DefaultPcodeThread<T> implements PcodeThread<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected RegisterValue getContextAfterCommits() {
|
||||||
|
PseudoInstruction pins = (PseudoInstruction) instruction;
|
||||||
|
try {
|
||||||
|
SleighParserContext parserCtx = (SleighParserContext) pins.getParserContext();
|
||||||
|
var procCtx = new DisassemblerContextAdapter() {
|
||||||
|
RegisterValue ctxVal = new RegisterValue(language.getContextBaseRegister());
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setFutureRegisterValue(Address address, RegisterValue value) {
|
||||||
|
if (!value.getRegister().isProcessorContext()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!address.equals(counter)) {
|
||||||
|
Msg.warn(this, "Context applied somewhere other than the counter.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ctxVal = ctxVal.assign(value.getRegister(), value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
parserCtx.applyCommits(procCtx);
|
||||||
|
return procCtx.ctxVal;
|
||||||
|
}
|
||||||
|
catch (MemoryAccessException e) {
|
||||||
|
throw new AssertionError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolve a finished instruction, advancing the program counter if necessary
|
* Resolve a finished instruction, advancing the program counter if necessary
|
||||||
*/
|
*/
|
||||||
@@ -469,7 +499,10 @@ public class DefaultPcodeThread<T> implements PcodeThread<T> {
|
|||||||
overrideCounter(counter.addWrap(decoder.getLastLengthWithDelays()));
|
overrideCounter(counter.addWrap(decoder.getLastLengthWithDelays()));
|
||||||
}
|
}
|
||||||
if (contextreg != Register.NO_CONTEXT) {
|
if (contextreg != Register.NO_CONTEXT) {
|
||||||
overrideContext(defaultContext.getFlowValue(instruction.getRegisterValue(contextreg)));
|
RegisterValue flowCtx =
|
||||||
|
defaultContext.getFlowValue(instruction.getRegisterValue(contextreg));
|
||||||
|
RegisterValue commitCtx = getContextAfterCommits();
|
||||||
|
overrideContext(flowCtx.combineValues(commitCtx));
|
||||||
}
|
}
|
||||||
postExecuteInstruction();
|
postExecuteInstruction();
|
||||||
frame = null;
|
frame = null;
|
||||||
|
|||||||
+82
@@ -0,0 +1,82 @@
|
|||||||
|
/* ###
|
||||||
|
* 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.math.BigInteger;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import ghidra.program.model.address.Address;
|
||||||
|
import ghidra.program.model.lang.*;
|
||||||
|
import ghidra.program.model.listing.ContextChangeException;
|
||||||
|
|
||||||
|
public interface DisassemblerContextAdapter extends DisassemblerContext {
|
||||||
|
@Override
|
||||||
|
default Register getBaseContextRegister() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default List<Register> getRegisters() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default Register getRegister(String name) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default BigInteger getValue(Register register, boolean signed) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default RegisterValue getRegisterValue(Register register) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default boolean hasValue(Register register) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default void setValue(Register register, BigInteger value)
|
||||||
|
throws ContextChangeException {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default void setRegisterValue(RegisterValue value) throws ContextChangeException {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default void clearRegister(Register register) throws ContextChangeException {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default void setFutureRegisterValue(Address address, RegisterValue value) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default void setFutureRegisterValue(Address fromAddr, Address toAddr,
|
||||||
|
RegisterValue value) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user