mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-09-28 17:11:11 -09:00
Merge remote-tracking branch 'origin/GP-5285_Dan_testArmThumbSkip'
This commit is contained in:
@@ -13,13 +13,14 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package ghidra.pcode.emu.jit;
|
package ghidra.pcode.emu;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.fail;
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@@ -28,10 +29,9 @@ import generic.test.AbstractGTest;
|
|||||||
import ghidra.GhidraTestApplicationLayout;
|
import ghidra.GhidraTestApplicationLayout;
|
||||||
import ghidra.app.plugin.assembler.Assemblers;
|
import ghidra.app.plugin.assembler.Assemblers;
|
||||||
import ghidra.app.plugin.assembler.AssemblyBuffer;
|
import ghidra.app.plugin.assembler.AssemblyBuffer;
|
||||||
|
import ghidra.app.plugin.assembler.sleigh.sem.AssemblyPatternBlock;
|
||||||
import ghidra.framework.Application;
|
import ghidra.framework.Application;
|
||||||
import ghidra.framework.ApplicationConfiguration;
|
import ghidra.framework.ApplicationConfiguration;
|
||||||
import ghidra.pcode.emu.PcodeEmulator;
|
|
||||||
import ghidra.pcode.emu.PcodeThread;
|
|
||||||
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;
|
||||||
@@ -48,6 +48,7 @@ public abstract class AbstractPcodeEmulatorTest extends AbstractGTest {
|
|||||||
public static final LanguageID LANGID_TOY_BE = new LanguageID("Toy:BE:64:default");
|
public static final LanguageID LANGID_TOY_BE = new LanguageID("Toy:BE:64:default");
|
||||||
public static final LanguageID LANGID_TOY_LE = new LanguageID("Toy:BE:64:default");
|
public static final LanguageID LANGID_TOY_LE = new LanguageID("Toy:BE:64:default");
|
||||||
public static final LanguageID LANGID_X64 = new LanguageID("x86:LE:64:default");
|
public static final LanguageID LANGID_X64 = new LanguageID("x86:LE:64:default");
|
||||||
|
public static final LanguageID LANGID_ARMV8 = new LanguageID("ARM:LE:32:v8");
|
||||||
|
|
||||||
public static final int FIB_ITER_N = 100000;
|
public static final int FIB_ITER_N = 100000;
|
||||||
public static final long FIB_ITER_VAL = 2754320626097736315L;
|
public static final long FIB_ITER_VAL = 2754320626097736315L;
|
||||||
@@ -298,4 +299,64 @@ public abstract class AbstractPcodeEmulatorTest extends AbstractGTest {
|
|||||||
arithmetic.toLong(thread.getState().getVar(r1, Reason.INSPECT), Purpose.INSPECT));
|
arithmetic.toLong(thread.getState().getVar(r1, Reason.INSPECT), Purpose.INSPECT));
|
||||||
assertEquals(inject, thread.getCounter());
|
assertEquals(inject, thread.getCounter());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSkipThumbStaysThumb() throws Exception {
|
||||||
|
PcodeEmulator emu = createEmulator(getLanguage(LANGID_ARMV8));
|
||||||
|
PcodeArithmetic<byte[]> arithmetic = emu.getArithmetic();
|
||||||
|
AddressSpace space = emu.getLanguage().getDefaultSpace();
|
||||||
|
Address entry = space.getAddress(0x00400000);
|
||||||
|
AssemblyBuffer asm = new AssemblyBuffer(Assemblers.getAssembler(emu.getLanguage()), entry);
|
||||||
|
|
||||||
|
Language language = asm.getAssembler().getLanguage();
|
||||||
|
Register regCtx = language.getContextBaseRegister();
|
||||||
|
Register regT = language.getRegister("T");
|
||||||
|
RegisterValue rvDefault = new RegisterValue(regCtx,
|
||||||
|
asm.getAssembler().getContextAt(asm.getNext()).toBigInteger(regCtx.getNumBytes()));
|
||||||
|
RegisterValue rvThumb = rvDefault.assign(regT, BigInteger.ONE);
|
||||||
|
AssemblyPatternBlock ctxThumb = AssemblyPatternBlock.fromRegisterValue(rvThumb);
|
||||||
|
|
||||||
|
Address addrBlx = asm.getNext();
|
||||||
|
asm.assemble("blx 0x0");
|
||||||
|
Address addrThumb = asm.getNext();
|
||||||
|
asm.assemble("hlt 1", ctxThumb);
|
||||||
|
Address addrB = asm.getNext();
|
||||||
|
asm.assemble("b 0x%s".formatted(entry), ctxThumb); // placeholder
|
||||||
|
asm.assemble("adds r0, #0x1", ctxThumb); // Never executed
|
||||||
|
Address addrTgt = asm.getNext();
|
||||||
|
asm.assemble("adds r1, #0x1", ctxThumb);
|
||||||
|
Address addrEnd = asm.getNext();
|
||||||
|
|
||||||
|
// NOTE: blx [addr] always changes the instruction set
|
||||||
|
asm.assemble(addrBlx, "blx 0x%s".formatted(addrThumb));
|
||||||
|
asm.assemble(addrB, "b 0x%s".formatted(addrTgt), ctxThumb);
|
||||||
|
|
||||||
|
// Skip the HLT instruction
|
||||||
|
emu.inject(addrThumb, "goto 0x%s[ram];".formatted(addrB));
|
||||||
|
|
||||||
|
byte[] bytes = asm.getBytes();
|
||||||
|
// Sanity check regarding instruction encoding
|
||||||
|
assertEquals(12, bytes.length);
|
||||||
|
|
||||||
|
emu.getSharedState().setVar(asm.getEntry(), bytes.length, false, bytes);
|
||||||
|
PcodeThread<byte[]> thread = emu.newThread();
|
||||||
|
thread.overrideCounter(entry);
|
||||||
|
thread.overrideContextWithDefault();
|
||||||
|
|
||||||
|
try {
|
||||||
|
thread.run();
|
||||||
|
fail("Should have crashed on decode error");
|
||||||
|
}
|
||||||
|
catch (DecodePcodeExecutionException e) {
|
||||||
|
assertEquals(addrEnd, e.getProgramCounter());
|
||||||
|
}
|
||||||
|
|
||||||
|
Register r0 = emu.getLanguage().getRegister("r0");
|
||||||
|
Register r1 = emu.getLanguage().getRegister("r1");
|
||||||
|
|
||||||
|
assertEquals(0,
|
||||||
|
arithmetic.toLong(thread.getState().getVar(r0, Reason.INSPECT), Purpose.INSPECT));
|
||||||
|
assertEquals(1,
|
||||||
|
arithmetic.toLong(thread.getState().getVar(r1, Reason.INSPECT), Purpose.INSPECT));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -13,9 +13,8 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package ghidra.pcode.emu.jit;
|
package ghidra.pcode.emu;
|
||||||
|
|
||||||
import ghidra.pcode.emu.PcodeEmulator;
|
|
||||||
import ghidra.program.model.lang.Language;
|
import ghidra.program.model.lang.Language;
|
||||||
|
|
||||||
public class PlainPcodeEmulatorTest extends AbstractPcodeEmulatorTest {
|
public class PlainPcodeEmulatorTest extends AbstractPcodeEmulatorTest {
|
||||||
@@ -23,6 +23,7 @@ import org.junit.Test;
|
|||||||
|
|
||||||
import ghidra.app.plugin.assembler.Assemblers;
|
import ghidra.app.plugin.assembler.Assemblers;
|
||||||
import ghidra.app.plugin.assembler.AssemblyBuffer;
|
import ghidra.app.plugin.assembler.AssemblyBuffer;
|
||||||
|
import ghidra.pcode.emu.AbstractPcodeEmulatorTest;
|
||||||
import ghidra.pcode.emu.jit.JitPassage.AddrCtx;
|
import ghidra.pcode.emu.jit.JitPassage.AddrCtx;
|
||||||
import ghidra.pcode.emu.jit.gen.tgt.JitCompiledPassage.EntryPoint;
|
import ghidra.pcode.emu.jit.gen.tgt.JitCompiledPassage.EntryPoint;
|
||||||
import ghidra.pcode.exec.*;
|
import ghidra.pcode.exec.*;
|
||||||
Reference in New Issue
Block a user