Merge remote-tracking branch 'origin/GP-927_SleighCaseSensitiveRegisters' into Ghidra_10.0

This commit is contained in:
ghidra1 2021-06-03 11:15:59 -04:00
commit 43a9499e39
14 changed files with 1607 additions and 808 deletions

View file

@ -41,7 +41,7 @@ public abstract class SleighBase extends Translate implements NamedSymbolProvide
public static final int SLA_FORMAT_VERSION = 3;
public static final long MAX_UNIQUE_SIZE = 128; //Maximum size of a varnode in the unique space.
//Should match value in sleighbase.cc
//Should match value in sleighbase.cc
private VectorSTL<String> userop = new VectorSTL<>();
private address_set varnode_xref = new address_set(); // Cross-reference registers by address
@ -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
public VarnodeData getRegister(String nm) {
VarnodeSymbol sym = (VarnodeSymbol) findSymbol(nm);

View file

@ -29,24 +29,22 @@ import ghidra.pcodeCPort.space.AddrSpace;
class ConsistencyChecker {
int unnecessarypcode;
int readnowrite;
int writenoread;
// number of constructors using a temporary varnode larger than SleighBase.MAX_UNIQUE_SIZE
int largetemp;
boolean printextwarning;
boolean printdeadwarning;
//if true, print information about constructors using temporary varnodes larger than SleighBase.MAX_UNIQUE_SIZE
boolean printlargetempwarning;
SleighCompile compiler;
SubtableSymbol root_symbol;
VectorSTL<SubtableSymbol> postorder = new VectorSTL<>();
private int unnecessarypcode;
private int readnowrite;
private int writenoread;
private int largetemp; // number of constructors using a temporary varnode larger than SleighBase.MAX_UNIQUE_SIZE
private boolean printextwarning;
private boolean printdeadwarning;
private boolean printlargetempwarning; // if true, warning about temporary varnodes larger than SleighBase.MAX_UNIQUE_SIZE
private SleighCompile compiler;
private SubtableSymbol root_symbol;
private VectorSTL<SubtableSymbol> postorder = new VectorSTL<>();
// Sizes associated with tables
MapSTL<SubtableSymbol, Integer> sizemap =
new MapSTL<>((s1, s2) -> s1.compareTo(s2));
private MapSTL<SubtableSymbol, Integer> sizemap = 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;
OperandSymbol opsym = null;
int handindex;
@ -69,9 +67,8 @@ class ConsistencyChecker {
return opsym;
}
boolean sizeRestriction(OpTpl op, Constructor ct)
{ // Make sure op template meets size restrictions
private boolean sizeRestriction(OpTpl op, Constructor ct) {
// Make sure op template meets size restrictions
// Return false and any info about mismatched sizes
int vnout, vn0, vn1;
AddrSpace spc;
@ -103,7 +100,7 @@ class ConsistencyChecker {
return true;
}
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;
case CPUI_INT_ADD:
case CPUI_INT_SUB:
@ -240,8 +237,8 @@ class ConsistencyChecker {
return false;
}
return true;
// The shift amount does not necessarily have to be the same size
// But the output and first parameter must be same size
// The shift amount does not necessarily have to be the same size
// But the output and first parameter must be same size
case CPUI_INT_LEFT:
case CPUI_INT_RIGHT:
case CPUI_INT_SRIGHT:
@ -284,7 +281,7 @@ class ConsistencyChecker {
}
else if (vnout < vn0) {
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 true;
@ -349,7 +346,7 @@ class ConsistencyChecker {
return true;
}
String getOpName(OpTpl op) {
private String getOpName(OpTpl op) {
switch (op.getOpcode()) {
case CPUI_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();
OperandSymbol op1, op2;
@ -498,10 +495,10 @@ class ConsistencyChecker {
StringBuilder sb = new StringBuilder();
sb.append("Size restriction error in table '")
.append(sym.getName())
.append("' in constructor at ").append(ct.location)
.append("\n");
.append(sym.getName())
.append("' in constructor at ")
.append(ct.location)
.append("\n");
sb.append(" Problem");
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;
OperandSymbol opsym;
SubtableSymbol tabsym;
@ -572,7 +569,7 @@ class ConsistencyChecker {
"\" (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()) {
case CPUI_INT_LESS: {
VarnodeTpl vn0 = op.getIn(0);
@ -594,7 +591,7 @@ class ConsistencyChecker {
handleBetter("!= 0", ct);
}
}
break;
break;
case CPUI_INT_LESSEQUAL: {
VarnodeTpl vn0 = op.getIn(0);
VarnodeTpl vn1 = op.getIn(1);
@ -615,14 +612,14 @@ class ConsistencyChecker {
handleBetter("== 0", ct);
}
}
break;
break;
default:
break;
}
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
if (cttpl == null) {
return true; // Nothing to check
@ -649,7 +646,7 @@ class ConsistencyChecker {
* @param opTpl the op to check
* @return true if {@code opTpl} uses a large temporary varnode
*/
boolean hasLargeTemporary(OpTpl opTpl) {
private boolean hasLargeTemporary(OpTpl opTpl) {
VarnodeTpl out = opTpl.getOut();
if (out != null && isTemporaryAndTooBig(out)) {
return true;
@ -659,7 +656,7 @@ class ConsistencyChecker {
if (isTemporaryAndTooBig(in)) {
return true;
}
}
}
return false;
}
@ -669,12 +666,12 @@ class ConsistencyChecker {
* @param vn varnode template to check
* @return true if it uses a large temporary
*/
boolean isTemporaryAndTooBig(VarnodeTpl vn) {
return vn.getSpace().isUniqueSpace() &&
vn.getSize().getReal() > SleighBase.MAX_UNIQUE_SIZE;
private boolean isTemporaryAndTooBig(VarnodeTpl vn) {
return vn.getSpace().isUniqueSpace() && vn.getSize().getReal() > SleighBase.MAX_UNIQUE_SIZE;
}
boolean checkVarnodeTruncation(Constructor ct,int slot,OpTpl op,VarnodeTpl vn,boolean isbigendian) {
private boolean checkVarnodeTruncation(Constructor ct, int slot, OpTpl op, VarnodeTpl vn,
boolean isbigendian) {
ConstTpl off = vn.getOffset();
if (off.getType() != const_type.handle) {
return true;
@ -683,24 +680,25 @@ class ConsistencyChecker {
return true;
}
const_type sztype = vn.getSize().getType();
if ((sztype != const_type.real)&&(sztype != const_type.handle)){
printOpError(op,ct,slot,slot,"Bad truncation expression");
if ((sztype != const_type.real) && (sztype != const_type.handle)) {
printOpError(op, ct, slot, slot, "Bad truncation expression");
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) {
printOpError(op,ct,slot,slot,"Could not recover size");
printOpError(op, ct, slot, slot, "Could not recover size");
return false;
}
boolean res = vn.adjustTruncation(sz, isbigendian);
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 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
// adjust the plus if we are big endian
// make sure the truncation is valid
@ -709,16 +707,16 @@ class ConsistencyChecker {
Iterator<OpTpl> iter;
iter = ops.iterator();
while(iter.hasNext()) {
while (iter.hasNext()) {
OpTpl op = iter.next();
VarnodeTpl outvn = op.getOut();
if (outvn != null) {
if (!checkVarnodeTruncation(ct,-1,op,outvn,isbigendian)) {
if (!checkVarnodeTruncation(ct, -1, op, outvn, isbigendian)) {
testresult = false;
}
}
for(int i=0;i<op.numInput();++i) {
if (!checkVarnodeTruncation(ct,i,op,op.getIn(i),isbigendian)) {
for (int i = 0; i < op.numInput(); ++i) {
if (!checkVarnodeTruncation(ct, i, op, op.getIn(i), isbigendian)) {
testresult = false;
}
}
@ -726,7 +724,7 @@ class ConsistencyChecker {
return testresult;
}
boolean checkSubtable(SubtableSymbol sym) {
private boolean checkSubtable(SubtableSymbol sym) {
int tablesize = 0;
int numconstruct = sym.getNumConstructors();
Constructor ct;
@ -796,7 +794,7 @@ class ConsistencyChecker {
// Deal with detected extension (SEXT or ZEXT) where the
// input size is the same as the output size
void dealWithUnnecessaryExt(OpTpl op, Constructor ct) {
private void dealWithUnnecessaryExt(OpTpl op, Constructor ct) {
if (printextwarning) {
compiler.reportWarning(op.location, "Unnecessary '" + getOpName(op) + "'");
}
@ -804,7 +802,7 @@ class ConsistencyChecker {
unnecessarypcode += 1;
}
void dealWithUnnecessaryTrunc(OpTpl op, Constructor ct) {
private void dealWithUnnecessaryTrunc(OpTpl op, Constructor ct) {
if (printextwarning) {
compiler.reportWarning(op.location, "Unnecessary '" + getOpName(op) + "'");
}
@ -814,7 +812,7 @@ class ConsistencyChecker {
}
// Establish table ordering
void setPostOrder(SubtableSymbol root) {
private void setPostOrder(SubtableSymbol root) {
postorder.clear();
sizemap.clear();
@ -869,8 +867,8 @@ class ConsistencyChecker {
}
// Optimization routines
static void examineVn(MapSTL<Long, OptimizeRecord> recs, VarnodeTpl vn, int i, int inslot,
int secnum) {
private static void examineVn(MapSTL<Long, OptimizeRecord> recs, VarnodeTpl vn, int i,
int inslot, int secnum) {
if (vn == null) {
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
if (vn1.getSpace().isConstSpace()) {
return false;
@ -958,7 +956,7 @@ class ConsistencyChecker {
// This is extremely conservative. Basically any op where
// we can't see exactly what might be written is considered
// interference
boolean readWriteInterference(VarnodeTpl vn, OpTpl op, boolean checkread) {
private boolean readWriteInterference(VarnodeTpl vn, OpTpl op, boolean checkread) {
switch (op.getOpcode()) {
case CPUI_MULTIEQUAL:
case CPUI_PTRSUB:
@ -999,7 +997,7 @@ class ConsistencyChecker {
}
// 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;
if (secnum < 0) {
tpl = ct.getTempl();
@ -1023,7 +1021,7 @@ class ConsistencyChecker {
}
// 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;
if (secnum < 0) {
tpl = ct.getTempl();
@ -1053,7 +1051,7 @@ class ConsistencyChecker {
}
if (hand.getSpace().isUniqueSpace()) {
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();
recs.put(offset, new OptimizeRecord());
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;
iter = recs.begin();
while (!iter.isEnd()) {
@ -1075,7 +1073,7 @@ class ConsistencyChecker {
iter.increment();
if ((currec.writecount == 1) && (currec.readcount == 1) &&
(currec.readsection == currec.writesection)) {
(currec.readsection == currec.writesection)) {
// Temporary must be read and written exactly once
ConstructTpl tpl;
if (currec.readsection < 0) {
@ -1123,7 +1121,7 @@ class ConsistencyChecker {
return null;
}
void applyOptimization(Constructor ct, OptimizeRecord rec) {
private void applyOptimization(Constructor ct, OptimizeRecord rec) {
VectorSTL<Integer> deleteops = new VectorSTL<>();
ConstructTpl ctempl;
if (rec.readsection < 0) {
@ -1150,7 +1148,7 @@ class ConsistencyChecker {
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();
while (!iter.isEnd()) {
Pair<Long, OptimizeRecord> pair = iter.get();
@ -1168,30 +1166,29 @@ class ConsistencyChecker {
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}.
* @param ct constructor to check
* @param ctpl is the specific p-code section
*/
void checkLargeTemporaries(Constructor ct) {
ConstructTpl ctTpl = ct.getTempl();
if (ctTpl == null) {
return;
}
VectorSTL<OpTpl> ops = ctTpl.getOpvec();
private void checkLargeTemporaries(Constructor ct, ConstructTpl ctpl) {
VectorSTL<OpTpl> ops = ctpl.getOpvec();
for (IteratorSTL<OpTpl> iter = ops.begin(); !iter.isEnd(); iter.increment()) {
if (hasLargeTemporary(iter.get())) {
if (printlargetempwarning) {
compiler.reportWarning(ct.location, "Constructor uses temporary varnode larger than " + SleighBase.MAX_UNIQUE_SIZE + " bytes.");
}
if (printlargetempwarning) {
compiler.reportWarning(ct.location,
"Constructor uses temporary varnode larger than " +
SleighBase.MAX_UNIQUE_SIZE + " bytes.");
}
largetemp++;
return;
}
return;
}
}
}
void optimize(Constructor ct) {
private void optimize(Constructor ct) {
OptimizeRecord currec;
MapSTL<Long, OptimizeRecord> recs = new ComparableMapSTL<>();
int numsections = ct.getNumSections();
@ -1208,17 +1205,17 @@ class ConsistencyChecker {
}
while (currec != null);
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;
root_symbol = rt;
unnecessarypcode = 0;
readnowrite = 0;
writenoread = 0;
//number of constructors which reference a temporary varnode larger than SleighBase.MAX_UNIQUE_SIZE
largetemp = 0;
largetemp = 0;
printextwarning = unnecessary;
printdeadwarning = warndead;
//whether to print information about constructors which reference large temporary varnodes
@ -1226,7 +1223,7 @@ class ConsistencyChecker {
}
// Main entry point for size consistency check
boolean test() {
public boolean testSizeRestrictions() {
setPostOrder(root_symbol);
boolean testresult = true;
@ -1239,18 +1236,19 @@ class ConsistencyChecker {
return testresult;
}
boolean testTruncations(boolean isbigendian) {
public boolean testTruncations() {
// Now that the sizemap is calculated, we can check/adjust the offset_plus templates
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);
int numconstruct = sym.getNumConstructors();
Constructor ct;
for(int j=0;j<numconstruct;++j) {
for (int j = 0; j < numconstruct; ++j) {
ct = sym.getConstructor(j);
int numsections = ct.getNumSections();
for(int k=-1;k<numsections;++k) {
for (int k = -1; k < numsections; ++k) {
ConstructTpl tpl;
if (k < 0) {
tpl = ct.getTempl();
@ -1261,7 +1259,7 @@ class ConsistencyChecker {
if (tpl == null) {
continue;
}
if (!checkSectionTruncations(ct,tpl,isbigendian)) {
if (!checkSectionTruncations(ct, tpl, isbigendian)) {
testresult = false;
}
}
@ -1270,7 +1268,33 @@ class ConsistencyChecker {
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) {
SubtableSymbol sym = postorder.get(i);
int numconstruct = sym.getNumConstructors();
@ -1282,24 +1306,24 @@ class ConsistencyChecker {
}
}
int getNumUnnecessaryPcode() {
public int getNumUnnecessaryPcode() {
return unnecessarypcode;
}
int getNumReadNoWrite() {
public int getNumReadNoWrite() {
return readnowrite;
}
int getNumWriteNoRead() {
public int getNumWriteNoRead() {
return writenoread;
}
/**
* Returns the number of constructors which reference a varnode in the
* unique space with size larger than {@link SleighBase#MAX_UNIQUE_SIZE}.
* @return num constructors with large temp varnodes
*/
int getNumLargeTemporaries() {
public int getNumLargeTemporaries() {
return largetemp;
}
}

View file

@ -15,14 +15,13 @@
*/
package ghidra.pcodeCPort.slgh_compile;
import java.io.IOException;
import java.io.PrintStream;
import java.io.*;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.Map.Entry;
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 generic.stl.*;
@ -39,8 +38,10 @@ import ghidra.pcodeCPort.space.*;
import ghidra.pcodeCPort.utils.Utils;
import ghidra.pcodeCPort.xml.DocumentStorage;
import ghidra.program.model.lang.BasicCompilerSpec;
import ghidra.sleigh.grammar.Location;
import ghidra.sleigh.grammar.*;
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)
@ -50,7 +51,7 @@ public class SleighCompile extends SleighBase {
static boolean yydebug = false;
static boolean isLocationIsh(Object o) {
private static boolean isLocationIsh(Object o) {
if (o instanceof Location) {
return true;
}
@ -225,48 +226,45 @@ public class SleighCompile extends SleighBase {
}
// Defines for the preprocessor
MapSTL<String, String> preproc_defines = new MapSTL<>(new SelfComparator<String>());
VectorSTL<FieldContext> contexttable = new VectorSTL<>();
Integer firstContextField = null;
VectorSTL<ConstructTpl> macrotable = new VectorSTL<>();
VectorSTL<ghidra.pcodeCPort.context.Token> tokentable = new VectorSTL<>();
VectorSTL<SubtableSymbol> tables = new VectorSTL<>();
VectorSTL<SectionSymbol> sections = new VectorSTL<>();
Constructor curct; // Current constructor being defined
MacroSymbol curmacro; // Current macro being defined
private MapSTL<String, String> preproc_defines = new MapSTL<>(new SelfComparator<String>());
private VectorSTL<FieldContext> contexttable = new VectorSTL<>();
private Integer firstContextField = null;
private VectorSTL<ConstructTpl> macrotable = new VectorSTL<>();
private VectorSTL<ghidra.pcodeCPort.context.Token> tokentable = new VectorSTL<>();
private VectorSTL<SubtableSymbol> tables = new VectorSTL<>();
private VectorSTL<SectionSymbol> sections = new VectorSTL<>();
private Constructor curct; // Current constructor being defined
private MacroSymbol curmacro; // Current macro being defined
// If the context layout has been established yet
boolean contextlock;
private boolean contextlock;
// Stack of current files being parsed
// VectorSTL<String> filename = new VectorSTL<String>();
String filename;
// Current line number for each file in stack
// 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
boolean warndeadtemps; // True if we warn of temporaries that are written but not read
boolean warnunusedfields; // True if fields are defined but not used
boolean enforcelocalkeyword; // Force slaspec to use 'local' keyword when defining temporary varnodes
boolean lenientconflicterrors; // True if we ignore most pattern conflict errors
boolean largetemporarywarning; // True if we warn about temporaries larger than SleighBase.MAX_UNIQUE_SIZE
public boolean warnalllocalcollisions;
public boolean warnallnops;
public VectorSTL<String> noplist = new VectorSTL<>();
private boolean warnunnecessarypcode; // True if we warn of unnecessary ZEXT or SEXT
private boolean warndeadtemps; // True if we warn of temporaries that are written but not read
private boolean warnunusedfields; // True if fields are defined but not used
private 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
private boolean warnalllocalcollisions; // True if local export collisions generate individual warnings
private boolean warnallnops; // True if pcode NOPs generate individual warnings
private boolean failinsensitivedups; // True if case insensitive register duplicates cause error
private VectorSTL<String> noplist = new VectorSTL<>();
public Deque<WithBlock> withstack = new LinkedList<>();
private Deque<WithBlock> withstack = new LinkedList<>();
int errors;
int warnings;
private int errors;
private int warnings;
// Define the "pre" defined spaces and symbols
// This must happen after endian has been defined
void predefinedSymbols() {
private void predefinedSymbols() {
entry("predefinedSymbols");
symtab.addScope(); // Create global scope
@ -327,14 +325,14 @@ public class SleighCompile extends SleighBase {
return res;
}
SectionVector standaloneSection(ConstructTpl main) {
protected SectionVector standaloneSection(ConstructTpl main) {
entry("standaloneSection", main);
// Create SectionVector for just the main rtl section with no named sections
SectionVector res = new SectionVector(main, symtab.getCurrentScope());
return res;
}
SectionVector firstNamedSection(ConstructTpl main, SectionSymbol sym) {
protected SectionVector firstNamedSection(ConstructTpl main, SectionSymbol sym) {
entry("firstNamedSection", main);
// Start the first named p-code section after the main p-code section
sym.incrementDefineCount();
@ -349,7 +347,8 @@ public class SleighCompile extends SleighBase {
return res;
}
SectionVector nextNamedSection(SectionVector vec, ConstructTpl section, SectionSymbol sym) {
protected SectionVector nextNamedSection(SectionVector vec, ConstructTpl section,
SectionSymbol sym) {
entry("nextNamedSection", vec, section, sym);
// Add additional named p-code sections
sym.incrementDefineCount();
@ -365,7 +364,7 @@ public class SleighCompile extends SleighBase {
return vec;
}
SectionVector finalNamedSection(SectionVector vec, ConstructTpl section) {
protected SectionVector finalNamedSection(SectionVector vec, ConstructTpl section) {
entry("finalNamedSection", vec, section);
// Fill-in final named section to match the previous SectionSymbol
vec.append(section, symtab.getCurrentScope());
@ -373,7 +372,7 @@ public class SleighCompile extends SleighBase {
return vec;
}
int calcContextVarLayout(int start, int sz, int numbits) {
private int calcContextVarLayout(int start, int sz, int numbits) {
entry("calcContextVarLayout", start, sz, numbits);
VarnodeSymbol sym = contexttable.get(start).sym;
FieldQuality qual;
@ -390,7 +389,7 @@ public class SleighCompile extends SleighBase {
i = 0;
while (i < sz) {
qual = contexttable.get(i).qual;
qual = contexttable.get(i + start).qual;
int min = qual.low;
int max = qual.high;
if (max - min > (8 * 4)) {
@ -409,7 +408,7 @@ public class SleighCompile extends SleighBase {
j = i + 1;
// Find union of fields overlapping with first field
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.high > max) {
max = qual.high;
@ -434,7 +433,7 @@ public class SleighCompile extends SleighBase {
numbits += alloc;
for (; i < j; ++i) {
qual = contexttable.get(i).qual;
qual = contexttable.get(i + start).qual;
int l = qual.low - min + low;
int h = numbits - 1 - (max - qual.high);
ContextField field = new ContextField(qual.location, qual.signext, l, h);
@ -450,7 +449,7 @@ public class SleighCompile extends SleighBase {
return numbits;
}
void buildDecisionTrees() {
private void buildDecisionTrees() {
entry("buildDecisionTrees");
DecisionProperties props = new DecisionProperties();
root.buildDecisionTree(props);
@ -474,7 +473,7 @@ public class SleighCompile extends SleighBase {
}
}
void buildPatterns() {
private void buildPatterns() {
entry("buildPatterns");
if (root == null) {
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");
ConsistencyChecker checker =
new ConsistencyChecker(this, root, warnunnecessarypcode, warndeadtemps, largetemporarywarning);
ConsistencyChecker checker = new ConsistencyChecker(this, root, warnunnecessarypcode,
warndeadtemps, largetemporarywarning);
if (!checker.test()) {
if (!checker.testSizeRestrictions()) {
errors += 1;
return;
}
if (!checker.testTruncations(isBigEndian())) {
if (!checker.testTruncations()) {
errors += 1;
return;
}
@ -524,14 +523,17 @@ public class SleighCompile extends SleighBase {
" operations wrote to temporaries that were not read");
reportWarning(null, "Use -t switch to list each individually");
}
checker.testLargeTemporary();
if ((!largetemporarywarning) && checker.getNumLargeTemporaries() > 0) {
reportWarning(null, checker.getNumLargeTemporaries() +
" constructors contain temporaries larger than " + SleighBase.MAX_UNIQUE_SIZE + " bytes.");
reportWarning(null,
checker.getNumLargeTemporaries() +
" constructors contain temporaries larger than " + SleighBase.MAX_UNIQUE_SIZE +
" bytes.");
reportWarning(null, "Use -o switch to list each individually.");
}
}
}
static int findCollision(Map<Long, Integer> local2Operand, ArrayList<Long> locals,
private static int findCollision(Map<Long, Integer> local2Operand, ArrayList<Long> locals,
int operand) {
Integer boxOperand = Integer.valueOf(operand);
for (Long local : locals) {
@ -545,7 +547,7 @@ public class SleighCompile extends SleighBase {
return -1;
}
boolean checkLocalExports(Constructor ct) {
private boolean checkLocalExports(Constructor ct) {
if (ct.getTempl() == null) {
return true; // No template, collisions impossible
}
@ -556,9 +558,9 @@ public class SleighCompile extends SleighBase {
return true; // Collisions can only happen with multiple operands
}
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) {
ArrayList<Long> newCollect = new ArrayList<Long>();
ArrayList<Long> newCollect = new ArrayList<>();
ct.getOperand(i).collectLocalValues(newCollect);
if (newCollect.isEmpty()) {
continue;
@ -578,7 +580,7 @@ public class SleighCompile extends SleighBase {
return noCollisions;
}
void checkLocalCollisions() {
private void checkLocalCollisions() {
int collisionCount = 0;
SubtableSymbol sym = root; // Start with the instruction table
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
String checkSymbols(SymbolScope scope) {
private String checkSymbols(SymbolScope scope) {
entry("checkSymbols", scope);
List<String> symbolErrors = new ArrayList<>();
IteratorSTL<SleighSymbol> iter;
@ -628,7 +675,7 @@ public class SleighCompile extends SleighBase {
}
// Make sure symbol table errors are caught
int addSymbol(SleighSymbol sym) {
protected int addSymbol(SleighSymbol sym) {
entry("addSymbol", sym);
int id = -1;
try {
@ -648,7 +695,9 @@ public class SleighCompile extends SleighBase {
errors = 0;
warnunnecessarypcode = false;
lenientconflicterrors = true;
largetemporarywarning = false;
warnallnops = false;
failinsensitivedups = true;
root = null;
pcode.resetLabelCount();
}
@ -689,63 +738,69 @@ public class SleighCompile extends SleighBase {
return warnings;
}
long getUniqueAddr() {
protected long getUniqueAddr() {
entry("getUniqueAddr");
long base = getUniqueBase();
setUniqueBase(base + MAX_UNIQUE_SIZE);
setUniqueBase(base + MAX_UNIQUE_SIZE);
return base;
}
void setUnnecessaryPcodeWarning(boolean val) {
public void setUnnecessaryPcodeWarning(boolean val) {
entry("setUnecessaryPcodeWarning", val);
warnunnecessarypcode = val;
}
void setDeadTempWarning(boolean val) {
public void setDeadTempWarning(boolean val) {
entry("setDeadTempWarning", val);
warndeadtemps = val;
}
void setUnusedFieldWarning(boolean val) {
public void setUnusedFieldWarning(boolean val) {
entry("setUnusedFieldWarning", val);
warnunusedfields = val;
}
void setEnforceLocalKeyWord(boolean val) {
public void setEnforceLocalKeyWord(boolean val) {
entry("setEnforceLocalKeyWord", val);
enforcelocalkeyword = val;
pcode.setEnforceLocalKey(val);
}
/**
* Sets whether or not to print out warning info about
* {@link Constructor}s which reference varnodes in the
* unique space larger than {@link SleighBase#MAX_UNIQUE_SIZE}.
* @param val whether to print info about contructors using large varnodes
*/
void setLargeTemporaryWarning(boolean val) {
entry("setLargeTemporaryWarning",val);
public void setLargeTemporaryWarning(boolean val) {
entry("setLargeTemporaryWarning", val);
largetemporarywarning = val;
}
void setLenientConflict(boolean val) {
public void setLenientConflict(boolean val) {
entry("setLenientConflict", val);
lenientconflicterrors = val;
}
void setLocalCollisionWarning(boolean val) {
public void setLocalCollisionWarning(boolean val) {
entry("setLocalCollisionWarning", val);
warnalllocalcollisions = val;
}
void setAllNopWarning(boolean val) {
public void setAllNopWarning(boolean val) {
entry("setAllNopWarning", val);
warnallnops = val;
}
public void setInsensitiveDuplicateError(boolean val) {
entry("setInsensitiveDuplicateError", val);
failinsensitivedups = val;
}
// Do all post processing on the parsed data structures
public void process() {
private void process() {
entry("process");
checkNops();
checkCaseSensitivity();
if (getDefaultSpace() == null) {
reportError(null, "No default space specified");
}
@ -768,7 +823,7 @@ public class SleighCompile extends SleighBase {
if (errors > 0) {
return;
}
ArrayList<SleighSymbol> errorPairs = new ArrayList<SleighSymbol>();
ArrayList<SleighSymbol> errorPairs = new ArrayList<>();
buildXrefs(errorPairs); // Make sure we can build crossrefs properly
if (!errorPairs.isEmpty()) {
for (int i = 0; i < errorPairs.size(); i += 2) {
@ -816,25 +871,7 @@ public class SleighCompile extends SleighBase {
contexttable.clear();
}
private static final Pattern PREPROCPOS = Pattern.compile("%%%(.*)\b(\\d+)%%%");
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) {
public Pair<Boolean, String> getPreprocValue(String nm) {
IteratorSTL<Pair<String, String>> iter = preproc_defines.find(nm);
if (iter.isEnd()) {
return new Pair<>(false, null);
@ -842,11 +879,11 @@ public class SleighCompile extends SleighBase {
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);
}
boolean undefinePreprocValue(String nm) {
public boolean undefinePreprocValue(String nm) {
IteratorSTL<Pair<String, String>> iter = preproc_defines.find(nm);
if (iter.isEnd()) {
return false;
@ -1281,7 +1318,7 @@ public class SleighCompile extends SleighBase {
// Match up any qualities of the macro's OperandSymbols with
// 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);
for (int i = 0; i < param.size(); ++i) {
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
void resetConstructors() {
protected void resetConstructors() {
entry("resetConstructors");
symtab.setCurrentScope(symtab.getGlobalScope()); // Purge any
// dangling local
@ -1361,7 +1398,7 @@ public class SleighCompile extends SleighBase {
// Find a defining instance of the local variable
// 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);
VectorSTL<OpTpl> ops = ct.getOpvec();
VarnodeTpl vn;
@ -1386,7 +1423,7 @@ public class SleighCompile extends SleighBase {
}
// 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);
HandleTpl result = ct.getResult();
if (result == null) {
@ -1396,14 +1433,14 @@ public class SleighCompile extends SleighBase {
VarnodeTpl vt;
if (result.getPtrSpace().isUniqueSpace() && result.getPtrSize().isZero()) {
vt = find_size(result.getPtrOffset(), ct);
vt = findSize(result.getPtrOffset(), ct);
if (vt == null) {
return false;
}
result.setPtrSize(vt.getSize());
}
else if (result.getSpace().isUniqueSpace() && result.getSize().isZero()) {
vt = find_size(result.getPtrOffset(), ct);
vt = findSize(result.getPtrOffset(), ct);
if (vt == null) {
return false;
}
@ -1412,7 +1449,7 @@ public class SleighCompile extends SleighBase {
return true;
}
boolean expandMacros(ConstructTpl ctpl) {
private boolean expandMacros(ConstructTpl ctpl) {
VectorSTL<OpTpl> vec = ctpl.getOpvec();
VectorSTL<OpTpl> newvec = new VectorSTL<>();
IteratorSTL<OpTpl> iter;
@ -1442,7 +1479,7 @@ public class SleighCompile extends SleighBase {
return true;
}
boolean finalizeSections(Constructor big, SectionVector vec) {
private boolean finalizeSections(Constructor big, SectionVector vec) {
entry("finalizeSections", big, vec);
// Do all final checks, expansions, and linking for p-code sections
VectorSTL<String> myErrors = new VectorSTL<>();
@ -1485,7 +1522,7 @@ public class SleighCompile extends SleighBase {
if (big.getParent() == root) {
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");
}
}
@ -1523,7 +1560,7 @@ public class SleighCompile extends SleighBase {
return true;
}
void shiftUniqueVn(VarnodeTpl vn, int sa) {
private static void shiftUniqueVn(VarnodeTpl vn, int sa) {
entry("shiftUniqueVn", vn, sa);
// If the varnode is in the unique space, shift its offset up by -sa- bits
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);
// Shift the offset up by -sa- bits for any varnode used by this -op- in the unique space
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);
// 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() &&
@ -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);
// Shift the offset up by -sa- bits, for any varnode in the unique space associated with this template
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
// 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
@ -1623,7 +1660,7 @@ public class SleighCompile extends SleighBase {
setUniqueBase(ubase);
}
void checkFieldUsage() {
private void checkFieldUsage() {
if (warnunusedfields) {
VectorSTL<SleighSymbol> unsoughtSymbols = symtab.getUnsoughtSymbols();
IteratorSTL<SleighSymbol> siter;
@ -1718,6 +1755,93 @@ public class SleighCompile extends SleighBase {
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
* compiler without using the launcher. The full SoftwareModeling classpath

View file

@ -17,24 +17,17 @@ package ghidra.pcodeCPort.slgh_compile;
import java.io.*;
import java.util.*;
import java.util.Map.Entry;
import org.antlr.runtime.*;
import org.antlr.runtime.tree.CommonTreeNodeStream;
import org.antlr.runtime.RecognitionException;
import org.jdom.JDOMException;
import generic.jar.ResourceFile;
import generic.stl.IteratorSTL;
import ghidra.GhidraApplicationLayout;
import ghidra.GhidraLaunchable;
import ghidra.framework.Application;
import ghidra.framework.ApplicationConfiguration;
import ghidra.pcodeCPort.context.SleighError;
import ghidra.sleigh.grammar.*;
import ghidra.util.Msg;
import ghidra.util.SystemUtilities;
import utilities.util.FileResolutionResult;
import utilities.util.FileUtilities;
/**
* <code>SleighCompileLauncher</code> Sleigh compiler launch provider
@ -46,24 +39,6 @@ public class SleighCompileLauncher implements GhidraLaunchable {
private static final FileFilter SLASPEC_FILTER =
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
public void launch(GhidraApplicationLayout layout, String[] args)
throws JDOMException, IOException, RecognitionException {
@ -80,9 +55,9 @@ public class SleighCompileLauncher implements GhidraLaunchable {
*
* @param args sleigh compiler command line arguments
* @return exit code (TODO: exit codes are not well defined)
* @throws JDOMException
* @throws IOException
* @throws RecognitionException
* @throws JDOMException for XML errors
* @throws IOException for file access errors
* @throws RecognitionException for parse errors
*/
public static int runMain(String[] args)
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, " -f print warnings for unused token fields");
Msg.info(SleighCompile.class, " -o print warnings for temporaries which are too large");
Msg.info(SleighCompile.class, " -s treat register names as case sensitive");
Msg.info(SleighCompile.class, " -DNAME=VALUE defines a preprocessor macro NAME with value VALUE (option may be repeated)");
Msg.info(SleighCompile.class, " -dMODULE defines a preprocessor macro MODULE with a value of its module path (option may be repeated)");
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 unusedFieldWarning = false;
boolean largeTemporaryWarning = false;
boolean caseSensitiveRegisterNames = false;
int i;
for (i = 0; i < args.length; ++i) {
@ -191,6 +168,9 @@ public class SleighCompileLauncher implements GhidraLaunchable {
else if (args[i].charAt(1) == 'o') {
largeTemporaryWarning = true;
}
else if (args[i].charAt(1) == 's') {
caseSensitiveRegisterNames = true;
}
else if (args[i].charAt(1) == 'x') {
SleighCompile.yydebug = true; // Debug option
}
@ -223,14 +203,14 @@ public class SleighCompileLauncher implements GhidraLaunchable {
for (File input : visitor) {
System.out.println("Compiling " + input + ":");
SleighCompile compiler = new SleighCompile();
initCompiler(compiler, preprocs, unnecessaryPcodeWarning, lenientConflict,
compiler.setAllOptions(preprocs, unnecessaryPcodeWarning, lenientConflict,
allCollisionWarning, allNopWarning, deadTempWarning, unusedFieldWarning,
enforceLocalKeyWord, largeTemporaryWarning);
enforceLocalKeyWord, largeTemporaryWarning, caseSensitiveRegisterNames);
String outname = input.getName().replace(".slaspec", ".sla");
File output = new File(input.getParent(), outname);
retval =
run_compilation(input.getAbsolutePath(), output.getAbsolutePath(), compiler);
compiler.run_compilation(input.getAbsolutePath(), output.getAbsolutePath());
System.out.println();
if (retval != 0) {
++totalFailures;
@ -252,9 +232,9 @@ public class SleighCompileLauncher implements GhidraLaunchable {
// single file compile
SleighCompile compiler = new SleighCompile();
initCompiler(compiler, preprocs, unnecessaryPcodeWarning, lenientConflict,
compiler.setAllOptions(preprocs, unnecessaryPcodeWarning, lenientConflict,
allCollisionWarning, allNopWarning, deadTempWarning, unusedFieldWarning,
enforceLocalKeyWord, largeTemporaryWarning);
enforceLocalKeyWord, largeTemporaryWarning, caseSensitiveRegisterNames);
if (i == args.length) {
Msg.error(SleighCompile.class, "Missing input file name");
return 1;
@ -280,7 +260,7 @@ public class SleighCompileLauncher implements GhidraLaunchable {
}
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) {
@ -326,131 +306,4 @@ public class SleighCompileLauncher implements GhidraLaunchable {
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;
}
}

View file

@ -220,8 +220,6 @@ public abstract class Translate implements BasicSpaceProvider {
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 String getRegisterName(AddrSpace base, long off, int size);
@ -293,15 +291,6 @@ public abstract class Translate implements BasicSpaceProvider {
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
// 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
@ -542,8 +531,8 @@ public abstract class Translate implements BasicSpaceProvider {
public AddrSpace getSpaceBySpacebase(Address loc, int size) { // Get space associated with spacebase register
AddrSpace id;
for (int i = 0; i < baselist.size(); ++i) {
id = baselist.get(i);
for (AddrSpace element : baselist) {
id = element;
int numspace = numSpacebase(id);
for (int j = 0; j < numspace; ++j) {
VarnodeData point = getSpacebase(id, j);