Merge remote-tracking branch 'origin/patch'

This commit is contained in:
Ryan Kurtz
2026-01-13 04:38:15 -05:00
19 changed files with 145 additions and 149 deletions
@@ -228,16 +228,15 @@ public class DebuggerSnapshotTablePanel extends JPanel {
}
TraceSnapshot snapshot = row.getSnapshot();
if (snapshot.getSchedule().isSnapOnly() ||
snapshot.getVersion() >= current.getTrace().getEmulatorCacheVersion()) {
if (snapshot.isStale(true)) {
setForeground(
data.isSelected() ? COLOR_FOREGROUND_STALE_SEL : COLOR_FOREGROUND_STALE);
}
else {
JTable table = data.getTable();
setForeground(
data.isSelected() ? table.getSelectionForeground() : table.getForeground());
}
else {
setForeground(
data.isSelected() ? COLOR_FOREGROUND_STALE_SEL : COLOR_FOREGROUND_STALE);
}
return this;
}
@@ -699,7 +699,7 @@ public class DebuggerEmulationServicePlugin extends Plugin implements DebuggerEm
TraceSchedule time = key.time;
TraceSnapshot tracePrefix = trace.getTimeManager().findSnapshotWithNearestPrefix(time);
if (tracePrefix.getSchedule().isSnapOnly()) {
if (tracePrefix != null && tracePrefix.isSnapOnly(true)) {
tracePrefix = null;
}
Map.Entry<CacheKey, CachedEmulator> cachePrefix = findNearestPrefix(key);
@@ -227,6 +227,28 @@ public class DBTraceSnapshot extends DBAnnotatedObject implements TraceSnapshot
}
}
@Override
public boolean isSnapOnly(boolean whenInconsistent) {
if (schedule == null && key < 0) {
return whenInconsistent;
}
return schedule == null || schedule.isSnapOnly();
}
@Override
public boolean isStale(boolean whenInconsistent) {
if (schedule == null) {
if (key < 0) {
return whenInconsistent;
}
return false; // A recorded snapshot
}
if (schedule.isSnapOnly()) {
return false;
}
return version < manager.trace.getEmulatorCacheVersion();
}
@Override
public void delete() {
manager.deleteSnapshot(this);
@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -43,7 +43,7 @@ public interface TraceSnapshot {
/**
* Get the description of the snapshot
*
* @return
* @return the description
*/
String getDescription();
@@ -131,6 +131,34 @@ public interface TraceSnapshot {
*/
void setVersion(long version);
/**
* Check if a snapshot involves any steps of emulation
* <p>
* A scratch snapshot, i.e., whose key is negative, without a schedule set is considered
* inconsistent.
*
* @param whenInconsistent the value to return for a scratch snapshot without a set schedule
* @return true if no emulation is involved
*/
boolean isSnapOnly(boolean whenInconsistent);
/**
* For an emulated snapshot, check if re-emulation is necessary to produce an up-to-date
* snapshot.
* <p>
* For non-emulated snapshots, this always returns false. A non-emulated snapshot is a snapshot
* whose schedule includes no emulation steps. An emulation snapshot is stale when its version
* is less than the trace's emulator cache version. A scratch snapshot, i.e., whose key is
* negative, without a schedule set is considered inconsistent.
*
* @param whenInconsistent the value to return for a scratch snapshot without a set schedule
* @return true if re-emulation is needed
* @see #getVersion()
* @see #setVersion(long)
* @see Trace#getEmulatorCacheVersion()
*/
boolean isStale(boolean whenInconsistent);
/**
* Delete this snapshot
*
@@ -17,7 +17,7 @@
namespace ghidra {
const uint4 SleighBase::MAX_UNIQUE_SIZE = 128;
const uint4 SleighBase::MAX_UNIQUE_SIZE = 256;
int4 SourceFileIndexer::index(const string filename){
auto it = fileToIndex.find(filename);
@@ -255,8 +255,7 @@ void ConsistencyChecker::OptimizeRecord::updateCombine(ConsistencyChecker::Optim
/// \param rt is the root subtable of the SLEIGH spec
/// \param un is \b true to request "Unnecessary extension" warnings
/// \param warndead is \b true to request warnings for written but not read temporaries
/// \param warnlargetemp is \b true to request warnings for temporaries that are too large
ConsistencyChecker::ConsistencyChecker(SleighCompile *sleigh,SubtableSymbol *rt,bool un,bool warndead, bool warnlargetemp)
ConsistencyChecker::ConsistencyChecker(SleighCompile *sleigh,SubtableSymbol *rt,bool un,bool warndead)
{
compiler = sleigh;
@@ -264,10 +263,8 @@ 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
}
/// \brief Recover a specific value for the size associated with a Varnode template
@@ -1632,12 +1629,9 @@ void ConsistencyChecker::checkLargeTemporaries(Constructor *ct,ConstructTpl *ctp
vector<OpTpl*> ops = ctpl->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++;
compiler->reportError(
compiler->getLocation(ct),
"Constructor uses temporary varnode larger than " + to_string(SleighBase::MAX_UNIQUE_SIZE) + " bytes.");
return;
}
}
@@ -1959,7 +1953,6 @@ SleighCompile::SleighCompile(void)
warnunnecessarypcode = false;
warndeadtemps = false;
lenientconflicterrors = true;
largetemporarywarning = false;
warnalllocalcollisions = false;
warnallnops = false;
failinsensitivedups = true;
@@ -2141,7 +2134,7 @@ void SleighCompile::buildPatterns(void)
void SleighCompile::checkConsistency(void)
{
ConsistencyChecker checker(this, root,warnunnecessarypcode,warndeadtemps,largetemporarywarning);
ConsistencyChecker checker(this, root,warnunnecessarypcode,warndeadtemps);
if (!checker.testSizeRestrictions()) {
errors += 1;
@@ -2171,14 +2164,6 @@ void SleighCompile::checkConsistency(void)
reportWarning("Use -t switch to list each individually");
}
checker.testLargeTemporary();
if ((!largetemporarywarning) && (checker.getNumLargeTemporaries() > 0)) {
ostringstream msg;
msg << dec << checker.getNumLargeTemporaries();
msg << " constructors contain temporaries larger than ";
msg << SleighBase::MAX_UNIQUE_SIZE << " bytes";
reportWarning(msg.str());
reportWarning("Use -o switch to list each individually.");
}
}
/// \brief Search for offset matches between a previous set and the given current set
@@ -3345,6 +3330,18 @@ vector<OpTpl *> *SleighCompile::createCrossBuild(VarnodeTpl *addr,SectionSymbol
return res;
}
/// \brief Prepare for a new section of p-code templates
///
/// Create the ConstructTpl to hold the templates and reset counters.
/// \return the new ConstructTpl
ConstructTpl *SleighCompile::enterSection(void)
{
ConstructTpl *tpl = new ConstructTpl();
pcode.resetLabelCount(); // Macros have their own labels
return tpl;
}
/// \brief Create a new Constructor under the given subtable
///
/// Create the object and initialize parsing for the new definition
@@ -3882,13 +3879,12 @@ static void findSlaSpecs(vector<string> &res, const string &dir, const string &s
/// \param allNopWarning is \b true for individual warnings about NOP constructors
/// \param deadTempWarning is \b true for individual warnings about dead temporary varnodes
/// \param enforceLocalKeyWord is \b true to force all local variable definitions to use the \b local keyword
/// \param largeTemporaryWarning is \b true for individual warnings about temporary varnodes that are too large
/// \param caseSensitiveRegisterNames is \b true if register names are allowed to be case sensitive
/// \param debugOutput is \b true if the output file is written using the debug (XML) form of the .sla format
void SleighCompile::setAllOptions(const map<string,string> &defines, bool unnecessaryPcodeWarning,
bool lenientConflict, bool allCollisionWarning,
bool allNopWarning,bool deadTempWarning,bool enforceLocalKeyWord,
bool largeTemporaryWarning, bool caseSensitiveRegisterNames,bool debugOutput)
bool caseSensitiveRegisterNames,bool debugOutput)
{
map<string,string>::const_iterator iter = defines.begin();
for (iter = defines.begin(); iter != defines.end(); iter++) {
@@ -3900,7 +3896,6 @@ void SleighCompile::setAllOptions(const map<string,string> &defines, bool unnece
setAllNopWarning( allNopWarning );
setDeadTempWarning(deadTempWarning);
setEnforceLocalKeyWord(enforceLocalKeyWord);
setLargeTemporaryWarning(largeTemporaryWarning);
setInsensitiveDuplicateError(!caseSensitiveRegisterNames);
setDebugOutput(debugOutput);
}
@@ -3935,7 +3930,6 @@ 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 << " -s treat register names as case sensitive" << endl;
cerr << " -DNAME=VALUE defines a preprocessor macro NAME with value VALUE" << endl;
exit(2);
@@ -3950,7 +3944,6 @@ int main(int argc,char **argv)
bool allNopWarning = false;
bool deadTempWarning = false;
bool enforceLocalKeyWord = false;
bool largeTemporaryWarning = false;
bool caseSensitiveRegisterNames = false;
bool debugOutput = false;
@@ -3984,8 +3977,6 @@ int main(int argc,char **argv)
deadTempWarning = true;
else if (argv[i][1] == 'e')
enforceLocalKeyWord = true;
else if (argv[i][1] == 'o')
largeTemporaryWarning = true;
else if (argv[i][1] == 's')
caseSensitiveRegisterNames = true;
else if (argv[i][1] == 'y')
@@ -4021,8 +4012,7 @@ int main(int argc,char **argv)
sla.replace(slaspec.length() - slaspecExtLen, slaspecExtLen, SLAEXT);
SleighCompile compiler;
compiler.setAllOptions(defines, unnecessaryPcodeWarning, lenientConflict, allCollisionWarning, allNopWarning,
deadTempWarning, enforceLocalKeyWord,largeTemporaryWarning, caseSensitiveRegisterNames,
debugOutput);
deadTempWarning, enforceLocalKeyWord, caseSensitiveRegisterNames, debugOutput);
retval = compiler.run_compilation(slaspec,sla);
if (retval != 0) {
return retval; // stop on first error
@@ -4058,8 +4048,7 @@ int main(int argc,char **argv)
SleighCompile compiler;
compiler.setAllOptions(defines, unnecessaryPcodeWarning, lenientConflict, allCollisionWarning, allNopWarning,
deadTempWarning, enforceLocalKeyWord,largeTemporaryWarning,caseSensitiveRegisterNames,
debugOutput);
deadTempWarning, enforceLocalKeyWord,caseSensitiveRegisterNames,debugOutput);
if (i < argc - 1) {
string fileoutExamine(argv[i+1]);
@@ -188,10 +188,8 @@ private:
int4 unnecessarypcode; ///< Count of unnecessary extension/truncation operations
int4 readnowrite; ///< Count of temporary registers that are read but not written
int4 writenoread; ///< Count of temporary registers that are written but not read
int4 largetemp; ///< Count of temporary registers that are too large
bool printextwarning; ///< Set to \b true if warning emitted for each unnecessary truncation/extension
bool printdeadwarning; ///< Set to \b true if warning emitted for each written but not read temporary
bool printlargetempwarning; ///< Set to \b true if warning emitted for each too large temporary
SubtableSymbol *root_symbol; ///< The root symbol table for the parsed SLEIGH file
vector<SubtableSymbol *> postorder; ///< Subtables sorted into \e post order (dependent tables listed earlier)
map<SubtableSymbol *,int4> sizemap; ///< Sizes associated with table \e exports
@@ -223,7 +221,7 @@ private:
void checkLargeTemporaries(Constructor *ct,ConstructTpl *ctpl);
void optimize(Constructor *ct);
public:
ConsistencyChecker(SleighCompile *sleigh, SubtableSymbol *rt,bool unnecessary,bool warndead, bool warnlargetemp);
ConsistencyChecker(SleighCompile *sleigh, SubtableSymbol *rt,bool unnecessary,bool warndead);
bool testSizeRestrictions(void); ///< Test size consistency of all p-code
bool testTruncations(void); ///< Test truncation validity of all p-code
void testLargeTemporary(void); ///< Test for temporary Varnodes that are too large
@@ -231,7 +229,6 @@ public:
int4 getNumUnnecessaryPcode(void) const { return unnecessarypcode; } ///< Return the number of unnecessary extensions and truncations
int4 getNumReadNoWrite(void) const { return readnowrite; } ///< Return the number of temporaries read but not written
int4 getNumWriteNoRead(void) const { return writenoread; } ///< Return the number of temporaries written but not read
int4 getNumLargeTemporaries(void) const {return largetemp;} ///< Return the number of \e too large temporaries
};
/// \brief Helper function holding properties of a \e context field prior to calculating the context layout
@@ -325,7 +322,6 @@ private:
bool warnunnecessarypcode; ///< \b true if we warn of unnecessary ZEXT or SEXT
bool warndeadtemps; ///< \b true if we warn of temporaries that are written but not read
bool lenientconflicterrors; ///< \b true if we ignore most pattern conflict errors
bool largetemporarywarning; ///< \b true if we warn about temporaries larger than SleighBase::MAX_UNIQUE_SIZE
bool warnalllocalcollisions; ///< \b true if local export collisions generate individual warnings
bool warnallnops; ///< \b true if pcode NOPs generate individual warnings
bool failinsensitivedups; ///< \b true if case insensitive register duplicates cause error
@@ -388,11 +384,6 @@ public:
/// \param val is \b true if the \b local keyword must always be used. The default is \b false.
void setEnforceLocalKeyWord(bool val) { pcode.setEnforceLocalKey(val); }
/// \brief Set whether too large temporary registers generate warnings individually
///
/// \param val is \b true if warnings are generated individually. The default is \b false.
void setLargeTemporaryWarning (bool val) {largetemporarywarning = val;}
/// \brief Set whether indistinguishable Constructor patterns generate fatal errors
///
/// \param val is \b true if no error is generated. The default is \b true.
@@ -466,6 +457,7 @@ public:
SectionVector *nextNamedSection(SectionVector *vec,ConstructTpl *section,SectionSymbol *sym);
SectionVector *finalNamedSection(SectionVector *vec,ConstructTpl *section);
vector<OpTpl *> *createCrossBuild(VarnodeTpl *addr,SectionSymbol *sym);
ConstructTpl *enterSection(void);
Constructor *createConstructor(SubtableSymbol *sym);
bool isInRoot(Constructor *ct) const { return (root == ct->getParent()); } ///< Is the Constructor in the root table?
void resetConstructors(void);
@@ -484,7 +476,7 @@ public:
void setAllOptions(const map<string,string> &defines, bool unnecessaryPcodeWarning,
bool lenientConflict, bool allCollisionWarning,
bool allNopWarning,bool deadTempWarning,bool enforceLocalKeyWord,
bool largeTemporaryWarning, bool caseSensitiveRegisterNames,bool debugOutput);
bool caseSensitiveRegisterNames,bool debugOutput);
int4 run_compilation(const string &filein,const string &fileout);
};
@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -2856,7 +2856,7 @@ yyreduce:
break;
case 145:
{ (yyval.sem) = new ConstructTpl(); }
{ (yyval.sem) = slgh->enterSection(); }
break;
case 146:
@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -350,7 +350,7 @@ rtl: rtlmid { $$ = $1; if ($$->getOpvec().empty() && ($$->getResult() == (Handle
| rtlmid EXPORT_KEY STRING { string errmsg="Unknown export varnode: "+*$3; delete $3; slgh->reportError(errmsg); YYERROR; }
| rtlmid EXPORT_KEY sizedstar STRING { string errmsg="Unknown pointer varnode: "+*$4; delete $3; delete $4; slgh->reportError(errmsg); YYERROR; }
;
rtlmid: /* EMPTY */ { $$ = new ConstructTpl(); }
rtlmid: /* EMPTY */ { $$ = slgh->enterSection(); }
| rtlmid statement { $$ = $1; if (!$$->addOpList(*$2)) { delete $2; slgh->reportError("Multiple delayslot declarations"); YYERROR; } delete $2; }
| rtlmid LOCAL_KEY STRING ';' { $$ = $1; slgh->pcode.newLocalDefinition($3); }
| rtlmid LOCAL_KEY STRING ':' INTEGER ';' { $$ = $1; slgh->pcode.newLocalDefinition($3,*$5); delete $5; }
@@ -89,6 +89,7 @@ public class IndexedLocalFileSystem extends LocalFileSystem {
* to notify listeners. If false, blocking notification will be performed.
* @param create if true a new folder will be created.
* @throws FileNotFoundException if specified rootPath does not exist
* @throws IndexReadException failure occured reading index file
* @throws IOException if error occurs while reading/writing index files
*/
IndexedLocalFileSystem(String rootPath, boolean isVersioned, boolean readOnly,
@@ -440,11 +441,21 @@ public class IndexedLocalFileSystem extends LocalFileSystem {
public static int readIndexVersion(String rootPath) throws IOException {
File indexFile = new File(rootPath, INDEX_FILE);
if (indexFile.exists() && indexFile.length() == 0) {
return 0; // will trigger index rebuild
}
BufferedReader indexReader = null;
try {
indexReader = new BufferedReader(new InputStreamReader(
new BufferedInputStream(new FileInputStream(indexFile)), "UTF8"));
return getIndexVersion(indexReader.readLine());
int ver = getIndexVersion(indexReader.readLine());
if (ver >= 0 && ver < LATEST_INDEX_VERSION) {
Msg.warn(LocalFileSystem.class,
"Using deprecated Indexed filesystem (V0): " + rootPath);
}
return ver;
}
finally {
if (indexReader != null) {
@@ -463,6 +474,10 @@ public class IndexedLocalFileSystem extends LocalFileSystem {
// TODO: current implementation does not attempt to avoid concurrent read/write
// access to index/journal files
if (indexFile.length() == 0) {
throw new IndexReadException("empty index: " + indexFile);
}
MessageDigest messageDigest = null;
try {
messageDigest = MessageDigest.getInstance("MD5");
@@ -485,7 +500,7 @@ public class IndexedLocalFileSystem extends LocalFileSystem {
new BufferedInputStream(new FileInputStream(indexFile)), "UTF8"));
String line = indexReader.readLine();
if (checkIndexVersion(line)) {
// version line consumed - read next line
// version line consumed - read next line - Version-0 lacked VERSION line
line = indexReader.readLine();
}
Folder currentFolder = null;
@@ -1714,6 +1729,8 @@ public class IndexedLocalFileSystem extends LocalFileSystem {
/**
* Get the V0 indexed-file-system instance. File system storage should first be
* pre-qualified as an having indexed storage using the {@link #isIndexed(String)} method.
* <p>
* NOTE: If there is a index read error a forced migration to V1 may occur
* @param rootPath
* @param isVersioned
* @param readOnly
@@ -1735,41 +1752,16 @@ public class IndexedLocalFileSystem extends LocalFileSystem {
Msg.error(LocalFileSystem.class, "Indexed filesystem error: " + e.getMessage());
Msg.info(LocalFileSystem.class, "Attempting index rebuild: " + rootPath);
if (!IndexedLocalFileSystem.rebuild(new File(rootPath))) {
if (!IndexedV1LocalFileSystem.rebuild(new File(rootPath))) {
throw e;
}
// retry after index rebuild
return new IndexedLocalFileSystem(rootPath, isVersioned, readOnly,
return new IndexedV1LocalFileSystem(rootPath, isVersioned, readOnly,
enableAsyncronousDispatching, false);
}
}
/**
* Completely rebuild filesystem index using item information contained
* within indexed property files. Empty folders will be lost.
* @param rootDir
* @throws IOException
*/
public static boolean rebuild(File rootDir) throws IOException {
verifyIndexedFileStructure(rootDir);
IndexedLocalFileSystem fs = new IndexedLocalFileSystem(rootDir.getAbsolutePath());
fs.rebuildIndex();
fs.cleanupAfterConstruction();
fs.dispose();
File errorFile = new File(rootDir, REBUILD_ERROR_FILE);
if (errorFile.exists()) {
Msg.error(LocalFileSystem.class,
"Indexed filesystem rebuild failed, see log for details: " + errorFile);
return false;
}
Msg.info(LocalFileSystem.class, "Index rebuild completed: " + rootDir);
return true;
}
static class IndexedItemStorage extends ItemStorage {
IndexedItemStorage(File dir, String storageName, String folderPath, String itemName) {
@@ -43,6 +43,7 @@ public class IndexedV1LocalFileSystem extends IndexedLocalFileSystem {
* to notify listeners. If false, blocking notification will be performed.
* @param create if true a new folder will be created.
* @throws FileNotFoundException if specified rootPath does not exist
* @throws IndexReadException failure occured reading index file
* @throws IOException if error occurs while reading/writing index files
*/
protected IndexedV1LocalFileSystem(String rootPath, boolean isVersioned, boolean readOnly,
@@ -130,8 +130,6 @@ public abstract class LocalFileSystem implements FileSystem {
return new MangledLocalFileSystem(rootPath, isVersioned, readOnly,
enableAsyncronousDispatching);
case 0:
Msg.warn(LocalFileSystem.class,
"Using deprecated Indexed filesystem (V0): " + rootPath);
return IndexedLocalFileSystem.getFileSystem(rootPath, isVersioned, readOnly,
enableAsyncronousDispatching);
case 1:
@@ -1023,7 +1023,7 @@ code_block[Location startingPoint] returns [ConstructTpl rtl]
}
scope Block;
@init {
$Block::ct = new ConstructTpl(startingPoint);
$Block::ct = pcode.enterSection(startingPoint);
$code_block::stmtLocation = new Location("<internal error populating statement location>", 0);
}
@after {
@@ -1089,7 +1089,7 @@ statement
pcode.recordNop(s.first);
}
$semantic::containsMultipleSections = true;
$Block::ct = new ConstructTpl(s.first);
$Block::ct = pcode.enterSection(s.first);
}
;
@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -37,7 +37,7 @@ public abstract class SleighBase extends Translate implements NamedSymbolProvide
* Note: The value of {@link #MAX_UNIQUE_SIZE} must match the corresponding value
* defined by sleighbase.cc
*/
public static final long MAX_UNIQUE_SIZE = 128; //Maximum size of a varnode in the unique space.
public static final long MAX_UNIQUE_SIZE = 256; //Maximum size of a varnode in the unique space.
//Should match value in sleighbase.cc
private VectorSTL<String> userop = new VectorSTL<>();
@@ -35,10 +35,8 @@ class ConsistencyChecker {
private int readnowrite;
private int writenoread;
private int largetemp; // number of constructors using a temporary varnode larger than SleighBase.MAX_UNIQUE_SIZE
private boolean printextwarning;
private boolean printdeadwarning;
private boolean printlargetempwarning; // if true, warning about temporary varnodes larger than SleighBase.MAX_UNIQUE_SIZE
private SleighCompile compiler;
private SubtableSymbol root_symbol;
private List<SubtableSymbol> postorder = new ArrayList<>();
@@ -1261,12 +1259,9 @@ class ConsistencyChecker {
VectorSTL<OpTpl> ops = ctpl.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++;
compiler.reportError(ct.location,
"Constructor uses temporary varnode larger than " +
SleighBase.MAX_UNIQUE_SIZE + " bytes.");
return;
}
}
@@ -1298,12 +1293,8 @@ class ConsistencyChecker {
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
@@ -1401,14 +1392,4 @@ class ConsistencyChecker {
public 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
*/
public int getNumLargeTemporaries() {
return largetemp;
}
}
@@ -68,6 +68,8 @@ public abstract class PcodeCompile {
public abstract VectorSTL<OpTpl> createCrossBuild(Location find, VarnodeTpl v,
SectionSymbol second);
public abstract ConstructTpl enterSection(Location where);
public abstract SectionVector standaloneSection(ConstructTpl c);
public abstract SectionVector firstNamedSection(ConstructTpl main, SectionSymbol sym);
@@ -167,6 +167,11 @@ public class SleighCompile extends SleighBase {
return SleighCompile.this.createCrossBuild(find, v, section);
}
@Override
public ConstructTpl enterSection(Location where) {
return SleighCompile.this.enterSection(where);
}
@Override
public SectionVector standaloneSection(ConstructTpl c) {
return SleighCompile.this.standaloneSection(c);
@@ -333,6 +338,12 @@ public class SleighCompile extends SleighBase {
return res;
}
protected ConstructTpl enterSection(Location where) {
entry("enterSection", where);
pcode.resetLabelCount();
return new ConstructTpl(where);
}
protected SectionVector standaloneSection(ConstructTpl main) {
entry("standaloneSection", main);
// Create SectionVector for just the main rtl section with no named sections
@@ -534,13 +545,6 @@ public class SleighCompile extends SleighBase {
reportWarning(null, "Use -t switch to list each individually");
}
checker.testLargeTemporary();
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.");
}
}
private static int findCollision(Map<Long, Integer> local2Operand, ArrayList<Long> locals,
@@ -776,17 +780,6 @@ 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
*/
public void setLargeTemporaryWarning(boolean val) {
entry("setLargeTemporaryWarning", val);
largetemporarywarning = val;
}
public void setLenientConflict(boolean val) {
entry("setLenientConflict", val);
lenientconflicterrors = val;
@@ -1794,8 +1787,7 @@ public class SleighCompile extends SleighBase {
public void setAllOptions(Map<String, String> preprocs, boolean unnecessaryPcodeWarning,
boolean lenientConflict, boolean allCollisionWarning, boolean allNopWarning,
boolean deadTempWarning, boolean unusedFieldWarning, boolean enforceLocalKeyWord,
boolean largeTemporaryWarning, boolean caseSensitiveRegisterNames,
boolean debugOutput) {
boolean caseSensitiveRegisterNames, boolean debugOutput) {
Set<Entry<String, String>> entrySet = preprocs.entrySet();
for (Entry<String, String> entry : entrySet) {
setPreprocValue(entry.getKey(), entry.getValue());
@@ -1807,7 +1799,6 @@ public class SleighCompile extends SleighBase {
setDeadTempWarning(deadTempWarning);
setUnusedFieldWarning(unusedFieldWarning);
setEnforceLocalKeyWord(enforceLocalKeyWord);
setLargeTemporaryWarning(largeTemporaryWarning);
setInsensitiveDuplicateError(!caseSensitiveRegisterNames);
setDebugOutput(debugOutput);
}
@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -86,7 +86,6 @@ 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, " -s treat register names as case sensitive");
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)");
@@ -102,7 +101,6 @@ public class SleighCompileLauncher implements GhidraLaunchable {
boolean deadTempWarning = false;
boolean enforceLocalKeyWord = false;
boolean unusedFieldWarning = false;
boolean largeTemporaryWarning = false;
boolean caseSensitiveRegisterNames = false;
boolean debugOutput = false;
@@ -165,9 +163,6 @@ 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) == 's') {
caseSensitiveRegisterNames = true;
}
@@ -208,7 +203,7 @@ public class SleighCompileLauncher implements GhidraLaunchable {
SleighCompile compiler = new SleighCompile();
compiler.setAllOptions(preprocs, unnecessaryPcodeWarning, lenientConflict,
allCollisionWarning, allNopWarning, deadTempWarning, unusedFieldWarning,
enforceLocalKeyWord, largeTemporaryWarning, caseSensitiveRegisterNames,
enforceLocalKeyWord, caseSensitiveRegisterNames,
debugOutput);
String outname = input.getName().replace(".slaspec", ".sla");
@@ -238,7 +233,7 @@ public class SleighCompileLauncher implements GhidraLaunchable {
SleighCompile compiler = new SleighCompile();
compiler.setAllOptions(preprocs, unnecessaryPcodeWarning, lenientConflict,
allCollisionWarning, allNopWarning, deadTempWarning, unusedFieldWarning,
enforceLocalKeyWord, largeTemporaryWarning, caseSensitiveRegisterNames, debugOutput);
enforceLocalKeyWord, caseSensitiveRegisterNames, debugOutput);
if (i == args.length) {
Msg.error(SleighCompile.class, "Missing input file name");
return 1;
@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -479,6 +479,12 @@ public class PcodeParser extends PcodeCompile {
throw new SleighError("Pcode snippet parsing does not support use of sections", where);
}
@Override
public ghidra.pcodeCPort.semantics.ConstructTpl enterSection(Location where) {
resetLabelCount();
return new ghidra.pcodeCPort.semantics.ConstructTpl(where);
}
@Override
public SectionVector standaloneSection(ghidra.pcodeCPort.semantics.ConstructTpl main) {
// Create SectionVector for just the main rtl section with no named sections