mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 18:29:37 +02:00
Use InjectPayload for segment ops
This commit is contained in:
parent
06de0d46a0
commit
4c3289f09f
7 changed files with 93 additions and 132 deletions
|
@ -124,31 +124,6 @@ SegmentOp::SegmentOp(Architecture *g,const string &nm,int4 ind)
|
|||
constresolve.space = (AddrSpace *)0;
|
||||
}
|
||||
|
||||
/// \brief Execute a stream of operations (OpFollow) given a starting input value
|
||||
///
|
||||
/// Each operation is performed in turn, with output from the previous becoming
|
||||
/// input of the next. The final output is returned.
|
||||
/// \param follow is the ordered set of operations to perform
|
||||
/// \param input is the constant input for the first operation
|
||||
/// \return the final constant output
|
||||
uintb SegmentOp::executeSide(const vector<OpFollow> &follow,uintb input)
|
||||
|
||||
{
|
||||
for(int4 i=0;i<follow.size();++i) {
|
||||
switch(follow[i].opc) {
|
||||
case CPUI_INT_AND:
|
||||
input &= follow[i].val;
|
||||
break;
|
||||
case CPUI_INT_LEFT:
|
||||
input <<= follow[i].val;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return input;
|
||||
}
|
||||
|
||||
bool SegmentOp::unify(Funcdata &data,PcodeOp *op,
|
||||
vector<Varnode *> &bindlist) const
|
||||
{
|
||||
|
@ -163,7 +138,7 @@ bool SegmentOp::unify(Funcdata &data,PcodeOp *op,
|
|||
if (op->getIn(0)->getOffset() != useropindex) return false;
|
||||
if (op->numInput() != 3) return false;
|
||||
innervn = op->getIn(1);
|
||||
if (basepresent) {
|
||||
if (baseinsize != 0) {
|
||||
basevn = op->getIn(1);
|
||||
innervn = op->getIn(2);
|
||||
if (basevn->isConstant())
|
||||
|
@ -181,40 +156,23 @@ bool SegmentOp::unify(Funcdata &data,PcodeOp *op,
|
|||
uintb SegmentOp::execute(const vector<uintb> &input) const
|
||||
|
||||
{
|
||||
uintb base,inner;
|
||||
|
||||
if (basepresent)
|
||||
base = executeSide(basefollow,input[1]);
|
||||
else
|
||||
base = 0;
|
||||
|
||||
inner = executeSide(innerfollow,input[0]);
|
||||
return (base+inner);
|
||||
ExecutablePcode *pcodeScript = (ExecutablePcode *)glb->pcodeinjectlib->getPayload(injectId);
|
||||
return pcodeScript->evaluate(input);
|
||||
}
|
||||
|
||||
void SegmentOp::restoreXml(const Element *el)
|
||||
|
||||
{
|
||||
spc = glb->getSpaceByName(el->getAttributeValue("space"));
|
||||
injectId = -1;
|
||||
baseinsize = 0;
|
||||
innerinsize = 0;
|
||||
bool userdefined = false;
|
||||
forcesegment = true;
|
||||
supportsfarpointer = false;
|
||||
name = "segment"; // Default name, might be overridden by userop attribute
|
||||
for(int4 i=0;i<el->getNumAttributes();++i) {
|
||||
const string &nm(el->getAttributeName(i));
|
||||
if (nm == "space") continue;
|
||||
else if (nm == "baseinsize") {
|
||||
istringstream s(el->getAttributeValue(i));
|
||||
s.unsetf(ios::dec | ios::hex | ios::oct);
|
||||
s >> baseinsize;
|
||||
}
|
||||
else if (nm == "innerinsize") {
|
||||
istringstream s1(el->getAttributeValue(i));
|
||||
s1.unsetf(ios::dec | ios::hex | ios::oct);
|
||||
s1 >> innerinsize;
|
||||
}
|
||||
else if (nm == "farpointer")
|
||||
supportsfarpointer = true;
|
||||
else if (nm == "userop") { // Based on existing sleigh op
|
||||
|
@ -227,28 +185,17 @@ void SegmentOp::restoreXml(const Element *el)
|
|||
throw LowlevelError("Redefining userop "+name);
|
||||
}
|
||||
}
|
||||
else if (nm == "force")
|
||||
forcesegment = xml_readbool(el->getAttributeValue(i));
|
||||
else
|
||||
throw LowlevelError("Bad segmentop tag attribute: "+nm);
|
||||
}
|
||||
if (!userdefined)
|
||||
throw LowlevelError("Missing userop attribute in segmentop tag");
|
||||
basepresent = (baseinsize != 0);
|
||||
|
||||
const List &list(el->getChildren());
|
||||
List::const_iterator iter;
|
||||
for(iter=list.begin();iter!=list.end();++iter) {
|
||||
const Element *subel = *iter;
|
||||
if (subel->getName()=="baseop") {
|
||||
basefollow.push_back(OpFollow());
|
||||
basefollow.back().restoreXml(subel);
|
||||
}
|
||||
else if (subel->getName()=="innerop") {
|
||||
innerfollow.push_back(OpFollow());
|
||||
innerfollow.back().restoreXml(subel);
|
||||
}
|
||||
else if (subel->getName()=="constresolve") {
|
||||
if (subel->getName()=="constresolve") {
|
||||
int4 sz;
|
||||
const List &sublist(subel->getChildren());
|
||||
if (!sublist.empty()) {
|
||||
|
@ -260,9 +207,28 @@ void SegmentOp::restoreXml(const Element *el)
|
|||
constresolve.size = sz;
|
||||
}
|
||||
}
|
||||
else if (subel->getName() == "pcode") {
|
||||
string nm = name + "_pcode";
|
||||
string source = "cspec";
|
||||
injectId = glb->pcodeinjectlib->restoreXmlInject(source, nm, InjectPayload::EXECUTABLEPCODE_TYPE, subel);
|
||||
}
|
||||
else
|
||||
throw LowlevelError("Bad segment pattern tag: "+subel->getName());
|
||||
}
|
||||
if (injectId < 0)
|
||||
throw LowlevelError("Missing <execute> child in <segmentop> tag");
|
||||
InjectPayload *payload = glb->pcodeinjectlib->getPayload(injectId);
|
||||
if (payload->sizeOutput() != 1)
|
||||
throw LowlevelError("<execute> child of <segmentop> tag must declare one <output>");
|
||||
if (payload->sizeInput() == 1) {
|
||||
innerinsize = payload->getInput(0).getSize();
|
||||
}
|
||||
else if (payload->sizeInput() == 2) {
|
||||
baseinsize = payload->getInput(0).getSize();
|
||||
innerinsize = payload->getInput(1).getSize();
|
||||
}
|
||||
else
|
||||
throw LowlevelError("<execute> child of <segmentop> tag must declare one or two <input> tags");
|
||||
}
|
||||
|
||||
/// \param g is the Architecture owning this set of jump assist scripts
|
||||
|
|
|
@ -198,24 +198,19 @@ struct OpFollow {
|
|||
/// The core routine that looks for the term-tree is unify().
|
||||
class SegmentOp : public TermPatternOp {
|
||||
AddrSpace *spc; ///< The physical address space into which a segmented pointer points
|
||||
int4 injectId; ///< Id of InjectPayload that emulates \b this operation
|
||||
int4 baseinsize; ///< The size in bytes of the \e base or \e segment value
|
||||
int4 innerinsize; ///< The size in bytes of the \e near pointer value
|
||||
bool basepresent; ///< Is \b true is a base value must be present in the raw p-code
|
||||
bool forcesegment; ///< Is \b true if an exception is thrown when a segment op can't be unified
|
||||
bool supportsfarpointer; ///< Is \b true if the joined pair base:near acts as a \b far pointer
|
||||
vector<OpFollow> basefollow; ///< Sequence of operations performed on the \b base value
|
||||
vector<OpFollow> innerfollow; ///< Sequence of operations performed on the \b near value
|
||||
VarnodeData constresolve; ///< How to resolve constant near pointers
|
||||
static uintb executeSide(const vector<OpFollow> &follow,uintb input);
|
||||
public:
|
||||
SegmentOp(Architecture *g,const string &nm,int4 ind); ///< Constructor
|
||||
AddrSpace *getSpace(void) const { return spc; } ///< Get the address space being pointed to
|
||||
bool hasFarPointerSupport(void) const { return supportsfarpointer; } ///< Return \b true, if \b this op supports far pointers
|
||||
bool isForced(void) const { return forcesegment; } ///< Return \b true if exceptions are thrown for bad unification
|
||||
int4 getBaseSize(void) const { return baseinsize; } ///< Get size in bytes of the base/segment value
|
||||
int4 getInnerSize(void) const { return innerinsize; } ///< Get size in bytes of the near value
|
||||
const VarnodeData &getResolve(void) const { return constresolve; } ///< Get the default register for resolving indirect segments
|
||||
virtual int4 getNumVariableTerms(void) const { if (basepresent) return 2; return 1; }
|
||||
virtual int4 getNumVariableTerms(void) const { if (baseinsize!=0) return 2; return 1; }
|
||||
virtual bool unify(Funcdata &data,PcodeOp *op,vector<Varnode *> &bindlist) const;
|
||||
virtual uintb execute(const vector<uintb> &input) const;
|
||||
virtual void restoreXml(const Element *el);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue