mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 10:49:34 +02:00
GP-2235 Eliminate threading conflict when using context for delayslot
This commit is contained in:
parent
28f59b8fa3
commit
ab31812dd4
2 changed files with 129 additions and 80 deletions
|
@ -13,10 +13,6 @@
|
||||||
* 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.
|
||||||
*/
|
*/
|
||||||
/*
|
|
||||||
* Created on Feb 9, 2005
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package ghidra.app.plugin.processors.sleigh;
|
package ghidra.app.plugin.processors.sleigh;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
@ -161,19 +157,22 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
||||||
|
|
||||||
private static void addExplicitFlow(ConstructState state, OpTpl op, int flags,
|
private static void addExplicitFlow(ConstructState state, OpTpl op, int flags,
|
||||||
FlowSummary summary) {
|
FlowSummary summary) {
|
||||||
if (summary.flowState == null)
|
if (summary.flowState == null) {
|
||||||
summary.flowState = new ArrayList<>();
|
summary.flowState = new ArrayList<>();
|
||||||
|
}
|
||||||
FlowRecord res = new FlowRecord();
|
FlowRecord res = new FlowRecord();
|
||||||
summary.flowState.add(res);
|
summary.flowState.add(res);
|
||||||
res.flowFlags = flags;
|
res.flowFlags = flags;
|
||||||
res.op = op;
|
res.op = op;
|
||||||
res.addressnode = null;
|
res.addressnode = null;
|
||||||
VarnodeTpl dest = op.getInput()[0]; // First varnode input contains the destination address
|
VarnodeTpl dest = op.getInput()[0]; // First varnode input contains the destination address
|
||||||
if ((flags & (JUMPOUT | CALL | CROSSBUILD)) == 0)
|
if ((flags & (JUMPOUT | CALL | CROSSBUILD)) == 0) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
// If the flow is out of the instruction, store the ConstructState so we can easily calculate address
|
// If the flow is out of the instruction, store the ConstructState so we can easily calculate address
|
||||||
if (state == null)
|
if (state == null) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
if ((flags & CROSSBUILD) != 0) {
|
if ((flags & CROSSBUILD) != 0) {
|
||||||
res.addressnode = state;
|
res.addressnode = state;
|
||||||
}
|
}
|
||||||
|
@ -191,6 +190,7 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
||||||
* Walk the pcode templates in the order they would be emitted.
|
* Walk the pcode templates in the order they would be emitted.
|
||||||
* Collect flowFlags FlowRecords
|
* Collect flowFlags FlowRecords
|
||||||
* @param walker the pcode template walker
|
* @param walker the pcode template walker
|
||||||
|
* @return a summary of the flow information
|
||||||
*/
|
*/
|
||||||
public static FlowSummary walkTemplates(OpTplWalker walker) {
|
public static FlowSummary walkTemplates(OpTplWalker walker) {
|
||||||
FlowSummary res = new FlowSummary();
|
FlowSummary res = new FlowSummary();
|
||||||
|
@ -218,24 +218,31 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
||||||
break;
|
break;
|
||||||
case PcodeOp.BRANCH:
|
case PcodeOp.BRANCH:
|
||||||
destType = res.lastop.getInput()[0].getOffset().getType();
|
destType = res.lastop.getInput()[0].getOffset().getType();
|
||||||
if (destType == ConstTpl.J_NEXT)
|
if (destType == ConstTpl.J_NEXT) {
|
||||||
flags = BRANCH_TO_END;
|
flags = BRANCH_TO_END;
|
||||||
else if (destType == ConstTpl.J_START)
|
}
|
||||||
|
else if (destType == ConstTpl.J_START) {
|
||||||
flags = NO_FALLTHRU;
|
flags = NO_FALLTHRU;
|
||||||
else if (destType == ConstTpl.J_RELATIVE)
|
}
|
||||||
|
else if (destType == ConstTpl.J_RELATIVE) {
|
||||||
flags = NO_FALLTHRU;
|
flags = NO_FALLTHRU;
|
||||||
else
|
}
|
||||||
|
else {
|
||||||
flags = JUMPOUT | NO_FALLTHRU;
|
flags = JUMPOUT | NO_FALLTHRU;
|
||||||
|
}
|
||||||
addExplicitFlow(walker.getState(), res.lastop, flags, res);
|
addExplicitFlow(walker.getState(), res.lastop, flags, res);
|
||||||
break;
|
break;
|
||||||
case PcodeOp.CBRANCH:
|
case PcodeOp.CBRANCH:
|
||||||
destType = res.lastop.getInput()[0].getOffset().getType();
|
destType = res.lastop.getInput()[0].getOffset().getType();
|
||||||
if (destType == ConstTpl.J_NEXT)
|
if (destType == ConstTpl.J_NEXT) {
|
||||||
flags = BRANCH_TO_END;
|
flags = BRANCH_TO_END;
|
||||||
else if ((destType != ConstTpl.J_START) && (destType != ConstTpl.J_RELATIVE))
|
}
|
||||||
|
else if ((destType != ConstTpl.J_START) && (destType != ConstTpl.J_RELATIVE)) {
|
||||||
flags = JUMPOUT;
|
flags = JUMPOUT;
|
||||||
else
|
}
|
||||||
|
else {
|
||||||
flags = 0;
|
flags = 0;
|
||||||
|
}
|
||||||
addExplicitFlow(walker.getState(), res.lastop, flags, res);
|
addExplicitFlow(walker.getState(), res.lastop, flags, res);
|
||||||
break;
|
break;
|
||||||
case PcodeOp.CALL:
|
case PcodeOp.CALL:
|
||||||
|
@ -252,8 +259,9 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
||||||
break;
|
break;
|
||||||
case PcodeOp.INDIRECT: // Encode delayslot
|
case PcodeOp.INDIRECT: // Encode delayslot
|
||||||
destType = (int) res.lastop.getInput()[0].getOffset().getReal();
|
destType = (int) res.lastop.getInput()[0].getOffset().getReal();
|
||||||
if (destType > res.delay)
|
if (destType > res.delay) {
|
||||||
res.delay = destType;
|
res.delay = destType;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -263,8 +271,9 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static FlowType flowListToFlowType(List<FlowRecord> flowstate) {
|
public static FlowType flowListToFlowType(List<FlowRecord> flowstate) {
|
||||||
if (flowstate == null)
|
if (flowstate == null) {
|
||||||
return RefType.FALL_THROUGH;
|
return RefType.FALL_THROUGH;
|
||||||
|
}
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
for (FlowRecord rec : flowstate) {
|
for (FlowRecord rec : flowstate) {
|
||||||
flags &= ~(NO_FALLTHRU | CROSSBUILD | LABEL);
|
flags &= ~(NO_FALLTHRU | CROSSBUILD | LABEL);
|
||||||
|
@ -307,8 +316,9 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
||||||
|
|
||||||
private static FlowType convertFlowFlags(int flowFlags) {
|
private static FlowType convertFlowFlags(int flowFlags) {
|
||||||
|
|
||||||
if ((flowFlags & LABEL) != 0)
|
if ((flowFlags & LABEL) != 0) {
|
||||||
flowFlags |= BRANCH_TO_END;
|
flowFlags |= BRANCH_TO_END;
|
||||||
|
}
|
||||||
flowFlags &= ~(CROSSBUILD | LABEL);
|
flowFlags &= ~(CROSSBUILD | LABEL);
|
||||||
// NOTE: If prototype has cross-build, flow must be determined dynamically
|
// NOTE: If prototype has cross-build, flow must be determined dynamically
|
||||||
switch (flowFlags) { // Convert flags to a standard flowtype
|
switch (flowFlags) { // Convert flags to a standard flowtype
|
||||||
|
@ -395,8 +405,9 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
if (obj == null)
|
if (obj == null) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
return (hashCode() == obj.hashCode()); // Trust entirely in hash
|
return (hashCode() == obj.hashCode()); // Trust entirely in hash
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -415,8 +426,9 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FlowType getFlowType(InstructionContext context) {
|
public FlowType getFlowType(InstructionContext context) {
|
||||||
if (!hasCrossBuilds)
|
if (!hasCrossBuilds) {
|
||||||
return flowType;
|
return flowType;
|
||||||
|
}
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
try {
|
try {
|
||||||
flags = gatherFlags(0, context, -1);
|
flags = gatherFlags(0, context, -1);
|
||||||
|
@ -457,6 +469,7 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
|
// Treat bad instructions as not part of delay slot
|
||||||
}
|
}
|
||||||
return delayInstrCnt;
|
return delayInstrCnt;
|
||||||
}
|
}
|
||||||
|
@ -473,8 +486,9 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getOpType(int opIndex, InstructionContext context) {
|
public int getOpType(int opIndex, InstructionContext context) {
|
||||||
if (opIndex < 0 || opIndex >= opresolve.length)
|
if (opIndex < 0 || opIndex >= opresolve.length) {
|
||||||
return OperandType.DYNAMIC;
|
return OperandType.DYNAMIC;
|
||||||
|
}
|
||||||
|
|
||||||
SleighParserContext protoContext;
|
SleighParserContext protoContext;
|
||||||
try {
|
try {
|
||||||
|
@ -485,20 +499,25 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
||||||
}
|
}
|
||||||
ConstructState opState = mnemonicState.getSubState(opresolve[opIndex]);
|
ConstructState opState = mnemonicState.getSubState(opresolve[opIndex]);
|
||||||
FixedHandle hand = protoContext.getFixedHandle(opState);
|
FixedHandle hand = protoContext.getFixedHandle(opState);
|
||||||
if (hand.isInvalid())
|
if (hand.isInvalid()) {
|
||||||
return OperandType.DYNAMIC;
|
return OperandType.DYNAMIC;
|
||||||
|
}
|
||||||
int indirect = isIndirect(opresolve[opIndex]) ? OperandType.INDIRECT : 0;
|
int indirect = isIndirect(opresolve[opIndex]) ? OperandType.INDIRECT : 0;
|
||||||
if (hand.offset_space == null) { // Static handle
|
if (hand.offset_space == null) { // Static handle
|
||||||
int type = hand.space.getType();
|
int type = hand.space.getType();
|
||||||
if (type == AddressSpace.TYPE_REGISTER)
|
if (type == AddressSpace.TYPE_REGISTER) {
|
||||||
return OperandType.REGISTER | indirect;
|
return OperandType.REGISTER | indirect;
|
||||||
if (type == AddressSpace.TYPE_CONSTANT)
|
}
|
||||||
|
if (type == AddressSpace.TYPE_CONSTANT) {
|
||||||
return OperandType.SCALAR | indirect;
|
return OperandType.SCALAR | indirect;
|
||||||
|
}
|
||||||
OperandSymbol sym = mnemonicState.getConstructor().getOperand(opresolve[opIndex]);
|
OperandSymbol sym = mnemonicState.getConstructor().getOperand(opresolve[opIndex]);
|
||||||
if (sym.isCodeAddress())
|
if (sym.isCodeAddress()) {
|
||||||
return (OperandType.ADDRESS | OperandType.CODE | indirect);
|
return (OperandType.ADDRESS | OperandType.CODE | indirect);
|
||||||
if (type == AddressSpace.TYPE_RAM)
|
}
|
||||||
|
if (type == AddressSpace.TYPE_RAM) {
|
||||||
return (OperandType.ADDRESS | OperandType.DATA | indirect);
|
return (OperandType.ADDRESS | OperandType.DATA | indirect);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return OperandType.DYNAMIC | indirect;
|
return OperandType.DYNAMIC | indirect;
|
||||||
}
|
}
|
||||||
|
@ -530,6 +549,7 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
||||||
return context.getAddress().addNoWrap(getFallThroughOffset(context));
|
return context.getAddress().addNoWrap(getFallThroughOffset(context));
|
||||||
}
|
}
|
||||||
catch (AddressOverflowException e) {
|
catch (AddressOverflowException e) {
|
||||||
|
// Return null if fallthru goes beyond boundary of address space
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
@ -565,13 +585,16 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
||||||
private int gatherFlags(int curflags, InstructionContext context, int secnum)
|
private int gatherFlags(int curflags, InstructionContext context, int secnum)
|
||||||
throws MemoryAccessException, UnknownContextException {
|
throws MemoryAccessException, UnknownContextException {
|
||||||
List<FlowRecord> curlist = null;
|
List<FlowRecord> curlist = null;
|
||||||
if (secnum < 0)
|
if (secnum < 0) {
|
||||||
curlist = flowStateList;
|
curlist = flowStateList;
|
||||||
else if ((flowStateListNamed != null) && (secnum < flowStateListNamed.size()))
|
}
|
||||||
|
else if ((flowStateListNamed != null) && (secnum < flowStateListNamed.size())) {
|
||||||
curlist = flowStateListNamed.get(secnum);
|
curlist = flowStateListNamed.get(secnum);
|
||||||
|
}
|
||||||
|
|
||||||
if (curlist == null)
|
if (curlist == null) {
|
||||||
return curflags;
|
return curflags;
|
||||||
|
}
|
||||||
|
|
||||||
for (FlowRecord rec : curlist) {
|
for (FlowRecord rec : curlist) {
|
||||||
if ((rec.flowFlags & CROSSBUILD) != 0) {
|
if ((rec.flowFlags & CROSSBUILD) != 0) {
|
||||||
|
@ -611,20 +634,23 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
||||||
* @param res is the resulting flow Addresses
|
* @param res is the resulting flow Addresses
|
||||||
* @param parsecontext is the parsing context for the current instruction
|
* @param parsecontext is the parsing context for the current instruction
|
||||||
* @param context is the context for the particular address so crossbuilds can be resolved
|
* @param context is the context for the particular address so crossbuilds can be resolved
|
||||||
* @throws MemoryAccessException
|
* @throws MemoryAccessException if a memory error occurred while resolving instruction details
|
||||||
* @throws UnknownContextException
|
* @throws UnknownContextException if the gather encounters an instruction not previously parsed
|
||||||
*/
|
*/
|
||||||
private void gatherFlows(ArrayList<Address> res, SleighParserContext parsecontext,
|
private void gatherFlows(ArrayList<Address> res, SleighParserContext parsecontext,
|
||||||
InstructionContext context, int secnum)
|
InstructionContext context, int secnum)
|
||||||
throws MemoryAccessException, UnknownContextException {
|
throws MemoryAccessException, UnknownContextException {
|
||||||
List<FlowRecord> curlist = null;
|
List<FlowRecord> curlist = null;
|
||||||
if (secnum < 0)
|
if (secnum < 0) {
|
||||||
curlist = flowStateList;
|
curlist = flowStateList;
|
||||||
else if ((flowStateListNamed != null) && (secnum < flowStateListNamed.size()))
|
}
|
||||||
|
else if ((flowStateListNamed != null) && (secnum < flowStateListNamed.size())) {
|
||||||
curlist = flowStateListNamed.get(secnum);
|
curlist = flowStateListNamed.get(secnum);
|
||||||
|
}
|
||||||
|
|
||||||
if (curlist == null)
|
if (curlist == null) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for (FlowRecord rec : curlist) {
|
for (FlowRecord rec : curlist) {
|
||||||
if ((rec.flowFlags & CROSSBUILD) != 0) {
|
if ((rec.flowFlags & CROSSBUILD) != 0) {
|
||||||
|
@ -654,8 +680,9 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
||||||
@Override
|
@Override
|
||||||
public Address[] getFlows(InstructionContext context) {
|
public Address[] getFlows(InstructionContext context) {
|
||||||
|
|
||||||
if (flowStateList.size() == 0)
|
if (flowStateList.size() == 0) {
|
||||||
return emptyFlow;
|
return emptyFlow;
|
||||||
|
}
|
||||||
|
|
||||||
ArrayList<Address> addresses = new ArrayList<>();
|
ArrayList<Address> addresses = new ArrayList<>();
|
||||||
try {
|
try {
|
||||||
|
@ -668,8 +695,9 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
||||||
return emptyFlow;
|
return emptyFlow;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (addresses.size() == 0)
|
if (addresses.size() == 0) {
|
||||||
return emptyFlow;
|
return emptyFlow;
|
||||||
|
}
|
||||||
return addresses.toArray(new Address[addresses.size()]);
|
return addresses.toArray(new Address[addresses.size()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -706,6 +734,7 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
||||||
sym.printList(walker, list);
|
sym.printList(walker, list);
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
|
// If the instruction produces memory errors, treat as if it has no representation list
|
||||||
}
|
}
|
||||||
|
|
||||||
AddressSpace curSpace = context.getAddress().getAddressSpace();
|
AddressSpace curSpace = context.getAddress().getAddressSpace();
|
||||||
|
@ -730,6 +759,7 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
||||||
return ct.getOperand(opresolve[opIndex]);
|
return ct.getOperand(opresolve[opIndex]);
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
|
// Return null for an out-of bounds opIndex
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -746,8 +776,9 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
||||||
protoContext = (SleighParserContext) context.getParserContext();
|
protoContext = (SleighParserContext) context.getParserContext();
|
||||||
ConstructState opState = mnemonicState.getSubState(opresolve[opIndex]);
|
ConstructState opState = mnemonicState.getSubState(opresolve[opIndex]);
|
||||||
hand = protoContext.getFixedHandle(opState);
|
hand = protoContext.getFixedHandle(opState);
|
||||||
if (hand.isInvalid())
|
if (hand.isInvalid()) {
|
||||||
return null;
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -769,8 +800,9 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
||||||
|
|
||||||
ConstructState opState = mnemonicState.getSubState(opresolve[opIndex]);
|
ConstructState opState = mnemonicState.getSubState(opresolve[opIndex]);
|
||||||
FixedHandle hand = protoContext.getFixedHandle(opState);
|
FixedHandle hand = protoContext.getFixedHandle(opState);
|
||||||
if (hand.isInvalid())
|
if (hand.isInvalid()) {
|
||||||
return null;
|
return null;
|
||||||
|
}
|
||||||
if (hand.space.getType() == AddressSpace.TYPE_CONSTANT) {
|
if (hand.space.getType() == AddressSpace.TYPE_CONSTANT) {
|
||||||
int size = hand.size;
|
int size = hand.size;
|
||||||
if (size == 0) {
|
if (size == 0) {
|
||||||
|
@ -784,6 +816,7 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
|
// If opIndex is out of bounds (or if there are memory errors) return a null Scalar
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -798,13 +831,15 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
||||||
SleighParserContext protoContext = (SleighParserContext) context.getParserContext();
|
SleighParserContext protoContext = (SleighParserContext) context.getParserContext();
|
||||||
ConstructState opState = mnemonicState.getSubState(opresolve[opIndex]);
|
ConstructState opState = mnemonicState.getSubState(opresolve[opIndex]);
|
||||||
FixedHandle hand = protoContext.getFixedHandle(opState);
|
FixedHandle hand = protoContext.getFixedHandle(opState);
|
||||||
if (hand.isInvalid())
|
if (hand.isInvalid()) {
|
||||||
return null;
|
return null;
|
||||||
|
}
|
||||||
if (hand.space.getType() == AddressSpace.TYPE_REGISTER) {
|
if (hand.space.getType() == AddressSpace.TYPE_REGISTER) {
|
||||||
return language.getRegister(hand.space, hand.offset_offset, hand.size);
|
return language.getRegister(hand.space, hand.offset_offset, hand.size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
|
// If opIndex is out of bounds (or if there are memory errors) return null
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -960,7 +995,7 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
||||||
bytecount += len;
|
bytecount += len;
|
||||||
}
|
}
|
||||||
while (bytecount < delaySlotByteCnt);
|
while (bytecount < delaySlotByteCnt);
|
||||||
protoContext.setDelaySlotLength(bytecount);
|
protoContext = new SleighParserContext(protoContext, bytecount);
|
||||||
}
|
}
|
||||||
ParserWalker walker = new ParserWalker(protoContext);
|
ParserWalker walker = new ParserWalker(protoContext);
|
||||||
walker.baseState();
|
walker.baseState();
|
||||||
|
@ -971,7 +1006,6 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
||||||
if (!isindelayslot) {
|
if (!isindelayslot) {
|
||||||
emit.resolveFinalFallthrough();
|
emit.resolveFinalFallthrough();
|
||||||
}
|
}
|
||||||
protoContext.setDelaySlotLength(0);
|
|
||||||
return emit.getPcodeOp();
|
return emit.getPcodeOp();
|
||||||
}
|
}
|
||||||
catch (NotYetImplementedException e) {
|
catch (NotYetImplementedException e) {
|
||||||
|
@ -1002,7 +1036,7 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
||||||
bytecount += len;
|
bytecount += len;
|
||||||
}
|
}
|
||||||
while (bytecount < delaySlotByteCnt);
|
while (bytecount < delaySlotByteCnt);
|
||||||
protoContext.setDelaySlotLength(bytecount);
|
protoContext = new SleighParserContext(protoContext, bytecount);
|
||||||
}
|
}
|
||||||
ParserWalker walker = new ParserWalker(protoContext);
|
ParserWalker walker = new ParserWalker(protoContext);
|
||||||
walker.baseState();
|
walker.baseState();
|
||||||
|
@ -1022,7 +1056,6 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
||||||
if (!isindelayslot) {
|
if (!isindelayslot) {
|
||||||
emit.resolveFinalFallthrough();
|
emit.resolveFinalFallthrough();
|
||||||
}
|
}
|
||||||
protoContext.setDelaySlotLength(0);
|
|
||||||
emit.write(PcodeEmitPacked.end_tag); // Terminate the inst_tag
|
emit.write(PcodeEmitPacked.end_tag); // Terminate the inst_tag
|
||||||
return emit.getPackedBytes();
|
return emit.getPackedBytes();
|
||||||
}
|
}
|
||||||
|
@ -1061,6 +1094,7 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
|
// If opIndex is out of bounds (or if there are memory errors) return an empty p-code list
|
||||||
}
|
}
|
||||||
return emptyPCode;
|
return emptyPCode;
|
||||||
}
|
}
|
||||||
|
@ -1342,8 +1376,9 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
||||||
if (subct != null) {
|
if (subct != null) {
|
||||||
walker.setConstructor(subct);
|
walker.setConstructor(subct);
|
||||||
subct.applyContext(walker, debug);
|
subct.applyContext(walker, debug);
|
||||||
if (debug != null)
|
if (debug != null) {
|
||||||
debug.indent();
|
debug.indent();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (debug != null) {
|
if (debug != null) {
|
||||||
|
@ -1355,8 +1390,9 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (debug != null)
|
if (debug != null) {
|
||||||
debug.dumpPattern(sym, walker);
|
debug.dumpPattern(sym, walker);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
walker.setCurrentLength(sym.getMinimumLength());
|
walker.setCurrentLength(sym.getMinimumLength());
|
||||||
walker.popOperand();
|
walker.popOperand();
|
||||||
|
@ -1416,10 +1452,12 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
||||||
ConstructTpl templ = ct.getTempl();
|
ConstructTpl templ = ct.getTempl();
|
||||||
if (templ != null) {
|
if (templ != null) {
|
||||||
HandleTpl res = templ.getResult();
|
HandleTpl res = templ.getResult();
|
||||||
if (res != null) // Pop up handle to containing operand
|
if (res != null) { // Pop up handle to containing operand
|
||||||
res.fix(walker.getParentHandle(), walker);
|
res.fix(walker.getParentHandle(), walker);
|
||||||
else
|
}
|
||||||
|
else {
|
||||||
walker.getParentHandle().setInvalid();
|
walker.getParentHandle().setInvalid();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
walker.popOperand();
|
walker.popOperand();
|
||||||
}
|
}
|
||||||
|
@ -1430,8 +1468,8 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
||||||
* Reconstruct the ParserContext's internal packed context array and its list of global ContextSet directives
|
* Reconstruct the ParserContext's internal packed context array and its list of global ContextSet directives
|
||||||
* by walking a previously resolved ConstructState tree
|
* by walking a previously resolved ConstructState tree
|
||||||
* @param protoContext is the SleighParserContext containing the tree and holding the context results
|
* @param protoContext is the SleighParserContext containing the tree and holding the context results
|
||||||
* @param debug
|
* @param debug (optional) logger for collecting information about the recovered context
|
||||||
* @throws MemoryAccessException
|
* @throws MemoryAccessException if memory errors occur trying to recover context
|
||||||
*/
|
*/
|
||||||
private void reconstructContext(SleighParserContext protoContext, SleighDebugLogger debug)
|
private void reconstructContext(SleighParserContext protoContext, SleighDebugLogger debug)
|
||||||
throws MemoryAccessException {
|
throws MemoryAccessException {
|
||||||
|
@ -1442,8 +1480,9 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
||||||
if (ct != null) {
|
if (ct != null) {
|
||||||
int oper = walker.getOperand();
|
int oper = walker.getOperand();
|
||||||
int numoper = ct.getNumOperands();
|
int numoper = ct.getNumOperands();
|
||||||
if (oper == 0) // Upon first entry to this Constructor
|
if (oper == 0) { // Upon first entry to this Constructor
|
||||||
ct.applyContext(walker, debug); // Apply its context changes
|
ct.applyContext(walker, debug); // Apply its context changes
|
||||||
|
}
|
||||||
if (oper < numoper) {
|
if (oper < numoper) {
|
||||||
walker.pushOperand(oper);
|
walker.pushOperand(oper);
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -13,10 +13,6 @@
|
||||||
* 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.
|
||||||
*/
|
*/
|
||||||
/*
|
|
||||||
* Created on Jan 26, 2005
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package ghidra.app.plugin.processors.sleigh;
|
package ghidra.app.plugin.processors.sleigh;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
@ -36,7 +32,6 @@ import ghidra.program.model.mem.MemoryAccessException;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class SleighParserContext implements ParserContext {
|
public class SleighParserContext implements ParserContext {
|
||||||
// private WeakReference<MemBuffer> memBufferRef;
|
|
||||||
private MemBuffer memBuffer;
|
private MemBuffer memBuffer;
|
||||||
private Address addr; // Address of start of instruction
|
private Address addr; // Address of start of instruction
|
||||||
private Address nextInstrAddr; // Address of next instruction
|
private Address nextInstrAddr; // Address of next instruction
|
||||||
|
@ -44,23 +39,22 @@ public class SleighParserContext implements ParserContext {
|
||||||
private Address destAddr; // corresponds to inst_dest for call-fixup use
|
private Address destAddr; // corresponds to inst_dest for call-fixup use
|
||||||
private SleighInstructionPrototype prototype;
|
private SleighInstructionPrototype prototype;
|
||||||
private AddressSpace constantSpace;
|
private AddressSpace constantSpace;
|
||||||
private HashMap<ConstructState, FixedHandle> handleMap =
|
private HashMap<ConstructState, FixedHandle> handleMap;
|
||||||
new HashMap<ConstructState, FixedHandle>();
|
|
||||||
private ArrayList<ContextSet> contextcommit; // Pending changes to context
|
private ArrayList<ContextSet> contextcommit; // Pending changes to context
|
||||||
private int[] context; // packed context bits
|
private int[] context; // packed context bits
|
||||||
|
|
||||||
public SleighParserContext(MemBuffer memBuf, SleighInstructionPrototype prototype,
|
public SleighParserContext(MemBuffer memBuf, SleighInstructionPrototype prototype,
|
||||||
ProcessorContextView processorContext) {
|
ProcessorContextView processorContext) {
|
||||||
|
this.handleMap = new HashMap<>();
|
||||||
this.prototype = prototype;
|
this.prototype = prototype;
|
||||||
this.constantSpace = prototype.getLanguage().getAddressFactory().getConstantSpace();
|
this.constantSpace = prototype.getLanguage().getAddressFactory().getConstantSpace();
|
||||||
// this.memBufferRef = new WeakReference<MemBuffer>(memBuf);
|
|
||||||
this.memBuffer = memBuf;
|
this.memBuffer = memBuf;
|
||||||
this.addr = memBuf.getAddress();
|
this.addr = memBuf.getAddress();
|
||||||
|
|
||||||
int contextSize = prototype.getContextCache().getContextSize();
|
int contextSize = prototype.getContextCache().getContextSize();
|
||||||
context = new int[contextSize];
|
context = new int[contextSize];
|
||||||
|
|
||||||
contextcommit = new ArrayList<ContextSet>();
|
contextcommit = new ArrayList<>();
|
||||||
try {
|
try {
|
||||||
nextInstrAddr = addr.add(prototype.getLength());
|
nextInstrAddr = addr.add(prototype.getLength());
|
||||||
}
|
}
|
||||||
|
@ -69,7 +63,6 @@ public class SleighParserContext implements ParserContext {
|
||||||
nextInstrAddr = null;
|
nextInstrAddr = null;
|
||||||
}
|
}
|
||||||
prototype.getContextCache().getContext(processorContext, context);
|
prototype.getContextCache().getContext(processorContext, context);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -95,6 +88,33 @@ public class SleighParserContext implements ParserContext {
|
||||||
destAddr = dAddr;
|
destAddr = dAddr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate context specifically for an instruction that has a delayslot.
|
||||||
|
* When generating p-code SLEIGH has an alternate interpretation of the "inst_next"
|
||||||
|
* symbol that takes into account the instruction in the delay slot. This context is
|
||||||
|
* generated at the point when specific instruction(s) in the delay slot are known.
|
||||||
|
* @param origContext is the original context (for the instruction in isolation)
|
||||||
|
* @param delayByteCount is the number of bytes in instruction stream occupied by the delay slot
|
||||||
|
*/
|
||||||
|
public SleighParserContext(SleighParserContext origContext, int delayByteCount) {
|
||||||
|
memBuffer = origContext.memBuffer;
|
||||||
|
prototype = origContext.prototype;
|
||||||
|
context = origContext.context;
|
||||||
|
contextcommit = origContext.contextcommit;
|
||||||
|
addr = origContext.addr;
|
||||||
|
refAddr = origContext.refAddr;
|
||||||
|
destAddr = origContext.destAddr;
|
||||||
|
constantSpace = origContext.constantSpace;
|
||||||
|
handleMap = origContext.handleMap;
|
||||||
|
try {
|
||||||
|
nextInstrAddr = addr.add(prototype.getLength() + delayByteCount);
|
||||||
|
}
|
||||||
|
catch (AddressOutOfBoundsException exc) {
|
||||||
|
// no next instruction, last instruction in memory.
|
||||||
|
nextInstrAddr = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return context commits for normal instruction parse.
|
* @return context commits for normal instruction parse.
|
||||||
*/
|
*/
|
||||||
|
@ -113,13 +133,13 @@ public class SleighParserContext implements ParserContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void applyCommits(ProcessorContext ctx) throws MemoryAccessException {
|
public void applyCommits(ProcessorContext ctx) throws MemoryAccessException {
|
||||||
if (contextcommit.size() == 0)
|
if (contextcommit.size() == 0) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
ContextCache contextCache = prototype.getContextCache();
|
ContextCache contextCache = prototype.getContextCache();
|
||||||
ParserWalker walker = new ParserWalker(this);
|
ParserWalker walker = new ParserWalker(this);
|
||||||
walker.baseState();
|
walker.baseState();
|
||||||
for (int i = 0; i < contextcommit.size(); ++i) {
|
for (ContextSet set : contextcommit) {
|
||||||
ContextSet set = contextcommit.get(i);
|
|
||||||
FixedHandle hand;
|
FixedHandle hand;
|
||||||
if (set.sym instanceof OperandSymbol) { // value of OperandSymbol is already calculated, find right node
|
if (set.sym instanceof OperandSymbol) { // value of OperandSymbol is already calculated, find right node
|
||||||
int ind = ((OperandSymbol) set.sym).getIndex();
|
int ind = ((OperandSymbol) set.sym).getIndex();
|
||||||
|
@ -159,16 +179,6 @@ public class SleighParserContext implements ParserContext {
|
||||||
return nextInstrAddr;
|
return nextInstrAddr;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDelaySlotLength(int delayByteLength) {
|
|
||||||
try {
|
|
||||||
nextInstrAddr = addr.add(prototype.getLength() + delayByteLength);
|
|
||||||
}
|
|
||||||
catch (AddressOutOfBoundsException exc) {
|
|
||||||
// no next instruction, last instruction in memory.
|
|
||||||
nextInstrAddr = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public AddressSpace getCurSpace() {
|
public AddressSpace getCurSpace() {
|
||||||
return addr.getAddressSpace();
|
return addr.getAddressSpace();
|
||||||
}
|
}
|
||||||
|
@ -187,7 +197,7 @@ public class SleighParserContext implements ParserContext {
|
||||||
* undefined memory will return zero byte values.
|
* undefined memory will return zero byte values.
|
||||||
* @param offset offset relative start of this context
|
* @param offset offset relative start of this context
|
||||||
* @param bytestart pattern byte offset relative to specified context offset
|
* @param bytestart pattern byte offset relative to specified context offset
|
||||||
* @param size
|
* @param size is the number of bytes to fetch
|
||||||
* @return requested byte-range value
|
* @return requested byte-range value
|
||||||
* @throws MemoryAccessException if no bytes are available at first byte when (offset+bytestart==0).
|
* @throws MemoryAccessException if no bytes are available at first byte when (offset+bytestart==0).
|
||||||
*/
|
*/
|
||||||
|
@ -212,8 +222,8 @@ public class SleighParserContext implements ParserContext {
|
||||||
* (packed in big endian format). Uninitialized or
|
* (packed in big endian format). Uninitialized or
|
||||||
* undefined memory will return zero bit values.
|
* undefined memory will return zero bit values.
|
||||||
* @param offset offset relative start of this context
|
* @param offset offset relative start of this context
|
||||||
* @param startbit
|
* @param startbit is the index of the first bit to fetch
|
||||||
* @param size
|
* @param size is the number of bits to fetch
|
||||||
* @return requested bit-range value
|
* @return requested bit-range value
|
||||||
* @throws MemoryAccessException if no bytes are available at first byte when (offset+bytestart/8==0).
|
* @throws MemoryAccessException if no bytes are available at first byte when (offset+bytestart/8==0).
|
||||||
*/
|
*/
|
||||||
|
@ -242,9 +252,9 @@ public class SleighParserContext implements ParserContext {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get bytes from context into an int
|
* Get bytes from context into an int
|
||||||
* @param bytestart
|
* @param bytestart is the index of the first byte to fetch
|
||||||
* @param bytesize number of bytes (range: 1 - 4)
|
* @param bytesize number of bytes (range: 1 - 4)
|
||||||
* @return
|
* @return the packed bytes from context
|
||||||
*/
|
*/
|
||||||
public int getContextBytes(int bytestart, int bytesize) {
|
public int getContextBytes(int bytestart, int bytesize) {
|
||||||
int intstart = bytestart / 4;
|
int intstart = bytestart / 4;
|
||||||
|
@ -266,7 +276,7 @@ public class SleighParserContext implements ParserContext {
|
||||||
/**
|
/**
|
||||||
* Get full set of context bytes. Sleigh only supports context
|
* Get full set of context bytes. Sleigh only supports context
|
||||||
* which is a multiple of 4-bytes (i.e., size of int)
|
* which is a multiple of 4-bytes (i.e., size of int)
|
||||||
* @return
|
* @return the array of context data
|
||||||
*/
|
*/
|
||||||
public int[] getContextBytes() {
|
public int[] getContextBytes() {
|
||||||
return context;
|
return context;
|
||||||
|
@ -274,9 +284,9 @@ public class SleighParserContext implements ParserContext {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get bits from context into an int
|
* Get bits from context into an int
|
||||||
* @param startbit
|
* @param startbit is the index of the first bit to fetch
|
||||||
* @param bitsize number of bits (range: 1 - 32)
|
* @param bitsize number of bits (range: 1 - 32)
|
||||||
* @return
|
* @return the packed bits
|
||||||
*/
|
*/
|
||||||
public int getContextBits(int startbit, int bitsize) {
|
public int getContextBits(int startbit, int bitsize) {
|
||||||
int intstart = startbit / 32;
|
int intstart = startbit / 32;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue