GP-3680 Add case label tokens

This commit is contained in:
caheckman 2023-08-02 17:08:22 +00:00
parent c072972153
commit fe2f993e11
15 changed files with 415 additions and 138 deletions

View file

@ -1260,6 +1260,14 @@ void BlockGraph::printRaw(ostream &s) const
(*iter)->printRaw(s); (*iter)->printRaw(s);
} }
PcodeOp *BlockGraph::firstOp(void) const
{
if (getSize() == 0)
return (PcodeOp *)0;
return getBlock(0)->firstOp();
}
FlowBlock *BlockGraph::nextFlowAfter(const FlowBlock *bl) const FlowBlock *BlockGraph::nextFlowAfter(const FlowBlock *bl) const
{ {
@ -2255,6 +2263,13 @@ Address BlockBasic::getStop(void) const
return range->getLastAddr(); return range->getLastAddr();
} }
PcodeOp *BlockBasic::firstOp(void) const
{
if (op.empty()) return (PcodeOp *)0;
return (PcodeOp *)op.front();
}
PcodeOp *BlockBasic::lastOp(void) const PcodeOp *BlockBasic::lastOp(void) const
{ {

View file

@ -175,6 +175,7 @@ public:
virtual void printRaw(ostream &s) const {} ///< Print raw instructions contained in \b this FlowBlock virtual void printRaw(ostream &s) const {} ///< Print raw instructions contained in \b this FlowBlock
virtual void emit(PrintLanguage *lng) const; ///<Emit the instructions in \b this FlowBlock as structured code virtual void emit(PrintLanguage *lng) const; ///<Emit the instructions in \b this FlowBlock as structured code
virtual const FlowBlock *getExitLeaf(void) const { return (const FlowBlock *)0; } ///< Get the FlowBlock to which \b this block exits virtual const FlowBlock *getExitLeaf(void) const { return (const FlowBlock *)0; } ///< Get the FlowBlock to which \b this block exits
virtual PcodeOp *firstOp(void) const { return (PcodeOp *)0; } ///< Get the first PcodeOp executed by \b this FlowBlock
virtual PcodeOp *lastOp(void) const { return (PcodeOp *)0; } ///< Get the last PcodeOp executed by \b this FlowBlock virtual PcodeOp *lastOp(void) const { return (PcodeOp *)0; } ///< Get the last PcodeOp executed by \b this FlowBlock
virtual bool negateCondition(bool toporbottom); ///< Flip the condition computed by \b this virtual bool negateCondition(bool toporbottom); ///< Flip the condition computed by \b this
virtual bool preferComplement(Funcdata &data); ///< Rearrange \b this hierarchy to simplify boolean expressions virtual bool preferComplement(Funcdata &data); ///< Rearrange \b this hierarchy to simplify boolean expressions
@ -307,6 +308,7 @@ public:
virtual void printTree(ostream &s,int4 level) const; virtual void printTree(ostream &s,int4 level) const;
virtual void printRaw(ostream &s) const; virtual void printRaw(ostream &s) const;
virtual void emit(PrintLanguage *lng) const { lng->emitBlockGraph(this); } virtual void emit(PrintLanguage *lng) const { lng->emitBlockGraph(this); }
virtual PcodeOp *firstOp(void) const;
virtual FlowBlock *nextFlowAfter(const FlowBlock *bl) const; virtual FlowBlock *nextFlowAfter(const FlowBlock *bl) const;
virtual void finalTransform(Funcdata &data); virtual void finalTransform(Funcdata &data);
virtual void finalizePrinting(Funcdata &data) const; virtual void finalizePrinting(Funcdata &data) const;
@ -400,6 +402,7 @@ public:
virtual void printRaw(ostream &s) const; virtual void printRaw(ostream &s) const;
virtual void emit(PrintLanguage *lng) const { lng->emitBlockBasic(this); } virtual void emit(PrintLanguage *lng) const { lng->emitBlockBasic(this); }
virtual const FlowBlock *getExitLeaf(void) const { return this; } virtual const FlowBlock *getExitLeaf(void) const { return this; }
virtual PcodeOp *firstOp(void) const;
virtual PcodeOp *lastOp(void) const; virtual PcodeOp *lastOp(void) const;
virtual bool negateCondition(bool toporbottom); virtual bool negateCondition(bool toporbottom);
virtual FlowBlock *getSplitPoint(void); virtual FlowBlock *getSplitPoint(void);
@ -440,6 +443,7 @@ public:
virtual void printRaw(ostream &s) const { copy->printRaw(s); } virtual void printRaw(ostream &s) const { copy->printRaw(s); }
virtual void emit(PrintLanguage *lng) const { lng->emitBlockCopy(this); } virtual void emit(PrintLanguage *lng) const { lng->emitBlockCopy(this); }
virtual const FlowBlock *getExitLeaf(void) const { return this; } virtual const FlowBlock *getExitLeaf(void) const { return this; }
virtual PcodeOp *firstOp(void) const { return copy->firstOp(); }
virtual PcodeOp *lastOp(void) const { return copy->lastOp(); } virtual PcodeOp *lastOp(void) const { return copy->lastOp(); }
virtual bool negateCondition(bool toporbottom) { bool res = copy->negateCondition(true); FlowBlock::negateCondition(toporbottom); return res; } virtual bool negateCondition(bool toporbottom) { bool res = copy->negateCondition(true); FlowBlock::negateCondition(toporbottom); return res; }
virtual FlowBlock *getSplitPoint(void) { return copy->getSplitPoint(); } virtual FlowBlock *getSplitPoint(void) { return copy->getSplitPoint(); }

View file

@ -244,6 +244,19 @@ void EmitMarkup::tagLabel(const string &name,syntax_highlight hl,const AddrSpace
encoder->closeElement(ELEM_LABEL); encoder->closeElement(ELEM_LABEL);
} }
void EmitMarkup::tagCaseLabel(const string &name,syntax_highlight hl,const PcodeOp *op,uintb value)
{
encoder->openElement(ELEM_VALUE);
if (hl != no_color)
encoder->writeUnsignedInteger(ATTRIB_COLOR,hl);
encoder->writeUnsignedInteger(ATTRIB_OFF, value);
if (op != (const PcodeOp *)0)
encoder->writeUnsignedInteger(ATTRIB_OPREF, op->getTime());
encoder->writeString(ATTRIB_CONTENT,name);
encoder->closeElement(ELEM_VALUE);
}
void EmitMarkup::print(const string &data,syntax_highlight hl) void EmitMarkup::print(const string &data,syntax_highlight hl)
{ {
@ -357,6 +370,9 @@ void TokenSplit::print(Emit *emit) const
case label_t: // tagLabel case label_t: // tagLabel
emit->tagLabel(tok,hl,ptr_second.spc,off); emit->tagLabel(tok,hl,ptr_second.spc,off);
break; break;
case case_t: // tagCaseLabel
emit->tagCaseLabel(tok, hl, op, off);
break;
case synt_t: // print case synt_t: // print
emit->print(tok,hl); emit->print(tok,hl);
break; break;
@ -448,6 +464,9 @@ void TokenSplit::printDebug(ostream &s) const
case label_t: // tagLabel case label_t: // tagLabel
s << "label_t"; s << "label_t";
break; break;
case case_t: // tagCaseLabel
s << "case_t";
break;
case synt_t: // print case synt_t: // print
s << "synt_t"; s << "synt_t";
break; break;
@ -1011,6 +1030,15 @@ void EmitPrettyPrint::tagLabel(const string &name,syntax_highlight hl,const Addr
scan(); scan();
} }
void EmitPrettyPrint::tagCaseLabel(const string &name,syntax_highlight hl,const PcodeOp *op,uintb value)
{
checkstring();
TokenSplit &tok( tokqueue.push() );
tok.tagCaseLabel(name, hl, op, value);
scan();
}
void EmitPrettyPrint::print(const string &data,syntax_highlight hl) void EmitPrettyPrint::print(const string &data,syntax_highlight hl)
{ {

View file

@ -292,6 +292,15 @@ public:
/// \param off is the offset of the code address being labeled /// \param off is the offset of the code address being labeled
virtual void tagLabel(const string &name,syntax_highlight hl,const AddrSpace *spc,uintb off)=0; virtual void tagLabel(const string &name,syntax_highlight hl,const AddrSpace *spc,uintb off)=0;
/// \brief Emit a \e case label constant
///
/// A string describing the \e switch variable value is emitted and starting PcodeOp of the \e case block.
/// \param name is the character data of the value
/// \param hl indicates how the value should be highlighted
/// \param op is the first PcodeOp in the \e case block
/// \param value is the raw integer value underlying the switch value
virtual void tagCaseLabel(const string &name,syntax_highlight hl,const PcodeOp *op,uintb value)=0;
/// \brief Emit other (more unusual) syntax as part of source code generation /// \brief Emit other (more unusual) syntax as part of source code generation
/// ///
/// This method is used to emit syntax not covered by the other methods, such as /// This method is used to emit syntax not covered by the other methods, such as
@ -473,6 +482,7 @@ public:
virtual void tagField(const string &name,syntax_highlight hl,const Datatype *ct,int4 off,const PcodeOp *op); virtual void tagField(const string &name,syntax_highlight hl,const Datatype *ct,int4 off,const PcodeOp *op);
virtual void tagComment(const string &name,syntax_highlight hl,const AddrSpace *spc,uintb off); virtual void tagComment(const string &name,syntax_highlight hl,const AddrSpace *spc,uintb off);
virtual void tagLabel(const string &name,syntax_highlight hl,const AddrSpace *spc,uintb off); virtual void tagLabel(const string &name,syntax_highlight hl,const AddrSpace *spc,uintb off);
virtual void tagCaseLabel(const string &name,syntax_highlight hl,const PcodeOp *op,uintb value);
virtual void print(const string &data,syntax_highlight hl=no_color); virtual void print(const string &data,syntax_highlight hl=no_color);
virtual int4 openParen(const string &paren,int4 id=0); virtual int4 openParen(const string &paren,int4 id=0);
virtual void closeParen(const string &paren,int4 id); virtual void closeParen(const string &paren,int4 id);
@ -522,6 +532,8 @@ public:
*s << name; } *s << name; }
virtual void tagLabel(const string &name,syntax_highlight hl,const AddrSpace *spc,uintb off) { virtual void tagLabel(const string &name,syntax_highlight hl,const AddrSpace *spc,uintb off) {
*s << name; } *s << name; }
virtual void tagCaseLabel(const string &name,syntax_highlight hl,const PcodeOp *op,uintb value) {
*s << name; }
virtual void print(const string &data,syntax_highlight hl=no_color) { virtual void print(const string &data,syntax_highlight hl=no_color) {
*s << data; } *s << data; }
virtual int4 openParen(const string &paren,int4 id=0) { virtual int4 openParen(const string &paren,int4 id=0) {
@ -584,6 +596,7 @@ public:
field_t, ///< A field name for a structured data-type field_t, ///< A field name for a structured data-type
comm_t, ///< Part of a comment block comm_t, ///< Part of a comment block
label_t, ///< A code label label_t, ///< A code label
case_t, ///< A case label
synt_t, ///< Other unspecified syntax synt_t, ///< Other unspecified syntax
opar_t, ///< Open parenthesis opar_t, ///< Open parenthesis
cpar_t, ///< Close parenthesis cpar_t, ///< Close parenthesis
@ -774,6 +787,16 @@ public:
tok = name; size = tok.size(); ptr_second.spc=s; off=o; tok = name; size = tok.size(); ptr_second.spc=s; off=o;
tagtype=label_t; delimtype=tokenstring; hl=h; } tagtype=label_t; delimtype=tokenstring; hl=h; }
/// \brief Create a \e case label token
///
/// \param name is the character data of the label
/// \param h indicates how the label should be highlighted
/// \param inOp is the first PcodeOp in the \e case block
/// \param intValue is the constant value underlying the case label
void tagCaseLabel(const string &name,EmitMarkup::syntax_highlight h,const PcodeOp *inOp,uintb intValue) {
tok = name; size = tok.size(); op = inOp; off = intValue;
tagtype=case_t; delimtype=tokenstring; hl=h; }
/// \brief Create a token for other (more unusual) syntax in source code /// \brief Create a token for other (more unusual) syntax in source code
/// ///
/// \param data is the character data of the syntax being emitted /// \param data is the character data of the syntax being emitted
@ -1019,6 +1042,7 @@ public:
virtual void tagField(const string &name,syntax_highlight hl,const Datatype *ct,int4 off,const PcodeOp *op); virtual void tagField(const string &name,syntax_highlight hl,const Datatype *ct,int4 off,const PcodeOp *op);
virtual void tagComment(const string &name,syntax_highlight hl,const AddrSpace *spc,uintb off); virtual void tagComment(const string &name,syntax_highlight hl,const AddrSpace *spc,uintb off);
virtual void tagLabel(const string &name,syntax_highlight hl,const AddrSpace *spc,uintb off); virtual void tagLabel(const string &name,syntax_highlight hl,const AddrSpace *spc,uintb off);
virtual void tagCaseLabel(const string &name,syntax_highlight hl,const PcodeOp *op,uintb value);
virtual void print(const string &data,syntax_highlight hl=no_color); virtual void print(const string &data,syntax_highlight hl=no_color);
virtual int4 openParen(const string &paren,int4 id=0); virtual int4 openParen(const string &paren,int4 id=0);
virtual void closeParen(const string &paren,int4 id); virtual void closeParen(const string &paren,int4 id);

View file

@ -324,7 +324,7 @@ void PrintC::pushTypeEnd(const Datatype *ct)
else if (ct->getMetatype()==TYPE_ARRAY) { else if (ct->getMetatype()==TYPE_ARRAY) {
const TypeArray *ctarray = (const TypeArray *)ct; const TypeArray *ctarray = (const TypeArray *)ct;
ct = ctarray->getBase(); ct = ctarray->getBase();
push_integer(ctarray->numElements(),4,false, push_integer(ctarray->numElements(),4,false,syntax,
(const Varnode *)0,(const PcodeOp *)0); (const Varnode *)0,(const PcodeOp *)0);
} }
else if (ct->getMetatype()==TYPE_CODE) { else if (ct->getMetatype()==TYPE_CODE) {
@ -967,7 +967,7 @@ void PrintC::opPtrsub(const PcodeOp *op)
pushAtom(Atom(fieldname,fieldtoken,EmitMarkup::no_color,ct,fieldid,op)); pushAtom(Atom(fieldname,fieldtoken,EmitMarkup::no_color,ct,fieldid,op));
} }
if (arrayvalue) if (arrayvalue)
push_integer(0,4,false,(Varnode *)0,op); push_integer(0,4,false,syntax,(Varnode *)0,op);
} }
} }
else if (ct->getMetatype() == TYPE_SPACEBASE) { else if (ct->getMetatype() == TYPE_SPACEBASE) {
@ -1009,7 +1009,7 @@ void PrintC::opPtrsub(const PcodeOp *op)
} }
} }
if (arrayvalue) if (arrayvalue)
push_integer(0,4,false,(Varnode *)0,op); push_integer(0,4,false,syntax,(Varnode *)0,op);
} }
else if (ct->getMetatype() == TYPE_ARRAY) { else if (ct->getMetatype() == TYPE_ARRAY) {
if (in1const != 0) { if (in1const != 0) {
@ -1040,7 +1040,7 @@ void PrintC::opPtrsub(const PcodeOp *op)
if (ptrel != (TypePointerRel *)0) if (ptrel != (TypePointerRel *)0)
pushTypePointerRel(op); pushTypePointerRel(op);
pushVn(in0,op,m); pushVn(in0,op,m);
push_integer(0,4,false,(Varnode *)0,op); push_integer(0,4,false,syntax,(Varnode *)0,op);
} }
else { // EMIT (* )[0] else { // EMIT (* )[0]
pushOp(&subscript,op); pushOp(&subscript,op);
@ -1048,7 +1048,7 @@ void PrintC::opPtrsub(const PcodeOp *op)
if (ptrel != (TypePointerRel *)0) if (ptrel != (TypePointerRel *)0)
pushTypePointerRel(op); pushTypePointerRel(op);
pushVn(in0,op,m); pushVn(in0,op,m);
push_integer(0,4,false,(Varnode *)0,op); push_integer(0,4,false,syntax,(Varnode *)0,op);
} }
} }
} }
@ -1198,9 +1198,10 @@ void PrintC::opExtractOp(const PcodeOp *op)
/// \param val is the given integer value /// \param val is the given integer value
/// \param sz is the size (in bytes) to associate with the integer /// \param sz is the size (in bytes) to associate with the integer
/// \param sign is set to \b true if the integer should be treated as a signed value /// \param sign is set to \b true if the integer should be treated as a signed value
/// \param tag is the type of token to associate with the integer
/// \param vn is the Varnode holding the value /// \param vn is the Varnode holding the value
/// \param op is the PcodeOp using the value /// \param op is the PcodeOp using the value
void PrintC::push_integer(uintb val,int4 sz,bool sign, void PrintC::push_integer(uintb val,int4 sz,bool sign,tagtype tag,
const Varnode *vn,const PcodeOp *op) const Varnode *vn,const PcodeOp *op)
{ {
bool print_negsign; bool print_negsign;
@ -1279,10 +1280,7 @@ void PrintC::push_integer(uintb val,int4 sz,bool sign,
if (force_sized_token) if (force_sized_token)
t << sizeSuffix; t << sizeSuffix;
if (vn==(const Varnode *)0) pushAtom(Atom(t.str(),tag,EmitMarkup::const_color,op,vn,val));
pushAtom(Atom(t.str(),syntax,EmitMarkup::const_color,op));
else
pushAtom(Atom(t.str(),vartoken,EmitMarkup::const_color,op,vn));
} }
/// \brief Push a constant with a floating-point data-type to the RPN stack /// \brief Push a constant with a floating-point data-type to the RPN stack
@ -1292,9 +1290,10 @@ void PrintC::push_integer(uintb val,int4 sz,bool sign,
/// is decided upon, and the constant is pushed as a single token. /// is decided upon, and the constant is pushed as a single token.
/// \param val is the given encoded floating-point value /// \param val is the given encoded floating-point value
/// \param sz is the size (in bytes) of the encoded value /// \param sz is the size (in bytes) of the encoded value
/// \param tag is the type of token to associate with the float
/// \param vn is the Varnode holding the value /// \param vn is the Varnode holding the value
/// \param op is the PcodeOp using the value /// \param op is the PcodeOp using the value
void PrintC::push_float(uintb val,int4 sz,const Varnode *vn,const PcodeOp *op) void PrintC::push_float(uintb val,int4 sz,tagtype tag,const Varnode *vn,const PcodeOp *op)
{ {
string token; string token;
@ -1345,10 +1344,7 @@ void PrintC::push_float(uintb val,int4 sz,const Varnode *vn,const PcodeOp *op)
} }
} }
} }
if (vn==(const Varnode *)0) pushAtom(Atom(token,tag,EmitMarkup::const_color,op,vn,val));
pushAtom(Atom(token,syntax,EmitMarkup::const_color,op));
else
pushAtom(Atom(token,vartoken,EmitMarkup::const_color,op,vn));
} }
void PrintC::printUnicode(ostream &s,int4 onechar) const void PrintC::printUnicode(ostream &s,int4 onechar) const
@ -1410,16 +1406,16 @@ void PrintC::pushType(const Datatype *ct)
/// A single Atom representing the boolean value is emitted /// A single Atom representing the boolean value is emitted
/// \param val is the boolean value (non-zero for \b true) /// \param val is the boolean value (non-zero for \b true)
/// \param ct is the data-type associated with the value /// \param ct is the data-type associated with the value
/// \param tag is the type of token to associate with the boolean value
/// \param vn is the Varnode holding the value /// \param vn is the Varnode holding the value
/// \param op is the PcodeOp using the value /// \param op is the PcodeOp using the value
void PrintC::pushBoolConstant(uintb val,const TypeBase *ct, void PrintC::pushBoolConstant(uintb val,const TypeBase *ct,tagtype tag,
const Varnode *vn, const Varnode *vn,const PcodeOp *op)
const PcodeOp *op)
{ {
if (val != 0) if (val != 0)
pushAtom(Atom(KEYWORD_TRUE,vartoken,EmitMarkup::const_color,op,vn)); pushAtom(Atom(KEYWORD_TRUE,tag,EmitMarkup::const_color,op,vn,val));
else else
pushAtom(Atom(KEYWORD_FALSE,vartoken,EmitMarkup::const_color,op,vn)); pushAtom(Atom(KEYWORD_FALSE,tag,EmitMarkup::const_color,op,vn,val));
} }
/// \brief Return \b true if this language requires a prefix when expressing \e wide characters /// \brief Return \b true if this language requires a prefix when expressing \e wide characters
@ -1524,9 +1520,10 @@ void PrintC::resetDefaultsPrintC(void)
/// Handle unicode, wide characters, etc. Characters come in with the compiler's raw encoding. /// Handle unicode, wide characters, etc. Characters come in with the compiler's raw encoding.
/// \param val is the constant value /// \param val is the constant value
/// \param ct is data-type attached to the value /// \param ct is data-type attached to the value
/// \param tag is the type of token to associate with the character
/// \param vn is the Varnode holding the value /// \param vn is the Varnode holding the value
/// \param op is the PcodeOp using the value /// \param op is the PcodeOp using the value
void PrintC::pushCharConstant(uintb val,const Datatype *ct,const Varnode *vn,const PcodeOp *op) void PrintC::pushCharConstant(uintb val,const Datatype *ct,tagtype tag,const Varnode *vn,const PcodeOp *op)
{ {
uint4 displayFormat = 0; uint4 displayFormat = 0;
@ -1546,7 +1543,7 @@ void PrintC::pushCharConstant(uintb val,const Datatype *ct,const Varnode *vn,con
} }
if (displayFormat != 0 && displayFormat != Symbol::force_char) { if (displayFormat != 0 && displayFormat != Symbol::force_char) {
if (!castStrategy->caresAboutCharRepresentation(vn, op)) { if (!castStrategy->caresAboutCharRepresentation(vn, op)) {
push_integer(val, ct->getSize(), isSigned, vn, op); push_integer(val, ct->getSize(), isSigned, tag, vn, op);
return; return;
} }
} }
@ -1556,7 +1553,7 @@ void PrintC::pushCharConstant(uintb val,const Datatype *ct,const Varnode *vn,con
// unicode code-point. Its either part of a multi-byte UTF-8 encoding or an unknown // unicode code-point. Its either part of a multi-byte UTF-8 encoding or an unknown
// code-page value. In either case, we print as an integer or an escape sequence. // code-page value. In either case, we print as an integer or an escape sequence.
if (displayFormat != Symbol::force_hex && displayFormat != Symbol::force_char) { if (displayFormat != Symbol::force_hex && displayFormat != Symbol::force_char) {
push_integer(val, 1, isSigned, vn, op); push_integer(val, 1, isSigned, tag, vn, op);
return; return;
} }
displayFormat = Symbol::force_hex; // Fallthru but force a hex representation displayFormat = Symbol::force_hex; // Fallthru but force a hex representation
@ -1574,7 +1571,7 @@ void PrintC::pushCharConstant(uintb val,const Datatype *ct,const Varnode *vn,con
else else
printUnicode(t,(int4)val); printUnicode(t,(int4)val);
t << '\''; t << '\'';
pushAtom(Atom(t.str(),vartoken,EmitMarkup::const_color,op,vn)); pushAtom(Atom(t.str(),tag,EmitMarkup::const_color,op,vn,val));
} }
/// \brief Push an enumerated value to the RPN stack /// \brief Push an enumerated value to the RPN stack
@ -1583,11 +1580,11 @@ void PrintC::pushCharConstant(uintb val,const Datatype *ct,const Varnode *vn,con
/// enumeration or where the value cannot be expressed using named elements /// enumeration or where the value cannot be expressed using named elements
/// \param val is the enumerated value being pushed /// \param val is the enumerated value being pushed
/// \param ct is the enumerated data-type attached to the value /// \param ct is the enumerated data-type attached to the value
/// \param tag is the type of token to associate with the value
/// \param vn is the Varnode holding the value /// \param vn is the Varnode holding the value
/// \param op is the PcodeOp using the value /// \param op is the PcodeOp using the value
void PrintC::pushEnumConstant(uintb val,const TypeEnum *ct, void PrintC::pushEnumConstant(uintb val,const TypeEnum *ct,tagtype tag,
const Varnode *vn, const Varnode *vn,const PcodeOp *op)
const PcodeOp *op)
{ {
vector<string> valnames; vector<string> valnames;
@ -1598,10 +1595,10 @@ void PrintC::pushEnumConstant(uintb val,const TypeEnum *ct,
for(int4 i=valnames.size()-1;i>0;--i) for(int4 i=valnames.size()-1;i>0;--i)
pushOp(&enum_cat,op); pushOp(&enum_cat,op);
for(int4 i=0;i<valnames.size();++i) for(int4 i=0;i<valnames.size();++i)
pushAtom(Atom(valnames[i],vartoken,EmitMarkup::const_color,op,vn)); pushAtom(Atom(valnames[i],tag,EmitMarkup::const_color,op,vn,val));
} }
else { else {
push_integer(val,ct->getSize(),false,vn,op); push_integer(val,ct->getSize(),false,tag,vn,op);
// ostringstream s; // ostringstream s;
// s << "BAD_ENUM(0x" << hex << val << ")"; // s << "BAD_ENUM(0x" << hex << val << ")";
// pushAtom(Atom(s.str(),vartoken,EmitMarkup::const_color,op,vn)); // pushAtom(Atom(s.str(),vartoken,EmitMarkup::const_color,op,vn));
@ -1650,8 +1647,7 @@ bool PrintC::pushPtrCharConstant(uintb val,const TypePointer *ct,const Varnode *
/// \param op is the PcodeOp using the value /// \param op is the PcodeOp using the value
/// \return \b true if a name was pushed to the RPN stack, return \b false otherwise /// \return \b true if a name was pushed to the RPN stack, return \b false otherwise
bool PrintC::pushPtrCodeConstant(uintb val,const TypePointer *ct, bool PrintC::pushPtrCodeConstant(uintb val,const TypePointer *ct,
const Varnode *vn, const Varnode *vn,const PcodeOp *op)
const PcodeOp *op)
{ {
AddrSpace *spc = glb->getDefaultCodeSpace(); AddrSpace *spc = glb->getDefaultCodeSpace();
Funcdata *fd = (Funcdata *)0; Funcdata *fd = (Funcdata *)0;
@ -1664,7 +1660,7 @@ bool PrintC::pushPtrCodeConstant(uintb val,const TypePointer *ct,
return false; return false;
} }
void PrintC::pushConstant(uintb val,const Datatype *ct, void PrintC::pushConstant(uintb val,const Datatype *ct,tagtype tag,
const Varnode *vn, const Varnode *vn,
const PcodeOp *op) const PcodeOp *op)
{ {
@ -1672,25 +1668,25 @@ void PrintC::pushConstant(uintb val,const Datatype *ct,
switch(ct->getMetatype()) { switch(ct->getMetatype()) {
case TYPE_UINT: case TYPE_UINT:
if (ct->isCharPrint()) if (ct->isCharPrint())
pushCharConstant(val,(TypeChar *)ct,vn,op); pushCharConstant(val,(TypeChar *)ct,tag,vn,op);
else if (ct->isEnumType()) else if (ct->isEnumType())
pushEnumConstant(val,(TypeEnum *)ct,vn,op); pushEnumConstant(val,(TypeEnum *)ct,tag,vn,op);
else else
push_integer(val,ct->getSize(),false,vn,op); push_integer(val,ct->getSize(),false,tag,vn,op);
return; return;
case TYPE_INT: case TYPE_INT:
if (ct->isCharPrint()) if (ct->isCharPrint())
pushCharConstant(val,(TypeChar *)ct,vn,op); pushCharConstant(val,(TypeChar *)ct,tag,vn,op);
else if (ct->isEnumType()) else if (ct->isEnumType())
pushEnumConstant(val,(TypeEnum *)ct,vn,op); pushEnumConstant(val,(TypeEnum *)ct,tag,vn,op);
else else
push_integer(val,ct->getSize(),true,vn,op); push_integer(val,ct->getSize(),true,tag,vn,op);
return; return;
case TYPE_UNKNOWN: case TYPE_UNKNOWN:
push_integer(val,ct->getSize(),false,vn,op); push_integer(val,ct->getSize(),false,tag,vn,op);
return; return;
case TYPE_BOOL: case TYPE_BOOL:
pushBoolConstant(val,(const TypeBase *)ct,vn,op); pushBoolConstant(val,(const TypeBase *)ct,tag,vn,op);
return; return;
case TYPE_VOID: case TYPE_VOID:
clear(); clear();
@ -1712,7 +1708,7 @@ void PrintC::pushConstant(uintb val,const Datatype *ct,
} }
break; break;
case TYPE_FLOAT: case TYPE_FLOAT:
push_float(val,ct->getSize(),vn,op); push_float(val,ct->getSize(),tag,vn,op);
return; return;
case TYPE_SPACEBASE: case TYPE_SPACEBASE:
case TYPE_CODE: case TYPE_CODE:
@ -1731,7 +1727,7 @@ void PrintC::pushConstant(uintb val,const Datatype *ct,
pushMod(); pushMod();
if (!isSet(force_dec)) if (!isSet(force_dec))
setMod(force_hex); setMod(force_hex);
push_integer(val,ct->getSize(),false,vn,op); push_integer(val,ct->getSize(),false,tag,vn,op);
popMod(); popMod();
} }
@ -1765,14 +1761,14 @@ bool PrintC::pushEquate(uintb val,int4 sz,const EquateSymbol *sym,const Varnode
if (modval == val) { if (modval == val) {
pushOp(&binary_plus,(const PcodeOp *)0); pushOp(&binary_plus,(const PcodeOp *)0);
pushSymbol(sym,vn,op); pushSymbol(sym,vn,op);
push_integer(1, sz, false, (const Varnode *)0, (const PcodeOp *)0); push_integer(1, sz, false, syntax, (const Varnode *)0, (const PcodeOp *)0);
return true; return true;
} }
modval = (baseval - 1) & mask; modval = (baseval - 1) & mask;
if (modval == val) { if (modval == val) {
pushOp(&binary_minus,(const PcodeOp *)0); pushOp(&binary_minus,(const PcodeOp *)0);
pushSymbol(sym,vn,op); pushSymbol(sym,vn,op);
push_integer(1, sz, false, (const Varnode *)0, (const PcodeOp *)0); push_integer(1, sz, false, syntax, (const Varnode *)0, (const PcodeOp *)0);
return true; return true;
} }
return false; return false;
@ -2092,8 +2088,7 @@ void PrintC::emitEnumDefinition(const TypeEnum *ct)
emit->spaces(1); emit->spaces(1);
emit->print(EQUALSIGN,EmitMarkup::no_color); emit->print(EQUALSIGN,EmitMarkup::no_color);
emit->spaces(1); emit->spaces(1);
push_integer((*iter).first,ct->getSize(),sign,(Varnode *)0, push_integer((*iter).first,ct->getSize(),sign,syntax,(Varnode *)0,(PcodeOp *)0);
(PcodeOp *)0);
recurse(); recurse();
emit->print(SEMICOLON); emit->print(SEMICOLON);
++iter; ++iter;
@ -3087,12 +3082,15 @@ void PrintC::emitSwitchCase(int4 casenum,const BlockSwitch *switchbl)
int4 i,num; int4 i,num;
uintb val; uintb val;
const Datatype *ct; const Datatype *ct;
const PcodeOp *op;
ct = switchbl->getSwitchType(); ct = switchbl->getSwitchType();
op = switchbl->getCaseBlock(casenum)->firstOp();
if (switchbl->isDefaultCase(casenum)) { if (switchbl->isDefaultCase(casenum)) {
val = switchbl->getLabel(casenum,0);
emit->tagLine(); emit->tagLine();
emit->print(KEYWORD_DEFAULT,EmitMarkup::keyword_color); emit->tagCaseLabel(KEYWORD_DEFAULT, EmitMarkup::keyword_color, op, val);
emit->print(COLON); emit->print(COLON);
} }
else { else {
@ -3102,7 +3100,7 @@ void PrintC::emitSwitchCase(int4 casenum,const BlockSwitch *switchbl)
emit->tagLine(); emit->tagLine();
emit->print(KEYWORD_CASE,EmitMarkup::keyword_color); emit->print(KEYWORD_CASE,EmitMarkup::keyword_color);
emit->spaces(1); emit->spaces(1);
pushConstant(val,ct,(Varnode *)0,(PcodeOp *)0); pushConstant(val,ct,casetoken,(Varnode *)0,op);
recurse(); recurse();
emit->print(COLON); emit->print(COLON);
} }

View file

@ -159,11 +159,11 @@ protected:
void emitSymbolScope(const Symbol *symbol); ///< Emit tokens resolving a symbol's scope void emitSymbolScope(const Symbol *symbol); ///< Emit tokens resolving a symbol's scope
virtual void pushTypeStart(const Datatype *ct,bool noident); ///< Push part of a data-type declaration onto the RPN stack, up to the identifier virtual void pushTypeStart(const Datatype *ct,bool noident); ///< Push part of a data-type declaration onto the RPN stack, up to the identifier
virtual void pushTypeEnd(const Datatype *ct); ///< Push the tail ends of a data-type declaration onto the RPN stack virtual void pushTypeEnd(const Datatype *ct); ///< Push the tail ends of a data-type declaration onto the RPN stack
void pushBoolConstant(uintb val,const TypeBase *ct,const Varnode *vn, void pushBoolConstant(uintb val,const TypeBase *ct,tagtype tag,const Varnode *vn,
const PcodeOp *op); const PcodeOp *op);
void pushCharConstant(uintb val,const Datatype *ct,const Varnode *vn, void pushCharConstant(uintb val,const Datatype *ct,tagtype tag,const Varnode *vn,
const PcodeOp *op); const PcodeOp *op);
void pushEnumConstant(uintb val,const TypeEnum *ct,const Varnode *vn, void pushEnumConstant(uintb val,const TypeEnum *ct,tagtype tag,const Varnode *vn,
const PcodeOp *op); const PcodeOp *op);
virtual bool pushPtrCharConstant(uintb val,const TypePointer *ct,const Varnode *vn, virtual bool pushPtrCharConstant(uintb val,const TypePointer *ct,const Varnode *vn,
const PcodeOp *op); const PcodeOp *op);
@ -196,7 +196,7 @@ protected:
bool printCharacterConstant(ostream &s,const Address &addr,Datatype *charType) const; bool printCharacterConstant(ostream &s,const Address &addr,Datatype *charType) const;
int4 getHiddenThisSlot(const PcodeOp *op,FuncProto *fc); ///< Get position of "this" pointer needing to be hidden int4 getHiddenThisSlot(const PcodeOp *op,FuncProto *fc); ///< Get position of "this" pointer needing to be hidden
void resetDefaultsPrintC(void); ///< Set default values for options specific to PrintC void resetDefaultsPrintC(void); ///< Set default values for options specific to PrintC
virtual void pushConstant(uintb val,const Datatype *ct, virtual void pushConstant(uintb val,const Datatype *ct,tagtype tag,
const Varnode *vn,const PcodeOp *op); const Varnode *vn,const PcodeOp *op);
virtual bool pushEquate(uintb val,int4 sz,const EquateSymbol *sym, virtual bool pushEquate(uintb val,int4 sz,const EquateSymbol *sym,
const Varnode *vn,const PcodeOp *op); const Varnode *vn,const PcodeOp *op);
@ -209,10 +209,10 @@ protected:
virtual void pushMismatchSymbol(const Symbol *sym,int4 off,int4 sz, virtual void pushMismatchSymbol(const Symbol *sym,int4 off,int4 sz,
const Varnode *vn,const PcodeOp *op); const Varnode *vn,const PcodeOp *op);
virtual void pushImpliedField(const Varnode *vn,const PcodeOp *op); virtual void pushImpliedField(const Varnode *vn,const PcodeOp *op);
virtual void push_integer(uintb val,int4 sz,bool sign, virtual void push_integer(uintb val,int4 sz,bool sign,tagtype tag,
const Varnode *vn, const Varnode *vn,
const PcodeOp *op); const PcodeOp *op);
virtual void push_float(uintb val,int4 sz,const Varnode *vn, virtual void push_float(uintb val,int4 sz,tagtype tag,const Varnode *vn,
const PcodeOp *op); const PcodeOp *op);
virtual void printUnicode(ostream &s,int4 onechar) const; virtual void printUnicode(ostream &s,int4 onechar) const;
virtual void pushType(const Datatype *ct); virtual void pushType(const Datatype *ct);

View file

@ -234,7 +234,7 @@ void PrintJava::opLoad(const PcodeOp *op)
pushOp(&subscript,op); pushOp(&subscript,op);
pushVn(op->getIn(1),op,m); pushVn(op->getIn(1),op,m);
if (printArrayRef) if (printArrayRef)
push_integer(0,4,false,(Varnode *)0,op); push_integer(0,4,false,syntax,(Varnode *)0,op);
} }
void PrintJava::opStore(const PcodeOp *op) void PrintJava::opStore(const PcodeOp *op)
@ -245,7 +245,7 @@ void PrintJava::opStore(const PcodeOp *op)
if (needZeroArray(op->getIn(1))) { if (needZeroArray(op->getIn(1))) {
pushOp(&subscript,op); pushOp(&subscript,op);
pushVn(op->getIn(1),op,m); pushVn(op->getIn(1),op,m);
push_integer(0,4,false,(Varnode *)0,op); push_integer(0,4,false,syntax,(Varnode *)0,op);
pushVn(op->getIn(2),op,mods); pushVn(op->getIn(2),op,mods);
} }
else { else {

View file

@ -223,7 +223,7 @@ void PrintLanguage::pushVnExplicit(const Varnode *vn,const PcodeOp *op)
return; return;
} }
if (vn->isConstant()) { if (vn->isConstant()) {
pushConstant(vn->getOffset(),vn->getHighTypeReadFacing(op),vn,op); pushConstant(vn->getOffset(),vn->getHighTypeReadFacing(op),vartoken,vn,op);
return; return;
} }
pushSymbolDetail(vn,op,true); pushSymbolDetail(vn,op,true);
@ -394,6 +394,9 @@ void PrintLanguage::emitAtom(const Atom &atom)
case fieldtoken: case fieldtoken:
emit->tagField(atom.name,atom.highlight,atom.ptr_second.ct,atom.offset,atom.op); emit->tagField(atom.name,atom.highlight,atom.ptr_second.ct,atom.offset,atom.op);
break; break;
case casetoken:
emit->tagCaseLabel(atom.name, atom.highlight, atom.op, atom.ptr_second.intValue);
break;
case blanktoken: case blanktoken:
break; // Print nothing break; // Print nothing
} }

View file

@ -167,6 +167,7 @@ public:
optoken, ///< Emit atom as operator optoken, ///< Emit atom as operator
typetoken, ///< Emit atom as operator typetoken, ///< Emit atom as operator
fieldtoken, ///< Emit atom as structure field fieldtoken, ///< Emit atom as structure field
casetoken, ///< Emit atom as a \e case label
blanktoken ///< For anonymous types blanktoken ///< For anonymous types
}; };
@ -215,6 +216,7 @@ public:
const Varnode *vn; ///< A Varnode associated with the token const Varnode *vn; ///< A Varnode associated with the token
const Funcdata *fd; ///< A function associated with the token const Funcdata *fd; ///< A function associated with the token
const Datatype *ct; ///< A type associated with the token const Datatype *ct; ///< A type associated with the token
uintb intValue; ///< An integer value associated with the token
} ptr_second; ///< Other meta-data associated with the token } ptr_second; ///< Other meta-data associated with the token
int4 offset; ///< The offset (within the parent structure) for a \e field token int4 offset; ///< The offset (within the parent structure) for a \e field token
@ -241,6 +243,19 @@ public:
/// \brief Construct a token for a function name /// \brief Construct a token for a function name
Atom(const string &nm,tagtype t,EmitMarkup::syntax_highlight hl,const PcodeOp *o,const Funcdata *f) Atom(const string &nm,tagtype t,EmitMarkup::syntax_highlight hl,const PcodeOp *o,const Funcdata *f)
: name(nm) { type=t; highlight = hl; op = o; ptr_second.fd = f; } : name(nm) { type=t; highlight = hl; op = o; ptr_second.fd = f; }
/// \brief Construct a token with an associated PcodeOp, Varnode, and constant value
Atom(const string &nm,tagtype t,EmitMarkup::syntax_highlight hl,const PcodeOp *o,const Varnode *v,uintb intValue)
: name(nm) {
type=t;
highlight = hl;
if (t==casetoken)
ptr_second.intValue = intValue;
else
ptr_second.vn = v;
op = o;
}
}; };
private: private:
string name; ///< The name of the high-level language string name; ///< The name of the high-level language
@ -308,9 +323,10 @@ protected:
/// The value is ultimately emitted based on its data-type and other associated mark-up /// The value is ultimately emitted based on its data-type and other associated mark-up
/// \param val is the value of the constant /// \param val is the value of the constant
/// \param ct is the data-type of the constant /// \param ct is the data-type of the constant
/// \param tag is the type of token associated with the constant
/// \param vn is the Varnode holding the constant (optional) /// \param vn is the Varnode holding the constant (optional)
/// \param op is the PcodeOp using the constant (optional) /// \param op is the PcodeOp using the constant (optional)
virtual void pushConstant(uintb val,const Datatype *ct, virtual void pushConstant(uintb val,const Datatype *ct,tagtype tag,
const Varnode *vn,const PcodeOp *op)=0; const Varnode *vn,const PcodeOp *op)=0;
/// \brief Push a constant marked up by and EquateSymbol onto the RPN stack /// \brief Push a constant marked up by and EquateSymbol onto the RPN stack

View file

@ -0,0 +1,151 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.decompiler;
import ghidra.program.model.address.Address;
import ghidra.program.model.data.AbstractIntegerDataType;
import ghidra.program.model.data.DataType;
import ghidra.program.model.pcode.*;
import ghidra.program.model.scalar.Scalar;
/**
* A token representing a switch "case" label, or other constant not directly linked to data-flow.
* The token has an associated constant value and a data-type
*/
public class ClangCaseToken extends ClangToken {
private PcodeOp op; // Op associated with the start of the "case"
private long value; // The constant value
public ClangCaseToken(ClangNode par) {
super(par);
op = null;
value = 0;
}
@Override
public boolean isVariableRef() {
return true;
}
@Override
public Address getMinAddress() {
if (op == null) {
return null;
}
return op.getSeqnum().getTarget();
}
@Override
public Address getMaxAddress() {
if (op == null) {
return null;
}
return op.getSeqnum().getTarget();
}
@Override
public Varnode getVarnode() {
PcodeOp switchOp = getSwitchOp();
if (switchOp == null) {
return null;
}
return switchOp.getInput(0);
}
@Override
public PcodeOp getPcodeOp() {
return op;
}
@Override
public HighVariable getHighVariable() {
Varnode vn = getVarnode();
if (vn == null) {
return null;
}
return vn.getHigh();
}
@Override
public HighSymbol getHighSymbol(HighFunction highFunction) {
HighVariable hvar = getHighVariable();
if (hvar != null) {
HighSymbol symbol = hvar.getSymbol();
if (symbol != null) {
return symbol;
}
}
return null;
}
@Override
public Scalar getScalar() {
HighVariable hvar = getHighVariable();
if (hvar == null) {
return null;
}
DataType dt = hvar.getDataType();
int sz = dt.getLength();
if (sz < 1 || sz > 8) {
return null;
}
boolean isSigned = true;
if (dt instanceof AbstractIntegerDataType) {
isSigned = ((AbstractIntegerDataType) dt).isSigned();
}
return new Scalar(sz * 8, value, isSigned);
}
/**
* @return the BRANCHIND PcodeOp that jumps to this label
*/
public PcodeOp getSwitchOp() {
if (op == null) {
return null;
}
PcodeBlockBasic parent = op.getParent();
for (int i = 0; i < parent.getInSize(); ++i) {
PcodeBlockBasic in = (PcodeBlockBasic) parent.getIn(i);
PcodeOp switchOp = in.getLastOp();
if (switchOp != null && switchOp.getOpcode() == PcodeOp.BRANCHIND) {
return switchOp;
}
}
return null;
}
@Override
public void decode(Decoder decoder, PcodeFactory pfactory) throws DecoderException {
for (;;) {
int attribId = decoder.getNextAttributeId();
if (attribId == 0) {
break;
}
else if (attribId == AttributeId.ATTRIB_OPREF.id()) {
int refid = (int) decoder.readUnsignedInteger();
op = pfactory.getOpRef(refid);
}
else if (attribId == AttributeId.ATTRIB_OFF.id()) {
value = decoder.readUnsignedInteger();
}
}
decoder.rewindAttributes();
super.decode(decoder, pfactory);
}
}

View file

@ -24,6 +24,7 @@ import java.util.List;
//import ghidra.app.plugin.core.decompile.*; //import ghidra.app.plugin.core.decompile.*;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.pcode.*; import ghidra.program.model.pcode.*;
import ghidra.program.model.scalar.Scalar;
/** /**
* Class representing a source code language token. * Class representing a source code language token.
@ -257,6 +258,9 @@ public class ClangToken implements ClangNode {
else if (node == ELEM_FIELD.id()) { else if (node == ELEM_FIELD.id()) {
token = new ClangFieldToken(par); token = new ClangFieldToken(par);
} }
else if (node == ELEM_VALUE.id()) {
token = new ClangCaseToken(par);
}
else { else {
throw new DecoderException("Expecting token element"); throw new DecoderException("Expecting token element");
} }
@ -319,4 +323,13 @@ public class ClangToken implements ClangNode {
public PcodeOp getPcodeOp() { public PcodeOp getPcodeOp() {
return null; return null;
} }
/**
* If the token represents an underlying integer constant, return the constant as a Scalar.
* Otherwise return null.
* @return the Scalar that the token represents or null
*/
public Scalar getScalar() {
return null;
}
} }

View file

@ -17,7 +17,10 @@ package ghidra.app.decompiler;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressFactory; import ghidra.program.model.address.AddressFactory;
import ghidra.program.model.data.AbstractIntegerDataType;
import ghidra.program.model.data.DataType;
import ghidra.program.model.pcode.*; import ghidra.program.model.pcode.*;
import ghidra.program.model.scalar.Scalar;
/** /**
* *
@ -44,6 +47,34 @@ public class ClangVariableToken extends ClangToken {
return op; return op;
} }
@Override
public Scalar getScalar() {
if (varnode == null) {
return null;
}
long offset = varnode.getOffset();
int sz = varnode.getSize();
HighVariable high = varnode.getHigh();
if (!(high instanceof HighConstant)) {
return null;
}
HighConstant constant = (HighConstant) high;
boolean isSigned = true;
DataType dt = constant.getDataType();
if (dt instanceof AbstractIntegerDataType) {
isSigned = ((AbstractIntegerDataType) dt).isSigned();
}
if (sz > 8) {
// our Scalar can currently only handle long values
return null;
}
return new Scalar(sz * 8, offset, isSigned);
}
@Override @Override
public boolean isVariableRef() { public boolean isVariableRef() {
return true; return true;

View file

@ -21,15 +21,11 @@ import docking.widgets.fieldpanel.field.Field;
import docking.widgets.fieldpanel.support.FieldLocation; import docking.widgets.fieldpanel.support.FieldLocation;
import ghidra.GhidraOptions; import ghidra.GhidraOptions;
import ghidra.app.decompiler.ClangToken; import ghidra.app.decompiler.ClangToken;
import ghidra.app.decompiler.ClangVariableToken;
import ghidra.app.decompiler.component.ClangTextField; import ghidra.app.decompiler.component.ClangTextField;
import ghidra.app.plugin.core.hover.AbstractScalarOperandHover; import ghidra.app.plugin.core.hover.AbstractScalarOperandHover;
import ghidra.framework.plugintool.PluginTool; import ghidra.framework.plugintool.PluginTool;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.data.AbstractIntegerDataType;
import ghidra.program.model.data.DataType;
import ghidra.program.model.listing.Program; import ghidra.program.model.listing.Program;
import ghidra.program.model.pcode.*;
import ghidra.program.model.scalar.Scalar; import ghidra.program.model.scalar.Scalar;
import ghidra.program.util.ProgramLocation; import ghidra.program.util.ProgramLocation;
@ -82,35 +78,10 @@ public class ScalarValueDecompilerHover extends AbstractScalarOperandHover
} }
ClangToken token = ((ClangTextField) field).getToken(fieldLocation); ClangToken token = ((ClangTextField) field).getToken(fieldLocation);
if (!(token instanceof ClangVariableToken)) { Scalar scalar = token.getScalar();
if (scalar == null) {
return null; return null;
} }
Varnode vn = ((ClangVariableToken) token).getVarnode();
if (vn == null) {
return null;
}
long offset = vn.getOffset();
int sz = vn.getSize();
HighVariable high = vn.getHigh();
if (!(high instanceof HighConstant)) {
return null;
}
HighConstant constant = (HighConstant) high;
boolean isSigned = true;
DataType dt = constant.getDataType();
if (dt instanceof AbstractIntegerDataType) {
isSigned = ((AbstractIntegerDataType) dt).isSigned();
}
if (sz > 8) {
// our Scalar can currently only handle long values
return null;
}
Scalar scalar = new Scalar(sz * 8, offset, isSigned);
Address addr = token.getMinAddress(); Address addr = token.getMinAddress();
String formatted = formatScalar(program, addr, scalar); String formatted = formatScalar(program, addr, scalar);
return createTooltipComponent(formatted); return createTooltipComponent(formatted);

View file

@ -1,6 +1,5 @@
/* ### /* ###
* IP: GHIDRA * IP: GHIDRA
* REVIEWED: YES
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -17,6 +16,7 @@
package ghidra.program.model.pcode; package ghidra.program.model.pcode;
import java.util.Iterator; import java.util.Iterator;
/** /**
* *
* *
@ -46,26 +46,22 @@ public class ListLinked<T> {
curNode = cur; curNode = cur;
} }
/* (non-Javadoc) @Override
* @see java.util.Iterator#remove()
*/
public void remove() { public void remove() {
if (curNode.data == null) return; // Should probably throw an exception here if (curNode.data == null) {
return; // Should probably throw an exception here
}
curNode.nextNode.previousNode = curNode.previousNode; curNode.nextNode.previousNode = curNode.previousNode;
curNode.previousNode.nextNode = curNode.nextNode; curNode.previousNode.nextNode = curNode.nextNode;
curNode = curNode.previousNode; curNode = curNode.previousNode;
} }
/* (non-Javadoc) @Override
* @see java.util.Iterator#hasNext()
*/
public boolean hasNext() { public boolean hasNext() {
return (curNode.nextNode.data != null); return (curNode.nextNode.data != null);
} }
/* (non-Javadoc) @Override
* @see java.util.Iterator#next()
*/
public T next() { public T next() {
curNode = curNode.nextNode; curNode = curNode.nextNode;
return curNode.data; return curNode.data;
@ -141,7 +137,9 @@ public class ListLinked<T> {
*/ */
public void remove(Iterator<T> itr) { public void remove(Iterator<T> itr) {
LinkedNode cur = ((LinkedIterator) itr).curNode; LinkedNode cur = ((LinkedIterator) itr).curNode;
if (cur.data == null) return; // Should probably throw an exception here if (cur.data == null) {
return; // Should probably throw an exception here
}
cur.previousNode.nextNode = cur.nextNode; cur.previousNode.nextNode = cur.nextNode;
cur.nextNode.previousNode = cur.previousNode; cur.nextNode.previousNode = cur.previousNode;
} }
@ -162,4 +160,17 @@ public class ListLinked<T> {
terminal.previousNode = terminal; // Recreate empty list terminal.previousNode = terminal; // Recreate empty list
} }
/**
* @return the first element in the list (or null)
*/
public T first() {
return terminal.nextNode.data;
}
/**
* @return the last element in the list (or null)
*/
public T last() {
return terminal.previousNode.data;
}
} }

View file

@ -118,10 +118,8 @@ public class PcodeBlockBasic extends PcodeBlock {
AddressRange range = iter.next(); AddressRange range = iter.next();
encoder.openElement(ELEM_RANGE); encoder.openElement(ELEM_RANGE);
encoder.writeSpace(ATTRIB_SPACE, range.getAddressSpace()); encoder.writeSpace(ATTRIB_SPACE, range.getAddressSpace());
encoder.writeUnsignedInteger(ATTRIB_FIRST, encoder.writeUnsignedInteger(ATTRIB_FIRST, range.getMinAddress().getOffset());
range.getMinAddress().getOffset()); encoder.writeUnsignedInteger(ATTRIB_LAST, range.getMaxAddress().getOffset());
encoder.writeUnsignedInteger(ATTRIB_LAST,
range.getMaxAddress().getOffset());
} }
encoder.closeElement(ELEM_RANGELIST); encoder.closeElement(ELEM_RANGELIST);
} }
@ -146,4 +144,18 @@ public class PcodeBlockBasic extends PcodeBlock {
decoder.closeElement(rangelistel); decoder.closeElement(rangelistel);
} }
/**
* @return the first PcodeOp in this block (or null if the block is empty)
*/
public PcodeOp getFirstOp() {
return oplist.first();
}
/**
* @return the last PcodeOp in this block (or null if the block is empty)
*/
public PcodeOp getLastOp() {
return oplist.last();
}
} }