mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 10:49:34 +02:00
Merge remote-tracking branch 'origin/GP-1583_BitrangeDynamic' (Closes
#3716)
This commit is contained in:
commit
b618c24140
63 changed files with 1064 additions and 747 deletions
|
@ -49,10 +49,10 @@ public abstract class PcodeEmit {
|
|||
private Address defaultFallAddress;
|
||||
private Address fallOverride;
|
||||
private int fallOffset;
|
||||
private UniqueAddressFactory uniqueFactory;
|
||||
private SleighLanguage language;
|
||||
private AddressFactory addressFactory;
|
||||
private VarnodeData outcache;
|
||||
protected VarnodeData[] incache;
|
||||
private VarnodeData[] dyncache;
|
||||
protected ArrayList<Integer> labeldef = null;
|
||||
protected int numOps = 0; // Number of PcodeOps generated so far
|
||||
private int labelbase = 0;
|
||||
|
@ -76,10 +76,9 @@ public abstract class PcodeEmit {
|
|||
* @param ictx is the InstructionContext interface to resolve requests for context
|
||||
* @param fallOffset default instruction fall offset (i.e., instruction length including delay slotted instructions)
|
||||
* @param override required if pcode overrides are to be utilized
|
||||
* @param uniqueFactory required when override specified or if overlay normalization is required
|
||||
*/
|
||||
public PcodeEmit(ParserWalker walk, InstructionContext ictx, int fallOffset,
|
||||
PcodeOverride override, UniqueAddressFactory uniqueFactory) {
|
||||
PcodeOverride override) {
|
||||
this.walker = walk;
|
||||
this.parsercontext = walk.getParserContext();
|
||||
this.instcontext = ictx;
|
||||
|
@ -88,30 +87,27 @@ public abstract class PcodeEmit {
|
|||
AddressSpace myspace = startAddress.getAddressSpace();
|
||||
if (myspace.isOverlaySpace()) {
|
||||
overlayspace = myspace;
|
||||
startAddress = ((OverlayAddressSpace) myspace).getOverlayedSpace().getAddress(
|
||||
startAddress.getOffset());
|
||||
startAddress = ((OverlayAddressSpace) myspace).getOverlayedSpace()
|
||||
.getAddress(startAddress.getOffset());
|
||||
}
|
||||
this.fallOffset = fallOffset;
|
||||
this.uniqueFactory = uniqueFactory;
|
||||
this.override = override;
|
||||
SleighInstructionPrototype sleighproto = parsercontext.getPrototype();
|
||||
if (sleighproto != null) {
|
||||
SleighLanguage sleighlang = (SleighLanguage) sleighproto.getLanguage();
|
||||
uniq_space = sleighlang.getAddressFactory().getUniqueSpace();
|
||||
uniquemask = sleighlang.getUniqueAllocationMask();
|
||||
language = (SleighLanguage) sleighproto.getLanguage();
|
||||
addressFactory = language.getAddressFactory();
|
||||
uniq_space = addressFactory.getUniqueSpace();
|
||||
uniquemask = language.getUniqueAllocationMask();
|
||||
uniqueoffset = (startAddress.getOffset() & uniquemask) << 4;
|
||||
}
|
||||
else { // This can happen for CallFixup snippets, but these don't need their temporary vars patched up
|
||||
language = null;
|
||||
uniq_space = null;
|
||||
uniquemask = 0;
|
||||
uniqueoffset = 0;
|
||||
}
|
||||
|
||||
if (override != null) {
|
||||
if (uniqueFactory == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"uniqueFactory required when override is specified");
|
||||
}
|
||||
flowOverride = override.getFlowOverride();
|
||||
if (flowOverride == FlowOverride.NONE) {
|
||||
flowOverride = null;
|
||||
|
@ -131,7 +127,6 @@ public abstract class PcodeEmit {
|
|||
}
|
||||
|
||||
incache = new VarnodeData[8]; // Maximum number of inputs
|
||||
dyncache = null;
|
||||
}
|
||||
|
||||
private void setUniqueOffset(Address addr) {
|
||||
|
@ -159,7 +154,7 @@ public abstract class PcodeEmit {
|
|||
*/
|
||||
private void setLabel(OpTpl op) {
|
||||
if (labeldef == null) {
|
||||
labeldef = new ArrayList<Integer>();
|
||||
labeldef = new ArrayList<>();
|
||||
}
|
||||
int labelindex = (int) op.getInput()[0].getOffset().getReal() + labelbase;
|
||||
while (labeldef.size() <= labelindex) {
|
||||
|
@ -282,9 +277,11 @@ public abstract class PcodeEmit {
|
|||
// CALL <dest>
|
||||
// <label>
|
||||
|
||||
Address tmpAddr = uniqueFactory.getNextUniqueAddress();
|
||||
VarnodeTpl tmp = new VarnodeTpl(new ConstTpl(tmpAddr.getAddressSpace()),
|
||||
new ConstTpl(ConstTpl.REAL, tmpAddr.getOffset()), inputs[1].getSize());
|
||||
VarnodeTpl tmp =
|
||||
new VarnodeTpl(new ConstTpl(uniq_space),
|
||||
new ConstTpl(ConstTpl.REAL,
|
||||
UniqueLayout.RUNTIME_BOOLEAN_INVERT.getOffset(language)),
|
||||
inputs[1].getSize());
|
||||
int labelIndex = labelcount++;
|
||||
VarnodeTpl label = new VarnodeTpl(new ConstTpl(const_space),
|
||||
new ConstTpl(ConstTpl.J_RELATIVE, labelIndex), new ConstTpl(ConstTpl.REAL, 8));
|
||||
|
@ -338,9 +335,9 @@ public abstract class PcodeEmit {
|
|||
// tmp = COPY &<dest>
|
||||
// RETURN tmp
|
||||
|
||||
Address tmpAddr = uniqueFactory.getNextUniqueAddress();
|
||||
VarnodeTpl tmp = new VarnodeTpl(new ConstTpl(tmpAddr.getAddressSpace()),
|
||||
new ConstTpl(ConstTpl.REAL, tmpAddr.getOffset()),
|
||||
VarnodeTpl tmp = new VarnodeTpl(new ConstTpl(uniq_space),
|
||||
new ConstTpl(ConstTpl.REAL,
|
||||
UniqueLayout.RUNTIME_RETURN_LOCATION.getOffset(language)),
|
||||
new ConstTpl(ConstTpl.REAL, ptrSize));
|
||||
|
||||
VarnodeTpl destAddr = new VarnodeTpl(new ConstTpl(const_space), inputs[0].getOffset(),
|
||||
|
@ -379,13 +376,15 @@ public abstract class PcodeEmit {
|
|||
// RETURN <dest>
|
||||
// <label>
|
||||
|
||||
Address tmpAddr = uniqueFactory.getNextUniqueAddress();
|
||||
VarnodeTpl tmp = new VarnodeTpl(new ConstTpl(tmpAddr.getAddressSpace()),
|
||||
new ConstTpl(ConstTpl.REAL, tmpAddr.getOffset()), inputs[1].getSize());
|
||||
VarnodeTpl tmp =
|
||||
new VarnodeTpl(new ConstTpl(uniq_space),
|
||||
new ConstTpl(ConstTpl.REAL,
|
||||
UniqueLayout.RUNTIME_BOOLEAN_INVERT.getOffset(language)),
|
||||
inputs[1].getSize());
|
||||
|
||||
tmpAddr = uniqueFactory.getNextUniqueAddress();
|
||||
VarnodeTpl tmp2 = new VarnodeTpl(new ConstTpl(tmpAddr.getAddressSpace()),
|
||||
new ConstTpl(ConstTpl.REAL, tmpAddr.getOffset()),
|
||||
VarnodeTpl tmp2 = new VarnodeTpl(new ConstTpl(uniq_space),
|
||||
new ConstTpl(ConstTpl.REAL,
|
||||
UniqueLayout.RUNTIME_RETURN_LOCATION.getOffset(language)),
|
||||
new ConstTpl(ConstTpl.REAL, ptrSize));
|
||||
|
||||
VarnodeTpl destAddr = new VarnodeTpl(new ConstTpl(const_space), inputs[0].getOffset(),
|
||||
|
@ -478,8 +477,37 @@ public abstract class PcodeEmit {
|
|||
return hand.space;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjust the dynamic pointer to account for a V_OFFSET_PLUS in the given VarnodeTpl.
|
||||
* We are passed in an existing array (dyncache) of VarnodeData for input/output.
|
||||
* We assume the location of the base pointer is in dyncache[1]
|
||||
* @param dyncache is the existing array
|
||||
* @param vn is the V_OFFSET_PLUS VarnodeTpl to adjust for
|
||||
*/
|
||||
private void generatePointerAdd(VarnodeData[] dyncache, VarnodeTpl vn) {
|
||||
long offsetPlus = vn.getOffset().getReal() & 0xffff;
|
||||
if (offsetPlus == 0) {
|
||||
return;
|
||||
}
|
||||
VarnodeData tmpData = dyncache[0]; // Swap dyncache[1] with dyncache[0]
|
||||
dyncache[0] = dyncache[1];
|
||||
dyncache[1] = tmpData;
|
||||
dyncache[1].space = const_space; // Put V_OFFSET_PLUS constant in dyncache[1]
|
||||
dyncache[1].offset = offsetPlus;
|
||||
dyncache[1].size = dyncache[0].size;
|
||||
dyncache[2].space = uniq_space; // Result of INT_ADD in special runtime temp
|
||||
dyncache[2].offset = UniqueLayout.RUNTIME_BITRANGE_EA.getOffset(language);
|
||||
dyncache[2].size = dyncache[0].size;
|
||||
dump(startAddress, PcodeOp.INT_ADD, dyncache, 2, dyncache[2]);
|
||||
numOps += 1;
|
||||
tmpData = dyncache[2];
|
||||
dyncache[2] = dyncache[1];
|
||||
dyncache[1] = tmpData;
|
||||
}
|
||||
|
||||
private void dump(OpTpl opt) {
|
||||
|
||||
VarnodeData[] dyncache = null;
|
||||
VarnodeTpl vn, outvn;
|
||||
int isize = opt.getInput().length;
|
||||
|
||||
|
@ -493,13 +521,16 @@ public abstract class PcodeEmit {
|
|||
dyncache[1] = new VarnodeData();
|
||||
dyncache[2] = new VarnodeData();
|
||||
generateLocation(vn, incache[i]); // Temporary storage
|
||||
dyncache[2].space = incache[i].space;
|
||||
dyncache[2].offset = incache[i].offset;
|
||||
dyncache[2].size = incache[i].size;
|
||||
AddressSpace spc = generatePointer(vn, dyncache[1]);
|
||||
if (vn.getOffset().getSelect() == ConstTpl.V_OFFSET_PLUS) {
|
||||
generatePointerAdd(dyncache, vn);
|
||||
}
|
||||
dyncache[0].space = const_space;
|
||||
dyncache[0].offset = spc.getSpaceID();
|
||||
dyncache[0].size = 4; // Size of spaceid
|
||||
dyncache[2].space = incache[i].space;
|
||||
dyncache[2].offset = incache[i].offset;
|
||||
dyncache[2].size = incache[i].size;
|
||||
dump(startAddress, PcodeOp.LOAD, dyncache, 2, dyncache[2]);
|
||||
numOps += 1;
|
||||
}
|
||||
|
@ -524,13 +555,16 @@ public abstract class PcodeEmit {
|
|||
generateLocation(outvn, outcache); // Temporary storage
|
||||
dump(startAddress, opt.getOpcode(), incache, isize, outcache);
|
||||
numOps += 1;
|
||||
dyncache[2].space = outcache.space;
|
||||
dyncache[2].offset = outcache.offset;
|
||||
dyncache[2].size = outcache.size;
|
||||
AddressSpace spc = generatePointer(outvn, dyncache[1]);
|
||||
if (outvn.getOffset().getSelect() == ConstTpl.V_OFFSET_PLUS) {
|
||||
generatePointerAdd(dyncache, outvn);
|
||||
}
|
||||
dyncache[0].space = const_space;
|
||||
dyncache[0].offset = spc.getSpaceID();
|
||||
dyncache[0].size = 4; // Size of spaceid;
|
||||
dyncache[2].space = outcache.space;
|
||||
dyncache[2].offset = outcache.offset;
|
||||
dyncache[2].size = outcache.size;
|
||||
dump(startAddress, PcodeOp.STORE, dyncache, 3, null);
|
||||
numOps += 1;
|
||||
}
|
||||
|
@ -576,8 +610,8 @@ public abstract class PcodeEmit {
|
|||
/**
|
||||
* Insert the p-code of instruction(s) in the delay slot at this point in the p-code generation for the current instruction
|
||||
* @param op is the DELAYSLOT directive
|
||||
* @throws UnknownInstructionException
|
||||
* @throws MemoryAccessException
|
||||
* @throws UnknownInstructionException for problems finding the delay slot Instruction
|
||||
* @throws MemoryAccessException for problems resolving details of the delay slot Instruction
|
||||
*/
|
||||
private void delaySlot(OpTpl op) throws UnknownInstructionException, MemoryAccessException {
|
||||
|
||||
|
@ -620,8 +654,8 @@ public abstract class PcodeEmit {
|
|||
* Inject the p-code for a different instruction at this point in the p-code generation for current instruction
|
||||
* @param bld is the CROSSBUILD directive containing the section number and address parameters
|
||||
* @param secnum is the section number of the section containing the CROSSBUILD directive
|
||||
* @throws UnknownInstructionException
|
||||
* @throws MemoryAccessException
|
||||
* @throws UnknownInstructionException for problems finding the referenced Instruction
|
||||
* @throws MemoryAccessException for problems resolving details of the referenced Instruction
|
||||
*/
|
||||
private void appendCrossBuild(OpTpl bld, int secnum)
|
||||
throws UnknownInstructionException, MemoryAccessException {
|
||||
|
@ -703,8 +737,8 @@ public abstract class PcodeEmit {
|
|||
* Build a named p-code section of a constructor that contains only implied BUILD directives
|
||||
* @param ct Constructor to build section for
|
||||
* @param secnum index of the section to be built
|
||||
* @throws MemoryAccessException
|
||||
* @throws UnknownInstructionException
|
||||
* @throws MemoryAccessException for problems resolving details of the underlying Instruction
|
||||
* @throws UnknownInstructionException for problems finding the underlying Instruction
|
||||
*/
|
||||
private void buildEmpty(Constructor ct, int secnum)
|
||||
throws UnknownInstructionException, MemoryAccessException {
|
||||
|
@ -730,12 +764,9 @@ public abstract class PcodeEmit {
|
|||
|
||||
void checkOverlays(int opcode, VarnodeData[] in, int isize, VarnodeData out) {
|
||||
if (overlayspace != null) {
|
||||
if (uniqueFactory == null) {
|
||||
return;
|
||||
}
|
||||
if ((opcode == PcodeOp.LOAD) || (opcode == PcodeOp.STORE)) {
|
||||
int spaceId = (int) in[0].offset;
|
||||
AddressSpace space = uniqueFactory.getAddressFactory().getAddressSpace(spaceId);
|
||||
AddressSpace space = addressFactory.getAddressSpace(spaceId);
|
||||
if (space.isOverlaySpace()) {
|
||||
space = ((OverlayAddressSpace) space).getOverlayedSpace();
|
||||
in[0].offset = space.getSpaceID();
|
||||
|
|
|
@ -17,7 +17,8 @@ package ghidra.app.plugin.processors.sleigh;
|
|||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressSpace;
|
||||
import ghidra.program.model.lang.InstructionContext;
|
||||
import ghidra.program.model.pcode.*;
|
||||
|
||||
|
@ -32,7 +33,7 @@ public class PcodeEmitObjects extends PcodeEmit {
|
|||
* @param walk state of the ParserContext from which to generate p-code
|
||||
*/
|
||||
public PcodeEmitObjects(ParserWalker walk) { // For use with emitting precompiled p-code templates
|
||||
this(walk, null, 0, null, null);
|
||||
this(walk, null, 0, null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -42,7 +43,7 @@ public class PcodeEmitObjects extends PcodeEmit {
|
|||
* of instruction including delay-sloted instructions)
|
||||
*/
|
||||
public PcodeEmitObjects(ParserWalker walk, int fallOffset) { // For use with emitting precompiled p-code templates
|
||||
this(walk, null, fallOffset, null, null);
|
||||
this(walk, null, fallOffset, null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -50,12 +51,11 @@ public class PcodeEmitObjects extends PcodeEmit {
|
|||
* @param ictx is the InstructionContext used to resolve delayslot and crossbuild directives
|
||||
* @param fallOffset default instruction fall offset (i.e., instruction length including delay slotted instructions)
|
||||
* @param override required if pcode overrides are to be utilized
|
||||
* @param uniqueFactory required when override specified or if overlay normalization is required
|
||||
*/
|
||||
public PcodeEmitObjects(ParserWalker walk, InstructionContext ictx, int fallOffset,
|
||||
PcodeOverride override, UniqueAddressFactory uniqueFactory) {
|
||||
super(walk, ictx, fallOffset, override, uniqueFactory);
|
||||
oplist = new ArrayList<PcodeOp>();
|
||||
PcodeOverride override) {
|
||||
super(walk, ictx, fallOffset, override);
|
||||
oplist = new ArrayList<>();
|
||||
}
|
||||
|
||||
public PcodeOp[] getPcodeOp() {
|
||||
|
@ -72,8 +72,7 @@ public class PcodeEmitObjects extends PcodeEmit {
|
|||
if (labelref == null) {
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < labelref.size(); ++i) {
|
||||
int opindex = labelref.get(i);
|
||||
for (Integer opindex : labelref) {
|
||||
PcodeOp op = oplist.get(opindex);
|
||||
Varnode vn = op.getInput(0);
|
||||
int labelid = (int) vn.getOffset();
|
||||
|
@ -98,7 +97,7 @@ public class PcodeEmitObjects extends PcodeEmit {
|
|||
@Override
|
||||
void addLabelRef() {
|
||||
if (labelref == null) {
|
||||
labelref = new ArrayList<Integer>();
|
||||
labelref = new ArrayList<>();
|
||||
}
|
||||
labelref.add(numOps);
|
||||
}
|
||||
|
|
|
@ -17,7 +17,8 @@ package ghidra.app.plugin.processors.sleigh;
|
|||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressSpace;
|
||||
import ghidra.program.model.lang.InstructionContext;
|
||||
import ghidra.program.model.lang.PackedBytes;
|
||||
import ghidra.program.model.pcode.PcodeOp;
|
||||
|
@ -63,11 +64,10 @@ public class PcodeEmitPacked extends PcodeEmit {
|
|||
* @param ictx instruction contexts
|
||||
* @param fallOffset default instruction fall offset (i.e., instruction length including delay slotted instructions)
|
||||
* @param override required if pcode overrides are to be utilized
|
||||
* @param uniqueFactory required when override specified or if overlay normalization is required
|
||||
*/
|
||||
public PcodeEmitPacked(ParserWalker walk, InstructionContext ictx, int fallOffset,
|
||||
PcodeOverride override, UniqueAddressFactory uniqueFactory) {
|
||||
super(walk, ictx, fallOffset, override, uniqueFactory);
|
||||
PcodeOverride override) {
|
||||
super(walk, ictx, fallOffset, override);
|
||||
buf = new PackedBytes(512);
|
||||
}
|
||||
|
||||
|
@ -80,8 +80,7 @@ public class PcodeEmitPacked extends PcodeEmit {
|
|||
if (labelref == null) {
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < labelref.size(); ++i) {
|
||||
LabelRef ref = labelref.get(i);
|
||||
for (LabelRef ref : labelref) {
|
||||
if ((ref.labelIndex >= labeldef.size()) || (labeldef.get(ref.labelIndex) == null)) {
|
||||
throw new SleighException("Reference to non-existant sleigh label");
|
||||
}
|
||||
|
@ -102,7 +101,7 @@ public class PcodeEmitPacked extends PcodeEmit {
|
|||
@Override
|
||||
void addLabelRef() {
|
||||
if (labelref == null) {
|
||||
labelref = new ArrayList<LabelRef>();
|
||||
labelref = new ArrayList<>();
|
||||
}
|
||||
int labelIndex = (int) incache[0].offset;
|
||||
int labelSize = incache[0].size;
|
||||
|
|
|
@ -161,19 +161,22 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
|||
|
||||
private static void addExplicitFlow(ConstructState state, OpTpl op, int flags,
|
||||
FlowSummary summary) {
|
||||
if (summary.flowState == null)
|
||||
if (summary.flowState == null) {
|
||||
summary.flowState = new ArrayList<>();
|
||||
}
|
||||
FlowRecord res = new FlowRecord();
|
||||
summary.flowState.add(res);
|
||||
res.flowFlags = flags;
|
||||
res.op = op;
|
||||
res.addressnode = null;
|
||||
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;
|
||||
}
|
||||
// If the flow is out of the instruction, store the ConstructState so we can easily calculate address
|
||||
if (state == null)
|
||||
if (state == null) {
|
||||
return;
|
||||
}
|
||||
if ((flags & CROSSBUILD) != 0) {
|
||||
res.addressnode = state;
|
||||
}
|
||||
|
@ -218,24 +221,31 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
|||
break;
|
||||
case PcodeOp.BRANCH:
|
||||
destType = res.lastop.getInput()[0].getOffset().getType();
|
||||
if (destType == ConstTpl.J_NEXT)
|
||||
if (destType == ConstTpl.J_NEXT) {
|
||||
flags = BRANCH_TO_END;
|
||||
else if (destType == ConstTpl.J_START)
|
||||
}
|
||||
else if (destType == ConstTpl.J_START) {
|
||||
flags = NO_FALLTHRU;
|
||||
else if (destType == ConstTpl.J_RELATIVE)
|
||||
}
|
||||
else if (destType == ConstTpl.J_RELATIVE) {
|
||||
flags = NO_FALLTHRU;
|
||||
else
|
||||
}
|
||||
else {
|
||||
flags = JUMPOUT | NO_FALLTHRU;
|
||||
}
|
||||
addExplicitFlow(walker.getState(), res.lastop, flags, res);
|
||||
break;
|
||||
case PcodeOp.CBRANCH:
|
||||
destType = res.lastop.getInput()[0].getOffset().getType();
|
||||
if (destType == ConstTpl.J_NEXT)
|
||||
if (destType == ConstTpl.J_NEXT) {
|
||||
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;
|
||||
else
|
||||
}
|
||||
else {
|
||||
flags = 0;
|
||||
}
|
||||
addExplicitFlow(walker.getState(), res.lastop, flags, res);
|
||||
break;
|
||||
case PcodeOp.CALL:
|
||||
|
@ -252,8 +262,9 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
|||
break;
|
||||
case PcodeOp.INDIRECT: // Encode delayslot
|
||||
destType = (int) res.lastop.getInput()[0].getOffset().getReal();
|
||||
if (destType > res.delay)
|
||||
if (destType > res.delay) {
|
||||
res.delay = destType;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
|
||||
|
@ -263,8 +274,9 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
|||
}
|
||||
|
||||
public static FlowType flowListToFlowType(List<FlowRecord> flowstate) {
|
||||
if (flowstate == null)
|
||||
if (flowstate == null) {
|
||||
return RefType.FALL_THROUGH;
|
||||
}
|
||||
int flags = 0;
|
||||
for (FlowRecord rec : flowstate) {
|
||||
flags &= ~(NO_FALLTHRU | CROSSBUILD | LABEL);
|
||||
|
@ -307,8 +319,9 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
|||
|
||||
private static FlowType convertFlowFlags(int flowFlags) {
|
||||
|
||||
if ((flowFlags & LABEL) != 0)
|
||||
if ((flowFlags & LABEL) != 0) {
|
||||
flowFlags |= BRANCH_TO_END;
|
||||
}
|
||||
flowFlags &= ~(CROSSBUILD | LABEL);
|
||||
// NOTE: If prototype has cross-build, flow must be determined dynamically
|
||||
switch (flowFlags) { // Convert flags to a standard flowtype
|
||||
|
@ -395,8 +408,9 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
|||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == null)
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
return (hashCode() == obj.hashCode()); // Trust entirely in hash
|
||||
}
|
||||
|
||||
|
@ -415,8 +429,9 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
|||
|
||||
@Override
|
||||
public FlowType getFlowType(InstructionContext context) {
|
||||
if (!hasCrossBuilds)
|
||||
if (!hasCrossBuilds) {
|
||||
return flowType;
|
||||
}
|
||||
int flags = 0;
|
||||
try {
|
||||
flags = gatherFlags(0, context, -1);
|
||||
|
@ -473,8 +488,9 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
|||
|
||||
@Override
|
||||
public int getOpType(int opIndex, InstructionContext context) {
|
||||
if (opIndex < 0 || opIndex >= opresolve.length)
|
||||
if (opIndex < 0 || opIndex >= opresolve.length) {
|
||||
return OperandType.DYNAMIC;
|
||||
}
|
||||
|
||||
SleighParserContext protoContext;
|
||||
try {
|
||||
|
@ -485,20 +501,25 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
|||
}
|
||||
ConstructState opState = mnemonicState.getSubState(opresolve[opIndex]);
|
||||
FixedHandle hand = protoContext.getFixedHandle(opState);
|
||||
if (hand.isInvalid())
|
||||
if (hand.isInvalid()) {
|
||||
return OperandType.DYNAMIC;
|
||||
}
|
||||
int indirect = isIndirect(opresolve[opIndex]) ? OperandType.INDIRECT : 0;
|
||||
if (hand.offset_space == null) { // Static handle
|
||||
int type = hand.space.getType();
|
||||
if (type == AddressSpace.TYPE_REGISTER)
|
||||
if (type == AddressSpace.TYPE_REGISTER) {
|
||||
return OperandType.REGISTER | indirect;
|
||||
if (type == AddressSpace.TYPE_CONSTANT)
|
||||
}
|
||||
if (type == AddressSpace.TYPE_CONSTANT) {
|
||||
return OperandType.SCALAR | indirect;
|
||||
}
|
||||
OperandSymbol sym = mnemonicState.getConstructor().getOperand(opresolve[opIndex]);
|
||||
if (sym.isCodeAddress())
|
||||
if (sym.isCodeAddress()) {
|
||||
return (OperandType.ADDRESS | OperandType.CODE | indirect);
|
||||
if (type == AddressSpace.TYPE_RAM)
|
||||
}
|
||||
if (type == AddressSpace.TYPE_RAM) {
|
||||
return (OperandType.ADDRESS | OperandType.DATA | indirect);
|
||||
}
|
||||
}
|
||||
return OperandType.DYNAMIC | indirect;
|
||||
}
|
||||
|
@ -565,13 +586,16 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
|||
private int gatherFlags(int curflags, InstructionContext context, int secnum)
|
||||
throws MemoryAccessException, UnknownContextException {
|
||||
List<FlowRecord> curlist = null;
|
||||
if (secnum < 0)
|
||||
if (secnum < 0) {
|
||||
curlist = flowStateList;
|
||||
else if ((flowStateListNamed != null) && (secnum < flowStateListNamed.size()))
|
||||
}
|
||||
else if ((flowStateListNamed != null) && (secnum < flowStateListNamed.size())) {
|
||||
curlist = flowStateListNamed.get(secnum);
|
||||
}
|
||||
|
||||
if (curlist == null)
|
||||
if (curlist == null) {
|
||||
return curflags;
|
||||
}
|
||||
|
||||
for (FlowRecord rec : curlist) {
|
||||
if ((rec.flowFlags & CROSSBUILD) != 0) {
|
||||
|
@ -618,13 +642,16 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
|||
InstructionContext context, int secnum)
|
||||
throws MemoryAccessException, UnknownContextException {
|
||||
List<FlowRecord> curlist = null;
|
||||
if (secnum < 0)
|
||||
if (secnum < 0) {
|
||||
curlist = flowStateList;
|
||||
else if ((flowStateListNamed != null) && (secnum < flowStateListNamed.size()))
|
||||
}
|
||||
else if ((flowStateListNamed != null) && (secnum < flowStateListNamed.size())) {
|
||||
curlist = flowStateListNamed.get(secnum);
|
||||
}
|
||||
|
||||
if (curlist == null)
|
||||
if (curlist == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (FlowRecord rec : curlist) {
|
||||
if ((rec.flowFlags & CROSSBUILD) != 0) {
|
||||
|
@ -654,8 +681,9 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
|||
@Override
|
||||
public Address[] getFlows(InstructionContext context) {
|
||||
|
||||
if (flowStateList.size() == 0)
|
||||
if (flowStateList.size() == 0) {
|
||||
return emptyFlow;
|
||||
}
|
||||
|
||||
ArrayList<Address> addresses = new ArrayList<>();
|
||||
try {
|
||||
|
@ -668,8 +696,9 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
|||
return emptyFlow;
|
||||
}
|
||||
|
||||
if (addresses.size() == 0)
|
||||
if (addresses.size() == 0) {
|
||||
return emptyFlow;
|
||||
}
|
||||
return addresses.toArray(new Address[addresses.size()]);
|
||||
}
|
||||
|
||||
|
@ -746,8 +775,9 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
|||
protoContext = (SleighParserContext) context.getParserContext();
|
||||
ConstructState opState = mnemonicState.getSubState(opresolve[opIndex]);
|
||||
hand = protoContext.getFixedHandle(opState);
|
||||
if (hand.isInvalid())
|
||||
if (hand.isInvalid()) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
return null;
|
||||
|
@ -769,8 +799,9 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
|||
|
||||
ConstructState opState = mnemonicState.getSubState(opresolve[opIndex]);
|
||||
FixedHandle hand = protoContext.getFixedHandle(opState);
|
||||
if (hand.isInvalid())
|
||||
if (hand.isInvalid()) {
|
||||
return null;
|
||||
}
|
||||
if (hand.space.getType() == AddressSpace.TYPE_CONSTANT) {
|
||||
int size = hand.size;
|
||||
if (size == 0) {
|
||||
|
@ -798,8 +829,9 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
|||
SleighParserContext protoContext = (SleighParserContext) context.getParserContext();
|
||||
ConstructState opState = mnemonicState.getSubState(opresolve[opIndex]);
|
||||
FixedHandle hand = protoContext.getFixedHandle(opState);
|
||||
if (hand.isInvalid())
|
||||
if (hand.isInvalid()) {
|
||||
return null;
|
||||
}
|
||||
if (hand.space.getType() == AddressSpace.TYPE_REGISTER) {
|
||||
return language.getRegister(hand.space, hand.offset_offset, hand.size);
|
||||
}
|
||||
|
@ -834,7 +866,7 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
|||
public Object[] getInputObjects(InstructionContext context) {
|
||||
PcodeOp[] pcode = null;
|
||||
try {
|
||||
pcode = getPcode(context, null, null);
|
||||
pcode = getPcode(context, null);
|
||||
}
|
||||
catch (Exception e) {
|
||||
return new Object[0];
|
||||
|
@ -892,7 +924,7 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
|||
public Object[] getResultObjects(InstructionContext context) {
|
||||
PcodeOp[] pcode = null;
|
||||
try {
|
||||
pcode = getPcode(context, null, null);
|
||||
pcode = getPcode(context, null);
|
||||
}
|
||||
catch (Exception e) {
|
||||
return new Object[0];
|
||||
|
@ -944,8 +976,7 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
|||
}
|
||||
|
||||
@Override
|
||||
public PcodeOp[] getPcode(InstructionContext context, PcodeOverride override,
|
||||
UniqueAddressFactory uniqueFactory) {
|
||||
public PcodeOp[] getPcode(InstructionContext context, PcodeOverride override) {
|
||||
try {
|
||||
SleighParserContext protoContext = (SleighParserContext) context.getParserContext();
|
||||
int fallOffset = getLength();
|
||||
|
@ -964,8 +995,7 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
|||
}
|
||||
ParserWalker walker = new ParserWalker(protoContext);
|
||||
walker.baseState();
|
||||
PcodeEmitObjects emit =
|
||||
new PcodeEmitObjects(walker, context, fallOffset, override, uniqueFactory);
|
||||
PcodeEmitObjects emit = new PcodeEmitObjects(walker, context, fallOffset, override);
|
||||
emit.build(walker.getConstructor().getTempl(), -1);
|
||||
emit.resolveRelatives();
|
||||
if (!isindelayslot) {
|
||||
|
@ -986,8 +1016,7 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
|||
}
|
||||
|
||||
@Override
|
||||
public PackedBytes getPcodePacked(InstructionContext context, PcodeOverride override,
|
||||
UniqueAddressFactory uniqueFactory) {
|
||||
public PackedBytes getPcodePacked(InstructionContext context, PcodeOverride override) {
|
||||
int fallOffset = getLength();
|
||||
try {
|
||||
SleighParserContext protoContext = (SleighParserContext) context.getParserContext();
|
||||
|
@ -1006,8 +1035,7 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
|||
}
|
||||
ParserWalker walker = new ParserWalker(protoContext);
|
||||
walker.baseState();
|
||||
PcodeEmitPacked emit =
|
||||
new PcodeEmitPacked(walker, context, fallOffset, override, uniqueFactory);
|
||||
PcodeEmitPacked emit = new PcodeEmitPacked(walker, context, fallOffset, override);
|
||||
emit.write(PcodeEmitPacked.inst_tag);
|
||||
emit.dumpOffset(emit.getFallOffset());
|
||||
|
||||
|
@ -1067,7 +1095,7 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
|||
|
||||
@Override
|
||||
public RefType getOperandRefType(int opIndex, InstructionContext context,
|
||||
PcodeOverride override, UniqueAddressFactory uniqueFactory) {
|
||||
PcodeOverride override) {
|
||||
if (opIndex < 0 || opIndex >= opRefTypes.length) {
|
||||
return null;
|
||||
}
|
||||
|
@ -1085,7 +1113,7 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
|||
if (refType != null) {
|
||||
return refType;
|
||||
}
|
||||
cacheDefaultOperandRefTypes(context, uniqueFactory);
|
||||
cacheDefaultOperandRefTypes(context);
|
||||
return opRefTypes[opIndex];
|
||||
}
|
||||
|
||||
|
@ -1097,7 +1125,7 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
|||
catch (MemoryAccessException e) {
|
||||
return RefType.DATA;
|
||||
}
|
||||
PcodeOp[] pcode = getPcode(context, override, uniqueFactory);
|
||||
PcodeOp[] pcode = getPcode(context, override);
|
||||
if (pcode == null || pcode.length == 0) {
|
||||
return RefType.DATA;
|
||||
}
|
||||
|
@ -1121,8 +1149,7 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
|||
return refType;
|
||||
}
|
||||
|
||||
private void cacheDefaultOperandRefTypes(InstructionContext context,
|
||||
UniqueAddressFactory uniqueFactory) {
|
||||
private void cacheDefaultOperandRefTypes(InstructionContext context) {
|
||||
|
||||
// Resolve handles for each operand
|
||||
SleighParserContext protoContext;
|
||||
|
@ -1132,7 +1159,7 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
|||
catch (MemoryAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
PcodeOp[] pcode = getPcode(context, null, uniqueFactory);
|
||||
PcodeOp[] pcode = getPcode(context, null);
|
||||
if (pcode == null || pcode.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
@ -1342,8 +1369,9 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
|||
if (subct != null) {
|
||||
walker.setConstructor(subct);
|
||||
subct.applyContext(walker, debug);
|
||||
if (debug != null)
|
||||
if (debug != null) {
|
||||
debug.indent();
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (debug != null) {
|
||||
|
@ -1355,8 +1383,9 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
|||
}
|
||||
}
|
||||
else {
|
||||
if (debug != null)
|
||||
if (debug != null) {
|
||||
debug.dumpPattern(sym, walker);
|
||||
}
|
||||
}
|
||||
walker.setCurrentLength(sym.getMinimumLength());
|
||||
walker.popOperand();
|
||||
|
@ -1416,10 +1445,12 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
|||
ConstructTpl templ = ct.getTempl();
|
||||
if (templ != null) {
|
||||
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);
|
||||
else
|
||||
}
|
||||
else {
|
||||
walker.getParentHandle().setInvalid();
|
||||
}
|
||||
}
|
||||
walker.popOperand();
|
||||
}
|
||||
|
@ -1442,8 +1473,9 @@ public class SleighInstructionPrototype implements InstructionPrototype {
|
|||
if (ct != null) {
|
||||
int oper = walker.getOperand();
|
||||
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
|
||||
}
|
||||
if (oper < numoper) {
|
||||
walker.pushOperand(oper);
|
||||
continue;
|
||||
|
|
|
@ -904,8 +904,8 @@ public class SleighLanguage implements Language {
|
|||
Endian ldefEndian = description.getEndian();
|
||||
Endian instEndian = description.getInstructionEndian();
|
||||
if (slaEndian != ldefEndian && instEndian == ldefEndian) {
|
||||
throw new SleighException(".ldefs says " + getLanguageID() + " is " +
|
||||
ldefEndian + " but .sla says " + slaEndian);
|
||||
throw new SleighException(".ldefs says " + getLanguageID() + " is " + ldefEndian +
|
||||
" but .sla says " + slaEndian);
|
||||
}
|
||||
uniqueBase = SpecXmlUtils.decodeLong(el.getAttribute("uniqbase"));
|
||||
alignment = SpecXmlUtils.decodeInt(el.getAttribute("align"));
|
||||
|
@ -935,9 +935,9 @@ public class SleighLanguage implements Language {
|
|||
String defname = el.getAttribute("defaultspace");
|
||||
spacetable = new LinkedHashMap<>();
|
||||
// Slot zero is always the constant space
|
||||
AddressSpace constspc = new GenericAddressSpace("const", 64, AddressSpace.TYPE_CONSTANT, 0);
|
||||
spacetable.put("const", constspc);
|
||||
//spacetable.put("OTHER", AddressSpace.OTHER_SPACE);
|
||||
AddressSpace constspc = new GenericAddressSpace(SpaceNames.CONSTANT_SPACE_NAME, 64,
|
||||
AddressSpace.TYPE_CONSTANT, SpaceNames.CONSTANT_SPACE_INDEX);
|
||||
spacetable.put(SpaceNames.CONSTANT_SPACE_NAME, constspc);
|
||||
default_space = null;
|
||||
XmlElement subel = parser.peek();
|
||||
if (subel.getName().equals("space_other")) { // tag must be present
|
||||
|
|
|
@ -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.app.plugin.processors.sleigh;
|
||||
|
||||
/**
|
||||
* Offsets for various ranges in the p-code unique space. Offsets are either:
|
||||
* 1) Relative to the last temporary allocated statically by the SLEIGH compiler
|
||||
* or a particular language (.sla), OR
|
||||
* 2) Absolute within the unique address space.
|
||||
* So the layout of the unique address space looks like:
|
||||
* 1) SLEIGH static temporaries
|
||||
* 2) Runtime temporaries used by the SLEIGH p-code generator
|
||||
* 3) Temporaries used by the PcodeInjectLibrary for p-code snippets
|
||||
* 4) Temporaries generated during (decompiler) analysis
|
||||
*
|
||||
* The "unique" space is set to 32 bits across all architectures.
|
||||
* The maximum offset is 0xFFFFFFFF.
|
||||
* The offsets and names should match with the parallel decompiler enum in translate.hh
|
||||
*/
|
||||
public enum UniqueLayout {
|
||||
SLEIGH_BASE(0, true), // First offset after SLEIGH static temporaries
|
||||
RUNTIME_BOOLEAN_INVERT(0, true),
|
||||
RUNTIME_RETURN_LOCATION(0x80, true),
|
||||
RUNTIME_BITRANGE_EA(0x100, true),
|
||||
INJECT(0x200, true),
|
||||
ANALYSIS(0x10000000, false);
|
||||
|
||||
private final long offset;
|
||||
private final boolean isRelative; // Is this offset relative to the end of SLEIGH statics
|
||||
|
||||
UniqueLayout(long off, boolean isRel) {
|
||||
offset = off;
|
||||
isRelative = isRel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the starting offset of a named range in the unique address space. The returned offset
|
||||
* is absolute and specific to the given SLEIGH language.
|
||||
* @param language is the given SLEIGH language
|
||||
* @return the absolute offset
|
||||
*/
|
||||
public long getOffset(SleighLanguage language) {
|
||||
return (isRelative && language != null) ? language.getUniqueBase() + offset : offset;
|
||||
}
|
||||
}
|
|
@ -95,6 +95,14 @@ public class ConstTpl {
|
|||
select = (short) vf;
|
||||
}
|
||||
|
||||
public ConstTpl(int tp, long val, AddressSpace spc, int ht, int sel) {
|
||||
type = tp;
|
||||
value_real = val;
|
||||
value_spaceid = spc;
|
||||
handle_index = (short) ht;
|
||||
select = (short) sel;
|
||||
}
|
||||
|
||||
public boolean isConstSpace() {
|
||||
if (type == SPACEID) {
|
||||
return (value_spaceid.getType() == AddressSpace.TYPE_CONSTANT);
|
||||
|
@ -121,6 +129,10 @@ public class ConstTpl {
|
|||
return handle_index;
|
||||
}
|
||||
|
||||
public int getSelect() {
|
||||
return select;
|
||||
}
|
||||
|
||||
public int getType() {
|
||||
return type;
|
||||
}
|
||||
|
@ -160,8 +172,7 @@ public class ConstTpl {
|
|||
return hand.size;
|
||||
case V_OFFSET_PLUS:
|
||||
if (hand.space.getType() != AddressSpace.TYPE_CONSTANT) { // If we are not a constant
|
||||
if (hand.offset_space == null)
|
||||
{
|
||||
if (hand.offset_space == null) {
|
||||
return hand.offset_offset + (value_real & 0xffff); // Adjust offset by truncation amount
|
||||
}
|
||||
return hand.temp_offset + (value_real & 0xffff);
|
||||
|
|
|
@ -63,6 +63,19 @@ public class ConstructTpl {
|
|||
result = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Manually build a constructor template from pieces. This is used to translate from the
|
||||
* internal SLEIGH compiler pcodeCPort.semantics.ConstructTpl
|
||||
* @param opvec is the list of p-code op templates making up the constructor
|
||||
* @param res is the result handle template for the constructor
|
||||
* @param nmLabels is the number of labels int the template
|
||||
*/
|
||||
public ConstructTpl(OpTpl[] opvec, HandleTpl res, int nmLabels) {
|
||||
vec = opvec;
|
||||
result = res;
|
||||
numlabels = nmLabels;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the number of labels needing resolution in this template
|
||||
*/
|
||||
|
|
|
@ -45,6 +45,17 @@ public class HandleTpl {
|
|||
protected HandleTpl() {
|
||||
}
|
||||
|
||||
public HandleTpl(ConstTpl spc, ConstTpl sz, ConstTpl ptrspc, ConstTpl ptroff, ConstTpl ptrsz,
|
||||
ConstTpl tmpspc, ConstTpl tmpoff) {
|
||||
space = spc;
|
||||
size = sz;
|
||||
ptrspace = ptrspc;
|
||||
ptroffset = ptroff;
|
||||
ptrsize = ptrsz;
|
||||
temp_space = tmpspc;
|
||||
temp_offset = tmpoff;
|
||||
}
|
||||
|
||||
public void fix(FixedHandle hand, ParserWalker walker) {
|
||||
if (ptrspace.getType() == ConstTpl.REAL) {
|
||||
// The export is unstarred, but this doesn't mean
|
||||
|
@ -72,8 +83,9 @@ public class HandleTpl {
|
|||
}
|
||||
|
||||
public void fixPrintPiece(FixedHandle hand, ParserWalker walker, int handleIndex) {
|
||||
if (!hand.fixable)
|
||||
if (!hand.fixable) {
|
||||
return;
|
||||
}
|
||||
if (hand.space.getType() != AddressSpace.TYPE_CONSTANT) {
|
||||
hand.fixable = false;
|
||||
return;
|
||||
|
|
|
@ -56,7 +56,7 @@ public class PseudoInstruction extends PseudoCodeUnit implements Instruction, In
|
|||
|
||||
/**
|
||||
* Construct a new PseudoInstruction within a program.
|
||||
* @param program
|
||||
* @param program is the given Program
|
||||
* @param addr address of the instruction
|
||||
* @param prototype prototype of the instruction
|
||||
* @param memBuffer buffer containing the bytes for the instruction
|
||||
|
@ -221,22 +221,25 @@ public class PseudoInstruction extends PseudoCodeUnit implements Instruction, In
|
|||
|
||||
@Override
|
||||
public Scalar getScalar(int opIndex) {
|
||||
if (opIndex < 0)
|
||||
if (opIndex < 0) {
|
||||
return null;
|
||||
}
|
||||
return instrProto.getScalar(opIndex, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Register getRegister(int opIndex) {
|
||||
if (opIndex < 0)
|
||||
if (opIndex < 0) {
|
||||
return null;
|
||||
}
|
||||
return instrProto.getRegister(opIndex, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] getOpObjects(int opIndex) {
|
||||
if (opIndex < 0)
|
||||
if (opIndex < 0) {
|
||||
return new Object[0];
|
||||
}
|
||||
return instrProto.getOpObjects(opIndex, this);
|
||||
}
|
||||
|
||||
|
@ -393,16 +396,15 @@ public class PseudoInstruction extends PseudoCodeUnit implements Instruction, In
|
|||
|
||||
@Override
|
||||
public PcodeOp[] getPcode() {
|
||||
return instrProto.getPcode(this, null, null);
|
||||
return instrProto.getPcode(this, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PcodeOp[] getPcode(boolean includeOverrides) {
|
||||
if (!includeOverrides || addrFactory == null) {
|
||||
return instrProto.getPcode(this, null, null);
|
||||
return instrProto.getPcode(this, null);
|
||||
}
|
||||
return instrProto.getPcode(this, new InstructionPcodeOverride(this),
|
||||
new UniqueAddressFactory(addrFactory, instrProto.getLanguage()));
|
||||
return instrProto.getPcode(this, new InstructionPcodeOverride(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -422,8 +424,9 @@ public class PseudoInstruction extends PseudoCodeUnit implements Instruction, In
|
|||
|
||||
@Override
|
||||
public Instruction getNext() {
|
||||
if (program == null)
|
||||
if (program == null) {
|
||||
return null;
|
||||
}
|
||||
return program.getListing().getInstructionAfter(address);
|
||||
}
|
||||
|
||||
|
@ -444,8 +447,9 @@ public class PseudoInstruction extends PseudoCodeUnit implements Instruction, In
|
|||
}
|
||||
}
|
||||
}
|
||||
if (program == null)
|
||||
if (program == null) {
|
||||
return null;
|
||||
}
|
||||
return program.getListing().getInstructionBefore(address);
|
||||
}
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ import ghidra.pcodeCPort.slghsymbol.*;
|
|||
import ghidra.pcodeCPort.space.*;
|
||||
import ghidra.pcodeCPort.utils.Utils;
|
||||
import ghidra.pcodeCPort.xml.DocumentStorage;
|
||||
import ghidra.program.model.lang.BasicCompilerSpec;
|
||||
import ghidra.program.model.lang.SpaceNames;
|
||||
import ghidra.sleigh.grammar.*;
|
||||
import ghidra.util.Msg;
|
||||
import utilities.util.FileResolutionResult;
|
||||
|
@ -272,16 +272,16 @@ public class SleighCompile extends SleighBase {
|
|||
// Some predefined symbols
|
||||
root = new SubtableSymbol(location, "instruction"); // Base constructors
|
||||
symtab.addSymbol(root);
|
||||
insertSpace(new ConstantSpace(this, "const", BasicCompilerSpec.CONSTANT_SPACE_INDEX));
|
||||
insertSpace(new ConstantSpace(this));
|
||||
SpaceSymbol spacesym = new SpaceSymbol(location, getConstantSpace()); // Constant
|
||||
// space
|
||||
symtab.addSymbol(spacesym);
|
||||
OtherSpace otherSpace = new OtherSpace(this, BasicCompilerSpec.OTHER_SPACE_NAME,
|
||||
BasicCompilerSpec.OTHER_SPACE_INDEX);
|
||||
OtherSpace otherSpace =
|
||||
new OtherSpace(this, SpaceNames.OTHER_SPACE_NAME, SpaceNames.OTHER_SPACE_INDEX);
|
||||
insertSpace(otherSpace);
|
||||
spacesym = new SpaceSymbol(location, otherSpace);
|
||||
symtab.addSymbol(spacesym);
|
||||
insertSpace(new UniqueSpace(this, "unique", numSpaces(), 0));
|
||||
insertSpace(new UniqueSpace(this, numSpaces(), 0));
|
||||
spacesym = new SpaceSymbol(location, getUniqueSpace()); // Temporary register
|
||||
// space
|
||||
symtab.addSymbol(spacesym);
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -20,33 +19,33 @@ import java.io.PrintStream;
|
|||
|
||||
import org.jdom.Element;
|
||||
|
||||
import ghidra.pcodeCPort.error.*;
|
||||
import ghidra.pcodeCPort.translate.*;
|
||||
|
||||
|
||||
import ghidra.pcodeCPort.error.LowlevelError;
|
||||
import ghidra.pcodeCPort.translate.Translate;
|
||||
import ghidra.program.model.lang.SpaceNames;
|
||||
|
||||
public class ConstantSpace extends AddrSpace {
|
||||
public ConstantSpace( Translate t, String nm, int ind ) {
|
||||
super( t, spacetype.IPTR_CONSTANT, nm, 8, 1, ind, 0, 0 );
|
||||
clearFlags( heritaged | big_endian );
|
||||
setFlags( big_endian );
|
||||
public ConstantSpace(Translate t) {
|
||||
super(t, spacetype.IPTR_CONSTANT, SpaceNames.CONSTANT_SPACE_NAME, 8, 1,
|
||||
SpaceNames.CONSTANT_SPACE_INDEX, 0, 0);
|
||||
clearFlags(heritaged | big_endian);
|
||||
setFlags(big_endian);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int printRaw( PrintStream s, long offset ) {
|
||||
s.append( "0x" );
|
||||
s.append( Long.toHexString( offset) );
|
||||
public int printRaw(PrintStream s, long offset) {
|
||||
s.append("0x");
|
||||
s.append(Long.toHexString(offset));
|
||||
return getTrans().getDefaultSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveXml( PrintStream s ) {
|
||||
throw new LowlevelError( "Should never save the constant space as XML" );
|
||||
public void saveXml(PrintStream s) {
|
||||
throw new LowlevelError("Should never save the constant space as XML");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreXml( Element el ) {
|
||||
throw new LowlevelError( "Should never restore the constant space from XML" );
|
||||
public void restoreXml(Element el) {
|
||||
throw new LowlevelError("Should never restore the constant space from XML");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -16,29 +15,30 @@
|
|||
*/
|
||||
package ghidra.pcodeCPort.space;
|
||||
|
||||
import ghidra.pcodeCPort.translate.*;
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
import ghidra.pcodeCPort.translate.Translate;
|
||||
import ghidra.program.model.lang.SpaceNames;
|
||||
|
||||
public class UniqueSpace extends AddrSpace {
|
||||
public UniqueSpace( Translate t, String nm, int ind, int fl ) {
|
||||
super( t, spacetype.IPTR_INTERNAL, nm, 4, 1, ind, fl, 0 );
|
||||
public UniqueSpace(Translate t, int ind, int fl) {
|
||||
super(t, spacetype.IPTR_INTERNAL, SpaceNames.UNIQUE_SPACE_NAME,
|
||||
SpaceNames.UNIQUE_SPACE_SIZE, 1, ind, fl, 0);
|
||||
|
||||
setFlags( hasphysical );
|
||||
setFlags(hasphysical);
|
||||
}
|
||||
|
||||
public UniqueSpace( Translate t ) {
|
||||
super( t, spacetype.IPTR_INTERNAL );
|
||||
public UniqueSpace(Translate t) {
|
||||
super(t, spacetype.IPTR_INTERNAL);
|
||||
|
||||
setFlags( hasphysical );
|
||||
setFlags(hasphysical);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveXml( PrintStream s ) {
|
||||
s.print( "<space_unique" );
|
||||
save_basic_attributes( s );
|
||||
s.println( "/>" );
|
||||
public void saveXml(PrintStream s) {
|
||||
s.print("<space_unique");
|
||||
save_basic_attributes(s);
|
||||
s.println("/>");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ import ghidra.pcodeCPort.pcoderaw.VarnodeData;
|
|||
import ghidra.pcodeCPort.space.*;
|
||||
import ghidra.pcodeCPort.utils.AddrSpaceToIdSymmetryMap;
|
||||
import ghidra.pcodeCPort.xml.DocumentStorage;
|
||||
import ghidra.program.model.lang.BasicCompilerSpec;
|
||||
import ghidra.program.model.lang.SpaceNames;
|
||||
|
||||
public abstract class Translate implements BasicSpaceProvider {
|
||||
|
||||
|
@ -215,10 +215,11 @@ public abstract class Translate implements BasicSpaceProvider {
|
|||
public abstract void initialize(DocumentStorage store);
|
||||
|
||||
protected void registerContext(String name, int sbit, int ebit) {
|
||||
// Base implementation (for compiling) doesn't need to keep track of context symbol
|
||||
}
|
||||
|
||||
public void setContextDefault(String name, int val) {
|
||||
}
|
||||
// public void setContextDefault(String name, int val) {
|
||||
// }
|
||||
|
||||
public abstract VarnodeData getRegister(String nm);
|
||||
|
||||
|
@ -257,11 +258,11 @@ public abstract class Translate implements BasicSpaceProvider {
|
|||
|
||||
protected void restoreXmlSpaces(Element el) {
|
||||
// The first space should always be the constant space
|
||||
insertSpace(new ConstantSpace(this, "const", BasicCompilerSpec.CONSTANT_SPACE_INDEX));
|
||||
insertSpace(new ConstantSpace(this));
|
||||
|
||||
// The second space should always be the other space
|
||||
insertSpace(new OtherSpace(this, BasicCompilerSpec.OTHER_SPACE_NAME,
|
||||
BasicCompilerSpec.OTHER_SPACE_INDEX));
|
||||
insertSpace(
|
||||
new OtherSpace(this, SpaceNames.OTHER_SPACE_NAME, SpaceNames.OTHER_SPACE_INDEX));
|
||||
|
||||
String defname = el.getAttributeValue("defaultspace");
|
||||
List<?> children = el.getChildren();
|
||||
|
@ -350,7 +351,7 @@ public abstract class Translate implements BasicSpaceProvider {
|
|||
boolean duplicatedefine = false;
|
||||
switch (spc.getType()) {
|
||||
case IPTR_CONSTANT:
|
||||
if (!spc.getName().equals("const")) {
|
||||
if (!spc.getName().equals(SpaceNames.CONSTANT_SPACE_NAME)) {
|
||||
nametype_mismatch = true;
|
||||
}
|
||||
if (baselist.size() != 0) {
|
||||
|
@ -359,7 +360,7 @@ public abstract class Translate implements BasicSpaceProvider {
|
|||
constantspace = spc;
|
||||
break;
|
||||
case IPTR_INTERNAL:
|
||||
if (!spc.getName().equals("unique")) {
|
||||
if (!spc.getName().equals(SpaceNames.UNIQUE_SPACE_NAME)) {
|
||||
nametype_mismatch = true;
|
||||
}
|
||||
if (uniqspace != null) {
|
||||
|
@ -368,7 +369,7 @@ public abstract class Translate implements BasicSpaceProvider {
|
|||
uniqspace = spc;
|
||||
break;
|
||||
case IPTR_FSPEC:
|
||||
if (!spc.getName().equals("fspec")) {
|
||||
if (!spc.getName().equals(SpaceNames.FSPEC_SPACE_NAME)) {
|
||||
nametype_mismatch = true;
|
||||
}
|
||||
if (fspecspace != null) {
|
||||
|
@ -377,7 +378,7 @@ public abstract class Translate implements BasicSpaceProvider {
|
|||
fspecspace = spc;
|
||||
break;
|
||||
case IPTR_IOP:
|
||||
if (!spc.getName().equals("iop")) {
|
||||
if (!spc.getName().equals(SpaceNames.IOP_SPACE_NAME)) {
|
||||
nametype_mismatch = true;
|
||||
}
|
||||
if (iopspace != null) {
|
||||
|
@ -386,18 +387,16 @@ public abstract class Translate implements BasicSpaceProvider {
|
|||
iopspace = spc;
|
||||
break;
|
||||
case IPTR_SPACEBASE:
|
||||
if (spc.getName().equals("stack")) {
|
||||
if (spc.getName().equals(SpaceNames.STACK_SPACE_NAME)) {
|
||||
if (stackspace != null) {
|
||||
duplicatedefine = true;
|
||||
}
|
||||
stackspace = spc;
|
||||
}
|
||||
else {
|
||||
}
|
||||
// fallthru
|
||||
case IPTR_PROCESSOR:
|
||||
if (spc.isOtherSpace()) {
|
||||
if (spc.getIndex() != BasicCompilerSpec.OTHER_SPACE_INDEX) {
|
||||
if (spc.getIndex() != SpaceNames.OTHER_SPACE_INDEX) {
|
||||
throw new LowlevelError("OTHER space must be assigned index 1");
|
||||
}
|
||||
}
|
||||
|
@ -481,7 +480,8 @@ public abstract class Translate implements BasicSpaceProvider {
|
|||
|
||||
// Get data for the stackpointer
|
||||
VarnodeData point = getRegister(el.getAttributeValue("register"));
|
||||
spc = new SpacebaseSpace("stack", ind, point.size, basespace, point.space.getDelay() + 1);
|
||||
spc = new SpacebaseSpace(SpaceNames.STACK_SPACE_NAME, ind, point.size, basespace,
|
||||
point.space.getDelay() + 1);
|
||||
insertSpace(spc);
|
||||
addSpacebase(stackspace, point.space, point.offset, point.size);
|
||||
}
|
||||
|
@ -554,7 +554,7 @@ public abstract class Translate implements BasicSpaceProvider {
|
|||
// spaceOrderMap = SpaceOrderMap.getSpaceOrderMapForProcessor( processorFile );
|
||||
}
|
||||
|
||||
public void allowContextSet(boolean val) {
|
||||
}
|
||||
// public void allowContextSet(boolean val) {
|
||||
// }
|
||||
|
||||
}
|
||||
|
|
|
@ -20,7 +20,8 @@ import java.util.List;
|
|||
|
||||
import db.DBRecord;
|
||||
import ghidra.program.database.DBObjectCache;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressOverflowException;
|
||||
import ghidra.program.model.lang.*;
|
||||
import ghidra.program.model.listing.*;
|
||||
import ghidra.program.model.mem.MemBuffer;
|
||||
|
@ -128,7 +129,7 @@ public class InstructionDB extends CodeUnitDB implements Instruction, Instructio
|
|||
|
||||
/**
|
||||
* Get the original context used to establish the shared prototype
|
||||
* @param baseContextReg
|
||||
* @param baseContextReg is a context register
|
||||
* @return prototype context value
|
||||
*/
|
||||
public RegisterValue getOriginalPrototypeContext(Register baseContextReg) {
|
||||
|
@ -158,8 +159,9 @@ public class InstructionDB extends CodeUnitDB implements Instruction, Instructio
|
|||
do {
|
||||
// skip past delay slot instructions
|
||||
try {
|
||||
instr = program.getListing().getInstructionContaining(
|
||||
instr.getMinAddress().subtractNoWrap(alignment));
|
||||
instr = program.getListing()
|
||||
.getInstructionContaining(
|
||||
instr.getMinAddress().subtractNoWrap(alignment));
|
||||
}
|
||||
catch (AddressOverflowException e) {
|
||||
return null;
|
||||
|
@ -219,10 +221,10 @@ public class InstructionDB extends CodeUnitDB implements Instruction, Instructio
|
|||
return EMPTY_ADDR_ARRAY;
|
||||
}
|
||||
|
||||
ArrayList<Address> list = new ArrayList<Address>();
|
||||
for (int i = 0; i < refs.length; ++i) {
|
||||
if (!refs[i].getReferenceType().isIndirect()) {
|
||||
list.add(refs[i].getToAddress());
|
||||
ArrayList<Address> list = new ArrayList<>();
|
||||
for (Reference ref : refs) {
|
||||
if (!ref.getReferenceType().isIndirect()) {
|
||||
list.add(ref.getToAddress());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -260,8 +262,7 @@ public class InstructionDB extends CodeUnitDB implements Instruction, Instructio
|
|||
lock.acquire();
|
||||
try {
|
||||
checkIsValid();
|
||||
return proto.getOperandRefType(opIndex, this, new InstructionPcodeOverride(this),
|
||||
new UniqueAddressFactory(program.getAddressFactory(), program.getLanguage()));
|
||||
return proto.getOperandRefType(opIndex, this, new InstructionPcodeOverride(this));
|
||||
}
|
||||
finally {
|
||||
lock.release();
|
||||
|
@ -593,10 +594,9 @@ public class InstructionDB extends CodeUnitDB implements Instruction, Instructio
|
|||
try {
|
||||
checkIsValid();
|
||||
if (!includeOverrides) {
|
||||
return proto.getPcode(this, null, null);
|
||||
return proto.getPcode(this, null);
|
||||
}
|
||||
return proto.getPcode(this, new InstructionPcodeOverride(this),
|
||||
new UniqueAddressFactory(program.getAddressFactory(), program.getLanguage()));
|
||||
return proto.getPcode(this, new InstructionPcodeOverride(this));
|
||||
}
|
||||
finally {
|
||||
lock.release();
|
||||
|
|
|
@ -17,7 +17,7 @@ package ghidra.program.model.address;
|
|||
|
||||
import java.math.BigInteger;
|
||||
|
||||
import ghidra.program.model.lang.BasicCompilerSpec;
|
||||
import ghidra.program.model.lang.SpaceNames;
|
||||
import ghidra.program.model.listing.Program;
|
||||
|
||||
/**
|
||||
|
@ -70,7 +70,7 @@ public interface AddressSpace extends Comparable<AddressSpace> {
|
|||
* get loaded into the final memory image and for user-defined spaces.
|
||||
*/
|
||||
public static final AddressSpace OTHER_SPACE = new GenericAddressSpace(
|
||||
BasicCompilerSpec.OTHER_SPACE_NAME, 64, TYPE_OTHER, BasicCompilerSpec.OTHER_SPACE_INDEX);
|
||||
SpaceNames.OTHER_SPACE_NAME, 64, TYPE_OTHER, SpaceNames.OTHER_SPACE_INDEX);
|
||||
|
||||
/**
|
||||
* The <code>EXTERNAL_SPACE</code> is used to contain all external locations (i.e., data and functions)
|
||||
|
|
|
@ -18,7 +18,7 @@ package ghidra.program.model.address;
|
|||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
import ghidra.program.model.lang.BasicCompilerSpec;
|
||||
import ghidra.program.model.lang.SpaceNames;
|
||||
import ghidra.util.datastruct.IntObjectHashtable;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
|
||||
|
@ -128,7 +128,7 @@ public class DefaultAddressFactory implements AddressFactory {
|
|||
|
||||
private void checkReservedJoin(AddressSpace space) {
|
||||
if (space.getType() == AddressSpace.TYPE_JOIN ||
|
||||
space.getName().equals(BasicCompilerSpec.JOIN_SPACE_NAME)) {
|
||||
space.getName().equals(SpaceNames.JOIN_SPACE_NAME)) {
|
||||
throw new IllegalArgumentException("Join space should not be specified");
|
||||
}
|
||||
}
|
||||
|
@ -142,7 +142,7 @@ public class DefaultAddressFactory implements AddressFactory {
|
|||
|
||||
private void checkReservedStack(AddressSpace space) {
|
||||
if (space.getType() == AddressSpace.TYPE_STACK ||
|
||||
space.getName().equalsIgnoreCase(BasicCompilerSpec.STACK_SPACE_NAME)) {
|
||||
space.getName().equalsIgnoreCase(SpaceNames.STACK_SPACE_NAME)) {
|
||||
throw new IllegalArgumentException("Stack space should not be specified");
|
||||
}
|
||||
}
|
||||
|
@ -399,7 +399,7 @@ public class DefaultAddressFactory implements AddressFactory {
|
|||
throw new DuplicateNameException("Space named " + space.getName() + " already exists!");
|
||||
}
|
||||
if (space.getType() == AddressSpace.TYPE_VARIABLE) {
|
||||
spaceNameTable.put("join", space);// Add VARIABLE space with name "join"
|
||||
spaceNameTable.put(SpaceNames.JOIN_SPACE_NAME, space);// Add VARIABLE space with name "join"
|
||||
return;// Don't put it in the spaces array or the id lookup table
|
||||
}
|
||||
spaces.add(space);
|
||||
|
|
|
@ -1,54 +0,0 @@
|
|||
/* ###
|
||||
* 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.model.address;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
|
||||
import ghidra.pcodeCPort.sleighbase.SleighBase;
|
||||
import ghidra.program.model.lang.Language;
|
||||
|
||||
public class UniqueAddressFactory {
|
||||
|
||||
private AddressFactory addrFactory;
|
||||
private AddressSpace uniqueSpace;
|
||||
private final long firstAvailableOffset;
|
||||
private long nextOffset;
|
||||
|
||||
public UniqueAddressFactory(AddressFactory addrFactory, Language language) {
|
||||
this.addrFactory = addrFactory;
|
||||
this.uniqueSpace = addrFactory.getUniqueSpace();
|
||||
if (language instanceof SleighLanguage) {
|
||||
firstAvailableOffset = ((SleighLanguage) language).getUniqueBase();
|
||||
}
|
||||
else {
|
||||
firstAvailableOffset = 0;
|
||||
}
|
||||
nextOffset = firstAvailableOffset;
|
||||
}
|
||||
|
||||
public synchronized Address getNextUniqueAddress() {
|
||||
Address addr = uniqueSpace.getAddress(nextOffset);
|
||||
nextOffset += SleighBase.MAX_UNIQUE_SIZE;
|
||||
return addr;
|
||||
}
|
||||
|
||||
public synchronized void reset() {
|
||||
nextOffset = firstAvailableOffset;
|
||||
}
|
||||
|
||||
public AddressFactory getAddressFactory() {
|
||||
return addrFactory;
|
||||
}
|
||||
}
|
|
@ -48,14 +48,6 @@ import ghidra.xml.*;
|
|||
*/
|
||||
public class BasicCompilerSpec implements CompilerSpec {
|
||||
|
||||
public static final String STACK_SPACE_NAME = "stack";
|
||||
public static final String JOIN_SPACE_NAME = "join";
|
||||
public static final String OTHER_SPACE_NAME = "OTHER";
|
||||
|
||||
//must match AddrSpace enum (see space.hh)
|
||||
public static final int CONSTANT_SPACE_INDEX = 0;
|
||||
public static final int OTHER_SPACE_INDEX = 1;
|
||||
|
||||
private final CompilerSpecDescription description;
|
||||
private String sourceName;
|
||||
private final SleighLanguage language;
|
||||
|
@ -426,21 +418,21 @@ public class BasicCompilerSpec implements CompilerSpec {
|
|||
@Override
|
||||
public AddressSpace getAddressSpace(String spaceName) {
|
||||
AddressSpace space;
|
||||
if (STACK_SPACE_NAME.equals(spaceName)) {
|
||||
if (SpaceNames.STACK_SPACE_NAME.equals(spaceName)) {
|
||||
space = stackSpace;
|
||||
}
|
||||
else if (JOIN_SPACE_NAME.equals(spaceName)) {
|
||||
else if (SpaceNames.JOIN_SPACE_NAME.equals(spaceName)) {
|
||||
if (joinSpace == null) {
|
||||
// This is a special address space that is only used internally to represent bonded registers
|
||||
joinSpace =
|
||||
new GenericAddressSpace(JOIN_SPACE_NAME, 64, AddressSpace.TYPE_JOIN, 10);
|
||||
joinSpace = new GenericAddressSpace(SpaceNames.JOIN_SPACE_NAME, 64,
|
||||
AddressSpace.TYPE_JOIN, 10);
|
||||
}
|
||||
space = joinSpace;
|
||||
}
|
||||
else {
|
||||
space = language.getAddressFactory().getAddressSpace(spaceName);
|
||||
}
|
||||
if (spaceName.equals(OTHER_SPACE_NAME)) {
|
||||
if (spaceName.equals(SpaceNames.OTHER_SPACE_NAME)) {
|
||||
space = AddressSpace.OTHER_SPACE;
|
||||
}
|
||||
if (space == null) {
|
||||
|
@ -701,7 +693,7 @@ public class BasicCompilerSpec implements CompilerSpec {
|
|||
parser.end();
|
||||
|
||||
if (stackPointer == null) {
|
||||
stackSpace = new GenericAddressSpace(STACK_SPACE_NAME,
|
||||
stackSpace = new GenericAddressSpace(SpaceNames.STACK_SPACE_NAME,
|
||||
language.getDefaultSpace().getSize(),
|
||||
language.getDefaultSpace().getAddressableUnitSize(), AddressSpace.TYPE_STACK, 0);
|
||||
}
|
||||
|
@ -979,7 +971,7 @@ public class BasicCompilerSpec implements CompilerSpec {
|
|||
throw new SleighException("Undefined base stack space: " + baseSpaceName);
|
||||
}
|
||||
int stackSpaceSize = Math.min(stackPointer.getBitLength(), stackBaseSpace.getSize());
|
||||
stackSpace = new GenericAddressSpace(STACK_SPACE_NAME, stackSpaceSize,
|
||||
stackSpace = new GenericAddressSpace(SpaceNames.STACK_SPACE_NAME, stackSpaceSize,
|
||||
stackBaseSpace.getAddressableUnitSize(), AddressSpace.TYPE_STACK, 0);
|
||||
String reverseJustifyStr = el.getAttribute("reversejustify");
|
||||
if (reverseJustifyStr != null) {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -16,8 +15,9 @@
|
|||
*/
|
||||
package ghidra.program.model.lang;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.UniqueAddressFactory;
|
||||
import ghidra.program.model.mem.MemBuffer;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.program.model.pcode.PcodeOp;
|
||||
|
@ -26,8 +26,6 @@ import ghidra.program.model.scalar.Scalar;
|
|||
import ghidra.program.model.symbol.FlowType;
|
||||
import ghidra.program.model.symbol.RefType;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* InstructionPrototype is designed to describe one machine level instruction.
|
||||
* A language parser can return the same InstructionProtoype object for the
|
||||
|
@ -252,11 +250,10 @@ public interface InstructionPrototype {
|
|||
* @param opIndex the index of the operand. (zero based)
|
||||
* @param context the instruction context
|
||||
* @param override if not null, steers local overrides of pcode generation
|
||||
* @param uniqueFactory must be specified if flowOverride is not null
|
||||
* @return reference type.
|
||||
*/
|
||||
public RefType getOperandRefType(int opIndex, InstructionContext context,
|
||||
PcodeOverride override, UniqueAddressFactory uniqueFactory);
|
||||
PcodeOverride override);
|
||||
|
||||
/**
|
||||
* Return true if the operand at opIndex should have a delimiter following it.
|
||||
|
@ -290,22 +287,18 @@ public interface InstructionPrototype {
|
|||
*
|
||||
* @param context the instruction context
|
||||
* @param override if not null, may indicate that different elements of the pcode generation are overridden
|
||||
* @param uniqueFactory must be specified if flowOverride is not null
|
||||
* @return array of PCODE,
|
||||
* zero length array if language doesn't support PCODE for this instruction
|
||||
*/
|
||||
public PcodeOp[] getPcode(InstructionContext context, PcodeOverride override,
|
||||
UniqueAddressFactory uniqueFactory);
|
||||
public PcodeOp[] getPcode(InstructionContext context, PcodeOverride override);
|
||||
|
||||
/**
|
||||
* Same as getPcode but returns the operations in a packed format to optimize transfer to other processes
|
||||
* @param context the instruction context
|
||||
* @param override if not null, may indicate that different elements of the pcode generation are overridden
|
||||
* @param uniqueFactory must be specified if flowOverride is not null
|
||||
* @return
|
||||
* @return the set of packed bytes encoding the p-code
|
||||
*/
|
||||
public PackedBytes getPcodePacked(InstructionContext context, PcodeOverride override,
|
||||
UniqueAddressFactory uniqueFactory);
|
||||
public PackedBytes getPcodePacked(InstructionContext context, PcodeOverride override);
|
||||
|
||||
/**
|
||||
* Get an array of PCode operations (micro code) that a particular operand
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -16,8 +15,9 @@
|
|||
*/
|
||||
package ghidra.program.model.lang;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.UniqueAddressFactory;
|
||||
import ghidra.program.model.mem.MemBuffer;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.program.model.pcode.PcodeOp;
|
||||
|
@ -26,8 +26,6 @@ import ghidra.program.model.scalar.Scalar;
|
|||
import ghidra.program.model.symbol.FlowType;
|
||||
import ghidra.program.model.symbol.RefType;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Class to represent an invalid instruction prototype.
|
||||
*/
|
||||
|
@ -39,6 +37,7 @@ public class InvalidPrototype implements InstructionPrototype, ParserContext {
|
|||
|
||||
/**
|
||||
* Construct a new invalid instruction prototype.
|
||||
* @param lang is the Language for which the invalid instruction is discovered
|
||||
*/
|
||||
public InvalidPrototype(Language lang) {
|
||||
super();
|
||||
|
@ -151,14 +150,12 @@ public class InvalidPrototype implements InstructionPrototype, ParserContext {
|
|||
}
|
||||
|
||||
@Override
|
||||
public PcodeOp[] getPcode(InstructionContext context, PcodeOverride override,
|
||||
UniqueAddressFactory uniqueFactory) {
|
||||
public PcodeOp[] getPcode(InstructionContext context, PcodeOverride override) {
|
||||
return new PcodeOp[] { new PcodeOp(context.getAddress(), 0, PcodeOp.UNIMPLEMENTED) };
|
||||
}
|
||||
|
||||
@Override
|
||||
public PackedBytes getPcodePacked(InstructionContext context, PcodeOverride override,
|
||||
UniqueAddressFactory uniqueFactory) {
|
||||
public PackedBytes getPcodePacked(InstructionContext context, PcodeOverride override) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -184,7 +181,7 @@ public class InvalidPrototype implements InstructionPrototype, ParserContext {
|
|||
|
||||
@Override
|
||||
public RefType getOperandRefType(int opIndex, InstructionContext context,
|
||||
PcodeOverride override, UniqueAddressFactory uniqueFactory) {
|
||||
PcodeOverride override) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,20 +19,15 @@ import java.io.IOException;
|
|||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.jdom.JDOMException;
|
||||
import org.xml.sax.*;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.SleighException;
|
||||
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
|
||||
import ghidra.app.plugin.processors.sleigh.template.*;
|
||||
import ghidra.pcodeCPort.sleighbase.SleighBase;
|
||||
import ghidra.pcodeCPort.slgh_compile.PcodeParser;
|
||||
import ghidra.app.plugin.processors.sleigh.*;
|
||||
import ghidra.app.plugin.processors.sleigh.template.ConstructTpl;
|
||||
import ghidra.program.model.lang.InjectPayload.InjectParameter;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.sleigh.grammar.Location;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.SystemUtilities;
|
||||
import ghidra.xml.*;
|
||||
import ghidra.xml.XmlParseException;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
|
||||
public class PcodeInjectLibrary {
|
||||
protected SleighLanguage language;
|
||||
|
@ -47,7 +42,7 @@ public class PcodeInjectLibrary {
|
|||
|
||||
public PcodeInjectLibrary(SleighLanguage l) {
|
||||
language = l;
|
||||
uniqueBase = language.getUniqueBase();
|
||||
uniqueBase = UniqueLayout.INJECT.getOffset(l);
|
||||
callFixupMap = new TreeMap<>();
|
||||
callOtherFixupMap = new TreeMap<>();
|
||||
callOtherOverride = null;
|
||||
|
@ -168,90 +163,21 @@ public class PcodeInjectLibrary {
|
|||
return; // Dynamic p-code generation, or already parsed
|
||||
}
|
||||
|
||||
String translateSpec = language.buildTranslatorTag(language.getAddressFactory(), uniqueBase,
|
||||
language.getSymbolTable());
|
||||
|
||||
try {
|
||||
PcodeParser parser = new PcodeParser(translateSpec);
|
||||
Location loc = new Location(sourceName, 1);
|
||||
InjectParameter[] input = payload.getInput();
|
||||
for (InjectParameter element : input) {
|
||||
parser.addOperand(loc, element.getName(), element.getIndex());
|
||||
}
|
||||
InjectParameter[] output = payload.getOutput();
|
||||
for (InjectParameter element : output) {
|
||||
parser.addOperand(loc, element.getName(), element.getIndex());
|
||||
}
|
||||
String constructTplXml =
|
||||
PcodeParser.stringifyTemplate(parser.compilePcode(pcodeText, sourceName, 1));
|
||||
if (constructTplXml == null) {
|
||||
throw new SleighException("pcode compile failed " + sourceName);
|
||||
}
|
||||
final SAXParseException[] exception = new SAXParseException[1];
|
||||
XmlPullParser xmlParser =
|
||||
XmlPullParserFactory.create(constructTplXml, sourceName, new ErrorHandler() {
|
||||
@Override
|
||||
public void warning(SAXParseException e) throws SAXException {
|
||||
Msg.warn(this, e.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fatalError(SAXParseException e) throws SAXException {
|
||||
exception[0] = e;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(SAXParseException e) throws SAXException {
|
||||
exception[0] = e;
|
||||
}
|
||||
}, false);
|
||||
|
||||
ConstructTpl constructTpl = new ConstructTpl();
|
||||
constructTpl.restoreXml(xmlParser, language.getAddressFactory());
|
||||
if (exception[0] != null) {
|
||||
throw new SleighException("pcode compiler returned invalid xml " + sourceName,
|
||||
exception[0]);
|
||||
}
|
||||
OpTpl[] opTemplates = constructTpl.getOpVec();
|
||||
adjustUniqueBase(opTemplates);
|
||||
|
||||
payloadSleigh.setTemplate(constructTpl);
|
||||
PcodeParser parser = new PcodeParser(language, uniqueBase);
|
||||
Location loc = new Location(sourceName, 1);
|
||||
InjectParameter[] input = payload.getInput();
|
||||
for (InjectParameter element : input) {
|
||||
parser.addOperand(loc, element.getName(), element.getIndex());
|
||||
}
|
||||
catch (UnknownInstructionException e) {
|
||||
throw new SleighException("compiled pcode contains invalid opcode " + sourceName, e);
|
||||
InjectParameter[] output = payload.getOutput();
|
||||
for (InjectParameter element : output) {
|
||||
parser.addOperand(loc, element.getName(), element.getIndex());
|
||||
}
|
||||
catch (JDOMException e) {
|
||||
throw new SleighException(
|
||||
"pcode compile failed due to invalid translator tag " + sourceName, e);
|
||||
}
|
||||
catch (SAXException e) {
|
||||
throw new SleighException("pcode compiler returned invalid xml " + sourceName, e);
|
||||
}
|
||||
}
|
||||
ConstructTpl constructTpl = parser.compilePcode(pcodeText, sourceName, 1);
|
||||
|
||||
//changed to protected for PcodeInjectLibraryJava
|
||||
protected void adjustUniqueBase(OpTpl[] opTemplates) {
|
||||
for (OpTpl opt : opTemplates) {
|
||||
VarnodeTpl out = opt.getOutput();
|
||||
if (out != null) {
|
||||
adjustUniqueBase(out);
|
||||
}
|
||||
for (VarnodeTpl in : opt.getInput()) {
|
||||
adjustUniqueBase(in);
|
||||
}
|
||||
}
|
||||
}
|
||||
uniqueBase = parser.getNextTempOffset();
|
||||
|
||||
private void adjustUniqueBase(VarnodeTpl v) {
|
||||
ConstTpl space = v.getSpace();
|
||||
if (!space.isUniqueSpace()) {
|
||||
return;
|
||||
}
|
||||
ConstTpl c = v.getOffset();
|
||||
long offset = c.getReal();
|
||||
if (offset >= uniqueBase) {
|
||||
uniqueBase = offset + SleighBase.MAX_UNIQUE_SIZE;
|
||||
}
|
||||
payloadSleigh.setTemplate(constructTpl);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.pcodeCPort.slgh_compile;
|
||||
package ghidra.program.model.lang;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
@ -21,32 +21,39 @@ import java.util.stream.Collectors;
|
|||
|
||||
import org.antlr.runtime.*;
|
||||
import org.antlr.runtime.tree.CommonTreeNodeStream;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.jdom.*;
|
||||
|
||||
import generic.stl.VectorSTL;
|
||||
import ghidra.app.plugin.processors.sleigh.SleighException;
|
||||
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
|
||||
import ghidra.app.plugin.processors.sleigh.*;
|
||||
import ghidra.app.plugin.processors.sleigh.symbol.Symbol;
|
||||
import ghidra.app.plugin.processors.sleigh.symbol.SymbolTable;
|
||||
import ghidra.app.plugin.processors.sleigh.symbol.UseropSymbol;
|
||||
import ghidra.app.plugin.processors.sleigh.symbol.VarnodeSymbol;
|
||||
import ghidra.app.plugin.processors.sleigh.template.*;
|
||||
import ghidra.pcode.utils.MessageFormattingUtils;
|
||||
import ghidra.pcodeCPort.address.Address;
|
||||
import ghidra.pcodeCPort.context.SleighError;
|
||||
import ghidra.pcodeCPort.error.LowlevelError;
|
||||
import ghidra.pcodeCPort.semantics.*;
|
||||
import ghidra.pcodeCPort.sleighbase.SleighBase;
|
||||
import ghidra.pcodeCPort.slgh_compile.*;
|
||||
import ghidra.pcodeCPort.slghsymbol.*;
|
||||
import ghidra.pcodeCPort.space.AddrSpace;
|
||||
import ghidra.pcodeCPort.utils.XmlUtils;
|
||||
import ghidra.pcodeCPort.slghsymbol.EndSymbol;
|
||||
import ghidra.pcodeCPort.slghsymbol.OperandSymbol;
|
||||
import ghidra.pcodeCPort.slghsymbol.StartSymbol;
|
||||
import ghidra.pcodeCPort.space.*;
|
||||
import ghidra.pcodeCPort.xml.DocumentStorage;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.sleigh.grammar.*;
|
||||
import ghidra.sleigh.grammar.SleighParser_SemanticParser.semantic_return;
|
||||
import ghidra.util.exception.AssertException;
|
||||
|
||||
/**
|
||||
* This class is intended to parse p-code snippets, typically from compiler specification files
|
||||
* or extensions. This is outside the normal SLEIGH compilation process, and the parser is built
|
||||
* on top of an existing SleighLanguage.
|
||||
*/
|
||||
public class PcodeParser extends PcodeCompile {
|
||||
|
||||
public final static Logger log = LogManager.getLogger(PcodeParser.class);
|
||||
|
||||
private SleighBase sleigh;
|
||||
private AddressFactory addrFactory;
|
||||
private long tempbase;
|
||||
private HashMap<String, SleighSymbol> symbolMap = new HashMap<>();
|
||||
|
||||
|
@ -60,25 +67,14 @@ public class PcodeParser extends PcodeCompile {
|
|||
}
|
||||
|
||||
/**
|
||||
* Build parser from a translator string
|
||||
* @param sleighSpec sleigh translator spec including address-spaces and register definitions, see
|
||||
* {@link SleighLanguage#buildTranslatorTag(ghidra.program.model.address.AddressFactory, long, ghidra.app.plugin.processors.sleigh.symbol.SymbolTable, boolean)}
|
||||
* @throws JDOMException
|
||||
* Build parser from an existing SleighLanguage.
|
||||
* @param language is the existing language
|
||||
* @param ubase is the starting offset for allocating temporary registers
|
||||
*/
|
||||
public PcodeParser(String sleighSpec) throws JDOMException {
|
||||
DocumentStorage store = new DocumentStorage();
|
||||
Document doc = null;
|
||||
try {
|
||||
doc = store.parseDocument(new StringBufferInputStream(sleighSpec));
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new AssertException(); // unexpected on string
|
||||
}
|
||||
store.registerTag(doc.getRootElement());
|
||||
public PcodeParser(SleighLanguage language, long ubase) {
|
||||
|
||||
PcodeTranslate translate = new PcodeTranslate();
|
||||
translate.initialize(store);
|
||||
sleigh = translate;
|
||||
addrFactory = language.getAddressFactory();
|
||||
sleigh = new PcodeTranslate(language, ubase);
|
||||
initializeSymbols();
|
||||
}
|
||||
|
||||
|
@ -97,6 +93,7 @@ public class PcodeParser extends PcodeCompile {
|
|||
* Inject a symbol representing an "operand" to the pcode snippet. This puts a placeholder in the
|
||||
* resulting template, which gets filled in with the context specific storage locations when final
|
||||
* p-code is generated
|
||||
* @param loc is location information for the operand
|
||||
* @param name of operand symbol
|
||||
* @param index to use for the placeholder
|
||||
*/
|
||||
|
@ -130,6 +127,10 @@ public class PcodeParser extends PcodeCompile {
|
|||
currentSymbols.clear();
|
||||
}
|
||||
|
||||
public long getNextTempOffset() {
|
||||
return tempbase;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long allocateTemp() {
|
||||
long base = tempbase;
|
||||
|
@ -138,8 +139,8 @@ public class PcodeParser extends PcodeCompile {
|
|||
}
|
||||
|
||||
@Override
|
||||
public VectorSTL<OpTpl> createMacroUse(Location location, MacroSymbol sym,
|
||||
VectorSTL<ExprTree> param) {
|
||||
public VectorSTL<ghidra.pcodeCPort.semantics.OpTpl> createMacroUse(Location location,
|
||||
MacroSymbol sym, VectorSTL<ExprTree> param) {
|
||||
throw new SleighError("Pcode snippet parsing does not support use of macros", location);
|
||||
}
|
||||
|
||||
|
@ -169,6 +170,7 @@ public class PcodeParser extends PcodeCompile {
|
|||
|
||||
@Override
|
||||
public void recordNop(Location location) {
|
||||
// No NOP statistics collected for snippet parsing
|
||||
}
|
||||
|
||||
// Make sure label symbols are used properly
|
||||
|
@ -181,19 +183,19 @@ public class PcodeParser extends PcodeCompile {
|
|||
LabelSymbol labsym = (LabelSymbol) sym;
|
||||
if (labsym.getRefCount() == 0) {
|
||||
errors.add(MessageFormattingUtils.format(labsym.location,
|
||||
String.format("Label <%s> was placed but never used", sym.getName())));
|
||||
String.format("Label <%s> was placed but never used", sym.getName())));
|
||||
|
||||
}
|
||||
else if (!labsym.isPlaced()) {
|
||||
errors.add(MessageFormattingUtils.format(labsym.location,
|
||||
String.format("Label <%s> was referenced but never placed", sym.getName())));
|
||||
String.format("Label <%s> was referenced but never placed", sym.getName())));
|
||||
}
|
||||
}
|
||||
return errors.stream().collect(Collectors.joining(" "));
|
||||
|
||||
}
|
||||
|
||||
private ConstructTpl buildConstructor(ConstructTpl rtl) {
|
||||
private ConstructTpl buildConstructor(ghidra.pcodeCPort.semantics.ConstructTpl rtl) {
|
||||
String errstring = "";
|
||||
if (rtl != null) {
|
||||
errstring = checkLabels();
|
||||
|
@ -210,38 +212,99 @@ public class PcodeParser extends PcodeCompile {
|
|||
if (errstring.length() != 0) {
|
||||
throw new SleighException(errstring);
|
||||
}
|
||||
return rtl;
|
||||
return translateConstructTpl(rtl);
|
||||
}
|
||||
|
||||
/**
|
||||
* This class wraps on existing SleighLanguage with the SleighBase interface expected by
|
||||
* PcodeCompile. It populates the symbol table with user-defined operations and the global
|
||||
* VarnodeSymbol objects, which typically includes all the general purpose registers.
|
||||
*/
|
||||
private static class PcodeTranslate extends SleighBase {
|
||||
|
||||
@Override
|
||||
public void initialize(DocumentStorage store) {
|
||||
Element el = store.getTag("sleigh");
|
||||
if (el == null) {
|
||||
throw new LowlevelError("Could not find sleigh tag");
|
||||
private void copySpaces(SleighLanguage language) {
|
||||
insertSpace(new ConstantSpace(this));
|
||||
insertSpace(
|
||||
new OtherSpace(this, SpaceNames.OTHER_SPACE_NAME, SpaceNames.OTHER_SPACE_INDEX));
|
||||
AddressSpace[] spaces = language.getAddressFactory().getAllAddressSpaces();
|
||||
for (AddressSpace spc : spaces) {
|
||||
if (spc.getUnique() < 2) {
|
||||
continue;
|
||||
}
|
||||
AddrSpace resSpace;
|
||||
int sz = spc.getSize();
|
||||
if (spc instanceof SegmentedAddressSpace) {
|
||||
// TODO: SegmentedAddressSpace shouldn't really return 21
|
||||
sz = 32;
|
||||
}
|
||||
if (sz > 64) {
|
||||
sz = 64;
|
||||
}
|
||||
int bytesize = (sz + 7) / 8; // Convert bits to bytes
|
||||
switch (spc.getType()) {
|
||||
case AddressSpace.TYPE_UNIQUE:
|
||||
resSpace = new UniqueSpace(this, spc.getUnique(), 0);
|
||||
break;
|
||||
case AddressSpace.TYPE_OTHER:
|
||||
resSpace = new OtherSpace(this, spc.getName(), spc.getUnique());
|
||||
break;
|
||||
case AddressSpace.TYPE_RAM:
|
||||
resSpace = new AddrSpace(this, spacetype.IPTR_PROCESSOR, spc.getName(),
|
||||
bytesize, spc.getAddressableUnitSize(), spc.getUnique(),
|
||||
AddrSpace.hasphysical, 1);
|
||||
break;
|
||||
case AddressSpace.TYPE_REGISTER:
|
||||
resSpace = new AddrSpace(this, spacetype.IPTR_PROCESSOR, spc.getName(),
|
||||
bytesize, spc.getAddressableUnitSize(), spc.getUnique(),
|
||||
AddrSpace.hasphysical, 0);
|
||||
break;
|
||||
default:
|
||||
resSpace = null;
|
||||
}
|
||||
if (resSpace == null) {
|
||||
break;
|
||||
}
|
||||
insertSpace(resSpace);
|
||||
}
|
||||
target_endian = XmlUtils.decodeBoolean(el.getAttributeValue("bigendian")) ? 1 : 0;
|
||||
alignment = XmlUtils.decodeUnknownInt(el.getAttributeValue("align"));
|
||||
long ubase = XmlUtils.decodeUnknownLong(el.getAttributeValue("uniqbase"));
|
||||
setDefaultSpace(language.getDefaultSpace().getUnique());
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate the predefined symbol table for the parser from the given SLEIGH language.
|
||||
* We only use user-defined op symbols and varnode symbols.
|
||||
* @param language is the SLEIGH language
|
||||
*/
|
||||
private void copySymbols(SleighLanguage language) {
|
||||
SymbolTable langTable = language.getSymbolTable();
|
||||
symtab.addScope(); // Global scope
|
||||
for (Symbol sym : langTable.getSymbolList()) {
|
||||
if (sym instanceof UseropSymbol) {
|
||||
UserOpSymbol cloneSym = new UserOpSymbol(null, sym.getName());
|
||||
cloneSym.setIndex(((UseropSymbol) sym).getIndex());
|
||||
symtab.addSymbol(cloneSym);
|
||||
}
|
||||
else if (sym instanceof VarnodeSymbol) {
|
||||
VarnodeData vData = ((VarnodeSymbol) sym).getFixedVarnode();
|
||||
if ("contextreg".equals(sym.getName())) {
|
||||
continue;
|
||||
}
|
||||
ghidra.pcodeCPort.slghsymbol.VarnodeSymbol cloneSym;
|
||||
AddrSpace base = getSpace(vData.space.getUnique());
|
||||
cloneSym = new ghidra.pcodeCPort.slghsymbol.VarnodeSymbol(null, sym.getName(),
|
||||
base, vData.offset, vData.size);
|
||||
symtab.addSymbol(cloneSym);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public PcodeTranslate(SleighLanguage language, long ubase) {
|
||||
super();
|
||||
target_endian = language.isBigEndian() ? 1 : 0;
|
||||
alignment = 0;
|
||||
setUniqueBase(ubase);
|
||||
|
||||
List<?> list = el.getChildren();
|
||||
Iterator<?> iter = list.iterator();
|
||||
Element child = (Element) iter.next();
|
||||
while (child.getName().equals("floatformat")) {
|
||||
child = (Element) iter.next(); // skip over
|
||||
}
|
||||
restoreXmlSpaces(child);
|
||||
|
||||
child = (Element) iter.next();
|
||||
|
||||
while ("truncate_space".equals(child.getName())) {
|
||||
// TODO: do we care about space truncations ?
|
||||
child = (Element) iter.next();
|
||||
}
|
||||
|
||||
symtab.restoreXml(child, this);
|
||||
copySpaces(language);
|
||||
copySymbols(language);
|
||||
|
||||
for (int i = 0; i < numSpaces(); i++) {
|
||||
AddrSpace space = getSpace(i);
|
||||
|
@ -250,29 +313,77 @@ public class PcodeParser extends PcodeCompile {
|
|||
}
|
||||
|
||||
@Override
|
||||
public int instructionLength(Address baseaddr) {
|
||||
return 0;
|
||||
public void initialize(DocumentStorage store) {
|
||||
// Unused
|
||||
}
|
||||
|
||||
@Override
|
||||
public int printAssembly(PrintStream s, int size, Address baseaddr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int instructionLength(Address baseaddr) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static String stringifyTemplate(ConstructTpl ctl) {
|
||||
|
||||
if (ctl == null) {
|
||||
return null;
|
||||
public ConstructTpl translateConstructTpl(
|
||||
ghidra.pcodeCPort.semantics.ConstructTpl constructTpl) {
|
||||
HandleTpl handle = null;
|
||||
if (constructTpl.getResult() != null) {
|
||||
handle = translateHandleTpl(constructTpl.getResult());
|
||||
}
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
ctl.saveXml(new PrintStream(out), -1); // for main section?
|
||||
return out.toString();
|
||||
OpTpl[] vec = new OpTpl[constructTpl.getOpvec().size()];
|
||||
for (int i = 0; i < vec.length; ++i) {
|
||||
vec[i] = translateOpTpl(constructTpl.getOpvec().get(i));
|
||||
}
|
||||
return new ConstructTpl(vec, handle, constructTpl.numLabels());
|
||||
}
|
||||
|
||||
public HandleTpl translateHandleTpl(ghidra.pcodeCPort.semantics.HandleTpl handleTpl) {
|
||||
return new HandleTpl(translateConstTpl(handleTpl.getSpace()),
|
||||
translateConstTpl(handleTpl.getSize()), translateConstTpl(handleTpl.getPtrSpace()),
|
||||
translateConstTpl(handleTpl.getPtrOffset()), translateConstTpl(handleTpl.getPtrSize()),
|
||||
translateConstTpl(handleTpl.getTempSpace()),
|
||||
translateConstTpl(handleTpl.getTempOffset()));
|
||||
}
|
||||
|
||||
public OpTpl translateOpTpl(ghidra.pcodeCPort.semantics.OpTpl opTpl) {
|
||||
VarnodeTpl output = null;
|
||||
if (opTpl.getOut() != null) {
|
||||
output = translateVarnodeTpl(opTpl.getOut());
|
||||
}
|
||||
VarnodeTpl[] input = new VarnodeTpl[opTpl.numInput()];
|
||||
for (int i = 0; i < input.length; ++i) {
|
||||
input[i] = translateVarnodeTpl(opTpl.getIn(i));
|
||||
}
|
||||
return new OpTpl(opTpl.getOpcode().ordinal(), output, input);
|
||||
}
|
||||
|
||||
public VarnodeTpl translateVarnodeTpl(ghidra.pcodeCPort.semantics.VarnodeTpl varnodeTpl) {
|
||||
return new VarnodeTpl(translateConstTpl(varnodeTpl.getSpace()),
|
||||
translateConstTpl(varnodeTpl.getOffset()), translateConstTpl(varnodeTpl.getSize()));
|
||||
}
|
||||
|
||||
public ConstTpl translateConstTpl(ghidra.pcodeCPort.semantics.ConstTpl constTpl) {
|
||||
AddrSpace spc = constTpl.getSpace();
|
||||
AddressSpace resSpace = null;
|
||||
if (spc != null) {
|
||||
resSpace = addrFactory.getAddressSpace(spc.getName());
|
||||
}
|
||||
int select = 0;
|
||||
ghidra.pcodeCPort.semantics.ConstTpl.v_field field = constTpl.getSelect();
|
||||
if (field != null) {
|
||||
select = field.ordinal();
|
||||
}
|
||||
return new ConstTpl(constTpl.getType().ordinal(), constTpl.getReal(), resSpace,
|
||||
constTpl.getHandleIndex(), select);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile pcode semantic statements.
|
||||
* @param pcodeStatements
|
||||
* @param pcodeStatements is the raw source to parse
|
||||
* @param srcFile source filename from which pcodeStatements came (
|
||||
* @param srcLine line number in srcFile corresponding to pcodeStatements
|
||||
* @return ConstructTpl. A null may be returned or
|
||||
|
@ -357,32 +468,35 @@ public class PcodeParser extends PcodeCompile {
|
|||
}
|
||||
|
||||
@Override
|
||||
public VectorSTL<OpTpl> createCrossBuild(Location where, VarnodeTpl v, SectionSymbol second) {
|
||||
public VectorSTL<ghidra.pcodeCPort.semantics.OpTpl> createCrossBuild(Location where,
|
||||
ghidra.pcodeCPort.semantics.VarnodeTpl v, SectionSymbol second) {
|
||||
throw new SleighError("Pcode snippet parsing does not support use of sections", where);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SectionVector standaloneSection(ConstructTpl main) {
|
||||
public SectionVector standaloneSection(ghidra.pcodeCPort.semantics.ConstructTpl main) {
|
||||
// Create SectionVector for just the main rtl section with no named sections
|
||||
SectionVector res = new SectionVector(main, null);
|
||||
return res;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SectionVector firstNamedSection(ConstructTpl main, SectionSymbol sym) {
|
||||
throw new SleighError("Pcode snippet parsing does not support use of sections",
|
||||
sym.location);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SectionVector nextNamedSection(SectionVector vec, ConstructTpl section,
|
||||
public SectionVector firstNamedSection(ghidra.pcodeCPort.semantics.ConstructTpl main,
|
||||
SectionSymbol sym) {
|
||||
throw new SleighError("Pcode snippet parsing does not support use of sections",
|
||||
sym.location);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SectionVector finalNamedSection(SectionVector vec, ConstructTpl section) {
|
||||
public SectionVector nextNamedSection(SectionVector vec,
|
||||
ghidra.pcodeCPort.semantics.ConstructTpl section, SectionSymbol sym) {
|
||||
throw new SleighError("Pcode snippet parsing does not support use of sections",
|
||||
sym.location);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SectionVector finalNamedSection(SectionVector vec,
|
||||
ghidra.pcodeCPort.semantics.ConstructTpl section) {
|
||||
throw new SleighError("Pcode snippet parsing does not support use of sections", null); // can never get here
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/* ###
|
||||
* 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.model.lang;
|
||||
|
||||
/**
|
||||
* Reserved AddressSpace names across architectures and associated attributes
|
||||
*/
|
||||
public class SpaceNames {
|
||||
public static final String CONSTANT_SPACE_NAME = "const"; // P-code constants
|
||||
public static final String UNIQUE_SPACE_NAME = "unique"; // Temporary p-code registers
|
||||
public static final String STACK_SPACE_NAME = "stack"; // Storage for stack relative varnodes
|
||||
public static final String JOIN_SPACE_NAME = "join"; // Logical storage for joined varnodes
|
||||
public static final String OTHER_SPACE_NAME = "OTHER"; // Other space
|
||||
public static final String IOP_SPACE_NAME = "iop"; // Internal p-code reference space
|
||||
public static final String FSPEC_SPACE_NAME = "fspec"; // Internal CALL reference
|
||||
|
||||
// must match ConstantSpace::INDEX (see space.hh)
|
||||
public static final int CONSTANT_SPACE_INDEX = 0; // Index for constant space is always 0
|
||||
// must match OtherSpace::INDEX (see space.hh)
|
||||
public static final int OTHER_SPACE_INDEX = 1; // Index for other space is always 1
|
||||
|
||||
public static final int UNIQUE_SPACE_SIZE = 4; // Number of bytes for a unique offset
|
||||
|
||||
}
|
|
@ -18,9 +18,9 @@ package ghidra.program.model.listing;
|
|||
import java.util.List;
|
||||
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.UniqueAddressFactory;
|
||||
import ghidra.program.model.lang.*;
|
||||
import ghidra.program.model.pcode.PcodeOp;
|
||||
import ghidra.program.model.pcode.PcodeOverride;
|
||||
import ghidra.program.model.symbol.FlowType;
|
||||
import ghidra.program.model.symbol.RefType;
|
||||
|
||||
|
|
|
@ -25,8 +25,7 @@ import ghidra.program.database.function.FunctionDB;
|
|||
import ghidra.program.database.symbol.CodeSymbol;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressOutOfBoundsException;
|
||||
import ghidra.program.model.lang.CompilerSpec;
|
||||
import ghidra.program.model.lang.Language;
|
||||
import ghidra.program.model.lang.*;
|
||||
import ghidra.program.model.listing.*;
|
||||
import ghidra.program.model.symbol.*;
|
||||
import ghidra.util.Msg;
|
||||
|
@ -64,7 +63,7 @@ public class HighFunction extends PcodeSyntaxTree {
|
|||
func = function;
|
||||
this.language = language;
|
||||
this.compilerSpec = compilerSpec;
|
||||
localSymbols = new LocalSymbolMap(this, "stack");
|
||||
localSymbols = new LocalSymbolMap(this, SpaceNames.STACK_SPACE_NAME);
|
||||
globalSymbols = new GlobalSymbolMap(this);
|
||||
proto = new FunctionPrototype(localSymbols, function);
|
||||
jumpTables = null;
|
||||
|
|
|
@ -27,6 +27,7 @@ import ghidra.pcode.error.LowlevelError;
|
|||
import ghidra.pcode.memstate.UniqueMemoryBank.WordInfo;
|
||||
import ghidra.program.model.address.AddressSpace;
|
||||
import ghidra.program.model.address.GenericAddressSpace;
|
||||
import ghidra.program.model.lang.SpaceNames;
|
||||
|
||||
public class UniqueMemoryBankTest extends AbstractGenericTest {
|
||||
|
||||
|
@ -39,7 +40,8 @@ public class UniqueMemoryBankTest extends AbstractGenericTest {
|
|||
|
||||
@Before
|
||||
public void setUp() {
|
||||
uniqueSpace = new GenericAddressSpace("unique", 64, AddressSpace.TYPE_UNIQUE, 0);
|
||||
uniqueSpace =
|
||||
new GenericAddressSpace(SpaceNames.UNIQUE_SPACE_NAME, 64, AddressSpace.TYPE_UNIQUE, 0);
|
||||
uniqueBank = new UniqueMemoryBank(uniqueSpace, false);
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ import static org.junit.Assert.*;
|
|||
import org.junit.*;
|
||||
|
||||
import generic.test.AbstractGenericTest;
|
||||
import ghidra.program.model.lang.SpaceNames;
|
||||
|
||||
public class AddressMapImplTest extends AbstractGenericTest {
|
||||
AddressSpace sp8;
|
||||
|
@ -49,7 +50,8 @@ public class AddressMapImplTest extends AbstractGenericTest {
|
|||
segSpace2 = new SegmentedAddressSpace("SegSpaceTwo", 4);
|
||||
|
||||
regSpace = new GenericAddressSpace("Register", 32, AddressSpace.TYPE_REGISTER, 0);
|
||||
stackSpace = new GenericAddressSpace("stack", 32, AddressSpace.TYPE_STACK, 0);
|
||||
stackSpace =
|
||||
new GenericAddressSpace(SpaceNames.STACK_SPACE_NAME, 32, AddressSpace.TYPE_STACK, 0);
|
||||
|
||||
map = new AddressMapImpl();
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ import static org.junit.Assert.*;
|
|||
import org.junit.*;
|
||||
|
||||
import generic.test.AbstractGenericTest;
|
||||
import ghidra.program.model.lang.SpaceNames;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
|
||||
public class GenericAddressTest extends AbstractGenericTest {
|
||||
|
@ -37,7 +38,8 @@ public class GenericAddressTest extends AbstractGenericTest {
|
|||
space2 = new GenericAddressSpace("Test2", 8, AddressSpace.TYPE_RAM, 1);
|
||||
wordSpace = new GenericAddressSpace("Test3", 16, 2, AddressSpace.TYPE_RAM, 1);
|
||||
regSpace = new GenericAddressSpace("Register", 8, AddressSpace.TYPE_REGISTER, 0);
|
||||
stackSpace = new GenericAddressSpace("stack", 8, AddressSpace.TYPE_STACK, 0);
|
||||
stackSpace =
|
||||
new GenericAddressSpace(SpaceNames.STACK_SPACE_NAME, 8, AddressSpace.TYPE_STACK, 0);
|
||||
factory =
|
||||
new TestAddressFactory(new AddressSpace[] { space, space2, regSpace }, stackSpace);
|
||||
space = factory.getAddressSpace(space.getName());
|
||||
|
|
|
@ -15,21 +15,22 @@
|
|||
*/
|
||||
package ghidra.program.model.pcode;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import generic.test.AbstractGenericTest;
|
||||
import ghidra.program.model.address.AddressSpace;
|
||||
import ghidra.program.model.address.GenericAddressSpace;
|
||||
import ghidra.program.model.lang.SpaceNames;
|
||||
|
||||
public class VarnodeTest extends AbstractGenericTest {
|
||||
|
||||
private static AddressSpace ramSpace = new GenericAddressSpace("ram", 64,
|
||||
AddressSpace.TYPE_RAM, 0);
|
||||
private static AddressSpace ramSpace =
|
||||
new GenericAddressSpace("ram", 64, AddressSpace.TYPE_RAM, 0);
|
||||
|
||||
private static AddressSpace stackSpace = new GenericAddressSpace("stack", ramSpace.getSize(),
|
||||
ramSpace.getAddressableUnitSize(), AddressSpace.TYPE_STACK, 0);
|
||||
private static AddressSpace stackSpace = new GenericAddressSpace(SpaceNames.STACK_SPACE_NAME,
|
||||
ramSpace.getSize(), ramSpace.getAddressableUnitSize(), AddressSpace.TYPE_STACK, 0);
|
||||
|
||||
// @formatter:off
|
||||
|
||||
|
@ -145,8 +146,8 @@ public class VarnodeTest extends AbstractGenericTest {
|
|||
super();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRamIntersects() {
|
||||
@Test
|
||||
public void testRamIntersects() {
|
||||
for (int i = 0; i < RAM_NODES.length; i++) {
|
||||
assertTrue("Varnodes expected to intersect [" + i + "]",
|
||||
RAM_NODES[i].intersects(INTERSECTING_RAM_NODES[i]));
|
||||
|
@ -157,8 +158,8 @@ public class VarnodeTest extends AbstractGenericTest {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStackIntersects() {
|
||||
@Test
|
||||
public void testStackIntersects() {
|
||||
for (int i = 0; i < STACK_NODES.length; i++) {
|
||||
assertTrue("Varnodes expected to intersect [" + i + "]",
|
||||
STACK_NODES[i].intersects(INTERSECTING_STACK_NODES[i]));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue