mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-05-19 03:53:49 +08:00
GP-4241: Port EmulateInstructionStateModifiers to PcodeUseropLibraryFactories.
This commit is contained in:
+47
@@ -0,0 +1,47 @@
|
||||
/* ###
|
||||
* 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.stdoplib;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
|
||||
import ghidra.pcode.exec.*;
|
||||
import ghidra.pcode.exec.PcodeUseropLibraryFactory.UseropLibrary;
|
||||
|
||||
// This treads on GP-4240 a bit. Still, enough to demonstrate the framework can support it.
|
||||
@UseropLibrary("trig")
|
||||
public class TrigPcodeUseropLibraryFactory implements PcodeUseropLibraryFactory {
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> PcodeUseropLibrary<T> create(SleighLanguage language,
|
||||
PcodeArithmetic<T> arithmetic) {
|
||||
return (PcodeUseropLibrary<T>) TrigPcodeUseropLibrary.INSTANCE;
|
||||
}
|
||||
|
||||
public static class TrigPcodeUseropLibrary<T> extends AnnotatedPcodeUseropLibrary<T> {
|
||||
public static final TrigPcodeUseropLibrary<?> INSTANCE = new TrigPcodeUseropLibrary<>();
|
||||
|
||||
@PcodeUserop(functional = true)
|
||||
public float sin(float a) {
|
||||
return (float) Math.sin(a);
|
||||
}
|
||||
|
||||
// GP-5339: This won't work until we support overloaded userops
|
||||
@PcodeUserop(functional = true)
|
||||
public double sin(double a) {
|
||||
return Math.sin(a);
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -20,6 +20,7 @@ import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
|
||||
import ghidra.program.model.lang.GhidraLanguagePropertyKeys;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.classfinder.ClassSearcher;
|
||||
import ghidra.util.classfinder.ExtensionPoint;
|
||||
@@ -33,7 +34,7 @@ import ghidra.util.classfinder.ExtensionPoint;
|
||||
*/
|
||||
public interface PcodeUseropLibraryFactory extends ExtensionPoint {
|
||||
/** The property key for useropLib ids in pspec files */
|
||||
public static final String KEY_USEROP_LIBS = "useropLibs";
|
||||
public static final String KEY_USEROP_LIBS = GhidraLanguagePropertyKeys.USEROP_LIBS;
|
||||
|
||||
/**
|
||||
* A required annotation for identifying the library in pspec files
|
||||
|
||||
+243
@@ -0,0 +1,243 @@
|
||||
/* ###
|
||||
* 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;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.*;
|
||||
|
||||
import org.junit.AssumptionViolatedException;
|
||||
import org.junit.Before;
|
||||
|
||||
import generic.test.AbstractGenericTest;
|
||||
import ghidra.app.plugin.assembler.*;
|
||||
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
|
||||
import ghidra.pcode.emu.*;
|
||||
import ghidra.pcode.emulate.BreakTableCallBack;
|
||||
import ghidra.pcode.emulate.Emulate;
|
||||
import ghidra.pcode.exec.PcodeArithmetic.Purpose;
|
||||
import ghidra.pcode.exec.PcodeExecutorStatePiece.Reason;
|
||||
import ghidra.pcode.memstate.*;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.lang.Register;
|
||||
import ghidra.program.model.pcode.PcodeOp;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.NumericUtilities;
|
||||
import ghidra.util.classfinder.ClassSearcher;
|
||||
import ghidra.util.exception.MultipleCauses;
|
||||
import ghidra.util.task.ConsoleTaskMonitor;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
public class AbstractEmulationEquivalenceTest extends AbstractGenericTest {
|
||||
protected static final TaskMonitor MONITOR = new ConsoleTaskMonitor();
|
||||
|
||||
protected static class TestMemoryFaultHandler implements MemoryFaultHandler {
|
||||
@Override
|
||||
public boolean uninitializedRead(Address address, int size, byte[] buf, int bufOffset) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean unknownAddress(Address address, boolean write) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected interface DoAsm {
|
||||
void accept(AssemblyBuffer buf) throws Exception;
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setupSearch() throws Exception {
|
||||
ClassSearcher.search(MONITOR);
|
||||
}
|
||||
|
||||
protected long getEntryOffset() {
|
||||
return 0x00400000;
|
||||
}
|
||||
|
||||
protected void doTestEquivOld(SleighLanguage language, Map<String, String> init,
|
||||
AssemblyBuffer buf, int count, Map<String, String> expected) throws Exception {
|
||||
Address entry = buf.getEntry();
|
||||
|
||||
MemoryState state = new DefaultMemoryState(language);
|
||||
Emulate emu = new Emulate(language, state, new BreakTableCallBack(language));
|
||||
AddressSet regsUnchecked = new AddressSet();
|
||||
state.setMemoryBank(new MemoryPageBank(language.getAddressFactory().getRegisterSpace(),
|
||||
language.isBigEndian(), 0x1000, new TestMemoryFaultHandler()) {
|
||||
|
||||
@Override
|
||||
public void setChunk(long offset, int size, byte[] val) {
|
||||
super.setChunk(offset, size, val);
|
||||
try {
|
||||
regsUnchecked.add(new AddressRangeImpl(getSpace().getAddress(offset), size));
|
||||
}
|
||||
catch (AddressOverflowException | AddressOutOfBoundsException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
state.setMemoryBank(new MemoryPageBank(language.getDefaultSpace(),
|
||||
language.isBigEndian(), 0x1000, new TestMemoryFaultHandler()) {
|
||||
@Override
|
||||
public void setChunk(long offset, int size, byte[] val) {
|
||||
/*Msg.info(this, "Old set ram[0x%x]:%d = %s".formatted(offset, size,
|
||||
NumericUtilities.convertBytesToString(val)));*/
|
||||
super.setChunk(offset, size, val);
|
||||
}
|
||||
});
|
||||
byte[] bytes = buf.getBytes();
|
||||
state.setChunk(bytes, language.getDefaultSpace(), entry.getOffset(), bytes.length);
|
||||
|
||||
for (Map.Entry<String, String> ent : init.entrySet()) {
|
||||
state.setValue(ent.getKey(), new BigInteger(ent.getValue(), 16));
|
||||
}
|
||||
|
||||
emu.setExecuteAddress(entry);
|
||||
for (int i = 0; i < count; i++) {
|
||||
emu.executeInstruction(false, MONITOR);
|
||||
}
|
||||
|
||||
for (Map.Entry<String, String> ent : expected.entrySet()) {
|
||||
assertEquals("Old register value mismatch on " + ent.getKey(), ent.getValue(),
|
||||
state.getBigInteger(ent.getKey()).toString(16));
|
||||
Register reg = language.getRegister(ent.getKey());
|
||||
if (!reg.getAddressSpace().isRegisterSpace()) {
|
||||
continue;
|
||||
}
|
||||
regsUnchecked.delete(new AddressRangeImpl(reg.getAddress(), reg.getNumBytes()));
|
||||
}
|
||||
|
||||
if (!regsUnchecked.isEmpty()) {
|
||||
Set<String> regs = new TreeSet<>();
|
||||
nextAddr: while (!regsUnchecked.isEmpty()) {
|
||||
Address min = regsUnchecked.getMinAddress();
|
||||
List<Register> found = Arrays.asList(language.getRegisters(min));
|
||||
found.sort((r1, r2) -> r1.getBitLength() - r2.getBitLength());
|
||||
for (Register r : found) {
|
||||
AddressRange rng = new AddressRangeImpl(r.getAddress(), r.getNumBytes());
|
||||
if (!regsUnchecked.contains(rng.getMinAddress(), rng.getMaxAddress())) {
|
||||
continue;
|
||||
}
|
||||
regs.add(r.getName());
|
||||
regsUnchecked.delete(rng);
|
||||
continue nextAddr;
|
||||
}
|
||||
regsUnchecked.delete(min, min);
|
||||
}
|
||||
if (!regs.isEmpty()) {
|
||||
throw new AssertionError("Some written registers were not asserted: " + regs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void doTestEquivNew(SleighLanguage language, Map<String, String> init,
|
||||
AssemblyBuffer buf, int count, Map<String, String> expected) throws Exception {
|
||||
Address entry = buf.getEntry();
|
||||
|
||||
@SuppressWarnings("unused") // uncomment arg to PcodeEmulator to enable
|
||||
PcodeEmulationCallbacks<byte[]> cb = new PcodeEmulationCallbacks<>() {
|
||||
public <A, U> void dataWritten(PcodeThread<byte[]> thread,
|
||||
PcodeExecutorStatePiece<A, U> piece, Address address, int length, U value) {
|
||||
if (!address.isMemoryAddress()) {
|
||||
return;
|
||||
}
|
||||
if (!(value instanceof byte[] v)) {
|
||||
return;
|
||||
}
|
||||
Msg.info(this, "New set ram[0x%x]:%d = %s".formatted(address.getOffset(), length,
|
||||
NumericUtilities.convertBytesToString(v)));
|
||||
};
|
||||
};
|
||||
PcodeEmulator emu = new PcodeEmulator(language/*, cb*/) {
|
||||
@Override
|
||||
protected BytesPcodeThread createThread(String name) {
|
||||
/**
|
||||
* TODO: There's a branch somewhere that will make this not work.
|
||||
*/
|
||||
return new BytesPcodeThread(name, this) {
|
||||
@Override
|
||||
protected boolean onMissingUseropDef(PcodeOp op, String opName) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
byte[] bytes = buf.getBytes();
|
||||
emu.getSharedState().setVar(entry, bytes.length, false, bytes);
|
||||
|
||||
PcodeThread<byte[]> thread = emu.newThread();
|
||||
PcodeExecutorState<byte[]> state = thread.getState();
|
||||
PcodeArithmetic<byte[]> arithmetic = thread.getArithmetic();
|
||||
|
||||
for (Map.Entry<String, String> ent : init.entrySet()) {
|
||||
Register reg = language.getRegister(ent.getKey());
|
||||
state.setVar(reg,
|
||||
arithmetic.fromConst(new BigInteger(ent.getValue(), 16), reg.getNumBytes()));
|
||||
}
|
||||
|
||||
thread.setCounter(entry);
|
||||
thread.overrideContextWithDefault();
|
||||
thread.stepInstruction(count);
|
||||
|
||||
for (Map.Entry<String, String> ent : expected.entrySet()) {
|
||||
Register reg = language.getRegister(ent.getKey());
|
||||
assertEquals("New register value mismatch on " + ent.getKey(), ent.getValue(),
|
||||
arithmetic.toBigInteger(state.getVar(reg, Reason.INSPECT), Purpose.INSPECT)
|
||||
.toString(16));
|
||||
}
|
||||
}
|
||||
|
||||
protected void doTestEquiv(SleighLanguage language, Map<String, String> init, DoAsm doAsm,
|
||||
int count, Map<String, String> expected) throws Exception {
|
||||
//Msg.info(this, "Language: " + language.getLanguageID());
|
||||
Assembler asm = Assemblers.getAssembler(language);
|
||||
Address entry = language.getDefaultSpace().getAddress(getEntryOffset());
|
||||
AssemblyBuffer buf = new AssemblyBuffer(asm, entry);
|
||||
|
||||
doAsm.accept(buf);
|
||||
|
||||
AssertionError oldFailure = null;
|
||||
AssertionError newFailure = null;
|
||||
try {
|
||||
doTestEquivOld(language, init, buf, count, expected);
|
||||
}
|
||||
catch (AssertionError e) {
|
||||
oldFailure = e;
|
||||
Msg.error("Old failed: " + e, e);
|
||||
}
|
||||
try {
|
||||
doTestEquivNew(language, init, buf, count, expected);
|
||||
}
|
||||
catch (AssertionError e) {
|
||||
newFailure = e;
|
||||
Msg.error("New failed: " + e, e);
|
||||
}
|
||||
|
||||
if (newFailure != null && oldFailure != null) {
|
||||
throw new AssertionError("Both old and new failed",
|
||||
new MultipleCauses(List.of(oldFailure, newFailure)));
|
||||
}
|
||||
if (newFailure != null) {
|
||||
throw newFailure;
|
||||
}
|
||||
if (oldFailure != null) {
|
||||
throw new AssumptionViolatedException(
|
||||
"Old failed, but new passed: " + oldFailure.getMessage(), oldFailure);
|
||||
}
|
||||
}
|
||||
}
|
||||
+12
-2
@@ -4,9 +4,9 @@
|
||||
* 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.
|
||||
@@ -89,6 +89,16 @@ public final class GhidraLanguagePropertyKeys {
|
||||
public static final String EMULATE_INSTRUCTION_STATE_MODIFIER_CLASS =
|
||||
"emulateInstructionStateModifierClass";
|
||||
|
||||
/**
|
||||
* USEROP_LIBS is a string property that indicates keys for matching one or more
|
||||
* {@code PcodeUseropLibaryFactory}s, which will be composed to form the library of custom
|
||||
* userop implementations available to an emulator. The default is empty. NOTE: This is
|
||||
* <em>not</em> the name of a class, but a comma-separated list of IDs. Each factory is also
|
||||
* tagged with a list of IDs. If any ID matches, then that factory is given a chance to
|
||||
* contribute userops.
|
||||
*/
|
||||
public static final String USEROP_LIBS = "useropLibs";
|
||||
|
||||
/**
|
||||
* PCODE_INJECT_LIBRARY_CLASS indicates the classname of a PcodeInjectLibrary implementation
|
||||
* that is used to generate p-code injection payloads which can replace either CALLs or CALLOTHERs
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
<processor_spec>
|
||||
<properties>
|
||||
<property key="emulateInstructionStateModifierClass" value="ghidra.program.emulation.m68kEmulateInstructionStateModifier"/>
|
||||
<property key="useropLibs" value="m68k,trig"/>
|
||||
<property key="assemblyRating:68000:BE:32:default" value="PLATINUM"/>
|
||||
</properties>
|
||||
<programcounter register="PC"/>
|
||||
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
/* ###
|
||||
* 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.program.emulation;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
|
||||
import ghidra.pcode.exec.*;
|
||||
import ghidra.pcode.exec.PcodeUseropLibraryFactory.UseropLibrary;
|
||||
|
||||
@UseropLibrary("m68k")
|
||||
public class M68kPcodeUseropLibraryFactory implements PcodeUseropLibraryFactory {
|
||||
@Override
|
||||
public <T> PcodeUseropLibrary<T> create(SleighLanguage language,
|
||||
PcodeArithmetic<T> arithmetic) {
|
||||
return PcodeUseropLibrary.nil();
|
||||
}
|
||||
}
|
||||
+1
@@ -22,6 +22,7 @@ import ghidra.pcode.memstate.MemoryState;
|
||||
import ghidra.pcodeCPort.error.LowlevelError;
|
||||
import ghidra.program.model.pcode.Varnode;
|
||||
|
||||
@Deprecated(forRemoval = true, since = "12.1")
|
||||
public class m68kEmulateInstructionStateModifier extends EmulateInstructionStateModifier {
|
||||
|
||||
/*
|
||||
|
||||
+1
@@ -25,6 +25,7 @@ import ghidra.pcode.memstate.MemoryState;
|
||||
import ghidra.program.model.pcode.Varnode;
|
||||
//import ghidra.pcode.emulate.callother.SignalingNaNOpBehavior;
|
||||
|
||||
@Deprecated(forRemoval = true, since = "12.1")
|
||||
public class AARCH64EmulateInstructionStateModifier extends EmulateInstructionStateModifier {
|
||||
|
||||
public AARCH64EmulateInstructionStateModifier(Emulate emu) {
|
||||
|
||||
+23
-9
@@ -27,25 +27,25 @@ import ghidra.program.model.pcode.Varnode;
|
||||
* https://developer.arm.com/documentation/ddi0602/2024-12/SIMD-FP-Instructions/TBL--Table-vector-lookup-
|
||||
*/
|
||||
@UseropLibrary("aarch64")
|
||||
public class AARCH64PcodeUseropLibraryFactory implements PcodeUseropLibraryFactory {
|
||||
public class Aarch64PcodeUseropLibraryFactory implements PcodeUseropLibraryFactory {
|
||||
@Override
|
||||
public <T> PcodeUseropLibrary<T> create(SleighLanguage language,
|
||||
PcodeArithmetic<T> arithmetic) {
|
||||
return new AARCH64PcodeUseropLibrary<>(language);
|
||||
return new Aarch64PcodeUseropLibrary<>(language);
|
||||
}
|
||||
|
||||
public static class AARCH64PcodeUseropLibrary<T> extends DefaultPcodeUseropLibrary<T> {
|
||||
public AARCH64PcodeUseropLibrary(SleighLanguage language) {
|
||||
public static class Aarch64PcodeUseropLibrary<T> extends AnnotatedPcodeUseropLibrary<T> {
|
||||
public Aarch64PcodeUseropLibrary(SleighLanguage language) {
|
||||
SleighPcodeUseropDefinition.Factory factory =
|
||||
new SleighPcodeUseropDefinition.Factory(language);
|
||||
|
||||
putOp(factory.define("MP_INT_ABS").params("n").body(args -> """
|
||||
if (n >= 0) goto <pos>;
|
||||
__op_output = -n;
|
||||
goto <done>;
|
||||
<pos>:
|
||||
goto <done>;
|
||||
<pos>
|
||||
__op_output = n;
|
||||
<done>:
|
||||
<done>
|
||||
""").build());
|
||||
|
||||
putOp(factory.define("SIMD_PIECE").params("simdBytes", "offset").body(args -> """
|
||||
@@ -74,7 +74,7 @@ public class AARCH64PcodeUseropLibraryFactory implements PcodeUseropLibraryFacto
|
||||
return "local table:16 = %s;\n".formatted(regs[0]);
|
||||
}
|
||||
int size = 16; // Table is always made up of 16-byte (128-bit) regs
|
||||
StringBuffer buf = new StringBuffer();
|
||||
StringBuilder buf = new StringBuilder();
|
||||
buf.append("local table:%d;\n".formatted(size * regs.length));
|
||||
for (int i = 0; i < regs.length; i++) {
|
||||
buf.append("table[%d,%d] = %s;\n".formatted(8 * size * i, 8 * size, regs[i]));
|
||||
@@ -84,7 +84,7 @@ public class AARCH64PcodeUseropLibraryFactory implements PcodeUseropLibraryFacto
|
||||
|
||||
protected String genIndex(int size, int regCount) {
|
||||
int tableSize = 16 * regCount;
|
||||
StringBuffer buf = new StringBuffer();
|
||||
StringBuilder buf = new StringBuilder();
|
||||
buf.append("local indicies:%d = m;\n".formatted(size));
|
||||
buf.append("local result:%d = init;\n".formatted(size));
|
||||
for (int i = 0; i < size; i++) {
|
||||
@@ -103,5 +103,19 @@ public class AARCH64PcodeUseropLibraryFactory implements PcodeUseropLibraryFacto
|
||||
buf.append("__op_output = result;");
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
@PcodeUserop(functional = true)
|
||||
public void CallSecureMonitor(int imm16) {
|
||||
}
|
||||
|
||||
@PcodeUserop(functional = true)
|
||||
public int ExclusiveMonitorPass(long addr, int rsize) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@PcodeUserop(functional = true)
|
||||
public byte ExclusiveMonitorsStatus() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -45,7 +45,7 @@ import ghidra.util.exception.MultipleCauses;
|
||||
import ghidra.util.task.ConsoleTaskMonitor;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
public class AARCH64PcodeLibraryTest extends AbstractGhidraHeadlessIntegrationTest {
|
||||
public class Aarch64PcodeLibraryTest extends AbstractGhidraHeadlessIntegrationTest {
|
||||
static final LanguageID LANG_ID_AARCH64 = new LanguageID("AARCH64:LE:64:v8A");
|
||||
|
||||
private SleighLanguage aarch64;
|
||||
@@ -293,19 +293,20 @@
|
||||
<pentry minsize="1" maxsize="500" align="4">
|
||||
<addr offset="0" space="stack"/>
|
||||
</pentry>
|
||||
</input>
|
||||
<output killedbycall="true">
|
||||
<pentry minsize="1" maxsize="4">
|
||||
<register name="r0"/>
|
||||
</pentry>
|
||||
</output>
|
||||
<unaffected>
|
||||
<register name="sp"/>
|
||||
</unaffected>
|
||||
</prototype>
|
||||
</input>
|
||||
<output killedbycall="true">
|
||||
<pentry minsize="1" maxsize="4">
|
||||
<register name="r0"/>
|
||||
</pentry>
|
||||
</output>
|
||||
<unaffected>
|
||||
<register name="sp"/>
|
||||
</unaffected>
|
||||
</prototype>
|
||||
|
||||
<callotherfixup targetop="setISAMode">
|
||||
<pcode incidentalcopy="true">
|
||||
<input name="newTB"/>
|
||||
<!-- NOP -->
|
||||
<body><![CDATA[
|
||||
r0 = r0;
|
||||
@@ -338,8 +339,7 @@
|
||||
|
||||
r12 = lr + r3;
|
||||
|
||||
ISAModeSwitch = (r12 & 1) != 1;
|
||||
TB = ISAModeSwitch;
|
||||
TB = (r12 & 1) != 1;
|
||||
pc = r12 & 0xfffffffe;
|
||||
goto [pc];
|
||||
]]></body>
|
||||
@@ -356,8 +356,7 @@
|
||||
offset = *:1 (tmpptr + r0);
|
||||
lr = lr + 2 * zext(offset);
|
||||
|
||||
ISAModeSwitch = (lr & 1) != 0;
|
||||
TB = ISAModeSwitch;
|
||||
TB = (lr & 1) != 0;
|
||||
pc = lr & 0xfffffffe;
|
||||
goto [pc];
|
||||
]]></body>
|
||||
@@ -374,8 +373,7 @@
|
||||
offset = *:1 (tmpptr + r0);
|
||||
lr = lr + 2 * sext(offset);
|
||||
|
||||
ISAModeSwitch = (lr & 1) != 0;
|
||||
TB = ISAModeSwitch;
|
||||
TB = (lr & 1) != 0;
|
||||
pc = lr & 0xfffffffe;
|
||||
goto [pc];
|
||||
]]></body>
|
||||
@@ -393,8 +391,7 @@
|
||||
offset = *:2 (tmpptr + index);
|
||||
lr = lr + 2 * sext(offset);
|
||||
|
||||
ISAModeSwitch = (lr & 1) != 0;
|
||||
TB = ISAModeSwitch;
|
||||
TB = (lr & 1) != 0;
|
||||
pc = lr & 0xfffffffe;
|
||||
goto [pc];
|
||||
]]></body>
|
||||
@@ -412,8 +409,7 @@
|
||||
offset = *:2 (tmpptr + index);
|
||||
lr = lr + 2 * zext(offset);
|
||||
|
||||
ISAModeSwitch = (lr & 1) != 0;
|
||||
TB = ISAModeSwitch;
|
||||
TB = (lr & 1) != 0;
|
||||
pc = lr & 0xfffffffe;
|
||||
goto [pc];
|
||||
]]></body>
|
||||
@@ -432,8 +428,7 @@
|
||||
offset = offset * 4;
|
||||
lr = lr + offset;
|
||||
|
||||
ISAModeSwitch = (lr & 1) != 0;
|
||||
TB = ISAModeSwitch;
|
||||
TB = (lr & 1) != 0;
|
||||
pc = lr & 0xfffffffe;
|
||||
goto [pc];
|
||||
]]></body>
|
||||
|
||||
@@ -15,7 +15,6 @@ define register offset=0x0084 size=4 [ r14_svc r13_svc spsr_svc ];
|
||||
define register offset=0x0090 size=8 [ mult_dat8 ]; # Special internal register for dealing with multiple stores/loads
|
||||
define register offset=0x0090 size=16 [ mult_dat16 ]; # Special internal register for dealing with multiple stores/loads
|
||||
define register offset=0x00A0 size=4 [ fpsr ]; # floating point state register (for FPA10 floating-point accelerator)
|
||||
define register offset=0x0078 size=1 [ ISAModeSwitch ]; # generic name for TB ThumbBit - set same as TB
|
||||
|
||||
@define FPSCR_N "fpscr[31,1]"
|
||||
@define FPSCR_Z "fpscr[30,1]"
|
||||
@@ -193,7 +192,7 @@ define pcodeop ReverseBitOrder;
|
||||
define pcodeop SendEvent;
|
||||
define pcodeop setEndianState;
|
||||
|
||||
# Copies ISAModeSwitch to TMode
|
||||
# Copies TB to TMode
|
||||
define pcodeop setISAMode;
|
||||
|
||||
macro affectflags() {
|
||||
@@ -204,14 +203,9 @@ macro affect_resflags() {
|
||||
ZR = tmpZR; NG = tmpNG;
|
||||
}
|
||||
|
||||
macro SetISAModeSwitch(value) {
|
||||
ISAModeSwitch = value;
|
||||
TB = ISAModeSwitch;
|
||||
}
|
||||
|
||||
macro SetThumbMode(value) {
|
||||
SetISAModeSwitch(value);
|
||||
setISAMode();
|
||||
TB = value;
|
||||
setISAMode(TB);
|
||||
}
|
||||
|
||||
#
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
<property key="useNewFunctionStackAnalysis" value="true"/>
|
||||
<property key="enableContiguousFunctionsOnly" value="false"/>
|
||||
<property key="emulateInstructionStateModifierClass" value="ghidra.program.emulation.ARMEmulateInstructionStateModifier"/>
|
||||
<property key="useropLibs" value="arm"/>
|
||||
</properties>
|
||||
<programcounter register="pc"/>
|
||||
<context_data>
|
||||
@@ -18,7 +19,11 @@
|
||||
<set name="spsr" val="0"/>
|
||||
</tracked_set>
|
||||
</context_data>
|
||||
|
||||
|
||||
<register_data>
|
||||
<register name="TB" alias="ISAModeSwitch"/>
|
||||
</register_data>
|
||||
|
||||
<default_symbols>
|
||||
<symbol name="MasterStackPointer" address="ram:0x0" entry="false" type="code_ptr"/>
|
||||
<symbol name="Reset" address="ram:0x4" entry="true" type="code_ptr"/>
|
||||
|
||||
@@ -162,6 +162,7 @@
|
||||
|
||||
<callotherfixup targetop="setISAMode">
|
||||
<pcode incidentalcopy="true">
|
||||
<input name="newTB"/>
|
||||
<!-- NOP -->
|
||||
<body><![CDATA[
|
||||
r0 = r0;
|
||||
@@ -194,8 +195,7 @@
|
||||
|
||||
r12 = lr + r3;
|
||||
|
||||
ISAModeSwitch = (r12 & 1) != 1;
|
||||
TB = ISAModeSwitch;
|
||||
TB = (r12 & 1) != 1;
|
||||
pc = r12 & 0xfffffffe;
|
||||
goto [pc];
|
||||
]]></body>
|
||||
@@ -212,8 +212,7 @@
|
||||
offset = *:1 (tmpptr + r0);
|
||||
lr = lr + 2 * zext(offset);
|
||||
|
||||
ISAModeSwitch = (lr & 1) != 0;
|
||||
TB = ISAModeSwitch;
|
||||
TB = (lr & 1) != 0;
|
||||
pc = lr & 0xfffffffe;
|
||||
goto [pc];
|
||||
]]></body>
|
||||
@@ -230,8 +229,7 @@
|
||||
offset = *:1 (tmpptr + r0);
|
||||
lr = lr + 2 * sext(offset);
|
||||
|
||||
ISAModeSwitch = (lr & 1) != 0;
|
||||
TB = ISAModeSwitch;
|
||||
TB = (lr & 1) != 0;
|
||||
pc = lr & 0xfffffffe;
|
||||
goto [pc];
|
||||
]]></body>
|
||||
@@ -249,8 +247,7 @@
|
||||
offset = *:2 (tmpptr + index);
|
||||
lr = lr + 2 * sext(offset);
|
||||
|
||||
ISAModeSwitch = (lr & 1) != 0;
|
||||
TB = ISAModeSwitch;
|
||||
TB = (lr & 1) != 0;
|
||||
pc = lr & 0xfffffffe;
|
||||
goto [pc];
|
||||
]]></body>
|
||||
@@ -268,8 +265,7 @@
|
||||
offset = *:2 (tmpptr + index);
|
||||
lr = lr + 2 * zext(offset);
|
||||
|
||||
ISAModeSwitch = (lr & 1) != 0;
|
||||
TB = ISAModeSwitch;
|
||||
TB = (lr & 1) != 0;
|
||||
pc = lr & 0xfffffffe;
|
||||
goto [pc];
|
||||
]]></body>
|
||||
@@ -288,8 +284,7 @@
|
||||
offset = offset * 4;
|
||||
lr = lr + offset;
|
||||
|
||||
ISAModeSwitch = (lr & 1) != 0;
|
||||
TB = ISAModeSwitch;
|
||||
TB = (lr & 1) != 0;
|
||||
pc = lr & 0xfffffffe;
|
||||
goto [pc];
|
||||
]]></body>
|
||||
|
||||
@@ -82,6 +82,7 @@
|
||||
|
||||
<callotherfixup targetop="setISAMode">
|
||||
<pcode incidentalcopy="true">
|
||||
<input name="newTB"/>
|
||||
<!-- NOP -->
|
||||
<body><![CDATA[
|
||||
r0 = r0;
|
||||
@@ -113,8 +114,7 @@
|
||||
|
||||
r12 = lr + r3;
|
||||
|
||||
ISAModeSwitch = (r12 & 1) != 1;
|
||||
TB = ISAModeSwitch;
|
||||
TB = (r12 & 1) != 1;
|
||||
pc = r12 & 0xfffffffe;
|
||||
goto [pc];
|
||||
]]></body>
|
||||
@@ -131,8 +131,7 @@
|
||||
offset = *:1 (tmpptr + r0);
|
||||
lr = lr + 2 * zext(offset);
|
||||
|
||||
ISAModeSwitch = (lr & 1) != 0;
|
||||
TB = ISAModeSwitch;
|
||||
TB = (lr & 1) != 0;
|
||||
pc = lr & 0xfffffffe;
|
||||
goto [pc];
|
||||
]]></body>
|
||||
@@ -149,8 +148,7 @@
|
||||
offset = *:1 (tmpptr + r0);
|
||||
lr = lr + 2 * sext(offset);
|
||||
|
||||
ISAModeSwitch = (lr & 1) != 0;
|
||||
TB = ISAModeSwitch;
|
||||
TB = (lr & 1) != 0;
|
||||
pc = lr & 0xfffffffe;
|
||||
goto [pc];
|
||||
]]></body>
|
||||
@@ -168,8 +166,7 @@
|
||||
offset = *:2 (tmpptr + index);
|
||||
lr = lr + 2 * sext(offset);
|
||||
|
||||
ISAModeSwitch = (lr & 1) != 0;
|
||||
TB = ISAModeSwitch;
|
||||
TB = (lr & 1) != 0;
|
||||
pc = lr & 0xfffffffe;
|
||||
goto [pc];
|
||||
]]></body>
|
||||
@@ -187,8 +184,7 @@
|
||||
offset = *:2 (tmpptr + index);
|
||||
lr = lr + 2 * zext(offset);
|
||||
|
||||
ISAModeSwitch = (lr & 1) != 0;
|
||||
TB = ISAModeSwitch;
|
||||
TB = (lr & 1) != 0;
|
||||
pc = lr & 0xfffffffe;
|
||||
goto [pc];
|
||||
]]></body>
|
||||
@@ -207,8 +203,7 @@
|
||||
offset = offset * 4;
|
||||
lr = lr + offset;
|
||||
|
||||
ISAModeSwitch = (lr & 1) != 0;
|
||||
TB = ISAModeSwitch;
|
||||
TB = (lr & 1) != 0;
|
||||
pc = lr & 0xfffffffe;
|
||||
goto [pc];
|
||||
]]></body>
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
<property key="enableSharedReturnAnalysis" value="false"/>
|
||||
<property key="enableContiguousFunctionsOnly" value="false"/>
|
||||
<property key="emulateInstructionStateModifierClass" value="ghidra.program.emulation.ARMEmulateInstructionStateModifier"/>
|
||||
<property key="useropLibs" value="arm"/>
|
||||
</properties>
|
||||
<programcounter register="pc"/>
|
||||
<context_data>
|
||||
@@ -18,7 +19,11 @@
|
||||
<set name="spsr" val="0"/>
|
||||
</tracked_set>
|
||||
</context_data>
|
||||
|
||||
|
||||
<register_data>
|
||||
<register name="TB" alias="ISAModeSwitch"/>
|
||||
</register_data>
|
||||
|
||||
<default_symbols>
|
||||
<symbol name="Reset" address="ram:0x0" entry="true"/>
|
||||
<symbol name="UndefinedInstruction" address="ram:0x4" entry="true"/>
|
||||
|
||||
@@ -228,6 +228,7 @@
|
||||
|
||||
<callotherfixup targetop="setISAMode">
|
||||
<pcode incidentalcopy="true">
|
||||
<input name="newTB"/>
|
||||
<!-- NOP -->
|
||||
<body><![CDATA[
|
||||
r0 = r0;
|
||||
|
||||
@@ -2317,7 +2317,7 @@ ArmPCRelImmed12: reloff is U23=0 & immed & rotate
|
||||
:blx HAddr24 is $(AMODE) & CALLoverride=0 & ARMcond=0 & cond=15 & c2527=5 & H24=0 & HAddr24
|
||||
{
|
||||
lr = inst_next;
|
||||
SetISAModeSwitch(1); # TMode done by HAddr24's globalset
|
||||
SetThumbMode(1); # TMode done by HAddr24's globalset
|
||||
call HAddr24;
|
||||
# don't do causes decompiler trouble TB = 0;
|
||||
} # Always changes to THUMB mode
|
||||
@@ -2325,7 +2325,7 @@ ArmPCRelImmed12: reloff is U23=0 & immed & rotate
|
||||
:blx HAddr24 is $(AMODE) & CALLoverride=1 & ARMcond=0 & cond=15 & c2527=5 & H24=0 & HAddr24
|
||||
{
|
||||
lr = inst_next;
|
||||
SetISAModeSwitch(1); # TMode done by HAddr24's globalset
|
||||
SetThumbMode(1); # TMode done by HAddr24's globalset
|
||||
goto HAddr24;
|
||||
} # Always changes to THUMB mode
|
||||
|
||||
@@ -2333,7 +2333,7 @@ ArmPCRelImmed12: reloff is U23=0 & immed & rotate
|
||||
:blx HAddr24 is $(AMODE) & ARMcond=0 & CALLoverride=0 & cond=15 & c2527=5 & H24=1 & HAddr24
|
||||
{
|
||||
lr = inst_next;
|
||||
SetISAModeSwitch(1); # TMode done by HAddr24's globalset
|
||||
SetThumbMode(1); # TMode done by HAddr24's globalset
|
||||
call HAddr24;
|
||||
# don't do causes decompiler trouble TB = 0;
|
||||
} # Always changes to THUMB mode
|
||||
@@ -2341,7 +2341,7 @@ ArmPCRelImmed12: reloff is U23=0 & immed & rotate
|
||||
:blx HAddr24 is $(AMODE) & ARMcond=0 & CALLoverride=1 & cond=15 & c2527=5 & H24=1 & HAddr24
|
||||
{
|
||||
lr = inst_next;
|
||||
SetISAModeSwitch(1); # TMode done by HAddr24's globalset
|
||||
SetThumbMode(1); # TMode done by HAddr24's globalset
|
||||
goto HAddr24;
|
||||
} # Always changes to THUMB mode
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
<property key="useNewFunctionStackAnalysis" value="true"/>
|
||||
<property key="enableContiguousFunctionsOnly" value="false"/>
|
||||
<property key="emulateInstructionStateModifierClass" value="ghidra.program.emulation.ARMEmulateInstructionStateModifier"/>
|
||||
<property key="useropLibs" value="arm"/>
|
||||
<property key="assemblyRating:ARM:BE:32:v7" value="PLATINUM"/>
|
||||
<property key="assemblyRating:ARM:LE:32:v7" value="PLATINUM"/>
|
||||
</properties>
|
||||
@@ -42,6 +43,8 @@
|
||||
</default_symbols>
|
||||
|
||||
<register_data>
|
||||
<register name="TB" alias="ISAModeSwitch"/>
|
||||
|
||||
<register name="q0" group="NEON" vector_lane_sizes="1,2,4"/>
|
||||
<register name="q1" group="NEON" vector_lane_sizes="1,2,4"/>
|
||||
<register name="q2" group="NEON" vector_lane_sizes="1,2,4"/>
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
<property key="useNewFunctionStackAnalysis" value="true"/>
|
||||
<property key="enableContiguousFunctionsOnly" value="false"/>
|
||||
<property key="emulateInstructionStateModifierClass" value="ghidra.program.emulation.ARMEmulateInstructionStateModifier"/>
|
||||
<property key="useropLibs" value="arm"/>
|
||||
<property key="assemblyRating:ARM:BE:32:v7" value="PLATINUM"/>
|
||||
<property key="assemblyRating:ARM:LE:32:v7" value="PLATINUM"/>
|
||||
</properties>
|
||||
@@ -43,6 +44,8 @@
|
||||
</default_symbols>
|
||||
|
||||
<register_data>
|
||||
<register name="TB" alias="ISAModeSwitch"/>
|
||||
|
||||
<register name="q0" group="NEON" vector_lane_sizes="1,2,4"/>
|
||||
<register name="q1" group="NEON" vector_lane_sizes="1,2,4"/>
|
||||
<register name="q2" group="NEON" vector_lane_sizes="1,2,4"/>
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
<property key="enableSharedReturnAnalysis" value="false"/>
|
||||
<property key="enableContiguousFunctionsOnly" value="false"/>
|
||||
<property key="emulateInstructionStateModifierClass" value="ghidra.program.emulation.ARMEmulateInstructionStateModifier"/>
|
||||
<property key="useropLibs" value="arm"/>
|
||||
</properties>
|
||||
<programcounter register="pc"/>
|
||||
<context_data>
|
||||
@@ -19,7 +20,11 @@
|
||||
<set name="spsr" val="0"/>
|
||||
</tracked_set>
|
||||
</context_data>
|
||||
|
||||
|
||||
<register_data>
|
||||
<register name="TB" alias="ISAModeSwitch"/>
|
||||
</register_data>
|
||||
|
||||
<default_symbols>
|
||||
<symbol name="Reset" address="ram:0x0" entry="true"/>
|
||||
<symbol name="UndefinedInstruction" address="ram:0x4" entry="true"/>
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
<property key="useNewFunctionStackAnalysis" value="true"/>
|
||||
<property key="enableContiguousFunctionsOnly" value="false"/>
|
||||
<property key="emulateInstructionStateModifierClass" value="ghidra.program.emulation.ARMEmulateInstructionStateModifier"/>
|
||||
<property key="useropLibs" value="arm"/>
|
||||
<property key="assemblyRating:ARM:BE:32:v7" value="PLATINUM"/>
|
||||
<property key="assemblyRating:ARM:LE:32:v7" value="PLATINUM"/>
|
||||
</properties>
|
||||
@@ -20,7 +21,11 @@
|
||||
<set name="spsr" val="0"/>
|
||||
</tracked_set>
|
||||
</context_data>
|
||||
|
||||
|
||||
<register_data>
|
||||
<register name="TB" alias="ISAModeSwitch"/>
|
||||
</register_data>
|
||||
|
||||
<default_symbols>
|
||||
<symbol name="Reset" address="ram:0x0" entry="true"/>
|
||||
<symbol name="UndefinedInstruction" address="ram:0x4" entry="true"/>
|
||||
|
||||
+1
@@ -26,6 +26,7 @@ import ghidra.program.model.lang.Register;
|
||||
import ghidra.program.model.lang.RegisterValue;
|
||||
import ghidra.program.model.pcode.Varnode;
|
||||
|
||||
@Deprecated(forRemoval = true, since = "12.1")
|
||||
public class ARMEmulateInstructionStateModifier extends EmulateInstructionStateModifier {
|
||||
|
||||
private Register TModeReg;
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
/* ###
|
||||
* 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.program.emulation;
|
||||
|
||||
public class ArmCpuState {
|
||||
private volatile boolean irqEnabled = true;
|
||||
private volatile boolean privileged = true;
|
||||
private volatile long mainStackPointer;
|
||||
private volatile long processStackPointer;
|
||||
private volatile boolean threadModePrivileged;
|
||||
private volatile boolean threadMode;
|
||||
|
||||
private volatile long basePriority;
|
||||
|
||||
public boolean isIrqEnabled() {
|
||||
return irqEnabled;
|
||||
}
|
||||
|
||||
public void setIrqEnabled(boolean irqEnabled) {
|
||||
this.irqEnabled = irqEnabled;
|
||||
}
|
||||
|
||||
public boolean isPrivileged() {
|
||||
return privileged;
|
||||
}
|
||||
|
||||
public void setPrivileged(boolean privileged) {
|
||||
this.privileged = privileged;
|
||||
}
|
||||
|
||||
public long getMainStackPointer() {
|
||||
return mainStackPointer;
|
||||
}
|
||||
|
||||
public void setMainStackPointer(long mainStackPointer) {
|
||||
this.mainStackPointer = mainStackPointer;
|
||||
}
|
||||
|
||||
public long getProcessStackPointer() {
|
||||
return processStackPointer;
|
||||
}
|
||||
|
||||
public void setProcessStackPointer(long processStackPointer) {
|
||||
this.processStackPointer = processStackPointer;
|
||||
}
|
||||
|
||||
public boolean isThreadModePrivileged() {
|
||||
return threadModePrivileged;
|
||||
}
|
||||
|
||||
public void setThreadModePrivileged(boolean threadModePrivileged) {
|
||||
this.threadModePrivileged = threadModePrivileged;
|
||||
}
|
||||
|
||||
public boolean isThreadMode() {
|
||||
return threadMode;
|
||||
}
|
||||
|
||||
public void setThreadMode(boolean threadMode) {
|
||||
this.threadMode = threadMode;
|
||||
}
|
||||
|
||||
public long getBasePriority() {
|
||||
return basePriority;
|
||||
}
|
||||
|
||||
public void setBasePriority(long basePriority) {
|
||||
this.basePriority = basePriority;
|
||||
}
|
||||
}
|
||||
+117
@@ -0,0 +1,117 @@
|
||||
/* ###
|
||||
* 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.program.emulation;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
|
||||
import ghidra.pcode.emu.DefaultPcodeThread.PcodeThreadExecutor;
|
||||
import ghidra.pcode.exec.*;
|
||||
import ghidra.pcode.exec.PcodeUseropLibraryFactory.UseropLibrary;
|
||||
import ghidra.program.model.lang.*;
|
||||
import ghidra.util.Msg;
|
||||
|
||||
@UseropLibrary("arm")
|
||||
public class ArmPcodeUseropLibraryFactory implements PcodeUseropLibraryFactory {
|
||||
@Override
|
||||
public <T> PcodeUseropLibrary<T> create(SleighLanguage language,
|
||||
PcodeArithmetic<T> arithmetic) {
|
||||
return new ArmPcodeUseropLibrary<>(language);
|
||||
}
|
||||
|
||||
public static class ArmPcodeUseropLibrary<T> extends AnnotatedPcodeUseropLibrary<T> {
|
||||
private final RegisterValue tMode;
|
||||
private final RegisterValue aMode;
|
||||
|
||||
// LATER: This should probably be injected
|
||||
private final ArmCpuState cpuState = new ArmCpuState();
|
||||
|
||||
public ArmPcodeUseropLibrary(Language language) {
|
||||
Register tModeReg = language.getRegister("TMode");
|
||||
if (tModeReg != null) {
|
||||
tMode = new RegisterValue(tModeReg, BigInteger.ONE);
|
||||
aMode = new RegisterValue(tModeReg, BigInteger.ZERO);
|
||||
}
|
||||
else {
|
||||
tMode = null;
|
||||
aMode = null;
|
||||
}
|
||||
}
|
||||
|
||||
@PcodeUserop(modifiesContext = true)
|
||||
public void setISAMode(@OpExecutor PcodeExecutor<T> exec, boolean tb) {
|
||||
if (!(exec instanceof PcodeThreadExecutor<T> tExec)) {
|
||||
return;
|
||||
}
|
||||
tExec.getThread().overrideContext(tb ? tMode : aMode);
|
||||
}
|
||||
|
||||
@PcodeUserop(functional = true)
|
||||
public void disableIRQinterrupts() {
|
||||
cpuState.setIrqEnabled(false);
|
||||
}
|
||||
|
||||
@PcodeUserop(functional = true)
|
||||
public void enableIRQinterrupts() {
|
||||
cpuState.setIrqEnabled(true);
|
||||
}
|
||||
|
||||
@PcodeUserop(functional = true, hasSideEffects = false)
|
||||
public boolean isCurrentModePrivileged() {
|
||||
return cpuState.isPrivileged();
|
||||
}
|
||||
|
||||
@PcodeUserop(functional = true)
|
||||
public void setMainStackPointer(long mainStackPointer) {
|
||||
cpuState.setMainStackPointer(mainStackPointer);
|
||||
}
|
||||
|
||||
@PcodeUserop(functional = true)
|
||||
public void setProcessStackPointer(long processStackPointer) {
|
||||
cpuState.setProcessStackPointer(processStackPointer);
|
||||
}
|
||||
|
||||
@PcodeUserop(functional = true, hasSideEffects = false)
|
||||
public long getProcessStackPointer() {
|
||||
return cpuState.getProcessStackPointer();
|
||||
}
|
||||
|
||||
@PcodeUserop(functional = true/*Maybe not*/)
|
||||
public void DataSynchronizationBarrier(int todo) {
|
||||
Msg.warn(this, "TODO:DataSyncBarrier");
|
||||
}
|
||||
|
||||
@PcodeUserop(functional = true/*Maybe not*/)
|
||||
public void InstructionSynchronizationBarrier(int todo) {
|
||||
Msg.warn(this, "TODO:InsSyncBarrier");
|
||||
}
|
||||
|
||||
@PcodeUserop(functional = true)
|
||||
public void setThreadModePrivileged(boolean privileged) {
|
||||
cpuState.setThreadModePrivileged(privileged);
|
||||
}
|
||||
|
||||
@PcodeUserop(functional = true, hasSideEffects = false)
|
||||
public boolean isThreadMode() {
|
||||
return cpuState.isThreadMode();
|
||||
}
|
||||
|
||||
@PcodeUserop(functional = true)
|
||||
public void setBasePriority(long basePriority) {
|
||||
cpuState.setBasePriority(basePriority);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -919,9 +919,12 @@ DXuPos: pos is lsb [ pos = lsb + 32; ] { tmp:1
|
||||
DinsXSize: mysize is msbd & lsb [ mysize = msbd - lsb + 1 + 32; ] { tmp:1 = mysize; export tmp; }
|
||||
@endif
|
||||
|
||||
define pcodeop setISAMode;
|
||||
|
||||
macro JXWritePC(addr) {
|
||||
@ifdef ISA_VARIANT
|
||||
ISAModeSwitch = (addr & 0x1) != 0;
|
||||
setISAMode(ISAModeSwitch);
|
||||
tmp:$(REGSIZE) = -2;
|
||||
tmp = tmp & addr;
|
||||
pc = tmp;
|
||||
|
||||
@@ -639,9 +639,10 @@ SAVE_TOP: SAVE_ARG^EXT_FRAME^SAVE_RA^SAVE_SREG^SAVE_STAT is EXT_FRAME & SAVE_RA
|
||||
|
||||
:jalx Abs26_m16 is ISA_MODE=1 & RELP=1 & ext_isjal=1 & ext_tgt_x=1 & Abs26_m16
|
||||
[ ext_delay=0b10; ISA_MODE = 0; globalset(Abs26_m16, ISA_MODE); globalset(inst_next, ext_delay); ] {
|
||||
ra = inst_next | 0x1;
|
||||
ra = inst_next | 0x1;
|
||||
delayslot( 1 );
|
||||
ISAModeSwitch = 0;
|
||||
ISAModeSwitch = 0;
|
||||
setISAMode(ISAModeSwitch);
|
||||
call Abs26_m16;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
<properties>
|
||||
<property key="addressesDoNotAppearDirectlyInCode" value="true"/>
|
||||
<property key="emulateInstructionStateModifierClass" value="ghidra.program.emulation.MIPSEmulateInstructionStateModifier"/>
|
||||
<property key="useropLibs" value="mips"/>
|
||||
<property key="assemblyRating:MIPS:BE:32:default" value="PLATINUM"/>
|
||||
</properties>
|
||||
<programcounter register="pc"/>
|
||||
|
||||
@@ -1018,6 +1018,7 @@ define pcodeop SYNC;
|
||||
ra = inst_next;
|
||||
delayslot( 1 );
|
||||
ISAModeSwitch = 1;
|
||||
setISAMode(ISAModeSwitch);
|
||||
call Abs26;
|
||||
}
|
||||
@endif
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
<properties>
|
||||
<property key="addressesDoNotAppearDirectlyInCode" value="true"/>
|
||||
<property key="emulateInstructionStateModifierClass" value="ghidra.program.emulation.MIPSEmulateInstructionStateModifier"/>
|
||||
<property key="useropLibs" value="mips"/>
|
||||
<property key="assemblyRating:MIPS:BE:32:R6" value="PLATINUM"/>
|
||||
</properties>
|
||||
<programcounter register="pc"/>
|
||||
|
||||
@@ -154,5 +154,15 @@
|
||||
</localrange>
|
||||
</prototype>
|
||||
</default_proto>
|
||||
|
||||
|
||||
<callotherfixup targetop="setISAMode">
|
||||
<pcode incidentalcopy="true">
|
||||
<input name="newMode"/>
|
||||
<!-- NOP -->
|
||||
<body><![CDATA[
|
||||
v0 = v0;
|
||||
]]></body>
|
||||
</pcode>
|
||||
</callotherfixup>
|
||||
|
||||
</compiler_spec>
|
||||
|
||||
@@ -84,5 +84,15 @@
|
||||
</localrange>
|
||||
</prototype>
|
||||
</default_proto>
|
||||
|
||||
|
||||
<callotherfixup targetop="setISAMode">
|
||||
<pcode incidentalcopy="true">
|
||||
<input name="newMode"/>
|
||||
<!-- NOP -->
|
||||
<body><![CDATA[
|
||||
v0 = v0;
|
||||
]]></body>
|
||||
</pcode>
|
||||
</callotherfixup>
|
||||
|
||||
</compiler_spec>
|
||||
|
||||
@@ -183,6 +183,15 @@
|
||||
<register name="gp"/> <!-- Compilers may save gp to the stack before a call and restore it afterward -->
|
||||
</internal_storage>
|
||||
</prototype>
|
||||
|
||||
|
||||
|
||||
<callotherfixup targetop="setISAMode">
|
||||
<pcode incidentalcopy="true">
|
||||
<input name="newMode"/>
|
||||
<!-- NOP -->
|
||||
<body><![CDATA[
|
||||
v0 = v0;
|
||||
]]></body>
|
||||
</pcode>
|
||||
</callotherfixup>
|
||||
|
||||
</compiler_spec>
|
||||
|
||||
@@ -174,5 +174,15 @@
|
||||
<register name="gp"/> <!-- Compilers may save gp to the stack before a call and restore it afterward -->
|
||||
</internal_storage>
|
||||
</prototype>
|
||||
|
||||
|
||||
<callotherfixup targetop="setISAMode">
|
||||
<pcode incidentalcopy="true">
|
||||
<input name="newMode"/>
|
||||
<!-- NOP -->
|
||||
<body><![CDATA[
|
||||
v0 = v0;
|
||||
]]></body>
|
||||
</pcode>
|
||||
</callotherfixup>
|
||||
|
||||
</compiler_spec>
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
<properties>
|
||||
<property key="addressesDoNotAppearDirectlyInCode" value="true"/>
|
||||
<property key="emulateInstructionStateModifierClass" value="ghidra.program.emulation.MIPSEmulateInstructionStateModifier"/>
|
||||
<property key="useropLibs" value="mips"/>
|
||||
<property key="assemblyRating:MIPS:BE:32:micro" value="PLATINUM"/>
|
||||
</properties>
|
||||
<programcounter register="pc"/>
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
<properties>
|
||||
<property key="addressesDoNotAppearDirectlyInCode" value="true"/>
|
||||
<property key="emulateInstructionStateModifierClass" value="ghidra.program.emulation.MIPSEmulateInstructionStateModifier"/>
|
||||
<property key="useropLibs" value="mips"/>
|
||||
<property key="assemblyRating:MIPS:BE:64:64-32addr" value="PLATINUM"/>
|
||||
<property key="assemblyRating:MIPS:BE:64:default" value="PLATINUM"/>
|
||||
</properties>
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
<properties>
|
||||
<property key="addressesDoNotAppearDirectlyInCode" value="true"/>
|
||||
<property key="emulateInstructionStateModifierClass" value="ghidra.program.emulation.MIPSEmulateInstructionStateModifier"/>
|
||||
<property key="useropLibs" value="mips"/>
|
||||
<property key="assemblyRating:MIPS:BE:64:R6" value="PLATINUM"/>
|
||||
</properties>
|
||||
<programcounter register="pc"/>
|
||||
|
||||
@@ -133,4 +133,15 @@
|
||||
</unaffected>
|
||||
</prototype>
|
||||
</default_proto>
|
||||
|
||||
<callotherfixup targetop="setISAMode">
|
||||
<pcode incidentalcopy="true">
|
||||
<input name="newMode"/>
|
||||
<!-- NOP -->
|
||||
<body><![CDATA[
|
||||
v0 = v0;
|
||||
]]></body>
|
||||
</pcode>
|
||||
</callotherfixup>
|
||||
|
||||
</compiler_spec>
|
||||
|
||||
@@ -125,4 +125,15 @@
|
||||
</localrange>
|
||||
</prototype>
|
||||
</default_proto>
|
||||
|
||||
<callotherfixup targetop="setISAMode">
|
||||
<pcode incidentalcopy="true">
|
||||
<input name="newMode"/>
|
||||
<!-- NOP -->
|
||||
<body><![CDATA[
|
||||
v0 = v0;
|
||||
]]></body>
|
||||
</pcode>
|
||||
</callotherfixup>
|
||||
|
||||
</compiler_spec>
|
||||
|
||||
@@ -95,4 +95,15 @@
|
||||
</unaffected>
|
||||
</prototype>
|
||||
</default_proto>
|
||||
|
||||
<callotherfixup targetop="setISAMode">
|
||||
<pcode incidentalcopy="true">
|
||||
<input name="newMode"/>
|
||||
<!-- NOP -->
|
||||
<body><![CDATA[
|
||||
v0 = v0;
|
||||
]]></body>
|
||||
</pcode>
|
||||
</callotherfixup>
|
||||
|
||||
</compiler_spec>
|
||||
|
||||
@@ -186,4 +186,15 @@
|
||||
</killedbycall>
|
||||
</prototype>
|
||||
</default_proto>
|
||||
|
||||
<callotherfixup targetop="setISAMode">
|
||||
<pcode incidentalcopy="true">
|
||||
<input name="newMode"/>
|
||||
<!-- NOP -->
|
||||
<body><![CDATA[
|
||||
v0 = v0;
|
||||
]]></body>
|
||||
</pcode>
|
||||
</callotherfixup>
|
||||
|
||||
</compiler_spec>
|
||||
|
||||
@@ -170,4 +170,15 @@
|
||||
</killedbycall>
|
||||
</prototype>
|
||||
</default_proto>
|
||||
|
||||
<callotherfixup targetop="setISAMode">
|
||||
<pcode incidentalcopy="true">
|
||||
<input name="newMode"/>
|
||||
<!-- NOP -->
|
||||
<body><![CDATA[
|
||||
v0 = v0;
|
||||
]]></body>
|
||||
</pcode>
|
||||
</callotherfixup>
|
||||
|
||||
</compiler_spec>
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
<properties>
|
||||
<property key="addressesDoNotAppearDirectlyInCode" value="true"/>
|
||||
<property key="emulateInstructionStateModifierClass" value="ghidra.program.emulation.MIPSEmulateInstructionStateModifier"/>
|
||||
<property key="useropLibs" value="mips"/>
|
||||
</properties>
|
||||
<programcounter register="pc"/>
|
||||
<context_data>
|
||||
|
||||
@@ -2369,7 +2369,8 @@ STORE_TOP16: STORE_SREG^ra,EXT_CODE4E(sp) is mic_listr6 & REL6=1 & STORE_SREG &
|
||||
:jalx Abs26_mic2 is ISA_MODE=1 & RELP=0 & mic_op=0b111100 & REL6=0 & mic_code ; Abs26_mic2 [ ext_32_code = mic_code; ISA_MODE = 0; globalset(Abs26_mic2, ISA_MODE);] {
|
||||
ra = inst_next | 0x1;
|
||||
delayslot( 1 );
|
||||
ISAModeSwitch = 0;
|
||||
ISAModeSwitch = 0;
|
||||
setISAMode(ISAModeSwitch);
|
||||
call Abs26_mic2;
|
||||
}
|
||||
|
||||
|
||||
+3
-2
@@ -4,9 +4,9 @@
|
||||
* 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.
|
||||
@@ -26,6 +26,7 @@ import ghidra.program.model.lang.RegisterValue;
|
||||
import ghidra.program.model.pcode.PcodeOp;
|
||||
//import ghidra.pcode.emulate.callother.SignalingNaNOpBehavior;
|
||||
|
||||
@Deprecated(forRemoval = true, since = "12.1")
|
||||
public class MIPSEmulateInstructionStateModifier extends EmulateInstructionStateModifier {
|
||||
|
||||
private Register ismReg;
|
||||
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
/* ###
|
||||
* 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.program.emulation;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
|
||||
import ghidra.pcode.emu.DefaultPcodeThread.PcodeThreadExecutor;
|
||||
import ghidra.pcode.exec.*;
|
||||
import ghidra.pcode.exec.PcodeUseropLibraryFactory.UseropLibrary;
|
||||
import ghidra.program.model.lang.*;
|
||||
|
||||
@UseropLibrary("mips")
|
||||
public class MipsPcodeUseropLibraryFactory implements PcodeUseropLibraryFactory {
|
||||
@Override
|
||||
public <T> PcodeUseropLibrary<T> create(SleighLanguage language,
|
||||
PcodeArithmetic<T> arithmetic) {
|
||||
return new MipsPcodeUseropLibrary<>(language);
|
||||
}
|
||||
|
||||
public static class MipsPcodeUseropLibrary<T> extends AnnotatedPcodeUseropLibrary<T> {
|
||||
private final RegisterValue mode0;
|
||||
private final RegisterValue mode1;
|
||||
|
||||
public MipsPcodeUseropLibrary(Language language) {
|
||||
Register isaModeReg = language.getRegister("ISA_MODE");
|
||||
if (isaModeReg != null) {
|
||||
mode0 = new RegisterValue(isaModeReg, BigInteger.ZERO);
|
||||
mode1 = new RegisterValue(isaModeReg, BigInteger.ONE);
|
||||
}
|
||||
else {
|
||||
mode0 = null;
|
||||
mode1 = null;
|
||||
}
|
||||
}
|
||||
|
||||
@PcodeUserop(modifiesContext = true)
|
||||
public void setISAMode(@OpExecutor PcodeExecutor<T> exec, boolean mode) {
|
||||
if (!(exec instanceof PcodeThreadExecutor<T> tExec)) {
|
||||
return;
|
||||
}
|
||||
tExec.getThread().overrideContext(mode ? mode1 : mode0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@
|
||||
<properties>
|
||||
<property key="addressesDoNotAppearDirectlyInCode" value="true"/>
|
||||
<property key="emulateInstructionStateModifierClass" value="ghidra.program.emulation.PPCEmulateInstructionStateModifier"/>
|
||||
<property key="useropLibs" value="ppc"/>
|
||||
<property key="assemblyRating:PowerPC:BE:32:default" value="PLATINUM"/>
|
||||
</properties>
|
||||
<programcounter register="pc"/>
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
<properties>
|
||||
<property key="addressesDoNotAppearDirectlyInCode" value="true"/>
|
||||
<property key="emulateInstructionStateModifierClass" value="ghidra.program.emulation.PPCEmulateInstructionStateModifier"/>
|
||||
<property key="useropLibs" value="ppc"/>
|
||||
</properties>
|
||||
|
||||
<programcounter register="pc"/>
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
<properties>
|
||||
<property key="addressesDoNotAppearDirectlyInCode" value="true"/>
|
||||
<property key="emulateInstructionStateModifierClass" value="ghidra.program.emulation.PPCEmulateInstructionStateModifier"/>
|
||||
<property key="useropLibs" value="ppc"/>
|
||||
<property key="assemblyRating:PowerPC:BE:64:A2-32addr" value="PLATINUM"/>
|
||||
<property key="assemblyRating:PowerPC:BE:64:A2ALT-32addr" value="PLATINUM"/>
|
||||
<property key="assemblyRating:PowerPC:BE:64:default" value="PLATINUM"/>
|
||||
|
||||
+1
@@ -24,6 +24,7 @@ import ghidra.pcode.memstate.MemoryState;
|
||||
import ghidra.pcodeCPort.error.LowlevelError;
|
||||
import ghidra.program.model.pcode.Varnode;
|
||||
|
||||
@Deprecated(forRemoval = true, since = "12.1")
|
||||
public class PPCEmulateInstructionStateModifier extends EmulateInstructionStateModifier {
|
||||
|
||||
public PPCEmulateInstructionStateModifier(Emulate emu) {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user