diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/pcodecompile.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/pcodecompile.cc index e4e24e46b9..7927bececa 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/pcodecompile.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/pcodecompile.cc @@ -15,7 +15,15 @@ */ #include "pcodecompile.hh" -ExprTree::ExprTree(VarnodeTpl *vn) +string Location::format(void) const + +{ + ostringstream s; + s << filename << ":" << dec << lineno; + return s.str(); +} + + ExprTree::ExprTree(VarnodeTpl *vn) { outvn = vn; @@ -305,9 +313,7 @@ vector *PcodeCompile::placeLabel(LabelSymbol *labsym) { // Create placeholder OpTpl for a label if (labsym->isPlaced()) { - string errmsg = "Label " + labsym->getName(); - errmsg += " is placed more than once"; - reportError(errmsg); + reportError(getLocation(labsym), "Label '" + labsym->getName() + "' is placed more than once"); } labsym->setPlaced(); vector *res = new vector; @@ -335,7 +341,7 @@ vector *PcodeCompile::newOutput(bool usesLocalKey,ExprTree *rhs,string sym = new VarnodeSymbol(*varname,tmpvn->getSpace().getSpace(),tmpvn->getOffset().getReal(),tmpvn->getSize().getReal()); // Create new symbol regardless addSymbol(sym); if ((!usesLocalKey) && enforceLocalKey) - reportError("Must use 'local' keyword to define symbol: "+*varname); + reportError(getLocation(sym), "Must use 'local' keyword to define symbol '"+*varname + "'"); delete varname; return ExprTree::toVector(rhs); } @@ -633,7 +639,7 @@ vector *PcodeCompile::assignBitRange(VarnodeTpl *vn,uint4 bitoffset,uin } if (errmsg.size()>0) { // Was there an error condition - reportError(errmsg); // Report the error + reportError((const Location *)0, errmsg); // Report the error delete vn; // Clean up vector *resops = rhs->ops; // Passthru old expression rhs->ops = (vector *)0; @@ -647,6 +653,7 @@ vector *PcodeCompile::assignBitRange(VarnodeTpl *vn,uint4 bitoffset,uin ExprTree *res; VarnodeTpl *finalout = buildTruncatedVarnode(vn,bitoffset,numbits); if (finalout != (VarnodeTpl *)0) { + delete vn; // Don't keep the original Varnode object res = createOpOutUnary(finalout,CPUI_COPY,rhs); } else { @@ -663,7 +670,7 @@ vector *PcodeCompile::assignBitRange(VarnodeTpl *vn,uint4 bitoffset,uin res = createOpOut(finalout,CPUI_INT_OR,res,rhs); } if (errmsg.size() > 0) - reportError(errmsg); + reportError((const Location *)0, errmsg); vector *resops = res->ops; res->ops = (vector *)0; delete res; @@ -737,7 +744,7 @@ ExprTree *PcodeCompile::createBitRange(SpecificSymbol *sym,uint4 bitoffset,uint4 ExprTree *res = new ExprTree(vn); if (errmsg.size()>0) { // Check for error condition - reportError(errmsg); + reportError(getLocation(sym), errmsg); return res; } @@ -774,4 +781,3 @@ VarnodeTpl *PcodeCompile::addressOf(VarnodeTpl *var,uint4 size) delete var; return res; } - diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/pcodecompile.hh b/Ghidra/Features/Decompiler/src/decompile/cpp/pcodecompile.hh index 59272be366..6205c47b91 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/pcodecompile.hh +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/pcodecompile.hh @@ -18,6 +18,17 @@ #include "slghsymbol.hh" +class Location { + string filename; + int4 lineno; +public: + Location(void) {} + Location(const string &fname, const int4 line) { filename = fname; lineno = line; } + string getFilename(void) const { return filename; } + int4 getLineno(void) const { return lineno; } + string format(void) const; +}; + struct StarQuality { ConstTpl id; uint4 size; @@ -53,7 +64,9 @@ public: PcodeCompile(void) { defaultspace=(AddrSpace *)0; constantspace=(AddrSpace *)0; uniqspace=(AddrSpace *)0; local_labelcount=0; enforceLocalKey=false; } virtual ~PcodeCompile(void) {} - virtual void reportError(const string &msg)=0; + virtual const Location *getLocation(SleighSymbol *sym) const=0; + virtual void reportError(const Location *loc, const string &msg)=0; + virtual void reportWarning(const Location *loc, const string &msg)=0; void resetLabelCount(void) { local_labelcount=0; } void setDefaultSpace(AddrSpace *spc) { defaultspace = spc; } void setConstantSpace(AddrSpace *spc) { constantspace = spc; } diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/pcodeparse.hh b/Ghidra/Features/Decompiler/src/decompile/cpp/pcodeparse.hh index c4f452a640..d8621a9eec 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/pcodeparse.hh +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/pcodeparse.hh @@ -82,7 +82,9 @@ public: void setResult(ConstructTpl *res) { result = res; } ConstructTpl *releaseResult(void) { ConstructTpl *res = result; result = (ConstructTpl *)0; return res; } virtual ~PcodeSnippet(void); - virtual void reportError(const string &msg); + virtual const Location *getLocation(SleighSymbol *sym) const { return (const Location *)0; } + virtual void reportError(const Location *loc, const string &msg); + virtual void reportWarning(const Location *loc, const string &msg) {} bool hasErrors(void) const { return (errorcount != 0); } const string getErrorMessage(void) const { return firsterror; } void setUniqueBase(uintb val) { tempbase = val; } diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/pcodeparse.y b/Ghidra/Features/Decompiler/src/decompile/cpp/pcodeparse.y index 790c1662d6..5656d6d9a3 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/pcodeparse.y +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/pcodeparse.y @@ -650,7 +650,7 @@ void PcodeSnippet::addSymbol(SleighSymbol *sym) res = tree.insert( sym ); if (!res.second) { - reportError("Duplicate symbol name: "+sym->getName()); + reportError((const Location *)0,"Duplicate symbol name: "+sym->getName()); delete sym; // Symbol is unattached to anything else } } @@ -712,7 +712,7 @@ PcodeSnippet::~PcodeSnippet(void) } } -void PcodeSnippet::reportError(const string &msg) +void PcodeSnippet::reportError(const Location *loc, const string &msg) { if (errorcount == 0) @@ -779,11 +779,11 @@ int4 PcodeSnippet::lex(void) pcode = this; // Setup global object for yyparse int4 res = yyparse(); if (res != 0) { - reportError("Syntax error"); + reportError((const Location *)0,"Syntax error"); return false; } if (!PcodeCompile::propagateSize(result)) { - reportError("Could not resolve at least 1 variable size"); + reportError((const Location *)0,"Could not resolve at least 1 variable size"); return false; } return true; @@ -803,6 +803,6 @@ int yylex(void) { int yyerror(const char *s) { - pcode->reportError(s); + pcode->reportError((const Location *)0,s); return 0; } diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/slgh_compile.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/slgh_compile.cc index ccb30b2f1f..ade7057c53 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/slgh_compile.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/slgh_compile.cc @@ -183,9 +183,10 @@ SubtableSymbol *WithBlock::getCurrentSubtable(const list &stack) return (SubtableSymbol *)0; } -ConsistencyChecker::ConsistencyChecker(SubtableSymbol *rt,bool un,bool warndead) +ConsistencyChecker::ConsistencyChecker(SleighCompile *sleigh,SubtableSymbol *rt,bool un,bool warndead) { + slgh = sleigh; root_symbol = rt; unnecessarypcode = 0; readnowrite = 0; @@ -194,6 +195,16 @@ ConsistencyChecker::ConsistencyChecker(SubtableSymbol *rt,bool un,bool warndead) printdeadwarning = warndead; } +void ConsistencyChecker::reportError(const Location *loc, const string &msg) +{ + slgh->reportError(loc, msg); +} + +void ConsistencyChecker::reportWarning(const Location *loc, const string &msg) +{ + slgh->reportWarning(loc, msg); +} + int4 ConsistencyChecker::recoverSize(const ConstTpl &sizeconst,Constructor *ct) { @@ -231,9 +242,10 @@ void ConsistencyChecker::dealWithUnnecessaryExt(OpTpl *op,Constructor *ct) { // Deal with detected extension (SEXT or ZEXT) where the // input size is the same as the output size if (printextwarning) { - cerr << "Unnecessary "; - printOpName(cerr,op); - cerr << " in constructor starting at line " << dec << ct->getLineno() << endl; + ostringstream msg; + msg << "Unnecessary "; + printOpName(msg,op); + reportWarning(slgh->getLocation(ct), msg.str()); } op->setOpcode(CPUI_COPY); // Equivalent to copy unnecessarypcode += 1; @@ -243,9 +255,10 @@ void ConsistencyChecker::dealWithUnnecessaryTrunc(OpTpl *op,Constructor *ct) { if (printextwarning) { - cerr << "Unnecessary "; - printOpName(cerr,op); - cerr << " in constructor starting at line " << dec << ct->getLineno() << endl; + ostringstream msg; + msg << "Unnecessary "; + printOpName(msg,op); + reportWarning(slgh->getLocation(ct), msg.str()); } op->setOpcode(CPUI_COPY); // Equivalent to copy op->removeInput(1); @@ -260,7 +273,7 @@ bool ConsistencyChecker::checkOpMisuse(OpTpl *op,Constructor *ct) { VarnodeTpl *vn = op->getIn(1); if (vn->getSpace().isConstSpace() && vn->getOffset().isZero()) { - cerr << "Unsigned comparison with zero is always false in constructor starting at line " << dec << ct->getLineno() << endl; + reportError(slgh->getLocation(ct), "Unsigned comparison with zero is always false"); } } break; @@ -771,21 +784,23 @@ void ConsistencyChecker::printOpError(OpTpl *op,Constructor *ct,int4 err1,int4 e op2 = getOperandSymbol(err2,op,ct); else op2 = (OperandSymbol *)0; - cerr << "Size restriction error in table \"" << sym->getName() << "\"" << endl; - cerr << " in constructor starting at line " << dec << ct->getLineno() << endl; - if ((op1 != (OperandSymbol *)0)&&(op2 != (OperandSymbol *)0)) { - cerr << " Problem with \"" << op1->getName(); - cerr << "\" and \"" << op2->getName() << "\""; - } + + ostringstream msgBuilder; + + msgBuilder << "Size restriction error in table '" << sym->getName() << "'" << endl; + if ((op1 != (OperandSymbol *)0)&&(op2 != (OperandSymbol *)0)) + msgBuilder << " Problem with operands '" << op1->getName() << "' and '" << op2->getName() << "'"; else if (op1 != (OperandSymbol *)0) - cerr << " Problem with \"" << op1->getName() << "\""; + msgBuilder << " Problem with operand 1 '" << op1->getName() << "'"; else if (op2 != (OperandSymbol *)0) - cerr << " Problem with \"" << op2->getName() << "\""; + msgBuilder << " Problem with operand 2 '" << op2->getName() << "'"; else - cerr << " Problem"; - cerr << " in "; - printOpName(cerr,op); - cerr << " operator" << endl << " " << msg << endl; + msgBuilder << " Problem"; + msgBuilder << " in "; + printOpName(msgBuilder,op); + msgBuilder << " operator" << endl << " " << msg; + + reportError(slgh->getLocation(ct), msgBuilder.str()); } bool ConsistencyChecker::checkConstructorSection(Constructor *ct,ConstructTpl *cttpl) @@ -878,8 +893,10 @@ bool ConsistencyChecker::checkSubtable(SubtableSymbol *sym) HandleTpl *exportres = ct->getTempl()->getResult(); if (exportres != (HandleTpl *)0) { if (seenemptyexport && (!seennonemptyexport)) { - cerr << "Table " << sym->getName() << " exports inconsistently" << endl; - cerr << "Constructor starting at line " << dec << ct->getLineno() << " is first inconsistency" << endl; + ostringstream msg; + msg << "Table '" << sym->getName() << "' exports inconsistently; "; + msg << "Constructor starting at line " << dec << ct->getLineno() << " is first inconsistency"; + reportError(slgh->getLocation(ct), msg.str()); testresult = false; } seennonemptyexport = true; @@ -887,23 +904,28 @@ bool ConsistencyChecker::checkSubtable(SubtableSymbol *sym) if (tablesize == 0) tablesize = exsize; if ((exsize!=0)&&(exsize != tablesize)) { - cerr << "Table " << sym->getName() << " has inconsistent export size." << endl; - cerr << "Constructor starting at line " << dec << ct->getLineno() << " is first conflict" << endl; + ostringstream msg; + msg << "Table '" << sym->getName() << "' has inconsistent export size; "; + msg << "Constructor starting at line " << dec << ct->getLineno() << " is first conflict"; + reportError(slgh->getLocation(ct), msg.str()); testresult = false; } } else { if (seennonemptyexport && (!seenemptyexport)) { - cerr << "Table " << sym->getName() << " exports inconsistently" << endl; - cerr << "Constructor starting at line " << dec << ct->getLineno() << " is first inconsistency" << endl; + ostringstream msg; + msg << "Table '" << sym->getName() << "' exports inconsistently; "; + msg << "Constructor starting at line " << dec << ct->getLineno() << " is first inconsistency"; + reportError(slgh->getLocation(ct), msg.str()); testresult = false; } seenemptyexport = true; } } if (seennonemptyexport) { - if (tablesize == 0) - cerr << "Warning: Table " << sym->getName() << " exports size 0" << endl; + if (tablesize == 0) { + reportWarning(slgh->getLocation(sym), "Table '" + sym->getName() + "' exports size 0"); + } sizemap[sym] = tablesize; // Remember recovered size } else @@ -1212,11 +1234,11 @@ void ConsistencyChecker::checkUnusedTemps(Constructor *ct,const mapgetLineno() << endl; + reportWarning(slgh->getLocation(ct), "Temporary is written but not read"); writenoread += 1; } else if (currec.writecount == 0) { - cerr << "Error: temporary is read but not written in constructor starting at line " << dec << ct->getLineno() << endl; + reportError(slgh->getLocation(ct), "Temporary is read but not written"); readnowrite += 1; } ++iter; @@ -1318,10 +1340,10 @@ void MacroBuilder::free(void) params.clear(); } -void MacroBuilder::reportError(const string &val) +void MacroBuilder::reportError(const Location* loc, const string &val) { - slgh->reportError(val,false); + slgh->reportError(loc, val); haserror = true; } @@ -1351,7 +1373,7 @@ bool MacroBuilder::transferOp(OpTpl *op,vector ¶ms) if (outvn != (VarnodeTpl *)0) { plus = outvn->transfer(params); if (plus >= 0) { - reportError("Cannot currently assign to bitrange of macro parameter that is a temporary"); + reportError((const Location *)0, "Cannot currently assign to bitrange of macro parameter that is a temporary"); return false; } } @@ -1365,7 +1387,7 @@ bool MacroBuilder::transferOp(OpTpl *op,vector ¶ms) plus = vn->transfer(params); if (plus >= 0) { if (!hasrealsize) { - reportError("Problem with bit range operator in macro"); + reportError((const Location *)0, "Problem with bit range operator in macro"); return false; } uintb newtemp = slgh->getUniqueAddr(); // Generate a new temporary location @@ -1441,10 +1463,22 @@ uintb SleighPcode::allocateTemp(void) return compiler->getUniqueAddr(); } -void SleighPcode::reportError(const string &msg) +const Location *SleighPcode::getLocation(SleighSymbol *sym) const { - return compiler->reportError(msg,true); + return compiler->getLocation(sym); +} + +void SleighPcode::reportError(const Location *loc, const string &msg) + +{ + return compiler->reportError(loc, msg); +} + +void SleighPcode::reportWarning(const Location *loc, const string &msg) + +{ + return compiler->reportWarning(loc, msg); } void SleighPcode::addSymbol(SleighSymbol *sym) @@ -1506,7 +1540,7 @@ int4 SleighCompile::calcContextVarLayout(int4 start,int4 sz,int4 numbits) int4 maxbits; if ((sym->getSize()) % 4 != 0) - reportError("Invalid size of context register: "+sym->getName()+" : must be a multiple of 4 bytes",false); + reportError(getCurrentLocation(), "Invalid size of context register '"+sym->getName()+"': must be a multiple of 4 bytes"); maxbits = sym->getSize() * 8 -1; i = 0; while(ilow; int4 max = qual->high; if ((max - min) > (8*sizeof(uintm))) - reportError("Size of bitfield " + qual->name + " larger than 32-bits",false); + reportError(getCurrentLocation(), "Size of bitfield '" + qual->name + "' larger than 32 bits"); if (max > maxbits) - reportError("Scope of bitfield " + qual->name + " extends beyond the size of context register",false); + reportError(getCurrentLocation(), "Scope of bitfield '" + qual->name + "' extends beyond the size of context register"); j = i+1; // Find union of fields overlapping with first field while(jbuildDecisionTree(props); - const vector &ierrors( props.getIdentErrors() ); - for(int4 i=0;i> &ierrors( props.getIdentErrors() ); + if (ierrors.size() != 0) { + string identMsg = "Constructor has identical pattern to constructor at "; + for(int4 i=0;iformat()); + reportError(locB, identMsg + locA->format()); + } } - if (!lenientconflicterrors) { - const vector &cerrors( props.getConflictErrors() ); + const vector> &cerrors( props.getConflictErrors() ); + if (!lenientconflicterrors && cerrors.size() != 0) { + string conflictMsg = "Constructor pattern cannot be distinguished from constructor at "; for(int4 i=0;iformat()); + reportError(locB, conflictMsg + locA->format()); } } } @@ -1582,23 +1626,28 @@ void SleighCompile::buildPatterns(void) { if (root == 0) { - reportError("No patterns to match.",false); + reportError(nullptr, "No patterns to match."); return; } - root->buildPattern(cerr); // This should recursively hit everything - if (root->isError()) errors += 1; + ostringstream msg; + root->buildPattern(msg); // This should recursively hit everything + if (root->isError()) { + reportError(getLocation(root), msg.str()); + errors += 1; + } for(int4 i=0;iisError()) errors += 1; - if (tables[i]->getPattern() == (TokenPattern *)0) - reportWarning("Unreferenced table: "+tables[i]->getName(),false); + if (tables[i]->getPattern() == (TokenPattern *)0) { + reportWarning(getLocation(tables[i]), "Unreferenced table '"+tables[i]->getName() + "'"); + } } } void SleighCompile::checkConsistency(void) { - ConsistencyChecker checker(root,warnunnecessarypcode,warndeadtemps); + ConsistencyChecker checker(this, root,warnunnecessarypcode,warndeadtemps); if (!checker.test()) { errors += 1; @@ -1609,9 +1658,11 @@ void SleighCompile::checkConsistency(void) return; } if ((!warnunnecessarypcode)&&(checker.getNumUnnecessaryPcode() > 0)) { - cerr << dec << checker.getNumUnnecessaryPcode(); - cerr << " unnecessary extensions/truncations were converted to copies" << endl; - cerr << "Use -u switch to list each individually" << endl; + ostringstream msg; + msg << dec << checker.getNumUnnecessaryPcode(); + msg << " unnecessary extensions/truncations were converted to copies" << endl; + msg << "Use -u switch to list each individually"; + reportInfo(msg.str()); } checker.optimizeAll(); if (checker.getNumReadNoWrite() > 0) { @@ -1619,9 +1670,11 @@ void SleighCompile::checkConsistency(void) return; } if ((!warndeadtemps)&&(checker.getNumWriteNoRead() > 0)) { - cerr << dec << checker.getNumWriteNoRead(); - cerr << " operations wrote to temporaries that were not read" << endl; - cerr << "Use -t switch to list each individually" << endl; + ostringstream msg; + msg << dec << checker.getNumWriteNoRead(); + msg << " operations wrote to temporaries that were not read" << endl; + msg << "Use -t switch to list each individually"; + reportInfo(msg.str()); } } @@ -1659,10 +1712,10 @@ bool SleighCompile::checkLocalExports(Constructor *ct) if (collideOperand >= 0) { noCollisions = false; if (warnalllocalcollisions) { - cerr << "Possible collision with symbols "; - cerr << ct->getOperand(collideOperand)->getName(); - cerr << " and " << ct->getOperand(i)->getName(); - cerr << " in constructor starting at line " << dec << ct->getLineno() << endl; + reportWarning(getLocation(ct), "Possible operand collision between symbols '" + + ct->getOperand(collideOperand)->getName() + + "' and '" + + ct->getOperand(i)->getName() + "'"); } break; // Don't continue } @@ -1687,9 +1740,11 @@ void SleighCompile::checkLocalCollisions(void) sym = tables[i]; } if (collisionCount > 0) { - cerr << "WARNING: " << dec << collisionCount << " constructors with local collisions between operands" << endl; + ostringstream msg; + msg << dec << collisionCount << " constructors with local collisions between operands"; if (!warnalllocalcollisions) - cerr << "Use -c switch to list each individually" << endl; + msg << endl << "Use -c switch to list each individually"; + reportInfo(msg.str()); } } @@ -1699,28 +1754,30 @@ void SleighCompile::checkNops(void) if (noplist.size() > 0) { if (warnallnops) { for(int4 i=0;ibegin();iter!=scope->end();++iter) { LabelSymbol *sym = (LabelSymbol *)*iter; if (sym->getType() != SleighSymbol::label_symbol) continue; if (sym->getRefCount() == 0) - s << " Label <" << sym->getName() << "> was placed but not used\n"; + msg << " Label <" << sym->getName() << "> was placed but not used" << endl; else if (!sym->isPlaced()) - s << " Label <" << sym->getName() << "> was referenced but never placed\n"; + msg << " Label <" << sym->getName() << "> was referenced but never placed" << endl; } - return s.str(); + return msg.str(); } void SleighCompile::addSymbol(SleighSymbol *sym) @@ -1728,33 +1785,79 @@ void SleighCompile::addSymbol(SleighSymbol *sym) { // Make sure symbol table errors are caught try { symtab.addSymbol(sym); + symbolLocationMap[sym] = *getCurrentLocation(); } catch(SleighError &err) { - reportError(err.explain,true); + reportError(err.explain); } } -void SleighCompile::reportError(const string &msg,bool includeline) +const Location *SleighCompile::getLocation(Constructor *ctor) const { - cerr << "Error in " << filename.back() << ' '; - if (includeline) - cerr << "at line " << dec << lineno.back() << ": "; - cerr << msg << endl; + return &ctorLocationMap.at(ctor); +} + +const Location *SleighCompile::getLocation(SleighSymbol *sym) const + +{ + return &symbolLocationMap.at(sym); +} + +const Location *SleighCompile::getCurrentLocation(void) const + +{ + // Update the location cache field + currentLocCache = Location(filename.back(), lineno.back()); + return ¤tLocCache; +} + +string SleighCompile::formatStatusMessage(const Location* loc, const string &msg) +{ + ostringstream s; + if (loc != (Location*)0) { + s << loc->format(); + s << ": "; + } + s << msg; + return s.str(); +} + +void SleighCompile::reportError(const Location* loc, const string &msg) +{ + reportError(formatStatusMessage(loc, msg)); +} + +void SleighCompile::reportError(const string &msg) +{ + cerr << "ERROR " << msg << endl; errors += 1; - if (errors >50) { + if (errors > 1000000) { cerr << "Too many errors: Aborting" << endl; exit(2); } } -void SleighCompile::reportWarning(const string &msg,bool includeline) +void SleighCompile::reportWarning(const Location* loc, const string &msg) +{ + reportWarning(formatStatusMessage(loc, msg)); +} + +void SleighCompile::reportWarning(const string &msg) { - cerr << "Warning in " << filename.back() << ' '; - if (includeline) - cerr << "at line " << dec << lineno.back() << ": "; - cerr << msg << endl; + cerr << "WARNING " << msg << endl; +} + +void SleighCompile::reportInfo(const Location* loc, const string &msg) +{ + reportInfo(formatStatusMessage(loc, msg)); +} + +void SleighCompile::reportInfo(const string &msg) + +{ + cerr << "INFO " << msg << endl; } uintb SleighCompile::getUniqueAddr(void) @@ -1770,7 +1873,7 @@ void SleighCompile::process(void) { // Do all post processing on the parsed data structures checkNops(); if (getDefaultSpace() == (AddrSpace *)0) - reportError("No default space specified",false); + reportError("No default space specified"); if (errors>0) return; checkConsistency(); if (errors>0) return; @@ -1783,8 +1886,7 @@ void SleighCompile::process(void) try { buildXrefs(); // Make sure we can build crossrefs properly } catch(SleighError &err) { - cerr << err.explain << endl; - errors += 1; + reportError(err.explain); return; } checkUniqueAllocation(); @@ -1893,7 +1995,7 @@ TokenSymbol *SleighCompile::defineToken(string *name,uintb *sz) uint4 size = *sz; delete sz; if ((size&7)!=0) { - reportError(*name+"token size must be multiple of 8",true); + reportError(getCurrentLocation(), "'" + *name + "': token size must be multiple of 8"); size = (size/8)+1; } else @@ -1928,7 +2030,7 @@ void SleighCompile::newSpace(SpaceQuality *qual) { if (qual->size == 0) { - reportError("Space definition missing size attribute",true); + reportError(getCurrentLocation(), "Space definition '" + qual->name + "' missing size attribute"); delete qual; return; } @@ -1938,7 +2040,7 @@ void SleighCompile::newSpace(SpaceQuality *qual) insertSpace(spc); if (qual->isdefault) { if (getDefaultSpace() != (AddrSpace *)0) - reportError("Multiple default spaces",true); + reportError(getCurrentLocation(), "Multiple default spaces -- '" + getDefaultSpace()->getName() + "', '" + qual->name + "'"); else { setDefaultSpace(spc->getIndex()); // Make the flagged space the default pcode.setDefaultSpace(spc); @@ -1955,7 +2057,7 @@ SectionSymbol *SleighCompile::newSectionSymbol(const string &nm) try { symtab.addGlobalSymbol(sym); } catch(SleighError &err) { - reportError(err.explain,true); + reportError(getCurrentLocation(), err.explain); } sections.push_back(sym); numSections = sections.size(); @@ -1995,11 +2097,11 @@ void SleighCompile::defineBitrange(string *name,VarnodeSymbol *sym,uint4 bitoffs delete name; uint4 size = 8*sym->getSize(); // Number of bits if (numb == 0) { - reportError("Size of bitrange is zero for: "+namecopy,true); + reportError(getCurrentLocation(), "'" + namecopy + "': size of bitrange is zero"); return; } if ((bitoffset >= size)||((bitoffset+numb)>size)) { - reportError("Bad bitrange for: "+namecopy,true); + reportError(getCurrentLocation(), "'" + namecopy + "': bad bitrange"); return; } if ((bitoffset%8 == 0)&&(numb%8 == 0)) { @@ -2050,13 +2152,13 @@ void SleighCompile::attachValues(vector *symlist,vector *n { SleighSymbol *dupsym = dedupSymbolList(symlist); if (dupsym != (SleighSymbol *)0) - reportWarning("\"attach values\" list contains duplicate entries: "+dupsym->getName(),true); + reportWarning(getCurrentLocation(), "'attach values' list contains duplicate entries: "+dupsym->getName()); for(int4 i=0;isize();++i) { ValueSymbol *sym = (ValueSymbol *)(*symlist)[i]; if (sym == (ValueSymbol *)0) continue; PatternValue *patval = sym->getPatternValue(); if (patval->maxValue() + 1 != numlist->size()) { - reportError("Attach value " + sym->getName() + " is wrong size for list", true); + reportError(getCurrentLocation(), "Attach value '" + sym->getName() + "' is wrong size for list"); } symtab.replaceSymbol(sym, new ValueMapSymbol(sym->getName(),patval,*numlist)); } @@ -2069,13 +2171,13 @@ void SleighCompile::attachNames(vector *symlist,vector * { SleighSymbol *dupsym = dedupSymbolList(symlist); if (dupsym != (SleighSymbol *)0) - reportWarning("\"attach names\" list contains duplicate entries: "+dupsym->getName(),true); + reportWarning(getCurrentLocation(), "'attach names' list contains duplicate entries: "+dupsym->getName()); for(int4 i=0;isize();++i) { ValueSymbol *sym = (ValueSymbol *)(*symlist)[i]; if (sym == (ValueSymbol *)0) continue; PatternValue *patval = sym->getPatternValue(); if (patval->maxValue() + 1 != names->size()) { - reportError("Attach name " + sym->getName() + " is wrong size for list", true); + reportError(getCurrentLocation(), "Attach name '" + sym->getName() + "' is wrong size for list"); } symtab.replaceSymbol(sym,new NameSymbol(sym->getName(),patval,*names)); } @@ -2088,13 +2190,13 @@ void SleighCompile::attachVarnodes(vector *symlist,vectorgetName(),true); + reportWarning(getCurrentLocation(), "'attach variables' list contains duplicate entries: "+dupsym->getName()); for(int4 i=0;isize();++i) { ValueSymbol *sym = (ValueSymbol *)(*symlist)[i]; if (sym == (ValueSymbol *)0) continue; PatternValue *patval = sym->getPatternValue(); if (patval->maxValue() + 1 != varlist->size()) { - reportError("Attach varnode " + sym->getName() + " is wrong size for list", true); + reportError(getCurrentLocation(), "Attach varnode '" + sym->getName() + "' is wrong size for list"); } int4 sz = 0; for(int4 j=0;jsize();++j) { @@ -2103,7 +2205,9 @@ void SleighCompile::attachVarnodes(vector *symlist,vectorgetFixedVarnode().size; else if (sz != vsym->getFixedVarnode().size) { - reportError("Attach statement contains varnodes of different sizes",true); + ostringstream msg; + msg << "Attach statement contains varnodes of different sizes -- " << dec << sz << " != " << dec << vsym->getFixedVarnode().size; + reportError(getCurrentLocation(), msg.str()); break; } } @@ -2160,7 +2264,7 @@ void SleighCompile::defineOperand(OperandSymbol *sym,PatternExpression *patexp) // the operand's offset is irrelevant } catch(SleighError &err) { - reportError(err.explain,true); + reportError(getCurrentLocation(), err.explain); PatternExpression::release(patexp); } } @@ -2184,7 +2288,7 @@ PatternEquation *SleighCompile::defineInvisibleOperand(TripleSymbol *sym) } } catch(SleighError &err) { - reportError(err.explain,true); + reportError(getCurrentLocation(), err.explain); } return res; } @@ -2194,7 +2298,7 @@ void SleighCompile::selfDefine(OperandSymbol *sym) { // Define operand as global symbol of same name TripleSymbol *glob = dynamic_cast(symtab.findSymbol(sym->getName(),1)); if (glob == (TripleSymbol *)0) { - reportError(sym->getName()+": No matching global symbol",true); + reportError(getCurrentLocation(), "No matching global symbol '" + sym->getName() + "'"); return; } SleighSymbol::symbol_type tp = glob->getType(); @@ -2206,7 +2310,7 @@ void SleighCompile::selfDefine(OperandSymbol *sym) sym->defineOperand(glob); } catch(SleighError &err) { - reportError(err.explain,true); + reportError(getCurrentLocation(), err.explain); } } @@ -2306,12 +2410,9 @@ vector *SleighCompile::createMacroUse(MacroSymbol *sym,vectorgetNumOperands() != param->size()) { - string errmsg = "Invocation of macro \"" + sym->getName(); - if (param->size() > sym->getNumOperands()) - errmsg += "\" passes too many parameters"; - else - errmsg += "\" passes too few parameters"; - reportError(errmsg,true); + bool tooManyParams = param->size() > sym->getNumOperands(); + string errmsg = "Invocation of macro '" + sym->getName() + "' passes too " + (tooManyParams ? "many" : "few") + " parameters"; + reportError(getCurrentLocation(), errmsg); return new vector; } compareMacroParams(sym,*param); @@ -2394,6 +2495,7 @@ Constructor *SleighCompile::createConstructor(SubtableSymbol *sym) curmacro = (MacroSymbol *)0; // Not currently defining a macro curct = new Constructor(sym); curct->setLineno(lineno.back()); + ctorLocationMap[curct] = *getCurrentLocation(); sym->addConstructor(curct); symtab.addScope(); // Make a new symbol scope for our constructor pcode.resetLabelCount(); @@ -2448,7 +2550,9 @@ bool SleighCompile::finalizeSections(Constructor *big,SectionVector *vec) string errstring; errstring = checkSymbols(cur.scope); // Check labels in the section's scope - if (errstring.size()==0) { + if (errstring.size()!=0) { + errors.push_back(sectionstring + errstring); + } else { if (!expandMacros(cur.section,macrotable)) errors.push_back(sectionstring + "Could not expand macros"); vector check; @@ -2472,10 +2576,11 @@ bool SleighCompile::finalizeSections(Constructor *big,SectionVector *vec) } if (cur.section->delaySlot() != 0) { // Delay slot is present in this constructor if (root != big->getParent()) { // it is not in a root constructor - reportWarning("Delay slot used in",false); - cerr << " "; - big->printInfo(cerr); - cerr << endl; + ostringstream msg; + msg << "Delay slot used in non-root constructor "; + big->printInfo(msg); + msg << endl; + reportWarning(getLocation(big), msg.str()); } if (cur.section->delaySlot() > maxdelayslotbytes) // Keep track of maximum delayslot parameter maxdelayslotbytes = cur.section->delaySlot(); @@ -2494,9 +2599,9 @@ bool SleighCompile::finalizeSections(Constructor *big,SectionVector *vec) ostringstream s; s << "in "; big->printInfo(s); - reportError(s.str(),false); + reportError(getLocation(big), s.str()); for(int4 j=0;jgetName(),false); - cerr << errstring; + reportError(getCurrentLocation(), "In definition of macro '"+sym->getName() + "': " + errstring); return; } if (!expandMacros(rtl,macrotable)) { - reportError("Could not expand submacro in definition of macro "+sym->getName(),true); + reportError(getCurrentLocation(), "Could not expand submacro in definition of macro '" + sym->getName() + "'"); return; } PcodeCompile::propagateSize(rtl); // Propagate size information (as much as possible) @@ -2654,9 +2758,9 @@ void SleighCompile::buildMacro(MacroSymbol *sym,ConstructTpl *rtl) void SleighCompile::recordNop(void) { - ostringstream s; - s << "NOP detected at " << filename.back() << ':' << dec << lineno.back(); - noplist.push_back(s.str()); + string msg = formatStatusMessage(getCurrentLocation(), "NOP detected"); + + noplist.push_back(msg); } static int4 run_compilation(const char *filein,const char *fileout,SleighCompile &compiler) @@ -2853,9 +2957,9 @@ int main(int argc,char **argv) enableAllCollisionWarning = true; else if (argv[i][1] == 'n') enableAllNopWarning = true; - else if (argv[1][1] == 't') + else if (argv[i][1] == 't') enableDeadTempWarning = true; - else if (argv[1][1] == 'e') + else if (argv[i][1] == 'e') enforceLocalKeyWord = true; #ifdef YYDEBUG else if (argv[i][1] == 'x') @@ -2880,10 +2984,10 @@ int main(int argc,char **argv) if (i != argc) dirStr = argv[i]; findSlaSpecs(slaspecs, dirStr,SLASPECEXT); - cout << "Compiling " << slaspecs.size() << " slaspec files in " << dirStr << "\n"; + cout << "Compiling " << dec << slaspecs.size() << " slaspec files in " << dirStr << endl; for(int4 j=0;j "sleigh file.slaspec file.sla" + if (autoExtInSet || extIsSLASPECEXT) { //Assumed format of at least "sleigh file" -> "sleigh file.slaspec file.sla" string fileoutSTR = fileinPreExt; fileoutSTR.append(SLAEXT); retval = run_compilation(fileinExamine.c_str(),fileoutSTR.c_str(),compiler); diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/slgh_compile.hh b/Ghidra/Features/Decompiler/src/decompile/cpp/slgh_compile.hh index dd12825809..3cce16aeed 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/slgh_compile.hh +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/slgh_compile.hh @@ -78,6 +78,8 @@ public: static SubtableSymbol *getCurrentSubtable(const list &stack); }; +class SleighCompile; + class ConsistencyChecker { struct OptimizeRecord { int4 writeop; @@ -91,6 +93,7 @@ class ConsistencyChecker { OptimizeRecord(void) { writeop = -1; readop = -1; inslot=-1; writecount=0; readcount=0; writesection=-2; readsection=-2; opttype=-1; } }; + SleighCompile *slgh; int4 unnecessarypcode; int4 readnowrite; int4 writenoread; @@ -99,6 +102,8 @@ class ConsistencyChecker { SubtableSymbol *root_symbol; vector postorder; map sizemap; // Sizes associated with tables + void reportError(const Location* loc, const string &msg); + void reportWarning(const Location* loc, const string &msg); OperandSymbol *getOperandSymbol(int4 slot,OpTpl *op,Constructor *ct); void printOpName(ostream &s,OpTpl *op); void printOpError(OpTpl *op,Constructor *ct,int4 err1,int4 err2,const string &message); @@ -124,7 +129,7 @@ class ConsistencyChecker { void checkUnusedTemps(Constructor *ct,const map &recs); void optimize(Constructor *ct); public: - ConsistencyChecker(SubtableSymbol *rt,bool unnecessary,bool warndead); + ConsistencyChecker(SleighCompile *sleigh, SubtableSymbol *rt,bool unnecessary,bool warndead); bool test(void); bool testTruncations(bool isbigendian); void optimizeAll(void); @@ -140,8 +145,6 @@ struct FieldContext { FieldContext(VarnodeSymbol *s,FieldQuality *q) { sym=s; qual=q; } }; -class SleighCompile; - class MacroBuilder : public PcodeBuilder { SleighCompile *slgh; bool haserror; @@ -150,7 +153,7 @@ class MacroBuilder : public PcodeBuilder { bool transferOp(OpTpl *op,vector ¶ms); virtual void dump( OpTpl *op ); void free(void); - void reportError(const string &val); + void reportError(const Location* loc, const string &val); public: MacroBuilder(SleighCompile *sl,vector &ovec,uint4 lbcnt) : PcodeBuilder(lbcnt),outvec(ovec) { slgh = sl; haserror = false; } @@ -166,7 +169,9 @@ public: class SleighPcode : public PcodeCompile { SleighCompile *compiler; virtual uintb allocateTemp(void); - virtual void reportError(const string &msg); + virtual const Location *getLocation(SleighSymbol *sym) const; + virtual void reportError(const Location* loc, const string &msg); + virtual void reportWarning(const Location* loc, const string &msg); virtual void addSymbol(SleighSymbol *sym); public: SleighPcode(void) : PcodeCompile() { compiler = (SleighCompile *)0; } @@ -191,6 +196,8 @@ private: vector relpath; // Relative path (to cwd) for each filename vector filename; // Stack of current files being parsed vector lineno; // Current line number for each file in stack + map ctorLocationMap; // Map constructor to its defining parse location + map symbolLocationMap; // Map symbol to its defining parse location int4 userop_count; // Number of userops defined bool warnunnecessarypcode; // True if we warn of unnecessary ZEXT or SEXT bool warndeadtemps; // True if we warn of temporaries that are written but not read @@ -198,7 +205,10 @@ private: bool warnalllocalcollisions; // True if local export collisions generate individual warnings bool warnallnops; // True if pcode NOPs generate individual warnings vector noplist; // List of individual NOP warnings + mutable Location currentLocCache; // Location for (last) request of current location int4 errors; + + const Location* getCurrentLocation(void) const; void predefinedSymbols(void); int4 calcContextVarLayout(int4 start,int4 sz,int4 numbits); void buildDecisionTrees(void); @@ -220,9 +230,18 @@ private: void checkUniqueAllocation(void); public: SleighCompile(void); - void reportError(const string &msg,bool includeline); - void reportWarning(const string &msg,bool includeline); + const Location *getLocation(Constructor* ctor) const; + const Location *getLocation(SleighSymbol *sym) const; + string formatStatusMessage(const Location* loc, const string &msg); + void reportError(const string &msg); + void reportError(const Location *loc, const string &msg); + void reportWarning(const string &msg); + void reportWarning(const Location *loc, const string &msg); int4 numErrors(void) const { return errors; } + void reportInfo(const string &msg); + void reportInfo(const Location *loc, const string &msg); + + uintb getUniqueAddr(void); void setUnnecessaryPcodeWarning(bool val) { warnunnecessarypcode = val; } void setDeadTempWarning(bool val) { warndeadtemps = val; } diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/slghparse.y b/Ghidra/Features/Decompiler/src/decompile/cpp/slghparse.y index 65b481b40e..b536307a40 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/slghparse.y +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/slghparse.y @@ -577,6 +577,6 @@ anysymbol: SPACESYM { $$ = $1; } int yyerror(const char *s) { - slgh->reportError(s,true); + slgh->reportError(s); return 0; } diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/slghpatexpress.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/slghpatexpress.cc index 9982823f9f..3b7534f091 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/slghpatexpress.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/slghpatexpress.cc @@ -52,44 +52,76 @@ int4 TokenPattern::resolveTokens(const TokenPattern &tok1,const TokenPattern &to throw SleighError("Right/left ellipsis"); else if (tok2.leftellipsis) leftellipsis = true; - else if (tok1.toklist.size() != minsize) - throw SleighError("Mismatched pattern sizes"); + else if (tok1.toklist.size() != minsize) { + ostringstream msg; + msg << "Mismatched pattern sizes -- " << dec << tok1.toklist.size() + << " != " + << dec << minsize; + throw SleighError(msg.str()); + } else if (tok1.toklist.size()==tok2.toklist.size()) - throw SleighError("Pattern size cannot vary (missing ... ?)"); + throw SleighError("Pattern size cannot vary (missing '...'?)"); } else if (tok1.rightellipsis) { if (tok2.leftellipsis) throw SleighError("Left/right ellipsis"); else if (tok2.rightellipsis) rightellipsis = true; - else if (tok1.toklist.size() != minsize) - throw SleighError("Mismatched pattern sizes"); + else if (tok1.toklist.size() != minsize) { + ostringstream msg; + msg << "Mismatched pattern sizes -- " << dec << tok1.toklist.size() + << " != " + << dec << minsize; + throw SleighError(msg.str()); + } else if (tok1.toklist.size()==tok2.toklist.size()) - throw SleighError("Pattern size cannot vary (missing ... ?)"); + throw SleighError("Pattern size cannot vary (missing '...'?)"); } else { if (tok2.leftellipsis) { reversedirection = true; - if (tok2.toklist.size() != minsize) - throw SleighError("Mismatched pattern sizes"); + if (tok2.toklist.size() != minsize) { + ostringstream msg; + msg << "Mismatched pattern sizes -- " << dec << tok2.toklist.size() + << " != " + << dec << minsize; + throw SleighError(msg.str()); + } else if (tok1.toklist.size()==tok2.toklist.size()) - throw SleighError("Pattern size cannot vary (missing ... ?)"); + throw SleighError("Pattern size cannot vary (missing '...'?)"); } else if (tok2.rightellipsis) { - if (tok2.toklist.size() != minsize) - throw SleighError("Mismatched pattern sizes"); + if (tok2.toklist.size() != minsize) { + ostringstream msg; + msg << "Mismatched pattern sizes -- " << dec << tok2.toklist.size() + << " != " + << dec << minsize; + throw SleighError(msg.str()); + } else if (tok1.toklist.size()==tok2.toklist.size()) - throw SleighError("Pattern size cannot vary (missing ... ?)"); + throw SleighError("Pattern size cannot vary (missing '...'?)"); } else { - if (tok2.toklist.size() != tok1.toklist.size()) - throw SleighError("Mismatched pattern sizes"); + if (tok2.toklist.size() != tok1.toklist.size()) { + ostringstream msg; + msg << "Mismatched pattern sizes -- " << dec << tok2.toklist.size() + << " != " + << dec << tok1.toklist.size(); + throw SleighError(msg.str()); + } } } if (reversedirection) { for(int4 i=0;icalcContextLayout(); return WITH filebuffers.pop_back(); slgh->parseFileFinished(); } - diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/slghsymbol.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/slghsymbol.cc index c5bfa420a4..8b9417e466 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/slghsymbol.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/slghsymbol.cc @@ -86,7 +86,7 @@ void SymbolTable::addGlobalSymbol(SleighSymbol *a) a->scopeid = scope->getId(); SleighSymbol *res = scope->addSymbol(a); if (res != a) - throw SleighError("Duplicate symbol name: "+a->getName()); + throw SleighError("Duplicate symbol name '" + a->getName() + "'"); } void SymbolTable::addSymbol(SleighSymbol *a) @@ -2017,13 +2017,8 @@ void DecisionProperties::identicalPattern(Constructor *a,Constructor *b) if ((!a->isError())&&(!b->isError())) { a->setError(true); b->setError(true); - ostringstream s; - s << "Constructors with identical patterns: \n "; - a->printInfo(s); - s << "\n "; - b->printInfo(s); - s << endl; - identerrors.push_back(s.str()); + + identerrors.push_back(make_pair(a, b)); } } @@ -2033,13 +2028,8 @@ void DecisionProperties::conflictingPattern(Constructor *a,Constructor *b) if ((!a->isError())&&(!b->isError())) { a->setError(true); b->setError(true); - ostringstream s; - s << "Constructor patterns cannot be distinguished: \n "; - a->printInfo(s); - s << "\n "; - b->printInfo(s); - s << endl; - conflicterrors.push_back(s.str()); + + conflicterrors.push_back(make_pair(a, b)); } } diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/slghsymbol.hh b/Ghidra/Features/Decompiler/src/decompile/cpp/slghsymbol.hh index deac712fe2..34cc142708 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/slghsymbol.hh +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/slghsymbol.hh @@ -525,13 +525,13 @@ public: }; class DecisionProperties { - vector identerrors; - vector conflicterrors; + vector> identerrors; + vector> conflicterrors; public: void identicalPattern(Constructor *a,Constructor *b); void conflictingPattern(Constructor *a,Constructor *b); - const vector &getIdentErrors(void) const { return identerrors; } - const vector &getConflictErrors(void) const { return conflicterrors; } + const vector> &getIdentErrors(void) const { return identerrors; } + const vector> &getConflictErrors(void) const { return conflicterrors; } }; class DecisionNode { diff --git a/Ghidra/Framework/SoftwareModeling/src/main/antlr/ghidra/sleigh/grammar/SleighCompiler.g b/Ghidra/Framework/SoftwareModeling/src/main/antlr/ghidra/sleigh/grammar/SleighCompiler.g index 12c53ee56b..f10c5e833c 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/antlr/ghidra/sleigh/grammar/SleighCompiler.g +++ b/Ghidra/Framework/SoftwareModeling/src/main/antlr/ghidra/sleigh/grammar/SleighCompiler.g @@ -66,7 +66,7 @@ scope Block { } private void redefinedError(SleighSymbol sym, Tree t, String what) { - String msg = "symbol " + sym.getName() + " (from " + sym.getLocation() + ") redefined as " + what; + String msg = "symbol '" + sym.getName() + "' (from " + sym.getLocation() + ") redefined as " + what; reportError(find(t), msg); } @@ -76,17 +76,17 @@ scope Block { } private void wrongSymbolTypeError(SleighSymbol sym, Location where, String type, String purpose) { - String msg = sym.getType() + " " + sym + " (defined at " + sym.getLocation() + ") is wrong type (should be " + type + ") in " + purpose; + String msg = sym.getType() + " '" + sym + "' (defined at " + sym.getLocation() + ") is wrong type (should be " + type + ") in " + purpose; reportError(where, msg); } private void undeclaredSymbolError(SleighSymbol sym, Location where, String purpose) { - String msg = sym + " (used in " + purpose + ") is not declared in the pattern list"; + String msg = "'" + sym + "' (used in " + purpose + ") is not declared in the pattern list"; reportError(where, msg); } private void unknownSymbolError(String text, Location loc, String type, String purpose) { - String msg = "unknown " + type + " " + text + " in " + purpose; + String msg = "unknown " + type + " '" + text + "' in " + purpose; reportError(loc, msg); } @@ -205,7 +205,7 @@ fielddef long start = $s.value.longValue(); long finish = $e.value.longValue(); if (finish < start) { - reportError(find($t), "field " + $n.value.getText() + " starts at " + start + " and ends at " + finish); + reportError(find($t), "field '" + $n.value.getText() + "' starts at " + start + " and ends at " + finish); } $fielddef::fieldQuality = new FieldQuality($n.value.getText(), find($t), $s.value.longValue(), $e.value.longValue()); } @@ -426,7 +426,7 @@ typemod space_class type = space_class.valueOf(typeName); $spacedef::quality.type = type; } catch(IllegalArgumentException e) { - reportError(find(n), "invalid space type " + typeName); + reportError(find(n), "invalid space type '" + typeName + "'"); } } } @@ -829,7 +829,7 @@ pattern_symbol[String purpose] returns [PatternExpression expr] } else if(sym.getType() == symbol_type.operand_symbol) { OperandSymbol os = (OperandSymbol) sym; if (os.getDefiningSymbol() != null && os.getDefiningSymbol().getType() == symbol_type.subtable_symbol) { - reportError(find($s), "Subtable symbol " + sym.getName() + " is not allowed in context block"); + reportError(find($s), "Subtable symbol '" + sym.getName() + "' is not allowed in context block"); } $expr = os.getPatternExpression(); } else if(sym.getType() == symbol_type.start_symbol @@ -847,7 +847,7 @@ pattern_symbol[String purpose] returns [PatternExpression expr] FamilySymbol z = (FamilySymbol) sym; $expr = z.getPatternValue(); } else { - reportError(find($s), "Global symbol " + sym.getName() + " is not allowed in action expression"); + reportError(find($s), "Global symbol '" + sym.getName() + "' is not allowed in action expression"); } } else { wrongSymbolTypeError(sym, find($s), "start, end, operand, epsilon, or varnode", purpose); @@ -908,7 +908,7 @@ cstatement[VectorSTL r] } else if(sym.getType() == symbol_type.context_symbol) { ContextSymbol t = (ContextSymbol) sym; if (!sc.contextMod(r, t, e)) { - reportError(find($id), "Cannot use 'inst_next' to set context variable: " + t.getName()); + reportError(find($id), "Cannot use 'inst_next' to set context variable: '" + t.getName() + "'"); } } else if(sym.getType() == symbol_type.operand_symbol) { OperandSymbol t = (OperandSymbol) sym; @@ -919,7 +919,7 @@ cstatement[VectorSTL r] } | ^(OP_APPLY ^(OP_IDENTIFIER id=.) ^(OP_IDENTIFIER arg1=.) ^(OP_IDENTIFIER arg2=.)) { if (!"globalset".equals(id.getText())) { - reportError(find($id), "unknown context block function " + id.getText()); + reportError(find($id), "unknown context block function '" + id.getText() + "'"); } else { SleighSymbol sym = sc.findSymbol($arg2.getText()); if (sym == null) { diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcode/utils/MessageFormattingUtils.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcode/utils/MessageFormattingUtils.java new file mode 100644 index 0000000000..fb66f8d712 --- /dev/null +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcode/utils/MessageFormattingUtils.java @@ -0,0 +1,23 @@ +package ghidra.pcode.utils; + +import ghidra.sleigh.grammar.Location; + +public final class MessageFormattingUtils { + + /** + * Format a log message. + * + * @param location Referenced file location + * @param message Message + * @return Formatted string with location prepended to message. + */ + public static String format(Location location, CharSequence message) { + StringBuilder sb = new StringBuilder(); + if (location != null) { + sb.append(location).append(": "); + } + sb.append(message); + return sb.toString().trim(); + } + +} diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/context/ParserContext.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/context/ParserContext.java index 5cfa473874..b0b5103573 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/context/ParserContext.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/context/ParserContext.java @@ -171,7 +171,7 @@ public class ParserContext { } public int getInstructionBytes(int bytestart, int size, int off) { - // Get bytes from the instruction stream into a intm + // Get bytes from the instruction stream into an int // (assuming big endian format) off += bytestart; if (off >= 16) { diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/sleighbase/SleighBase.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/sleighbase/SleighBase.java index cf93c607ad..b6836ab648 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/sleighbase/SleighBase.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/sleighbase/SleighBase.java @@ -18,6 +18,7 @@ package ghidra.pcodeCPort.sleighbase; import java.io.PrintStream; import generic.stl.*; +import ghidra.pcode.utils.MessageFormattingUtils; import ghidra.pcodeCPort.context.SleighError; import ghidra.pcodeCPort.pcoderaw.VarnodeData; import ghidra.pcodeCPort.slghpatexpress.ContextField; @@ -26,10 +27,13 @@ import ghidra.pcodeCPort.space.AddrSpace; import ghidra.pcodeCPort.space.spacetype; import ghidra.pcodeCPort.translate.Translate; import ghidra.pcodeCPort.utils.XmlUtils; +import ghidra.sleigh.grammar.Location; +import ghidra.util.Msg; public abstract class SleighBase extends Translate implements NamedSymbolProvider { - // NOTE: restoreXml method removed as it is only used by the decompiler's implementation + // NOTE: restoreXml method removed as it is only used by the decompiler's + // implementation public static final int SLA_FORMAT_VERSION = 2; // What format of the .sla file this produces // This value should always match SleighLanguage.SLA_FORMAT_VERSION @@ -65,6 +69,18 @@ public abstract class SleighBase extends Translate implements NamedSymbolProvide return (root != null); } + public void reportError(Location location, String msg) { + Msg.error(this, MessageFormattingUtils.format(location, msg)); + } + + public void reportError(Location location, String msg, Throwable t) { + Msg.error(this, MessageFormattingUtils.format(location, msg), t); + } + + public void reportWarning(Location location, String msg) { + Msg.warn(this, MessageFormattingUtils.format(location, msg)); + } + protected void buildXrefs() { SymbolScope glb = symtab.getGlobalScope(); int errors = 0; @@ -74,29 +90,26 @@ public abstract class SleighBase extends Translate implements NamedSymbolProvide for (iter = glb.begin(); !iter.isEnd(); iter.increment()) { SleighSymbol sym = iter.get(); if (sym.getType() == symbol_type.varnode_symbol) { - Pair, Boolean> res = - varnode_xref.insert((VarnodeSymbol) sym); + Pair, Boolean> res = varnode_xref.insert((VarnodeSymbol) sym); if (!res.second) { - buffer.append("Duplicate (offset,size) pair for registers: "); - buffer.append(sym.getName()); - buffer.append(" ("); - buffer.append(sym.getLocation()); - buffer.append(") and "); - buffer.append(res.first.get().getName()); - buffer.append(" ("); - buffer.append(res.first.get().getLocation()); - buffer.append(")\n"); + + String msg = String.format("Duplicate (offset,size) pair for registers: %s (%s) and %s (%s)", + sym.getName(), sym.getLocation(), res.first.get().getName(), res.first.get().getLocation()); + + buffer.append(msg + "\n"); + + reportError(sym.getLocation(), msg); + reportError(res.first.get().getLocation(), msg); + errors += 1; } - } - else if (sym.getType() == symbol_type.userop_symbol) { + } else if (sym.getType() == symbol_type.userop_symbol) { int index = ((UserOpSymbol) sym).getIndex(); while (userop.size() <= index) { userop.push_back(""); } userop.set(index, sym.getName()); - } - else if (sym.getType() == symbol_type.context_symbol) { + } else if (sym.getType() == symbol_type.context_symbol) { ContextSymbol csym = (ContextSymbol) sym; ContextField field = (ContextField) csym.getPatternValue(); int startbit = field.getStartBit(); @@ -137,10 +150,10 @@ public abstract class SleighBase extends Translate implements NamedSymbolProvide public VarnodeData getRegister(String nm) { VarnodeSymbol sym = (VarnodeSymbol) findSymbol(nm); if (sym == null) { - throw new SleighError("Unknown register name: " + nm, null); + throw new SleighError("Unknown register name '" + nm + "'", null); } if (sym.getType() != symbol_type.varnode_symbol) { - throw new SleighError("Symbol is not a register: " + nm, null); + throw new SleighError("Symbol is not a register '" + nm + "'", sym.location); } return sym.getFixedVarnode(); } @@ -208,8 +221,8 @@ public abstract class SleighBase extends Translate implements NamedSymbolProvide s.append(">\n"); for (int i = 0; i < numSpaces(); ++i) { AddrSpace spc = getSpace(i); - if ((spc.getType() == spacetype.IPTR_CONSTANT) || - (spc.getType() == spacetype.IPTR_FSPEC) || (spc.getType() == spacetype.IPTR_IOP)) { + if ((spc.getType() == spacetype.IPTR_CONSTANT) || (spc.getType() == spacetype.IPTR_FSPEC) + || (spc.getType() == spacetype.IPTR_IOP)) { continue; } spc.saveXml(s); diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slgh_compile/ConsistencyChecker.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slgh_compile/ConsistencyChecker.java index cd6c8aa4ab..21cba651a1 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slgh_compile/ConsistencyChecker.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slgh_compile/ConsistencyChecker.java @@ -25,6 +25,7 @@ import ghidra.pcodeCPort.semantics.ConstTpl.const_type; import ghidra.pcodeCPort.semantics.ConstTpl.v_field; import ghidra.pcodeCPort.slghsymbol.*; import ghidra.pcodeCPort.space.AddrSpace; +import ghidra.sleigh.grammar.Location; import ghidra.util.Msg; class ConsistencyChecker { @@ -97,7 +98,8 @@ class ConsistencyChecker { if ((vnout == 0) || (vn0 == 0)) { return true; } - printOpError(op, ct, -1, 0, "Input and output sizes must match"); + printOpError(op, ct, -1, 0, "Input and output sizes must match; " + + op.getIn(0).getSize() + " != " + op.getOut().getSize()); return false; case CPUI_INT_ADD: case CPUI_INT_SUB: @@ -324,7 +326,7 @@ class ConsistencyChecker { if ((vnout == 0) || (vn0 == 0)) { return true; } - if ((vnout == vn0) && (vn1 == 0)) { // No actual truncation is occuring + if ((vnout == vn0) && (vn1 == 0)) { // No actual truncation is occurring dealWithUnnecessaryTrunc(op, ct); return true; } @@ -478,6 +480,30 @@ class ConsistencyChecker { } } + private void reportError(Location location, CharSequence message) { + if (location == null) { + Msg.error(this, message); + return; + } + StringBuilder sb = new StringBuilder(); + sb.append(location).append(": ").append(message); + + Msg.error(this, sb.toString()); + } + + private void reportWarning(Location location, CharSequence message) { + if (location == null) { + Msg.warn(this, message); + return; + } + + StringBuilder sb = new StringBuilder(); + + sb.append(location).append(": ").append(message); + + Msg.warn(this, sb.toString()); + } + void printOpError(OpTpl op, Constructor ct, int err1, int err2, String message) { SubtableSymbol sym = ct.getParent(); OperandSymbol op1, op2; @@ -489,24 +515,30 @@ class ConsistencyChecker { else { op2 = null; } - Msg.error(this, "Size restriction error in table \"" + sym.getName() + - "\" in constructor at " + ct.location + " from operation located at " + op.location); StringBuilder sb = new StringBuilder(); + sb.append("Size restriction error in table '") + .append(sym.getName()) + .append("' in constructor at ").append(ct.location) + .append("\n"); + + sb.append(" Problem"); if ((op1 != null) && (op2 != null)) { - sb.append(" with \"" + op1.getName() + "\" and \"" + op2.getName() + "\""); + sb.append(" with '" + op1.getName() + "' and '" + op2.getName() + "'"); } else if (op1 != null) { - sb.append(" with \"" + op1.getName() + "\""); + sb.append(" with '" + op1.getName() + "'"); } else if (op2 != null) { - sb.append(" with \"" + op2.getName() + "\""); + sb.append(" with '" + op2.getName() + "'"); } - sb.append(" in \"" + getOpName(op) + "\" operator"); - Msg.error(this, sb.toString()); + sb.append(" in '" + getOpName(op) + "' operator"); + + sb.append("\n ").append(message); + + reportError(op.location, sb); - Msg.error(this, " " + message); } int recoverSize(ConstTpl sizeconst, Constructor ct) { @@ -544,7 +576,7 @@ class ConsistencyChecker { } private void handle(String msg, Constructor ct) { - Msg.error(this, "Unsigned comparison with " + msg + " in constructor at " + ct.location); + reportError(ct.location, " Unsigned comparison with " + msg + " in constructor"); } private void handleZero(String trueOrFalse, Constructor ct) { @@ -708,8 +740,9 @@ class ConsistencyChecker { HandleTpl exportres = ct.getTempl().getResult(); if (exportres != null) { if (seenemptyexport && (!seennonemptyexport)) { - Msg.error(this, "Table " + sym.getName() + " exports inconsistently"); - Msg.error(this, "Constructor at " + ct.location + " is first inconsistency"); + reportError(ct.location, String.format( + "Table '%s' exports inconsistently; Constructor at %s is first inconsitency", + sym.getName(), ct.location)); testresult = false; } seennonemptyexport = true; @@ -718,15 +751,17 @@ class ConsistencyChecker { tablesize = exsize; } if ((exsize != 0) && (exsize != tablesize)) { - Msg.error(this, "Table " + sym.getName() + " has inconsistent export size."); - Msg.error(this, "Constructor at " + ct.location + " is first conflict"); + reportError(ct.location, String.format( + "Table '%s' has inconsistent export size; Constructor at %s is first conflict", + sym.getName(), ct.location)); testresult = false; } } else { if (seennonemptyexport && (!seenemptyexport)) { - Msg.error(this, "Table " + sym.getName() + " exports inconsistently"); - Msg.error(this, "Constructor at " + ct.location + " is first inconsistency"); + reportError(ct.location, String.format( + "Table '%s' exports inconsistently; Constructor at %s is first inconsitency", + sym.getName(), ct.location)); testresult = false; } seenemptyexport = true; @@ -734,7 +769,8 @@ class ConsistencyChecker { } if (seennonemptyexport) { if (tablesize == 0) { - Msg.error(this, "Warning: Table " + sym.getName() + " exports size 0"); + reportWarning(sym.location, "Table '" + sym.getName() + "' exports size 0"); + } sizemap.put(sym, tablesize); // Remember recovered size } @@ -749,8 +785,7 @@ class ConsistencyChecker { // input size is the same as the output size void dealWithUnnecessaryExt(OpTpl op, Constructor ct) { if (printextwarning) { - Msg.error(this, "Unnecessary \"" + getOpName(op) + "\" in constructor from " + - ct.getFilename() + " starting at line " + ct.getLineno()); + reportWarning(op.location, "Unnecessary '" + getOpName(op) + "'"); } op.setOpcode(OpCode.CPUI_COPY); // Equivalent to copy unnecessarypcode += 1; @@ -758,8 +793,7 @@ class ConsistencyChecker { void dealWithUnnecessaryTrunc(OpTpl op, Constructor ct) { if (printextwarning) { - Msg.error(this, "Unnecessary \"" + getOpName(op) + "\" in constructor from " + - ct.getFilename() + " starting at line " + ct.getLineno()); + reportWarning(op.location, "Unnecessary '" + getOpName(op) + "'"); } op.setOpcode(OpCode.CPUI_COPY); // Equivalent to copy op.removeInput(1); @@ -853,14 +887,8 @@ class ConsistencyChecker { } } - static boolean possibleIntersection(VarnodeTpl vn1, VarnodeTpl vn2) { // Conservatively - // test - // whether - // vn1 - // and - // vn2 - // can - // intersect + static boolean possibleIntersection(VarnodeTpl vn1, VarnodeTpl vn2) { + // Conservatively test whether vn1 and vn2 can intersect if (vn1.getSpace().isConstSpace()) { return false; } @@ -1116,15 +1144,12 @@ class ConsistencyChecker { OptimizeRecord currec = pair.second; if (currec.readcount == 0) { if (printdeadwarning) { - Msg.error(this, - "Warning: temporary is written but not read in constructor at " + - ct.location); + reportWarning(ct.location, "Temporary is written but not read"); } writenoread += 1; } else if (currec.writecount == 0) { - Msg.error(this, - "Error: temporary is read but not written in constructor at " + ct.location); + reportError(ct.location, "Temporary is read but not written"); readnowrite += 1; } iter.increment(); diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slgh_compile/PcodeCompile.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slgh_compile/PcodeCompile.java index 1975dd8c25..21f8b30745 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slgh_compile/PcodeCompile.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slgh_compile/PcodeCompile.java @@ -15,13 +15,16 @@ */ package ghidra.pcodeCPort.slgh_compile; +import java.util.Arrays; import java.util.List; +import java.util.stream.Collectors; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import generic.stl.IteratorSTL; import generic.stl.VectorSTL; +import ghidra.pcode.utils.MessageFormattingUtils; import ghidra.pcodeCPort.context.SleighError; import ghidra.pcodeCPort.opcodes.OpCode; import ghidra.pcodeCPort.semantics.*; @@ -89,12 +92,9 @@ public abstract class PcodeCompile { public void reportError(Location location, String msg) { entry("reportError", location, msg); - if (location == null) { - log.error(msg); - } - else { - log.error(location + ": " + msg); - } + + log.error(MessageFormattingUtils.format(location, msg)); + ++errors; } @@ -104,12 +104,9 @@ public abstract class PcodeCompile { public void reportWarning(Location location, String msg) { entry("reportWarning", location, msg); - if (location == null) { - log.warn(msg); - } - else { - log.warn(location + ": " + msg); - } + + log.warn(MessageFormattingUtils.format(location, msg)); + ++warnings; } @@ -147,7 +144,8 @@ public abstract class PcodeCompile { if ((size.getType() == ConstTpl.const_type.real) && (vn.getSize().getType() == ConstTpl.const_type.real) && (vn.getSize().getReal() != 0) && (vn.getSize().getReal() != size.getReal())) { - throw new SleighError("Localtemp size mismatch", null); + throw new SleighError(String.format("Localtemp size mismatch: %d vs %d", + vn.getSize().getReal(), size.getReal()), op.location); } vn.setSize(size); } @@ -158,7 +156,8 @@ public abstract class PcodeCompile { if ((size.getType() == ConstTpl.const_type.real) && (vn.getSize().getType() == ConstTpl.const_type.real) && (vn.getSize().getReal() != 0) && (vn.getSize().getReal() != size.getReal())) { - throw new SleighError("Localtemp size mismatch", null); + throw new SleighError(String.format("Input size mismatch: %d vs %d", + vn.getSize().getReal(), size.getReal()), op.location); } vn.setSize(size); } @@ -189,9 +188,8 @@ public abstract class PcodeCompile { public VectorSTL placeLabel(Location location, LabelSymbol labsym) { entry("placeLabel", location, labsym); if (labsym.isPlaced()) { - String errmsg = "Label " + labsym.getName(); - errmsg += " is placed more than once"; - reportError(labsym.getLocation(), errmsg); + reportError(labsym.getLocation(), + String.format("Label '%s' is placed more than once", labsym.getName())); } labsym.setPlaced(); VectorSTL res = new VectorSTL(); @@ -272,7 +270,7 @@ public abstract class PcodeCompile { tmpvn.getOffset().getReal(), (int) tmpvn.getSize().getReal()); addSymbol(sym); if ((!usesLocalKey) && enforceLocalKey) { - reportError(location, "Must use 'local' keyword to define symbol: " + varname); + reportError(location, "Must use 'local' keyword to define symbol '" + varname + "'"); } return ExprTree.toVector(rhs); } @@ -465,7 +463,8 @@ public abstract class PcodeCompile { return null; } if (byteoffset + numbytes > fullsz) { - throw new SleighError("Requested bit range out of bounds", loc); + throw new SleighError(String.format("Requested bit range out of bounds -- %d > %d", + (byteoffset + numbytes), fullsz), loc); } } @@ -841,10 +840,12 @@ public abstract class PcodeCompile { } break; case CPUI_CPOOLREF: - if (op.getOut().isZeroSize() && (!op.getIn(0).isZeroSize())) + if (op.getOut().isZeroSize() && (!op.getIn(0).isZeroSize())) { force_size(op.getOut(),op.getIn(0).getSize(),ops); - if (op.getIn(0).isZeroSize() && (!op.getOut().isZeroSize())) + } + if (op.getIn(0).isZeroSize() && (!op.getOut().isZeroSize())) { force_size(op.getIn(0),op.getOut().getSize(),ops); + } for(i=1;i 0) { - sb.append(", "); - } - sb.append(args[ii]); - ++argsSoFar; - } - } + sb.append(name).append("("); + sb.append(Arrays.stream(args).map(Object::toString).collect(Collectors.joining(", "))); sb.append(")"); + log.trace(sb.toString()); } @@ -991,13 +983,15 @@ public abstract class PcodeCompile { return createOpConst(location, OpCode.CPUI_INDIRECT, r.outvn.getOffset().getReal()); } if ("cpool".equals(name)) { - if (operands.size() >= 2) // At least two parameters + if (operands.size() >= 2) { // At least two parameters return createVariadic(location, OpCode.CPUI_CPOOLREF, operands); + } reportError(location,name+"() expects at least two arguments"); } if ("newobject".equals(name)) { - if (operands.size() >= 1) // At least one parameter + if (operands.size() >= 1) { // At least one parameter return createVariadic(location, OpCode.CPUI_NEW, operands); + } reportError(location,name+"() expects at least one argument"); } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slgh_compile/PcodeParser.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slgh_compile/PcodeParser.java index 647d858467..e9edc403bf 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slgh_compile/PcodeParser.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slgh_compile/PcodeParser.java @@ -17,6 +17,7 @@ package ghidra.pcodeCPort.slgh_compile; import java.io.*; import java.util.*; +import java.util.stream.Collectors; import org.antlr.runtime.*; import org.antlr.runtime.tree.CommonTreeNodeStream; @@ -27,6 +28,7 @@ import org.jdom.*; import generic.stl.VectorSTL; import ghidra.app.plugin.processors.sleigh.SleighException; import ghidra.app.plugin.processors.sleigh.SleighLanguage; +import ghidra.pcode.utils.MessageFormattingUtils; import ghidra.pcodeCPort.address.Address; import ghidra.pcodeCPort.context.SleighError; import ghidra.pcodeCPort.error.LowlevelError; @@ -171,24 +173,24 @@ public class PcodeParser extends PcodeCompile { // Make sure label symbols are used properly private String checkLabels() { - StringBuilder s = new StringBuilder(); + List errors = new ArrayList<>(); for (SleighSymbol sym : symbolMap.values()) { if (sym.getType() != symbol_type.label_symbol) { continue; } LabelSymbol labsym = (LabelSymbol) sym; if (labsym.getRefCount() == 0) { - s.append(" Label <"); - s.append(sym.getName()); - s.append("> was placed but not used"); + errors.add(MessageFormattingUtils.format(labsym.location, + String.format("Label <%s> was placed but never used", sym.getName()))); + } else if (!labsym.isPlaced()) { - s.append(" Label <"); - s.append(sym.getName()); - s.append("> was referenced but never placed"); + errors.add(MessageFormattingUtils.format(labsym.location, + String.format("Label <%s> was referenced but never placed", sym.getName()))); } } - return s.toString(); + return errors.stream().collect(Collectors.joining(" ")); + } private ConstructTpl buildConstructor(ConstructTpl rtl) { diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slgh_compile/SleighCompile.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slgh_compile/SleighCompile.java index 185a19c166..eee2b7c1cc 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slgh_compile/SleighCompile.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slgh_compile/SleighCompile.java @@ -20,11 +20,13 @@ import java.io.PrintStream; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.stream.Collectors; import org.antlr.runtime.RecognitionException; import org.jdom.JDOMException; import generic.stl.*; +import ghidra.pcode.utils.MessageFormattingUtils; import ghidra.pcodeCPort.address.Address; import ghidra.pcodeCPort.context.SleighError; import ghidra.pcodeCPort.error.LowlevelError; @@ -72,25 +74,21 @@ public class SleighCompile extends SleighBase { } public static void entry(String name, Object... args) { -// StringBuilder sb = new StringBuilder(); -// sb.append(name); -// sb.append("("); -// int argsSoFar = 0; -// for (int ii = 0; ii < args.length; ++ii) { -// if (!isLocationIsh(args[ii])) { -// if (argsSoFar > 0) { -// sb.append(", "); -// } -// sb.append(args[ii]); -// ++argsSoFar; -// } -// } -// sb.append(")"); -// Msg.trace(SleighCompile.class, sb.toString()); + StringBuilder sb = new StringBuilder(); + sb.append(name).append("("); + // @formatter:off + sb.append(Arrays.stream(args) + .filter(a -> isLocationIsh(a)) + .map(Object::toString) + .collect(Collectors.joining(", "))); + // @formatter:on + sb.append(")"); + Msg.trace(SleighCompile.class, sb.toString()); } // Semantic pcode compiler public final PcodeCompile pcode = new PcodeCompile() { + @Override public void reportError(Location location, String msg) { SleighCompile.this.reportError(location, msg); @@ -382,8 +380,10 @@ public class SleighCompile extends SleighBase { final int symSize = sym.getSize(); if (symSize % 4 != 0) { - reportError(sym.location, "Invalid size of context register \"" + sym.getName() + - "\" (" + symSize + "); must be a multiple of 4"); + reportError(sym.location, + String.format( + "Invalid size of context register '%s' (%d); must be a multiple of 4", + sym.getName(), symSize)); } final int maxBits = symSize * 8 - 1; @@ -395,13 +395,15 @@ public class SleighCompile extends SleighBase { int max = qual.high; if (max - min > (8 * 4)) { reportError(qual.location, - "Size of bitfield " + qual.name + "=(" + min + "," + max + ") larger than " + - (8 * 4) + " bits in context register \"" + sym.getName() + "\""); + String.format( + "Size of bitfield %s=(%d,%d) larger than %d bits in context register '%s'", + qual.name, min, (8 * 4), sym.getName())); + } if (max > maxBits) { - reportError(qual.location, - "Scope of bitfield " + qual.name + "=(" + min + "," + max + - ") extends beyond the size of context register \"" + sym.getName() + "\""); + reportError(qual.location, String.format( + "Scope of bitfield %s=(%d,%d) extends beyond the size of context register '%s' (%d)", + qual.name, min, max, sym.getName(), maxBits)); } j = i + 1; @@ -489,7 +491,7 @@ public class SleighCompile extends SleighBase { } if (tables.get(i).getPattern() == null) { reportWarning(tables.get(i).getLocation(), - "Unreferenced table: " + tables.get(i).getName()); + "Unreferenced table: '" + tables.get(i).getName() + "'"); } } } @@ -508,9 +510,9 @@ public class SleighCompile extends SleighBase { return; } if ((!warnunnecessarypcode) && (checker.getNumUnnecessaryPcode() > 0)) { - Msg.warn(this, checker.getNumUnnecessaryPcode() + + reportWarning(null, checker.getNumUnnecessaryPcode() + " unnecessary extensions/truncations were converted to copies"); - Msg.warn(this, "Use -u switch to list each individually"); + reportWarning(null, "Use -u switch to list each individually"); } checker.optimizeAll(); if (checker.getNumReadNoWrite() > 0) { @@ -518,9 +520,9 @@ public class SleighCompile extends SleighBase { return; } if ((!warndeadtemps) && (checker.getNumWriteNoRead() > 0)) { - Msg.warn(this, checker.getNumWriteNoRead() + + reportWarning(null, checker.getNumWriteNoRead() + " operations wrote to temporaries that were not read"); - Msg.warn(this, "Use -t switch to list each individually"); + reportWarning(null, "Use -t switch to list each individually"); } } @@ -560,10 +562,11 @@ public class SleighCompile extends SleighBase { if (collideOperand >= 0) { noCollisions = false; if (warnalllocalcollisions) { - Msg.warn(this, "Possible collision with symbol " + - ct.getOperand(collideOperand).getName() + " and " + - ct.getOperand(i).getName() + " in constructor from " + ct.getFilename() + - " starting at line " + Integer.toString(ct.getLineno())); + reportWarning(ct.location, + String.format( + "Possible operand collision between symbols '%s' and '%s'", + ct.getOperand(collideOperand).getName(), ct.getOperand(i).getName())); + } break; // Don't continue } @@ -589,10 +592,10 @@ public class SleighCompile extends SleighBase { sym = tables.get(i); } if (collisionCount > 0) { - Msg.warn(this, "WARNING: " + Integer.toString(collisionCount) + - " constructors with local collisions between operands"); + reportWarning(null, + collisionCount + " constructors with local collisions between operands"); if (!warnalllocalcollisions) { - Msg.warn(this, "Use -c switch to list each individually"); + reportWarning(null, "Use -c switch to list each individually"); } } } @@ -600,7 +603,7 @@ public class SleighCompile extends SleighBase { // Make sure label symbols are used properly String checkSymbols(SymbolScope scope) { entry("checkSymbols", scope); - StringBuilder s = new StringBuilder(); + List errors = new ArrayList<>(); IteratorSTL iter; for (iter = scope.begin(); !iter.equals(scope.end()); iter.increment()) { SleighSymbol sym = iter.get(); @@ -609,17 +612,15 @@ public class SleighCompile extends SleighBase { } LabelSymbol labsym = (LabelSymbol) sym; if (labsym.getRefCount() == 0) { - s.append(" Label <"); - s.append(sym.getName()); - s.append("> was placed but not used"); + errors.add(MessageFormattingUtils.format(labsym.location, + String.format("Label <%s> was placed but never used", sym.getName()))); } else if (!labsym.isPlaced()) { - s.append(" Label <"); - s.append(sym.getName()); - s.append("> was referenced but never placed"); + errors.add(MessageFormattingUtils.format(labsym.location, + String.format("Label <%s> was referenced but never placed", sym.getName()))); } } - return s.toString(); + return errors.stream().collect(Collectors.joining(" ")); } // Make sure symbol table errors are caught @@ -648,25 +649,28 @@ public class SleighCompile extends SleighBase { pcode.resetLabelCount(); } + + @Override public void reportError(Location location, String msg) { entry("reportError", location, msg); - if (location == null) { - Msg.error(this, msg); - } - else { - Msg.error(this, location + ": " + msg); - } + super.reportError(location, msg); + errors += 1; } + @Override + public void reportError(Location location, String msg, Throwable t) { + entry("reportError", location, msg); + super.reportError(location, msg, t); + + errors += 1; + } + + @Override public void reportWarning(Location location, String msg) { entry("reportWarning", location, msg); - if (location == null) { - Msg.warn(this, msg); - } - else { - Msg.warn(this, location + ": " + msg); - } + super.reportWarning(location, msg); + warnings += 1; } @@ -757,7 +761,7 @@ public class SleighCompile extends SleighBase { buildXrefs(); // Make sure we can build crossrefs properly } catch (SleighError err) { - Msg.error(this, err.getMessage(), err); + Msg.error(this, err.location + ": " + err.getMessage(), err); errors += 1; return; } @@ -837,7 +841,8 @@ public class SleighCompile extends SleighBase { entry("defineToken", location, name, sz); int size = (int) sz; if ((size & 7) != 0) { - reportError(location, name + "token size must be multiple of 8"); + reportError(location, + "Definition of '" + name + "' token -- size must be multiple of 8"); size = (size / 8) + 1; } else { @@ -879,21 +884,24 @@ public class SleighCompile extends SleighBase { public void newSpace(Location location, SpaceQuality qual) { entry("newSpace", location, qual); if (qual.size == 0) { - reportError(location, "Space definition missing size attribute"); + reportError(location, "Space definition '" + qual.name + "' missing size attribute"); return; } if (qual.size <= 0 || qual.size > 8) { - throw new SleighError("Space " + qual.name + " has unsupported size: " + 16, location); + throw new SleighError("Space '" + qual.name + "' has unsupported size: " + qual.size, + location); } if (qual.wordsize < 1 || qual.wordsize > 8) { throw new SleighError( - "Space " + qual.name + " has unsupported wordsize: " + qual.wordsize, location); + "Space '" + qual.name + "' has unsupported wordsize: " + qual.wordsize, location); } int addressBits = bitsConsumedByUnitSize(qual.wordsize) + (8 * qual.size); if (addressBits > 64) { - throw new SleighError("Space " + qual.name + " has unsupported dimensions, requires " + - addressBits + "-bits (limit is 64-bits)", location); + throw new SleighError( + "Space '" + qual.name + "' has unsupported dimensions: requires " + addressBits + + " bits -- limit is 64 bits", + location); } int delay = (qual.type == space_class.register_space) ? 0 : 1; @@ -902,7 +910,9 @@ public class SleighCompile extends SleighBase { insertSpace(spc); if (qual.isdefault) { if (getDefaultSpace() != null) { - reportError(location, "Multiple default spaces"); + reportError(location, + "Multiple default spaces -- '" + getDefaultSpace().getName() + "', '" + + qual.name + "'"); } else { setDefaultSpace(spc.getIndex()); // Make the flagged space @@ -949,11 +959,11 @@ public class SleighCompile extends SleighBase { String namecopy = name; int size = 8 * sym.getSize(); // Number of bits if (numb == 0) { - reportError(location, "Size of bitrange is zero for: " + namecopy); + reportError(location, "Size of bitrange is zero for '" + namecopy + "'"); return; } if ((bitoffset >= size) || ((bitoffset + numb) > size)) { - reportError(location, "Bad bitrange for: " + namecopy); + reportError(location, "Bad bitrange for '" + namecopy + "'"); return; } if ((bitoffset % 8 == 0) && (numb % 8 == 0)) { @@ -971,8 +981,8 @@ public class SleighCompile extends SleighBase { } else { if (size > 64) { - reportError(location, - "Illegal bitrange on varnode larger than 64 bits: " + sym.getName()); + reportError(location, "'" + sym.getName() + "': " + + "Illegal bitrange on varnode larger than 64 bits"); } // Otherwise define the special symbol addSymbol(new BitrangeSymbol(location, namecopy, sym, bitoffset, numb)); @@ -984,8 +994,8 @@ public class SleighCompile extends SleighBase { for (int i = 0; i < names.size(); ++i) { boolean isInternal = pcode.isInternalFunction(names.get(i)); if (isInternal) { - reportError(locations.get(i), - names.get(i) + " is an internal pcodeop and cannot be redefined as a pseudoop"); + reportError(locations.get(i), "'" + names.get(i) + + "' is an internal pcodeop and cannot be redefined as a pseudoop"); } UserOpSymbol sym = new UserOpSymbol(locations.get(i), names.get(i)); sym.setIndex(userop_count++); @@ -1020,7 +1030,7 @@ public class SleighCompile extends SleighBase { SleighSymbol dupsym = dedupSymbolList(symlist); if (dupsym != null) { reportWarning(dupsym.location, - "\"attach values\" list contains duplicate entries: " + dupsym.getName()); + "'attach values' list contains duplicate entries: " + dupsym.getName()); } for (int i = 0; i < symlist.size(); ++i) { Location location = locations.get(i); @@ -1030,7 +1040,8 @@ public class SleighCompile extends SleighBase { } PatternValue patval = sym.getPatternValue(); if (patval.maxValue() + 1 != numlist.size()) { - reportError(location, "Attach value " + sym + " is wrong size for list " + numlist); + reportError(location, + "Attach value '" + sym + "' is wrong size for list: " + numlist); } symtab.replaceSymbol(sym, new ValueMapSymbol(location, sym.getName(), patval, numlist)); } @@ -1042,7 +1053,7 @@ public class SleighCompile extends SleighBase { SleighSymbol dupsym = dedupSymbolList(symlist); if (dupsym != null) { reportWarning(dupsym.location, - "\"attach names\" list contains duplicate entries: " + dupsym.getName()); + "'attach names' list contains duplicate entries: " + dupsym.getName()); } for (int i = 0; i < symlist.size(); ++i) { Location location = locations.get(i); @@ -1052,7 +1063,7 @@ public class SleighCompile extends SleighBase { } PatternValue patval = sym.getPatternValue(); if (patval.maxValue() + 1 != names.size()) { - reportError(location, "Attach name " + sym + " is wrong size for list " + names); + reportError(location, "Attach name '" + sym + "' is wrong size for list: " + names); } symtab.replaceSymbol(sym, new NameSymbol(location, sym.getName(), patval, names)); } @@ -1064,7 +1075,7 @@ public class SleighCompile extends SleighBase { SleighSymbol dupsym = dedupSymbolList(symlist); if (dupsym != null) { reportWarning(dupsym.location, - "\"attach variables\" list contains duplicate entries: " + dupsym.getName()); + "'attach variables' list contains duplicate entries: " + dupsym.getName()); } for (int i = 0; i < symlist.size(); ++i) { Location location = locations.get(i); @@ -1073,7 +1084,7 @@ public class SleighCompile extends SleighBase { continue; } if (firstContextField != null && sym.getId() == firstContextField) { - reportError(location, sym.getName() + + reportError(location, "'" + sym.getName() + "'" + " cannot be used to attach variables because it occurs at the lowest bit position in context at " + sym.getLocation()); continue; @@ -1081,7 +1092,7 @@ public class SleighCompile extends SleighBase { PatternValue patval = sym.getPatternValue(); if (patval.maxValue() + 1 != varlist.size()) { reportError(location, - "Attach varnode " + sym + " is wrong size for list " + varlist); + "Attach varnode '" + sym + "' is wrong size for list: " + varlist); } int sz = 0; for (int j = 0; j < varlist.size(); ++j) { @@ -1183,7 +1194,7 @@ public class SleighCompile extends SleighBase { entry("selfDefine", sym); SleighSymbol sleighSymbol = symtab.findSymbol(sym.getName(), 1); if (!(sleighSymbol instanceof TripleSymbol)) { - reportError(sym.getLocation(), sym.getName() + ": No matching global symbol"); + reportError(sym.getLocation(), "No matching global symbol '" + sym.getName() + "'"); return; } TripleSymbol glob = (TripleSymbol) sleighSymbol; @@ -1280,14 +1291,10 @@ public class SleighCompile extends SleighBase { VectorSTL param) { entry("createMacroUse", location, sym, param); if (sym.getNumOperands() != param.size()) { - String errmsg = "Invocation of macro \"" + sym.getName(); - if (param.size() > sym.getNumOperands()) { - errmsg += "\" passes too many parameters"; - } - else { - errmsg += "\" passes too few parameters"; - } - reportError(sym.getLocation(), errmsg); + boolean tooManyParams = param.size() > sym.getNumOperands(); + reportError(sym.getLocation(), String.format("Invocation of macro '%s' passes too " + + (tooManyParams ? "many" : "few") + " parameters", sym.getName())); + return new VectorSTL<>(); } compareMacroParams(sym, param); @@ -1416,28 +1423,34 @@ public class SleighCompile extends SleighBase { String sectionstring = " Main section: "; int max = vec.getMaxId(); for (;;) { + + String scopeString = cur.section.loc + ": " + sectionstring; + String errstring; errstring = checkSymbols(cur.scope); // Check labels in the section's scope - if (errstring.length() == 0) { + if (errstring.length() != 0) { + myErrors.push_back(scopeString + errstring); + } + else { if (!expandMacros(cur.section)) { - myErrors.push_back(sectionstring + "Could not expand macros"); + myErrors.push_back(scopeString + "Could not expand macros"); } VectorSTL check = new VectorSTL<>(); big.markSubtableOperands(check); Pair res = cur.section.fillinBuild(check, getConstantSpace()); if (res.first == 1) { myErrors.push_back( - sectionstring + "Duplicate BUILD statements at " + res.second); + scopeString + "Duplicate BUILD statements at " + res.second); } if (res.first == 2) { myErrors.push_back( - sectionstring + "Unnecessary BUILD statements at " + res.second); + scopeString + "Unnecessary BUILD statements at " + res.second); } if (!pcode.propagateSize(cur.section)) { myErrors.push_back( - sectionstring + "Could not resolve at least 1 variable size"); + scopeString + "Could not resolve at least 1 variable size"); } } if (i < 0) { // These potential errors only apply to main section @@ -1452,7 +1465,7 @@ public class SleighCompile extends SleighBase { } if (cur.section.delaySlot() != 0) { // Delay slot is present in this constructor if (root != big.getParent()) { // it is not in a root constructor - reportWarning(null, "Delay slot used in " + big); + reportWarning(big.location, "Delay slot used in " + big); } if (cur.section.delaySlot() > maxdelayslotbytes) { maxdelayslotbytes = cur.section.delaySlot(); @@ -1476,7 +1489,7 @@ public class SleighCompile extends SleighBase { if (!myErrors.empty()) { reportError(big.location, "in " + big); for (int j = 0; j < myErrors.size(); ++j) { - reportError(null, myErrors.get(j)); + reportError(big.location, myErrors.get(j)); } return false; } @@ -1594,8 +1607,8 @@ public class SleighCompile extends SleighBase { PatternValue patternValue = valueSymbol.getPatternValue(); if (patternValue instanceof TokenField) { if (sleighSymbol.location != Location.INTERNALLY_DEFINED) { - reportWarning(patternValue.location, "token field " + - sleighSymbol.getName() + " defined but never used"); + reportWarning(patternValue.location, "token field '" + + sleighSymbol.getName() + "' defined but never used"); } } } @@ -1648,12 +1661,12 @@ public class SleighCompile extends SleighBase { String errstring = checkSymbols(symtab.getCurrentScope()); if (errstring.length() != 0) { reportError(sym.getLocation(), - " in definition of macro " + sym.getName() + ":" + errstring); + "Error in definition of macro '" + sym.getName() + "': " + errstring); return; } if (!expandMacros(rtl)) { reportError(sym.getLocation(), - "Could not expand submacro in definition of macro " + sym.getName()); + "Could not expand submacro in definition of macro '" + sym.getName() + "'"); return; } pcode.propagateSize(rtl); // Propagate size information (as much as possible) diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slghpatexpress/TokenPattern.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slghpatexpress/TokenPattern.java index 55025e60ac..9dc14508a0 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slghpatexpress/TokenPattern.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slghpatexpress/TokenPattern.java @@ -118,7 +118,8 @@ public class TokenPattern { setLeftEllipsis(true); } else if (tok1.toklist.size() != minsize) { - throw new SleighError("Mismatched pattern sizes", location); + throw new SleighError(String.format("Mismatched pattern sizes -- %d vs %d", + tok1.toklist.size(), minsize), location); } else if (tok1.toklist.size() == tok2.toklist.size()) { throw new SleighError("Pattern size cannot vary (missing ... ?)", location); @@ -132,7 +133,8 @@ public class TokenPattern { setRightEllipsis(true); } else if (tok1.toklist.size() != minsize) { - throw new SleighError("Mismatched pattern sizes", location); + throw new SleighError(String.format("Mismatched pattern sizes -- %d vs %d", + tok1.toklist.size(), minsize), location); } else if (tok1.toklist.size() == tok2.toklist.size()) { throw new SleighError("Pattern size cannot vary (missing ... ?)", location); @@ -142,7 +144,8 @@ public class TokenPattern { if (tok2.getLeftEllipsis()) { reversedirection = true; if (tok2.toklist.size() != minsize) { - throw new SleighError("Mismatched pattern sizes", location); + throw new SleighError(String.format("Mismatched pattern sizes -- %d vs %d", + tok2.toklist.size(), minsize), location); } else if (tok1.toklist.size() == tok2.toklist.size()) { throw new SleighError("Pattern size cannot vary (missing ... ?)", location); @@ -150,7 +153,8 @@ public class TokenPattern { } else if (tok2.getRightEllipsis()) { if (tok2.toklist.size() != minsize) { - throw new SleighError("Mismatched pattern sizes", location); + throw new SleighError(String.format("Mismatched pattern sizes -- %d vs %d", + tok1.toklist.size(), minsize), location); } else if (tok1.toklist.size() == tok2.toklist.size()) { throw new SleighError("Pattern size cannot vary (missing ... ?)", location); @@ -158,7 +162,8 @@ public class TokenPattern { } else { if (tok2.toklist.size() != tok1.toklist.size()) { - throw new SleighError("Mismatched pattern sizes", location); + throw new SleighError(String.format("Mismatched pattern sizes -- %d vs %d", + tok2.toklist.size(), tok1.toklist.size()), location); } } } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slghsymbol/DecisionProperties.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slghsymbol/DecisionProperties.java index 00202955e6..96ac8b6860 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slghsymbol/DecisionProperties.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slghsymbol/DecisionProperties.java @@ -16,6 +16,7 @@ package ghidra.pcodeCPort.slghsymbol; import generic.stl.VectorSTL; +import ghidra.pcode.utils.MessageFormattingUtils; import ghidra.pcodeCPort.slghpattern.DisjointPattern; public class DecisionProperties { @@ -35,7 +36,10 @@ public class DecisionProperties { if ((!a.isError()) && (!b.isError())) { a.setError(true); b.setError(true); - identerrors.push_back("Constructors with identical patterns: \n " + a + "\n " + b); + + String msg = "Constructors with identical patterns:\n " + a + "\n " + b; + identerrors.push_back(MessageFormattingUtils.format(a.location, msg)); + identerrors.push_back(MessageFormattingUtils.format(b.location, msg)); } } @@ -45,9 +49,12 @@ public class DecisionProperties { if ((!a.isError()) && (!b.isError())) { a.setError(true); b.setError(true); - conflicterrors.push_back("Constructor patterns cannot be distinguished: \n" // + + String msg = "Constructor patterns cannot be distinguished: \n" // + " " + pa + " " + a + "\n" // - + " " + pb + " " + b); + + " " + pb + " " + b; + conflicterrors.push_back(MessageFormattingUtils.format(a.location, msg)); + conflicterrors.push_back(MessageFormattingUtils.format(b.location, msg)); } } } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slghsymbol/SubtableSymbol.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slghsymbol/SubtableSymbol.java index 62697e9281..69ee572cca 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slghsymbol/SubtableSymbol.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcodeCPort/slghsymbol/SubtableSymbol.java @@ -35,10 +35,8 @@ public class SubtableSymbol extends TripleSymbol { private TokenPattern pattern; private boolean beingbuilt, errors; - private VectorSTL construct = new VectorSTL(); // All - // the - // Constructors in - // this table + // All the Constructors in this table + private VectorSTL construct = new VectorSTL(); private DecisionNode decisiontree; public SubtableSymbol(Location location) {