mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 02:09:44 +02:00
GP-1922 Integer size suffix
This commit is contained in:
parent
d7f9cdfe5c
commit
fb3366a4e2
15 changed files with 178 additions and 66 deletions
|
@ -372,7 +372,7 @@ void Architecture::setPrintLanguage(const string &nm)
|
|||
ostream *t = print->getOutputStream();
|
||||
print = capa->buildLanguage(this);
|
||||
print->setOutputStream(t); // Restore settings from previous language
|
||||
print->getCastStrategy()->setTypeFactory(types);
|
||||
print->initializeFromArchitecture();
|
||||
if (printxml)
|
||||
print->setXML(true);
|
||||
printlist.push_back(print);
|
||||
|
@ -1342,7 +1342,7 @@ void Architecture::init(DocumentStorage &store)
|
|||
buildDatabase(store);
|
||||
|
||||
restoreFromSpec(store);
|
||||
print->getCastStrategy()->setTypeFactory(types);
|
||||
print->initializeFromArchitecture();
|
||||
symboltab->adjustCaches(); // In case the specs created additional address spaces
|
||||
postSpecFile(); // Let subclasses do things after translate is ready
|
||||
|
||||
|
|
|
@ -25,6 +25,80 @@ void CastStrategy::setTypeFactory(TypeFactory *t)
|
|||
promoteSize = tlst->getSizeOfInt();
|
||||
}
|
||||
|
||||
/// Many languages can mark an integer constant as explicitly \e unsigned. When
|
||||
/// the decompiler is deciding on \e cast operations, this is one of the checks
|
||||
/// it performs. This method checks if the indicated input is an
|
||||
/// integer constant that needs to be coerced (as a source token) into being unsigned.
|
||||
/// If this is \b true, the input Varnode is marked for printing as explicitly \e unsigned.
|
||||
/// \param op is the PcodeOp taking the value as input
|
||||
/// \param slot is the input slot of the value
|
||||
/// \return \b true if the Varnode gets marked for printing
|
||||
bool CastStrategy::markExplicitUnsigned(PcodeOp *op,int4 slot) const
|
||||
|
||||
{
|
||||
TypeOp *opcode = op->getOpcode();
|
||||
if (!opcode->inheritsSign()) return false;
|
||||
bool inheritsFirstParamOnly = opcode->inheritsSignFirstParamOnly();
|
||||
if ((slot==1) && inheritsFirstParamOnly) return false;
|
||||
Varnode *vn = op->getIn(slot);
|
||||
if (!vn->isConstant()) return false;
|
||||
Datatype *dt = vn->getHighTypeReadFacing(op);
|
||||
type_metatype meta = dt->getMetatype();
|
||||
if ((meta != TYPE_UINT)&&(meta != TYPE_UNKNOWN)) return false;
|
||||
if (dt->isCharPrint()) return false;
|
||||
if (dt->isEnumType()) return false;
|
||||
if ((op->numInput() == 2) && !inheritsFirstParamOnly) {
|
||||
Varnode *firstvn = op->getIn(1-slot);
|
||||
meta = firstvn->getHighTypeReadFacing(op)->getMetatype();
|
||||
if ((meta == TYPE_UINT)||(meta == TYPE_UNKNOWN))
|
||||
return false; // Other side of the operation will force the unsigned
|
||||
}
|
||||
// Check if type is going to get forced anyway
|
||||
Varnode *outvn = op->getOut();
|
||||
if (outvn != (Varnode *)0) {
|
||||
if (outvn->isExplicit()) return false;
|
||||
PcodeOp *lone = outvn->loneDescend();
|
||||
if (lone != (PcodeOp *)0) {
|
||||
if (!lone->getOpcode()->inheritsSign()) return false;
|
||||
}
|
||||
}
|
||||
|
||||
vn->setUnsignedPrint();
|
||||
return true;
|
||||
}
|
||||
|
||||
/// This method checks if the indicated input is an integer constant that needs to be coerced
|
||||
/// (as a source token) into a data-type that is larger than the base integer. If this is \b true,
|
||||
/// the input Varnode is marked for printing as explicitly a larger integer (typically \e long).
|
||||
/// \param op is the PcodeOp taking the value as input
|
||||
/// \param slot is the input slot of the value
|
||||
/// \return \b true if the Varnode gets marked for printing
|
||||
bool CastStrategy::markExplicitLongSize(PcodeOp *op,int4 slot) const
|
||||
|
||||
{
|
||||
if (!op->getOpcode()->isShiftOp()) return false;
|
||||
if (slot != 0) return false;
|
||||
Varnode *vn = op->getIn(slot);
|
||||
if (!vn->isConstant()) return false;
|
||||
if (vn->getSize() <= promoteSize) return false;
|
||||
Datatype *dt = vn->getHigh()->getType();
|
||||
type_metatype meta = dt->getMetatype();
|
||||
if ((meta != TYPE_UINT)&&(meta != TYPE_INT)&&(meta != TYPE_UNKNOWN)) return false;
|
||||
uintb off = vn->getOffset();
|
||||
if (meta == TYPE_INT && signbit_negative(off, vn->getSize())) {
|
||||
off = uintb_negate(off, vn->getSize());
|
||||
int4 bit = mostsigbit_set(off);
|
||||
if (bit >= promoteSize * 8 - 1) return false;
|
||||
}
|
||||
else {
|
||||
int4 bit = mostsigbit_set(off);
|
||||
if (bit >= promoteSize * 8) return false; // If integer is big enough, it naturally becomes a long
|
||||
}
|
||||
|
||||
vn->setLongPrint();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CastStrategyC::checkIntPromotionForCompare(const PcodeOp *op,int4 slot) const
|
||||
|
||||
{
|
||||
|
|
|
@ -153,6 +153,12 @@ public:
|
|||
/// \param intype is the input data-type
|
||||
/// \return \b true if the INT_ZEXT should be represented as a cast
|
||||
virtual bool isZextCast(Datatype *outtype,Datatype *intype) const=0;
|
||||
|
||||
/// \brief Check if a constant input should be explicitly labeled as an \e unsigned token
|
||||
bool markExplicitUnsigned(PcodeOp *op,int4 slot) const;
|
||||
|
||||
/// \brief Check is a constant input should be explicitly labeled as a \e long integer token
|
||||
bool markExplicitLongSize(PcodeOp *op,int4 slot) const;
|
||||
};
|
||||
|
||||
/// \brief Casting strategies that are specific to the C language
|
||||
|
|
|
@ -2474,7 +2474,9 @@ int4 ActionSetCasts::castInput(PcodeOp *op,int4 slot,Funcdata &data,CastStrategy
|
|||
|
||||
ct = op->getOpcode()->getInputCast(op,slot,castStrategy); // Input type expected by this operation
|
||||
if (ct == (Datatype *)0) {
|
||||
if (op->markExplicitUnsigned(slot)) // Decide if this input should be explicitly printed as unsigned constant
|
||||
bool resUnsigned = castStrategy->markExplicitUnsigned(op, slot);
|
||||
bool resSized = castStrategy->markExplicitLongSize(op, slot);
|
||||
if (resUnsigned || resSized)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -231,8 +231,6 @@ public:
|
|||
|
||||
Datatype *outputTypeLocal(void) const { return opcode->getOutputLocal(this); } ///< Calculate the local output type
|
||||
Datatype *inputTypeLocal(int4 slot) const { return opcode->getInputLocal(this,slot); } ///< Calculate the local input type
|
||||
bool markExplicitUnsigned(int4 slot) { return opcode->markExplicitUnsigned(this,slot); } ///< Decide on unsignedness printing
|
||||
bool inheritsSign(void) const { return opcode->inheritsSign(); } ///< Does this token inherit its sign from operands
|
||||
};
|
||||
|
||||
/// \brief An edge in a data-flow path or graph
|
||||
|
|
|
@ -1152,9 +1152,11 @@ void PrintC::push_integer(uintb val,int4 sz,bool sign,
|
|||
{
|
||||
bool print_negsign;
|
||||
bool force_unsigned_token;
|
||||
bool force_sized_token;
|
||||
uint4 displayFormat = 0;
|
||||
|
||||
force_unsigned_token = false;
|
||||
force_sized_token = false;
|
||||
if ((vn != (const Varnode *)0)&&(!vn->isAnnotation())) {
|
||||
Symbol *sym = vn->getHigh()->getSymbol();
|
||||
if (sym != (Symbol *)0) {
|
||||
|
@ -1164,6 +1166,8 @@ void PrintC::push_integer(uintb val,int4 sz,bool sign,
|
|||
}
|
||||
displayFormat = sym->getDisplayFormat();
|
||||
}
|
||||
force_unsigned_token = vn->isUnsignedPrint();
|
||||
force_sized_token = vn->isLongPrint();
|
||||
}
|
||||
if (sign && displayFormat != Symbol::force_char) { // Print the constant as signed
|
||||
uintb mask = calc_mask(sz);
|
||||
|
@ -1171,11 +1175,10 @@ void PrintC::push_integer(uintb val,int4 sz,bool sign,
|
|||
print_negsign = (flip < val);
|
||||
if (print_negsign)
|
||||
val = flip+1;
|
||||
force_unsigned_token = false;
|
||||
}
|
||||
else {
|
||||
print_negsign = false;
|
||||
if (vn != (const Varnode *)0)
|
||||
force_unsigned_token = vn->isUnsignedPrint();
|
||||
}
|
||||
|
||||
// Figure whether to print as hex or decimal
|
||||
|
@ -1217,6 +1220,8 @@ void PrintC::push_integer(uintb val,int4 sz,bool sign,
|
|||
}
|
||||
if (force_unsigned_token)
|
||||
t << 'U'; // Force unsignedness explicitly
|
||||
if (force_sized_token)
|
||||
t << sizeSuffix;
|
||||
|
||||
if (vn==(const Varnode *)0)
|
||||
pushAtom(Atom(t.str(),syntax,EmitXml::const_color,op));
|
||||
|
@ -2190,6 +2195,16 @@ void PrintC::resetDefaults(void)
|
|||
resetDefaultsPrintC();
|
||||
}
|
||||
|
||||
void PrintC::initializeFromArchitecture(void)
|
||||
|
||||
{
|
||||
castStrategy->setTypeFactory(glb->types);
|
||||
if (glb->types->getSizeOfLong() == glb->types->getSizeOfInt()) // If long and int sizes are the same
|
||||
sizeSuffix = "LL"; // Use "long long" suffix to indicate large integer
|
||||
else
|
||||
sizeSuffix = "L"; // Otherwise just use long suffix
|
||||
}
|
||||
|
||||
void PrintC::adjustTypeOperators(void)
|
||||
|
||||
{
|
||||
|
|
|
@ -121,6 +121,7 @@ protected:
|
|||
bool option_unplaced; ///< Set to \b true if we should display unplaced comments
|
||||
bool option_hide_exts; ///< Set to \b true if we should hide implied extension operations
|
||||
string nullToken; ///< Token to use for 'null'
|
||||
string sizeSuffix; ///< Characters to print to indicate a \e long integer token
|
||||
CommentSorter commsorter; ///< Container/organizer for comments in the current function
|
||||
|
||||
// Routines that are specific to C/C++
|
||||
|
@ -210,6 +211,7 @@ public:
|
|||
void setHideImpliedExts(bool val) { option_hide_exts = val; } ///< Toggle whether implied extensions are hidden
|
||||
virtual ~PrintC(void) {}
|
||||
virtual void resetDefaults(void);
|
||||
virtual void initializeFromArchitecture(void);
|
||||
virtual void adjustTypeOperators(void);
|
||||
virtual void setCommentStyle(const string &nm);
|
||||
virtual void docTypeDefinitions(const TypeFactory *typegrp);
|
||||
|
|
|
@ -435,10 +435,11 @@ public:
|
|||
void setXML(bool val); ///< Set whether the low-level emitter, emits XML markup
|
||||
void setFlat(bool val); ///< Set whether nesting code structure should be emitted
|
||||
|
||||
virtual void adjustTypeOperators(void)=0; ///< Set basic data-type information for p-code operators
|
||||
virtual void resetDefaults(void); ///< Set printing options to their default value
|
||||
virtual void clear(void); ///< Clear the RPN stack and the low-level emitter
|
||||
virtual void setIntegerFormat(const string &nm); ///< Set the default integer format
|
||||
virtual void initializeFromArchitecture(void)=0; ///< Initialize architecture specific aspects of printer
|
||||
virtual void adjustTypeOperators(void)=0; ///< Set basic data-type information for p-code operators
|
||||
virtual void resetDefaults(void); ///< Set printing options to their default value
|
||||
virtual void clear(void); ///< Clear the RPN stack and the low-level emitter
|
||||
virtual void setIntegerFormat(const string &nm); ///< Set the default integer format
|
||||
|
||||
/// \brief Set the way comments are displayed in decompiler output
|
||||
///
|
||||
|
|
|
@ -2308,6 +2308,7 @@ TypeFactory::TypeFactory(Architecture *g)
|
|||
{
|
||||
glb = g;
|
||||
sizeOfInt = 0;
|
||||
sizeOfLong = 0;
|
||||
align = 0;
|
||||
enumsize = 0;
|
||||
|
||||
|
@ -2341,6 +2342,9 @@ void TypeFactory::setupSizes(void)
|
|||
sizeOfInt = 4;
|
||||
}
|
||||
}
|
||||
if (sizeOfLong == 0) {
|
||||
sizeOfLong = (sizeOfInt == 4) ? 8 : sizeOfInt;
|
||||
}
|
||||
if (align == 0)
|
||||
align = glb->getDefaultSize();
|
||||
if (enumsize == 0) {
|
||||
|
@ -3271,6 +3275,7 @@ void TypeFactory::saveXml(ostream &s) const
|
|||
dependentOrder(deporder); // Put types in correct order
|
||||
s << "<typegrp";
|
||||
a_v_i(s,"intsize",sizeOfInt);
|
||||
a_v_i(s,"longsize",sizeOfLong);
|
||||
a_v_i(s,"structalign",align);
|
||||
a_v_i(s,"enumsize",enumsize);
|
||||
a_v_b(s,"enumsigned",(enumtype==TYPE_INT));
|
||||
|
@ -3573,6 +3578,9 @@ void TypeFactory::restoreXml(const Element *el)
|
|||
istringstream i3(el->getAttributeValue("intsize"));
|
||||
i3.unsetf(ios::dec | ios::hex | ios::oct);
|
||||
i3 >> sizeOfInt;
|
||||
istringstream i4(el->getAttributeValue("longsize"));
|
||||
i4.unsetf(ios::dec | ios::hex | ios::oct);
|
||||
i4 >> sizeOfLong;
|
||||
istringstream i(el->getAttributeValue("structalign"));
|
||||
i.unsetf(ios::dec | ios::hex | ios::oct);
|
||||
i >> align;
|
||||
|
@ -3621,6 +3629,11 @@ void TypeFactory::parseDataOrganization(const Element *el)
|
|||
i.unsetf(ios::dec | ios::hex | ios::oct);
|
||||
i >> sizeOfInt;
|
||||
}
|
||||
else if (subel->getName() == "long_size") {
|
||||
istringstream i(subel->getAttributeValue("value"));
|
||||
i.unsetf(ios::dec | ios::hex | ios::oct);
|
||||
i >> sizeOfLong;
|
||||
}
|
||||
else if (subel->getName() == "size_alignment_map") {
|
||||
const List &childlist(subel->getChildren());
|
||||
List::const_iterator iter2;
|
||||
|
|
|
@ -534,6 +534,7 @@ public:
|
|||
/// \brief Container class for all Datatype objects in an Architecture
|
||||
class TypeFactory {
|
||||
int4 sizeOfInt; ///< Size of the core "int" datatype
|
||||
int4 sizeOfLong; ///< Size of the core "long" datatype
|
||||
int4 align; ///< Alignment of structures
|
||||
int4 enumsize; ///< Size of an enumerated type
|
||||
type_metatype enumtype; ///< Default enumeration meta-type (when parsing C)
|
||||
|
@ -570,6 +571,7 @@ public:
|
|||
void setStructAlign(int4 al) { align = al; } ///< Set the default structure alignment
|
||||
int4 getStructAlign(void) const { return align; } ///< Get the default structure alignment
|
||||
int4 getSizeOfInt(void) const { return sizeOfInt; } ///< Get the size of the default "int"
|
||||
int4 getSizeOfLong(void) const { return sizeOfLong; } ///< Get the size of the default "long"
|
||||
Architecture *getArch(void) const { return glb; } ///< Get the Architecture object
|
||||
Datatype *findByName(const string &n); ///< Return type of given name
|
||||
Datatype *setName(Datatype *ct,const string &n); ///< Set the given types name
|
||||
|
|
|
@ -237,46 +237,6 @@ Datatype *TypeOp::propagateType(Datatype *alttype,PcodeOp *op,Varnode *invn,Varn
|
|||
return (Datatype *)0; // Don't propagate by default
|
||||
}
|
||||
|
||||
/// Many languages can mark an integer constant as explicitly \e unsigned. When
|
||||
/// the decompiler is deciding on \e cast operations, this is one of the checks
|
||||
/// it performs. This method checks if the indicated input is an
|
||||
/// integer constant that needs to be coerced (as a source token) into being unsigned.
|
||||
/// If this is \b true, the input Varnode is marked for printing as explicitly \e unsigned.
|
||||
/// \param op is the PcodeOp taking the value as input
|
||||
/// \param slot is the input slot of the value
|
||||
/// \return \b true if the Varnode gets marked for printing
|
||||
bool TypeOp::markExplicitUnsigned(PcodeOp *op,int4 slot) const
|
||||
|
||||
{
|
||||
if ((addlflags & inherits_sign)==0) return false;
|
||||
if ((slot==1) && ((addlflags & inherits_sign_zero)!=0)) return false;
|
||||
Varnode *vn = op->getIn(slot);
|
||||
if (!vn->isConstant()) return false;
|
||||
Datatype *dt = vn->getHighTypeReadFacing(op);
|
||||
type_metatype meta = dt->getMetatype();
|
||||
if ((meta != TYPE_UINT)&&(meta != TYPE_UNKNOWN)) return false;
|
||||
if (dt->isCharPrint()) return false;
|
||||
if (dt->isEnumType()) return false;
|
||||
if ((op->numInput() == 2) && ((addlflags & inherits_sign_zero)==0)) {
|
||||
Varnode *firstvn = op->getIn(1-slot);
|
||||
meta = firstvn->getHighTypeReadFacing(op)->getMetatype();
|
||||
if ((meta == TYPE_UINT)||(meta == TYPE_UNKNOWN))
|
||||
return false; // Other side of the operation will force the unsigned
|
||||
}
|
||||
// Check if type is going to get forced anyway
|
||||
Varnode *outvn = op->getOut();
|
||||
if (outvn != (Varnode *)0) {
|
||||
if (outvn->isExplicit()) return false;
|
||||
PcodeOp *lone = outvn->loneDescend();
|
||||
if (lone != (PcodeOp *)0) {
|
||||
if (!lone->inheritsSign()) return false;
|
||||
}
|
||||
}
|
||||
|
||||
vn->setUnsignedPrint();
|
||||
return true;
|
||||
}
|
||||
|
||||
Datatype *TypeOpBinary::getOutputLocal(const PcodeOp *op) const
|
||||
|
||||
{
|
||||
|
@ -1462,7 +1422,7 @@ TypeOpIntLeft::TypeOpIntLeft(TypeFactory *t)
|
|||
: TypeOpBinary(t,CPUI_INT_LEFT,"<<",TYPE_INT,TYPE_INT)
|
||||
{
|
||||
opflags = PcodeOp::binary;
|
||||
addlflags = inherits_sign | inherits_sign_zero;
|
||||
addlflags = inherits_sign | inherits_sign_zero | shift_op;
|
||||
behave = new OpBehaviorIntLeft();
|
||||
}
|
||||
|
||||
|
@ -1487,7 +1447,7 @@ TypeOpIntRight::TypeOpIntRight(TypeFactory *t)
|
|||
: TypeOpBinary(t,CPUI_INT_RIGHT,">>",TYPE_UINT,TYPE_UINT)
|
||||
{
|
||||
opflags = PcodeOp::binary;
|
||||
addlflags = inherits_sign | inherits_sign_zero;
|
||||
addlflags = inherits_sign | inherits_sign_zero | shift_op;
|
||||
behave = new OpBehaviorIntRight();
|
||||
}
|
||||
|
||||
|
@ -1527,7 +1487,7 @@ TypeOpIntSright::TypeOpIntSright(TypeFactory *t)
|
|||
: TypeOpBinary(t,CPUI_INT_SRIGHT,">>",TYPE_INT,TYPE_INT)
|
||||
{
|
||||
opflags = PcodeOp::binary;
|
||||
addlflags = inherits_sign | inherits_sign_zero;
|
||||
addlflags = inherits_sign | inherits_sign_zero | shift_op;
|
||||
behave = new OpBehaviorIntSright();
|
||||
}
|
||||
|
||||
|
|
|
@ -38,7 +38,8 @@ class TypeOp {
|
|||
public:
|
||||
enum {
|
||||
inherits_sign = 1, ///< Operator token inherits signedness from its inputs
|
||||
inherits_sign_zero = 2 ///< Only inherits sign from first operand, not the second
|
||||
inherits_sign_zero = 2, ///< Only inherits sign from first operand, not the second
|
||||
shift_op = 4 ///< Shift operation
|
||||
};
|
||||
protected:
|
||||
TypeFactory *tlst; ///< Pointer to data-type factory
|
||||
|
@ -57,7 +58,6 @@ public:
|
|||
OpCode getOpcode(void) const { return opcode; } ///< Get the op-code value
|
||||
uint4 getFlags(void) const { return opflags; } ///< Get the properties associated with the op-code
|
||||
OpBehavior *getBehavior(void) const { return behave; } ///< Get the behavior associated with the op-code
|
||||
bool markExplicitUnsigned(PcodeOp *op,int4 slot) const; ///< Check if a constant input should be explicitly labeled as \e unsigned
|
||||
|
||||
/// \brief Emulate the unary op-code on an input value
|
||||
///
|
||||
|
@ -103,9 +103,15 @@ public:
|
|||
|
||||
bool isCommutative(void) const; ///< Return \b true if this op-code is commutative
|
||||
|
||||
/// \brief Return \b true if the op-code inherits it signedness from its inputs
|
||||
/// \brief Return \b true if the op-code inherits its signedness from its inputs
|
||||
bool inheritsSign(void) const { return ((addlflags & inherits_sign)!=0); }
|
||||
|
||||
/// \brief Return \b true if the op-code inherits its signedness from only its first input
|
||||
bool inheritsSignFirstParamOnly(void) const { return ((addlflags & inherits_sign_zero)!=0); }
|
||||
|
||||
/// \brief Return \b true if the op-code is a shift (INT_LEFT, INT_RIGHT, or INT_SRIGHT)
|
||||
bool isShiftOp(void) const { return ((addlflags & shift_op)!=0); }
|
||||
|
||||
/// \brief Find the minimal (or suggested) data-type of an output to \b this op-code
|
||||
virtual Datatype *getOutputLocal(const PcodeOp *op) const;
|
||||
|
||||
|
|
|
@ -113,13 +113,14 @@ public:
|
|||
lisconsume = 0x08, ///< In consume worklist
|
||||
ptrcheck = 0x10, ///< The Varnode value is \e NOT a pointer
|
||||
ptrflow = 0x20, ///< If this varnode flows to or from a pointer
|
||||
unsignedprint = 0x40, ///< Constant that must be explicitly printed as unsigned
|
||||
stack_store = 0x80, ///< Created by an explicit STORE
|
||||
locked_input = 0x100, ///< Input that exists even if its unused
|
||||
spacebase_placeholder = 0x200, ///< This varnode is inserted artificially to track a register
|
||||
unsignedprint = 0x40, ///< Constant that must be explicitly printed as an unsigned token
|
||||
longprint = 0x80, ///< Constant that must be explicitly printed as a \e long integer token
|
||||
stack_store = 0x100, ///< Created by an explicit STORE
|
||||
locked_input = 0x200, ///< Input that exists even if its unused
|
||||
spacebase_placeholder = 0x400, ///< This varnode is inserted artificially to track a register
|
||||
///< value at a specific point in the code
|
||||
stop_uppropagation = 0x400, ///< Data-types do not propagate from an output into \b this
|
||||
has_implied_field = 0x800 ///< The varnode is implied but also has a data-type that needs resolution
|
||||
stop_uppropagation = 0x800, ///< Data-types do not propagate from an output into \b this
|
||||
has_implied_field = 0x1000 ///< The varnode is implied but also has a data-type that needs resolution
|
||||
};
|
||||
private:
|
||||
mutable uint4 flags; ///< The collection of boolean attributes for this Varnode
|
||||
|
@ -262,6 +263,7 @@ public:
|
|||
bool isIncidentalCopy(void) const { return ((flags&Varnode::incidental_copy)!=0); } ///< Does this varnode get copied as a side-effect
|
||||
bool isWriteMask(void) const { return ((addlflags&Varnode::writemask)!=0); } ///< Is \b this (not) considered a true write location when calculating SSA form?
|
||||
bool isUnsignedPrint(void) const { return ((addlflags&Varnode::unsignedprint)!=0); } ///< Must \b this be printed as unsigned
|
||||
bool isLongPrint(void) const { return ((addlflags&Varnode::longprint)!=0); } ///< Must \b this be printed as a \e long token
|
||||
bool isWritten(void) const { return ((flags&Varnode::written)!=0); } ///< Does \b this have a defining write operation?
|
||||
|
||||
/// Does \b this have Cover information?
|
||||
|
@ -309,6 +311,7 @@ public:
|
|||
void setAutoLiveHold(void) { flags |= Varnode::autolive_hold; } ///< Place temporary hold on dead code removal
|
||||
void clearAutoLiveHold(void) { flags &= ~Varnode::autolive_hold; } ///< Clear temporary hold on dead code removal
|
||||
void setUnsignedPrint(void) { addlflags |= Varnode::unsignedprint; } ///< Force \b this to be printed as unsigned
|
||||
void setLongPrint(void) { addlflags |= Varnode::longprint; } ///< Force \b this to be printed as a \e long token
|
||||
void setStopUpPropagation(void) { addlflags |= Varnode::stop_uppropagation; } ///< Stop up-propagation thru \b this
|
||||
void clearStopUpPropagation(void) { addlflags &= ~Varnode::stop_uppropagation; } ///< Stop up-propagation thru \b this
|
||||
void setImpliedField(void) { addlflags |= Varnode::has_implied_field; } ///< Mark \this as having an implied field
|
||||
|
|
|
@ -99,6 +99,23 @@ bool castPrinted(OpCode opc,Datatype *t1,Datatype *t2) {
|
|||
return (inst->getInputCast(op, 0, strategy) != (Datatype *)0);
|
||||
}
|
||||
|
||||
bool longPrinted(OpCode opc,Datatype *t1,uintb val)
|
||||
|
||||
{
|
||||
PcodeOp *op;
|
||||
Address addr(glb->getDefaultCodeSpace(),0x1000);
|
||||
op = dummyFunc->newOp(2, addr);
|
||||
Datatype *sa = glb->types->getBase(4,TYPE_INT);
|
||||
Varnode *vn1 = dummyFunc->newConstant(t1->getSize(), val);
|
||||
vn1->updateType(t1, false, true);
|
||||
Varnode *vn2 = dummyFunc->newUnique(sa->getSize(), sa);
|
||||
dummyFunc->opSetOpcode(op, opc);
|
||||
dummyFunc->opSetInput(op, vn1, 0);
|
||||
dummyFunc->opSetInput(op, vn2, 1);
|
||||
dummyFunc->newUniqueOut(vn1->getSize(), op);
|
||||
return glb->print->getCastStrategy()->markExplicitLongSize(op, 0);
|
||||
}
|
||||
|
||||
TEST(cast_basic) {
|
||||
TypeTestEnvironment::build();
|
||||
ASSERT(castPrinted(CPUI_COPY,parse("int4"),parse("int2")));
|
||||
|
@ -181,3 +198,14 @@ TEST(type_ordering) {
|
|||
ASSERT(parse("int4 *")->compare(*parse("void *"),10) < 0);
|
||||
ASSERT(parse("int2 *")->compare(*parse("xunknown2 *"),10) < 0);
|
||||
}
|
||||
|
||||
TEST(cast_integertoken) {
|
||||
TypeTestEnvironment::build();
|
||||
ASSERT(longPrinted(CPUI_INT_LEFT,parse("int8"),10));
|
||||
ASSERT(!longPrinted(CPUI_INT_LEFT,parse("int8"),0x100000000));
|
||||
ASSERT(longPrinted(CPUI_INT_SRIGHT,parse("int8"),-3));
|
||||
ASSERT(!longPrinted(CPUI_INT_SRIGHT,parse("int8"),0xffffffff7fffffff));
|
||||
ASSERT(longPrinted(CPUI_INT_SRIGHT,parse("int8"),0xffffffff80000000));
|
||||
ASSERT(longPrinted(CPUI_INT_RIGHT,parse("uint8"),0xffffffff));
|
||||
ASSERT(!longPrinted(CPUI_INT_RIGHT,parse("uint8"),0x100000000));
|
||||
}
|
||||
|
|
|
@ -26,8 +26,7 @@ import ghidra.app.plugin.processors.sleigh.symbol.ContextSymbol;
|
|||
import ghidra.app.plugin.processors.sleigh.symbol.Symbol;
|
||||
import ghidra.app.util.DataTypeDependencyOrderer;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.data.BuiltIn;
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.program.model.lang.*;
|
||||
import ghidra.program.model.listing.*;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
|
@ -327,10 +326,13 @@ public class DecompileDebug {
|
|||
}
|
||||
|
||||
private void dumpDataTypes(OutputStream debugStream) throws IOException {
|
||||
int intSize = program.getCompilerSpec().getDataOrganization().getIntegerSize();
|
||||
DataOrganization dataOrganization = program.getCompilerSpec().getDataOrganization();
|
||||
int intSize = dataOrganization.getIntegerSize();
|
||||
int longSize = dataOrganization.getLongSize();
|
||||
StringBuilder buf = new StringBuilder();
|
||||
buf.append("<typegrp");
|
||||
SpecXmlUtils.encodeSignedIntegerAttribute(buf, "intsize", intSize);
|
||||
SpecXmlUtils.encodeSignedIntegerAttribute(buf, "longsize", longSize);
|
||||
SpecXmlUtils.encodeSignedIntegerAttribute(buf, "structalign", 4);
|
||||
SpecXmlUtils.encodeSignedIntegerAttribute(buf, "enumsize", 4);
|
||||
SpecXmlUtils.encodeBooleanAttribute(buf, "enumsigned", false);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue