Addition of INSERT,EXTRACT, and POPCOUNT opcodes to decompiler code

This commit is contained in:
caheckman 2019-09-04 13:15:07 -04:00
parent 2cafb27574
commit 0fdd29b98d
17 changed files with 164 additions and 8 deletions

View file

@ -712,6 +712,22 @@ int4 mostsigbit_set(uintb val)
return res;
}
/// Count the number (population) bits set.
/// \param val is the given value
/// \return the number of one bits
int4 popcount(uintb val)
{
val = (val & 0x5555555555555555L) + ((val >> 1) & 0x5555555555555555L);
val = (val & 0x3333333333333333L) + ((val >> 2) & 0x3333333333333333L);
val = (val & 0x0f0f0f0f0f0f0f0fL) + ((val >> 4) & 0x0f0f0f0f0f0f0f0fL);
val = (val & 0x00ff00ff00ff00ffL) + ((val >> 8) & 0x00ff00ff00ff00ffL);
val = (val & 0x0000ffff0000ffffL) + ((val >> 16) & 0x0000ffff0000ffffL);
int4 res = (int4)(val & 0xff);
res += (int4)((val >> 32) & 0xff);
return res;
}
/// Count the number of more significant zero bits before the most significant
/// one bit in the representation of the given value;
/// \param val is the given value

View file

@ -495,6 +495,7 @@ extern void byte_swap(intb &val,int4 size); ///< Swap bytes in the given value
extern uintb byte_swap(uintb val,int4 size); ///< Return the given value with bytes swapped
extern int4 leastsigbit_set(uintb val); ///< Return index of least significant bit set in given value
extern int4 mostsigbit_set(uintb val); ///< Return index of most significant bit set in given value
extern int4 popcount(uintb val); ///< Return the number of one bits in the given value
extern int4 count_leading_zeros(uintb val); ///< Return the number of leading zero bits in the given value
extern uintb coveringmask(uintb val); ///< Return a mask that \e covers the given value

View file

@ -3053,6 +3053,34 @@ void ActionDeadCode::propagateConsumed(vector<Varnode *> &worklist)
pushConsumed(a,op->getIn(0),worklist);
pushConsumed(a,op->getIn(1),worklist);
break;
case CPUI_INSERT:
a = 1;
a <<= (int4)op->getIn(3)->getOffset();
a -= 1; // Insert mask
pushConsumed(a,op->getIn(1),worklist);
a <<= (int4)op->getIn(2)->getOffset();
pushConsumed(outc & ~a, op->getIn(0), worklist);
b = (outc == 0) ? 0 : ~((uintb)0);
pushConsumed(b,op->getIn(2), worklist);
pushConsumed(b,op->getIn(3), worklist);
break;
case CPUI_EXTRACT:
a = 1;
a <<= (int4)op->getIn(2)->getOffset();
a -= 1; // Extract mask
a &= outc; // Consumed bits of mask
a <<= (int4)op->getIn(1)->getOffset();
pushConsumed(a,op->getIn(0),worklist);
b = (outc == 0) ? 0 : ~((uintb)0);
pushConsumed(b,op->getIn(1), worklist);
pushConsumed(b,op->getIn(2), worklist);
break;
case CPUI_POPCOUNT:
a = 16 * op->getIn(0)->getSize() - 1; // Mask for possible bits that could be set
a &= outc; // Of the bits that could be set, which are consumed
b = (a == 0) ? 0 : ~((uintb)0); // if any consumed, treat all input bits as consumed
pushConsumed(b,op->getIn(0), worklist);
break;
default:
a = (outc==0) ? 0 : ~((uintb)0); // all or nothing
for(int4 i=0;i<op->numInput();++i)

View file

@ -55,7 +55,7 @@ uint4 DynamicHash::transtable[] = {
0, // CAST is skipped
CPUI_INT_ADD, CPUI_INT_ADD, // PTRADD and PTRSUB hash same as INT_ADD
CPUI_SEGMENTOP, CPUI_CPOOLREF, CPUI_NEW
CPUI_SEGMENTOP, CPUI_CPOOLREF, CPUI_NEW, CPUI_INSERT, CPUI_EXTRACT, CPUI_POPCOUNT
};

View file

@ -493,6 +493,11 @@ uintb PcodeOp::getNZMaskLocal(bool cliploop) const
val = (getIn(1)->getNZMask()-1); // Result is less than modulus
resmask = coveringmask(val);
break;
case CPUI_POPCOUNT:
sz1 = popcount(getIn(0)->getNZMask());
resmask = coveringmask((uintb)sz1);
resmask &= fullmask;
break;
case CPUI_SUBPIECE:
resmask = getIn(0)->getNZMask();
resmask >>= 8*getIn(1)->getOffset();

View file

@ -99,6 +99,9 @@ void OpBehavior::registerInstructions(vector<OpBehavior *> &inst,const Translate
inst[CPUI_SEGMENTOP] = new OpBehavior(CPUI_SEGMENTOP,false,true);
inst[CPUI_CPOOLREF] = new OpBehavior(CPUI_CPOOLREF,false,true);
inst[CPUI_NEW] = new OpBehavior(CPUI_NEW,false,true);
inst[CPUI_INSERT] = new OpBehavior(CPUI_INSERT,false,true);
inst[CPUI_EXTRACT] = new OpBehavior(CPUI_EXTRACT,false,true);
inst[CPUI_POPCOUNT] = new OpBehaviorPopcount();
}
/// \param sizeout is the size of the output in bytes
@ -725,3 +728,9 @@ uintb OpBehaviorSubpiece::evaluateBinary(int4 sizeout,int4 sizein,uintb in1,uint
return res;
}
uintb OpBehaviorPopcount::evaluateUnary(int4 sizeout,int4 sizein,uintb in1) const
{
return (uintb)popcount(in1);
}

View file

@ -502,5 +502,11 @@ public:
virtual uintb evaluateBinary(int4 sizeout,int4 sizein,uintb in1,uintb in2) const;
};
/// CPUI_POPCOUNT behavior
class OpBehaviorPopcount : public OpBehavior {
public:
OpBehaviorPopcount(void) : OpBehavior(CPUI_POPCOUNT,true) {} ///< Constructor
virtual uintb evaluateUnary(int4 sizeout,int4 sizein,uintb in1) const;
};
#endif

View file

@ -41,14 +41,15 @@ static const char *opcode_name[] = {
"FLOAT_ABS", "FLOAT_SQRT", "INT2FLOAT", "FLOAT2FLOAT",
"TRUNC", "CEIL", "FLOOR", "ROUND",
"BUILD", "DELAY_SLOT", "PIECE", "SUBPIECE", "CAST",
"LABEL", "CROSSBUILD", "SEGMENTOP", "CPOOLREF", "NEW"
"LABEL", "CROSSBUILD", "SEGMENTOP", "CPOOLREF", "NEW",
"INSERT", "EXTRACT", "POPCOUNT"
};
static const int4 opcode_indices[] = {
0, 39, 37, 40, 38, 4, 6, 60, 7, 8, 9, 64, 5, 57, 1, 68, 66,
61, 55, 52, 47, 48, 41, 43, 44, 49, 46, 51, 42, 53, 50, 58,
61, 71, 55, 52, 47, 48, 41, 43, 44, 49, 46, 51, 42, 53, 50, 58, 70,
54, 24, 19, 27, 21, 33, 11, 29, 15, 16, 32, 25, 12, 28, 35, 30,
23, 22, 34, 18, 13, 14, 36, 31, 20, 26, 17, 65, 2, 69, 62, 10, 59,
23, 22, 34, 18, 13, 14, 36, 31, 20, 26, 17, 65, 2, 69, 62, 72, 10, 59,
67, 3, 63, 56, 45
};

View file

@ -120,8 +120,11 @@ enum OpCode {
CPUI_SEGMENTOP = 67, ///< Look-up a \e segmented address
CPUI_CPOOLREF = 68, ///< Recover a value from the \e constant \e pool
CPUI_NEW = 69, ///< Allocate a new object (new)
CPUI_INSERT = 70, ///< Insert a bit-range
CPUI_EXTRACT = 71, ///< Extract a bit-range
CPUI_POPCOUNT = 72, ///< Count the 1-bits
CPUI_MAX = 70 ///< Value indicating the end of the op-code values
CPUI_MAX = 73 ///< Value indicating the end of the op-code values
};
extern const char *get_opname(OpCode opc); ///< Convert an OpCode to the name as a string

View file

@ -970,6 +970,18 @@ void PrintC::opNewOp(const PcodeOp *op)
pushVnImplied(vn0,op,mods);
}
void PrintC::opInsertOp(const PcodeOp *op)
{
opFunc(op); // If no other way to print it, print as functional operator
}
void PrintC::opExtractOp(const PcodeOp *op)
{
opFunc(op); // If no other way to print it, print as functional operator
}
/// \brief Push a constant with an integer data-type to the RPN stack
///
/// Various checks are made to see if the integer should be printed as an \e equate

View file

@ -290,6 +290,9 @@ public:
virtual void opSegmentOp(const PcodeOp *op);
virtual void opCpoolRefOp(const PcodeOp *op);
virtual void opNewOp(const PcodeOp *op);
virtual void opInsertOp(const PcodeOp *op);
virtual void opExtractOp(const PcodeOp *op);
virtual void opPopcountOp(const PcodeOp *op) { opFunc(op); }
};
#endif

View file

@ -538,6 +538,9 @@ public:
virtual void opSegmentOp(const PcodeOp *op)=0; ///< Emit a SEGMENTOP operator
virtual void opCpoolRefOp(const PcodeOp *op)=0; ///< Emit a CPOOLREF operator
virtual void opNewOp(const PcodeOp *op)=0; ///< Emit a NEW operator
virtual void opInsertOp(const PcodeOp *op)=0; ///< Emit an INSERT operator
virtual void opExtractOp(const PcodeOp *op)=0; ///< Emit an EXTRACT operator
virtual void opPopcountOp(const PcodeOp *op)=0; ///< Emit a POPCOUNT operator
static int4 mostNaturalBase(uintb val); ///< Determine the most natural base for an integer
static void formatBinary(ostream &s,uintb val); ///< Print a number in binary form

View file

@ -734,6 +734,9 @@ void ConsistencyChecker::printOpName(ostream &s,OpTpl *op)
case CPUI_NEW:
s << "New object(newobject)";
break;
case CPUI_POPCOUNT:
s << "Count bits(popcount)";
break;
default:
break;
}

View file

@ -93,7 +93,7 @@
%right '!' '~'
%token OP_ZEXT OP_CARRY OP_BORROW OP_SEXT OP_SCARRY OP_SBORROW OP_NAN OP_ABS
%token OP_SQRT OP_CEIL OP_FLOOR OP_ROUND OP_INT2FLOAT OP_FLOAT2FLOAT
%token OP_TRUNC OP_CPOOLREF OP_NEW
%token OP_TRUNC OP_CPOOLREF OP_NEW OP_POPCOUNT
%token BADINTEGER GOTO_KEY CALL_KEY RETURN_KEY IF_KEY
%token DEFINE_KEY ATTACH_KEY MACRO_KEY SPACE_KEY TYPE_KEY RAM_KEY DEFAULT_KEY
@ -436,9 +436,10 @@ expr: varnode { $$ = new ExprTree($1); }
| OP_TRUNC '(' expr ')' { $$ = slgh->pcode.createOp(CPUI_FLOAT_TRUNC,$3); }
| OP_CEIL '(' expr ')' { $$ = slgh->pcode.createOp(CPUI_FLOAT_CEIL,$3); }
| OP_FLOOR '(' expr ')' { $$ = slgh->pcode.createOp(CPUI_FLOAT_FLOOR,$3); }
| OP_ROUND '(' expr ')' { $$ = slgh->pcode.createOp(CPUI_FLOAT_ROUND,$3); };
| OP_NEW '(' expr ')' { $$ = slgh->pcode.createOp(CPUI_NEW,$3); };
| OP_ROUND '(' expr ')' { $$ = slgh->pcode.createOp(CPUI_FLOAT_ROUND,$3); }
| OP_NEW '(' expr ')' { $$ = slgh->pcode.createOp(CPUI_NEW,$3); }
| OP_NEW '(' expr ',' expr ')' { $$ = slgh->pcode.createOp(CPUI_NEW,$3,$5); }
| OP_POPCOUNT '(' expr ')' { $$ = slgh->pcode.createOp(CPUI_POPCOUNT,$3); }
| specificsymbol '(' integervarnode ')' { $$ = slgh->pcode.createOp(CPUI_SUBPIECE,new ExprTree($1->getVarnode()),new ExprTree($3)); }
| specificsymbol ':' INTEGER { $$ = slgh->pcode.createBitRange($1,0,(uint4)(*$3 * 8)); delete $3; }
| specificsymbol '[' INTEGER ',' INTEGER ']' { $$ = slgh->pcode.createBitRange($1,(uint4)*$3,(uint4)*$5); delete $3, delete $5; }

View file

@ -637,6 +637,7 @@ with { BEGIN(pattern); withsection = 1; slgh->calcContextLayout(); return WITH
<sem>trunc { return OP_TRUNC; }
<sem>cpool { return OP_CPOOLREF; }
<sem>newobject { return OP_NEW; }
<sem>popcount { return OP_POPCOUNT; }
<sem>if { return IF_KEY; }
<sem>goto { return GOTO_KEY; }
<sem>call { return CALL_KEY; }

View file

@ -100,6 +100,9 @@ void TypeOp::registerInstructions(vector<TypeOp *> &inst,TypeFactory *tlst,
inst[CPUI_SEGMENTOP] = new TypeOpSegment(tlst);
inst[CPUI_CPOOLREF] = new TypeOpCpoolref(tlst);
inst[CPUI_NEW] = new TypeOpNew(tlst);
inst[CPUI_INSERT] = new TypeOpInsert(tlst);
inst[CPUI_EXTRACT] = new TypeOpExtract(tlst);
inst[CPUI_POPCOUNT] = new TypeOpPopcount(tlst);
}
/// Change basic data-type info (signed vs unsigned) and operator names ( '>>' vs '>>>' )
@ -1809,3 +1812,40 @@ void TypeOpNew::printRaw(ostream &s,const PcodeOp *op)
}
s << ')';
}
TypeOpInsert::TypeOpInsert(TypeFactory *t)
: TypeOpFunc(t,CPUI_INSERT,"INSERT",TYPE_UNKNOWN,TYPE_INT)
{
opflags = PcodeOp::special;
behave = new OpBehavior(CPUI_INSERT,false,true); // Dummy behavior
}
Datatype *TypeOpInsert::getInputLocal(const PcodeOp *op,int4 slot) const
{
if (slot == 0)
return tlst->getBase(op->getIn(slot)->getSize(),TYPE_UNKNOWN);
return TypeOpFunc::getInputLocal(op, slot);
}
TypeOpExtract::TypeOpExtract(TypeFactory *t)
: TypeOpFunc(t,CPUI_EXTRACT,"EXTRACT",TYPE_INT,TYPE_INT)
{
opflags = PcodeOp::special;
behave = new OpBehavior(CPUI_EXTRACT,false,true); // Dummy behavior
}
Datatype *TypeOpExtract::getInputLocal(const PcodeOp *op,int4 slot) const
{
if (slot == 0)
return tlst->getBase(op->getIn(slot)->getSize(),TYPE_UNKNOWN);
return TypeOpFunc::getInputLocal(op, slot);
}
TypeOpPopcount::TypeOpPopcount(TypeFactory *t)
: TypeOpFunc(t,CPUI_POPCOUNT,"POPCOUNT",TYPE_INT,TYPE_UNKNOWN)
{
opflags = PcodeOp::unary;
behave = new OpBehaviorPopcount();
}

View file

@ -777,4 +777,28 @@ public:
virtual void push(PrintLanguage *lng,const PcodeOp *op) const { lng->opNewOp(op); }
virtual void printRaw(ostream &s,const PcodeOp *op);
};
/// \brief Information about the INSERT op-code
class TypeOpInsert : public TypeOpFunc {
public:
TypeOpInsert(TypeFactory *t); ///< Constructor
virtual Datatype *getInputLocal(const PcodeOp *op,int4 slot) const;
virtual void push(PrintLanguage *lng,const PcodeOp *op) const { lng->opInsertOp(op); }
};
/// \brief Information about the EXTRACT op-code
class TypeOpExtract : public TypeOpFunc {
public:
TypeOpExtract(TypeFactory *t); ///< Constructor
virtual Datatype *getInputLocal(const PcodeOp *op,int4 slot) const;
virtual void push(PrintLanguage *lng,const PcodeOp *op) const { lng->opExtractOp(op); }
};
/// \brief Information about the POPCOUNT op-code
class TypeOpPopcount : public TypeOpFunc {
public:
TypeOpPopcount(TypeFactory *t); ///< Constructor
virtual void push(PrintLanguage *lng,const PcodeOp *op) const { lng->opPopcountOp(op); }
};
#endif