mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 10:19:23 +02:00
GP-3680 Add case label tokens
This commit is contained in:
parent
c072972153
commit
fe2f993e11
15 changed files with 415 additions and 138 deletions
|
@ -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
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
|
@ -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(); }
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -159,12 +159,12 @@ 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);
|
||||||
bool pushPtrCodeConstant(uintb val,const TypePointer *ct,const Varnode *vn,
|
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;
|
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);
|
||||||
virtual void pushAnnotation(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 pushSymbol(const Symbol *sym,const Varnode *vn,const PcodeOp *op);
|
||||||
virtual void pushUnnamedLocation(const Address &addr,
|
virtual void pushUnnamedLocation(const Address &addr,
|
||||||
|
@ -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);
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
|
@ -31,64 +31,60 @@ public class ListLinked<T> {
|
||||||
public LinkedNode previousNode;
|
public LinkedNode previousNode;
|
||||||
public LinkedNode nextNode;
|
public LinkedNode nextNode;
|
||||||
public T data;
|
public T data;
|
||||||
|
|
||||||
LinkedNode(LinkedNode prev,LinkedNode nxt,T d) {
|
LinkedNode(LinkedNode prev, LinkedNode nxt, T d) {
|
||||||
previousNode = prev;
|
previousNode = prev;
|
||||||
nextNode = nxt;
|
nextNode = nxt;
|
||||||
data = d;
|
data = d;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class LinkedIterator implements Iterator<T> {
|
private class LinkedIterator implements Iterator<T> {
|
||||||
private LinkedNode curNode; // Current node in the linked list being pointed at by this iterator
|
private LinkedNode curNode; // Current node in the linked list being pointed at by this iterator
|
||||||
|
|
||||||
public LinkedIterator(LinkedNode cur) {
|
public LinkedIterator(LinkedNode cur) {
|
||||||
curNode = cur;
|
curNode = cur;
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see java.util.Iterator#remove()
|
|
||||||
*/
|
|
||||||
public void remove() {
|
|
||||||
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)
|
@Override
|
||||||
* @see java.util.Iterator#hasNext()
|
public void remove() {
|
||||||
*/
|
if (curNode.data == null) {
|
||||||
|
return; // Should probably throw an exception here
|
||||||
|
}
|
||||||
|
curNode.nextNode.previousNode = curNode.previousNode;
|
||||||
|
curNode.previousNode.nextNode = curNode.nextNode;
|
||||||
|
curNode = curNode.previousNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasPrevious() {
|
public boolean hasPrevious() {
|
||||||
return (curNode.data != null);
|
return (curNode.data != null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object previous() {
|
public Object previous() {
|
||||||
curNode = curNode.previousNode;
|
curNode = curNode.previousNode;
|
||||||
return curNode.nextNode.data;
|
return curNode.nextNode.data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private LinkedNode terminal; // The boundary of the linked list
|
private LinkedNode terminal; // The boundary of the linked list
|
||||||
|
|
||||||
ListLinked() {
|
ListLinked() {
|
||||||
terminal = new LinkedNode(null,null,null);
|
terminal = new LinkedNode(null, null, null);
|
||||||
terminal.nextNode = terminal;
|
terminal.nextNode = terminal;
|
||||||
terminal.previousNode = terminal; // Create empty list
|
terminal.previousNode = terminal; // Create empty list
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add object to end of the list, any existing iterators remain valid
|
* Add object to end of the list, any existing iterators remain valid
|
||||||
*
|
*
|
||||||
|
@ -96,11 +92,11 @@ public class ListLinked<T> {
|
||||||
* @return Iterator to new object
|
* @return Iterator to new object
|
||||||
*/
|
*/
|
||||||
public Iterator<T> add(T o) {
|
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.nextNode = newNode;
|
||||||
terminal.previousNode = newNode;
|
terminal.previousNode = newNode;
|
||||||
LinkedIterator iter = new LinkedIterator(newNode);
|
LinkedIterator iter = new LinkedIterator(newNode);
|
||||||
return iter;
|
return iter;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -110,14 +106,14 @@ public class ListLinked<T> {
|
||||||
* @param o New object to add
|
* @param o New object to add
|
||||||
* @return Iterator to new object
|
* @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 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.previousNode = newNode;
|
||||||
cur.nextNode = newNode;
|
cur.nextNode = newNode;
|
||||||
return new LinkedIterator(newNode);
|
return new LinkedIterator(newNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Insert new object BEFORE object pointed to by iterator, other Iterators remain valid
|
* Insert new object BEFORE object pointed to by iterator, other Iterators remain valid
|
||||||
*
|
*
|
||||||
|
@ -125,14 +121,14 @@ public class ListLinked<T> {
|
||||||
* @param o New object to add
|
* @param o New object to add
|
||||||
* @return Iterator to new object
|
* @return Iterator to new object
|
||||||
*/
|
*/
|
||||||
public Iterator<T> insertBefore(Iterator<T> itr,T o) { // Insert BEFORE iterator
|
public Iterator<T> insertBefore(Iterator<T> itr, T o) { // Insert BEFORE iterator
|
||||||
LinkedNode cur = ((LinkedIterator)itr).curNode;
|
LinkedNode cur = ((LinkedIterator) itr).curNode;
|
||||||
LinkedNode newNode = new LinkedNode(cur.previousNode,cur,o);
|
LinkedNode newNode = new LinkedNode(cur.previousNode, cur, o);
|
||||||
cur.previousNode.nextNode = newNode;
|
cur.previousNode.nextNode = newNode;
|
||||||
cur.previousNode = newNode;
|
cur.previousNode = newNode;
|
||||||
return new LinkedIterator(newNode);
|
return new LinkedIterator(newNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove object from list indicated by Iterator, all iterators that point to objects other
|
* Remove object from list indicated by Iterator, all iterators that point to objects other
|
||||||
* than this one remain valid
|
* than this one remain valid
|
||||||
|
@ -140,8 +136,10 @@ public class ListLinked<T> {
|
||||||
* @param itr Iterator to object to be removed
|
* @param itr Iterator to object to be removed
|
||||||
*/
|
*/
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
@ -151,9 +149,9 @@ public class ListLinked<T> {
|
||||||
*/
|
*/
|
||||||
public Iterator<T> iterator() {
|
public Iterator<T> iterator() {
|
||||||
LinkedIterator iter = new LinkedIterator(terminal); // Build starting iterator
|
LinkedIterator iter = new LinkedIterator(terminal); // Build starting iterator
|
||||||
return iter;
|
return iter;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get rid of all entries on the linked list.
|
* Get rid of all entries on the linked list.
|
||||||
*/
|
*/
|
||||||
|
@ -161,5 +159,18 @@ public class ListLinked<T> {
|
||||||
terminal.nextNode = terminal;
|
terminal.nextNode = terminal;
|
||||||
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue