mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 10:49:34 +02:00
GP-1518 Decompiler support for unions
This commit is contained in:
parent
53e2c4dc4f
commit
3fdbbbb231
65 changed files with 5119 additions and 1068 deletions
|
@ -360,7 +360,7 @@ void PrintC::opFunc(const PcodeOp *op)
|
|||
// implied vn's pushed on in reverse order for efficiency
|
||||
// see PrintLanguage::pushVnImplied
|
||||
for(int4 i=op->numInput()-1;i>=0;--i)
|
||||
pushVnImplied(op->getIn(i),op,mods);
|
||||
pushVn(op->getIn(i),op,mods);
|
||||
}
|
||||
else // Push empty token for void
|
||||
pushAtom(Atom("",blanktoken,EmitXml::no_color));
|
||||
|
@ -375,9 +375,9 @@ void PrintC::opTypeCast(const PcodeOp *op)
|
|||
{
|
||||
if (!option_nocasts) {
|
||||
pushOp(&typecast,op);
|
||||
pushType(op->getOut()->getHigh()->getType());
|
||||
pushType(op->getOut()->getHighTypeDefFacing());
|
||||
}
|
||||
pushVnImplied(op->getIn(0),op,mods);
|
||||
pushVn(op->getIn(0),op,mods);
|
||||
}
|
||||
|
||||
/// The syntax represents the given op using a function with one input,
|
||||
|
@ -392,13 +392,13 @@ void PrintC::opHiddenFunc(const PcodeOp *op)
|
|||
|
||||
{
|
||||
pushOp(&hidden,op);
|
||||
pushVnImplied(op->getIn(0),op,mods);
|
||||
pushVn(op->getIn(0),op,mods);
|
||||
}
|
||||
|
||||
void PrintC::opCopy(const PcodeOp *op)
|
||||
|
||||
{
|
||||
pushVnImplied(op->getIn(0),op,mods);
|
||||
pushVn(op->getIn(0),op,mods);
|
||||
}
|
||||
|
||||
void PrintC::opLoad(const PcodeOp *op)
|
||||
|
@ -411,7 +411,7 @@ void PrintC::opLoad(const PcodeOp *op)
|
|||
else {
|
||||
pushOp(&dereference,op);
|
||||
}
|
||||
pushVnImplied(op->getIn(1),op,m);
|
||||
pushVn(op->getIn(1),op,m);
|
||||
}
|
||||
|
||||
void PrintC::opStore(const PcodeOp *op)
|
||||
|
@ -430,8 +430,8 @@ void PrintC::opStore(const PcodeOp *op)
|
|||
}
|
||||
// implied vn's pushed on in reverse order for efficiency
|
||||
// see PrintLanguage::pushVnImplied
|
||||
pushVnImplied(op->getIn(2),op,mods);
|
||||
pushVnImplied(op->getIn(1),op,m);
|
||||
pushVn(op->getIn(2),op,mods);
|
||||
pushVn(op->getIn(1),op,m);
|
||||
}
|
||||
|
||||
void PrintC::opBranch(const PcodeOp *op)
|
||||
|
@ -441,7 +441,7 @@ void PrintC::opBranch(const PcodeOp *op)
|
|||
// Assume the BRANCH is a statement
|
||||
emit->tagOp("goto",EmitXml::keyword_color,op);
|
||||
emit->spaces(1);
|
||||
pushVnImplied(op->getIn(0),op,mods);
|
||||
pushVn(op->getIn(0),op,mods);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -480,7 +480,7 @@ void PrintC::opCbranch(const PcodeOp *op)
|
|||
}
|
||||
if (booleanflip)
|
||||
pushOp(&boolean_not,op);
|
||||
pushVnImplied(op->getIn(1),op,m);
|
||||
pushVn(op->getIn(1),op,m);
|
||||
// Make sure stack is clear before emitting more
|
||||
recurse();
|
||||
if (yesparen)
|
||||
|
@ -492,7 +492,7 @@ void PrintC::opCbranch(const PcodeOp *op)
|
|||
emit->spaces(1);
|
||||
emit->print("goto",EmitXml::keyword_color);
|
||||
emit->spaces(1);
|
||||
pushVnImplied(op->getIn(0),op,mods);
|
||||
pushVn(op->getIn(0),op,mods);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -502,7 +502,7 @@ void PrintC::opBranchind(const PcodeOp *op)
|
|||
// FIXME: This routine shouldn't emit directly
|
||||
emit->tagOp("switch",EmitXml::keyword_color,op); // Print header for switch
|
||||
int4 id = emit->openParen('(');
|
||||
pushVnImplied(op->getIn(0),op,mods);
|
||||
pushVn(op->getIn(0),op,mods);
|
||||
recurse();
|
||||
emit->closeParen(')',id);
|
||||
}
|
||||
|
@ -544,7 +544,7 @@ void PrintC::opCall(const PcodeOp *op)
|
|||
// see PrintLanguage::pushVnImplied
|
||||
for(int4 i=op->numInput()-1;i>=1;--i) {
|
||||
if (i == skip) continue;
|
||||
pushVnImplied(op->getIn(i),op,mods);
|
||||
pushVn(op->getIn(i),op,mods);
|
||||
}
|
||||
}
|
||||
else // Push empty token for void
|
||||
|
@ -564,25 +564,25 @@ void PrintC::opCallind(const PcodeOp *op)
|
|||
int4 count = op->numInput() - 1;
|
||||
count -= (skip < 0) ? 0 : 1;
|
||||
if (count > 1) { // Multiple parameters
|
||||
pushVnImplied(op->getIn(0),op,mods);
|
||||
pushVn(op->getIn(0),op,mods);
|
||||
for(int4 i=0;i<count-1;++i)
|
||||
pushOp(&comma,op);
|
||||
// implied vn's pushed on in reverse order for efficiency
|
||||
// see PrintLanguage::pushVnImplied
|
||||
for(int4 i=op->numInput()-1;i>=1;--i) {
|
||||
if (i == skip) continue;
|
||||
pushVnImplied(op->getIn(i),op,mods);
|
||||
pushVn(op->getIn(i),op,mods);
|
||||
}
|
||||
}
|
||||
else if (count == 1) { // One parameter
|
||||
if (skip == 1)
|
||||
pushVnImplied(op->getIn(2),op,mods);
|
||||
pushVn(op->getIn(2),op,mods);
|
||||
else
|
||||
pushVnImplied(op->getIn(1),op,mods);
|
||||
pushVnImplied(op->getIn(0),op,mods);
|
||||
pushVn(op->getIn(1),op,mods);
|
||||
pushVn(op->getIn(0),op,mods);
|
||||
}
|
||||
else { // A void function
|
||||
pushVnImplied(op->getIn(0),op,mods);
|
||||
pushVn(op->getIn(0),op,mods);
|
||||
pushAtom(Atom("",blanktoken,EmitXml::no_color));
|
||||
}
|
||||
}
|
||||
|
@ -599,7 +599,7 @@ void PrintC::opCallother(const PcodeOp *op)
|
|||
// implied vn's pushed on in reverse order for efficiency
|
||||
// see PrintLanguage::pushVnImplied
|
||||
for(int4 i=op->numInput()-1;i>=1;--i)
|
||||
pushVnImplied(op->getIn(i),op,mods);
|
||||
pushVn(op->getIn(i),op,mods);
|
||||
}
|
||||
else // Push empty token for void
|
||||
pushAtom(Atom("",blanktoken,EmitXml::no_color));
|
||||
|
@ -614,7 +614,7 @@ void PrintC::opConstructor(const PcodeOp *op,bool withNew)
|
|||
const Varnode *outvn = newop->getOut();
|
||||
pushOp(&new_op,newop);
|
||||
pushAtom(Atom("new",optoken,EmitXml::keyword_color,newop,outvn));
|
||||
dt = outvn->getType();
|
||||
dt = outvn->getTypeDefFacing();
|
||||
}
|
||||
else {
|
||||
const Varnode *thisvn = op->getIn(1);
|
||||
|
@ -632,10 +632,10 @@ void PrintC::opConstructor(const PcodeOp *op,bool withNew)
|
|||
for(int4 i=2;i<op->numInput()-1;++i)
|
||||
pushOp(&comma,op);
|
||||
for(int4 i=op->numInput()-1;i>=2;--i)
|
||||
pushVnImplied(op->getIn(i),op,mods);
|
||||
pushVn(op->getIn(i),op,mods);
|
||||
}
|
||||
else if (op->numInput()==3) { // One parameter
|
||||
pushVnImplied(op->getIn(2),op,mods);
|
||||
pushVn(op->getIn(2),op,mods);
|
||||
}
|
||||
else { // A void function
|
||||
pushAtom(Atom("",blanktoken,EmitXml::no_color));
|
||||
|
@ -652,7 +652,7 @@ void PrintC::opReturn(const PcodeOp *op)
|
|||
emit->tagOp("return",EmitXml::keyword_color,op);
|
||||
if (op->numInput()>1) {
|
||||
emit->spaces(1);
|
||||
pushVnImplied(op->getIn(1),op,mods);
|
||||
pushVn(op->getIn(1),op,mods);
|
||||
}
|
||||
return;
|
||||
case PcodeOp::noreturn: // Previous instruction does not exit
|
||||
|
@ -677,7 +677,7 @@ void PrintC::opReturn(const PcodeOp *op)
|
|||
void PrintC::opIntZext(const PcodeOp *op,const PcodeOp *readOp)
|
||||
|
||||
{
|
||||
if (castStrategy->isZextCast(op->getOut()->getHigh()->getType(),op->getIn(0)->getHigh()->getType())) {
|
||||
if (castStrategy->isZextCast(op->getOut()->getHighTypeDefFacing(),op->getIn(0)->getHighTypeReadFacing(op))) {
|
||||
if (option_hide_exts && castStrategy->isExtensionCastImplied(op,readOp))
|
||||
opHiddenFunc(op);
|
||||
else
|
||||
|
@ -690,7 +690,7 @@ void PrintC::opIntZext(const PcodeOp *op,const PcodeOp *readOp)
|
|||
void PrintC::opIntSext(const PcodeOp *op,const PcodeOp *readOp)
|
||||
|
||||
{
|
||||
if (castStrategy->isSextCast(op->getOut()->getHigh()->getType(),op->getIn(0)->getHigh()->getType())) {
|
||||
if (castStrategy->isSextCast(op->getOut()->getHighTypeDefFacing(),op->getIn(0)->getHighTypeReadFacing(op))) {
|
||||
if (option_hide_exts && castStrategy->isExtensionCastImplied(op,readOp))
|
||||
opHiddenFunc(op);
|
||||
else
|
||||
|
@ -707,22 +707,33 @@ void PrintC::opBoolNegate(const PcodeOp *op)
|
|||
{
|
||||
if (isSet(negatetoken)) { // Check if we are negated by a previous BOOL_NEGATE
|
||||
unsetMod(negatetoken); // If so, mark that negatetoken is consumed
|
||||
pushVnImplied(op->getIn(0),op,mods); // Don't print ourselves, but print our input unmodified
|
||||
pushVn(op->getIn(0),op,mods); // Don't print ourselves, but print our input unmodified
|
||||
}
|
||||
else if (checkPrintNegation(op->getIn(0))) { // If the next operator can be flipped
|
||||
pushVnImplied(op->getIn(0),op,mods|negatetoken); // Don't print ourselves, but print a modified input
|
||||
pushVn(op->getIn(0),op,mods|negatetoken); // Don't print ourselves, but print a modified input
|
||||
}
|
||||
else {
|
||||
pushOp(&boolean_not,op); // Otherwise print ourselves
|
||||
pushVnImplied(op->getIn(0),op,mods); // And print our input
|
||||
pushVn(op->getIn(0),op,mods); // And print our input
|
||||
}
|
||||
}
|
||||
|
||||
void PrintC::opSubpiece(const PcodeOp *op)
|
||||
|
||||
{
|
||||
if (castStrategy->isSubpieceCast(op->getOut()->getHigh()->getType(),
|
||||
op->getIn(0)->getHigh()->getType(),
|
||||
if (op->doesSpecialPrinting()) { // Special printing means it is a field extraction
|
||||
int4 offset;
|
||||
Datatype *ct;
|
||||
const TypeField *field = TypeOpSubpiece::testExtraction(true, op, ct, offset);
|
||||
if (field != (const TypeField *)0 && offset == 0) {
|
||||
pushOp(&object_member,op);
|
||||
pushVn(op->getIn(0), op, mods);
|
||||
pushAtom(Atom(field->name,fieldtoken,EmitXml::no_color,ct,field->ident,op));
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (castStrategy->isSubpieceCast(op->getOut()->getHighTypeDefFacing(),
|
||||
op->getIn(0)->getHighTypeReadFacing(op),
|
||||
(uint4)op->getIn(1)->getOffset()))
|
||||
opTypeCast(op);
|
||||
else
|
||||
|
@ -735,7 +746,7 @@ void PrintC::opPtradd(const PcodeOp *op)
|
|||
bool printval = isSet(print_load_value|print_store_value);
|
||||
uint4 m = mods & ~(print_load_value|print_store_value);
|
||||
if (!printval) {
|
||||
TypePointer *tp = (TypePointer *)op->getIn(0)->getHigh()->getType();
|
||||
TypePointer *tp = (TypePointer *)op->getIn(0)->getHighTypeReadFacing(op);
|
||||
if (tp->getMetatype() == TYPE_PTR) {
|
||||
if (tp->getPtrTo()->getMetatype() == TYPE_ARRAY)
|
||||
printval = true;
|
||||
|
@ -747,8 +758,8 @@ void PrintC::opPtradd(const PcodeOp *op)
|
|||
pushOp(&binary_plus,op);
|
||||
// implied vn's pushed on in reverse order for efficiency
|
||||
// see PrintLanguage::pushVnImplied
|
||||
pushVnImplied(op->getIn(1),op,m);
|
||||
pushVnImplied(op->getIn(0),op,m);
|
||||
pushVn(op->getIn(1),op,m);
|
||||
pushVn(op->getIn(0),op,m);
|
||||
}
|
||||
|
||||
static bool isValueFlexible(const Varnode *vn)
|
||||
|
@ -791,7 +802,7 @@ void PrintC::opPtrsub(const PcodeOp *op)
|
|||
|
||||
in0 = op->getIn(0);
|
||||
in1const = op->getIn(1)->getOffset();
|
||||
ptype = (TypePointer *)in0->getHigh()->getType();
|
||||
ptype = (TypePointer *)in0->getHighTypeReadFacing(op);
|
||||
if (ptype->getMetatype() != TYPE_PTR) {
|
||||
clear();
|
||||
throw LowlevelError("PTRSUB off of non-pointer type");
|
||||
|
@ -808,7 +819,7 @@ void PrintC::opPtrsub(const PcodeOp *op)
|
|||
valueon = (mods & (print_load_value|print_store_value)) != 0;
|
||||
flex = isValueFlexible(in0);
|
||||
|
||||
if (ct->getMetatype() == TYPE_STRUCT) {
|
||||
if (ct->getMetatype() == TYPE_STRUCT || ct->getMetatype() == TYPE_UNION) {
|
||||
uintb suboff = in1const; // How far into container
|
||||
if (ptrel != (TypePointerRel *)0) {
|
||||
suboff += ptrel->getPointerOffset();
|
||||
|
@ -817,34 +828,48 @@ void PrintC::opPtrsub(const PcodeOp *op)
|
|||
// Special case where we do not print a field
|
||||
pushTypePointerRel(op);
|
||||
if (flex)
|
||||
pushVnImplied(in0,op,m | print_load_value);
|
||||
pushVn(in0,op,m | print_load_value);
|
||||
else
|
||||
pushVnImplied(in0,op,m);
|
||||
pushVn(in0,op,m);
|
||||
return;
|
||||
}
|
||||
}
|
||||
suboff = AddrSpace::addressToByte(suboff,ptype->getWordSize());
|
||||
string fieldname;
|
||||
Datatype *fieldtype;
|
||||
int4 fieldoffset;
|
||||
int4 fieldid;
|
||||
int4 newoff;
|
||||
const TypeField *fld = ((TypeStruct *)ct)->getField((int4)suboff,0,&newoff);
|
||||
if (fld == (const TypeField *)0) {
|
||||
if (ct->getSize() <= suboff) {
|
||||
clear();
|
||||
throw LowlevelError("PTRSUB out of bounds into struct");
|
||||
}
|
||||
// Try to match the Ghidra's default field name from DataTypeComponent.getDefaultFieldName
|
||||
ostringstream s;
|
||||
s << "field_0x" << hex << suboff;
|
||||
fieldname = s.str();
|
||||
fieldtype = (Datatype *)0;
|
||||
fieldoffset = suboff;
|
||||
}
|
||||
else {
|
||||
if (ct->getMetatype() == TYPE_UNION) {
|
||||
if (suboff != 0)
|
||||
throw LowlevelError("PTRSUB accesses union with non-zero offset");
|
||||
const Funcdata *fd = op->getParent()->getFuncdata();
|
||||
const ResolvedUnion *resUnion = fd->getUnionField(ptype, op, -1);
|
||||
if (resUnion == (const ResolvedUnion *)0 || resUnion->getFieldNum() < 0)
|
||||
throw LowlevelError("PTRSUB for union that does not resolve to a field");
|
||||
const TypeField *fld = ((TypeUnion *)ct)->getField(resUnion->getFieldNum());
|
||||
fieldid = fld->ident;
|
||||
fieldname = fld->name;
|
||||
fieldtype = fld->type;
|
||||
fieldoffset = fld->offset;
|
||||
}
|
||||
else { // TYPE_STRUCT
|
||||
const TypeField *fld = ((TypeStruct*)ct)->resolveTruncation((int4)suboff,0,&newoff);
|
||||
if (fld == (const TypeField*)0) {
|
||||
if (ct->getSize() <= suboff) {
|
||||
clear();
|
||||
throw LowlevelError("PTRSUB out of bounds into struct");
|
||||
}
|
||||
// Try to match the Ghidra's default field name from DataTypeComponent.getDefaultFieldName
|
||||
ostringstream s;
|
||||
s << "field_0x" << hex << suboff;
|
||||
fieldname = s.str();
|
||||
fieldtype = (Datatype*)0;
|
||||
fieldid = suboff;
|
||||
}
|
||||
else {
|
||||
fieldname = fld->name;
|
||||
fieldtype = fld->type;
|
||||
fieldid = fld->ident;
|
||||
}
|
||||
}
|
||||
arrayvalue = false;
|
||||
// The '&' is dropped if the output type is an array
|
||||
|
@ -859,16 +884,16 @@ void PrintC::opPtrsub(const PcodeOp *op)
|
|||
pushOp(&object_member,op);
|
||||
if (ptrel != (TypePointerRel *)0)
|
||||
pushTypePointerRel(op);
|
||||
pushVnImplied(in0,op,m | print_load_value);
|
||||
pushAtom(Atom(fieldname,fieldtoken,EmitXml::no_color,ct,fieldoffset));
|
||||
pushVn(in0,op,m | print_load_value);
|
||||
pushAtom(Atom(fieldname,fieldtoken,EmitXml::no_color,ct,fieldid,op));
|
||||
}
|
||||
else { // EMIT &( )->name
|
||||
pushOp(&addressof,op);
|
||||
pushOp(&pointer_member,op);
|
||||
if (ptrel != (TypePointerRel *)0)
|
||||
pushTypePointerRel(op);
|
||||
pushVnImplied(in0,op,m);
|
||||
pushAtom(Atom(fieldname,fieldtoken,EmitXml::no_color,ct,fieldoffset));
|
||||
pushVn(in0,op,m);
|
||||
pushAtom(Atom(fieldname,fieldtoken,EmitXml::no_color,ct,fieldid,op));
|
||||
}
|
||||
}
|
||||
else { // Not printing an ampersand
|
||||
|
@ -878,15 +903,15 @@ void PrintC::opPtrsub(const PcodeOp *op)
|
|||
pushOp(&object_member,op);
|
||||
if (ptrel != (TypePointerRel *)0)
|
||||
pushTypePointerRel(op);
|
||||
pushVnImplied(in0,op,m | print_load_value);
|
||||
pushAtom(Atom(fieldname,fieldtoken,EmitXml::no_color,ct,fieldoffset));
|
||||
pushVn(in0,op,m | print_load_value);
|
||||
pushAtom(Atom(fieldname,fieldtoken,EmitXml::no_color,ct,fieldid,op));
|
||||
}
|
||||
else { // EMIT ( )->name
|
||||
pushOp(&pointer_member,op);
|
||||
if (ptrel != (TypePointerRel *)0)
|
||||
pushTypePointerRel(op);
|
||||
pushVnImplied(in0,op,m);
|
||||
pushAtom(Atom(fieldname,fieldtoken,EmitXml::no_color,ct,fieldoffset));
|
||||
pushVn(in0,op,m);
|
||||
pushAtom(Atom(fieldname,fieldtoken,EmitXml::no_color,ct,fieldid,op));
|
||||
}
|
||||
if (arrayvalue)
|
||||
push_integer(0,4,false,(Varnode *)0,op);
|
||||
|
@ -927,7 +952,7 @@ void PrintC::opPtrsub(const PcodeOp *op)
|
|||
// we can't use a cast in its description, so turn off
|
||||
// casting when printing the partial symbol
|
||||
// Datatype *exttype = ((mods & print_store_value)!=0) ? (Datatype *)0 : ct;
|
||||
pushPartialSymbol(symbol,off,0,(Varnode *)0,op,(Datatype *)0);
|
||||
pushPartialSymbol(symbol,off,0,(Varnode *)0,op,-1);
|
||||
}
|
||||
}
|
||||
if (arrayvalue)
|
||||
|
@ -947,13 +972,13 @@ void PrintC::opPtrsub(const PcodeOp *op)
|
|||
// becomes struct->arrayfield[i]
|
||||
if (ptrel != (TypePointerRel *)0)
|
||||
pushTypePointerRel(op);
|
||||
pushVnImplied(in0,op,m);
|
||||
pushVn(in0,op,m);
|
||||
}
|
||||
else { // EMIT *( )
|
||||
pushOp(&dereference,op);
|
||||
if (ptrel != (TypePointerRel *)0)
|
||||
pushTypePointerRel(op);
|
||||
pushVnImplied(in0,op,m);
|
||||
pushVn(in0,op,m);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -961,7 +986,7 @@ void PrintC::opPtrsub(const PcodeOp *op)
|
|||
pushOp(&subscript,op);
|
||||
if (ptrel != (TypePointerRel *)0)
|
||||
pushTypePointerRel(op);
|
||||
pushVnImplied(in0,op,m);
|
||||
pushVn(in0,op,m);
|
||||
push_integer(0,4,false,(Varnode *)0,op);
|
||||
}
|
||||
else { // EMIT (* )[0]
|
||||
|
@ -969,7 +994,7 @@ void PrintC::opPtrsub(const PcodeOp *op)
|
|||
pushOp(&dereference,op);
|
||||
if (ptrel != (TypePointerRel *)0)
|
||||
pushTypePointerRel(op);
|
||||
pushVnImplied(in0,op,m);
|
||||
pushVn(in0,op,m);
|
||||
push_integer(0,4,false,(Varnode *)0,op);
|
||||
}
|
||||
}
|
||||
|
@ -988,7 +1013,7 @@ void PrintC::opPtrsub(const PcodeOp *op)
|
|||
void PrintC::opSegmentOp(const PcodeOp *op)
|
||||
|
||||
{
|
||||
pushVnImplied(op->getIn(2),op,mods);
|
||||
pushVn(op->getIn(2),op,mods);
|
||||
}
|
||||
|
||||
void PrintC::opCpoolRefOp(const PcodeOp *op)
|
||||
|
@ -1033,7 +1058,7 @@ void PrintC::opCpoolRefOp(const PcodeOp *op)
|
|||
pushOp(&function_call,op);
|
||||
pushAtom(Atom(rec->getToken(),functoken,EmitXml::funcname_color,op,outvn));
|
||||
pushOp(&comma,(const PcodeOp *)0);
|
||||
pushVnImplied(vn0,op,mods);
|
||||
pushVn(vn0,op,mods);
|
||||
pushAtom(Atom(dt->getName(),syntax,EmitXml::type_color,op,outvn));
|
||||
break;
|
||||
}
|
||||
|
@ -1056,7 +1081,7 @@ void PrintC::opCpoolRefOp(const PcodeOp *op)
|
|||
}
|
||||
else {
|
||||
pushOp(&pointer_member, op);
|
||||
pushVnImplied(vn0, op, mods);
|
||||
pushVn(vn0, op, mods);
|
||||
pushAtom(Atom(rec->getToken(), syntax, color, op, outvn));
|
||||
}
|
||||
break;
|
||||
|
@ -1081,7 +1106,7 @@ void PrintC::opNewOp(const PcodeOp *op)
|
|||
nm = "<unused>";
|
||||
}
|
||||
else {
|
||||
Datatype *dt = outvn->getType();
|
||||
Datatype *dt = outvn->getTypeDefFacing();
|
||||
while (dt->getMetatype() == TYPE_PTR) {
|
||||
dt = ((TypePointer *)dt)->getPtrTo();
|
||||
}
|
||||
|
@ -1089,14 +1114,14 @@ void PrintC::opNewOp(const PcodeOp *op)
|
|||
}
|
||||
pushOp(&subscript,op);
|
||||
pushAtom(Atom(nm,optoken,EmitXml::type_color,op));
|
||||
pushVnImplied(vn1,op,mods);
|
||||
pushVn(vn1,op,mods);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// This printing is used only if the 'new' operator doesn't feed directly into a constructor
|
||||
pushOp(&function_call,op);
|
||||
pushAtom(Atom("new",optoken,EmitXml::keyword_color,op,outvn));
|
||||
pushVnImplied(vn0,op,mods);
|
||||
pushVn(vn0,op,mods);
|
||||
}
|
||||
|
||||
void PrintC::opInsertOp(const PcodeOp *op)
|
||||
|
@ -1133,7 +1158,7 @@ void PrintC::push_integer(uintb val,int4 sz,bool sign,
|
|||
if ((vn != (const Varnode *)0)&&(!vn->isAnnotation())) {
|
||||
Symbol *sym = vn->getHigh()->getSymbol();
|
||||
if (sym != (Symbol *)0) {
|
||||
if (sym->isNameLocked() && (sym->getCategory() == 1)) {
|
||||
if (sym->isNameLocked() && (sym->getCategory() == Symbol::equate)) {
|
||||
if (pushEquate(val,sz,(EquateSymbol *)sym,vn,op))
|
||||
return;
|
||||
}
|
||||
|
@ -1448,7 +1473,7 @@ void PrintC::pushCharConstant(uintb val,const Datatype *ct,const Varnode *vn,con
|
|||
if ((vn != (const Varnode *)0)&&(!vn->isAnnotation())) {
|
||||
Symbol *sym = vn->getHigh()->getSymbol();
|
||||
if (sym != (Symbol *)0) {
|
||||
if (sym->isNameLocked() && (sym->getCategory() == 1)) {
|
||||
if (sym->isNameLocked() && (sym->getCategory() == Symbol::equate)) {
|
||||
if (pushEquate(val,vn->getSize(),(EquateSymbol *)sym,vn,op))
|
||||
return;
|
||||
}
|
||||
|
@ -1627,6 +1652,7 @@ void PrintC::pushConstant(uintb val,const Datatype *ct,
|
|||
case TYPE_CODE:
|
||||
case TYPE_ARRAY:
|
||||
case TYPE_STRUCT:
|
||||
case TYPE_UNION:
|
||||
case TYPE_PARTIALSTRUCT:
|
||||
break;
|
||||
}
|
||||
|
@ -1723,7 +1749,7 @@ void PrintC::pushAnnotation(const Varnode *vn,const PcodeOp *op)
|
|||
pushSymbol(entry->getSymbol(),vn,op);
|
||||
else {
|
||||
int4 symboloff = vn->getOffset() - entry->getFirst();
|
||||
pushPartialSymbol(entry->getSymbol(),symboloff,size,vn,op,(Datatype *)0);
|
||||
pushPartialSymbol(entry->getSymbol(),symboloff,size,vn,op,-1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -1743,7 +1769,7 @@ void PrintC::pushSymbol(const Symbol *sym,const Varnode *vn,const PcodeOp *op)
|
|||
EmitXml::syntax_highlight tokenColor;
|
||||
if (sym->getScope()->isGlobal())
|
||||
tokenColor = EmitXml::global_color;
|
||||
else if (sym->getCategory() == 0)
|
||||
else if (sym->getCategory() == Symbol::function_parameter)
|
||||
tokenColor = EmitXml::param_color;
|
||||
else
|
||||
tokenColor = EmitXml::var_color;
|
||||
|
@ -1777,7 +1803,7 @@ void PrintC::pushUnnamedLocation(const Address &addr,
|
|||
|
||||
void PrintC::pushPartialSymbol(const Symbol *sym,int4 off,int4 sz,
|
||||
const Varnode *vn,const PcodeOp *op,
|
||||
Datatype *outtype)
|
||||
int4 inslot)
|
||||
{
|
||||
// We need to print "bottom up" in order to get parentheses right
|
||||
// I.e. we want to print globalstruct.arrayfield[0], rather than
|
||||
|
@ -1788,12 +1814,19 @@ void PrintC::pushPartialSymbol(const Symbol *sym,int4 off,int4 sz,
|
|||
Datatype *ct = sym->getType();
|
||||
|
||||
while(ct != (Datatype *)0) {
|
||||
if (((sz==0)||(sz==ct->getSize()))&&(off==0))
|
||||
break; // Found the full partial
|
||||
if (off == 0) {
|
||||
if (sz == 0 || (sz == ct->getSize() && (!ct->needsResolution() || ct->getMetatype()==TYPE_PTR)))
|
||||
break;
|
||||
}
|
||||
bool succeeded = false;
|
||||
if (ct->getMetatype()==TYPE_STRUCT) {
|
||||
if (ct->needsResolution() && ct->getSize() == sz) {
|
||||
Datatype *outtype = ct->findResolve(op, inslot);
|
||||
if (outtype == ct)
|
||||
break; // Turns out we don't resolve to the field
|
||||
}
|
||||
const TypeField *field;
|
||||
field = ((TypeStruct *)ct)->getField(off,sz,&off);
|
||||
field = ((TypeStruct *)ct)->resolveTruncation(off,sz,&off);
|
||||
if (field != (const TypeField *)0) {
|
||||
stack.emplace_back();
|
||||
PartialSymbolEntry &entry( stack.back() );
|
||||
|
@ -1822,13 +1855,32 @@ void PrintC::pushPartialSymbol(const Symbol *sym,int4 off,int4 sz,
|
|||
succeeded = true;
|
||||
}
|
||||
}
|
||||
else if ((outtype != (Datatype *)0)&&
|
||||
castStrategy->isSubpieceCastEndian(outtype,ct,off,
|
||||
sym->getFirstWholeMap()->getAddr().getSpace()->isBigEndian())) {
|
||||
// Treat truncation as SUBPIECE style cast
|
||||
finalcast = outtype;
|
||||
ct = (Datatype *)0;
|
||||
succeeded = true;
|
||||
else if (ct->getMetatype() == TYPE_UNION) {
|
||||
const TypeField *field;
|
||||
field = ((TypeUnion *)ct)->findTruncation(off,op,inslot,off);
|
||||
if (field != (const TypeField*)0) {
|
||||
stack.emplace_back();
|
||||
PartialSymbolEntry &entry(stack.back());
|
||||
entry.token = &object_member;
|
||||
entry.field = field;
|
||||
entry.parent = ct;
|
||||
entry.fieldname = entry.field->name;
|
||||
entry.hilite = EmitXml::no_color;
|
||||
ct = field->type;
|
||||
succeeded = true;
|
||||
}
|
||||
else if (ct->getSize() == sz)
|
||||
break; // Turns out we don't need to resolve the field
|
||||
}
|
||||
else if (inslot >= 0) {
|
||||
Datatype *outtype = vn->getHigh()->getType();
|
||||
if (castStrategy->isSubpieceCastEndian(outtype,ct,off,
|
||||
sym->getFirstWholeMap()->getAddr().getSpace()->isBigEndian())) {
|
||||
// Treat truncation as SUBPIECE style cast
|
||||
finalcast = outtype;
|
||||
ct = (Datatype*)0;
|
||||
succeeded = true;
|
||||
}
|
||||
}
|
||||
if (!succeeded) { // Subtype was not good
|
||||
stack.emplace_back();
|
||||
|
@ -1860,7 +1912,7 @@ void PrintC::pushPartialSymbol(const Symbol *sym,int4 off,int4 sz,
|
|||
if (field == (const TypeField *)0)
|
||||
pushAtom(Atom(stack[i].fieldname,syntax,stack[i].hilite,op));
|
||||
else
|
||||
pushAtom(Atom(stack[i].fieldname,fieldtoken,stack[i].hilite,stack[i].parent,field->offset));
|
||||
pushAtom(Atom(stack[i].fieldname,fieldtoken,stack[i].hilite,stack[i].parent,field->ident,op));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1882,6 +1934,39 @@ void PrintC::pushMismatchSymbol(const Symbol *sym,int4 off,int4 sz,
|
|||
pushUnnamedLocation(vn->getAddr(),vn,op);
|
||||
}
|
||||
|
||||
void PrintC::pushImpliedField(const Varnode *vn,const PcodeOp *op)
|
||||
|
||||
{
|
||||
bool proceed = false;
|
||||
Datatype *parent = vn->getHigh()->getType();
|
||||
const TypeField *field;
|
||||
if (parent->needsResolution() && parent->getMetatype() != TYPE_PTR) {
|
||||
const Funcdata *fd = op->getParent()->getFuncdata();
|
||||
int4 slot = op->getSlot(vn);
|
||||
const ResolvedUnion *res = fd->getUnionField(parent, op, slot);
|
||||
if (res != (const ResolvedUnion *)0 && res->getFieldNum() >= 0) {
|
||||
if (parent->getMetatype() == TYPE_STRUCT && res->getFieldNum() == 0) {
|
||||
field = &(*((TypeStruct *)parent)->beginField());
|
||||
proceed = true;
|
||||
}
|
||||
else if (parent->getMetatype() == TYPE_UNION) {
|
||||
field = ((TypeUnion *)parent)->getField(res->getFieldNum());
|
||||
proceed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const PcodeOp *defOp = vn->getDef();
|
||||
if (!proceed) {
|
||||
// Just push original op
|
||||
defOp->getOpcode()->push(this,defOp,op);
|
||||
return;
|
||||
}
|
||||
pushOp(&object_member,op);
|
||||
defOp->getOpcode()->push(this,defOp,op);
|
||||
pushAtom(Atom(field->name,fieldtoken,EmitXml::no_color,parent,field->ident,op));
|
||||
}
|
||||
|
||||
/// Print all the components making up the data-type, using the \b struct keyword
|
||||
/// \param ct is the structure data-type
|
||||
void PrintC::emitStructDefinition(const TypeStruct *ct)
|
||||
|
@ -2038,14 +2123,14 @@ void PrintC::emitLocalVarDecls(const Funcdata *fd)
|
|||
{
|
||||
bool notempty = false;
|
||||
|
||||
if (emitScopeVarDecls(fd->getScopeLocal(),-1))
|
||||
if (emitScopeVarDecls(fd->getScopeLocal(),Symbol::no_category))
|
||||
notempty = true;
|
||||
ScopeMap::const_iterator iter,enditer;
|
||||
iter = fd->getScopeLocal()->childrenBegin();
|
||||
enditer = fd->getScopeLocal()->childrenEnd();
|
||||
while(iter!=enditer) {
|
||||
Scope *l1 = (*iter).second;
|
||||
if (emitScopeVarDecls(l1,-1))
|
||||
if (emitScopeVarDecls(l1,Symbol::no_category))
|
||||
notempty = true;
|
||||
++iter;
|
||||
}
|
||||
|
@ -2226,7 +2311,7 @@ bool PrintC::emitInplaceOp(const PcodeOp *op)
|
|||
if (op->getOut()->getHigh() != vn->getHigh()) return false;
|
||||
pushOp(tok,op);
|
||||
pushVnExplicit(vn,op);
|
||||
pushVnImplied(op->getIn(1),op,mods);
|
||||
pushVn(op->getIn(1),op,mods);
|
||||
recurse();
|
||||
return true;
|
||||
}
|
||||
|
@ -2238,14 +2323,14 @@ void PrintC::emitExpression(const PcodeOp *op)
|
|||
if (outvn != (Varnode *)0) {
|
||||
if (option_inplace_ops && emitInplaceOp(op)) return;
|
||||
pushOp(&assignment,op);
|
||||
pushVnLHS(outvn,op);
|
||||
pushSymbolDetail(outvn,op,false);
|
||||
}
|
||||
else if (op->doesSpecialPrinting()) {
|
||||
// Printing of constructor syntax
|
||||
const PcodeOp *newop = op->getIn(1)->getDef();
|
||||
outvn = newop->getOut();
|
||||
pushOp(&assignment,newop);
|
||||
pushVnLHS(outvn,newop);
|
||||
pushSymbolDetail(outvn,newop,false);
|
||||
opConstructor(op,true);
|
||||
recurse();
|
||||
return;
|
||||
|
@ -2377,7 +2462,7 @@ void PrintC::emitGlobalVarDeclsRecursive(Scope *symScope)
|
|||
|
||||
{
|
||||
if (!symScope->isGlobal()) return;
|
||||
emitScopeVarDecls(symScope,-1);
|
||||
emitScopeVarDecls(symScope,Symbol::no_category);
|
||||
ScopeMap::const_iterator iter,enditer;
|
||||
iter = symScope->childrenBegin();
|
||||
enditer = symScope->childrenEnd();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue