GT-2816 added ability to override indirect call destinations

This commit is contained in:
James 2019-04-17 13:34:29 -04:00
parent 4ce178c419
commit fa14932797
5 changed files with 229 additions and 179 deletions

View File

@ -149,7 +149,7 @@ public abstract class PcodeEmit {
public ParserWalker getWalker() {
return walker;
}
/**
* Make a note of the current op index, and associate
* it with the label index from the label template,
@ -158,11 +158,13 @@ public abstract class PcodeEmit {
* @param op = the label template op
*/
private void setLabel(OpTpl op) {
if (labeldef == null)
if (labeldef == null) {
labeldef = new ArrayList<Integer>();
}
int labelindex = (int) op.getInput()[0].getOffset().getReal() + labelbase;
while (labeldef.size() <= labelindex)
while (labeldef.size() <= labelindex) {
labeldef.add(null);
}
labeldef.set(labelindex, numOps);
}
@ -205,8 +207,8 @@ public abstract class PcodeEmit {
private void dumpNullReturn() {
VarnodeTpl nullAddr =
new VarnodeTpl(new ConstTpl(const_space), new ConstTpl(ConstTpl.REAL, 0), new ConstTpl(
ConstTpl.REAL, const_space.getPointerSize()));
new VarnodeTpl(new ConstTpl(const_space), new ConstTpl(ConstTpl.REAL, 0),
new ConstTpl(ConstTpl.REAL, const_space.getPointerSize()));
OpTpl retOpt = new OpTpl(PcodeOp.RETURN, null, new VarnodeTpl[] { nullAddr });
dump(retOpt);
@ -253,13 +255,11 @@ public abstract class PcodeEmit {
// <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(tmpAddr.getAddressSpace()),
new ConstTpl(ConstTpl.REAL, tmpAddr.getOffset()), 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));
VarnodeTpl label = new VarnodeTpl(new ConstTpl(const_space),
new ConstTpl(ConstTpl.J_RELATIVE, labelIndex), new ConstTpl(ConstTpl.REAL, 8));
VarnodeTpl dest = inputs[0];
VarnodeTpl cond = inputs[1];
@ -311,13 +311,12 @@ public abstract class PcodeEmit {
// RETURN tmp
Address tmpAddr = uniqueFactory.getNextUniqueAddress();
VarnodeTpl tmp =
new VarnodeTpl(new ConstTpl(tmpAddr.getAddressSpace()), new ConstTpl(ConstTpl.REAL,
tmpAddr.getOffset()), new ConstTpl(ConstTpl.REAL, ptrSize));
VarnodeTpl tmp = new VarnodeTpl(new ConstTpl(tmpAddr.getAddressSpace()),
new ConstTpl(ConstTpl.REAL, tmpAddr.getOffset()),
new ConstTpl(ConstTpl.REAL, ptrSize));
VarnodeTpl destAddr =
new VarnodeTpl(new ConstTpl(const_space), inputs[0].getOffset(), new ConstTpl(
ConstTpl.REAL, ptrSize));
VarnodeTpl destAddr = new VarnodeTpl(new ConstTpl(const_space), inputs[0].getOffset(),
new ConstTpl(ConstTpl.REAL, ptrSize));
OpTpl copyOpt = new OpTpl(PcodeOp.COPY, tmp, new VarnodeTpl[] { destAddr });
dump(copyOpt);
@ -353,23 +352,20 @@ public abstract class PcodeEmit {
// <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(tmpAddr.getAddressSpace()),
new ConstTpl(ConstTpl.REAL, tmpAddr.getOffset()), inputs[1].getSize());
tmpAddr = uniqueFactory.getNextUniqueAddress();
VarnodeTpl tmp2 =
new VarnodeTpl(new ConstTpl(tmpAddr.getAddressSpace()), new ConstTpl(ConstTpl.REAL,
tmpAddr.getOffset()), new ConstTpl(ConstTpl.REAL, ptrSize));
VarnodeTpl tmp2 = new VarnodeTpl(new ConstTpl(tmpAddr.getAddressSpace()),
new ConstTpl(ConstTpl.REAL, tmpAddr.getOffset()),
new ConstTpl(ConstTpl.REAL, ptrSize));
VarnodeTpl destAddr =
new VarnodeTpl(new ConstTpl(const_space), inputs[0].getOffset(), new ConstTpl(
ConstTpl.REAL, ptrSize));
VarnodeTpl destAddr = new VarnodeTpl(new ConstTpl(const_space), inputs[0].getOffset(),
new ConstTpl(ConstTpl.REAL, ptrSize));
int labelIndex = labelcount++;
VarnodeTpl label =
new VarnodeTpl(new ConstTpl(const_space), new ConstTpl(ConstTpl.J_RELATIVE,
labelIndex), new ConstTpl(ConstTpl.REAL, 8));
VarnodeTpl label = new VarnodeTpl(new ConstTpl(const_space),
new ConstTpl(ConstTpl.J_RELATIVE, labelIndex), new ConstTpl(ConstTpl.REAL, 8));
VarnodeTpl cond = inputs[1];
OpTpl negOpt = new OpTpl(PcodeOp.BOOL_NEGATE, tmp, new VarnodeTpl[] { cond });
@ -420,13 +416,16 @@ public abstract class PcodeEmit {
private void generateLocation(VarnodeTpl vntpl, VarnodeData vn) {
vn.space = vntpl.getSpace().fixSpace(walker);
vn.size = (int) vntpl.getSize().fix(walker);
if (vn.space == const_space)
if (vn.space == const_space) {
vn.offset =
vntpl.getOffset().fix(walker) & ConstTpl.calc_mask[vn.size > 8 ? 8 : vn.size];
else if (vn.space == uniq_space)
}
else if (vn.space == uniq_space) {
vn.offset = vntpl.getOffset().fix(walker) | uniqueoffset;
else
}
else {
vn.offset = vn.space.truncateOffset(vntpl.getOffset().fix(walker));
}
}
/**
@ -439,12 +438,15 @@ public abstract class PcodeEmit {
FixedHandle hand = walker.getFixedHandle(vntpl.getOffset().getHandleIndex());
vn.space = hand.offset_space;
vn.size = hand.offset_size;
if (vn.space == const_space)
if (vn.space == const_space) {
vn.offset = hand.offset_offset & ConstTpl.calc_mask[vn.size];
else if (vn.space == uniq_space)
}
else if (vn.space == uniq_space) {
vn.offset = hand.offset_offset | uniqueoffset;
else
}
else {
vn.offset = vn.space.truncateOffset(hand.offset_offset);
}
return hand.space;
}
@ -473,8 +475,9 @@ public abstract class PcodeEmit {
dump(startAddress, PcodeOp.LOAD, dyncache, 2, dyncache[2]);
numOps += 1;
}
else
else {
generateLocation(vn, incache[i]);
}
}
if ((isize > 0) && (opt.getInput()[0].isRelative())) {
incache[0].offset += labelbase;
@ -515,22 +518,25 @@ public abstract class PcodeEmit {
}
}
private void appendBuild(OpTpl bld, int secnum) throws UnknownInstructionException,
MemoryAccessException {
private void appendBuild(OpTpl bld, int secnum)
throws UnknownInstructionException, MemoryAccessException {
// Recover operand index from build statement
int index = (int) bld.getInput()[0].getOffset().getReal();
Symbol sym = walker.getConstructor().getOperand(index).getDefiningSymbol();
if ((sym == null) || (!(sym instanceof SubtableSymbol)))
if ((sym == null) || (!(sym instanceof SubtableSymbol))) {
return;
}
walker.pushOperand(index);
Constructor ct = walker.getConstructor();
if (secnum >= 0) {
ConstructTpl construct = ct.getNamedTempl(secnum);
if (construct == null)
if (construct == null) {
buildEmpty(ct, secnum);
else
}
else {
build(construct, secnum);
}
}
else {
ConstructTpl construct = ct.getTempl();
@ -548,8 +554,8 @@ public abstract class PcodeEmit {
private void delaySlot(OpTpl op) throws UnknownInstructionException, MemoryAccessException {
if (inDelaySlot) {
throw new SleighException("Delay Slot recursion problem for Instruction at " +
walker.getAddr());
throw new SleighException(
"Delay Slot recursion problem for Instruction at " + walker.getAddr());
}
inDelaySlot = true;
Address baseaddr = parsercontext.getAddr();
@ -589,11 +595,12 @@ public abstract class PcodeEmit {
* @throws UnknownInstructionException
* @throws MemoryAccessException
*/
private void appendCrossBuild(OpTpl bld, int secnum) throws UnknownInstructionException,
MemoryAccessException {
if (secnum >= 0)
throw new SleighException("CROSSBUILD recursion problem for instruction at " +
walker.getAddr());
private void appendCrossBuild(OpTpl bld, int secnum)
throws UnknownInstructionException, MemoryAccessException {
if (secnum >= 0) {
throw new SleighException(
"CROSSBUILD recursion problem for instruction at " + walker.getAddr());
}
secnum = (int) bld.getInput()[1].getOffset().getReal();
VarnodeTpl vn = bld.getInput()[0];
AddressSpace spc = vn.getSpace().fixSpace(walker);
@ -609,35 +616,38 @@ public abstract class PcodeEmit {
parsercontext = (SleighParserContext) instcontext.getParserContext(addr);
}
catch (UnknownContextException e) {
throw new UnknownInstructionException("Could not find cached crossbuild parser context");
throw new UnknownInstructionException(
"Could not find cached crossbuild parser context");
}
walker = new ParserWalker(parsercontext, oldwalker.getParserContext());
walker.baseState();
Constructor ct = walker.getConstructor();
ConstructTpl construct = ct.getNamedTempl(secnum);
if (construct == null)
if (construct == null) {
buildEmpty(ct, secnum);
else
}
else {
build(construct, secnum);
}
walker = oldwalker;
parsercontext = walker.getParserContext();
uniqueoffset = olduniqueoffset;
}
public void build(ConstructTpl construct, int secnum) throws UnknownInstructionException,
MemoryAccessException {
if (construct == null)
public void build(ConstructTpl construct, int secnum)
throws UnknownInstructionException, MemoryAccessException {
if (construct == null) {
throw new NotYetImplementedException(
"Semantics for this instruction are not implemented");
}
int oldbase = labelbase; // Recursively save old labelbase
labelbase = labelcount;
labelcount += construct.getNumLabels();
OpTpl[] optpllist = construct.getOpVec();
for (int i = 0; i < optpllist.length; ++i) {
OpTpl op = optpllist[i];
for (OpTpl op : optpllist) {
switch (op.getOpcode()) {
case PcodeOp.MULTIEQUAL: // Build placeholder
appendBuild(op, secnum);
@ -668,28 +678,32 @@ public abstract class PcodeEmit {
* @throws MemoryAccessException
* @throws UnknownInstructionException
*/
private void buildEmpty(Constructor ct, int secnum) throws UnknownInstructionException,
MemoryAccessException {
private void buildEmpty(Constructor ct, int secnum)
throws UnknownInstructionException, MemoryAccessException {
int numops = ct.getNumOperands();
for (int i = 0; i < numops; ++i) {
TripleSymbol sym = ct.getOperand(i).getDefiningSymbol();
if ((sym == null) || (!(sym instanceof SubtableSymbol)))
if ((sym == null) || (!(sym instanceof SubtableSymbol))) {
continue;
}
walker.pushOperand(i);
ConstructTpl construct = walker.getConstructor().getNamedTempl(secnum);
if (construct == null)
if (construct == null) {
buildEmpty(walker.getConstructor(), secnum);
else
}
else {
build(construct, secnum);
}
walker.popOperand();
}
}
void checkOverlays(int opcode, VarnodeData[] in, int isize, VarnodeData out) {
if (uniqueFactory == null)
if (uniqueFactory == null) {
return;
}
if ((opcode == PcodeOp.LOAD) || (opcode == PcodeOp.STORE)) {
int spaceId = (int) in[0].offset;
AddressSpace space = uniqueFactory.getAddressFactory().getAddressSpace(spaceId);
@ -713,16 +727,36 @@ public abstract class PcodeEmit {
}
}
void checkOverrides(int opcode, VarnodeData[] in) {
/**
* Applies opcode-specific overrides
* @param opcode opcode of instruction
* @param in input varnodes
* @return opcode of modified instruction
*/
int checkOverrides(int opcode, VarnodeData[] in) {
if (override == null) {
return;
return opcode;
}
//If there is an overriding reference on an indirect call, change the indirect
//call to a direct call
if (opcode == PcodeOp.CALLIND) {
Address callRef = override.getOverridingCallReference();
if (callRef != null) {
VarnodeData dest = in[0];
dest.space = callRef.getAddressSpace();
dest.offset = callRef.getOffset();
dest.size = dest.space.getPointerSize();
return PcodeOp.CALL;
}
}
// Simple call reference override - use primary call reference as destination
// Only perform reference override if destination function does not have a call-fixup
if (opcode == PcodeOp.CALL && !override.hasCallFixup(in[0].space.getAddress(in[0].offset))) {
// Only perform reference override if destination function does not have a call-fixup
if (opcode == PcodeOp.CALL &&
!override.hasCallFixup(in[0].space.getAddress(in[0].offset))) {
// Check for call reference (not supported if call-fixup exists for the instruction)
Address callRef = override.getPrimaryCallReference();
Address callRef = override.getOverridingCallReference();
if (callRef != null) {
VarnodeData dest = in[0];
dest.space = callRef.getAddressSpace();
@ -740,6 +774,6 @@ public abstract class PcodeEmit {
dest.size = dest.space.getPointerSize();
}
}
return opcode;
}
}

View File

@ -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,40 +15,36 @@
*/
package ghidra.app.plugin.processors.sleigh;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSpace;
import ghidra.program.model.address.UniqueAddressFactory;
import ghidra.program.model.lang.InstructionContext;
import ghidra.program.model.pcode.PcodeOp;
import ghidra.program.model.pcode.PcodeOverride;
import ghidra.program.model.pcode.Varnode;
import java.util.ArrayList;
import ghidra.program.model.address.*;
import ghidra.program.model.lang.InstructionContext;
import ghidra.program.model.pcode.*;
public class PcodeEmitObjects extends PcodeEmit {
private ArrayList<PcodeOp> oplist;
private ArrayList<Integer> labelref = null;
/**
* Pcode emitter constructor for producing PcodeOp objects for unimplemented, snippets or empty responses
* when {@link #getFallOffset()} will not be used.
* @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, null);
}
/**
* Pcode emitter constructor for producing PcodeOp objects for unimplemented, snippets or empty responses.
* @param walk state of the ParserContext from which to generate p-code
* @param fallOffset default fall-through offset (i.e., the full length
* 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);
public PcodeEmitObjects(ParserWalker walk, int fallOffset) { // For use with emitting precompiled p-code templates
this(walk, null, fallOffset, null, null);
}
/**
* @param walk state of the ParserContext from which to generate p-code
* @param ictx is the InstructionContext used to resolve delayslot and crossbuild directives
@ -57,68 +52,76 @@ public class PcodeEmitObjects extends PcodeEmit {
* @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);
public PcodeEmitObjects(ParserWalker walk, InstructionContext ictx, int fallOffset,
PcodeOverride override, UniqueAddressFactory uniqueFactory) {
super(walk, ictx, fallOffset, override, uniqueFactory);
oplist = new ArrayList<PcodeOp>();
}
public PcodeOp[] getPcodeOp() {
PcodeOp[] retop = new PcodeOp[oplist.size()];
oplist.toArray(retop);
return retop;
}
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.PcodeEmit#resolveRelatives()
*/
@Override
public void resolveRelatives() {
if (labelref==null) return;
for(int i=0;i<labelref.size();++i) {
if (labelref == null) {
return;
}
for (int i = 0; i < labelref.size(); ++i) {
int opindex = labelref.get(i);
PcodeOp op = oplist.get(opindex);
Varnode vn = op.getInput(0);
int labelid = (int)vn.getOffset();
if ((labelid>=labeldef.size())||(labeldef.get(labelid)==null))
int labelid = (int) vn.getOffset();
if ((labelid >= labeldef.size()) || (labeldef.get(labelid) == null)) {
throw new SleighException("Reference to non-existant sleigh label");
long res = (long)labeldef.get(labelid) - (long)opindex;
}
long res = (long) labeldef.get(labelid) - (long) opindex;
if (vn.getSize() < 8) {
long mask = -1;
mask >>>= (8-vn.getSize())*8;
mask >>>= (8 - vn.getSize()) * 8;
res &= mask;
}
AddressSpace spc = vn.getAddress().getAddressSpace();
vn = new Varnode(spc.getAddress(res),vn.getSize());
vn = new Varnode(spc.getAddress(res), vn.getSize());
op.setInput(vn, 0);
}
}
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.PcodeEmit#addLabelRef()
*/
@Override
void addLabelRef() {
if (labelref == null)
if (labelref == null) {
labelref = new ArrayList<Integer>();
}
labelref.add(numOps);
}
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.PcodeEmit#dump(ghidra.program.model.address.Address, int, ghidra.app.plugin.processors.sleigh.VarnodeData[], int, ghidra.app.plugin.processors.sleigh.VarnodeData)
*/
void dump(Address instrAddr, int opcode,VarnodeData[] in,int isize,VarnodeData out) {
checkOverrides(opcode,in);
@Override
void dump(Address instrAddr, int opcode, VarnodeData[] in, int isize, VarnodeData out) {
opcode = checkOverrides(opcode, in);
Varnode outvn;
if (out != null) {
outvn = new Varnode(out.space.getAddress(out.offset),out.size);
outvn = new Varnode(out.space.getAddress(out.offset), out.size);
}
else
else {
outvn = null;
Varnode[] invn = new Varnode[isize];
for(int i=0;i<isize;++i) {
invn[i] = new Varnode(in[i].space.getAddress(in[i].offset),
in[i].size);
}
PcodeOp op = new PcodeOp(instrAddr,oplist.size(), opcode,invn,outvn);
Varnode[] invn = new Varnode[isize];
for (int i = 0; i < isize; ++i) {
invn[i] = new Varnode(in[i].space.getAddress(in[i].offset), in[i].size);
}
PcodeOp op = new PcodeOp(instrAddr, oplist.size(), opcode, invn, outvn);
oplist.add(op);
}
}

View File

@ -28,30 +28,26 @@ import ghidra.program.model.pcode.PcodeOverride;
*
*/
public class PcodeEmitPacked extends PcodeEmit {
public final static int unimpl_tag = 0x20,
inst_tag = 0x21,
op_tag = 0x22,
void_tag = 0x23,
spaceid_tag = 0x24,
addrsz_tag = 0x25,
end_tag = 0x60; // End of a number
public final static int unimpl_tag = 0x20, inst_tag = 0x21, op_tag = 0x22, void_tag = 0x23,
spaceid_tag = 0x24, addrsz_tag = 0x25, end_tag = 0x60; // End of a number
public class LabelRef {
public int opIndex; // Index of operation referencing the label
public int labelIndex; // Index of label being referenced
public int labelSize; // Number of bytes in the label
public int streampos; // Position in byte stream where label is getting encoded
public LabelRef(int op,int lab,int size,int stream) {
public LabelRef(int op, int lab, int size, int stream) {
opIndex = op;
labelIndex = lab;
labelSize = size;
streampos = stream;
}
}
private PackedBytes buf;
private ArrayList<LabelRef> labelref = null;
/**
* Pcode emitter constructor for producing a packed binary representation
* for unimplemented or empty responses.
@ -60,7 +56,7 @@ public class PcodeEmitPacked extends PcodeEmit {
super();
buf = new PackedBytes(64);
}
/**
* Pcode emitter constructor for producing a packed binary representation.
* @param delayContexts delay slotted instruction contexts
@ -68,76 +64,86 @@ public class PcodeEmitPacked extends PcodeEmit {
* @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);
public PcodeEmitPacked(ParserWalker walk, InstructionContext ictx, int fallOffset,
PcodeOverride override, UniqueAddressFactory uniqueFactory) {
super(walk, ictx, fallOffset, override, uniqueFactory);
buf = new PackedBytes(512);
}
public PackedBytes getPackedBytes() {
return buf;
}
@Override
public void resolveRelatives() {
if (labelref==null) return;
for(int i=0;i<labelref.size();++i) {
if (labelref == null) {
return;
}
for (int i = 0; i < labelref.size(); ++i) {
LabelRef ref = labelref.get(i);
if ((ref.labelIndex>=labeldef.size())||(labeldef.get(ref.labelIndex)==null))
if ((ref.labelIndex >= labeldef.size()) || (labeldef.get(ref.labelIndex) == null)) {
throw new SleighException("Reference to non-existant sleigh label");
long res = (long)labeldef.get(ref.labelIndex) - (long)ref.opIndex;
}
long res = (long) labeldef.get(ref.labelIndex) - (long) ref.opIndex;
if (ref.labelSize < 8) {
long mask = -1;
mask >>>= (8-ref.labelSize)*8;
mask >>>= (8 - ref.labelSize) * 8;
res &= mask;
}
// We need to skip over op_tag, op_code, void_tag, addrsz_tag, and spc bytes
insertOffset(ref.streampos+5,res); // Insert the final offset into the stream
insertOffset(ref.streampos + 5, res); // Insert the final offset into the stream
}
}
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.PcodeEmit#addLabelRef()
*/
@Override
void addLabelRef() {
if (labelref == null)
if (labelref == null) {
labelref = new ArrayList<LabelRef>();
int labelIndex = (int)incache[0].offset;
}
int labelIndex = (int) incache[0].offset;
int labelSize = incache[0].size;
// Force the emitter to write out a maximum length encoding (12 bytes) of a long
// so that we have space to insert whatever value we need to when this relative is resolved
incache[0].offset = -1;
labelref.add(new LabelRef(numOps,labelIndex,labelSize,buf.size()));
labelref.add(new LabelRef(numOps, labelIndex, labelSize, buf.size()));
}
/* (non-Javadoc)
* @see ghidra.app.plugin.processors.sleigh.PcodeEmit#dump(ghidra.program.model.address.Address, int, ghidra.app.plugin.processors.sleigh.VarnodeData[], int, ghidra.app.plugin.processors.sleigh.VarnodeData)
*/
void dump(Address instrAddr, int opcode,VarnodeData[] in,int isize,VarnodeData out) {
checkOverrides(opcode,in);
checkOverlays(opcode,in,isize,out);
@Override
void dump(Address instrAddr, int opcode, VarnodeData[] in, int isize, VarnodeData out) {
opcode = checkOverrides(opcode, in);
checkOverlays(opcode, in, isize, out);
buf.write(op_tag);
buf.write(opcode + 0x20);
if (out==null)
if (out == null) {
buf.write(void_tag);
else
}
else {
dumpVarnodeData(out);
int i=0;
if ((opcode==PcodeOp.LOAD)||(opcode==PcodeOp.STORE)) {
}
int i = 0;
if ((opcode == PcodeOp.LOAD) || (opcode == PcodeOp.STORE)) {
dumpSpaceId(in[0]);
i = 1;
}
for(;i<isize;++i)
for (; i < isize; ++i) {
dumpVarnodeData(in[i]);
}
buf.write(end_tag);
}
private void dumpSpaceId(VarnodeData v) {
buf.write(spaceid_tag);
int spcindex = ((int)v.offset >> AddressSpace.ID_UNIQUE_SHIFT);
int spcindex = ((int) v.offset >> AddressSpace.ID_UNIQUE_SHIFT);
buf.write(spcindex + 0x20);
}
private void dumpVarnodeData(VarnodeData v) {
buf.write(addrsz_tag);
int spcindex = v.space.getUnique();
@ -145,37 +151,40 @@ public class PcodeEmitPacked extends PcodeEmit {
dumpOffset(v.offset);
buf.write(v.size + 0x20);
}
public void write(int val) {
buf.write(val);
}
/**
* Encode and dump an integer value to the packed byte stream
* @param val is the integer to write
*/
public void dumpOffset(long val) {
while (val!=0) {
int chunk = (int)(val & 0x3f);
while (val != 0) {
int chunk = (int) (val & 0x3f);
val >>>= 6;
buf.write(chunk + 0x20);
}
buf.write(end_tag);
}
private void insertOffset(int streampos,long val) {
while(val!=0) {
if (buf.getByte(streampos)==end_tag)
private void insertOffset(int streampos, long val) {
while (val != 0) {
if (buf.getByte(streampos) == end_tag) {
throw new SleighException("Could not properly insert relative jump offset");
int chunk = (int)(val & 0x3f);
}
int chunk = (int) (val & 0x3f);
val >>>= 6;
buf.insertByte(streampos,chunk + 0x20);
buf.insertByte(streampos, chunk + 0x20);
streampos += 1;
}
for(int i=0;i<11;++i) {
if (buf.getByte(streampos)==end_tag) return;
buf.insertByte(streampos,0x20); // Zero fill
streampos += 1;
for (int i = 0; i < 11; ++i) {
if (buf.getByte(streampos) == end_tag) {
return;
}
buf.insertByte(streampos, 0x20); // Zero fill
streampos += 1;
}
throw new SleighException("Could not find terminator while inserting relative jump offset");
}

View File

@ -19,6 +19,7 @@ import ghidra.program.model.address.Address;
import ghidra.program.model.lang.InjectPayload;
import ghidra.program.model.pcode.PcodeOverride;
import ghidra.program.model.symbol.Reference;
import ghidra.program.model.symbol.SourceType;
import ghidra.util.Msg;
public class InstructionPcodeOverride implements PcodeOverride {
@ -50,9 +51,10 @@ public class InstructionPcodeOverride implements PcodeOverride {
}
@Override
public Address getPrimaryCallReference() {
public Address getOverridingCallReference() {
for (Reference ref : instr.getReferencesFrom()) {
if (ref.isPrimary() && ref.getReferenceType().isCall()) {
if (ref.getSource().equals(SourceType.USER_DEFINED) && ref.isPrimary() &&
ref.getReferenceType().isCall()) {
return ref.getToAddress();
}
}

View File

@ -18,9 +18,10 @@ package ghidra.program.model.pcode;
import ghidra.program.model.address.Address;
import ghidra.program.model.lang.InjectPayload;
import ghidra.program.model.listing.FlowOverride;
import ghidra.program.model.symbol.SourceType;
public interface PcodeOverride {
/**
* @return current instruction address
*/
@ -34,10 +35,11 @@ public interface PcodeOverride {
FlowOverride getFlowOverride();
/**
* Get the primary call reference address from the current instruction
* Get the primary call reference address (whose {@link SourceType} must be {@link SourceType#USER_DEFINED})
* from the current instruction
* @return call reference address or null
*/
Address getPrimaryCallReference();
Address getOverridingCallReference();
/**
* Get the fall-through override address which may have been
@ -45,23 +47,23 @@ public interface PcodeOverride {
* @return fall-through override address or null
*/
Address getFallThroughOverride();
/**
* Returns the call-fixup for a specified call destination.
* @param callDestAddr call destination address. This address is used to
* identify a function which may have been tagged with a CallFixup.
* @return true if call destination function has been tagged with a call-fixup
*/
* Returns the call-fixup for a specified call destination.
* @param callDestAddr call destination address. This address is used to
* identify a function which may have been tagged with a CallFixup.
* @return true if call destination function has been tagged with a call-fixup
*/
boolean hasCallFixup(Address callDestAddr);
/**
* Returns the call-fixup for a specified call destination.
* If the destination function has not be tagged or was tagged
* with an unknown CallFixup name this method will return null.
* @param callDestAddr call destination address. This address is used to
* identify a function which may have been tagged with a CallFixup.
* @return call fixup object or null
*/
* Returns the call-fixup for a specified call destination.
* If the destination function has not be tagged or was tagged
* with an unknown CallFixup name this method will return null.
* @param callDestAddr call destination address. This address is used to
* identify a function which may have been tagged with a CallFixup.
* @return call fixup object or null
*/
InjectPayload getCallFixup(Address callDestAddr);
}