mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 18:29:37 +02:00
Check for case sensitivity in register names
This commit is contained in:
parent
fca4fd4844
commit
faf2909910
14 changed files with 1607 additions and 808 deletions
|
@ -457,7 +457,7 @@ RECURSIVE = NO
|
||||||
# excluded from the INPUT source files. This way you can easily exclude a
|
# excluded from the INPUT source files. This way you can easily exclude a
|
||||||
# subdirectory from a directory tree whose root is specified with the INPUT tag.
|
# subdirectory from a directory tree whose root is specified with the INPUT tag.
|
||||||
|
|
||||||
EXCLUDE = unify.hh unify.cc rulecompile.hh rulecompile.cc slgh_compile.hh slgh_compile.cc slghparse.cc slghparse.hh slghscan.cc slghpattern.hh slghpattern.cc slghpatexpress.hh slghpatexpress.cc slghsymbol.hh slghsymbol.cc codedata.hh codedata.cc semantics.hh semantics.cc grammar.hh grammar.cc callgraph.hh callgraph.cc filemanage.hh filemanage.cc graph.hh graph.cc loadimage_bfd.hh loadimage_bfd.cc pcodecompile.cc pcodecompile.hh pcodeparse.hh pcodeparse.cc inject_sleigh.hh inject_sleigh.cc context.hh context.cc consolemain.cc sleighexample.cc xml.cc double.hh double.cc paramid.hh paramid.cc prefersplit.hh prefersplit.cc
|
EXCLUDE = unify.hh unify.cc rulecompile.hh rulecompile.cc slghparse.cc slghparse.hh slghscan.cc slghpattern.hh slghpattern.cc slghpatexpress.hh slghpatexpress.cc slghsymbol.hh slghsymbol.cc codedata.hh codedata.cc semantics.hh semantics.cc grammar.hh grammar.cc callgraph.hh callgraph.cc filemanage.hh filemanage.cc graph.hh graph.cc loadimage_bfd.hh loadimage_bfd.cc pcodecompile.cc pcodecompile.hh pcodeparse.hh pcodeparse.cc inject_sleigh.hh inject_sleigh.cc context.hh context.cc consolemain.cc sleighexample.cc xml.cc double.hh double.cc paramid.hh paramid.cc prefersplit.hh prefersplit.cc
|
||||||
|
|
||||||
# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
|
# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
|
||||||
# directories that are symbolic links (a Unix filesystem feature) are excluded
|
# directories that are symbolic links (a Unix filesystem feature) are excluded
|
||||||
|
|
|
@ -41,8 +41,6 @@ public:
|
||||||
GhidraTranslate(ArchitectureGhidra *g) { glb = g; } ///< Constructor
|
GhidraTranslate(ArchitectureGhidra *g) { glb = g; } ///< Constructor
|
||||||
|
|
||||||
virtual void initialize(DocumentStorage &store);
|
virtual void initialize(DocumentStorage &store);
|
||||||
virtual void addRegister(const string &nm,AddrSpace *base,uintb offset,int4 size) {
|
|
||||||
throw LowlevelError("Cannot add register name into GHIDRA through this interface"); }
|
|
||||||
virtual const VarnodeData &getRegister(const string &nm) const;
|
virtual const VarnodeData &getRegister(const string &nm) const;
|
||||||
virtual string getRegisterName(AddrSpace *base,uintb off,int4 size) const;
|
virtual string getRegisterName(AddrSpace *base,uintb off,int4 size) const;
|
||||||
virtual void getAllRegisters(map<VarnodeData,string> ®list) const {
|
virtual void getAllRegisters(map<VarnodeData,string> ®list) const {
|
||||||
|
|
|
@ -61,7 +61,6 @@ public:
|
||||||
class DummyTranslate : public Translate {
|
class DummyTranslate : public Translate {
|
||||||
public:
|
public:
|
||||||
virtual void initialize(DocumentStorage &store) {}
|
virtual void initialize(DocumentStorage &store) {}
|
||||||
virtual void addRegister(const string &nm,AddrSpace *base,uintb offset,int4 size) {}
|
|
||||||
virtual const VarnodeData &getRegister(const string &nm) const { throw LowlevelError("Cannot add register to DummyTranslate"); }
|
virtual const VarnodeData &getRegister(const string &nm) const { throw LowlevelError("Cannot add register to DummyTranslate"); }
|
||||||
virtual string getRegisterName(AddrSpace *base,uintb off,int4 size) const { return ""; }
|
virtual string getRegisterName(AddrSpace *base,uintb off,int4 size) const { return ""; }
|
||||||
virtual void getAllRegisters(map<VarnodeData,string> ®list) const {}
|
virtual void getAllRegisters(map<VarnodeData,string> ®list) const {}
|
||||||
|
|
|
@ -124,13 +124,6 @@ void SleighBase::reregisterContext(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SleighBase::addRegister(const string &nm,AddrSpace *base,uintb offset,int4 size)
|
|
||||||
|
|
||||||
{
|
|
||||||
VarnodeSymbol *sym = new VarnodeSymbol(nm,base,offset,size);
|
|
||||||
symtab.addSymbol(sym);
|
|
||||||
}
|
|
||||||
|
|
||||||
const VarnodeData &SleighBase::getRegister(const string &nm) const
|
const VarnodeData &SleighBase::getRegister(const string &nm) const
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
|
@ -73,7 +73,6 @@ public:
|
||||||
SleighBase(void); ///< Construct an uninitialized translator
|
SleighBase(void); ///< Construct an uninitialized translator
|
||||||
bool isInitialized(void) const { return (root != (SubtableSymbol *)0); } ///< Return \b true if \b this is initialized
|
bool isInitialized(void) const { return (root != (SubtableSymbol *)0); } ///< Return \b true if \b this is initialized
|
||||||
virtual ~SleighBase(void) {} ///< Destructor
|
virtual ~SleighBase(void) {} ///< Destructor
|
||||||
virtual void addRegister(const string &nm,AddrSpace *base,uintb offset,int4 size);
|
|
||||||
virtual const VarnodeData &getRegister(const string &nm) const;
|
virtual const VarnodeData &getRegister(const string &nm) const;
|
||||||
virtual string getRegisterName(AddrSpace *base,uintb off,int4 size) const;
|
virtual string getRegisterName(AddrSpace *base,uintb off,int4 size) const;
|
||||||
virtual void getAllRegisters(map<VarnodeData,string> ®list) const;
|
virtual void getAllRegisters(map<VarnodeData,string> ®list) const;
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -13,66 +13,99 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
/// \file slgh_compile.hh
|
||||||
|
/// \brief High-level control of the sleigh compilation process
|
||||||
|
|
||||||
#include "sleighbase.hh"
|
#include "sleighbase.hh"
|
||||||
#include "pcodecompile.hh"
|
#include "pcodecompile.hh"
|
||||||
#include "filemanage.hh"
|
#include "filemanage.hh"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
// High-level control of the sleigh compilation process
|
/// \brief A helper class to associate a \e named Constructor section with its symbol scope
|
||||||
|
///
|
||||||
|
/// A Constructor can contain multiple named sections of p-code. There is a \e main
|
||||||
|
/// section associated with the constructor, but other sections are possible and can
|
||||||
|
/// be accessed through the \b crossbuild directive, which allows their operations to be
|
||||||
|
/// incorporated into nearby instructions. During parsing of a SLEIGH file, \b this class
|
||||||
|
/// associates a named section with its dedicated symbol scope.
|
||||||
struct RtlPair {
|
struct RtlPair {
|
||||||
ConstructTpl *section; // A p-code section
|
ConstructTpl *section; ///< A named p-code section
|
||||||
SymbolScope *scope; // and its associated symbol scope
|
SymbolScope *scope; ///< Symbol scope associated with the section
|
||||||
RtlPair(void) { section = (ConstructTpl *)0; scope = (SymbolScope *)0; }
|
RtlPair(void) { section = (ConstructTpl *)0; scope = (SymbolScope *)0; } ///< Construct on empty pair
|
||||||
RtlPair(ConstructTpl *sec,SymbolScope *sc) { section = sec; scope = sc; }
|
RtlPair(ConstructTpl *sec,SymbolScope *sc) { section = sec; scope = sc; } ///< Constructor
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// \brief A collection of \e named p-code sections for a single Constructor
|
||||||
|
///
|
||||||
|
/// A Constructor always has a \b main section of p-code (which may be empty).
|
||||||
|
/// Alternately a Constructor may define additional \e named sections of p-code.
|
||||||
|
/// Operations in these sections are emitted using the \b crossbuild directive and
|
||||||
|
/// can be incorporated into following instructions.
|
||||||
|
///
|
||||||
|
/// Internally different sections (RtlPair) are identified by index. A
|
||||||
|
/// SectionSymbol holds the section's name and its corresponding index.
|
||||||
class SectionVector {
|
class SectionVector {
|
||||||
int4 nextindex;
|
int4 nextindex; ///< Index of the section currently being parsed.
|
||||||
RtlPair main;
|
RtlPair main; ///< The main section
|
||||||
vector<RtlPair> named;
|
vector<RtlPair> named; ///< Named sections accessed by index
|
||||||
public:
|
public:
|
||||||
SectionVector(ConstructTpl *rtl,SymbolScope *scope);
|
SectionVector(ConstructTpl *rtl,SymbolScope *scope); ///< Constructor
|
||||||
ConstructTpl *getMainSection(void) const { return main.section; }
|
ConstructTpl *getMainSection(void) const { return main.section; } ///< Get the \e main section
|
||||||
ConstructTpl *getNamedSection(int4 index) const { return named[index].section; }
|
ConstructTpl *getNamedSection(int4 index) const { return named[index].section; } ///< Get a \e named section by index
|
||||||
RtlPair getMainPair(void) const { return main; }
|
RtlPair getMainPair(void) const { return main; } ///< Get the \e main section/namespace pair
|
||||||
RtlPair getNamedPair(int4 i) const { return named[i]; }
|
RtlPair getNamedPair(int4 i) const { return named[i]; } ///< Get a \e named section/namespace pair by index
|
||||||
void setNextIndex(int4 i) { nextindex = i; }
|
void setNextIndex(int4 i) { nextindex = i; } ///< Set the index of the currently parsing \e named section
|
||||||
int4 getMaxId(void) const { return named.size(); }
|
int4 getMaxId(void) const { return named.size(); } ///< Get the maximum (exclusive) named section index
|
||||||
void append(ConstructTpl *rtl,SymbolScope *scope);
|
void append(ConstructTpl *rtl,SymbolScope *scope); ///< Add a new \e named section
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SpaceQuality { // Qualities of an address space
|
/// \brief Qualities associated (via parsing) with an address space
|
||||||
enum { // Class of space
|
///
|
||||||
ramtype,
|
/// An object of this class accumulates properties of an address space as they
|
||||||
registertype
|
/// are parsed in the \b define statement prior to formally allocating the AddrSpace object.
|
||||||
|
struct SpaceQuality {
|
||||||
|
/// \brief The type of space being defined
|
||||||
|
enum {
|
||||||
|
ramtype, ///< An address space representing normal, indexed, memory
|
||||||
|
registertype ///< An address space containing registers
|
||||||
};
|
};
|
||||||
string name;
|
string name; ///< Name of the address space
|
||||||
uint4 type;
|
uint4 type; ///< Type of address space, \e ramtype or \e registertype
|
||||||
uint4 size;
|
uint4 size; ///< Number of bytes required to index all bytes of the space
|
||||||
uint4 wordsize; // number of bytes in unit of the space
|
uint4 wordsize; ///< Number of bytes in an addressable unit of the space
|
||||||
bool isdefault;
|
bool isdefault; ///< \b true if the new address space will be the default
|
||||||
SpaceQuality(const string &nm);
|
SpaceQuality(const string &nm); ///< Constructor
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// \brief Qualities associated (via parsing) with a token or context \b field
|
||||||
|
///
|
||||||
|
/// An object of this class accumulates properties of a field as they
|
||||||
|
/// are parsed in of a \b define \b token block prior to formally allocating the
|
||||||
|
/// TokenField or FieldContext object.
|
||||||
struct FieldQuality {
|
struct FieldQuality {
|
||||||
string name;
|
string name; ///< Name of the field
|
||||||
uint4 low,high;
|
uint4 low; ///< The least significant bit of the field within the token
|
||||||
bool signext;
|
uint4 high; ///< The most significant bit of the field within the token
|
||||||
bool flow;
|
bool signext; ///< \b true if the field's value is signed
|
||||||
bool hex;
|
bool flow; ///< \b true if the context \b flows for this field.
|
||||||
FieldQuality(string *nm,uintb *l,uintb *h);
|
bool hex; ///< \b true if the field value is displayed in hex
|
||||||
|
FieldQuality(string *nm,uintb *l,uintb *h); ///< Constructor
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// \brief Subtable, pattern, and context information applied across a \b with block
|
||||||
|
///
|
||||||
|
/// The header of a \b with block is applied to all constructors in the block. It
|
||||||
|
/// attaches each constructor to a specific subtable. A pattern expression and/or a
|
||||||
|
/// a series of context changes is attached to each constructor as well.
|
||||||
class WithBlock {
|
class WithBlock {
|
||||||
SubtableSymbol *ss;
|
SubtableSymbol *ss; ///< Subtable containing each Constructor (or null for root table)
|
||||||
PatternEquation *pateq;
|
PatternEquation *pateq; ///< Pattern to prepend to each Constructor (or null)
|
||||||
vector<ContextChange *> contvec;
|
vector<ContextChange *> contvec; ///< Context change to associate with each constructor (or null)
|
||||||
public:
|
public:
|
||||||
WithBlock(void) { pateq = (PatternEquation *)0; }
|
WithBlock(void) { pateq = (PatternEquation *)0; } ///< Constructor
|
||||||
void set(SubtableSymbol *s, PatternEquation *pq, vector<ContextChange *> *cvec);
|
void set(SubtableSymbol *s, PatternEquation *pq, vector<ContextChange *> *cvec); ///< Set components of the header
|
||||||
~WithBlock(void);
|
~WithBlock(void); ///< Destructor
|
||||||
static PatternEquation *collectAndPrependPattern(const list<WithBlock> &stack, PatternEquation *pateq);
|
static PatternEquation *collectAndPrependPattern(const list<WithBlock> &stack, PatternEquation *pateq);
|
||||||
static vector<ContextChange *> *collectAndPrependContext(const list<WithBlock> &stack, vector<ContextChange *> *contvec);
|
static vector<ContextChange *> *collectAndPrependContext(const list<WithBlock> &stack, vector<ContextChange *> *contvec);
|
||||||
static SubtableSymbol *getCurrentSubtable(const list<WithBlock> &stack);
|
static SubtableSymbol *getCurrentSubtable(const list<WithBlock> &stack);
|
||||||
|
@ -80,30 +113,53 @@ public:
|
||||||
|
|
||||||
class SleighCompile;
|
class SleighCompile;
|
||||||
|
|
||||||
|
/// \brief Derive Varnode sizes and optimize p-code in SLEIGH Constructors
|
||||||
|
///
|
||||||
|
/// This class examines p-code parsed from a SLEIGH file and performs three main tasks:
|
||||||
|
/// - Enforcing size rules in Constructor p-code,
|
||||||
|
/// - Optimizing p-code within a Constructor, and
|
||||||
|
/// - Searching for other p-code validity violations
|
||||||
|
///
|
||||||
|
/// Many p-code operators require that their input and/or output operands are all the same size
|
||||||
|
/// or have other specific size restrictions on their operands. This class enforces those requirements.
|
||||||
|
///
|
||||||
|
/// This class performs limited optimization of p-code within a Constructor by performing COPY
|
||||||
|
/// propagation through \e temporary registers.
|
||||||
|
///
|
||||||
|
/// This class searches for unnecessary truncations and extensions, temporary varnodes that are either dead,
|
||||||
|
/// read before written, or that exceed the standard allocation size.
|
||||||
class ConsistencyChecker {
|
class ConsistencyChecker {
|
||||||
|
|
||||||
|
/// \brief Description of how a temporary register is being used within a Constructor
|
||||||
|
///
|
||||||
|
/// This counts reads and writes of the register. If the register is read only once, the
|
||||||
|
/// particular p-code op and input slot reading it is recorded. If the register is written
|
||||||
|
/// only once, the particular p-code op writing it is recorded.
|
||||||
struct OptimizeRecord {
|
struct OptimizeRecord {
|
||||||
int4 writeop;
|
int4 writeop; ///< Index of the (last) p-code op writing to register (or -1)
|
||||||
int4 readop;
|
int4 readop; ///< Index of the (last) p-code op reading the register (or -1)
|
||||||
int4 inslot;
|
int4 inslot; ///< Input slot of p-code op reading the register (or -1)
|
||||||
int4 writecount;
|
int4 writecount; ///< Number of times the register is written
|
||||||
int4 readcount;
|
int4 readcount; ///< Number of times the register is read
|
||||||
int4 writesection;
|
int4 writesection; ///< Section containing (last) p-code op writing to the register (or -2)
|
||||||
int4 readsection;
|
int4 readsection; ///< Section containing (last) p-code op reading the register (or -2)
|
||||||
int4 opttype;
|
mutable int4 opttype; ///< 0 = register read by a COPY, 1 = register written by a COPY (-1 otherwise)
|
||||||
|
|
||||||
|
/// \brief Construct a record, initializing counts
|
||||||
OptimizeRecord(void) {
|
OptimizeRecord(void) {
|
||||||
writeop = -1; readop = -1; inslot=-1; writecount=0; readcount=0; writesection=-2; readsection=-2; opttype=-1; }
|
writeop = -1; readop = -1; inslot=-1; writecount=0; readcount=0; writesection=-2; readsection=-2; opttype=-1; }
|
||||||
};
|
};
|
||||||
SleighCompile *compiler;
|
SleighCompile *compiler; ///< Parsed form of the SLEIGH file being examined
|
||||||
int4 unnecessarypcode;
|
int4 unnecessarypcode; ///< Count of unnecessary extension/truncation operations
|
||||||
int4 readnowrite;
|
int4 readnowrite; ///< Count of temporary registers that are read but not written
|
||||||
int4 writenoread;
|
int4 writenoread; ///< Count of temporary registers that are written but not read
|
||||||
int4 largetemp;
|
int4 largetemp; ///< Count of temporary registers that are too large
|
||||||
bool printextwarning;
|
bool printextwarning; ///< Set to \b true if warning emitted for each unnecessary truncation/extension
|
||||||
bool printdeadwarning;
|
bool printdeadwarning; ///< Set to \b true if warning emitted for each written but not read temporary
|
||||||
bool printlargetempwarning;
|
bool printlargetempwarning; ///< Set to \b true if warning emitted for each too large temporary
|
||||||
SubtableSymbol *root_symbol;
|
SubtableSymbol *root_symbol; ///< The root symbol table for the parsed SLEIGH file
|
||||||
vector<SubtableSymbol *> postorder;
|
vector<SubtableSymbol *> postorder; ///< Subtables sorted into \e post order (dependent tables listed earlier)
|
||||||
map<SubtableSymbol *,int4> sizemap; // Sizes associated with tables
|
map<SubtableSymbol *,int4> sizemap; ///< Sizes associated with table \e exports
|
||||||
OperandSymbol *getOperandSymbol(int4 slot,OpTpl *op,Constructor *ct);
|
OperandSymbol *getOperandSymbol(int4 slot,OpTpl *op,Constructor *ct);
|
||||||
void printOpName(ostream &s,OpTpl *op);
|
void printOpName(ostream &s,OpTpl *op);
|
||||||
void printOpError(OpTpl *op,Constructor *ct,int4 err1,int4 err2,const string &message);
|
void printOpError(OpTpl *op,Constructor *ct,int4 err1,int4 err2,const string &message);
|
||||||
|
@ -118,7 +174,7 @@ class ConsistencyChecker {
|
||||||
bool checkSubtable(SubtableSymbol *sym);
|
bool checkSubtable(SubtableSymbol *sym);
|
||||||
void dealWithUnnecessaryExt(OpTpl *op,Constructor *ct);
|
void dealWithUnnecessaryExt(OpTpl *op,Constructor *ct);
|
||||||
void dealWithUnnecessaryTrunc(OpTpl *op,Constructor *ct);
|
void dealWithUnnecessaryTrunc(OpTpl *op,Constructor *ct);
|
||||||
void setPostOrder(SubtableSymbol *root); // Establish table ordering
|
void setPostOrder(SubtableSymbol *root);
|
||||||
|
|
||||||
// Optimization routines
|
// Optimization routines
|
||||||
static void examineVn(map<uintb,OptimizeRecord> &recs,const VarnodeTpl *vn,uint4 i,int4 inslot,int4 secnum);
|
static void examineVn(map<uintb,OptimizeRecord> &recs,const VarnodeTpl *vn,uint4 i,int4 inslot,int4 secnum);
|
||||||
|
@ -126,43 +182,56 @@ class ConsistencyChecker {
|
||||||
bool readWriteInterference(const VarnodeTpl *vn,const OpTpl *op,bool checkread) const;
|
bool readWriteInterference(const VarnodeTpl *vn,const OpTpl *op,bool checkread) const;
|
||||||
void optimizeGather1(Constructor *ct,map<uintb,OptimizeRecord> &recs,int4 secnum) const;
|
void optimizeGather1(Constructor *ct,map<uintb,OptimizeRecord> &recs,int4 secnum) const;
|
||||||
void optimizeGather2(Constructor *ct,map<uintb,OptimizeRecord> &recs,int4 secnum) const;
|
void optimizeGather2(Constructor *ct,map<uintb,OptimizeRecord> &recs,int4 secnum) const;
|
||||||
OptimizeRecord *findValidRule(Constructor *ct,map<uintb,OptimizeRecord> &recs) const;
|
const OptimizeRecord *findValidRule(Constructor *ct,const map<uintb,OptimizeRecord> &recs) const;
|
||||||
void applyOptimization(Constructor *ct,const OptimizeRecord &rec);
|
void applyOptimization(Constructor *ct,const OptimizeRecord &rec);
|
||||||
void checkUnusedTemps(Constructor *ct,const map<uintb,OptimizeRecord> &recs);
|
void checkUnusedTemps(Constructor *ct,const map<uintb,OptimizeRecord> &recs);
|
||||||
void checkLargeTemporaries(Constructor *ct);
|
void checkLargeTemporaries(Constructor *ct,ConstructTpl *ctpl);
|
||||||
void optimize(Constructor *ct);
|
void optimize(Constructor *ct);
|
||||||
public:
|
public:
|
||||||
ConsistencyChecker(SleighCompile *sleigh, SubtableSymbol *rt,bool unnecessary,bool warndead, bool warnlargetemp);
|
ConsistencyChecker(SleighCompile *sleigh, SubtableSymbol *rt,bool unnecessary,bool warndead, bool warnlargetemp);
|
||||||
bool test(void);
|
bool testSizeRestrictions(void); ///< Test size consistency of all p-code
|
||||||
bool testTruncations(bool isbigendian);
|
bool testTruncations(void); ///< Test truncation validity of all p-code
|
||||||
void optimizeAll(void);
|
void testLargeTemporary(void); ///< Test for temporary Varnodes that are too large
|
||||||
int4 getNumUnnecessaryPcode(void) const { return unnecessarypcode; }
|
void optimizeAll(void); ///< Do COPY propagation optimization on all p-code
|
||||||
int4 getNumReadNoWrite(void) const { return readnowrite; }
|
int4 getNumUnnecessaryPcode(void) const { return unnecessarypcode; } ///< Return the number of unnecessary extensions and truncations
|
||||||
int4 getNumWriteNoRead(void) const { return writenoread; }
|
int4 getNumReadNoWrite(void) const { return readnowrite; } ///< Return the number of temporaries read but not written
|
||||||
int4 getNumLargeTemporaries(void) const {return largetemp;}
|
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
|
||||||
|
///
|
||||||
|
/// This holds the concrete Varnode reprensenting the context field's physical storage and the
|
||||||
|
/// properties of the field itself, prior to the final ContextField being allocated.
|
||||||
struct FieldContext {
|
struct FieldContext {
|
||||||
VarnodeSymbol *sym;
|
VarnodeSymbol *sym; ///< The concrete Varnode representing physical storage for the field
|
||||||
FieldQuality *qual;
|
FieldQuality *qual; ///< Qualities of the field, as parsed
|
||||||
bool operator<(const FieldContext &op2) const;
|
bool operator<(const FieldContext &op2) const; ///< Sort context fields based on their least significant bit boundary
|
||||||
FieldContext(VarnodeSymbol *s,FieldQuality *q) { sym=s; qual=q; }
|
FieldContext(VarnodeSymbol *s,FieldQuality *q) { sym=s; qual=q; } ///< Constructor
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// \brief A class for expanding macro directives within a p-code section
|
||||||
|
///
|
||||||
|
/// It is handed a (partial) list of p-code op templates (OpTpl). The
|
||||||
|
/// macro directive is established with the setMacroOp() method. Then calling
|
||||||
|
/// build() expands the macro into the list of OpTpls, providing parameter
|
||||||
|
/// substitution. The class is derived from PcodeBuilder, where the dump() method,
|
||||||
|
/// instead of emitting raw p-code, clones the macro templates into the list
|
||||||
|
/// of OpTpls.
|
||||||
class MacroBuilder : public PcodeBuilder {
|
class MacroBuilder : public PcodeBuilder {
|
||||||
SleighCompile *slgh;
|
SleighCompile *slgh; ///< The SLEIGH parsing object
|
||||||
bool haserror;
|
bool haserror; ///< Set to \b true by the build() method if there was an error
|
||||||
vector<OpTpl *> &outvec;
|
vector<OpTpl *> &outvec; ///< The partial list of op templates to expand the macro into
|
||||||
vector<HandleTpl *> params;
|
vector<HandleTpl *> params; ///< List of parameters to substitute into the macro
|
||||||
bool transferOp(OpTpl *op,vector<HandleTpl *> ¶ms);
|
bool transferOp(OpTpl *op,vector<HandleTpl *> ¶ms);
|
||||||
virtual void dump( OpTpl *op );
|
virtual void dump( OpTpl *op );
|
||||||
void free(void);
|
void free(void); ///< Free resources used by the builder
|
||||||
void reportError(const Location* loc, const string &val);
|
void reportError(const Location* loc, const string &val); ///< Report error encountered expanding the macro
|
||||||
public:
|
public:
|
||||||
MacroBuilder(SleighCompile *sl,vector<OpTpl *> &ovec,uint4 lbcnt) : PcodeBuilder(lbcnt),outvec(ovec) {
|
MacroBuilder(SleighCompile *sl,vector<OpTpl *> &ovec,uint4 lbcnt) : PcodeBuilder(lbcnt),outvec(ovec) {
|
||||||
slgh = sl; haserror = false; }
|
slgh = sl; haserror = false; } ///< Constructor
|
||||||
void setMacroOp(OpTpl *macroop);
|
void setMacroOp(OpTpl *macroop); ///< Establish the MACRO directive to expand
|
||||||
bool hasError(void) const { return haserror; }
|
bool hasError(void) const { return haserror; } ///< Return \b true if there were errors during expansion
|
||||||
virtual ~MacroBuilder(void) { free(); }
|
virtual ~MacroBuilder(void) { free(); }
|
||||||
virtual void appendBuild(OpTpl *bld,int4 secnum) { dump(bld); }
|
virtual void appendBuild(OpTpl *bld,int4 secnum) { dump(bld); }
|
||||||
virtual void delaySlot(OpTpl *op) { dump(op); }
|
virtual void delaySlot(OpTpl *op) { dump(op); }
|
||||||
|
@ -170,103 +239,151 @@ public:
|
||||||
virtual void appendCrossBuild(OpTpl *bld,int4 secnum) { dump(bld); }
|
virtual void appendCrossBuild(OpTpl *bld,int4 secnum) { dump(bld); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// \brief Parsing for the semantic section of Constructors
|
||||||
|
///
|
||||||
|
/// This is just the base p-code compiler for building OpTpl and VarnodeTpl.
|
||||||
|
/// Symbols, locations, and error/warning messages are tied into to the main
|
||||||
|
/// parser.
|
||||||
class SleighPcode : public PcodeCompile {
|
class SleighPcode : public PcodeCompile {
|
||||||
SleighCompile *compiler;
|
SleighCompile *compiler; ///< The main SLEIGH parser
|
||||||
virtual uintb allocateTemp(void);
|
virtual uintb allocateTemp(void);
|
||||||
virtual const Location *getLocation(SleighSymbol *sym) const;
|
virtual const Location *getLocation(SleighSymbol *sym) const;
|
||||||
virtual void reportError(const Location* loc, const string &msg);
|
virtual void reportError(const Location* loc, const string &msg);
|
||||||
virtual void reportWarning(const Location* loc, const string &msg);
|
virtual void reportWarning(const Location* loc, const string &msg);
|
||||||
virtual void addSymbol(SleighSymbol *sym);
|
virtual void addSymbol(SleighSymbol *sym);
|
||||||
public:
|
public:
|
||||||
SleighPcode(void) : PcodeCompile() { compiler = (SleighCompile *)0; }
|
SleighPcode(void) : PcodeCompile() { compiler = (SleighCompile *)0; } ///< Constructor
|
||||||
void setCompiler(SleighCompile *comp) { compiler = comp; }
|
void setCompiler(SleighCompile *comp) { compiler = comp; } ///< Hook in the main parser
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// \brief SLEIGH specification compiling
|
||||||
|
///
|
||||||
|
/// Class for parsing SLEIGH specifications (.slaspec files) and producing the
|
||||||
|
/// \e compiled form (.sla file), which can then be loaded by a SLEIGH disassembly
|
||||||
|
/// and p-code generation engine. This full parser contains the p-code parser SleighPcode
|
||||||
|
/// within it. The main entry point is run_compilation(), which takes the input and output
|
||||||
|
/// file paths as parameters. Various options and preprocessor macros can be set using the
|
||||||
|
/// various set*() methods prior to calling run_compilation.
|
||||||
class SleighCompile : public SleighBase {
|
class SleighCompile : public SleighBase {
|
||||||
friend class SleighPcode;
|
friend class SleighPcode;
|
||||||
public:
|
public:
|
||||||
SleighPcode pcode;
|
SleighPcode pcode; ///< The p-code parsing (sub)engine
|
||||||
private:
|
private:
|
||||||
map<string,string> preproc_defines; // Defines for the preprocessor
|
map<string,string> preproc_defines; ///< Defines for the preprocessor
|
||||||
vector<FieldContext> contexttable;
|
vector<FieldContext> contexttable; ///< Context field definitions (prior to defining ContextField and ContextSymbol)
|
||||||
vector<ConstructTpl *> macrotable;
|
vector<ConstructTpl *> macrotable; ///< SLEIGH macro definitions
|
||||||
vector<Token *> tokentable;
|
vector<Token *> tokentable; ///< SLEIGH token definitions
|
||||||
vector<SubtableSymbol *> tables;
|
vector<SubtableSymbol *> tables; ///< SLEIGH subtables
|
||||||
vector<SectionSymbol *> sections;
|
vector<SectionSymbol *> sections; ///< Symbols defining Constructor sections
|
||||||
list<WithBlock> withstack;
|
list<WithBlock> withstack; ///< Current stack of \b with blocks
|
||||||
Constructor *curct; // Current constructor being defined
|
Constructor *curct; ///< Current Constructor being defined
|
||||||
MacroSymbol *curmacro; // Current macro being defined
|
MacroSymbol *curmacro; ///< Current macro being defined
|
||||||
bool contextlock; // If the context layout has been established yet
|
bool contextlock; ///< If the context layout has been established yet
|
||||||
vector<string> relpath; // Relative path (to cwd) for each filename
|
vector<string> relpath; ///< Relative path (to cwd) for each filename
|
||||||
vector<string> filename; // Stack of current files being parsed
|
vector<string> filename; ///< Stack of current files being parsed
|
||||||
vector<int4> lineno; // Current line number for each file in stack
|
vector<int4> lineno; ///< Current line number for each file in stack
|
||||||
map<Constructor *, Location> ctorLocationMap; // Map constructor to its defining parse location
|
map<Constructor *, Location> ctorLocationMap; ///< Map each Constructor to its defining parse location
|
||||||
map<SleighSymbol *, Location> symbolLocationMap; // Map symbol to its defining parse location
|
map<SleighSymbol *, Location> symbolLocationMap; ///< Map each symbol to its defining parse location
|
||||||
int4 userop_count; // Number of userops defined
|
int4 userop_count; ///< Number of userops defined
|
||||||
bool warnunnecessarypcode; // True if we warn of unnecessary ZEXT or SEXT
|
bool warnunnecessarypcode; ///< \b true if we warn of unnecessary ZEXT or SEXT
|
||||||
bool warndeadtemps; // True if we warn of temporaries that are written but not read
|
bool warndeadtemps; ///< \b true if we warn of temporaries that are written but not read
|
||||||
bool lenientconflicterrors; // True if we ignore most pattern conflict errors
|
bool lenientconflicterrors; ///< \b true if we ignore most pattern conflict errors
|
||||||
bool largetemporarywarning; // True if we warn about temporaries larger than SleighBase::MAX_UNIQUE_SIZE
|
bool largetemporarywarning; ///< \b true if we warn about temporaries larger than SleighBase::MAX_UNIQUE_SIZE
|
||||||
bool warnalllocalcollisions; // True if local export collisions generate individual warnings
|
bool warnalllocalcollisions; ///< \b true if local export collisions generate individual warnings
|
||||||
bool warnallnops; // True if pcode NOPs generate individual warnings
|
bool warnallnops; ///< \b true if pcode NOPs generate individual warnings
|
||||||
vector<string> noplist; // List of individual NOP warnings
|
bool failinsensitivedups; ///< \b true if case insensitive register duplicates cause error
|
||||||
mutable Location currentLocCache; // Location for (last) request of current location
|
vector<string> noplist; ///< List of individual NOP warnings
|
||||||
int4 errors;
|
mutable Location currentLocCache; ///< Location for (last) request of current location
|
||||||
|
int4 errors; ///< Number of fatal errors encountered
|
||||||
|
|
||||||
const Location* getCurrentLocation(void) const;
|
const Location* getCurrentLocation(void) const; ///< Get the current file and line number being parsed
|
||||||
void predefinedSymbols(void);
|
void predefinedSymbols(void); ///< Get SLEIGHs predefined address spaces and symbols
|
||||||
int4 calcContextVarLayout(int4 start,int4 sz,int4 numbits);
|
int4 calcContextVarLayout(int4 start,int4 sz,int4 numbits);
|
||||||
void buildDecisionTrees(void);
|
void buildDecisionTrees(void); ///< Build decision trees for all subtables
|
||||||
void buildPatterns(void);
|
void buildPatterns(void); ///< Generate final match patterns based on parse constraint equations
|
||||||
void checkConsistency(void);
|
void checkConsistency(void); ///< Perform final consistency checks on the SLEIGH definitions
|
||||||
static int4 findCollision(map<uintb,int4> &local2Operand,const vector<uintb> &locals,int operand);
|
static int4 findCollision(map<uintb,int4> &local2Operand,const vector<uintb> &locals,int operand);
|
||||||
bool checkLocalExports(Constructor *ct);
|
bool checkLocalExports(Constructor *ct); ///< Check for operands that \e might export the same local variable
|
||||||
void checkLocalCollisions(void);
|
void checkLocalCollisions(void); ///< Check all Constructors for local export collisions between operands
|
||||||
void checkNops(void);
|
void checkNops(void); ///< Report on all Constructors with empty semantic sections
|
||||||
string checkSymbols(SymbolScope *scope);
|
void checkCaseSensitivity(void); ///< Check that register names can be treated as case insensitive
|
||||||
void addSymbol(SleighSymbol *sym);
|
string checkSymbols(SymbolScope *scope); ///< Make sure label symbols are both defined and used
|
||||||
SleighSymbol *dedupSymbolList(vector<SleighSymbol *> *symlist);
|
void addSymbol(SleighSymbol *sym); ///< Add a new symbol to the current scope
|
||||||
bool expandMacros(ConstructTpl *ctpl,const vector<ConstructTpl *> ¯otable);
|
SleighSymbol *dedupSymbolList(vector<SleighSymbol *> *symlist); ///< Deduplicate the given list of symbols
|
||||||
bool finalizeSections(Constructor *big,SectionVector *vec);
|
bool expandMacros(ConstructTpl *ctpl); ///< Expand any formal SLEIGH macros in the given section of p-code
|
||||||
|
|
||||||
|
bool finalizeSections(Constructor *big,SectionVector *vec); ///< Do final checks, expansions, and linking for p-code sections
|
||||||
|
static VarnodeTpl *findSize(const ConstTpl &offset,const ConstructTpl *ct);
|
||||||
|
static bool forceExportSize(ConstructTpl *ct);
|
||||||
static void shiftUniqueVn(VarnodeTpl *vn,int4 sa);
|
static void shiftUniqueVn(VarnodeTpl *vn,int4 sa);
|
||||||
static void shiftUniqueOp(OpTpl *op,int4 sa);
|
static void shiftUniqueOp(OpTpl *op,int4 sa);
|
||||||
static void shiftUniqueHandle(HandleTpl *hand,int4 sa);
|
static void shiftUniqueHandle(HandleTpl *hand,int4 sa);
|
||||||
static void shiftUniqueConstruct(ConstructTpl *tpl,int4 sa);
|
static void shiftUniqueConstruct(ConstructTpl *tpl,int4 sa);
|
||||||
void checkUniqueAllocation(void);
|
static string formatStatusMessage(const Location* loc, const string &msg);
|
||||||
|
void checkUniqueAllocation(void); ///< Modify temporary Varnode offsets to support \b crossbuilds
|
||||||
|
void process(void); ///< Do all post processing on the parsed data structures
|
||||||
public:
|
public:
|
||||||
SleighCompile(void);
|
SleighCompile(void); ///< Constructor
|
||||||
const Location *getLocation(Constructor* ctor) const;
|
const Location *getLocation(Constructor* ctor) const; ///< Get the source location of the given Constructor's definition
|
||||||
const Location *getLocation(SleighSymbol *sym) const;
|
const Location *getLocation(SleighSymbol *sym) const; ///< Get the source location of the given symbol's definition
|
||||||
string formatStatusMessage(const Location* loc, const string &msg);
|
void reportError(const string &msg); ///< Issue a fatal error message
|
||||||
void reportError(const string &msg);
|
void reportError(const Location *loc, const string &msg); ///< Issue a fatal error message with a source location
|
||||||
void reportError(const Location *loc, const string &msg);
|
void reportWarning(const string &msg); ///< Issue a warning message
|
||||||
void reportWarning(const string &msg);
|
void reportWarning(const Location *loc, const string &msg); ///< Issue a warning message with a source location
|
||||||
void reportWarning(const Location *loc, const string &msg);
|
int4 numErrors(void) const { return errors; } ///< Return the current number of fatal errors
|
||||||
int4 numErrors(void) const { return errors; }
|
|
||||||
void reportInfo(const string &msg);
|
|
||||||
void reportInfo(const Location *loc, const string &msg);
|
|
||||||
|
|
||||||
|
uintb getUniqueAddr(void); ///< Get the next available temporary register offset
|
||||||
|
|
||||||
uintb getUniqueAddr(void);
|
/// \brief Set whether unnecessary truncation and extension operators generate warnings individually
|
||||||
|
///
|
||||||
|
/// \param val is \b true if warnings are generated individually. The default is \b false.
|
||||||
void setUnnecessaryPcodeWarning(bool val) { warnunnecessarypcode = val; }
|
void setUnnecessaryPcodeWarning(bool val) { warnunnecessarypcode = val; }
|
||||||
|
|
||||||
|
/// \brief Set whether dead temporary registers generate warnings individually
|
||||||
|
///
|
||||||
|
/// \param val is \b true if warnings are generated individually. The default is \b false.
|
||||||
void setDeadTempWarning(bool val) { warndeadtemps = val; }
|
void setDeadTempWarning(bool val) { warndeadtemps = val; }
|
||||||
|
|
||||||
|
/// \brief Set whether named temporary registers must be defined using the \b local keyword.
|
||||||
|
///
|
||||||
|
/// \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); }
|
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;}
|
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.
|
||||||
void setLenientConflict(bool val) { lenientconflicterrors = val; }
|
void setLenientConflict(bool val) { lenientconflicterrors = val; }
|
||||||
|
|
||||||
|
/// \brief Set whether collisions in exported locals generate warnings individually
|
||||||
|
///
|
||||||
|
/// \param val is \b true if warnings are generated individually. The default is \b false.
|
||||||
void setLocalCollisionWarning(bool val) { warnalllocalcollisions = val; }
|
void setLocalCollisionWarning(bool val) { warnalllocalcollisions = val; }
|
||||||
|
|
||||||
|
/// \brief Set whether NOP Constructors generate warnings individually
|
||||||
|
///
|
||||||
|
/// \param val is \b true if warnings are generated individually. The default is \b false.
|
||||||
void setAllNopWarning(bool val) { warnallnops = val; }
|
void setAllNopWarning(bool val) { warnallnops = val; }
|
||||||
void process(void);
|
|
||||||
|
/// \brief Set whether case insensitive duplicates of register names cause an error
|
||||||
|
///
|
||||||
|
/// \param val is \b true is duplicates cause an error.
|
||||||
|
void setInsensitiveDuplicateError(bool val) { failinsensitivedups = val; }
|
||||||
|
|
||||||
// Lexer functions
|
// Lexer functions
|
||||||
void calcContextLayout(void);
|
void calcContextLayout(void); ///< Calculate the internal context field layout
|
||||||
string grabCurrentFilePath(void) const;
|
string grabCurrentFilePath(void) const; ///< Get the path to the current source file
|
||||||
void parseFromNewFile(const string &fname);
|
void parseFromNewFile(const string &fname); ///< Push a new source file to the current parse stack
|
||||||
void parsePreprocMacro(void);
|
void parsePreprocMacro(void); ///< Mark start of parsing for an expanded preprocessor macro
|
||||||
void parseFileFinished(void);
|
void parseFileFinished(void); ///< Mark end of parsing for the current file or macro
|
||||||
void nextLine(void) { lineno.back() += 1; }
|
void nextLine(void) { lineno.back() += 1; } ///< Indicate parsing proceeded to the next line of the current file
|
||||||
bool getPreprocValue(const string &nm,string &res) const;
|
bool getPreprocValue(const string &nm,string &res) const; ///< Retrieve a given preprocessor variable
|
||||||
void setPreprocValue(const string &nm,const string &value);
|
void setPreprocValue(const string &nm,const string &value); ///< Set a given preprocessor variable
|
||||||
bool undefinePreprocValue(const string &nm);
|
bool undefinePreprocValue(const string &nm); ///< Remove the value associated with the given preprocessor variable
|
||||||
|
|
||||||
// Parser functions
|
// Parser functions
|
||||||
TokenSymbol *defineToken(string *name,uintb *sz,int4 endian);
|
TokenSymbol *defineToken(string *name,uintb *sz,int4 endian);
|
||||||
|
@ -275,7 +392,12 @@ public:
|
||||||
void newSpace(SpaceQuality *qual);
|
void newSpace(SpaceQuality *qual);
|
||||||
SectionSymbol *newSectionSymbol(const string &nm);
|
SectionSymbol *newSectionSymbol(const string &nm);
|
||||||
void setEndian(int4 end);
|
void setEndian(int4 end);
|
||||||
|
|
||||||
|
/// \brief Set instruction alignment for the SLEIGH specification
|
||||||
|
///
|
||||||
|
/// \param val is the alignment value in bytes. 1 is the default indicating no alignment
|
||||||
void setAlignment(int4 val) { alignment = val; }
|
void setAlignment(int4 val) { alignment = val; }
|
||||||
|
|
||||||
void defineVarnodes(SpaceSymbol *spacesym,uintb *off,uintb *size,vector<string> *names);
|
void defineVarnodes(SpaceSymbol *spacesym,uintb *off,uintb *size,vector<string> *names);
|
||||||
void defineBitrange(string *name,VarnodeSymbol *sym,uint4 bitoffset,uint4 numb);
|
void defineBitrange(string *name,VarnodeSymbol *sym,uint4 bitoffset,uint4 numb);
|
||||||
void addUserOp(vector<string> *names);
|
void addUserOp(vector<string> *names);
|
||||||
|
@ -284,7 +406,6 @@ public:
|
||||||
void attachVarnodes(vector<SleighSymbol *> *symlist,vector<SleighSymbol *> *varlist);
|
void attachVarnodes(vector<SleighSymbol *> *symlist,vector<SleighSymbol *> *varlist);
|
||||||
SubtableSymbol *newTable(string *nm);
|
SubtableSymbol *newTable(string *nm);
|
||||||
void newOperand(Constructor *ct,string *nm);
|
void newOperand(Constructor *ct,string *nm);
|
||||||
VarnodeTpl *addressOf(VarnodeTpl *var,uint4 size);
|
|
||||||
PatternEquation *constrainOperand(OperandSymbol *sym,PatternExpression *patexp);
|
PatternEquation *constrainOperand(OperandSymbol *sym,PatternExpression *patexp);
|
||||||
void defineOperand(OperandSymbol *sym,PatternExpression *patexp);
|
void defineOperand(OperandSymbol *sym,PatternExpression *patexp);
|
||||||
PatternEquation *defineInvisibleOperand(TripleSymbol *sym);
|
PatternEquation *defineInvisibleOperand(TripleSymbol *sym);
|
||||||
|
@ -302,7 +423,7 @@ public:
|
||||||
SectionVector *finalNamedSection(SectionVector *vec,ConstructTpl *section);
|
SectionVector *finalNamedSection(SectionVector *vec,ConstructTpl *section);
|
||||||
vector<OpTpl *> *createCrossBuild(VarnodeTpl *addr,SectionSymbol *sym);
|
vector<OpTpl *> *createCrossBuild(VarnodeTpl *addr,SectionSymbol *sym);
|
||||||
Constructor *createConstructor(SubtableSymbol *sym);
|
Constructor *createConstructor(SubtableSymbol *sym);
|
||||||
bool isInRoot(Constructor *ct) const { return (root == ct->getParent()); }
|
bool isInRoot(Constructor *ct) const { return (root == ct->getParent()); } ///< Is the Constructor in the root table?
|
||||||
void resetConstructors(void);
|
void resetConstructors(void);
|
||||||
void pushWith(SubtableSymbol *ss,PatternEquation *pateq,vector<ContextChange *> *contvec);
|
void pushWith(SubtableSymbol *ss,PatternEquation *pateq,vector<ContextChange *> *contvec);
|
||||||
void popWith(void);
|
void popWith(void);
|
||||||
|
@ -315,7 +436,13 @@ public:
|
||||||
virtual int4 instructionLength(const Address &baseaddr) const { return 0; }
|
virtual int4 instructionLength(const Address &baseaddr) const { return 0; }
|
||||||
virtual int4 oneInstruction(PcodeEmit &emit,const Address &baseaddr) const { return 0; }
|
virtual int4 oneInstruction(PcodeEmit &emit,const Address &baseaddr) const { return 0; }
|
||||||
virtual int4 printAssembly(AssemblyEmit &emit,const Address &baseaddr) const { return 0; }
|
virtual int4 printAssembly(AssemblyEmit &emit,const Address &baseaddr) const { return 0; }
|
||||||
|
|
||||||
|
void setAllOptions(const map<string,string> &defines, bool unnecessaryPcodeWarning,
|
||||||
|
bool lenientConflict, bool allCollisionWarning,
|
||||||
|
bool allNopWarning,bool deadTempWarning,bool enforceLocalKeyWord,
|
||||||
|
bool largeTemporaryWarning, bool caseSensitiveRegisterNames);
|
||||||
|
int4 run_compilation(const string &filein,const string &fileout);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern SleighCompile *slgh;
|
extern SleighCompile *slgh; ///< A global reference to the SLEIGH compiler accessible to the parse functions
|
||||||
extern int yydebug;
|
extern int yydebug; ///< Debug state for the SLEIGH parse functions
|
||||||
|
|
|
@ -346,16 +346,6 @@ public:
|
||||||
/// \param val is \b true to allow context changes, \b false prevents changes
|
/// \param val is \b true to allow context changes, \b false prevents changes
|
||||||
virtual void allowContextSet(bool val) const {}
|
virtual void allowContextSet(bool val) const {}
|
||||||
|
|
||||||
/// \brief Add a named register to the model for this processor
|
|
||||||
///
|
|
||||||
/// \deprecated All registers used to be formally added to the
|
|
||||||
/// processor model through this method.
|
|
||||||
/// \param nm is the name of the new register
|
|
||||||
/// \param base is the address space containing the register
|
|
||||||
/// \param offset is the offset of the register
|
|
||||||
/// \param size is the number of bytes in the register
|
|
||||||
virtual void addRegister(const string &nm,AddrSpace *base,uintb offset,int4 size)=0;
|
|
||||||
|
|
||||||
/// \brief Get a register as VarnodeData given its name
|
/// \brief Get a register as VarnodeData given its name
|
||||||
///
|
///
|
||||||
/// Retrieve the location and size of a register given its name
|
/// Retrieve the location and size of a register given its name
|
||||||
|
|
|
@ -380,7 +380,7 @@ public:
|
||||||
struct TraverseNode {
|
struct TraverseNode {
|
||||||
const Varnode *vn; ///< Varnode at the point of traversal
|
const Varnode *vn; ///< Varnode at the point of traversal
|
||||||
uint4 flags; ///< Flags associated with the node
|
uint4 flags; ///< Flags associated with the node
|
||||||
TraverseNode(const Varnode *v,uint4 f) { vn = v; flags = f; }
|
TraverseNode(const Varnode *v,uint4 f) { vn = v; flags = f; } ///< Constructor
|
||||||
};
|
};
|
||||||
|
|
||||||
bool contiguous_test(Varnode *vn1,Varnode *vn2); ///< Test if Varnodes are pieces of a whole
|
bool contiguous_test(Varnode *vn1,Varnode *vn2); ///< Test if Varnodes are pieces of a whole
|
||||||
|
|
|
@ -41,7 +41,7 @@ public abstract class SleighBase extends Translate implements NamedSymbolProvide
|
||||||
public static final int SLA_FORMAT_VERSION = 3;
|
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.
|
public static final long MAX_UNIQUE_SIZE = 128; //Maximum size of a varnode in the unique space.
|
||||||
//Should match value in sleighbase.cc
|
//Should match value in sleighbase.cc
|
||||||
|
|
||||||
private VectorSTL<String> userop = new VectorSTL<>();
|
private VectorSTL<String> userop = new VectorSTL<>();
|
||||||
private address_set varnode_xref = new address_set(); // Cross-reference registers by address
|
private address_set varnode_xref = new address_set(); // Cross-reference registers by address
|
||||||
|
@ -127,12 +127,6 @@ public abstract class SleighBase extends Translate implements NamedSymbolProvide
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addRegister(String nm, AddrSpace base, long offset, int size) {
|
|
||||||
VarnodeSymbol sym = new VarnodeSymbol(null, nm, base, offset, size);
|
|
||||||
symtab.addSymbol(sym);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public VarnodeData getRegister(String nm) {
|
public VarnodeData getRegister(String nm) {
|
||||||
VarnodeSymbol sym = (VarnodeSymbol) findSymbol(nm);
|
VarnodeSymbol sym = (VarnodeSymbol) findSymbol(nm);
|
||||||
|
|
|
@ -29,24 +29,22 @@ import ghidra.pcodeCPort.space.AddrSpace;
|
||||||
|
|
||||||
class ConsistencyChecker {
|
class ConsistencyChecker {
|
||||||
|
|
||||||
int unnecessarypcode;
|
private int unnecessarypcode;
|
||||||
int readnowrite;
|
private int readnowrite;
|
||||||
int writenoread;
|
private int writenoread;
|
||||||
// number of constructors using a temporary varnode larger than SleighBase.MAX_UNIQUE_SIZE
|
|
||||||
int largetemp;
|
private int largetemp; // number of constructors using a temporary varnode larger than SleighBase.MAX_UNIQUE_SIZE
|
||||||
boolean printextwarning;
|
private boolean printextwarning;
|
||||||
boolean printdeadwarning;
|
private boolean printdeadwarning;
|
||||||
//if true, print information about constructors using temporary varnodes larger than SleighBase.MAX_UNIQUE_SIZE
|
private boolean printlargetempwarning; // if true, warning about temporary varnodes larger than SleighBase.MAX_UNIQUE_SIZE
|
||||||
boolean printlargetempwarning;
|
private SleighCompile compiler;
|
||||||
SleighCompile compiler;
|
private SubtableSymbol root_symbol;
|
||||||
SubtableSymbol root_symbol;
|
private VectorSTL<SubtableSymbol> postorder = new VectorSTL<>();
|
||||||
VectorSTL<SubtableSymbol> postorder = new VectorSTL<>();
|
|
||||||
|
|
||||||
// Sizes associated with tables
|
// Sizes associated with tables
|
||||||
MapSTL<SubtableSymbol, Integer> sizemap =
|
private MapSTL<SubtableSymbol, Integer> sizemap = new MapSTL<>((s1, s2) -> s1.compareTo(s2));
|
||||||
new MapSTL<>((s1, s2) -> s1.compareTo(s2));
|
|
||||||
|
|
||||||
OperandSymbol getOperandSymbol(int slot, OpTpl op, Constructor ct) {
|
private OperandSymbol getOperandSymbol(int slot, OpTpl op, Constructor ct) {
|
||||||
VarnodeTpl vn;
|
VarnodeTpl vn;
|
||||||
OperandSymbol opsym = null;
|
OperandSymbol opsym = null;
|
||||||
int handindex;
|
int handindex;
|
||||||
|
@ -69,9 +67,8 @@ class ConsistencyChecker {
|
||||||
return opsym;
|
return opsym;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean sizeRestriction(OpTpl op, Constructor ct)
|
private boolean sizeRestriction(OpTpl op, Constructor ct) {
|
||||||
|
// Make sure op template meets size restrictions
|
||||||
{ // Make sure op template meets size restrictions
|
|
||||||
// Return false and any info about mismatched sizes
|
// Return false and any info about mismatched sizes
|
||||||
int vnout, vn0, vn1;
|
int vnout, vn0, vn1;
|
||||||
AddrSpace spc;
|
AddrSpace spc;
|
||||||
|
@ -103,7 +100,7 @@ class ConsistencyChecker {
|
||||||
return true;
|
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());
|
op.getIn(0).getSize() + " != " + op.getOut().getSize());
|
||||||
return false;
|
return false;
|
||||||
case CPUI_INT_ADD:
|
case CPUI_INT_ADD:
|
||||||
case CPUI_INT_SUB:
|
case CPUI_INT_SUB:
|
||||||
|
@ -240,8 +237,8 @@ class ConsistencyChecker {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
// The shift amount does not necessarily have to be the same size
|
// The shift amount does not necessarily have to be the same size
|
||||||
// But the output and first parameter must be same size
|
// But the output and first parameter must be same size
|
||||||
case CPUI_INT_LEFT:
|
case CPUI_INT_LEFT:
|
||||||
case CPUI_INT_RIGHT:
|
case CPUI_INT_RIGHT:
|
||||||
case CPUI_INT_SRIGHT:
|
case CPUI_INT_SRIGHT:
|
||||||
|
@ -284,7 +281,7 @@ class ConsistencyChecker {
|
||||||
}
|
}
|
||||||
else if (vnout < vn0) {
|
else if (vnout < vn0) {
|
||||||
printOpError(op, ct, -1, 0,
|
printOpError(op, ct, -1, 0,
|
||||||
"Output size must be strictly bigger than input size");
|
"Output size must be strictly bigger than input size");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -349,7 +346,7 @@ class ConsistencyChecker {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
String getOpName(OpTpl op) {
|
private String getOpName(OpTpl op) {
|
||||||
switch (op.getOpcode()) {
|
switch (op.getOpcode()) {
|
||||||
case CPUI_COPY:
|
case CPUI_COPY:
|
||||||
return "Copy(=)";
|
return "Copy(=)";
|
||||||
|
@ -484,7 +481,7 @@ class ConsistencyChecker {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void printOpError(OpTpl op, Constructor ct, int err1, int err2, String message) {
|
private void printOpError(OpTpl op, Constructor ct, int err1, int err2, String message) {
|
||||||
SubtableSymbol sym = ct.getParent();
|
SubtableSymbol sym = ct.getParent();
|
||||||
OperandSymbol op1, op2;
|
OperandSymbol op1, op2;
|
||||||
|
|
||||||
|
@ -498,10 +495,10 @@ class ConsistencyChecker {
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
sb.append("Size restriction error in table '")
|
sb.append("Size restriction error in table '")
|
||||||
.append(sym.getName())
|
.append(sym.getName())
|
||||||
.append("' in constructor at ").append(ct.location)
|
.append("' in constructor at ")
|
||||||
.append("\n");
|
.append(ct.location)
|
||||||
|
.append("\n");
|
||||||
|
|
||||||
sb.append(" Problem");
|
sb.append(" Problem");
|
||||||
if ((op1 != null) && (op2 != null)) {
|
if ((op1 != null) && (op2 != null)) {
|
||||||
|
@ -521,7 +518,7 @@ class ConsistencyChecker {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int recoverSize(ConstTpl sizeconst, Constructor ct) {
|
private int recoverSize(ConstTpl sizeconst, Constructor ct) {
|
||||||
int size = 0, handindex;
|
int size = 0, handindex;
|
||||||
OperandSymbol opsym;
|
OperandSymbol opsym;
|
||||||
SubtableSymbol tabsym;
|
SubtableSymbol tabsym;
|
||||||
|
@ -572,7 +569,7 @@ class ConsistencyChecker {
|
||||||
"\" (or did you mean to use signed comparison?)", ct);
|
"\" (or did you mean to use signed comparison?)", ct);
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean checkOpMisuse(OpTpl op, Constructor ct) {
|
private boolean checkOpMisuse(OpTpl op, Constructor ct) {
|
||||||
switch (op.getOpcode()) {
|
switch (op.getOpcode()) {
|
||||||
case CPUI_INT_LESS: {
|
case CPUI_INT_LESS: {
|
||||||
VarnodeTpl vn0 = op.getIn(0);
|
VarnodeTpl vn0 = op.getIn(0);
|
||||||
|
@ -594,7 +591,7 @@ class ConsistencyChecker {
|
||||||
handleBetter("!= 0", ct);
|
handleBetter("!= 0", ct);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CPUI_INT_LESSEQUAL: {
|
case CPUI_INT_LESSEQUAL: {
|
||||||
VarnodeTpl vn0 = op.getIn(0);
|
VarnodeTpl vn0 = op.getIn(0);
|
||||||
VarnodeTpl vn1 = op.getIn(1);
|
VarnodeTpl vn1 = op.getIn(1);
|
||||||
|
@ -615,14 +612,14 @@ class ConsistencyChecker {
|
||||||
handleBetter("== 0", ct);
|
handleBetter("== 0", ct);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean checkConstructorSection(Constructor ct, ConstructTpl cttpl) {
|
private boolean checkConstructorSection(Constructor ct, ConstructTpl cttpl) {
|
||||||
// Check all the OpTpl s within the given section for consistency, return true if all tests pass
|
// Check all the OpTpl s within the given section for consistency, return true if all tests pass
|
||||||
if (cttpl == null) {
|
if (cttpl == null) {
|
||||||
return true; // Nothing to check
|
return true; // Nothing to check
|
||||||
|
@ -649,7 +646,7 @@ class ConsistencyChecker {
|
||||||
* @param opTpl the op to check
|
* @param opTpl the op to check
|
||||||
* @return true if {@code opTpl} uses a large temporary varnode
|
* @return true if {@code opTpl} uses a large temporary varnode
|
||||||
*/
|
*/
|
||||||
boolean hasLargeTemporary(OpTpl opTpl) {
|
private boolean hasLargeTemporary(OpTpl opTpl) {
|
||||||
VarnodeTpl out = opTpl.getOut();
|
VarnodeTpl out = opTpl.getOut();
|
||||||
if (out != null && isTemporaryAndTooBig(out)) {
|
if (out != null && isTemporaryAndTooBig(out)) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -659,7 +656,7 @@ class ConsistencyChecker {
|
||||||
if (isTemporaryAndTooBig(in)) {
|
if (isTemporaryAndTooBig(in)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -669,12 +666,12 @@ class ConsistencyChecker {
|
||||||
* @param vn varnode template to check
|
* @param vn varnode template to check
|
||||||
* @return true if it uses a large temporary
|
* @return true if it uses a large temporary
|
||||||
*/
|
*/
|
||||||
boolean isTemporaryAndTooBig(VarnodeTpl vn) {
|
private boolean isTemporaryAndTooBig(VarnodeTpl vn) {
|
||||||
return vn.getSpace().isUniqueSpace() &&
|
return vn.getSpace().isUniqueSpace() && vn.getSize().getReal() > SleighBase.MAX_UNIQUE_SIZE;
|
||||||
vn.getSize().getReal() > SleighBase.MAX_UNIQUE_SIZE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean checkVarnodeTruncation(Constructor ct,int slot,OpTpl op,VarnodeTpl vn,boolean isbigendian) {
|
private boolean checkVarnodeTruncation(Constructor ct, int slot, OpTpl op, VarnodeTpl vn,
|
||||||
|
boolean isbigendian) {
|
||||||
ConstTpl off = vn.getOffset();
|
ConstTpl off = vn.getOffset();
|
||||||
if (off.getType() != const_type.handle) {
|
if (off.getType() != const_type.handle) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -683,24 +680,25 @@ class ConsistencyChecker {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
const_type sztype = vn.getSize().getType();
|
const_type sztype = vn.getSize().getType();
|
||||||
if ((sztype != const_type.real)&&(sztype != const_type.handle)){
|
if ((sztype != const_type.real) && (sztype != const_type.handle)) {
|
||||||
printOpError(op,ct,slot,slot,"Bad truncation expression");
|
printOpError(op, ct, slot, slot, "Bad truncation expression");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
int sz = recoverSize(off,ct); // Recover the size of the original operand
|
int sz = recoverSize(off, ct); // Recover the size of the original operand
|
||||||
if (sz <= 0) {
|
if (sz <= 0) {
|
||||||
printOpError(op,ct,slot,slot,"Could not recover size");
|
printOpError(op, ct, slot, slot, "Could not recover size");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
boolean res = vn.adjustTruncation(sz, isbigendian);
|
boolean res = vn.adjustTruncation(sz, isbigendian);
|
||||||
if (!res) {
|
if (!res) {
|
||||||
printOpError(op,ct,slot,slot,"Truncation operator out of bounds");
|
printOpError(op, ct, slot, slot, "Truncation operator out of bounds");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean checkSectionTruncations(Constructor ct,ConstructTpl cttpl,boolean isbigendian) {
|
private boolean checkSectionTruncations(Constructor ct, ConstructTpl cttpl,
|
||||||
|
boolean isbigendian) {
|
||||||
// Check all the varnodes that have an offset_plus template
|
// Check all the varnodes that have an offset_plus template
|
||||||
// adjust the plus if we are big endian
|
// adjust the plus if we are big endian
|
||||||
// make sure the truncation is valid
|
// make sure the truncation is valid
|
||||||
|
@ -709,16 +707,16 @@ class ConsistencyChecker {
|
||||||
Iterator<OpTpl> iter;
|
Iterator<OpTpl> iter;
|
||||||
|
|
||||||
iter = ops.iterator();
|
iter = ops.iterator();
|
||||||
while(iter.hasNext()) {
|
while (iter.hasNext()) {
|
||||||
OpTpl op = iter.next();
|
OpTpl op = iter.next();
|
||||||
VarnodeTpl outvn = op.getOut();
|
VarnodeTpl outvn = op.getOut();
|
||||||
if (outvn != null) {
|
if (outvn != null) {
|
||||||
if (!checkVarnodeTruncation(ct,-1,op,outvn,isbigendian)) {
|
if (!checkVarnodeTruncation(ct, -1, op, outvn, isbigendian)) {
|
||||||
testresult = false;
|
testresult = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for(int i=0;i<op.numInput();++i) {
|
for (int i = 0; i < op.numInput(); ++i) {
|
||||||
if (!checkVarnodeTruncation(ct,i,op,op.getIn(i),isbigendian)) {
|
if (!checkVarnodeTruncation(ct, i, op, op.getIn(i), isbigendian)) {
|
||||||
testresult = false;
|
testresult = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -726,7 +724,7 @@ class ConsistencyChecker {
|
||||||
return testresult;
|
return testresult;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean checkSubtable(SubtableSymbol sym) {
|
private boolean checkSubtable(SubtableSymbol sym) {
|
||||||
int tablesize = 0;
|
int tablesize = 0;
|
||||||
int numconstruct = sym.getNumConstructors();
|
int numconstruct = sym.getNumConstructors();
|
||||||
Constructor ct;
|
Constructor ct;
|
||||||
|
@ -796,7 +794,7 @@ class ConsistencyChecker {
|
||||||
|
|
||||||
// Deal with detected extension (SEXT or ZEXT) where the
|
// Deal with detected extension (SEXT or ZEXT) where the
|
||||||
// input size is the same as the output size
|
// input size is the same as the output size
|
||||||
void dealWithUnnecessaryExt(OpTpl op, Constructor ct) {
|
private void dealWithUnnecessaryExt(OpTpl op, Constructor ct) {
|
||||||
if (printextwarning) {
|
if (printextwarning) {
|
||||||
compiler.reportWarning(op.location, "Unnecessary '" + getOpName(op) + "'");
|
compiler.reportWarning(op.location, "Unnecessary '" + getOpName(op) + "'");
|
||||||
}
|
}
|
||||||
|
@ -804,7 +802,7 @@ class ConsistencyChecker {
|
||||||
unnecessarypcode += 1;
|
unnecessarypcode += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dealWithUnnecessaryTrunc(OpTpl op, Constructor ct) {
|
private void dealWithUnnecessaryTrunc(OpTpl op, Constructor ct) {
|
||||||
if (printextwarning) {
|
if (printextwarning) {
|
||||||
compiler.reportWarning(op.location, "Unnecessary '" + getOpName(op) + "'");
|
compiler.reportWarning(op.location, "Unnecessary '" + getOpName(op) + "'");
|
||||||
}
|
}
|
||||||
|
@ -814,7 +812,7 @@ class ConsistencyChecker {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Establish table ordering
|
// Establish table ordering
|
||||||
void setPostOrder(SubtableSymbol root) {
|
private void setPostOrder(SubtableSymbol root) {
|
||||||
postorder.clear();
|
postorder.clear();
|
||||||
sizemap.clear();
|
sizemap.clear();
|
||||||
|
|
||||||
|
@ -869,8 +867,8 @@ class ConsistencyChecker {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Optimization routines
|
// Optimization routines
|
||||||
static void examineVn(MapSTL<Long, OptimizeRecord> recs, VarnodeTpl vn, int i, int inslot,
|
private static void examineVn(MapSTL<Long, OptimizeRecord> recs, VarnodeTpl vn, int i,
|
||||||
int secnum) {
|
int inslot, int secnum) {
|
||||||
if (vn == null) {
|
if (vn == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -900,7 +898,7 @@ class ConsistencyChecker {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean possibleIntersection(VarnodeTpl vn1, VarnodeTpl vn2) {
|
private static boolean possibleIntersection(VarnodeTpl vn1, VarnodeTpl vn2) {
|
||||||
// Conservatively test whether vn1 and vn2 can intersect
|
// Conservatively test whether vn1 and vn2 can intersect
|
||||||
if (vn1.getSpace().isConstSpace()) {
|
if (vn1.getSpace().isConstSpace()) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -958,7 +956,7 @@ class ConsistencyChecker {
|
||||||
// This is extremely conservative. Basically any op where
|
// This is extremely conservative. Basically any op where
|
||||||
// we can't see exactly what might be written is considered
|
// we can't see exactly what might be written is considered
|
||||||
// interference
|
// interference
|
||||||
boolean readWriteInterference(VarnodeTpl vn, OpTpl op, boolean checkread) {
|
private boolean readWriteInterference(VarnodeTpl vn, OpTpl op, boolean checkread) {
|
||||||
switch (op.getOpcode()) {
|
switch (op.getOpcode()) {
|
||||||
case CPUI_MULTIEQUAL:
|
case CPUI_MULTIEQUAL:
|
||||||
case CPUI_PTRSUB:
|
case CPUI_PTRSUB:
|
||||||
|
@ -999,7 +997,7 @@ class ConsistencyChecker {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Look for reads and writes to temporaries
|
// Look for reads and writes to temporaries
|
||||||
void optimizeGather1(Constructor ct, MapSTL<Long, OptimizeRecord> recs, int secnum) {
|
private void optimizeGather1(Constructor ct, MapSTL<Long, OptimizeRecord> recs, int secnum) {
|
||||||
ConstructTpl tpl;
|
ConstructTpl tpl;
|
||||||
if (secnum < 0) {
|
if (secnum < 0) {
|
||||||
tpl = ct.getTempl();
|
tpl = ct.getTempl();
|
||||||
|
@ -1023,7 +1021,7 @@ class ConsistencyChecker {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure any temp used by the export is not optimized away
|
// Make sure any temp used by the export is not optimized away
|
||||||
void optimizeGather2(Constructor ct, MapSTL<Long, OptimizeRecord> recs, int secnum) {
|
private void optimizeGather2(Constructor ct, MapSTL<Long, OptimizeRecord> recs, int secnum) {
|
||||||
ConstructTpl tpl;
|
ConstructTpl tpl;
|
||||||
if (secnum < 0) {
|
if (secnum < 0) {
|
||||||
tpl = ct.getTempl();
|
tpl = ct.getTempl();
|
||||||
|
@ -1053,7 +1051,7 @@ class ConsistencyChecker {
|
||||||
}
|
}
|
||||||
if (hand.getSpace().isUniqueSpace()) {
|
if (hand.getSpace().isUniqueSpace()) {
|
||||||
if ((hand.getPtrSpace().getType() == ConstTpl.const_type.real) &&
|
if ((hand.getPtrSpace().getType() == ConstTpl.const_type.real) &&
|
||||||
(hand.getPtrOffset().getType() == ConstTpl.const_type.real)) {
|
(hand.getPtrOffset().getType() == ConstTpl.const_type.real)) {
|
||||||
long offset = hand.getPtrOffset().getReal();
|
long offset = hand.getPtrOffset().getReal();
|
||||||
recs.put(offset, new OptimizeRecord());
|
recs.put(offset, new OptimizeRecord());
|
||||||
IteratorSTL<Pair<Long, OptimizeRecord>> res = recs.find(offset);
|
IteratorSTL<Pair<Long, OptimizeRecord>> res = recs.find(offset);
|
||||||
|
@ -1067,7 +1065,7 @@ class ConsistencyChecker {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
OptimizeRecord findValidRule(Constructor ct, MapSTL<Long, OptimizeRecord> recs) {
|
private OptimizeRecord findValidRule(Constructor ct, MapSTL<Long, OptimizeRecord> recs) {
|
||||||
IteratorSTL<Pair<Long, OptimizeRecord>> iter;
|
IteratorSTL<Pair<Long, OptimizeRecord>> iter;
|
||||||
iter = recs.begin();
|
iter = recs.begin();
|
||||||
while (!iter.isEnd()) {
|
while (!iter.isEnd()) {
|
||||||
|
@ -1075,7 +1073,7 @@ class ConsistencyChecker {
|
||||||
iter.increment();
|
iter.increment();
|
||||||
|
|
||||||
if ((currec.writecount == 1) && (currec.readcount == 1) &&
|
if ((currec.writecount == 1) && (currec.readcount == 1) &&
|
||||||
(currec.readsection == currec.writesection)) {
|
(currec.readsection == currec.writesection)) {
|
||||||
// Temporary must be read and written exactly once
|
// Temporary must be read and written exactly once
|
||||||
ConstructTpl tpl;
|
ConstructTpl tpl;
|
||||||
if (currec.readsection < 0) {
|
if (currec.readsection < 0) {
|
||||||
|
@ -1123,7 +1121,7 @@ class ConsistencyChecker {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
void applyOptimization(Constructor ct, OptimizeRecord rec) {
|
private void applyOptimization(Constructor ct, OptimizeRecord rec) {
|
||||||
VectorSTL<Integer> deleteops = new VectorSTL<>();
|
VectorSTL<Integer> deleteops = new VectorSTL<>();
|
||||||
ConstructTpl ctempl;
|
ConstructTpl ctempl;
|
||||||
if (rec.readsection < 0) {
|
if (rec.readsection < 0) {
|
||||||
|
@ -1150,7 +1148,7 @@ class ConsistencyChecker {
|
||||||
ctempl.deleteOps(deleteops);
|
ctempl.deleteOps(deleteops);
|
||||||
}
|
}
|
||||||
|
|
||||||
void checkUnusedTemps(Constructor ct, MapSTL<Long, OptimizeRecord> recs) {
|
private void checkUnusedTemps(Constructor ct, MapSTL<Long, OptimizeRecord> recs) {
|
||||||
IteratorSTL<Pair<Long, OptimizeRecord>> iter = recs.begin();
|
IteratorSTL<Pair<Long, OptimizeRecord>> iter = recs.begin();
|
||||||
while (!iter.isEnd()) {
|
while (!iter.isEnd()) {
|
||||||
Pair<Long, OptimizeRecord> pair = iter.get();
|
Pair<Long, OptimizeRecord> pair = iter.get();
|
||||||
|
@ -1168,30 +1166,29 @@ class ConsistencyChecker {
|
||||||
iter.increment();
|
iter.increment();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks {@code ct} to see whether it contains an {@link OpTpl} which
|
* Checks {@code ct} to see whether p-code section contains an {@link OpTpl} which
|
||||||
* uses a varnode in the unique space which is larger than {@link SleighBase#MAX_UNIQUE_SIZE}.
|
* uses a varnode in the unique space which is larger than {@link SleighBase#MAX_UNIQUE_SIZE}.
|
||||||
* @param ct constructor to check
|
* @param ct constructor to check
|
||||||
|
* @param ctpl is the specific p-code section
|
||||||
*/
|
*/
|
||||||
void checkLargeTemporaries(Constructor ct) {
|
private void checkLargeTemporaries(Constructor ct, ConstructTpl ctpl) {
|
||||||
ConstructTpl ctTpl = ct.getTempl();
|
VectorSTL<OpTpl> ops = ctpl.getOpvec();
|
||||||
if (ctTpl == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
VectorSTL<OpTpl> ops = ctTpl.getOpvec();
|
|
||||||
for (IteratorSTL<OpTpl> iter = ops.begin(); !iter.isEnd(); iter.increment()) {
|
for (IteratorSTL<OpTpl> iter = ops.begin(); !iter.isEnd(); iter.increment()) {
|
||||||
if (hasLargeTemporary(iter.get())) {
|
if (hasLargeTemporary(iter.get())) {
|
||||||
if (printlargetempwarning) {
|
if (printlargetempwarning) {
|
||||||
compiler.reportWarning(ct.location, "Constructor uses temporary varnode larger than " + SleighBase.MAX_UNIQUE_SIZE + " bytes.");
|
compiler.reportWarning(ct.location,
|
||||||
}
|
"Constructor uses temporary varnode larger than " +
|
||||||
|
SleighBase.MAX_UNIQUE_SIZE + " bytes.");
|
||||||
|
}
|
||||||
largetemp++;
|
largetemp++;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void optimize(Constructor ct) {
|
private void optimize(Constructor ct) {
|
||||||
OptimizeRecord currec;
|
OptimizeRecord currec;
|
||||||
MapSTL<Long, OptimizeRecord> recs = new ComparableMapSTL<>();
|
MapSTL<Long, OptimizeRecord> recs = new ComparableMapSTL<>();
|
||||||
int numsections = ct.getNumSections();
|
int numsections = ct.getNumSections();
|
||||||
|
@ -1208,17 +1205,17 @@ class ConsistencyChecker {
|
||||||
}
|
}
|
||||||
while (currec != null);
|
while (currec != null);
|
||||||
checkUnusedTemps(ct, recs);
|
checkUnusedTemps(ct, recs);
|
||||||
checkLargeTemporaries(ct);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ConsistencyChecker(SleighCompile cp, SubtableSymbol rt, boolean unnecessary, boolean warndead, boolean warnlargetemp) {
|
public ConsistencyChecker(SleighCompile cp, SubtableSymbol rt, boolean unnecessary,
|
||||||
|
boolean warndead, boolean warnlargetemp) {
|
||||||
compiler = cp;
|
compiler = cp;
|
||||||
root_symbol = rt;
|
root_symbol = rt;
|
||||||
unnecessarypcode = 0;
|
unnecessarypcode = 0;
|
||||||
readnowrite = 0;
|
readnowrite = 0;
|
||||||
writenoread = 0;
|
writenoread = 0;
|
||||||
//number of constructors which reference a temporary varnode larger than SleighBase.MAX_UNIQUE_SIZE
|
//number of constructors which reference a temporary varnode larger than SleighBase.MAX_UNIQUE_SIZE
|
||||||
largetemp = 0;
|
largetemp = 0;
|
||||||
printextwarning = unnecessary;
|
printextwarning = unnecessary;
|
||||||
printdeadwarning = warndead;
|
printdeadwarning = warndead;
|
||||||
//whether to print information about constructors which reference large temporary varnodes
|
//whether to print information about constructors which reference large temporary varnodes
|
||||||
|
@ -1226,7 +1223,7 @@ class ConsistencyChecker {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Main entry point for size consistency check
|
// Main entry point for size consistency check
|
||||||
boolean test() {
|
public boolean testSizeRestrictions() {
|
||||||
setPostOrder(root_symbol);
|
setPostOrder(root_symbol);
|
||||||
boolean testresult = true;
|
boolean testresult = true;
|
||||||
|
|
||||||
|
@ -1239,18 +1236,19 @@ class ConsistencyChecker {
|
||||||
return testresult;
|
return testresult;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean testTruncations(boolean isbigendian) {
|
public boolean testTruncations() {
|
||||||
// Now that the sizemap is calculated, we can check/adjust the offset_plus templates
|
// Now that the sizemap is calculated, we can check/adjust the offset_plus templates
|
||||||
boolean testresult = true;
|
boolean testresult = true;
|
||||||
for(int i=0;i<postorder.size();++i) {
|
boolean isbigendian = compiler.isBigEndian();
|
||||||
|
for (int i = 0; i < postorder.size(); ++i) {
|
||||||
SubtableSymbol sym = postorder.get(i);
|
SubtableSymbol sym = postorder.get(i);
|
||||||
int numconstruct = sym.getNumConstructors();
|
int numconstruct = sym.getNumConstructors();
|
||||||
Constructor ct;
|
Constructor ct;
|
||||||
for(int j=0;j<numconstruct;++j) {
|
for (int j = 0; j < numconstruct; ++j) {
|
||||||
ct = sym.getConstructor(j);
|
ct = sym.getConstructor(j);
|
||||||
|
|
||||||
int numsections = ct.getNumSections();
|
int numsections = ct.getNumSections();
|
||||||
for(int k=-1;k<numsections;++k) {
|
for (int k = -1; k < numsections; ++k) {
|
||||||
ConstructTpl tpl;
|
ConstructTpl tpl;
|
||||||
if (k < 0) {
|
if (k < 0) {
|
||||||
tpl = ct.getTempl();
|
tpl = ct.getTempl();
|
||||||
|
@ -1261,7 +1259,7 @@ class ConsistencyChecker {
|
||||||
if (tpl == null) {
|
if (tpl == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!checkSectionTruncations(ct,tpl,isbigendian)) {
|
if (!checkSectionTruncations(ct, tpl, isbigendian)) {
|
||||||
testresult = false;
|
testresult = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1270,7 +1268,33 @@ class ConsistencyChecker {
|
||||||
return testresult;
|
return testresult;
|
||||||
}
|
}
|
||||||
|
|
||||||
void optimizeAll() {
|
public void testLargeTemporary() {
|
||||||
|
for (int i = 0; i < postorder.size(); ++i) {
|
||||||
|
SubtableSymbol sym = postorder.get(i);
|
||||||
|
int numconstruct = sym.getNumConstructors();
|
||||||
|
Constructor ct;
|
||||||
|
for (int j = 0; j < numconstruct; ++j) {
|
||||||
|
ct = sym.getConstructor(j);
|
||||||
|
|
||||||
|
int numsections = ct.getNumSections();
|
||||||
|
for (int k = -1; k < numsections; ++k) {
|
||||||
|
ConstructTpl tpl;
|
||||||
|
if (k < 0) {
|
||||||
|
tpl = ct.getTempl();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
tpl = ct.getNamedTempl(k);
|
||||||
|
}
|
||||||
|
if (tpl == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
checkLargeTemporaries(ct, tpl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void optimizeAll() {
|
||||||
for (int i = 0; i < postorder.size(); ++i) {
|
for (int i = 0; i < postorder.size(); ++i) {
|
||||||
SubtableSymbol sym = postorder.get(i);
|
SubtableSymbol sym = postorder.get(i);
|
||||||
int numconstruct = sym.getNumConstructors();
|
int numconstruct = sym.getNumConstructors();
|
||||||
|
@ -1282,24 +1306,24 @@ class ConsistencyChecker {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int getNumUnnecessaryPcode() {
|
public int getNumUnnecessaryPcode() {
|
||||||
return unnecessarypcode;
|
return unnecessarypcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
int getNumReadNoWrite() {
|
public int getNumReadNoWrite() {
|
||||||
return readnowrite;
|
return readnowrite;
|
||||||
}
|
}
|
||||||
|
|
||||||
int getNumWriteNoRead() {
|
public int getNumWriteNoRead() {
|
||||||
return writenoread;
|
return writenoread;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the number of constructors which reference a varnode in the
|
* Returns the number of constructors which reference a varnode in the
|
||||||
* unique space with size larger than {@link SleighBase#MAX_UNIQUE_SIZE}.
|
* unique space with size larger than {@link SleighBase#MAX_UNIQUE_SIZE}.
|
||||||
* @return num constructors with large temp varnodes
|
* @return num constructors with large temp varnodes
|
||||||
*/
|
*/
|
||||||
int getNumLargeTemporaries() {
|
public int getNumLargeTemporaries() {
|
||||||
return largetemp;
|
return largetemp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,14 +15,13 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.pcodeCPort.slgh_compile;
|
package ghidra.pcodeCPort.slgh_compile;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.*;
|
||||||
import java.io.PrintStream;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.regex.Matcher;
|
import java.util.Map.Entry;
|
||||||
import java.util.regex.Pattern;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.antlr.runtime.RecognitionException;
|
import org.antlr.runtime.*;
|
||||||
|
import org.antlr.runtime.tree.CommonTreeNodeStream;
|
||||||
import org.jdom.JDOMException;
|
import org.jdom.JDOMException;
|
||||||
|
|
||||||
import generic.stl.*;
|
import generic.stl.*;
|
||||||
|
@ -39,8 +38,10 @@ import ghidra.pcodeCPort.space.*;
|
||||||
import ghidra.pcodeCPort.utils.Utils;
|
import ghidra.pcodeCPort.utils.Utils;
|
||||||
import ghidra.pcodeCPort.xml.DocumentStorage;
|
import ghidra.pcodeCPort.xml.DocumentStorage;
|
||||||
import ghidra.program.model.lang.BasicCompilerSpec;
|
import ghidra.program.model.lang.BasicCompilerSpec;
|
||||||
import ghidra.sleigh.grammar.Location;
|
import ghidra.sleigh.grammar.*;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
|
import utilities.util.FileResolutionResult;
|
||||||
|
import utilities.util.FileUtilities;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <code>SleighCompile</code> provides the ability to compile Sleigh language module (e.g., *.slaspec)
|
* <code>SleighCompile</code> provides the ability to compile Sleigh language module (e.g., *.slaspec)
|
||||||
|
@ -50,7 +51,7 @@ public class SleighCompile extends SleighBase {
|
||||||
|
|
||||||
static boolean yydebug = false;
|
static boolean yydebug = false;
|
||||||
|
|
||||||
static boolean isLocationIsh(Object o) {
|
private static boolean isLocationIsh(Object o) {
|
||||||
if (o instanceof Location) {
|
if (o instanceof Location) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -225,48 +226,45 @@ public class SleighCompile extends SleighBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Defines for the preprocessor
|
// Defines for the preprocessor
|
||||||
MapSTL<String, String> preproc_defines = new MapSTL<>(new SelfComparator<String>());
|
private MapSTL<String, String> preproc_defines = new MapSTL<>(new SelfComparator<String>());
|
||||||
VectorSTL<FieldContext> contexttable = new VectorSTL<>();
|
private VectorSTL<FieldContext> contexttable = new VectorSTL<>();
|
||||||
Integer firstContextField = null;
|
private Integer firstContextField = null;
|
||||||
VectorSTL<ConstructTpl> macrotable = new VectorSTL<>();
|
private VectorSTL<ConstructTpl> macrotable = new VectorSTL<>();
|
||||||
VectorSTL<ghidra.pcodeCPort.context.Token> tokentable = new VectorSTL<>();
|
private VectorSTL<ghidra.pcodeCPort.context.Token> tokentable = new VectorSTL<>();
|
||||||
VectorSTL<SubtableSymbol> tables = new VectorSTL<>();
|
private VectorSTL<SubtableSymbol> tables = new VectorSTL<>();
|
||||||
VectorSTL<SectionSymbol> sections = new VectorSTL<>();
|
private VectorSTL<SectionSymbol> sections = new VectorSTL<>();
|
||||||
Constructor curct; // Current constructor being defined
|
private Constructor curct; // Current constructor being defined
|
||||||
MacroSymbol curmacro; // Current macro being defined
|
private MacroSymbol curmacro; // Current macro being defined
|
||||||
|
|
||||||
// If the context layout has been established yet
|
// If the context layout has been established yet
|
||||||
boolean contextlock;
|
private boolean contextlock;
|
||||||
|
|
||||||
// Stack of current files being parsed
|
// Stack of current files being parsed
|
||||||
// VectorSTL<String> filename = new VectorSTL<String>();
|
// VectorSTL<String> filename = new VectorSTL<String>();
|
||||||
String filename;
|
|
||||||
|
|
||||||
// Current line number for each file in stack
|
// Current line number for each file in stack
|
||||||
// VectorSTL<Integer> lineno = new VectorSTL<Integer>();
|
// VectorSTL<Integer> lineno = new VectorSTL<Integer>();
|
||||||
int lineno;
|
|
||||||
int linenoDifferential;
|
|
||||||
|
|
||||||
int userop_count; // Number of userops defined
|
private int userop_count; // Number of userops defined
|
||||||
|
|
||||||
boolean warnunnecessarypcode; // True if we warn of unnecessary ZEXT or SEXT
|
private boolean warnunnecessarypcode; // True if we warn of unnecessary ZEXT or SEXT
|
||||||
boolean warndeadtemps; // True if we warn of temporaries that are written but not read
|
private boolean warndeadtemps; // True if we warn of temporaries that are written but not read
|
||||||
boolean warnunusedfields; // True if fields are defined but not used
|
private boolean warnunusedfields; // True if fields are defined but not used
|
||||||
boolean enforcelocalkeyword; // Force slaspec to use 'local' keyword when defining temporary varnodes
|
private boolean lenientconflicterrors; // True if we ignore most pattern conflict errors
|
||||||
boolean lenientconflicterrors; // True if we ignore most pattern conflict errors
|
private boolean largetemporarywarning; // True if we warn about temporaries larger than SleighBase.MAX_UNIQUE_SIZE
|
||||||
boolean largetemporarywarning; // True if we warn about temporaries larger than SleighBase.MAX_UNIQUE_SIZE
|
private boolean warnalllocalcollisions; // True if local export collisions generate individual warnings
|
||||||
public boolean warnalllocalcollisions;
|
private boolean warnallnops; // True if pcode NOPs generate individual warnings
|
||||||
public boolean warnallnops;
|
private boolean failinsensitivedups; // True if case insensitive register duplicates cause error
|
||||||
public VectorSTL<String> noplist = new VectorSTL<>();
|
private VectorSTL<String> noplist = new VectorSTL<>();
|
||||||
|
|
||||||
public Deque<WithBlock> withstack = new LinkedList<>();
|
private Deque<WithBlock> withstack = new LinkedList<>();
|
||||||
|
|
||||||
int errors;
|
private int errors;
|
||||||
int warnings;
|
private int warnings;
|
||||||
|
|
||||||
// Define the "pre" defined spaces and symbols
|
// Define the "pre" defined spaces and symbols
|
||||||
// This must happen after endian has been defined
|
// This must happen after endian has been defined
|
||||||
void predefinedSymbols() {
|
private void predefinedSymbols() {
|
||||||
entry("predefinedSymbols");
|
entry("predefinedSymbols");
|
||||||
symtab.addScope(); // Create global scope
|
symtab.addScope(); // Create global scope
|
||||||
|
|
||||||
|
@ -327,14 +325,14 @@ public class SleighCompile extends SleighBase {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
SectionVector standaloneSection(ConstructTpl main) {
|
protected SectionVector standaloneSection(ConstructTpl main) {
|
||||||
entry("standaloneSection", main);
|
entry("standaloneSection", main);
|
||||||
// Create SectionVector for just the main rtl section with no named sections
|
// Create SectionVector for just the main rtl section with no named sections
|
||||||
SectionVector res = new SectionVector(main, symtab.getCurrentScope());
|
SectionVector res = new SectionVector(main, symtab.getCurrentScope());
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
SectionVector firstNamedSection(ConstructTpl main, SectionSymbol sym) {
|
protected SectionVector firstNamedSection(ConstructTpl main, SectionSymbol sym) {
|
||||||
entry("firstNamedSection", main);
|
entry("firstNamedSection", main);
|
||||||
// Start the first named p-code section after the main p-code section
|
// Start the first named p-code section after the main p-code section
|
||||||
sym.incrementDefineCount();
|
sym.incrementDefineCount();
|
||||||
|
@ -349,7 +347,8 @@ public class SleighCompile extends SleighBase {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
SectionVector nextNamedSection(SectionVector vec, ConstructTpl section, SectionSymbol sym) {
|
protected SectionVector nextNamedSection(SectionVector vec, ConstructTpl section,
|
||||||
|
SectionSymbol sym) {
|
||||||
entry("nextNamedSection", vec, section, sym);
|
entry("nextNamedSection", vec, section, sym);
|
||||||
// Add additional named p-code sections
|
// Add additional named p-code sections
|
||||||
sym.incrementDefineCount();
|
sym.incrementDefineCount();
|
||||||
|
@ -365,7 +364,7 @@ public class SleighCompile extends SleighBase {
|
||||||
return vec;
|
return vec;
|
||||||
}
|
}
|
||||||
|
|
||||||
SectionVector finalNamedSection(SectionVector vec, ConstructTpl section) {
|
protected SectionVector finalNamedSection(SectionVector vec, ConstructTpl section) {
|
||||||
entry("finalNamedSection", vec, section);
|
entry("finalNamedSection", vec, section);
|
||||||
// Fill-in final named section to match the previous SectionSymbol
|
// Fill-in final named section to match the previous SectionSymbol
|
||||||
vec.append(section, symtab.getCurrentScope());
|
vec.append(section, symtab.getCurrentScope());
|
||||||
|
@ -373,7 +372,7 @@ public class SleighCompile extends SleighBase {
|
||||||
return vec;
|
return vec;
|
||||||
}
|
}
|
||||||
|
|
||||||
int calcContextVarLayout(int start, int sz, int numbits) {
|
private int calcContextVarLayout(int start, int sz, int numbits) {
|
||||||
entry("calcContextVarLayout", start, sz, numbits);
|
entry("calcContextVarLayout", start, sz, numbits);
|
||||||
VarnodeSymbol sym = contexttable.get(start).sym;
|
VarnodeSymbol sym = contexttable.get(start).sym;
|
||||||
FieldQuality qual;
|
FieldQuality qual;
|
||||||
|
@ -390,7 +389,7 @@ public class SleighCompile extends SleighBase {
|
||||||
i = 0;
|
i = 0;
|
||||||
while (i < sz) {
|
while (i < sz) {
|
||||||
|
|
||||||
qual = contexttable.get(i).qual;
|
qual = contexttable.get(i + start).qual;
|
||||||
int min = qual.low;
|
int min = qual.low;
|
||||||
int max = qual.high;
|
int max = qual.high;
|
||||||
if (max - min > (8 * 4)) {
|
if (max - min > (8 * 4)) {
|
||||||
|
@ -409,7 +408,7 @@ public class SleighCompile extends SleighBase {
|
||||||
j = i + 1;
|
j = i + 1;
|
||||||
// Find union of fields overlapping with first field
|
// Find union of fields overlapping with first field
|
||||||
while (j < sz) {
|
while (j < sz) {
|
||||||
qual = contexttable.get(j).qual;
|
qual = contexttable.get(j + start).qual;
|
||||||
if (qual.low <= max) { // We have overlap of context variables
|
if (qual.low <= max) { // We have overlap of context variables
|
||||||
if (qual.high > max) {
|
if (qual.high > max) {
|
||||||
max = qual.high;
|
max = qual.high;
|
||||||
|
@ -434,7 +433,7 @@ public class SleighCompile extends SleighBase {
|
||||||
numbits += alloc;
|
numbits += alloc;
|
||||||
|
|
||||||
for (; i < j; ++i) {
|
for (; i < j; ++i) {
|
||||||
qual = contexttable.get(i).qual;
|
qual = contexttable.get(i + start).qual;
|
||||||
int l = qual.low - min + low;
|
int l = qual.low - min + low;
|
||||||
int h = numbits - 1 - (max - qual.high);
|
int h = numbits - 1 - (max - qual.high);
|
||||||
ContextField field = new ContextField(qual.location, qual.signext, l, h);
|
ContextField field = new ContextField(qual.location, qual.signext, l, h);
|
||||||
|
@ -450,7 +449,7 @@ public class SleighCompile extends SleighBase {
|
||||||
return numbits;
|
return numbits;
|
||||||
}
|
}
|
||||||
|
|
||||||
void buildDecisionTrees() {
|
private void buildDecisionTrees() {
|
||||||
entry("buildDecisionTrees");
|
entry("buildDecisionTrees");
|
||||||
DecisionProperties props = new DecisionProperties();
|
DecisionProperties props = new DecisionProperties();
|
||||||
root.buildDecisionTree(props);
|
root.buildDecisionTree(props);
|
||||||
|
@ -474,7 +473,7 @@ public class SleighCompile extends SleighBase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void buildPatterns() {
|
private void buildPatterns() {
|
||||||
entry("buildPatterns");
|
entry("buildPatterns");
|
||||||
if (root == null) {
|
if (root == null) {
|
||||||
reportError(null, "No patterns to match--could not find any constructors");
|
reportError(null, "No patterns to match--could not find any constructors");
|
||||||
|
@ -496,16 +495,16 @@ public class SleighCompile extends SleighBase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void checkConsistency() {
|
private void checkConsistency() {
|
||||||
entry("checkConsistency");
|
entry("checkConsistency");
|
||||||
ConsistencyChecker checker =
|
ConsistencyChecker checker = new ConsistencyChecker(this, root, warnunnecessarypcode,
|
||||||
new ConsistencyChecker(this, root, warnunnecessarypcode, warndeadtemps, largetemporarywarning);
|
warndeadtemps, largetemporarywarning);
|
||||||
|
|
||||||
if (!checker.test()) {
|
if (!checker.testSizeRestrictions()) {
|
||||||
errors += 1;
|
errors += 1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!checker.testTruncations(isBigEndian())) {
|
if (!checker.testTruncations()) {
|
||||||
errors += 1;
|
errors += 1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -524,14 +523,17 @@ public class SleighCompile extends SleighBase {
|
||||||
" operations wrote to temporaries that were not read");
|
" operations wrote to temporaries that were not read");
|
||||||
reportWarning(null, "Use -t switch to list each individually");
|
reportWarning(null, "Use -t switch to list each individually");
|
||||||
}
|
}
|
||||||
|
checker.testLargeTemporary();
|
||||||
if ((!largetemporarywarning) && checker.getNumLargeTemporaries() > 0) {
|
if ((!largetemporarywarning) && checker.getNumLargeTemporaries() > 0) {
|
||||||
reportWarning(null, checker.getNumLargeTemporaries() +
|
reportWarning(null,
|
||||||
" constructors contain temporaries larger than " + SleighBase.MAX_UNIQUE_SIZE + " bytes.");
|
checker.getNumLargeTemporaries() +
|
||||||
|
" constructors contain temporaries larger than " + SleighBase.MAX_UNIQUE_SIZE +
|
||||||
|
" bytes.");
|
||||||
reportWarning(null, "Use -o switch to list each individually.");
|
reportWarning(null, "Use -o switch to list each individually.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int findCollision(Map<Long, Integer> local2Operand, ArrayList<Long> locals,
|
private static int findCollision(Map<Long, Integer> local2Operand, ArrayList<Long> locals,
|
||||||
int operand) {
|
int operand) {
|
||||||
Integer boxOperand = Integer.valueOf(operand);
|
Integer boxOperand = Integer.valueOf(operand);
|
||||||
for (Long local : locals) {
|
for (Long local : locals) {
|
||||||
|
@ -545,7 +547,7 @@ public class SleighCompile extends SleighBase {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean checkLocalExports(Constructor ct) {
|
private boolean checkLocalExports(Constructor ct) {
|
||||||
if (ct.getTempl() == null) {
|
if (ct.getTempl() == null) {
|
||||||
return true; // No template, collisions impossible
|
return true; // No template, collisions impossible
|
||||||
}
|
}
|
||||||
|
@ -556,9 +558,9 @@ public class SleighCompile extends SleighBase {
|
||||||
return true; // Collisions can only happen with multiple operands
|
return true; // Collisions can only happen with multiple operands
|
||||||
}
|
}
|
||||||
boolean noCollisions = true;
|
boolean noCollisions = true;
|
||||||
Map<Long, Integer> collect = new TreeMap<Long, Integer>();
|
Map<Long, Integer> collect = new TreeMap<>();
|
||||||
for (int i = 0; i < ct.getNumOperands(); ++i) {
|
for (int i = 0; i < ct.getNumOperands(); ++i) {
|
||||||
ArrayList<Long> newCollect = new ArrayList<Long>();
|
ArrayList<Long> newCollect = new ArrayList<>();
|
||||||
ct.getOperand(i).collectLocalValues(newCollect);
|
ct.getOperand(i).collectLocalValues(newCollect);
|
||||||
if (newCollect.isEmpty()) {
|
if (newCollect.isEmpty()) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -578,7 +580,7 @@ public class SleighCompile extends SleighBase {
|
||||||
return noCollisions;
|
return noCollisions;
|
||||||
}
|
}
|
||||||
|
|
||||||
void checkLocalCollisions() {
|
private void checkLocalCollisions() {
|
||||||
int collisionCount = 0;
|
int collisionCount = 0;
|
||||||
SubtableSymbol sym = root; // Start with the instruction table
|
SubtableSymbol sym = root; // Start with the instruction table
|
||||||
int i = -1;
|
int i = -1;
|
||||||
|
@ -604,8 +606,53 @@ public class SleighCompile extends SleighBase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void checkNops() {
|
||||||
|
if (noplist.size() > 0) {
|
||||||
|
if (warnallnops) {
|
||||||
|
IteratorSTL<String> iter;
|
||||||
|
for (iter = noplist.begin(); !iter.isEnd(); iter.increment()) {
|
||||||
|
Msg.warn(SleighCompile.class, iter.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Msg.warn(SleighCompile.class, noplist.size() + " NOP constructors found");
|
||||||
|
if (!warnallnops) {
|
||||||
|
Msg.warn(SleighCompile.class, "Use -n switch to list each individually");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkCaseSensitivity() {
|
||||||
|
if (!failinsensitivedups) {
|
||||||
|
return; // Case insensitive duplicates don't cause error
|
||||||
|
}
|
||||||
|
HashMap<String, SleighSymbol> registerMap = new HashMap<>();
|
||||||
|
SymbolScope scope = symtab.getGlobalScope();
|
||||||
|
IteratorSTL<SleighSymbol> iter;
|
||||||
|
for (iter = scope.begin(); !iter.isEnd(); iter.increment()) {
|
||||||
|
SleighSymbol sym = iter.get();
|
||||||
|
if (!(sym instanceof VarnodeSymbol)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
VarnodeSymbol vsym = (VarnodeSymbol) sym;
|
||||||
|
AddrSpace space = vsym.getFixedVarnode().space;
|
||||||
|
if (space.getType() != spacetype.IPTR_PROCESSOR) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String nm = sym.getName().toUpperCase();
|
||||||
|
SleighSymbol oldsym = registerMap.putIfAbsent(nm, sym);
|
||||||
|
if (oldsym != null) { // Name already existed
|
||||||
|
StringBuilder buffer = new StringBuilder();
|
||||||
|
buffer.append("Name collision: ").append(sym.getName()).append(" --- ");
|
||||||
|
Location oldLocation = oldsym.getLocation();
|
||||||
|
buffer.append("Duplicate symbol ").append(oldsym.getName()).append(" defined at ");
|
||||||
|
buffer.append(oldLocation);
|
||||||
|
reportError(sym.getLocation(), buffer.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Make sure label symbols are used properly
|
// Make sure label symbols are used properly
|
||||||
String checkSymbols(SymbolScope scope) {
|
private String checkSymbols(SymbolScope scope) {
|
||||||
entry("checkSymbols", scope);
|
entry("checkSymbols", scope);
|
||||||
List<String> symbolErrors = new ArrayList<>();
|
List<String> symbolErrors = new ArrayList<>();
|
||||||
IteratorSTL<SleighSymbol> iter;
|
IteratorSTL<SleighSymbol> iter;
|
||||||
|
@ -628,7 +675,7 @@ public class SleighCompile extends SleighBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure symbol table errors are caught
|
// Make sure symbol table errors are caught
|
||||||
int addSymbol(SleighSymbol sym) {
|
protected int addSymbol(SleighSymbol sym) {
|
||||||
entry("addSymbol", sym);
|
entry("addSymbol", sym);
|
||||||
int id = -1;
|
int id = -1;
|
||||||
try {
|
try {
|
||||||
|
@ -648,7 +695,9 @@ public class SleighCompile extends SleighBase {
|
||||||
errors = 0;
|
errors = 0;
|
||||||
warnunnecessarypcode = false;
|
warnunnecessarypcode = false;
|
||||||
lenientconflicterrors = true;
|
lenientconflicterrors = true;
|
||||||
|
largetemporarywarning = false;
|
||||||
warnallnops = false;
|
warnallnops = false;
|
||||||
|
failinsensitivedups = true;
|
||||||
root = null;
|
root = null;
|
||||||
pcode.resetLabelCount();
|
pcode.resetLabelCount();
|
||||||
}
|
}
|
||||||
|
@ -689,63 +738,69 @@ public class SleighCompile extends SleighBase {
|
||||||
return warnings;
|
return warnings;
|
||||||
}
|
}
|
||||||
|
|
||||||
long getUniqueAddr() {
|
protected long getUniqueAddr() {
|
||||||
entry("getUniqueAddr");
|
entry("getUniqueAddr");
|
||||||
long base = getUniqueBase();
|
long base = getUniqueBase();
|
||||||
setUniqueBase(base + MAX_UNIQUE_SIZE);
|
setUniqueBase(base + MAX_UNIQUE_SIZE);
|
||||||
return base;
|
return base;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setUnnecessaryPcodeWarning(boolean val) {
|
public void setUnnecessaryPcodeWarning(boolean val) {
|
||||||
entry("setUnecessaryPcodeWarning", val);
|
entry("setUnecessaryPcodeWarning", val);
|
||||||
warnunnecessarypcode = val;
|
warnunnecessarypcode = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setDeadTempWarning(boolean val) {
|
public void setDeadTempWarning(boolean val) {
|
||||||
entry("setDeadTempWarning", val);
|
entry("setDeadTempWarning", val);
|
||||||
warndeadtemps = val;
|
warndeadtemps = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setUnusedFieldWarning(boolean val) {
|
public void setUnusedFieldWarning(boolean val) {
|
||||||
entry("setUnusedFieldWarning", val);
|
entry("setUnusedFieldWarning", val);
|
||||||
warnunusedfields = val;
|
warnunusedfields = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setEnforceLocalKeyWord(boolean val) {
|
public void setEnforceLocalKeyWord(boolean val) {
|
||||||
entry("setEnforceLocalKeyWord", val);
|
entry("setEnforceLocalKeyWord", val);
|
||||||
enforcelocalkeyword = val;
|
|
||||||
pcode.setEnforceLocalKey(val);
|
pcode.setEnforceLocalKey(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets whether or not to print out warning info about
|
* Sets whether or not to print out warning info about
|
||||||
* {@link Constructor}s which reference varnodes in the
|
* {@link Constructor}s which reference varnodes in the
|
||||||
* unique space larger than {@link SleighBase#MAX_UNIQUE_SIZE}.
|
* unique space larger than {@link SleighBase#MAX_UNIQUE_SIZE}.
|
||||||
* @param val whether to print info about contructors using large varnodes
|
* @param val whether to print info about contructors using large varnodes
|
||||||
*/
|
*/
|
||||||
void setLargeTemporaryWarning(boolean val) {
|
public void setLargeTemporaryWarning(boolean val) {
|
||||||
entry("setLargeTemporaryWarning",val);
|
entry("setLargeTemporaryWarning", val);
|
||||||
largetemporarywarning = val;
|
largetemporarywarning = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setLenientConflict(boolean val) {
|
public void setLenientConflict(boolean val) {
|
||||||
entry("setLenientConflict", val);
|
entry("setLenientConflict", val);
|
||||||
lenientconflicterrors = val;
|
lenientconflicterrors = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setLocalCollisionWarning(boolean val) {
|
public void setLocalCollisionWarning(boolean val) {
|
||||||
entry("setLocalCollisionWarning", val);
|
entry("setLocalCollisionWarning", val);
|
||||||
warnalllocalcollisions = val;
|
warnalllocalcollisions = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setAllNopWarning(boolean val) {
|
public void setAllNopWarning(boolean val) {
|
||||||
entry("setAllNopWarning", val);
|
entry("setAllNopWarning", val);
|
||||||
warnallnops = val;
|
warnallnops = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setInsensitiveDuplicateError(boolean val) {
|
||||||
|
entry("setInsensitiveDuplicateError", val);
|
||||||
|
failinsensitivedups = val;
|
||||||
|
}
|
||||||
|
|
||||||
// Do all post processing on the parsed data structures
|
// Do all post processing on the parsed data structures
|
||||||
public void process() {
|
private void process() {
|
||||||
entry("process");
|
entry("process");
|
||||||
|
checkNops();
|
||||||
|
checkCaseSensitivity();
|
||||||
if (getDefaultSpace() == null) {
|
if (getDefaultSpace() == null) {
|
||||||
reportError(null, "No default space specified");
|
reportError(null, "No default space specified");
|
||||||
}
|
}
|
||||||
|
@ -768,7 +823,7 @@ public class SleighCompile extends SleighBase {
|
||||||
if (errors > 0) {
|
if (errors > 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ArrayList<SleighSymbol> errorPairs = new ArrayList<SleighSymbol>();
|
ArrayList<SleighSymbol> errorPairs = new ArrayList<>();
|
||||||
buildXrefs(errorPairs); // Make sure we can build crossrefs properly
|
buildXrefs(errorPairs); // Make sure we can build crossrefs properly
|
||||||
if (!errorPairs.isEmpty()) {
|
if (!errorPairs.isEmpty()) {
|
||||||
for (int i = 0; i < errorPairs.size(); i += 2) {
|
for (int i = 0; i < errorPairs.size(); i += 2) {
|
||||||
|
@ -816,25 +871,7 @@ public class SleighCompile extends SleighBase {
|
||||||
contexttable.clear();
|
contexttable.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final Pattern PREPROCPOS = Pattern.compile("%%%(.*)\b(\\d+)%%%");
|
public Pair<Boolean, String> getPreprocValue(String nm) {
|
||||||
|
|
||||||
public void setPosition(String pos, int presumedLineno) {
|
|
||||||
Matcher m;
|
|
||||||
if ((m = PREPROCPOS.matcher(pos)).matches()) {
|
|
||||||
filename = m.group(1);
|
|
||||||
lineno = Integer.parseInt(m.group(2));
|
|
||||||
this.linenoDifferential = lineno - presumedLineno;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new RuntimeException("couldn't parse position '" + pos + "'");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setLineno(int presumedLineno) {
|
|
||||||
lineno = presumedLineno + linenoDifferential;
|
|
||||||
}
|
|
||||||
|
|
||||||
Pair<Boolean, String> getPreprocValue(String nm) {
|
|
||||||
IteratorSTL<Pair<String, String>> iter = preproc_defines.find(nm);
|
IteratorSTL<Pair<String, String>> iter = preproc_defines.find(nm);
|
||||||
if (iter.isEnd()) {
|
if (iter.isEnd()) {
|
||||||
return new Pair<>(false, null);
|
return new Pair<>(false, null);
|
||||||
|
@ -842,11 +879,11 @@ public class SleighCompile extends SleighBase {
|
||||||
return new Pair<>(true, iter.get().second);
|
return new Pair<>(true, iter.get().second);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setPreprocValue(String nm, String value) {
|
public void setPreprocValue(String nm, String value) {
|
||||||
preproc_defines.put(nm, value);
|
preproc_defines.put(nm, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean undefinePreprocValue(String nm) {
|
public boolean undefinePreprocValue(String nm) {
|
||||||
IteratorSTL<Pair<String, String>> iter = preproc_defines.find(nm);
|
IteratorSTL<Pair<String, String>> iter = preproc_defines.find(nm);
|
||||||
if (iter.isEnd()) {
|
if (iter.isEnd()) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -1281,7 +1318,7 @@ public class SleighCompile extends SleighBase {
|
||||||
|
|
||||||
// Match up any qualities of the macro's OperandSymbols with
|
// Match up any qualities of the macro's OperandSymbols with
|
||||||
// any OperandSymbol passed into the macro
|
// any OperandSymbol passed into the macro
|
||||||
void compareMacroParams(MacroSymbol sym, VectorSTL<ExprTree> param) {
|
public void compareMacroParams(MacroSymbol sym, VectorSTL<ExprTree> param) {
|
||||||
entry("compareMacroParams", sym, param);
|
entry("compareMacroParams", sym, param);
|
||||||
for (int i = 0; i < param.size(); ++i) {
|
for (int i = 0; i < param.size(); ++i) {
|
||||||
VarnodeTpl outvn = param.get(i).outvn;
|
VarnodeTpl outvn = param.get(i).outvn;
|
||||||
|
@ -1352,7 +1389,7 @@ public class SleighCompile extends SleighBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset set state after a an error in previous constructor
|
// Reset set state after a an error in previous constructor
|
||||||
void resetConstructors() {
|
protected void resetConstructors() {
|
||||||
entry("resetConstructors");
|
entry("resetConstructors");
|
||||||
symtab.setCurrentScope(symtab.getGlobalScope()); // Purge any
|
symtab.setCurrentScope(symtab.getGlobalScope()); // Purge any
|
||||||
// dangling local
|
// dangling local
|
||||||
|
@ -1361,7 +1398,7 @@ public class SleighCompile extends SleighBase {
|
||||||
|
|
||||||
// Find a defining instance of the local variable
|
// Find a defining instance of the local variable
|
||||||
// with given -offset-
|
// with given -offset-
|
||||||
private static VarnodeTpl find_size(ConstTpl offset, ConstructTpl ct) {
|
private static VarnodeTpl findSize(ConstTpl offset, ConstructTpl ct) {
|
||||||
entry("find_size", offset, ct);
|
entry("find_size", offset, ct);
|
||||||
VectorSTL<OpTpl> ops = ct.getOpvec();
|
VectorSTL<OpTpl> ops = ct.getOpvec();
|
||||||
VarnodeTpl vn;
|
VarnodeTpl vn;
|
||||||
|
@ -1386,7 +1423,7 @@ public class SleighCompile extends SleighBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Look for zero size temps in export statement
|
// Look for zero size temps in export statement
|
||||||
private static boolean force_exportsize(ConstructTpl ct) {
|
private static boolean forceExportSize(ConstructTpl ct) {
|
||||||
entry("force_exportsize", ct);
|
entry("force_exportsize", ct);
|
||||||
HandleTpl result = ct.getResult();
|
HandleTpl result = ct.getResult();
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
|
@ -1396,14 +1433,14 @@ public class SleighCompile extends SleighBase {
|
||||||
VarnodeTpl vt;
|
VarnodeTpl vt;
|
||||||
|
|
||||||
if (result.getPtrSpace().isUniqueSpace() && result.getPtrSize().isZero()) {
|
if (result.getPtrSpace().isUniqueSpace() && result.getPtrSize().isZero()) {
|
||||||
vt = find_size(result.getPtrOffset(), ct);
|
vt = findSize(result.getPtrOffset(), ct);
|
||||||
if (vt == null) {
|
if (vt == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
result.setPtrSize(vt.getSize());
|
result.setPtrSize(vt.getSize());
|
||||||
}
|
}
|
||||||
else if (result.getSpace().isUniqueSpace() && result.getSize().isZero()) {
|
else if (result.getSpace().isUniqueSpace() && result.getSize().isZero()) {
|
||||||
vt = find_size(result.getPtrOffset(), ct);
|
vt = findSize(result.getPtrOffset(), ct);
|
||||||
if (vt == null) {
|
if (vt == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1412,7 +1449,7 @@ public class SleighCompile extends SleighBase {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean expandMacros(ConstructTpl ctpl) {
|
private boolean expandMacros(ConstructTpl ctpl) {
|
||||||
VectorSTL<OpTpl> vec = ctpl.getOpvec();
|
VectorSTL<OpTpl> vec = ctpl.getOpvec();
|
||||||
VectorSTL<OpTpl> newvec = new VectorSTL<>();
|
VectorSTL<OpTpl> newvec = new VectorSTL<>();
|
||||||
IteratorSTL<OpTpl> iter;
|
IteratorSTL<OpTpl> iter;
|
||||||
|
@ -1442,7 +1479,7 @@ public class SleighCompile extends SleighBase {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean finalizeSections(Constructor big, SectionVector vec) {
|
private boolean finalizeSections(Constructor big, SectionVector vec) {
|
||||||
entry("finalizeSections", big, vec);
|
entry("finalizeSections", big, vec);
|
||||||
// Do all final checks, expansions, and linking for p-code sections
|
// Do all final checks, expansions, and linking for p-code sections
|
||||||
VectorSTL<String> myErrors = new VectorSTL<>();
|
VectorSTL<String> myErrors = new VectorSTL<>();
|
||||||
|
@ -1485,7 +1522,7 @@ public class SleighCompile extends SleighBase {
|
||||||
if (big.getParent() == root) {
|
if (big.getParent() == root) {
|
||||||
myErrors.push_back(" Cannot have export statement in root constructor");
|
myErrors.push_back(" Cannot have export statement in root constructor");
|
||||||
}
|
}
|
||||||
else if (!force_exportsize(cur.section)) {
|
else if (!forceExportSize(cur.section)) {
|
||||||
myErrors.push_back(" Size of export is unknown");
|
myErrors.push_back(" Size of export is unknown");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1523,7 +1560,7 @@ public class SleighCompile extends SleighBase {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void shiftUniqueVn(VarnodeTpl vn, int sa) {
|
private static void shiftUniqueVn(VarnodeTpl vn, int sa) {
|
||||||
entry("shiftUniqueVn", vn, sa);
|
entry("shiftUniqueVn", vn, sa);
|
||||||
// If the varnode is in the unique space, shift its offset up by -sa- bits
|
// If the varnode is in the unique space, shift its offset up by -sa- bits
|
||||||
if (vn.getSpace().isUniqueSpace() &&
|
if (vn.getSpace().isUniqueSpace() &&
|
||||||
|
@ -1534,7 +1571,7 @@ public class SleighCompile extends SleighBase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void shiftUniqueOp(OpTpl op, int sa) {
|
private static void shiftUniqueOp(OpTpl op, int sa) {
|
||||||
entry("shiftUniqueOp", op, sa);
|
entry("shiftUniqueOp", op, sa);
|
||||||
// Shift the offset up by -sa- bits for any varnode used by this -op- in the unique space
|
// Shift the offset up by -sa- bits for any varnode used by this -op- in the unique space
|
||||||
VarnodeTpl outvn = op.getOut();
|
VarnodeTpl outvn = op.getOut();
|
||||||
|
@ -1546,7 +1583,7 @@ public class SleighCompile extends SleighBase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void shiftUniqueHandle(HandleTpl hand, int sa) {
|
private static void shiftUniqueHandle(HandleTpl hand, int sa) {
|
||||||
entry("shiftUniqueHandle", hand, sa);
|
entry("shiftUniqueHandle", hand, sa);
|
||||||
// Shift the offset up by -sa- bits, for either the dynamic or static varnode aspects that are in the unique space
|
// Shift the offset up by -sa- bits, for either the dynamic or static varnode aspects that are in the unique space
|
||||||
if (hand.getSpace().isUniqueSpace() &&
|
if (hand.getSpace().isUniqueSpace() &&
|
||||||
|
@ -1571,7 +1608,7 @@ public class SleighCompile extends SleighBase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void shiftUniqueConstruct(ConstructTpl tpl, int sa) {
|
private static void shiftUniqueConstruct(ConstructTpl tpl, int sa) {
|
||||||
entry("shiftUniqueConstruct", tpl, sa);
|
entry("shiftUniqueConstruct", tpl, sa);
|
||||||
// Shift the offset up by -sa- bits, for any varnode in the unique space associated with this template
|
// Shift the offset up by -sa- bits, for any varnode in the unique space associated with this template
|
||||||
HandleTpl result = tpl.getResult();
|
HandleTpl result = tpl.getResult();
|
||||||
|
@ -1584,7 +1621,7 @@ public class SleighCompile extends SleighBase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void checkUniqueAllocation() {
|
private void checkUniqueAllocation() {
|
||||||
// With crossbuilds, temporaries may need to survive across instructions in a packet, so here we
|
// With crossbuilds, temporaries may need to survive across instructions in a packet, so here we
|
||||||
// provide space in the offset of the temporary (within the unique space) so that the run-time sleigh
|
// provide space in the offset of the temporary (within the unique space) so that the run-time sleigh
|
||||||
// engine can alter the value to prevent collisions with other nearby instructions
|
// engine can alter the value to prevent collisions with other nearby instructions
|
||||||
|
@ -1623,7 +1660,7 @@ public class SleighCompile extends SleighBase {
|
||||||
setUniqueBase(ubase);
|
setUniqueBase(ubase);
|
||||||
}
|
}
|
||||||
|
|
||||||
void checkFieldUsage() {
|
private void checkFieldUsage() {
|
||||||
if (warnunusedfields) {
|
if (warnunusedfields) {
|
||||||
VectorSTL<SleighSymbol> unsoughtSymbols = symtab.getUnsoughtSymbols();
|
VectorSTL<SleighSymbol> unsoughtSymbols = symtab.getUnsoughtSymbols();
|
||||||
IteratorSTL<SleighSymbol> siter;
|
IteratorSTL<SleighSymbol> siter;
|
||||||
|
@ -1718,6 +1755,93 @@ public class SleighCompile extends SleighBase {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
Set<Entry<String, String>> entrySet = preprocs.entrySet();
|
||||||
|
for (Entry<String, String> entry : entrySet) {
|
||||||
|
setPreprocValue(entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
|
setUnnecessaryPcodeWarning(unnecessaryPcodeWarning);
|
||||||
|
setLenientConflict(lenientConflict);
|
||||||
|
setLocalCollisionWarning(allCollisionWarning);
|
||||||
|
setAllNopWarning(allNopWarning);
|
||||||
|
setDeadTempWarning(deadTempWarning);
|
||||||
|
setUnusedFieldWarning(unusedFieldWarning);
|
||||||
|
setEnforceLocalKeyWord(enforceLocalKeyWord);
|
||||||
|
setLargeTemporaryWarning(largeTemporaryWarning);
|
||||||
|
setInsensitiveDuplicateError(!caseSensitiveRegisterNames);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int run_compilation(String filein, String fileout)
|
||||||
|
throws IOException, RecognitionException {
|
||||||
|
LineArrayListWriter writer = new LineArrayListWriter();
|
||||||
|
ParsingEnvironment env = new ParsingEnvironment(writer);
|
||||||
|
try {
|
||||||
|
final SleighCompilePreprocessorDefinitionsAdapater definitionsAdapter =
|
||||||
|
new SleighCompilePreprocessorDefinitionsAdapater(this);
|
||||||
|
final File inputFile = new File(filein);
|
||||||
|
FileResolutionResult result = FileUtilities.existsAndIsCaseDependent(inputFile);
|
||||||
|
if (!result.isOk()) {
|
||||||
|
throw new BailoutException("input file \"" + inputFile +
|
||||||
|
"\" is not properly case dependent: " + result.getMessage());
|
||||||
|
}
|
||||||
|
SleighPreprocessor sp = new SleighPreprocessor(definitionsAdapter, inputFile);
|
||||||
|
sp.process(writer);
|
||||||
|
|
||||||
|
CharStream input = new ANTLRStringStream(writer.toString());
|
||||||
|
SleighLexer lex = new SleighLexer(input);
|
||||||
|
lex.setEnv(env);
|
||||||
|
UnbufferedTokenStream tokens = new UnbufferedTokenStream(lex);
|
||||||
|
SleighParser parser = new SleighParser(tokens);
|
||||||
|
parser.setEnv(env);
|
||||||
|
parser.setLexer(lex);
|
||||||
|
SleighParser.spec_return parserRoot = parser.spec();
|
||||||
|
/*ANTLRUtil.debugTree(root.getTree(),
|
||||||
|
new PrintStream(new FileOutputStream("blargh.tree")));*/
|
||||||
|
CommonTreeNodeStream nodes = new CommonTreeNodeStream(parserRoot.getTree());
|
||||||
|
nodes.setTokenStream(tokens);
|
||||||
|
// ANTLRUtil.debugNodeStream(nodes, System.out);
|
||||||
|
SleighCompiler walker = new SleighCompiler(nodes);
|
||||||
|
|
||||||
|
int parseres = -1;
|
||||||
|
try {
|
||||||
|
parseres = walker.root(env, this); // Try to parse
|
||||||
|
}
|
||||||
|
catch (SleighError e) {
|
||||||
|
reportError(e.location, e.getMessage());
|
||||||
|
}
|
||||||
|
if (parseres == 0) {
|
||||||
|
process(); // Do all the post-processing
|
||||||
|
}
|
||||||
|
if ((parseres == 0) && (numErrors() == 0)) {
|
||||||
|
// If no errors
|
||||||
|
PrintStream s = new PrintStream(new FileOutputStream(new File(fileout)));
|
||||||
|
saveXml(s); // Dump output xml
|
||||||
|
s.close();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Msg.error(SleighCompile.class, "No output produced");
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (BailoutException e) {
|
||||||
|
Msg.error(SleighCompile.class, "Unrecoverable error(s), halting compilation", e);
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
catch (NullPointerException e) {
|
||||||
|
Msg.error(SleighCompile.class, "Unrecoverable error(s), halting compilation", e);
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
catch (PreprocessorException e) {
|
||||||
|
Msg.error(SleighCompile.class, e.getMessage());
|
||||||
|
Msg.error(SleighCompile.class, "Errors during preprocessing, halting compilation");
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Run the sleigh compiler. This provides a direct means of invoking the
|
* Run the sleigh compiler. This provides a direct means of invoking the
|
||||||
* compiler without using the launcher. The full SoftwareModeling classpath
|
* compiler without using the launcher. The full SoftwareModeling classpath
|
||||||
|
|
|
@ -17,24 +17,17 @@ package ghidra.pcodeCPort.slgh_compile;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.Map.Entry;
|
|
||||||
|
|
||||||
import org.antlr.runtime.*;
|
import org.antlr.runtime.RecognitionException;
|
||||||
import org.antlr.runtime.tree.CommonTreeNodeStream;
|
|
||||||
import org.jdom.JDOMException;
|
import org.jdom.JDOMException;
|
||||||
|
|
||||||
import generic.jar.ResourceFile;
|
import generic.jar.ResourceFile;
|
||||||
import generic.stl.IteratorSTL;
|
|
||||||
import ghidra.GhidraApplicationLayout;
|
import ghidra.GhidraApplicationLayout;
|
||||||
import ghidra.GhidraLaunchable;
|
import ghidra.GhidraLaunchable;
|
||||||
import ghidra.framework.Application;
|
import ghidra.framework.Application;
|
||||||
import ghidra.framework.ApplicationConfiguration;
|
import ghidra.framework.ApplicationConfiguration;
|
||||||
import ghidra.pcodeCPort.context.SleighError;
|
|
||||||
import ghidra.sleigh.grammar.*;
|
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
import ghidra.util.SystemUtilities;
|
import ghidra.util.SystemUtilities;
|
||||||
import utilities.util.FileResolutionResult;
|
|
||||||
import utilities.util.FileUtilities;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <code>SleighCompileLauncher</code> Sleigh compiler launch provider
|
* <code>SleighCompileLauncher</code> Sleigh compiler launch provider
|
||||||
|
@ -46,24 +39,6 @@ public class SleighCompileLauncher implements GhidraLaunchable {
|
||||||
private static final FileFilter SLASPEC_FILTER =
|
private static final FileFilter SLASPEC_FILTER =
|
||||||
pathname -> pathname.getName().endsWith(".slaspec");
|
pathname -> pathname.getName().endsWith(".slaspec");
|
||||||
|
|
||||||
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 largeTemporaryWarning) {
|
|
||||||
Set<Entry<String, String>> entrySet = preprocs.entrySet();
|
|
||||||
for (Entry<String, String> entry : entrySet) {
|
|
||||||
compiler.setPreprocValue(entry.getKey(), entry.getValue());
|
|
||||||
}
|
|
||||||
compiler.setUnnecessaryPcodeWarning(unnecessaryPcodeWarning);
|
|
||||||
compiler.setLenientConflict(lenientConflict);
|
|
||||||
compiler.setLocalCollisionWarning(allCollisionWarning);
|
|
||||||
compiler.setAllNopWarning(allNopWarning);
|
|
||||||
compiler.setDeadTempWarning(deadTempWarning);
|
|
||||||
compiler.setUnusedFieldWarning(unusedFieldWarning);
|
|
||||||
compiler.setEnforceLocalKeyWord(enforceLocalKeyWord);
|
|
||||||
compiler.setLargeTemporaryWarning(largeTemporaryWarning);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void launch(GhidraApplicationLayout layout, String[] args)
|
public void launch(GhidraApplicationLayout layout, String[] args)
|
||||||
throws JDOMException, IOException, RecognitionException {
|
throws JDOMException, IOException, RecognitionException {
|
||||||
|
@ -80,9 +55,9 @@ public class SleighCompileLauncher implements GhidraLaunchable {
|
||||||
*
|
*
|
||||||
* @param args sleigh compiler command line arguments
|
* @param args sleigh compiler command line arguments
|
||||||
* @return exit code (TODO: exit codes are not well defined)
|
* @return exit code (TODO: exit codes are not well defined)
|
||||||
* @throws JDOMException
|
* @throws JDOMException for XML errors
|
||||||
* @throws IOException
|
* @throws IOException for file access errors
|
||||||
* @throws RecognitionException
|
* @throws RecognitionException for parse errors
|
||||||
*/
|
*/
|
||||||
public static int runMain(String[] args)
|
public static int runMain(String[] args)
|
||||||
throws JDOMException, IOException, RecognitionException {
|
throws JDOMException, IOException, RecognitionException {
|
||||||
|
@ -113,6 +88,7 @@ public class SleighCompileLauncher implements GhidraLaunchable {
|
||||||
Msg.info(SleighCompile.class, " -c print warnings for all constructors with colliding operands");
|
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, " -f print warnings for unused token fields");
|
||||||
Msg.info(SleighCompile.class, " -o print warnings for temporaries which are too large");
|
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, " -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, " -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");
|
Msg.info(SleighCompile.class, " -i <options-file> inject options from specified file");
|
||||||
|
@ -128,6 +104,7 @@ public class SleighCompileLauncher implements GhidraLaunchable {
|
||||||
boolean enforceLocalKeyWord = false;
|
boolean enforceLocalKeyWord = false;
|
||||||
boolean unusedFieldWarning = false;
|
boolean unusedFieldWarning = false;
|
||||||
boolean largeTemporaryWarning = false;
|
boolean largeTemporaryWarning = false;
|
||||||
|
boolean caseSensitiveRegisterNames = false;
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < args.length; ++i) {
|
for (i = 0; i < args.length; ++i) {
|
||||||
|
@ -191,6 +168,9 @@ public class SleighCompileLauncher implements GhidraLaunchable {
|
||||||
else if (args[i].charAt(1) == 'o') {
|
else if (args[i].charAt(1) == 'o') {
|
||||||
largeTemporaryWarning = true;
|
largeTemporaryWarning = true;
|
||||||
}
|
}
|
||||||
|
else if (args[i].charAt(1) == 's') {
|
||||||
|
caseSensitiveRegisterNames = true;
|
||||||
|
}
|
||||||
else if (args[i].charAt(1) == 'x') {
|
else if (args[i].charAt(1) == 'x') {
|
||||||
SleighCompile.yydebug = true; // Debug option
|
SleighCompile.yydebug = true; // Debug option
|
||||||
}
|
}
|
||||||
|
@ -223,14 +203,14 @@ public class SleighCompileLauncher implements GhidraLaunchable {
|
||||||
for (File input : visitor) {
|
for (File input : visitor) {
|
||||||
System.out.println("Compiling " + input + ":");
|
System.out.println("Compiling " + input + ":");
|
||||||
SleighCompile compiler = new SleighCompile();
|
SleighCompile compiler = new SleighCompile();
|
||||||
initCompiler(compiler, preprocs, unnecessaryPcodeWarning, lenientConflict,
|
compiler.setAllOptions(preprocs, unnecessaryPcodeWarning, lenientConflict,
|
||||||
allCollisionWarning, allNopWarning, deadTempWarning, unusedFieldWarning,
|
allCollisionWarning, allNopWarning, deadTempWarning, unusedFieldWarning,
|
||||||
enforceLocalKeyWord, largeTemporaryWarning);
|
enforceLocalKeyWord, largeTemporaryWarning, caseSensitiveRegisterNames);
|
||||||
|
|
||||||
String outname = input.getName().replace(".slaspec", ".sla");
|
String outname = input.getName().replace(".slaspec", ".sla");
|
||||||
File output = new File(input.getParent(), outname);
|
File output = new File(input.getParent(), outname);
|
||||||
retval =
|
retval =
|
||||||
run_compilation(input.getAbsolutePath(), output.getAbsolutePath(), compiler);
|
compiler.run_compilation(input.getAbsolutePath(), output.getAbsolutePath());
|
||||||
System.out.println();
|
System.out.println();
|
||||||
if (retval != 0) {
|
if (retval != 0) {
|
||||||
++totalFailures;
|
++totalFailures;
|
||||||
|
@ -252,9 +232,9 @@ public class SleighCompileLauncher implements GhidraLaunchable {
|
||||||
|
|
||||||
// single file compile
|
// single file compile
|
||||||
SleighCompile compiler = new SleighCompile();
|
SleighCompile compiler = new SleighCompile();
|
||||||
initCompiler(compiler, preprocs, unnecessaryPcodeWarning, lenientConflict,
|
compiler.setAllOptions(preprocs, unnecessaryPcodeWarning, lenientConflict,
|
||||||
allCollisionWarning, allNopWarning, deadTempWarning, unusedFieldWarning,
|
allCollisionWarning, allNopWarning, deadTempWarning, unusedFieldWarning,
|
||||||
enforceLocalKeyWord, largeTemporaryWarning);
|
enforceLocalKeyWord, largeTemporaryWarning, caseSensitiveRegisterNames);
|
||||||
if (i == args.length) {
|
if (i == args.length) {
|
||||||
Msg.error(SleighCompile.class, "Missing input file name");
|
Msg.error(SleighCompile.class, "Missing input file name");
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -280,7 +260,7 @@ public class SleighCompileLauncher implements GhidraLaunchable {
|
||||||
}
|
}
|
||||||
fileout = baseOutName + FILE_OUT_DEFAULT_EXT;
|
fileout = baseOutName + FILE_OUT_DEFAULT_EXT;
|
||||||
|
|
||||||
return run_compilation(filein, fileout, compiler);
|
return compiler.run_compilation(filein, fileout);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String[] injectOptionsFromFile(String[] args, int index) {
|
private static String[] injectOptionsFromFile(String[] args, int index) {
|
||||||
|
@ -326,131 +306,4 @@ public class SleighCompileLauncher implements GhidraLaunchable {
|
||||||
return list.toArray(new String[list.size()]);
|
return list.toArray(new String[list.size()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int run_compilation(String filein, String fileout, SleighCompile compiler)
|
|
||||||
throws IOException, RecognitionException {
|
|
||||||
// try {
|
|
||||||
// compiler.parseFromNewFile(filein);
|
|
||||||
//FileInputStream yyin = new FileInputStream(new File(filein));
|
|
||||||
// StringWriter output = new StringWriter();
|
|
||||||
|
|
||||||
// System.out.println(output.toString());
|
|
||||||
// UGLY_STATIC_GLOBAL_COMPILER = null; // Set global pointer up for parser
|
|
||||||
|
|
||||||
// SleighCompiler realCompiler = new SleighCompiler(new StringReader(output.toString()));
|
|
||||||
|
|
||||||
// too late for this because we snarf a token or two on constructor time?
|
|
||||||
// if (yydebug) {
|
|
||||||
// realCompiler.enable_tracing();
|
|
||||||
// } else {
|
|
||||||
// realCompiler.disable_tracing();
|
|
||||||
// }
|
|
||||||
|
|
||||||
LineArrayListWriter writer = new LineArrayListWriter();
|
|
||||||
ParsingEnvironment env = new ParsingEnvironment(writer);
|
|
||||||
try {
|
|
||||||
final SleighCompilePreprocessorDefinitionsAdapater definitionsAdapter =
|
|
||||||
new SleighCompilePreprocessorDefinitionsAdapater(compiler);
|
|
||||||
final File inputFile = new File(filein);
|
|
||||||
FileResolutionResult result = FileUtilities.existsAndIsCaseDependent(inputFile);
|
|
||||||
if (!result.isOk()) {
|
|
||||||
throw new BailoutException("input file \"" + inputFile +
|
|
||||||
"\" is not properly case dependent: " + result.getMessage());
|
|
||||||
}
|
|
||||||
SleighPreprocessor sp = new SleighPreprocessor(definitionsAdapter, inputFile);
|
|
||||||
sp.process(writer);
|
|
||||||
|
|
||||||
CharStream input = new ANTLRStringStream(writer.toString());
|
|
||||||
SleighLexer lex = new SleighLexer(input);
|
|
||||||
lex.setEnv(env);
|
|
||||||
UnbufferedTokenStream tokens = new UnbufferedTokenStream(lex);
|
|
||||||
SleighParser parser = new SleighParser(tokens);
|
|
||||||
parser.setEnv(env);
|
|
||||||
parser.setLexer(lex);
|
|
||||||
SleighParser.spec_return root = parser.spec();
|
|
||||||
/*ANTLRUtil.debugTree(root.getTree(),
|
|
||||||
new PrintStream(new FileOutputStream("blargh.tree")));*/
|
|
||||||
CommonTreeNodeStream nodes = new CommonTreeNodeStream(root.getTree());
|
|
||||||
nodes.setTokenStream(tokens);
|
|
||||||
// ANTLRUtil.debugNodeStream(nodes, System.out);
|
|
||||||
SleighCompiler walker = new SleighCompiler(nodes);
|
|
||||||
|
|
||||||
int parseres = -1;
|
|
||||||
try {
|
|
||||||
parseres = walker.root(env, compiler); // Try to parse
|
|
||||||
}
|
|
||||||
catch (SleighError e) {
|
|
||||||
compiler.reportError(e.location, e.getMessage());
|
|
||||||
}
|
|
||||||
// yyin.close();
|
|
||||||
if (parseres == 0) {
|
|
||||||
if (compiler.noplist.size() > 0) {
|
|
||||||
if (compiler.warnallnops) {
|
|
||||||
IteratorSTL<String> iter;
|
|
||||||
for (iter = compiler.noplist.begin(); !iter.isEnd(); iter.increment()) {
|
|
||||||
Msg.warn(SleighCompile.class, iter.get());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Msg.warn(SleighCompile.class,
|
|
||||||
compiler.noplist.size() + " NOP constructors found");
|
|
||||||
if (!compiler.warnallnops) {
|
|
||||||
Msg.warn(SleighCompile.class, "Use -n switch to list each individually");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
compiler.process(); // Do all the post-processing
|
|
||||||
}
|
|
||||||
if ((parseres == 0) && (compiler.numErrors() == 0)) {
|
|
||||||
// If no errors
|
|
||||||
// try {
|
|
||||||
PrintStream s = new PrintStream(new FileOutputStream(new File(fileout)));
|
|
||||||
compiler.saveXml(s); // Dump output xml
|
|
||||||
s.close();
|
|
||||||
// }
|
|
||||||
// catch (Exception e) {
|
|
||||||
// throw new SleighError("Unable to open output file: "
|
|
||||||
// + fileout);
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Msg.error(SleighCompile.class, "No output produced");
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (BailoutException e) {
|
|
||||||
Msg.error(SleighCompile.class, "Unrecoverable error(s), halting compilation", e);
|
|
||||||
return 3;
|
|
||||||
}
|
|
||||||
catch (NullPointerException e) {
|
|
||||||
Msg.error(SleighCompile.class, "Unrecoverable error(s), halting compilation", e);
|
|
||||||
return 4;
|
|
||||||
}
|
|
||||||
catch (PreprocessorException e) {
|
|
||||||
Msg.error(SleighCompile.class, e.getMessage());
|
|
||||||
Msg.error(SleighCompile.class, "Errors during preprocessing, halting compilation");
|
|
||||||
return 5;
|
|
||||||
}
|
|
||||||
// catch (LowlevelError err) {
|
|
||||||
// Msg.info(this, "Unrecoverable error: " + err.getMessage());
|
|
||||||
// err.printStackTrace();
|
|
||||||
// return 2;
|
|
||||||
// }
|
|
||||||
// catch (IOException e) {
|
|
||||||
// Msg.info(this, "Couldn't close file: " + e.getMessage());
|
|
||||||
// return 1;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// catch (FileNotFoundException e) {
|
|
||||||
// Msg.info(this, "Unable to open specfile: " + filein);
|
|
||||||
// return 2;
|
|
||||||
// }
|
|
||||||
// catch (IOException e) {
|
|
||||||
// // TODO Auto-generated catch block
|
|
||||||
// e.printStackTrace();
|
|
||||||
// }
|
|
||||||
// catch (ParseException e) {
|
|
||||||
// // TODO Auto-generated catch block
|
|
||||||
// e.printStackTrace();
|
|
||||||
// }
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -220,8 +220,6 @@ public abstract class Translate implements BasicSpaceProvider {
|
||||||
public void setContextDefault(String name, int val) {
|
public void setContextDefault(String name, int val) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void addRegister(String nm, AddrSpace base, long offset, int size);
|
|
||||||
|
|
||||||
public abstract VarnodeData getRegister(String nm);
|
public abstract VarnodeData getRegister(String nm);
|
||||||
|
|
||||||
public abstract String getRegisterName(AddrSpace base, long off, int size);
|
public abstract String getRegisterName(AddrSpace base, long off, int size);
|
||||||
|
@ -293,15 +291,6 @@ public abstract class Translate implements BasicSpaceProvider {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
void addRegisterList(String[] nms, int num, AddrSpace base, long offset, int size, int skip) { // Add names assigning indices in order
|
|
||||||
// allocating -size- space for each starting at -offset-
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < num; ++i) {
|
|
||||||
addRegister(nms[i], base, offset + skip * i, size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Associate a particular register or memory location with an address space
|
// Associate a particular register or memory location with an address space
|
||||||
// The canonical example is the \b stack \b pointer and the stack space.
|
// The canonical example is the \b stack \b pointer and the stack space.
|
||||||
// The \b basespace is the so-called stack space, which is really a
|
// The \b basespace is the so-called stack space, which is really a
|
||||||
|
@ -542,8 +531,8 @@ public abstract class Translate implements BasicSpaceProvider {
|
||||||
|
|
||||||
public AddrSpace getSpaceBySpacebase(Address loc, int size) { // Get space associated with spacebase register
|
public AddrSpace getSpaceBySpacebase(Address loc, int size) { // Get space associated with spacebase register
|
||||||
AddrSpace id;
|
AddrSpace id;
|
||||||
for (int i = 0; i < baselist.size(); ++i) {
|
for (AddrSpace element : baselist) {
|
||||||
id = baselist.get(i);
|
id = element;
|
||||||
int numspace = numSpacebase(id);
|
int numspace = numSpacebase(id);
|
||||||
for (int j = 0; j < numspace; ++j) {
|
for (int j = 0; j < numspace; ++j) {
|
||||||
VarnodeData point = getSpacebase(id, j);
|
VarnodeData point = getSpacebase(id, j);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue