Merge remote-tracking branch 'origin/GP-621_CommentGroups'

This commit is contained in:
ghidra1 2021-01-26 11:58:20 -05:00
commit 5d1fdc9158
7 changed files with 141 additions and 75 deletions

View file

@ -21,10 +21,8 @@
/// \param ad is the Address of the instruction associated with the comment
/// \param uq is used internally to sub-sort comments at the same address
/// \param txt is the body of the comment
Comment::Comment(uint4 tp,const Address &fad,
const Address &ad,int4 uq,
const string &txt) :
type(tp), funcaddr(fad), addr(ad), uniq(uq), text(txt)
Comment::Comment(uint4 tp,const Address &fad,const Address &ad,int4 uq,const string &txt) :
type(tp), uniq(uq), funcaddr(fad), addr(ad), text(txt), emitted(false)
{
}
@ -55,6 +53,7 @@ void Comment::saveXml(ostream &s) const
void Comment::restoreXml(const Element *el,const AddrSpaceManager *manage)
{
emitted = false;
type = 0;
type = Comment::encodeCommentType(el->getAttributeValue("type"));
const List &list(el->getChildren());
@ -344,6 +343,7 @@ void CommentSorter::setupFunctionList(uint4 tp,const Funcdata *fd,const CommentD
while(iter != lastiter) {
Comment *comm = *iter;
if (findPosition(subsort, comm, fd)) {
comm->setEmitted(false);
commmap[ subsort ] = comm;
subsort.pos += 1; // Advance the uniqueness counter
}

View file

@ -37,10 +37,11 @@ class Funcdata;
class Comment {
friend class CommentDatabaseInternal;
uint4 type; ///< The properties associated with the comment
int4 uniq; ///< Sub-identifier for uniqueness
Address funcaddr; ///< Address of the function containing the comment
Address addr; ///< Address associated with the comment
int4 uniq; ///< Sub-identifier for uniqueness
string text; ///< The body of the comment
mutable bool emitted; ///< \b true if this comment has already been emitted
public:
/// \brief Possible properties associated with a comment
enum comment_type {
@ -51,9 +52,10 @@ public:
warning = 16, ///< The comment is auto-generated to alert the user
warningheader = 32 ///< The comment is auto-generated and should be in the header
};
Comment(uint4 tp,const Address &fad,
const Address &ad,int4 uq,const string &txt); ///< Constructor
Comment(uint4 tp,const Address &fad,const Address &ad,int4 uq,const string &txt); ///< Constructor
Comment(void) {} ///< Constructor for use with restoreXml
void setEmitted(bool val) const { emitted = val; }
bool isEmitted(void) const { return emitted; }
uint4 getType(void) const { return type; } ///< Get the properties associated with the comment
const Address &getFuncAddr(void) const { return funcaddr; } ///< Get the address of the function containing the comment
const Address &getAddr(void) const { return addr; } ///< Get the address to which the instruction is attached

View file

@ -2586,19 +2586,21 @@ void PrintC::emitBlockIf(const BlockIf *bl)
pushMod();
setMod(no_branch);
bl->getBlock(0)->emit(this);
FlowBlock *condBlock = bl->getBlock(0);
condBlock->emit(this);
popMod();
emitCommentBlockTree(condBlock);
emit->tagLine();
op = bl->getBlock(0)->lastOp();
op = condBlock->lastOp();
emit->tagOp("if",EmitXml::keyword_color,op);
emit->spaces(1);
pushMod();
setMod(only_branch);
bl->getBlock(0)->emit(this);
condBlock->emit(this);
popMod();
if (bl->getGotoTarget() != (FlowBlock *)0) {
emit->spaces(1);
emitGotoStatement(bl->getBlock(0),bl->getGotoTarget(),bl->getGotoType());
emitGotoStatement(condBlock,bl->getGotoTarget(),bl->getGotoType());
popMod();
return;
}
@ -2644,8 +2646,10 @@ void PrintC::emitForLoop(const BlockWhileDo *bl)
pushMod();
unsetMod(no_branch|only_branch);
emitAnyLabelStatement(bl);
FlowBlock *condBlock = bl->getBlock(0);
emitCommentBlockTree(condBlock);
emit->tagLine();
op = bl->getBlock(0)->lastOp();
op = condBlock->lastOp();
emit->tagOp("for",EmitXml::keyword_color,op);
emit->spaces(1);
int4 id1 = emit->openParen('(');
@ -2659,7 +2663,7 @@ void PrintC::emitForLoop(const BlockWhileDo *bl)
}
emit->print(";");
emit->spaces(1);
bl->getBlock(0)->emit(this); // Emit the conditional statement
condBlock->emit(this); // Emit the conditional statement
emit->print(";");
emit->spaces(1);
op = bl->getIterateOp(); // Emit the iterator statement
@ -2695,13 +2699,14 @@ void PrintC::emitBlockWhileDo(const BlockWhileDo *bl)
pushMod();
unsetMod(no_branch|only_branch);
emitAnyLabelStatement(bl);
emit->tagLine();
op = bl->getBlock(0)->lastOp();
FlowBlock *condBlock = bl->getBlock(0);
op = condBlock->lastOp();
if (bl->hasOverflowSyntax()) {
// Print conditional block as
// while( true ) {
// conditionbody ...
// if (conditionalbranch) break;
emit->tagLine();
emit->tagOp("while",EmitXml::keyword_color,op);
int4 id1 = emit->openParen('(');
emit->spaces(1);
@ -2713,27 +2718,30 @@ void PrintC::emitBlockWhileDo(const BlockWhileDo *bl)
emit->print("{");
pushMod();
setMod(no_branch);
bl->getBlock(0)->emit(this);
condBlock->emit(this);
popMod();
emitCommentBlockTree(condBlock);
emit->tagLine();
emit->tagOp("if",EmitXml::keyword_color,op);
emit->spaces(1);
pushMod();
setMod(only_branch);
bl->getBlock(0)->emit(this);
condBlock->emit(this);
popMod();
emit->spaces(1);
emitGotoStatement(bl->getBlock(0),(const FlowBlock *)0,FlowBlock::f_break_goto);
emitGotoStatement(condBlock,(const FlowBlock *)0,FlowBlock::f_break_goto);
}
else {
// Print conditional block "normally" as
// while(condition) {
emitCommentBlockTree(condBlock);
emit->tagLine();
emit->tagOp("while",EmitXml::keyword_color,op);
emit->spaces(1);
int4 id1 = emit->openParen('(');
pushMod();
setMod(comma_separate);
bl->getBlock(0)->emit(this);
condBlock->emit(this);
popMod();
emit->closeParen(')',id1);
emit->spaces(1);
@ -2924,11 +2932,38 @@ void PrintC::emitCommentGroup(const PcodeOp *inst)
commsorter.setupOpList(inst);
while(commsorter.hasNext()) {
Comment *comm = commsorter.getNext();
if (comm->isEmitted()) continue;
if ((instr_comment_type & comm->getType())==0) continue;
emitLineComment(-1,comm);
}
}
/// With the control-flow hierarchy, print any comments associated with basic blocks in
/// the specified subtree. Used where statements from multiple basic blocks are printed on
/// one line and a normal comment would get printed in the middle of this line.
/// \param bl is the root of the control-flow subtree
void PrintC::emitCommentBlockTree(const FlowBlock *bl)
{
if (bl == (const FlowBlock *)0) return;
FlowBlock::block_type btype = bl->getType();
if (btype == FlowBlock::t_copy) {
bl = bl->subBlock(0);
btype = bl->getType();
}
if (btype == FlowBlock::t_plain) return;
if (bl->getType() != FlowBlock::t_basic) {
const BlockGraph *rootbl = (const BlockGraph *)bl;
int4 size = rootbl->getSize();
for(int4 i=0;i<size;++i) {
emitCommentBlockTree(rootbl->subBlock(i));
}
return;
}
commsorter.setupBlockList(bl);
emitCommentGroup((const PcodeOp *)0); // Emit any comments for the block
}
/// Collect all comment lines marked as \e header for the function and
/// emit them with the appropriate delimiters.
/// \param fd is the given function
@ -2939,6 +2974,7 @@ void PrintC::emitCommentFuncHeader(const Funcdata *fd)
commsorter.setupHeader(CommentSorter::header_basic);
while(commsorter.hasNext()) {
Comment *comm = commsorter.getNext();
if (comm->isEmitted()) continue;
if ((head_comment_type & comm->getType())==0) continue;
emitLineComment(0,comm);
extralinebreak = true;
@ -2950,6 +2986,7 @@ void PrintC::emitCommentFuncHeader(const Funcdata *fd)
commsorter.setupHeader(CommentSorter::header_unplaced);
while(commsorter.hasNext()) {
Comment *comm = commsorter.getNext();
if (comm->isEmitted()) continue;
if (!extralinebreak) {
Comment label(Comment::warningheader,fd->getAddress(),fd->getAddress(),0,
"Comments that could not be placed in the function body:");

View file

@ -156,6 +156,7 @@ protected:
void emitLabelStatement(const FlowBlock *bl); ///< Emit any required label statement for a given basic block
void emitAnyLabelStatement(const FlowBlock *bl); ///< Emit any required label statement for a given control-flow block
void emitCommentGroup(const PcodeOp *inst); ///< Emit comments associated with a given statement
void emitCommentBlockTree(const FlowBlock *bl); ///< Emit any comments under the given control-flow subtree
void emitCommentFuncHeader(const Funcdata *fd); ///< Emit comments in the given function's header
void emitForLoop(const BlockWhileDo *bl); ///< Emit block as a \e for loop
void opFunc(const PcodeOp *op); ///< Push a \e functional expression based on the given p-code op to the RPN stack

View file

@ -631,6 +631,7 @@ void PrintLanguage::emitLineComment(int4 indent,const Comment *comm)
emit->tagComment(commentend.c_str(),EmitXml::comment_color,
spc,off);
emit->stopComment(id);
comm->setEmitted(true);
}
/// Tell the emitter whether to emit just the raw tokens or if