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);
}
PcodeOp *BlockGraph::firstOp(void) const
{
if (getSize() == 0)
return (PcodeOp *)0;
return getBlock(0)->firstOp();
}
FlowBlock *BlockGraph::nextFlowAfter(const FlowBlock *bl) const
{
@ -2255,6 +2263,13 @@ Address BlockBasic::getStop(void) const
return range->getLastAddr();
}
PcodeOp *BlockBasic::firstOp(void) const
{
if (op.empty()) return (PcodeOp *)0;
return (PcodeOp *)op.front();
}
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 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 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 bool negateCondition(bool toporbottom); ///< Flip the condition computed by \b this
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 printRaw(ostream &s) const;
virtual void emit(PrintLanguage *lng) const { lng->emitBlockGraph(this); }
virtual PcodeOp *firstOp(void) const;
virtual FlowBlock *nextFlowAfter(const FlowBlock *bl) const;
virtual void finalTransform(Funcdata &data);
virtual void finalizePrinting(Funcdata &data) const;
@ -400,6 +402,7 @@ public:
virtual void printRaw(ostream &s) const;
virtual void emit(PrintLanguage *lng) const { lng->emitBlockBasic(this); }
virtual const FlowBlock *getExitLeaf(void) const { return this; }
virtual PcodeOp *firstOp(void) const;
virtual PcodeOp *lastOp(void) const;
virtual bool negateCondition(bool toporbottom);
virtual FlowBlock *getSplitPoint(void);
@ -440,6 +443,7 @@ public:
virtual void printRaw(ostream &s) const { copy->printRaw(s); }
virtual void emit(PrintLanguage *lng) const { lng->emitBlockCopy(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 bool negateCondition(bool toporbottom) { bool res = copy->negateCondition(true); FlowBlock::negateCondition(toporbottom); return res; }
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);
}
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)
{
@ -357,6 +370,9 @@ void TokenSplit::print(Emit *emit) const
case label_t: // tagLabel
emit->tagLabel(tok,hl,ptr_second.spc,off);
break;
case case_t: // tagCaseLabel
emit->tagCaseLabel(tok, hl, op, off);
break;
case synt_t: // print
emit->print(tok,hl);
break;
@ -448,6 +464,9 @@ void TokenSplit::printDebug(ostream &s) const
case label_t: // tagLabel
s << "label_t";
break;
case case_t: // tagCaseLabel
s << "case_t";
break;
case synt_t: // print
s << "synt_t";
break;
@ -1011,6 +1030,15 @@ void EmitPrettyPrint::tagLabel(const string &name,syntax_highlight hl,const Addr
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)
{

View file

@ -292,6 +292,15 @@ public:
/// \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;
/// \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
///
/// 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 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 tagCaseLabel(const string &name,syntax_highlight hl,const PcodeOp *op,uintb value);
virtual void print(const string &data,syntax_highlight hl=no_color);
virtual int4 openParen(const string &paren,int4 id=0);
virtual void closeParen(const string &paren,int4 id);
@ -522,6 +532,8 @@ public:
*s << name; }
virtual void tagLabel(const string &name,syntax_highlight hl,const AddrSpace *spc,uintb off) {
*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) {
*s << data; }
virtual int4 openParen(const string &paren,int4 id=0) {
@ -584,6 +596,7 @@ public:
field_t, ///< A field name for a structured data-type
comm_t, ///< Part of a comment block
label_t, ///< A code label
case_t, ///< A case label
synt_t, ///< Other unspecified syntax
opar_t, ///< Open parenthesis
cpar_t, ///< Close parenthesis
@ -774,6 +787,16 @@ public:
tok = name; size = tok.size(); ptr_second.spc=s; off=o;
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
///
/// \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 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 tagCaseLabel(const string &name,syntax_highlight hl,const PcodeOp *op,uintb value);
virtual void print(const string &data,syntax_highlight hl=no_color);
virtual int4 openParen(const string &paren,int4 id=0);
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) {
const TypeArray *ctarray = (const TypeArray *)ct;
ct = ctarray->getBase();
push_integer(ctarray->numElements(),4,false,
push_integer(ctarray->numElements(),4,false,syntax,
(const Varnode *)0,(const PcodeOp *)0);
}
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));
}
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) {
@ -1009,7 +1009,7 @@ void PrintC::opPtrsub(const PcodeOp *op)
}
}
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) {
if (in1const != 0) {
@ -1040,7 +1040,7 @@ void PrintC::opPtrsub(const PcodeOp *op)
if (ptrel != (TypePointerRel *)0)
pushTypePointerRel(op);
pushVn(in0,op,m);
push_integer(0,4,false,(Varnode *)0,op);
push_integer(0,4,false,syntax,(Varnode *)0,op);
}
else { // EMIT (* )[0]
pushOp(&subscript,op);
@ -1048,7 +1048,7 @@ void PrintC::opPtrsub(const PcodeOp *op)
if (ptrel != (TypePointerRel *)0)
pushTypePointerRel(op);
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 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 tag is the type of token to associate with the integer
/// \param vn is the Varnode holding 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)
{
bool print_negsign;
@ -1279,10 +1280,7 @@ void PrintC::push_integer(uintb val,int4 sz,bool sign,
if (force_sized_token)
t << sizeSuffix;
if (vn==(const Varnode *)0)
pushAtom(Atom(t.str(),syntax,EmitMarkup::const_color,op));
else
pushAtom(Atom(t.str(),vartoken,EmitMarkup::const_color,op,vn));
pushAtom(Atom(t.str(),tag,EmitMarkup::const_color,op,vn,val));
}
/// \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.
/// \param val is the given encoded floating-point 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 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;
@ -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,syntax,EmitMarkup::const_color,op));
else
pushAtom(Atom(token,vartoken,EmitMarkup::const_color,op,vn));
pushAtom(Atom(token,tag,EmitMarkup::const_color,op,vn,val));
}
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
/// \param val is the boolean value (non-zero for \b true)
/// \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 op is the PcodeOp using the value
void PrintC::pushBoolConstant(uintb val,const TypeBase *ct,
const Varnode *vn,
const PcodeOp *op)
void PrintC::pushBoolConstant(uintb val,const TypeBase *ct,tagtype tag,
const Varnode *vn,const PcodeOp *op)
{
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
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
@ -1524,9 +1520,10 @@ void PrintC::resetDefaultsPrintC(void)
/// Handle unicode, wide characters, etc. Characters come in with the compiler's raw encoding.
/// \param val is the constant 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 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;
@ -1546,7 +1543,7 @@ void PrintC::pushCharConstant(uintb val,const Datatype *ct,const Varnode *vn,con
}
if (displayFormat != 0 && displayFormat != Symbol::force_char) {
if (!castStrategy->caresAboutCharRepresentation(vn, op)) {
push_integer(val, ct->getSize(), isSigned, vn, op);
push_integer(val, ct->getSize(), isSigned, tag, vn, op);
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
// code-page value. In either case, we print as an integer or an escape sequence.
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;
}
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
printUnicode(t,(int4)val);
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
@ -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
/// \param val is the enumerated value being pushed
/// \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 op is the PcodeOp using the value
void PrintC::pushEnumConstant(uintb val,const TypeEnum *ct,
const Varnode *vn,
const PcodeOp *op)
void PrintC::pushEnumConstant(uintb val,const TypeEnum *ct,tagtype tag,
const Varnode *vn,const PcodeOp *op)
{
vector<string> valnames;
@ -1598,10 +1595,10 @@ void PrintC::pushEnumConstant(uintb val,const TypeEnum *ct,
for(int4 i=valnames.size()-1;i>0;--i)
pushOp(&enum_cat,op);
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 {
push_integer(val,ct->getSize(),false,vn,op);
push_integer(val,ct->getSize(),false,tag,vn,op);
// ostringstream s;
// s << "BAD_ENUM(0x" << hex << val << ")";
// 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
/// \return \b true if a name was pushed to the RPN stack, return \b false otherwise
bool PrintC::pushPtrCodeConstant(uintb val,const TypePointer *ct,
const Varnode *vn,
const PcodeOp *op)
const Varnode *vn,const PcodeOp *op)
{
AddrSpace *spc = glb->getDefaultCodeSpace();
Funcdata *fd = (Funcdata *)0;
@ -1664,7 +1660,7 @@ bool PrintC::pushPtrCodeConstant(uintb val,const TypePointer *ct,
return false;
}
void PrintC::pushConstant(uintb val,const Datatype *ct,
void PrintC::pushConstant(uintb val,const Datatype *ct,tagtype tag,
const Varnode *vn,
const PcodeOp *op)
{
@ -1672,25 +1668,25 @@ void PrintC::pushConstant(uintb val,const Datatype *ct,
switch(ct->getMetatype()) {
case TYPE_UINT:
if (ct->isCharPrint())
pushCharConstant(val,(TypeChar *)ct,vn,op);
pushCharConstant(val,(TypeChar *)ct,tag,vn,op);
else if (ct->isEnumType())
pushEnumConstant(val,(TypeEnum *)ct,vn,op);
pushEnumConstant(val,(TypeEnum *)ct,tag,vn,op);
else
push_integer(val,ct->getSize(),false,vn,op);
push_integer(val,ct->getSize(),false,tag,vn,op);
return;
case TYPE_INT:
if (ct->isCharPrint())
pushCharConstant(val,(TypeChar *)ct,vn,op);
pushCharConstant(val,(TypeChar *)ct,tag,vn,op);
else if (ct->isEnumType())
pushEnumConstant(val,(TypeEnum *)ct,vn,op);
pushEnumConstant(val,(TypeEnum *)ct,tag,vn,op);
else
push_integer(val,ct->getSize(),true,vn,op);
push_integer(val,ct->getSize(),true,tag,vn,op);
return;
case TYPE_UNKNOWN:
push_integer(val,ct->getSize(),false,vn,op);
push_integer(val,ct->getSize(),false,tag,vn,op);
return;
case TYPE_BOOL:
pushBoolConstant(val,(const TypeBase *)ct,vn,op);
pushBoolConstant(val,(const TypeBase *)ct,tag,vn,op);
return;
case TYPE_VOID:
clear();
@ -1712,7 +1708,7 @@ void PrintC::pushConstant(uintb val,const Datatype *ct,
}
break;
case TYPE_FLOAT:
push_float(val,ct->getSize(),vn,op);
push_float(val,ct->getSize(),tag,vn,op);
return;
case TYPE_SPACEBASE:
case TYPE_CODE:
@ -1731,7 +1727,7 @@ void PrintC::pushConstant(uintb val,const Datatype *ct,
pushMod();
if (!isSet(force_dec))
setMod(force_hex);
push_integer(val,ct->getSize(),false,vn,op);
push_integer(val,ct->getSize(),false,tag,vn,op);
popMod();
}
@ -1765,14 +1761,14 @@ bool PrintC::pushEquate(uintb val,int4 sz,const EquateSymbol *sym,const Varnode
if (modval == val) {
pushOp(&binary_plus,(const PcodeOp *)0);
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;
}
modval = (baseval - 1) & mask;
if (modval == val) {
pushOp(&binary_minus,(const PcodeOp *)0);
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 false;
@ -2092,8 +2088,7 @@ void PrintC::emitEnumDefinition(const TypeEnum *ct)
emit->spaces(1);
emit->print(EQUALSIGN,EmitMarkup::no_color);
emit->spaces(1);
push_integer((*iter).first,ct->getSize(),sign,(Varnode *)0,
(PcodeOp *)0);
push_integer((*iter).first,ct->getSize(),sign,syntax,(Varnode *)0,(PcodeOp *)0);
recurse();
emit->print(SEMICOLON);
++iter;
@ -3087,12 +3082,15 @@ void PrintC::emitSwitchCase(int4 casenum,const BlockSwitch *switchbl)
int4 i,num;
uintb val;
const Datatype *ct;
const PcodeOp *op;
ct = switchbl->getSwitchType();
op = switchbl->getCaseBlock(casenum)->firstOp();
if (switchbl->isDefaultCase(casenum)) {
val = switchbl->getLabel(casenum,0);
emit->tagLine();
emit->print(KEYWORD_DEFAULT,EmitMarkup::keyword_color);
emit->tagCaseLabel(KEYWORD_DEFAULT, EmitMarkup::keyword_color, op, val);
emit->print(COLON);
}
else {
@ -3102,7 +3100,7 @@ void PrintC::emitSwitchCase(int4 casenum,const BlockSwitch *switchbl)
emit->tagLine();
emit->print(KEYWORD_CASE,EmitMarkup::keyword_color);
emit->spaces(1);
pushConstant(val,ct,(Varnode *)0,(PcodeOp *)0);
pushConstant(val,ct,casetoken,(Varnode *)0,op);
recurse();
emit->print(COLON);
}

View file

@ -159,12 +159,12 @@ protected:
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 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,
const PcodeOp *op);
void pushCharConstant(uintb val,const Datatype *ct,const Varnode *vn,
const PcodeOp *op);
void pushEnumConstant(uintb val,const TypeEnum *ct,const Varnode *vn,
const PcodeOp *op);
void pushBoolConstant(uintb val,const TypeBase *ct,tagtype tag,const Varnode *vn,
const PcodeOp *op);
void pushCharConstant(uintb val,const Datatype *ct,tagtype tag,const Varnode *vn,
const PcodeOp *op);
void pushEnumConstant(uintb val,const TypeEnum *ct,tagtype tag,const Varnode *vn,
const PcodeOp *op);
virtual bool pushPtrCharConstant(uintb val,const TypePointer *ct,const Varnode *vn,
const PcodeOp *op);
bool pushPtrCodeConstant(uintb val,const TypePointer *ct,const Varnode *vn,
@ -196,10 +196,10 @@ protected:
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
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);
virtual bool pushEquate(uintb val,int4 sz,const EquateSymbol *sym,
const Varnode *vn,const PcodeOp *op);
const Varnode *vn,const PcodeOp *op);
virtual void pushAnnotation(const Varnode *vn,const PcodeOp *op);
virtual void pushSymbol(const Symbol *sym,const Varnode *vn,const PcodeOp *op);
virtual void pushUnnamedLocation(const Address &addr,
@ -209,10 +209,10 @@ protected:
virtual void pushMismatchSymbol(const Symbol *sym,int4 off,int4 sz,
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 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);
virtual void printUnicode(ostream &s,int4 onechar) const;
virtual void pushType(const Datatype *ct);

View file

@ -234,7 +234,7 @@ void PrintJava::opLoad(const PcodeOp *op)
pushOp(&subscript,op);
pushVn(op->getIn(1),op,m);
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)
@ -245,7 +245,7 @@ void PrintJava::opStore(const PcodeOp *op)
if (needZeroArray(op->getIn(1))) {
pushOp(&subscript,op);
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);
}
else {

View file

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

View file

@ -167,6 +167,7 @@ public:
optoken, ///< Emit atom as operator
typetoken, ///< Emit atom as operator
fieldtoken, ///< Emit atom as structure field
casetoken, ///< Emit atom as a \e case label
blanktoken ///< For anonymous types
};
@ -215,6 +216,7 @@ public:
const Varnode *vn; ///< A Varnode associated with the token
const Funcdata *fd; ///< A function 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
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
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; }
/// \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:
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
/// \param val is the value 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 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;
/// \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.program.model.address.Address;
import ghidra.program.model.pcode.*;
import ghidra.program.model.scalar.Scalar;
/**
* Class representing a source code language token.
@ -257,6 +258,9 @@ public class ClangToken implements ClangNode {
else if (node == ELEM_FIELD.id()) {
token = new ClangFieldToken(par);
}
else if (node == ELEM_VALUE.id()) {
token = new ClangCaseToken(par);
}
else {
throw new DecoderException("Expecting token element");
}
@ -319,4 +323,13 @@ public class ClangToken implements ClangNode {
public PcodeOp getPcodeOp() {
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.AddressFactory;
import ghidra.program.model.data.AbstractIntegerDataType;
import ghidra.program.model.data.DataType;
import ghidra.program.model.pcode.*;
import ghidra.program.model.scalar.Scalar;
/**
*
@ -44,6 +47,34 @@ public class ClangVariableToken extends ClangToken {
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
public boolean isVariableRef() {
return true;

View file

@ -21,15 +21,11 @@ import docking.widgets.fieldpanel.field.Field;
import docking.widgets.fieldpanel.support.FieldLocation;
import ghidra.GhidraOptions;
import ghidra.app.decompiler.ClangToken;
import ghidra.app.decompiler.ClangVariableToken;
import ghidra.app.decompiler.component.ClangTextField;
import ghidra.app.plugin.core.hover.AbstractScalarOperandHover;
import ghidra.framework.plugintool.PluginTool;
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.pcode.*;
import ghidra.program.model.scalar.Scalar;
import ghidra.program.util.ProgramLocation;
@ -82,35 +78,10 @@ public class ScalarValueDecompilerHover extends AbstractScalarOperandHover
}
ClangToken token = ((ClangTextField) field).getToken(fieldLocation);
if (!(token instanceof ClangVariableToken)) {
Scalar scalar = token.getScalar();
if (scalar == 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();
String formatted = formatScalar(program, addr, scalar);
return createTooltipComponent(formatted);

View file

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -17,6 +16,7 @@
package ghidra.program.model.pcode;
import java.util.Iterator;
/**
*
*
@ -32,7 +32,7 @@ public class ListLinked<T> {
public LinkedNode nextNode;
public T data;
LinkedNode(LinkedNode prev,LinkedNode nxt,T d) {
LinkedNode(LinkedNode prev, LinkedNode nxt, T d) {
previousNode = prev;
nextNode = nxt;
data = d;
@ -46,26 +46,22 @@ public class ListLinked<T> {
curNode = cur;
}
/* (non-Javadoc)
* @see java.util.Iterator#remove()
*/
@Override
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.previousNode.nextNode = curNode.nextNode;
curNode = curNode.previousNode;
}
/* (non-Javadoc)
* @see java.util.Iterator#hasNext()
*/
@Override
public boolean hasNext() {
return (curNode.nextNode.data != null);
}
/* (non-Javadoc)
* @see java.util.Iterator#next()
*/
@Override
public T next() {
curNode = curNode.nextNode;
return curNode.data;
@ -84,7 +80,7 @@ public class ListLinked<T> {
private LinkedNode terminal; // The boundary of the linked list
ListLinked() {
terminal = new LinkedNode(null,null,null);
terminal = new LinkedNode(null, null, null);
terminal.nextNode = terminal;
terminal.previousNode = terminal; // Create empty list
}
@ -96,7 +92,7 @@ public class ListLinked<T> {
* @return Iterator to new object
*/
public Iterator<T> add(T o) {
LinkedNode newNode = new LinkedNode(terminal.previousNode,terminal,o);
LinkedNode newNode = new LinkedNode(terminal.previousNode, terminal, o);
terminal.previousNode.nextNode = newNode;
terminal.previousNode = newNode;
LinkedIterator iter = new LinkedIterator(newNode);
@ -110,9 +106,9 @@ public class ListLinked<T> {
* @param o New object to add
* @return Iterator to new object
*/
public Iterator<T> insertAfter(Iterator<T> itr,T o) { // Insert object AFTER object indicated by iter
public Iterator<T> insertAfter(Iterator<T> itr, T o) { // Insert object AFTER object indicated by iter
LinkedNode cur = ((LinkedIterator) itr).curNode;
LinkedNode newNode = new LinkedNode(cur,cur.nextNode,o);
LinkedNode newNode = new LinkedNode(cur, cur.nextNode, o);
cur.nextNode.previousNode = newNode;
cur.nextNode = newNode;
return new LinkedIterator(newNode);
@ -125,9 +121,9 @@ public class ListLinked<T> {
* @param o New object to add
* @return Iterator to new object
*/
public Iterator<T> insertBefore(Iterator<T> itr,T o) { // Insert BEFORE iterator
LinkedNode cur = ((LinkedIterator)itr).curNode;
LinkedNode newNode = new LinkedNode(cur.previousNode,cur,o);
public Iterator<T> insertBefore(Iterator<T> itr, T o) { // Insert BEFORE iterator
LinkedNode cur = ((LinkedIterator) itr).curNode;
LinkedNode newNode = new LinkedNode(cur.previousNode, cur, o);
cur.previousNode.nextNode = newNode;
cur.previousNode = newNode;
return new LinkedIterator(newNode);
@ -140,8 +136,10 @@ public class ListLinked<T> {
* @param itr Iterator to object to be removed
*/
public void remove(Iterator<T> itr) {
LinkedNode cur = ((LinkedIterator)itr).curNode;
if (cur.data == null) return; // Should probably throw an exception here
LinkedNode cur = ((LinkedIterator) itr).curNode;
if (cur.data == null) {
return; // Should probably throw an exception here
}
cur.previousNode.nextNode = cur.nextNode;
cur.nextNode.previousNode = cur.previousNode;
}
@ -162,4 +160,17 @@ public class ListLinked<T> {
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();
encoder.openElement(ELEM_RANGE);
encoder.writeSpace(ATTRIB_SPACE, range.getAddressSpace());
encoder.writeUnsignedInteger(ATTRIB_FIRST,
range.getMinAddress().getOffset());
encoder.writeUnsignedInteger(ATTRIB_LAST,
range.getMaxAddress().getOffset());
encoder.writeUnsignedInteger(ATTRIB_FIRST, range.getMinAddress().getOffset());
encoder.writeUnsignedInteger(ATTRIB_LAST, range.getMaxAddress().getOffset());
}
encoder.closeElement(ELEM_RANGELIST);
}
@ -146,4 +144,18 @@ public class PcodeBlockBasic extends PcodeBlock {
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();
}
}