mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 10:49:34 +02:00
Merge remote-tracking branch
'origin/GP-520_James_max_unique_varnode_size'
This commit is contained in:
commit
a3f223619c
10 changed files with 196 additions and 27 deletions
|
@ -37,6 +37,7 @@ ConstTpl::ConstTpl(const_type tp,int4 ht,v_field vf)
|
|||
type = handle;
|
||||
value.handle_index = ht;
|
||||
select = vf;
|
||||
value_real = 0;
|
||||
}
|
||||
|
||||
ConstTpl::ConstTpl(const_type tp,int4 ht,v_field vf,uintb plus)
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
|
||||
const int4 SleighBase::SLA_FORMAT_VERSION = 3;
|
||||
|
||||
const uintb SleighBase::MAX_UNIQUE_SIZE = 128;
|
||||
|
||||
int4 SourceFileIndexer::index(const string filename){
|
||||
auto it = fileToIndex.find(filename);
|
||||
if (fileToIndex.end() != it){
|
||||
|
@ -57,7 +59,6 @@ void SourceFileIndexer::saveXml(ostream& s) const {
|
|||
s << "</sourcefiles>\n";
|
||||
}
|
||||
|
||||
|
||||
SleighBase::SleighBase(void)
|
||||
|
||||
{
|
||||
|
|
|
@ -69,6 +69,7 @@ protected:
|
|||
void reregisterContext(void); ///< Reregister context fields for a new executable
|
||||
void restoreXml(const Element *el); ///< Read a SLEIGH specification from XML
|
||||
public:
|
||||
static const uintb MAX_UNIQUE_SIZE; ///< Maximum size of a varnode in the unique space (should match value in SleighBase.java)
|
||||
SleighBase(void); ///< Construct an uninitialized translator
|
||||
bool isInitialized(void) const { return (root != (SubtableSymbol *)0); } ///< Return \b true if \b this is initialized
|
||||
virtual ~SleighBase(void) {} ///< Destructor
|
||||
|
|
|
@ -183,7 +183,7 @@ SubtableSymbol *WithBlock::getCurrentSubtable(const list<WithBlock> &stack)
|
|||
return (SubtableSymbol *)0;
|
||||
}
|
||||
|
||||
ConsistencyChecker::ConsistencyChecker(SleighCompile *sleigh,SubtableSymbol *rt,bool un,bool warndead)
|
||||
ConsistencyChecker::ConsistencyChecker(SleighCompile *sleigh,SubtableSymbol *rt,bool un,bool warndead, bool warnlargetemp)
|
||||
|
||||
{
|
||||
compiler = sleigh;
|
||||
|
@ -191,8 +191,10 @@ ConsistencyChecker::ConsistencyChecker(SleighCompile *sleigh,SubtableSymbol *rt,
|
|||
unnecessarypcode = 0;
|
||||
readnowrite = 0;
|
||||
writenoread = 0;
|
||||
largetemp = 0; ///<Number of constructors using at least one temporary varnode larger than SleighBase::MAX_UNIQUE_SIZE
|
||||
printextwarning = un;
|
||||
printdeadwarning = warndead;
|
||||
printlargetempwarning = warnlargetemp; ///< If true, prints a warning about each constructor using a temporary varnode larger than SleighBase::MAX_UNIQUE_SIZE
|
||||
}
|
||||
|
||||
int4 ConsistencyChecker::recoverSize(const ConstTpl &sizeconst,Constructor *ct)
|
||||
|
@ -814,6 +816,33 @@ bool ConsistencyChecker::checkConstructorSection(Constructor *ct,ConstructTpl *c
|
|||
return testresult;
|
||||
}
|
||||
|
||||
///
|
||||
/// Returns true if the output or one of the inputs of
|
||||
/// op is in the unique space and larger than SleighBase::MAX_UNIQUE_SIZE
|
||||
///
|
||||
bool ConsistencyChecker::hasLargeTemporary(OpTpl *op){
|
||||
VarnodeTpl *out = op->getOut();
|
||||
if ((out != (VarnodeTpl *) 0x0) && isTemporaryAndTooBig(out)) {
|
||||
return true;
|
||||
}
|
||||
for (int4 i = 0; i < op->numInput(); ++i) {
|
||||
VarnodeTpl *in = op->getIn(i);
|
||||
if (isTemporaryAndTooBig(in)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
///
|
||||
/// Returns true precisely when vn is in the unique space and
|
||||
/// has size larger than SleighBase::MAX_UNIQUE_SIZE
|
||||
///
|
||||
bool ConsistencyChecker::isTemporaryAndTooBig(VarnodeTpl *vn){
|
||||
return vn->getSpace().isUniqueSpace() &&
|
||||
(vn->getSize().getReal() > SleighBase::MAX_UNIQUE_SIZE);
|
||||
}
|
||||
|
||||
bool ConsistencyChecker::checkVarnodeTruncation(Constructor *ct,int4 slot,
|
||||
OpTpl *op,VarnodeTpl *vn,bool isbigendian)
|
||||
{
|
||||
|
@ -1238,6 +1267,24 @@ void ConsistencyChecker::checkUnusedTemps(Constructor *ct,const map<uintb,Optimi
|
|||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Checks the ops in ct to see whether a varnode larger than
|
||||
/// SleighBase::MAX_UNIQUE_SIZE is used. Note that this method
|
||||
/// returns after the first large varnode is found.
|
||||
///
|
||||
void ConsistencyChecker::checkLargeTemporaries(Constructor *ct){
|
||||
vector<OpTpl *> ops = ct->getTempl()->getOpvec();
|
||||
for (vector<OpTpl *>::iterator iter = ops.begin(); iter != ops.end(); ++iter){
|
||||
if (hasLargeTemporary(*iter)){
|
||||
if (printlargetempwarning){
|
||||
compiler->reportWarning(compiler->getLocation(ct), "Constructor uses temporary varnode larger than " + to_string(SleighBase::MAX_UNIQUE_SIZE) + " bytes.");
|
||||
}
|
||||
largetemp++;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ConsistencyChecker::optimize(Constructor *ct)
|
||||
|
||||
{
|
||||
|
@ -1255,6 +1302,7 @@ void ConsistencyChecker::optimize(Constructor *ct)
|
|||
applyOptimization(ct,*currec);
|
||||
} while(currec != (OptimizeRecord *)0);
|
||||
checkUnusedTemps(ct,recs);
|
||||
checkLargeTemporaries(ct);
|
||||
}
|
||||
|
||||
bool ConsistencyChecker::test(void)
|
||||
|
@ -1640,7 +1688,7 @@ void SleighCompile::buildPatterns(void)
|
|||
void SleighCompile::checkConsistency(void)
|
||||
|
||||
{
|
||||
ConsistencyChecker checker(this, root,warnunnecessarypcode,warndeadtemps);
|
||||
ConsistencyChecker checker(this, root,warnunnecessarypcode,warndeadtemps,largetemporarywarning);
|
||||
|
||||
if (!checker.test()) {
|
||||
errors += 1;
|
||||
|
@ -1669,6 +1717,14 @@ void SleighCompile::checkConsistency(void)
|
|||
msg << "Use -t switch to list each individually";
|
||||
reportInfo(msg.str());
|
||||
}
|
||||
if ((!largetemporarywarning) && (checker.getNumLargeTemporaries() > 0)) {
|
||||
ostringstream msg;
|
||||
msg << dec << checker.getNumLargeTemporaries();
|
||||
msg << " constructors contain temporaries larger than ";
|
||||
msg << SleighBase::MAX_UNIQUE_SIZE << " bytes" << endl;
|
||||
msg << "Use -o switch to list each individually.";
|
||||
reportInfo(msg.str());
|
||||
}
|
||||
}
|
||||
|
||||
int4 SleighCompile::findCollision(map<uintb,int4> &local2Operand,const vector<uintb> &locals,int operand)
|
||||
|
@ -1857,7 +1913,7 @@ uintb SleighCompile::getUniqueAddr(void)
|
|||
|
||||
{
|
||||
uintb base = getUniqueBase();
|
||||
setUniqueBase(base + 16); // Should be maximum size of a unique
|
||||
setUniqueBase(base + SleighBase::MAX_UNIQUE_SIZE);
|
||||
return base;
|
||||
}
|
||||
|
||||
|
@ -2876,7 +2932,7 @@ static void findSlaSpecs(vector<string> &res, const string &dir, const string &s
|
|||
|
||||
static void initCompiler(SleighCompile &compiler, map<string,string> &defines, bool enableUnnecessaryPcodeWarning,
|
||||
bool disableLenientConflict, bool enableAllCollisionWarning,
|
||||
bool enableAllNopWarning,bool enableDeadTempWarning,bool enforceLocalKeyWord)
|
||||
bool enableAllNopWarning,bool enableDeadTempWarning,bool enforceLocalKeyWord, bool largeTemporaryWarning)
|
||||
|
||||
{
|
||||
map<string,string>::iterator iter = defines.begin();
|
||||
|
@ -2895,6 +2951,8 @@ static void initCompiler(SleighCompile &compiler, map<string,string> &defines, b
|
|||
compiler.setDeadTempWarning(true);
|
||||
if (enforceLocalKeyWord)
|
||||
compiler.setEnforceLocalKeyWord(true);
|
||||
if (largeTemporaryWarning)
|
||||
compiler.setLargeTemporaryWarning(true);
|
||||
}
|
||||
|
||||
static void segvHandler(int sig) {
|
||||
|
@ -2922,6 +2980,7 @@ int main(int argc,char **argv)
|
|||
cerr << " -t print warnings for dead temporaries" << endl;
|
||||
cerr << " -e enforce use of 'local' keyword for temporaries" << endl;
|
||||
cerr << " -c print warnings for all constructors with colliding operands" << endl;
|
||||
cerr << " -o print warnings for temporaries which are too large" << endl;
|
||||
cerr << " -DNAME=VALUE defines a preprocessor macro NAME with value VALUE" << endl;
|
||||
exit(2);
|
||||
}
|
||||
|
@ -2935,6 +2994,7 @@ int main(int argc,char **argv)
|
|||
bool enableAllNopWarning = false;
|
||||
bool enableDeadTempWarning = false;
|
||||
bool enforceLocalKeyWord = false;
|
||||
bool largeTemporaryWarning = false;
|
||||
|
||||
bool compileAll = false;
|
||||
|
||||
|
@ -2966,6 +3026,8 @@ int main(int argc,char **argv)
|
|||
enableDeadTempWarning = true;
|
||||
else if (argv[i][1] == 'e')
|
||||
enforceLocalKeyWord = true;
|
||||
else if (argv[i][1] == 'o')
|
||||
largeTemporaryWarning = true;
|
||||
#ifdef YYDEBUG
|
||||
else if (argv[i][1] == 'x')
|
||||
yydebug = 1; // Debug option
|
||||
|
@ -2998,7 +3060,7 @@ int main(int argc,char **argv)
|
|||
SleighCompile compiler;
|
||||
initCompiler(compiler, defines, enableUnnecessaryPcodeWarning,
|
||||
disableLenientConflict, enableAllCollisionWarning, enableAllNopWarning,
|
||||
enableDeadTempWarning, enforceLocalKeyWord);
|
||||
enableDeadTempWarning, enforceLocalKeyWord,largeTemporaryWarning);
|
||||
retval = run_compilation(slaspec.c_str(),sla.c_str(),compiler);
|
||||
if (retval != 0) {
|
||||
return retval; // stop on first error
|
||||
|
@ -3035,7 +3097,7 @@ int main(int argc,char **argv)
|
|||
SleighCompile compiler;
|
||||
initCompiler(compiler, defines, enableUnnecessaryPcodeWarning,
|
||||
disableLenientConflict, enableAllCollisionWarning, enableAllNopWarning,
|
||||
enableDeadTempWarning, enforceLocalKeyWord);
|
||||
enableDeadTempWarning, enforceLocalKeyWord,largeTemporaryWarning);
|
||||
|
||||
if (i < argc - 1) {
|
||||
string fileoutExamine(argv[i+1]);
|
||||
|
|
|
@ -97,8 +97,10 @@ class ConsistencyChecker {
|
|||
int4 unnecessarypcode;
|
||||
int4 readnowrite;
|
||||
int4 writenoread;
|
||||
int4 largetemp;
|
||||
bool printextwarning;
|
||||
bool printdeadwarning;
|
||||
bool printlargetempwarning;
|
||||
SubtableSymbol *root_symbol;
|
||||
vector<SubtableSymbol *> postorder;
|
||||
map<SubtableSymbol *,int4> sizemap; // Sizes associated with tables
|
||||
|
@ -109,6 +111,8 @@ class ConsistencyChecker {
|
|||
bool checkOpMisuse(OpTpl *op,Constructor *ct);
|
||||
bool sizeRestriction(OpTpl *op,Constructor *ct);
|
||||
bool checkConstructorSection(Constructor *ct,ConstructTpl *cttpl);
|
||||
bool hasLargeTemporary(OpTpl *op);
|
||||
bool isTemporaryAndTooBig(VarnodeTpl *vn);
|
||||
bool checkVarnodeTruncation(Constructor *ct,int4 slot,OpTpl *op,VarnodeTpl *vn,bool isbigendian);
|
||||
bool checkSectionTruncations(Constructor *ct,ConstructTpl *cttpl,bool isbigendian);
|
||||
bool checkSubtable(SubtableSymbol *sym);
|
||||
|
@ -125,15 +129,17 @@ class ConsistencyChecker {
|
|||
OptimizeRecord *findValidRule(Constructor *ct,map<uintb,OptimizeRecord> &recs) const;
|
||||
void applyOptimization(Constructor *ct,const OptimizeRecord &rec);
|
||||
void checkUnusedTemps(Constructor *ct,const map<uintb,OptimizeRecord> &recs);
|
||||
void checkLargeTemporaries(Constructor *ct);
|
||||
void optimize(Constructor *ct);
|
||||
public:
|
||||
ConsistencyChecker(SleighCompile *sleigh, SubtableSymbol *rt,bool unnecessary,bool warndead);
|
||||
ConsistencyChecker(SleighCompile *sleigh, SubtableSymbol *rt,bool unnecessary,bool warndead, bool warnlargetemp);
|
||||
bool test(void);
|
||||
bool testTruncations(bool isbigendian);
|
||||
void optimizeAll(void);
|
||||
int4 getNumUnnecessaryPcode(void) const { return unnecessarypcode; }
|
||||
int4 getNumReadNoWrite(void) const { return readnowrite; }
|
||||
int4 getNumWriteNoRead(void) const { return writenoread; }
|
||||
int4 getNumLargeTemporaries(void) const {return largetemp;}
|
||||
};
|
||||
|
||||
struct FieldContext {
|
||||
|
@ -200,6 +206,7 @@ private:
|
|||
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
|
||||
bool lenientconflicterrors; // True if we ignore most pattern conflict errors
|
||||
bool largetemporarywarning; // True if we warn about temporaries larger than SleighBase::MAX_UNIQUE_SIZE
|
||||
bool warnalllocalcollisions; // True if local export collisions generate individual warnings
|
||||
bool warnallnops; // True if pcode NOPs generate individual warnings
|
||||
vector<string> noplist; // List of individual NOP warnings
|
||||
|
@ -244,6 +251,7 @@ public:
|
|||
void setUnnecessaryPcodeWarning(bool val) { warnunnecessarypcode = val; }
|
||||
void setDeadTempWarning(bool val) { warndeadtemps = val; }
|
||||
void setEnforceLocalKeyWord(bool val) { pcode.setEnforceLocalKey(val); }
|
||||
void setLargeTemporaryWarning (bool val) {largetemporarywarning = val;}
|
||||
void setLenientConflict(bool val) { lenientconflicterrors = val; }
|
||||
void setLocalCollisionWarning(bool val) { warnalllocalcollisions = val; }
|
||||
void setAllNopWarning(bool val) { warnallnops = val; }
|
||||
|
|
|
@ -33,6 +33,7 @@ import ghidra.app.plugin.processors.sleigh.expression.ContextField;
|
|||
import ghidra.app.plugin.processors.sleigh.expression.PatternValue;
|
||||
import ghidra.app.plugin.processors.sleigh.symbol.*;
|
||||
import ghidra.framework.Application;
|
||||
import ghidra.pcodeCPort.sleighbase.SleighBase;
|
||||
import ghidra.pcodeCPort.slgh_compile.SleighCompileLauncher;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.lang.*;
|
||||
|
@ -42,8 +43,8 @@ import ghidra.program.model.mem.MemoryAccessException;
|
|||
import ghidra.program.model.symbol.SourceType;
|
||||
import ghidra.program.model.util.AddressLabelInfo;
|
||||
import ghidra.program.model.util.ProcessorSymbolType;
|
||||
import ghidra.sleigh.grammar.SourceFileIndexer;
|
||||
import ghidra.sleigh.grammar.SleighPreprocessor;
|
||||
import ghidra.sleigh.grammar.SourceFileIndexer;
|
||||
import ghidra.util.*;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
import ghidra.util.xml.SpecXmlUtils;
|
||||
|
@ -54,17 +55,14 @@ import utilities.util.FileUtilities;
|
|||
public class SleighLanguage implements Language {
|
||||
|
||||
/**
|
||||
* NOTE: The value of {@link SleighLanguage#SLA_FORMAT_VERSION} must match that of
|
||||
* {@link ghidra.pcodeCPort.sleighbase.SleighBase#SLA_FORMAT_VERSION}!.
|
||||
* <p>
|
||||
* SLA_FORMAT_VERSION should be incremented whenever the format of the .sla
|
||||
* SLA_FORMAT_VERSION will be incremented whenever the format of the .sla
|
||||
* files change.
|
||||
* <p>
|
||||
* Version 3: October 2020: added source file information for each constructor. <br>
|
||||
* Version 3: January 2021: added source file information for each constructor. <br>
|
||||
* Version 2: April 2019: Changed numbering of Overlay spaces.<br>
|
||||
* Version 1: Initial version.<br>
|
||||
*/
|
||||
public static final int SLA_FORMAT_VERSION = 3;
|
||||
public static final int SLA_FORMAT_VERSION = SleighBase.SLA_FORMAT_VERSION;
|
||||
private Map<CompilerSpecID, SleighCompilerSpecDescription> compilerSpecDescriptions;
|
||||
private HashMap<CompilerSpecID, BasicCompilerSpec> compilerSpecs;
|
||||
private List<InjectPayloadSleigh> additionalInject = null;
|
||||
|
|
|
@ -35,10 +35,14 @@ public abstract class SleighBase extends Translate implements NamedSymbolProvide
|
|||
// implementation
|
||||
|
||||
/**
|
||||
* Note: The value of {@link SleighBase#SLA_FORMAT_VERSION} must match
|
||||
* {@link ghidra.app.plugin.processors.sleigh.SleighLanguage#SLA_FORMAT_VERSION}.
|
||||
* Note: The values of {@link #SLA_FORMAT_VERSION} and {@link #MAX_UNIQUE_SIZE}
|
||||
* must match the corresponding values defined by sleighbase.cc
|
||||
*/
|
||||
public static final int SLA_FORMAT_VERSION = 3;
|
||||
|
||||
public static final long MAX_UNIQUE_SIZE = 128; //Maximum size of a varnode in the unique space.
|
||||
//Should match value in sleighbase.cc
|
||||
|
||||
private VectorSTL<String> userop = new VectorSTL<>();
|
||||
private address_set varnode_xref = new address_set(); // Cross-reference registers by address
|
||||
protected SubtableSymbol root;
|
||||
|
|
|
@ -23,16 +23,22 @@ import ghidra.pcodeCPort.opcodes.OpCode;
|
|||
import ghidra.pcodeCPort.semantics.*;
|
||||
import ghidra.pcodeCPort.semantics.ConstTpl.const_type;
|
||||
import ghidra.pcodeCPort.semantics.ConstTpl.v_field;
|
||||
import ghidra.pcodeCPort.sleighbase.SleighBase;
|
||||
import ghidra.pcodeCPort.slghsymbol.*;
|
||||
import ghidra.pcodeCPort.space.AddrSpace;
|
||||
import ghidra.util.Msg;
|
||||
|
||||
class ConsistencyChecker {
|
||||
|
||||
int unnecessarypcode;
|
||||
int readnowrite;
|
||||
int writenoread;
|
||||
// number of constructors using a temporary varnode larger than SleighBase.MAX_UNIQUE_SIZE
|
||||
int largetemp;
|
||||
boolean printextwarning;
|
||||
boolean printdeadwarning;
|
||||
//if true, print information about constructors using temporary varnodes larger than SleighBase.MAX_UNIQUE_SIZE
|
||||
boolean printlargetempwarning;
|
||||
SleighCompile compiler;
|
||||
SubtableSymbol root_symbol;
|
||||
VectorSTL<SubtableSymbol> postorder = new VectorSTL<>();
|
||||
|
@ -637,6 +643,38 @@ class ConsistencyChecker {
|
|||
return testresult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true precisely when {@code opTpl} uses a {@link VarnodeTpl} in
|
||||
* the unique space whose size is larger than {@link SleighBase#MAX_UNIQUE_SIZE}.
|
||||
* Note that this method returns as soon as one large {@link VarnodeTpl} is found.
|
||||
* @param opTpl the op to check
|
||||
* @return true if {@code opTpl} uses a large temporary varnode
|
||||
*/
|
||||
boolean hasLargeTemporary(OpTpl opTpl) {
|
||||
VarnodeTpl out = opTpl.getOut();
|
||||
if (out != null && isTemporaryAndTooBig(out)) {
|
||||
return true;
|
||||
}
|
||||
for (int i = 0; i < opTpl.numInput(); ++i) {
|
||||
VarnodeTpl in = opTpl.getIn(i);
|
||||
if (isTemporaryAndTooBig(in)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true precisely when {@code vn} is in the unique space
|
||||
* and has a size larger than {@link SleighBase#MAX_UNIQUE_SIZE}.
|
||||
* @param vn varnode template to check
|
||||
* @return true if it uses a large temporary
|
||||
*/
|
||||
boolean isTemporaryAndTooBig(VarnodeTpl vn) {
|
||||
return vn.getSpace().isUniqueSpace() &&
|
||||
vn.getSize().getReal() > SleighBase.MAX_UNIQUE_SIZE;
|
||||
}
|
||||
|
||||
boolean checkVarnodeTruncation(Constructor ct,int slot,OpTpl op,VarnodeTpl vn,boolean isbigendian) {
|
||||
ConstTpl off = vn.getOffset();
|
||||
if (off.getType() != const_type.handle) {
|
||||
|
@ -1132,6 +1170,25 @@ class ConsistencyChecker {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks {@code ct} to see whether it contains an {@link OpTpl} which
|
||||
* uses a varnode in the unique space which is larger than {@link SleighBase#MAX_UNIQUE_SIZE}.
|
||||
* @param ct constructor to check
|
||||
*/
|
||||
void checkLargeTemporaries(Constructor ct) {
|
||||
ConstructTpl ctTpl = ct.getTempl();
|
||||
VectorSTL<OpTpl> ops = ctTpl.getOpvec();
|
||||
for (IteratorSTL<OpTpl> iter = ops.begin(); !iter.isEnd(); iter.increment()) {
|
||||
if (hasLargeTemporary(iter.get())) {
|
||||
if (printlargetempwarning) {
|
||||
compiler.reportWarning(ct.location, "Constructor uses temporary varnode larger than " + SleighBase.MAX_UNIQUE_SIZE + " bytes.");
|
||||
}
|
||||
largetemp++;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void optimize(Constructor ct) {
|
||||
OptimizeRecord currec;
|
||||
MapSTL<Long, OptimizeRecord> recs = new ComparableMapSTL<>();
|
||||
|
@ -1149,16 +1206,21 @@ class ConsistencyChecker {
|
|||
}
|
||||
while (currec != null);
|
||||
checkUnusedTemps(ct, recs);
|
||||
checkLargeTemporaries(ct);
|
||||
}
|
||||
|
||||
ConsistencyChecker(SleighCompile cp, SubtableSymbol rt, boolean unnecessary, boolean warndead) {
|
||||
ConsistencyChecker(SleighCompile cp, SubtableSymbol rt, boolean unnecessary, boolean warndead, boolean warnlargetemp) {
|
||||
compiler = cp;
|
||||
root_symbol = rt;
|
||||
unnecessarypcode = 0;
|
||||
readnowrite = 0;
|
||||
writenoread = 0;
|
||||
//number of constructors which reference a temporary varnode larger than SleighBase.MAX_UNIQUE_SIZE
|
||||
largetemp = 0;
|
||||
printextwarning = unnecessary;
|
||||
printdeadwarning = warndead;
|
||||
//whether to print information about constructors which reference large temporary varnodes
|
||||
printlargetempwarning = warnlargetemp;
|
||||
}
|
||||
|
||||
// Main entry point for size consistency check
|
||||
|
@ -1229,4 +1291,13 @@ class ConsistencyChecker {
|
|||
int getNumWriteNoRead() {
|
||||
return writenoread;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of constructors which reference a varnode in the
|
||||
* unique space with size larger than {@link SleighBase#MAX_UNIQUE_SIZE}.
|
||||
* @return num constructors with large temp varnodes
|
||||
*/
|
||||
int getNumLargeTemporaries() {
|
||||
return largetemp;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -254,6 +254,7 @@ public class SleighCompile extends SleighBase {
|
|||
boolean warnunusedfields; // True if fields are defined but not used
|
||||
boolean enforcelocalkeyword; // Force slaspec to use 'local' keyword when defining temporary varnodes
|
||||
boolean lenientconflicterrors; // True if we ignore most pattern conflict errors
|
||||
boolean largetemporarywarning; // True if we warn about temporaries larger than SleighBase.MAX_UNIQUE_SIZE
|
||||
public boolean warnalllocalcollisions;
|
||||
public boolean warnallnops;
|
||||
public VectorSTL<String> noplist = new VectorSTL<>();
|
||||
|
@ -498,7 +499,7 @@ public class SleighCompile extends SleighBase {
|
|||
void checkConsistency() {
|
||||
entry("checkConsistency");
|
||||
ConsistencyChecker checker =
|
||||
new ConsistencyChecker(this, root, warnunnecessarypcode, warndeadtemps);
|
||||
new ConsistencyChecker(this, root, warnunnecessarypcode, warndeadtemps, largetemporarywarning);
|
||||
|
||||
if (!checker.test()) {
|
||||
errors += 1;
|
||||
|
@ -523,6 +524,11 @@ public class SleighCompile extends SleighBase {
|
|||
" operations wrote to temporaries that were not read");
|
||||
reportWarning(null, "Use -t switch to list each individually");
|
||||
}
|
||||
if ((!largetemporarywarning) && checker.getNumLargeTemporaries() > 0) {
|
||||
reportWarning(null, checker.getNumLargeTemporaries() +
|
||||
" constructors contain temporaries larger than " + SleighBase.MAX_UNIQUE_SIZE + " bytes.");
|
||||
reportWarning(null, "Use -o switch to list each individually.");
|
||||
}
|
||||
}
|
||||
|
||||
static int findCollision(Map<Long, Integer> local2Operand, ArrayList<Long> locals,
|
||||
|
@ -686,7 +692,7 @@ public class SleighCompile extends SleighBase {
|
|||
long getUniqueAddr() {
|
||||
entry("getUniqueAddr");
|
||||
long base = getUniqueBase();
|
||||
setUniqueBase(base + 16); // Should be maximum size of a unique
|
||||
setUniqueBase(base + MAX_UNIQUE_SIZE);
|
||||
return base;
|
||||
}
|
||||
|
||||
|
@ -711,6 +717,17 @@ public class SleighCompile extends SleighBase {
|
|||
pcode.setEnforceLocalKey(val);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether or not to print out warning info about
|
||||
* {@link Constructor}s which reference varnodes in the
|
||||
* unique space larger than {@link SleighBase#MAX_UNIQUE_SIZE}.
|
||||
* @param val whether to print info about contructors using large varnodes
|
||||
*/
|
||||
void setLargeTemporaryWarning(boolean val) {
|
||||
entry("setLargeTemporaryWarning",val);
|
||||
largetemporarywarning = val;
|
||||
}
|
||||
|
||||
void setLenientConflict(boolean val) {
|
||||
entry("setLenientConflict", val);
|
||||
lenientconflicterrors = val;
|
||||
|
|
|
@ -49,7 +49,7 @@ public class SleighCompileLauncher implements GhidraLaunchable {
|
|||
private static void initCompiler(SleighCompile compiler, Map<String, String> preprocs,
|
||||
boolean unnecessaryPcodeWarning, boolean lenientConflict, boolean allCollisionWarning,
|
||||
boolean allNopWarning, boolean deadTempWarning, boolean unusedFieldWarning,
|
||||
boolean enforceLocalKeyWord) {
|
||||
boolean enforceLocalKeyWord, boolean largeTemporaryWarning) {
|
||||
Set<Entry<String, String>> entrySet = preprocs.entrySet();
|
||||
for (Entry<String, String> entry : entrySet) {
|
||||
compiler.setPreprocValue(entry.getKey(), entry.getValue());
|
||||
|
@ -61,6 +61,7 @@ public class SleighCompileLauncher implements GhidraLaunchable {
|
|||
compiler.setDeadTempWarning(deadTempWarning);
|
||||
compiler.setUnusedFieldWarning(unusedFieldWarning);
|
||||
compiler.setEnforceLocalKeyWord(enforceLocalKeyWord);
|
||||
compiler.setLargeTemporaryWarning(largeTemporaryWarning);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -111,6 +112,7 @@ public class SleighCompileLauncher implements GhidraLaunchable {
|
|||
Msg.info(SleighCompile.class, " -e enforce use of 'local' keyword for temporaries");
|
||||
Msg.info(SleighCompile.class, " -c print warnings for all constructors with colliding operands");
|
||||
Msg.info(SleighCompile.class, " -f print warnings for unused token fields");
|
||||
Msg.info(SleighCompile.class, " -o print warnings for temporaries which are too large");
|
||||
Msg.info(SleighCompile.class, " -DNAME=VALUE defines a preprocessor macro NAME with value VALUE (option may be repeated)");
|
||||
Msg.info(SleighCompile.class, " -dMODULE defines a preprocessor macro MODULE with a value of its module path (option may be repeated)");
|
||||
Msg.info(SleighCompile.class, " -i <options-file> inject options from specified file");
|
||||
|
@ -125,6 +127,7 @@ public class SleighCompileLauncher implements GhidraLaunchable {
|
|||
boolean deadTempWarning = false;
|
||||
boolean enforceLocalKeyWord = false;
|
||||
boolean unusedFieldWarning = false;
|
||||
boolean largeTemporaryWarning = false;
|
||||
|
||||
int i;
|
||||
for (i = 0; i < args.length; ++i) {
|
||||
|
@ -185,6 +188,9 @@ public class SleighCompileLauncher implements GhidraLaunchable {
|
|||
else if (args[i].charAt(1) == 'a') {
|
||||
allMode = true;
|
||||
}
|
||||
else if (args[i].charAt(1) == 'o') {
|
||||
largeTemporaryWarning = true;
|
||||
}
|
||||
else if (args[i].charAt(1) == 'x') {
|
||||
SleighCompile.yydebug = true; // Debug option
|
||||
}
|
||||
|
@ -219,7 +225,7 @@ public class SleighCompileLauncher implements GhidraLaunchable {
|
|||
SleighCompile compiler = new SleighCompile();
|
||||
initCompiler(compiler, preprocs, unnecessaryPcodeWarning, lenientConflict,
|
||||
allCollisionWarning, allNopWarning, deadTempWarning, unusedFieldWarning,
|
||||
enforceLocalKeyWord);
|
||||
enforceLocalKeyWord, largeTemporaryWarning);
|
||||
|
||||
String outname = input.getName().replace(".slaspec", ".sla");
|
||||
File output = new File(input.getParent(), outname);
|
||||
|
@ -248,7 +254,7 @@ public class SleighCompileLauncher implements GhidraLaunchable {
|
|||
SleighCompile compiler = new SleighCompile();
|
||||
initCompiler(compiler, preprocs, unnecessaryPcodeWarning, lenientConflict,
|
||||
allCollisionWarning, allNopWarning, deadTempWarning, unusedFieldWarning,
|
||||
enforceLocalKeyWord);
|
||||
enforceLocalKeyWord, largeTemporaryWarning);
|
||||
if (i == args.length) {
|
||||
Msg.error(SleighCompile.class, "Missing input file name");
|
||||
return 1;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue