mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 18:29:37 +02:00
GP-4285 Compressed SLEIGH
This commit is contained in:
parent
b380fd5fa6
commit
8fbd171cdf
207 changed files with 15233 additions and 6055 deletions
|
@ -19,21 +19,18 @@
|
|||
*/
|
||||
package ghidra.app.plugin.processors.sleigh;
|
||||
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.symbol.*;
|
||||
import ghidra.app.plugin.processors.sleigh.template.ConstructTpl;
|
||||
import ghidra.app.plugin.processors.sleigh.template.HandleTpl;
|
||||
import ghidra.program.model.lang.UnknownInstructionException;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.xml.SpecXmlUtils;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
import ghidra.program.model.pcode.Decoder;
|
||||
import ghidra.program.model.pcode.DecoderException;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* The primary sleigh concept representing a semantic action
|
||||
* taking operands (semantic values) as input
|
||||
* producing a semantic value as output
|
||||
|
@ -313,65 +310,59 @@ public class Constructor implements Comparable<Constructor> {
|
|||
return null;
|
||||
}
|
||||
|
||||
public void restoreXml(XmlPullParser parser, SleighLanguage sleigh)
|
||||
throws UnknownInstructionException {
|
||||
XmlElement el = parser.start("constructor");
|
||||
public void decode(Decoder decoder, SleighLanguage sleigh) throws DecoderException {
|
||||
int el = decoder.openElement(ELEM_CONSTRUCTOR);
|
||||
SymbolTable symtab = sleigh.getSymbolTable();
|
||||
|
||||
int myId = SpecXmlUtils.decodeInt(el.getAttribute("parent"));
|
||||
int myId = (int) decoder.readUnsignedInteger(ATTRIB_PARENT);
|
||||
parent = (SubtableSymbol) symtab.findSymbol(myId);
|
||||
firstwhitespace = SpecXmlUtils.decodeInt(el.getAttribute("first"));
|
||||
minimumlength = SpecXmlUtils.decodeInt(el.getAttribute("length"));
|
||||
String sourceAndLine = el.getAttribute("line");
|
||||
String[] parts = sourceAndLine.split(":");
|
||||
if (parts.length != 2) {
|
||||
Msg.error(this, "Bad line attribute in .sla file");
|
||||
lineno = -1;
|
||||
sourceFile = "UNKNOWN";
|
||||
}
|
||||
else {
|
||||
lineno = Integer.parseInt(parts[1].trim());
|
||||
sourceFile = sleigh.getSourceFileIndexer().getFileName(Integer.parseInt(parts[0].trim()));
|
||||
}
|
||||
firstwhitespace = (int) decoder.readSignedInteger(ATTRIB_FIRST);
|
||||
minimumlength = (int) decoder.readSignedInteger(ATTRIB_LENGTH);
|
||||
int srcLine = (int) decoder.readSignedInteger(ATTRIB_SOURCE);
|
||||
lineno = (int) decoder.readSignedInteger(ATTRIB_LINE);
|
||||
sourceFile = sleigh.getSourceFileIndexer().getFileName(srcLine);
|
||||
|
||||
ArrayList<Object> oplist = new ArrayList<>();
|
||||
ArrayList<Object> piecelist = new ArrayList<>();
|
||||
ArrayList<Object> coplist = new ArrayList<>();
|
||||
XmlElement subel = parser.peek();
|
||||
while (!subel.getName().equals("constructor")) {
|
||||
if (subel.getName().equals("oper")) {
|
||||
myId = SpecXmlUtils.decodeInt(subel.getAttribute("id"));
|
||||
int subel = decoder.peekElement();
|
||||
while (subel != 0) {
|
||||
if (subel == ELEM_OPER.id()) {
|
||||
decoder.openElement();
|
||||
myId = (int) decoder.readUnsignedInteger(ATTRIB_ID);
|
||||
oplist.add(symtab.findSymbol(myId));
|
||||
parser.discardSubTree();
|
||||
decoder.closeElementSkipping(subel);
|
||||
}
|
||||
else if (subel.getName().equals("print")) {
|
||||
piecelist.add(subel.getAttribute("piece"));
|
||||
parser.discardSubTree();
|
||||
else if (subel == ELEM_PRINT.id()) {
|
||||
decoder.openElement();
|
||||
piecelist.add(decoder.readString(ATTRIB_PIECE));
|
||||
decoder.closeElementSkipping(subel);
|
||||
}
|
||||
else if (subel.getName().equals("opprint")) {
|
||||
myId = SpecXmlUtils.decodeInt(subel.getAttribute("id"));
|
||||
else if (subel == ELEM_OPPRINT.id()) {
|
||||
decoder.openElement();
|
||||
myId = (int) decoder.readSignedInteger(ATTRIB_ID);
|
||||
String operstring = "\n";
|
||||
char ind = (char) ('A' + myId);
|
||||
operstring += ind;
|
||||
piecelist.add(operstring);
|
||||
parser.discardSubTree();
|
||||
decoder.closeElementSkipping(subel);
|
||||
}
|
||||
else if (subel.getName().equals("context_op")) {
|
||||
else if (subel == ELEM_CONTEXT_OP.id()) {
|
||||
ContextOp c_op = new ContextOp();
|
||||
c_op.restoreXml(parser, sleigh);
|
||||
c_op.decode(decoder, sleigh);
|
||||
coplist.add(c_op);
|
||||
}
|
||||
else if (subel.getName().equals("commit")) {
|
||||
else if (subel == ELEM_COMMIT.id()) {
|
||||
ContextCommit c_op = new ContextCommit();
|
||||
c_op.restoreXml(parser, sleigh);
|
||||
c_op.decode(decoder, sleigh);
|
||||
coplist.add(c_op);
|
||||
}
|
||||
else {
|
||||
ConstructTpl curtempl = new ConstructTpl();
|
||||
int sectionid = curtempl.restoreXml(parser, sleigh.getAddressFactory());
|
||||
int sectionid = curtempl.decode(decoder);
|
||||
if (sectionid < 0) {
|
||||
if (templ != null) {
|
||||
throw new UnknownInstructionException("Duplicate main template section");
|
||||
throw new DecoderException("Duplicate main template section");
|
||||
}
|
||||
templ = curtempl;
|
||||
}
|
||||
|
@ -383,12 +374,12 @@ public class Constructor implements Comparable<Constructor> {
|
|||
namedtempl.add(null);
|
||||
}
|
||||
if (namedtempl.get(sectionid) != null) {
|
||||
throw new UnknownInstructionException("Duplicate named template section");
|
||||
throw new DecoderException("Duplicate named template section");
|
||||
}
|
||||
namedtempl.set(sectionid, curtempl);
|
||||
}
|
||||
}
|
||||
subel = parser.peek();
|
||||
subel = decoder.peekElement();
|
||||
}
|
||||
operands = new OperandSymbol[oplist.size()];
|
||||
separators = new String[operands.length + 1];
|
||||
|
@ -404,7 +395,7 @@ public class Constructor implements Comparable<Constructor> {
|
|||
else {
|
||||
flowthruindex = -1;
|
||||
}
|
||||
parser.end(el);
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -432,10 +423,6 @@ public class Constructor implements Comparable<Constructor> {
|
|||
return res;
|
||||
}
|
||||
|
||||
/* ***************************** *
|
||||
* Get these working as map keys *
|
||||
* ***************************** */
|
||||
|
||||
@Override
|
||||
public int compareTo(Constructor that) {
|
||||
int result;
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -17,9 +16,11 @@
|
|||
package ghidra.app.plugin.processors.sleigh;
|
||||
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
import ghidra.program.model.pcode.Decoder;
|
||||
import ghidra.program.model.pcode.DecoderException;
|
||||
|
||||
public interface ContextChange {
|
||||
void apply(ParserWalker walker, SleighDebugLogger debug) throws MemoryAccessException;
|
||||
void restoreXml(XmlPullParser parser,SleighLanguage lang);
|
||||
|
||||
void decode(Decoder decoder, SleighLanguage lang) throws DecoderException;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -16,11 +15,12 @@
|
|||
*/
|
||||
package ghidra.app.plugin.processors.sleigh;
|
||||
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.symbol.TripleSymbol;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.util.xml.SpecXmlUtils;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
import ghidra.program.model.pcode.Decoder;
|
||||
import ghidra.program.model.pcode.DecoderException;
|
||||
|
||||
public class ContextCommit implements ContextChange {
|
||||
|
||||
|
@ -32,6 +32,7 @@ public class ContextCommit implements ContextChange {
|
|||
sym = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply(ParserWalker walker, SleighDebugLogger debug) throws MemoryAccessException {
|
||||
walker.getParserContext().addCommit(walker.getState(), sym, num, mask);
|
||||
if (debug != null) {
|
||||
|
@ -40,13 +41,14 @@ public class ContextCommit implements ContextChange {
|
|||
}
|
||||
}
|
||||
|
||||
public void restoreXml(XmlPullParser parser, SleighLanguage lang) {
|
||||
XmlElement el = parser.start("commit");
|
||||
int id = SpecXmlUtils.decodeInt(el.getAttribute("id"));
|
||||
@Override
|
||||
public void decode(Decoder decoder, SleighLanguage lang) throws DecoderException {
|
||||
int el = decoder.openElement(ELEM_COMMIT);
|
||||
int id = (int) decoder.readUnsignedInteger(ATTRIB_ID);
|
||||
sym = (TripleSymbol) lang.getSymbolTable().findSymbol(id);
|
||||
num = SpecXmlUtils.decodeInt(el.getAttribute("num"));
|
||||
mask = SpecXmlUtils.decodeInt(el.getAttribute("mask"));
|
||||
parser.end(el);
|
||||
num = (int) decoder.readSignedInteger(ATTRIB_NUMBER);
|
||||
mask = (int) decoder.readUnsignedInteger(ATTRIB_MASK);
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -19,16 +19,15 @@
|
|||
*/
|
||||
package ghidra.app.plugin.processors.sleigh;
|
||||
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.expression.PatternExpression;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.program.model.pcode.Decoder;
|
||||
import ghidra.program.model.pcode.DecoderException;
|
||||
import ghidra.util.NumericUtilities;
|
||||
import ghidra.util.xml.SpecXmlUtils;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* An operation on the context (bit-packed form) of an instruction
|
||||
*/
|
||||
public class ContextOp implements ContextChange {
|
||||
|
@ -51,13 +50,13 @@ public class ContextOp implements ContextChange {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void restoreXml(XmlPullParser parser, SleighLanguage lang) {
|
||||
XmlElement el = parser.start("context_op");
|
||||
num = SpecXmlUtils.decodeInt(el.getAttribute("i"));
|
||||
shift = SpecXmlUtils.decodeInt(el.getAttribute("shift"));
|
||||
mask = SpecXmlUtils.decodeInt(el.getAttribute("mask"));
|
||||
patexp = PatternExpression.restoreExpression(parser, lang);
|
||||
parser.end(el);
|
||||
public void decode(Decoder decoder, SleighLanguage lang) throws DecoderException {
|
||||
int el = decoder.openElement(ELEM_CONTEXT_OP);
|
||||
num = (int) decoder.readSignedInteger(ATTRIB_I);
|
||||
shift = (int) decoder.readSignedInteger(ATTRIB_SHIFT);
|
||||
mask = (int) decoder.readUnsignedInteger(ATTRIB_MASK);
|
||||
patexp = PatternExpression.decodeExpression(decoder, lang);
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
|
||||
public PatternExpression getPatternExpression() {
|
||||
|
|
|
@ -19,11 +19,9 @@
|
|||
*/
|
||||
package ghidra.app.plugin.processors.sleigh;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.pattern.DisjointPattern;
|
||||
import ghidra.app.plugin.processors.sleigh.pattern.PatternBlock;
|
||||
|
@ -31,13 +29,10 @@ import ghidra.app.plugin.processors.sleigh.symbol.SubtableSymbol;
|
|||
import ghidra.program.model.lang.UnknownInstructionException;
|
||||
import ghidra.program.model.mem.MemBuffer;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.util.xml.SpecXmlUtils;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
import ghidra.program.model.pcode.Decoder;
|
||||
import ghidra.program.model.pcode.DecoderException;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* A node in the decision tree for resolving a Constructor in
|
||||
* a SubtableSymbol based on the InstructionContext
|
||||
*/
|
||||
|
@ -224,33 +219,33 @@ public class DecisionNode {
|
|||
// }
|
||||
// }
|
||||
|
||||
public void restoreXml(XmlPullParser parser, DecisionNode par, SubtableSymbol sub) {
|
||||
XmlElement el = parser.start("decision");
|
||||
// parent = par;
|
||||
// num = SpecXmlUtils.decodeInt(el.getAttributeValue("number"));
|
||||
contextdecision = SpecXmlUtils.decodeBoolean(el.getAttribute("context"));
|
||||
startbit = SpecXmlUtils.decodeInt(el.getAttribute("start"));
|
||||
bitsize = SpecXmlUtils.decodeInt(el.getAttribute("size"));
|
||||
public void decode(Decoder decoder, DecisionNode par, SubtableSymbol sub)
|
||||
throws DecoderException {
|
||||
int el = decoder.openElement(ELEM_DECISION);
|
||||
|
||||
contextdecision = decoder.readBool(ATTRIB_CONTEXT);
|
||||
startbit = (int) decoder.readSignedInteger(ATTRIB_STARTBIT);
|
||||
bitsize = (int) decoder.readSignedInteger(ATTRIB_SIZE);
|
||||
|
||||
ArrayList<Object> patlist = new ArrayList<>();
|
||||
ArrayList<Object> conlist = new ArrayList<>();
|
||||
ArrayList<Object> childlist = new ArrayList<>();
|
||||
// num = 0;
|
||||
XmlElement subel = parser.peek();
|
||||
while (!subel.isEnd()) {
|
||||
if (subel.getName().equals("pair")) {
|
||||
XmlElement start = parser.start();
|
||||
int id = SpecXmlUtils.decodeInt(subel.getAttribute("id"));
|
||||
int subel = decoder.peekElement();
|
||||
while (subel != 0) {
|
||||
if (subel == ELEM_PAIR.id()) {
|
||||
decoder.openElement();
|
||||
int id = (int) decoder.readSignedInteger(ATTRIB_ID);
|
||||
conlist.add(sub.getConstructor(id));
|
||||
patlist.add(DisjointPattern.restoreDisjoint(parser));
|
||||
parser.end(start);
|
||||
patlist.add(DisjointPattern.decodeDisjoint(decoder));
|
||||
decoder.closeElement(subel);
|
||||
}
|
||||
else if (subel.getName().equals("decision")) {
|
||||
else if (subel == ELEM_DECISION.id()) {
|
||||
DecisionNode subnode = new DecisionNode();
|
||||
subnode.restoreXml(parser, this, sub);
|
||||
subnode.decode(decoder, this, sub);
|
||||
childlist.add(subnode);
|
||||
}
|
||||
subel = parser.peek();
|
||||
subel = decoder.peekElement();
|
||||
}
|
||||
patternlist = new DisjointPattern[patlist.size()];
|
||||
patlist.toArray(patternlist);
|
||||
|
@ -258,7 +253,7 @@ public class DecisionNode {
|
|||
conlist.toArray(constructlist);
|
||||
children = new DecisionNode[childlist.size()];
|
||||
childlist.toArray(children);
|
||||
parser.end(el);
|
||||
decoder.closeElement(el);
|
||||
|
||||
unmodifiablePatternList = Collections.unmodifiableList(Arrays.asList(patternlist));
|
||||
unmodifiableConstructorList = Collections.unmodifiableList(Arrays.asList(constructlist));
|
||||
|
|
|
@ -15,8 +15,7 @@
|
|||
*/
|
||||
package ghidra.app.plugin.processors.sleigh;
|
||||
|
||||
import static ghidra.program.model.pcode.AttributeId.*;
|
||||
import static ghidra.program.model.pcode.ElementId.*;
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import java.io.*;
|
||||
import java.math.BigInteger;
|
||||
|
@ -26,7 +25,6 @@ import java.util.regex.Matcher;
|
|||
import java.util.regex.Pattern;
|
||||
|
||||
import org.antlr.runtime.RecognitionException;
|
||||
import org.jdom.JDOMException;
|
||||
import org.xml.sax.*;
|
||||
|
||||
import generic.jar.ResourceFile;
|
||||
|
@ -36,15 +34,14 @@ import ghidra.app.plugin.processors.sleigh.expression.ContextField;
|
|||
import ghidra.app.plugin.processors.sleigh.expression.PatternValue;
|
||||
import ghidra.app.plugin.processors.sleigh.symbol.*;
|
||||
import ghidra.framework.Application;
|
||||
import ghidra.pcodeCPort.sleighbase.SleighBase;
|
||||
import ghidra.pcode.utils.SlaFormat;
|
||||
import ghidra.pcodeCPort.slgh_compile.SleighCompileLauncher;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.lang.*;
|
||||
import ghidra.program.model.listing.DefaultProgramContext;
|
||||
import ghidra.program.model.mem.MemBuffer;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.program.model.pcode.ElementId;
|
||||
import ghidra.program.model.pcode.Encoder;
|
||||
import ghidra.program.model.pcode.*;
|
||||
import ghidra.program.model.util.ProcessorSymbolType;
|
||||
import ghidra.sleigh.grammar.SleighPreprocessor;
|
||||
import ghidra.sleigh.grammar.SourceFileIndexer;
|
||||
|
@ -57,15 +54,6 @@ import utilities.util.FileUtilities;
|
|||
|
||||
public class SleighLanguage implements Language {
|
||||
|
||||
/**
|
||||
* SLA_FORMAT_VERSION will be incremented whenever the format of the .sla
|
||||
* files change.
|
||||
* <p>
|
||||
* Version 3: January 2021: added source file information for each constructor. <br>
|
||||
* Version 2: April 2019: Changed numbering of Overlay spaces.<br>
|
||||
* Version 1: Initial version.<br>
|
||||
*/
|
||||
public static final int SLA_FORMAT_VERSION = SleighBase.SLA_FORMAT_VERSION;
|
||||
private Map<CompilerSpecID, SleighCompilerSpecDescription> compilerSpecDescriptions;
|
||||
private HashMap<CompilerSpecID, BasicCompilerSpec> compilerSpecs;
|
||||
private List<InjectPayloadSleigh> additionalInject = null;
|
||||
|
@ -112,7 +100,7 @@ public class SleighLanguage implements Language {
|
|||
SortedMap<String, ManualEntry> manual = null;
|
||||
|
||||
SleighLanguage(SleighLanguageDescription description)
|
||||
throws SAXException, IOException, UnknownInstructionException {
|
||||
throws DecoderException, SAXException, IOException {
|
||||
initialize(description);
|
||||
}
|
||||
|
||||
|
@ -124,7 +112,7 @@ public class SleighLanguage implements Language {
|
|||
}
|
||||
|
||||
private void initialize(SleighLanguageDescription langDescription)
|
||||
throws SAXException, IOException, UnknownInstructionException {
|
||||
throws DecoderException, SAXException, IOException {
|
||||
this.defaultSymbols = new ArrayList<>();
|
||||
this.compilerSpecDescriptions = new LinkedHashMap<>();
|
||||
for (CompilerSpecDescription compilerSpecDescription : langDescription
|
||||
|
@ -151,7 +139,8 @@ public class SleighLanguage implements Language {
|
|||
}
|
||||
|
||||
// Read in the sleigh specification
|
||||
readSpecification(slaFile);
|
||||
PackedDecode decoder = SlaFormat.buildDecoder(slaFile);
|
||||
decode(decoder);
|
||||
|
||||
registerBuilder = new RegisterBuilder();
|
||||
loadRegisters(registerBuilder);
|
||||
|
@ -177,42 +166,12 @@ public class SleighLanguage implements Language {
|
|||
}
|
||||
|
||||
private boolean isSLAWrongVersion(ResourceFile slaFile) {
|
||||
XmlPullParser parser = null;
|
||||
try {
|
||||
parser = XmlPullParserFactory.create(slaFile, new ErrorHandler() {
|
||||
|
||||
@Override
|
||||
public void warning(SAXParseException exception) throws SAXException {
|
||||
// ignore
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fatalError(SAXParseException exception) throws SAXException {
|
||||
throw exception;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(SAXParseException exception) throws SAXException {
|
||||
throw exception;
|
||||
}
|
||||
}, false);
|
||||
|
||||
XmlElement e = parser.peek();
|
||||
if (!"sleigh".equals(e.getName())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
int version = SpecXmlUtils.decodeInt(e.getAttribute("version"));
|
||||
return (version != SLA_FORMAT_VERSION);
|
||||
try (InputStream stream = slaFile.getInputStream()) {
|
||||
return !SlaFormat.isSlaFormat(stream);
|
||||
}
|
||||
catch (SAXException | IOException e) {
|
||||
catch (Exception e) {
|
||||
return true;
|
||||
}
|
||||
finally {
|
||||
if (parser != null) {
|
||||
parser.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isSLAStale(ResourceFile slaFile) {
|
||||
|
@ -521,9 +480,6 @@ public class SleighLanguage implements Language {
|
|||
" -- please check log messages for details");
|
||||
}
|
||||
}
|
||||
catch (JDOMException e) {
|
||||
throw new IOException("JDOMException error recompiling: " + e.getMessage());
|
||||
}
|
||||
catch (RecognitionException e) {
|
||||
throw new IOException("RecognitionException error recompiling: " + e.getMessage());
|
||||
}
|
||||
|
@ -533,10 +489,10 @@ public class SleighLanguage implements Language {
|
|||
try {
|
||||
initialize(description);
|
||||
}
|
||||
catch (SAXException e) {
|
||||
catch (DecoderException e) {
|
||||
throw new IOException(e.getMessage());
|
||||
}
|
||||
catch (UnknownInstructionException e) {
|
||||
catch (SAXException e) {
|
||||
throw new IOException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
@ -907,96 +863,104 @@ public class SleighLanguage implements Language {
|
|||
}
|
||||
}
|
||||
|
||||
private void readSpecification(final ResourceFile sleighfile)
|
||||
throws SAXException, IOException, UnknownInstructionException {
|
||||
ErrorHandler errHandler = new ErrorHandler() {
|
||||
@Override
|
||||
public void error(SAXParseException exception) throws SAXException {
|
||||
Msg.error(SleighLanguage.this, "Error parsing " + sleighfile, exception);
|
||||
private void decode(Decoder decoder) throws DecoderException {
|
||||
int el = decoder.openElement(ELEM_SLEIGH);
|
||||
int version = 0;
|
||||
uniqueBase = 0;
|
||||
alignment = 1;
|
||||
uniqueAllocateMask = 0; // Default mask is 0
|
||||
numSections = 0;
|
||||
boolean isBigEndian = false;
|
||||
int attrib = decoder.getNextAttributeId();
|
||||
while (attrib != 0) {
|
||||
if (attrib == ATTRIB_VERSION.id()) {
|
||||
version = (int) decoder.readSignedInteger();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fatalError(SAXParseException exception) throws SAXException {
|
||||
Msg.error(SleighLanguage.this, "Fatal error parsing " + sleighfile, exception);
|
||||
else if (attrib == ATTRIB_BIGENDIAN.id()) {
|
||||
isBigEndian = decoder.readBool();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void warning(SAXParseException exception) throws SAXException {
|
||||
Msg.warn(SleighLanguage.this, "Warning parsing " + sleighfile, exception);
|
||||
else if (attrib == ATTRIB_UNIQBASE.id()) {
|
||||
uniqueBase = decoder.readUnsignedInteger();
|
||||
}
|
||||
};
|
||||
XmlPullParser parser = XmlPullParserFactory.create(sleighfile, errHandler, false);
|
||||
try {
|
||||
restoreXml(parser);
|
||||
else if (attrib == ATTRIB_ALIGN.id()) {
|
||||
alignment = (int) decoder.readSignedInteger();
|
||||
}
|
||||
else if (attrib == ATTRIB_UNIQMASK.id()) {
|
||||
uniqueAllocateMask = (int) decoder.readUnsignedInteger();
|
||||
}
|
||||
else if (attrib == ATTRIB_NUMSECTIONS.id()) {
|
||||
numSections = (int) decoder.readUnsignedInteger();
|
||||
}
|
||||
attrib = decoder.getNextAttributeId();
|
||||
}
|
||||
finally {
|
||||
parser.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private void restoreXml(XmlPullParser parser) throws UnknownInstructionException {
|
||||
XmlElement el = parser.start("sleigh");
|
||||
int version = SpecXmlUtils.decodeInt(el.getAttribute("version"));
|
||||
if (version != SLA_FORMAT_VERSION) {
|
||||
if (version != FORMAT_VERSION) {
|
||||
throw new SleighException(".sla file for " + getLanguageID() + " has the wrong format");
|
||||
}
|
||||
String endianAttr = el.getAttribute("bigendian");
|
||||
Endian slaEndian = SpecXmlUtils.decodeBoolean(endianAttr) ? Endian.BIG : Endian.LITTLE;
|
||||
Endian slaEndian = isBigEndian ? Endian.BIG : Endian.LITTLE;
|
||||
Endian ldefEndian = description.getEndian();
|
||||
Endian instEndian = description.getInstructionEndian();
|
||||
if (slaEndian != ldefEndian && instEndian == ldefEndian) {
|
||||
throw new SleighException(".ldefs says " + getLanguageID() + " is " + ldefEndian +
|
||||
" but .sla says " + slaEndian);
|
||||
}
|
||||
uniqueBase = SpecXmlUtils.decodeLong(el.getAttribute("uniqbase"));
|
||||
alignment = SpecXmlUtils.decodeInt(el.getAttribute("align"));
|
||||
uniqueAllocateMask = 0; // Default mask is 0
|
||||
String uniqmaskstr = el.getAttribute("uniqmask");
|
||||
if (uniqmaskstr != null) {
|
||||
uniqueAllocateMask = SpecXmlUtils.decodeInt(uniqmaskstr);
|
||||
}
|
||||
String numsecstr = el.getAttribute("numsections");
|
||||
if (numsecstr != null) {
|
||||
numSections = SpecXmlUtils.decodeInt(numsecstr);
|
||||
}
|
||||
indexer = new SourceFileIndexer();
|
||||
indexer.restoreXml(parser);
|
||||
parseSpaces(parser);
|
||||
indexer.decode(decoder);
|
||||
parseSpaces(decoder);
|
||||
symtab = new SymbolTable();
|
||||
symtab.restoreXml(parser, this);
|
||||
symtab.decode(decoder, this);
|
||||
root =
|
||||
((SubtableSymbol) symtab.getGlobalScope().findSymbol("instruction")).getDecisionNode();
|
||||
parser.end(el);
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
|
||||
private void parseSpaces(XmlPullParser parser) {
|
||||
private void parseSpaces(Decoder decoder) throws DecoderException {
|
||||
Set<String> truncatedSpaceNames = description.getTruncatedSpaceNames();
|
||||
int truncatedSpaceCnt = truncatedSpaceNames.size();
|
||||
XmlElement el = parser.start("spaces");
|
||||
String defname = el.getAttribute("defaultspace");
|
||||
int el = decoder.openElement(ELEM_SPACES);
|
||||
String defname = decoder.readString(ATTRIB_DEFAULTSPACE);
|
||||
spacetable = new LinkedHashMap<>();
|
||||
// Slot zero is always the constant space
|
||||
AddressSpace constspc = new GenericAddressSpace(SpaceNames.CONSTANT_SPACE_NAME, 64,
|
||||
AddressSpace.TYPE_CONSTANT, SpaceNames.CONSTANT_SPACE_INDEX);
|
||||
spacetable.put(SpaceNames.CONSTANT_SPACE_NAME, constspc);
|
||||
default_space = null;
|
||||
XmlElement subel = parser.peek();
|
||||
if (subel.getName().equals("space_other")) { // tag must be present
|
||||
parser.discardSubTree(); // We don't process it
|
||||
int subel = decoder.peekElement();
|
||||
if (subel == ELEM_SPACE_OTHER.id()) { // tag must be present
|
||||
decoder.openElement();
|
||||
decoder.closeElementSkipping(subel); // We don't process it
|
||||
// Instead the ProgramAddressFactory maps in the static OTHER_SPACE automatically
|
||||
}
|
||||
else {
|
||||
throw new SleighException(".sla file missing required OTHER space tag");
|
||||
}
|
||||
while ((subel = parser.softStart("space", "space_unique")) != null) {
|
||||
String name = subel.getAttribute("name");
|
||||
int index = SpecXmlUtils.decodeInt(subel.getAttribute("index"));
|
||||
String typename = subel.getName();
|
||||
int delay = SpecXmlUtils.decodeInt(subel.getAttribute("delay"));
|
||||
int size = SpecXmlUtils.decodeInt(subel.getAttribute("size"));
|
||||
|
||||
int type = AddressSpace.TYPE_UNKNOWN;
|
||||
if (typename.equals("space")) {
|
||||
while (decoder.peekElement() != 0) {
|
||||
int wordsize = 1;
|
||||
String name = null;
|
||||
int index = 0;
|
||||
int delay = -1;
|
||||
int size = 0;
|
||||
subel = decoder.openElement();
|
||||
int attrib = decoder.getNextAttributeId();
|
||||
while (attrib != 0) {
|
||||
if (attrib == ATTRIB_NAME.id()) {
|
||||
name = decoder.readString();
|
||||
}
|
||||
else if (attrib == ATTRIB_INDEX.id()) {
|
||||
index = (int) decoder.readSignedInteger();
|
||||
}
|
||||
else if (attrib == ATTRIB_DELAY.id()) {
|
||||
delay = (int) decoder.readSignedInteger();
|
||||
}
|
||||
else if (attrib == ATTRIB_SIZE.id()) {
|
||||
size = (int) decoder.readSignedInteger();
|
||||
}
|
||||
else if (attrib == ATTRIB_WORDSIZE.id()) {
|
||||
wordsize = (int) decoder.readSignedInteger();
|
||||
}
|
||||
attrib = decoder.getNextAttributeId();
|
||||
}
|
||||
int type;
|
||||
if (subel == ELEM_SPACE.id()) {
|
||||
if (delay > 0) {
|
||||
type = AddressSpace.TYPE_RAM;
|
||||
}
|
||||
|
@ -1004,19 +968,13 @@ public class SleighLanguage implements Language {
|
|||
type = AddressSpace.TYPE_REGISTER;
|
||||
}
|
||||
}
|
||||
else if (typename.equals("space_unique")) {
|
||||
else if (subel == ELEM_SPACE_UNIQUE.id()) {
|
||||
type = AddressSpace.TYPE_UNIQUE;
|
||||
}
|
||||
if (type == AddressSpace.TYPE_UNKNOWN) {
|
||||
else {
|
||||
throw new SleighException("Sleigh cannot match new space definition to old type");
|
||||
}
|
||||
|
||||
String wSizeString = subel.getAttribute("wordsize");
|
||||
int wordsize = 1;
|
||||
if (wSizeString != null) {
|
||||
wordsize = SpecXmlUtils.decodeInt(wSizeString);
|
||||
}
|
||||
|
||||
boolean truncateSpace = truncatedSpaceNames.contains(name);
|
||||
if (truncateSpace && type != AddressSpace.TYPE_RAM) {
|
||||
throw new SleighException("Non-ram space does not support truncation: " + name);
|
||||
|
@ -1048,7 +1006,7 @@ public class SleighLanguage implements Language {
|
|||
spc = new GenericAddressSpace(name, 8 * size, wordsize, type, index);
|
||||
}
|
||||
spacetable.put(name, spc);
|
||||
parser.end(subel);
|
||||
decoder.closeElement(subel);
|
||||
}
|
||||
if (truncatedSpaceCnt > 0) {
|
||||
throw new SleighException(
|
||||
|
@ -1058,7 +1016,8 @@ public class SleighLanguage implements Language {
|
|||
defaultDataSpace = default_space;
|
||||
defaultPointerWordSize = defaultDataSpace.getAddressableUnitSize();
|
||||
buildAddressSpaceFactory();
|
||||
parser.end(el);
|
||||
decoder.closeElement(el);
|
||||
decoder.setAddressFactory(addressFactory);
|
||||
}
|
||||
|
||||
void buildAddressSpaceFactory() {
|
||||
|
@ -1454,11 +1413,16 @@ public class SleighLanguage implements Language {
|
|||
throws IOException {
|
||||
AddressSpace[] spclist = factory.getAllAddressSpaces();
|
||||
|
||||
encoder.openElement(ELEM_SLEIGH);
|
||||
encoder.writeBool(ATTRIB_BIGENDIAN, isBigEndian());
|
||||
encoder.writeUnsignedInteger(ATTRIB_UNIQBASE, uniqueOffset);
|
||||
encoder.openElement(ELEM_SPACES);
|
||||
encoder.writeString(ATTRIB_DEFAULTSPACE, factory.getDefaultAddressSpace().getName());
|
||||
// WARNING
|
||||
// ELEM_ and ATTRIB_ symbols in this method all come from the AttributeId and ElementId
|
||||
// namespace, some of which conflict with other ELEM_ and ATTRIB_ symbols used in this file
|
||||
|
||||
encoder.openElement(ElementId.ELEM_SLEIGH);
|
||||
encoder.writeBool(AttributeId.ATTRIB_BIGENDIAN, isBigEndian());
|
||||
encoder.writeUnsignedInteger(AttributeId.ATTRIB_UNIQBASE, uniqueOffset);
|
||||
encoder.openElement(ElementId.ELEM_SPACES);
|
||||
encoder.writeString(AttributeId.ATTRIB_DEFAULTSPACE,
|
||||
factory.getDefaultAddressSpace().getName());
|
||||
|
||||
ElementId tag;
|
||||
int delay;
|
||||
|
@ -1467,31 +1431,31 @@ public class SleighLanguage implements Language {
|
|||
for (AddressSpace element : spclist) {
|
||||
if ((element instanceof OverlayAddressSpace)) {
|
||||
OverlayAddressSpace ospace = (OverlayAddressSpace) element;
|
||||
encoder.openElement(ELEM_SPACE_OVERLAY);
|
||||
encoder.writeString(ATTRIB_NAME, ospace.getName());
|
||||
encoder.writeSignedInteger(ATTRIB_INDEX, ospace.getUnique());
|
||||
encoder.writeSpace(ATTRIB_BASE, ospace.getOverlayedSpace());
|
||||
encoder.closeElement(ELEM_SPACE_OVERLAY);
|
||||
encoder.openElement(ElementId.ELEM_SPACE_OVERLAY);
|
||||
encoder.writeString(AttributeId.ATTRIB_NAME, ospace.getName());
|
||||
encoder.writeSignedInteger(AttributeId.ATTRIB_INDEX, ospace.getUnique());
|
||||
encoder.writeSpace(AttributeId.ATTRIB_BASE, ospace.getOverlayedSpace());
|
||||
encoder.closeElement(ElementId.ELEM_SPACE_OVERLAY);
|
||||
continue;
|
||||
}
|
||||
switch (element.getType()) {
|
||||
case AddressSpace.TYPE_RAM:
|
||||
tag = ELEM_SPACE;
|
||||
tag = ElementId.ELEM_SPACE;
|
||||
delay = 1;
|
||||
physical = true;
|
||||
break;
|
||||
case AddressSpace.TYPE_REGISTER:
|
||||
tag = ELEM_SPACE;
|
||||
tag = ElementId.ELEM_SPACE;
|
||||
delay = 0;
|
||||
physical = true;
|
||||
break;
|
||||
case AddressSpace.TYPE_UNIQUE:
|
||||
tag = ELEM_SPACE_UNIQUE;
|
||||
tag = ElementId.ELEM_SPACE_UNIQUE;
|
||||
delay = 0;
|
||||
physical = true;
|
||||
break;
|
||||
case AddressSpace.TYPE_OTHER:
|
||||
tag = ELEM_SPACE_OTHER;
|
||||
tag = ElementId.ELEM_SPACE_OTHER;
|
||||
delay = 0;
|
||||
physical = true;
|
||||
break;
|
||||
|
@ -1499,8 +1463,8 @@ public class SleighLanguage implements Language {
|
|||
continue;
|
||||
}
|
||||
encoder.openElement(tag);
|
||||
encoder.writeString(ATTRIB_NAME, element.getName());
|
||||
encoder.writeSignedInteger(ATTRIB_INDEX, element.getUnique());
|
||||
encoder.writeString(AttributeId.ATTRIB_NAME, element.getName());
|
||||
encoder.writeSignedInteger(AttributeId.ATTRIB_INDEX, element.getUnique());
|
||||
|
||||
int size = element.getSize(); // Size in bits
|
||||
if (element instanceof SegmentedAddressSpace) {
|
||||
|
@ -1511,18 +1475,19 @@ public class SleighLanguage implements Language {
|
|||
size = 64;
|
||||
}
|
||||
int bytesize = (size + 7) / 8; // Convert bits to bytes
|
||||
encoder.writeSignedInteger(ATTRIB_SIZE, bytesize);
|
||||
encoder.writeSignedInteger(AttributeId.ATTRIB_SIZE, bytesize);
|
||||
|
||||
if (element.getAddressableUnitSize() > 1) {
|
||||
encoder.writeUnsignedInteger(ATTRIB_WORDSIZE, element.getAddressableUnitSize());
|
||||
encoder.writeUnsignedInteger(AttributeId.ATTRIB_WORDSIZE,
|
||||
element.getAddressableUnitSize());
|
||||
}
|
||||
|
||||
encoder.writeBool(ATTRIB_BIGENDIAN, isBigEndian());
|
||||
encoder.writeSignedInteger(ATTRIB_DELAY, delay);
|
||||
encoder.writeBool(ATTRIB_PHYSICAL, physical);
|
||||
encoder.writeBool(AttributeId.ATTRIB_BIGENDIAN, isBigEndian());
|
||||
encoder.writeSignedInteger(AttributeId.ATTRIB_DELAY, delay);
|
||||
encoder.writeBool(AttributeId.ATTRIB_PHYSICAL, physical);
|
||||
encoder.closeElement(tag);
|
||||
}
|
||||
encoder.closeElement(ELEM_SPACES);
|
||||
encoder.closeElement(ElementId.ELEM_SPACES);
|
||||
|
||||
SleighLanguageDescription sleighDescription =
|
||||
(SleighLanguageDescription) getLanguageDescription();
|
||||
|
@ -1530,13 +1495,13 @@ public class SleighLanguage implements Language {
|
|||
if (!truncatedSpaceNames.isEmpty()) {
|
||||
for (String spaceName : truncatedSpaceNames) {
|
||||
int sz = sleighDescription.getTruncatedSpaceSize(spaceName);
|
||||
encoder.openElement(ELEM_TRUNCATE_SPACE);
|
||||
encoder.writeString(ATTRIB_SPACE, spaceName);
|
||||
encoder.writeSignedInteger(ATTRIB_SIZE, sz);
|
||||
encoder.closeElement(ELEM_TRUNCATE_SPACE);
|
||||
encoder.openElement(ElementId.ELEM_TRUNCATE_SPACE);
|
||||
encoder.writeString(AttributeId.ATTRIB_SPACE, spaceName);
|
||||
encoder.writeSignedInteger(AttributeId.ATTRIB_SIZE, sz);
|
||||
encoder.closeElement(ElementId.ELEM_TRUNCATE_SPACE);
|
||||
}
|
||||
}
|
||||
encoder.closeElement(ELEM_SLEIGH);
|
||||
encoder.closeElement(ElementId.ELEM_SLEIGH);
|
||||
}
|
||||
|
||||
private void initParallelHelper() {
|
||||
|
|
|
@ -27,6 +27,7 @@ import org.xml.sax.*;
|
|||
import generic.jar.ResourceFile;
|
||||
import ghidra.framework.Application;
|
||||
import ghidra.program.model.lang.*;
|
||||
import ghidra.program.model.pcode.DecoderException;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.SystemUtilities;
|
||||
import ghidra.util.xml.SpecXmlUtils;
|
||||
|
@ -137,18 +138,17 @@ public class SleighLanguageProvider implements LanguageProvider {
|
|||
"Can't read language spec " + description.getSlaFile().getAbsolutePath(), e);
|
||||
throw e;
|
||||
}
|
||||
catch (DecoderException e) {
|
||||
Msg.showError(this, null, "Error",
|
||||
"Can't read language spec " + description.getSlaFile().getAbsolutePath(), e);
|
||||
throw new SleighException("Format violation in the .sla file", e);
|
||||
}
|
||||
catch (FileNotFoundException e) {
|
||||
Msg.showError(this, null, "Error",
|
||||
"Can't read language spec " + description.getSlaFile().getAbsolutePath(), e);
|
||||
throw new SleighException(
|
||||
"File not found - language probably did not compile properly", e);
|
||||
}
|
||||
catch (UnknownInstructionException e) {
|
||||
Msg.showError(this, null, "Error",
|
||||
"Can't read language spec " + description.getSlaFile().getAbsolutePath(), e);
|
||||
throw new SleighException(
|
||||
"Unknown instruction - language probably did not compile properly", e);
|
||||
}
|
||||
catch (SAXException e) {
|
||||
Msg.showError(this, null, "Error",
|
||||
"Can't read language spec " + description.getSlaFile().getAbsolutePath(), e);
|
||||
|
|
|
@ -20,12 +20,10 @@
|
|||
package ghidra.app.plugin.processors.sleigh.expression;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
import ghidra.program.model.pcode.Decoder;
|
||||
import ghidra.program.model.pcode.DecoderException;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* Base class for binary operators that combine PatternExpressions
|
||||
*/
|
||||
public abstract class BinaryExpression extends PatternExpression {
|
||||
|
@ -69,10 +67,10 @@ public abstract class BinaryExpression extends PatternExpression {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void restoreXml(XmlPullParser parser, SleighLanguage lang) {
|
||||
XmlElement el = parser.start();
|
||||
left = PatternExpression.restoreExpression(parser, lang);
|
||||
right = PatternExpression.restoreExpression(parser, lang);
|
||||
parser.end(el);
|
||||
public void decode(Decoder decoder, SleighLanguage lang) throws DecoderException {
|
||||
int el = decoder.openElement();
|
||||
left = PatternExpression.decodeExpression(decoder, lang);
|
||||
right = PatternExpression.decodeExpression(decoder, lang);
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,19 +19,17 @@
|
|||
*/
|
||||
package ghidra.app.plugin.processors.sleigh.expression;
|
||||
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.ParserWalker;
|
||||
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.util.xml.SpecXmlUtils;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
import ghidra.program.model.pcode.Decoder;
|
||||
import ghidra.program.model.pcode.DecoderException;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* A constant value associated with an alwaysTrue pattern
|
||||
*/
|
||||
|
||||
public class ConstantValue extends PatternValue {
|
||||
|
||||
private long val; // The constant value
|
||||
|
@ -61,25 +59,16 @@ public class ConstantValue extends PatternValue {
|
|||
val = b;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.expression.PatternValue#minValue()
|
||||
*/
|
||||
@Override
|
||||
public long minValue() {
|
||||
return val;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.expression.PatternValue#maxValue()
|
||||
*/
|
||||
@Override
|
||||
public long maxValue() {
|
||||
return val;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.expression.PatternExpression#getValue(ghidra.app.plugin.processors.sleigh.ParserWalker)
|
||||
*/
|
||||
@Override
|
||||
public long getValue(ParserWalker walker) throws MemoryAccessException {
|
||||
return val;
|
||||
|
@ -89,14 +78,11 @@ public class ConstantValue extends PatternValue {
|
|||
return val;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.PatternExpression#restoreXml(org.jdom.Element)
|
||||
*/
|
||||
@Override
|
||||
public void restoreXml(XmlPullParser parser, SleighLanguage lang) {
|
||||
XmlElement el = parser.start("intb");
|
||||
val = SpecXmlUtils.decodeLong(el.getAttribute("val"));
|
||||
parser.end(el);
|
||||
public void decode(Decoder decoder, SleighLanguage lang) throws DecoderException {
|
||||
int el = decoder.openElement(ELEM_INTB);
|
||||
val = decoder.readSignedInteger(ATTRIB_VAL);
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -19,16 +19,15 @@
|
|||
*/
|
||||
package ghidra.app.plugin.processors.sleigh.expression;
|
||||
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.ParserWalker;
|
||||
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.util.xml.SpecXmlUtils;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
import ghidra.program.model.pcode.Decoder;
|
||||
import ghidra.program.model.pcode.DecoderException;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* Contiguous bits in the non-instruction part of the context interpreted
|
||||
* as an integer value
|
||||
*/
|
||||
|
@ -81,17 +80,11 @@ public class ContextField extends PatternValue {
|
|||
return signbit;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.expression.PatternValue#minValue()
|
||||
*/
|
||||
@Override
|
||||
public long minValue() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.expression.PatternValue#maxValue()
|
||||
*/
|
||||
@Override
|
||||
public long maxValue() {
|
||||
long res = -1;
|
||||
|
@ -100,39 +93,35 @@ public class ContextField extends PatternValue {
|
|||
return ~res;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.PatternExpression#getValue(ghidra.app.plugin.processors.sleigh.InstructionContext)
|
||||
*/
|
||||
@Override
|
||||
public long getValue(ParserWalker walker) throws MemoryAccessException {
|
||||
long res = getContextBytes(walker);
|
||||
res >>= shift;
|
||||
if (signbit)
|
||||
if (signbit) {
|
||||
res = TokenField.signExtend(res, endbit - startbit);
|
||||
else
|
||||
}
|
||||
else {
|
||||
res = TokenField.zeroExtend(res, endbit - startbit);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.PatternExpression#restoreXml(org.jdom.Element)
|
||||
*/
|
||||
@Override
|
||||
public void restoreXml(XmlPullParser parser, SleighLanguage lang) {
|
||||
XmlElement el = parser.start("contextfield");
|
||||
signbit = SpecXmlUtils.decodeBoolean(el.getAttribute("signbit"));
|
||||
startbit = SpecXmlUtils.decodeInt(el.getAttribute("startbit"));
|
||||
endbit = SpecXmlUtils.decodeInt(el.getAttribute("endbit"));
|
||||
startbyte = SpecXmlUtils.decodeInt(el.getAttribute("startbyte"));
|
||||
endbyte = SpecXmlUtils.decodeInt(el.getAttribute("endbyte"));
|
||||
shift = SpecXmlUtils.decodeInt(el.getAttribute("shift"));
|
||||
parser.end(el);
|
||||
public void decode(Decoder decoder, SleighLanguage lang) throws DecoderException {
|
||||
int el = decoder.openElement(ELEM_CONTEXTFIELD);
|
||||
signbit = decoder.readBool(ATTRIB_SIGNBIT);
|
||||
startbit = (int) decoder.readSignedInteger(ATTRIB_STARTBIT);
|
||||
endbit = (int) decoder.readSignedInteger(ATTRIB_ENDBIT);
|
||||
startbyte = (int) decoder.readSignedInteger(ATTRIB_STARTBYTE);
|
||||
endbyte = (int) decoder.readSignedInteger(ATTRIB_ENDBYTE);
|
||||
shift = (int) decoder.readSignedInteger(ATTRIB_SHIFT);
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a long from the context bytes in pos
|
||||
* @param pos
|
||||
* @return
|
||||
* Build a long from the context bytes at the current point in the instruction parse
|
||||
* @param walker is the parsing state
|
||||
* @return the recover value
|
||||
*/
|
||||
private long getContextBytes(ParserWalker walker) {
|
||||
long res = 0;
|
||||
|
|
|
@ -19,15 +19,16 @@
|
|||
*/
|
||||
package ghidra.app.plugin.processors.sleigh.expression;
|
||||
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.ParserWalker;
|
||||
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
import ghidra.program.model.pcode.Decoder;
|
||||
import ghidra.program.model.pcode.DecoderException;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* The integer offset of the address following the current instruction
|
||||
*/
|
||||
public class EndInstructionValue extends PatternValue {
|
||||
|
@ -43,37 +44,26 @@ public class EndInstructionValue extends PatternValue {
|
|||
return obj instanceof EndInstructionValue;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.expression.PatternValue#minValue()
|
||||
*/
|
||||
@Override
|
||||
public long minValue() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.expression.PatternValue#maxValue()
|
||||
*/
|
||||
@Override
|
||||
public long maxValue() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.expression.PatternExpression#getValue(ghidra.app.plugin.processors.sleigh.ParserWalker)
|
||||
*/
|
||||
@Override
|
||||
public long getValue(ParserWalker walker) throws MemoryAccessException {
|
||||
Address addr = walker.getNaddr();
|
||||
return addr.getAddressableWordOffset();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.PatternExpression#restoreXml(org.jdom.Element)
|
||||
*/
|
||||
@Override
|
||||
public void restoreXml(XmlPullParser parser, SleighLanguage lang) {
|
||||
parser.discardSubTree("end_exp");
|
||||
public void decode(Decoder decoder, SleighLanguage lang) throws DecoderException {
|
||||
int el = decoder.openElement(ELEM_END_EXP);
|
||||
decoder.closeElement(el);
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
|
|
|
@ -15,15 +15,16 @@
|
|||
*/
|
||||
package ghidra.app.plugin.processors.sleigh.expression;
|
||||
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.ParserWalker;
|
||||
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
import ghidra.program.model.pcode.Decoder;
|
||||
import ghidra.program.model.pcode.DecoderException;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* The integer offset of the address following the current instruction
|
||||
*/
|
||||
public class Next2InstructionValue extends PatternValue {
|
||||
|
@ -56,8 +57,9 @@ public class Next2InstructionValue extends PatternValue {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void restoreXml(XmlPullParser parser, SleighLanguage lang) {
|
||||
parser.discardSubTree("next2_exp");
|
||||
public void decode(Decoder decoder, SleighLanguage lang) throws DecoderException {
|
||||
int el = decoder.openElement(ELEM_NEXT2_EXP);
|
||||
decoder.closeElement(el);
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
|
|
|
@ -19,16 +19,15 @@
|
|||
*/
|
||||
package ghidra.app.plugin.processors.sleigh.expression;
|
||||
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.*;
|
||||
import ghidra.app.plugin.processors.sleigh.symbol.*;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.util.xml.SpecXmlUtils;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
import ghidra.program.model.pcode.Decoder;
|
||||
import ghidra.program.model.pcode.DecoderException;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* An Expression representing the value of a Constructor operand
|
||||
*/
|
||||
public class OperandValue extends PatternValue {
|
||||
|
@ -75,25 +74,16 @@ public class OperandValue extends PatternValue {
|
|||
return ct;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.expression.PatternValue#minValue()
|
||||
*/
|
||||
@Override
|
||||
public long minValue() {
|
||||
throw new SleighException("Operand used in pattern expression");
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.expression.PatternValue#maxValue()
|
||||
*/
|
||||
@Override
|
||||
public long maxValue() {
|
||||
throw new SleighException("Operand used in pattern expression");
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.expression.PatternExpression#getValue(ghidra.app.plugin.processors.sleigh.ParserWalker)
|
||||
*/
|
||||
@Override
|
||||
public long getValue(ParserWalker walker) throws MemoryAccessException {
|
||||
OperandSymbol sym = ct.getOperand(index);
|
||||
|
@ -114,18 +104,15 @@ public class OperandValue extends PatternValue {
|
|||
return res;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.PatternExpression#restoreXml(org.jdom.Element)
|
||||
*/
|
||||
@Override
|
||||
public void restoreXml(XmlPullParser parser, SleighLanguage lang) {
|
||||
XmlElement el = parser.start("operand_exp");
|
||||
index = SpecXmlUtils.decodeInt(el.getAttribute("index"));
|
||||
int tabid = SpecXmlUtils.decodeInt(el.getAttribute("table"));
|
||||
int ctid = SpecXmlUtils.decodeInt(el.getAttribute("ct"));
|
||||
public void decode(Decoder decoder, SleighLanguage lang) throws DecoderException {
|
||||
int el = decoder.openElement(ELEM_OPERAND_EXP);
|
||||
index = (int) decoder.readSignedInteger(ATTRIB_INDEX);
|
||||
int tabid = (int) decoder.readUnsignedInteger(ATTRIB_TABLE);
|
||||
int ctid = (int) decoder.readUnsignedInteger(ATTRIB_CT);
|
||||
SubtableSymbol sym = (SubtableSymbol) lang.getSymbolTable().findSymbol(tabid);
|
||||
ct = sym.getConstructor(ctid);
|
||||
parser.end(el);
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -19,66 +19,85 @@
|
|||
*/
|
||||
package ghidra.app.plugin.processors.sleigh.expression;
|
||||
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.ParserWalker;
|
||||
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
import ghidra.program.model.pcode.Decoder;
|
||||
import ghidra.program.model.pcode.DecoderException;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* An expression which results in a pattern for a specific InstructionContext
|
||||
*/
|
||||
public abstract class PatternExpression {
|
||||
public abstract long getValue(ParserWalker walker) throws MemoryAccessException;
|
||||
|
||||
public abstract void restoreXml(XmlPullParser parser, SleighLanguage lang);
|
||||
public abstract void decode(Decoder decoder, SleighLanguage lang) throws DecoderException;
|
||||
|
||||
public static PatternExpression restoreExpression(XmlPullParser parser, SleighLanguage lang) {
|
||||
XmlElement el = parser.peek();
|
||||
public static PatternExpression decodeExpression(Decoder decoder, SleighLanguage lang)
|
||||
throws DecoderException {
|
||||
int el = decoder.peekElement();
|
||||
PatternExpression res;
|
||||
String nm = el.getName();
|
||||
if (nm.equals("tokenfield"))
|
||||
if (el == ELEM_TOKENFIELD.id()) {
|
||||
res = new TokenField();
|
||||
else if (nm.equals("contextfield"))
|
||||
}
|
||||
else if (el == ELEM_CONTEXTFIELD.id()) {
|
||||
res = new ContextField();
|
||||
else if (nm.equals("intb"))
|
||||
}
|
||||
else if (el == ELEM_INTB.id()) {
|
||||
res = new ConstantValue();
|
||||
else if (nm.equals("operand_exp"))
|
||||
}
|
||||
else if (el == ELEM_OPERAND_EXP.id()) {
|
||||
res = new OperandValue();
|
||||
else if (nm.equals("start_exp"))
|
||||
}
|
||||
else if (el == ELEM_START_EXP.id()) {
|
||||
res = new StartInstructionValue();
|
||||
else if (nm.equals("end_exp"))
|
||||
}
|
||||
else if (el == ELEM_END_EXP.id()) {
|
||||
res = new EndInstructionValue();
|
||||
else if (nm.equals("next2_exp"))
|
||||
}
|
||||
else if (el == ELEM_NEXT2_EXP.id()) {
|
||||
res = new Next2InstructionValue();
|
||||
else if (nm.equals("plus_exp"))
|
||||
}
|
||||
else if (el == ELEM_PLUS_EXP.id()) {
|
||||
res = new PlusExpression();
|
||||
else if (nm.equals("sub_exp"))
|
||||
}
|
||||
else if (el == ELEM_SUB_EXP.id()) {
|
||||
res = new SubExpression();
|
||||
else if (nm.equals("mult_exp"))
|
||||
}
|
||||
else if (el == ELEM_MULT_EXP.id()) {
|
||||
res = new MultExpression();
|
||||
else if (nm.equals("lshift_exp"))
|
||||
}
|
||||
else if (el == ELEM_LSHIFT_EXP.id()) {
|
||||
res = new LeftShiftExpression();
|
||||
else if (nm.equals("rshift_exp"))
|
||||
}
|
||||
else if (el == ELEM_RSHIFT_EXP.id()) {
|
||||
res = new RightShiftExpression();
|
||||
else if (nm.equals("and_exp"))
|
||||
}
|
||||
else if (el == ELEM_AND_EXP.id()) {
|
||||
res = new AndExpression();
|
||||
else if (nm.equals("or_exp"))
|
||||
}
|
||||
else if (el == ELEM_OR_EXP.id()) {
|
||||
res = new OrExpression();
|
||||
else if (nm.equals("xor_exp"))
|
||||
}
|
||||
else if (el == ELEM_XOR_EXP.id()) {
|
||||
res = new XorExpression();
|
||||
else if (nm.equals("div_exp"))
|
||||
}
|
||||
else if (el == ELEM_DIV_EXP.id()) {
|
||||
res = new DivExpression();
|
||||
else if (nm.equals("minus_exp"))
|
||||
}
|
||||
else if (el == ELEM_MINUS_EXP.id()) {
|
||||
res = new MinusExpression();
|
||||
else if (nm.equals("not_exp"))
|
||||
}
|
||||
else if (el == ELEM_NOT_EXP.id()) {
|
||||
res = new NotExpression();
|
||||
else
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
|
||||
res.restoreXml(parser, lang);
|
||||
res.decode(decoder, lang);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,15 +19,16 @@
|
|||
*/
|
||||
package ghidra.app.plugin.processors.sleigh.expression;
|
||||
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.ParserWalker;
|
||||
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
import ghidra.program.model.pcode.Decoder;
|
||||
import ghidra.program.model.pcode.DecoderException;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* The offset value of the current instructions address
|
||||
*/
|
||||
public class StartInstructionValue extends PatternValue {
|
||||
|
@ -43,37 +44,26 @@ public class StartInstructionValue extends PatternValue {
|
|||
return obj instanceof StartInstructionValue;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.expression.PatternValue#minValue()
|
||||
*/
|
||||
@Override
|
||||
public long minValue() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.expression.PatternValue#maxValue()
|
||||
*/
|
||||
@Override
|
||||
public long maxValue() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.expression.PatternExpression#getValue(ghidra.app.plugin.processors.sleigh.ParserWalker)
|
||||
*/
|
||||
@Override
|
||||
public long getValue(ParserWalker walker) throws MemoryAccessException {
|
||||
Address addr = walker.getAddr();
|
||||
return addr.getAddressableWordOffset();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.PatternExpression#restoreXml(org.jdom.Element)
|
||||
*/
|
||||
@Override
|
||||
public void restoreXml(XmlPullParser parser, SleighLanguage lang) {
|
||||
parser.discardSubTree("start_exp");
|
||||
public void decode(Decoder decoder, SleighLanguage lang) throws DecoderException {
|
||||
int el = decoder.openElement(ELEM_START_EXP);
|
||||
decoder.closeElement(el);
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
|
|
|
@ -19,16 +19,15 @@
|
|||
*/
|
||||
package ghidra.app.plugin.processors.sleigh.expression;
|
||||
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.ParserWalker;
|
||||
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.util.xml.SpecXmlUtils;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
import ghidra.program.model.pcode.Decoder;
|
||||
import ghidra.program.model.pcode.DecoderException;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* A contiguous set of bits within instruction stream, interpreted
|
||||
* as an integer value
|
||||
*/
|
||||
|
@ -75,17 +74,11 @@ public class TokenField extends PatternValue {
|
|||
return true;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.expression.PatternValue#minValue()
|
||||
*/
|
||||
@Override
|
||||
public long minValue() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.expression.PatternValue#maxValue()
|
||||
*/
|
||||
@Override
|
||||
public long maxValue() {
|
||||
long res = -1;
|
||||
|
@ -94,18 +87,17 @@ public class TokenField extends PatternValue {
|
|||
return ~res;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.PatternExpression#getValue(ghidra.app.plugin.processors.sleigh.InstructionContext)
|
||||
*/
|
||||
@Override
|
||||
public long getValue(ParserWalker walker) throws MemoryAccessException {
|
||||
long res = getInstructionBytes(walker);
|
||||
|
||||
res >>= shift;
|
||||
if (signbit)
|
||||
if (signbit) {
|
||||
res = signExtend(res, bitend - bitstart);
|
||||
else
|
||||
}
|
||||
else {
|
||||
res = zeroExtend(res, bitend - bitstart);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -125,20 +117,17 @@ public class TokenField extends PatternValue {
|
|||
return byteend;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.PatternExpression#restoreXml(org.jdom.Element)
|
||||
*/
|
||||
@Override
|
||||
public void restoreXml(XmlPullParser parser, SleighLanguage lang) {
|
||||
XmlElement el = parser.start("tokenfield");
|
||||
bigendian = SpecXmlUtils.decodeBoolean(el.getAttribute("bigendian"));
|
||||
signbit = SpecXmlUtils.decodeBoolean(el.getAttribute("signbit"));
|
||||
bitstart = SpecXmlUtils.decodeInt(el.getAttribute("bitstart"));
|
||||
bitend = SpecXmlUtils.decodeInt(el.getAttribute("bitend"));
|
||||
bytestart = SpecXmlUtils.decodeInt(el.getAttribute("bytestart"));
|
||||
byteend = SpecXmlUtils.decodeInt(el.getAttribute("byteend"));
|
||||
shift = SpecXmlUtils.decodeInt(el.getAttribute("shift"));
|
||||
parser.end(el);
|
||||
public void decode(Decoder decoder, SleighLanguage lang) throws DecoderException {
|
||||
int el = decoder.openElement(ELEM_TOKENFIELD);
|
||||
bigendian = decoder.readBool(ATTRIB_BIGENDIAN);
|
||||
signbit = decoder.readBool(ATTRIB_SIGNBIT);
|
||||
bitstart = (int) decoder.readSignedInteger(ATTRIB_STARTBIT);
|
||||
bitend = (int) decoder.readSignedInteger(ATTRIB_ENDBIT);
|
||||
bytestart = (int) decoder.readSignedInteger(ATTRIB_STARTBYTE);
|
||||
byteend = (int) decoder.readSignedInteger(ATTRIB_ENDBYTE);
|
||||
shift = (int) decoder.readSignedInteger(ATTRIB_SHIFT);
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
|
||||
public boolean hasSignbit() {
|
||||
|
@ -146,10 +135,10 @@ public class TokenField extends PatternValue {
|
|||
}
|
||||
|
||||
/**
|
||||
* Build a long from the instruction bytes in pos
|
||||
* @param pos Current instruction
|
||||
* @return
|
||||
* @throws MemoryAccessException
|
||||
* Build a long from the instruction bytes at the current point in the parse
|
||||
* @param walker is the instruction parse state
|
||||
* @return the recovered value
|
||||
* @throws MemoryAccessException for problems reading the bytes
|
||||
*/
|
||||
private long getInstructionBytes(ParserWalker walker) throws MemoryAccessException {
|
||||
long res = 0;
|
||||
|
@ -171,8 +160,9 @@ public class TokenField extends PatternValue {
|
|||
res = res << (8 * tmpsize);
|
||||
res |= (tmp & 0xffffffffl);
|
||||
}
|
||||
if (!bigendian)
|
||||
if (!bigendian) {
|
||||
res = byteSwap(res, size);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -180,15 +170,17 @@ public class TokenField extends PatternValue {
|
|||
* Sign extend -val- above -bit-
|
||||
* @param val value to extend
|
||||
* @param bit bit specifying sign
|
||||
* @return
|
||||
* @return the extended value
|
||||
*/
|
||||
public static long signExtend(long val, int bit) {
|
||||
long mask = 0;
|
||||
mask = (~mask) << bit;
|
||||
if (((val >> bit) & 1) != 0)
|
||||
if (((val >> bit) & 1) != 0) {
|
||||
val |= mask;
|
||||
else
|
||||
}
|
||||
else {
|
||||
val &= (~mask);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
|
@ -196,7 +188,7 @@ public class TokenField extends PatternValue {
|
|||
* Clear all bits in -val- above -bit-
|
||||
* @param val value to zero extend
|
||||
* @param bit bit above which to zero extend
|
||||
* @return
|
||||
* @return the extended value
|
||||
*/
|
||||
public static long zeroExtend(long val, int bit) {
|
||||
long mask = 0;
|
||||
|
@ -210,7 +202,7 @@ public class TokenField extends PatternValue {
|
|||
* Swap the least sig -size- bytes in -val-
|
||||
* @param val value to be byte swapped
|
||||
* @param size number of bytes involved in swap
|
||||
* @return
|
||||
* @return the byte swapped value
|
||||
*/
|
||||
public static long byteSwap(long val, int size) {
|
||||
long res = 0;
|
||||
|
|
|
@ -21,12 +21,10 @@
|
|||
package ghidra.app.plugin.processors.sleigh.expression;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
import ghidra.program.model.pcode.Decoder;
|
||||
import ghidra.program.model.pcode.DecoderException;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* Base class for unary operators on PatternExpressions
|
||||
*/
|
||||
|
||||
|
@ -59,10 +57,10 @@ public abstract class UnaryExpression extends PatternExpression {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void restoreXml(XmlPullParser parser, SleighLanguage lang) {
|
||||
XmlElement el = parser.start();
|
||||
public void decode(Decoder decoder, SleighLanguage lang) throws DecoderException {
|
||||
int el = decoder.openElement();
|
||||
|
||||
unary = PatternExpression.restoreExpression(parser, lang);
|
||||
parser.end(el);
|
||||
unary = PatternExpression.decodeExpression(decoder, lang);
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,15 +19,15 @@
|
|||
*/
|
||||
package ghidra.app.plugin.processors.sleigh.pattern;
|
||||
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.ParserWalker;
|
||||
import ghidra.app.plugin.processors.sleigh.SleighDebugLogger;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
import ghidra.program.model.pcode.Decoder;
|
||||
import ghidra.program.model.pcode.DecoderException;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* A pattern that has both an instruction part and non-instruction part
|
||||
*/
|
||||
public class CombinePattern extends DisjointPattern {
|
||||
|
@ -35,9 +35,6 @@ public class CombinePattern extends DisjointPattern {
|
|||
private ContextPattern context; // Context piece
|
||||
private InstructionPattern instr; // Instruction piece
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.DisjointPattern#getBlock(boolean)
|
||||
*/
|
||||
@Override
|
||||
public PatternBlock getBlock(boolean cont) {
|
||||
return cont ? context.getBlock() : instr.getBlock();
|
||||
|
@ -53,55 +50,50 @@ public class CombinePattern extends DisjointPattern {
|
|||
instr = in;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#simplifyClone()
|
||||
*/
|
||||
@Override
|
||||
public Pattern simplifyClone() {
|
||||
if (context.alwaysTrue())
|
||||
if (context.alwaysTrue()) {
|
||||
return instr.simplifyClone();
|
||||
if (instr.alwaysTrue())
|
||||
}
|
||||
if (instr.alwaysTrue()) {
|
||||
return context.simplifyClone();
|
||||
if (context.alwaysFalse() || instr.alwaysFalse())
|
||||
}
|
||||
if (context.alwaysFalse() || instr.alwaysFalse()) {
|
||||
return new InstructionPattern(false);
|
||||
}
|
||||
|
||||
return new CombinePattern((ContextPattern) context.simplifyClone(),
|
||||
(InstructionPattern) instr.simplifyClone());
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#shiftInstruction(int)
|
||||
*/
|
||||
@Override
|
||||
public void shiftInstruction(int sa) {
|
||||
instr.shiftInstruction(sa);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#doOr(ghidra.app.plugin.processors.sleigh.Pattern, int)
|
||||
*/
|
||||
@Override
|
||||
public Pattern doOr(Pattern b, int sa) {
|
||||
if (b.numDisjoint() != 0)
|
||||
if (b.numDisjoint() != 0) {
|
||||
return b.doOr(this, -sa);
|
||||
}
|
||||
|
||||
DisjointPattern res1 = (DisjointPattern) simplifyClone();
|
||||
DisjointPattern res2 = (DisjointPattern) b.simplifyClone();
|
||||
if (sa < 0)
|
||||
if (sa < 0) {
|
||||
res1.shiftInstruction(-sa);
|
||||
else
|
||||
}
|
||||
else {
|
||||
res2.shiftInstruction(sa);
|
||||
}
|
||||
OrPattern tmp = new OrPattern(res1, res2);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#doAnd(ghidra.app.plugin.processors.sleigh.Pattern, int)
|
||||
*/
|
||||
@Override
|
||||
public Pattern doAnd(Pattern b, int sa) {
|
||||
if (b.numDisjoint() != 0)
|
||||
if (b.numDisjoint() != 0) {
|
||||
return b.doAnd(this, -sa);
|
||||
}
|
||||
|
||||
CombinePattern tmp;
|
||||
if (b instanceof CombinePattern) {
|
||||
|
@ -117,17 +109,15 @@ public class CombinePattern extends DisjointPattern {
|
|||
else { // Must be a ContextPattern
|
||||
ContextPattern c = (ContextPattern) context.doAnd(b, 0);
|
||||
InstructionPattern newpat = (InstructionPattern) instr.simplifyClone();
|
||||
if (sa < 0)
|
||||
if (sa < 0) {
|
||||
newpat.shiftInstruction(-sa);
|
||||
}
|
||||
tmp = new CombinePattern(c, newpat);
|
||||
}
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.pattern.Pattern#isMatch(ghidra.app.plugin.processors.sleigh.ParserWalker, ghidra.app.plugin.processors.sleigh.SleighDebugLogger)
|
||||
*/
|
||||
@Override
|
||||
public boolean isMatch(ParserWalker walker, SleighDebugLogger debug)
|
||||
throws MemoryAccessException {
|
||||
|
@ -167,41 +157,29 @@ public class CombinePattern extends DisjointPattern {
|
|||
debug.indent();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#alwaysTrue()
|
||||
*/
|
||||
@Override
|
||||
public boolean alwaysTrue() {
|
||||
return (context.alwaysTrue() && instr.alwaysTrue());
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#alwaysFalse()
|
||||
*/
|
||||
@Override
|
||||
public boolean alwaysFalse() {
|
||||
return (context.alwaysFalse() || instr.alwaysFalse());
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#alwaysInstructionTrue()
|
||||
*/
|
||||
@Override
|
||||
public boolean alwaysInstructionTrue() {
|
||||
return instr.alwaysInstructionTrue();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#restoreXml(org.jdom.Element)
|
||||
*/
|
||||
@Override
|
||||
public void restoreXml(XmlPullParser parser) {
|
||||
XmlElement el = parser.start("combine_pat");
|
||||
public void decode(Decoder decoder) throws DecoderException {
|
||||
int el = decoder.openElement(ELEM_COMBINE_PAT);
|
||||
context = new ContextPattern();
|
||||
context.restoreXml(parser);
|
||||
context.decode(decoder);
|
||||
instr = new InstructionPattern();
|
||||
instr.restoreXml(parser);
|
||||
parser.end(el);
|
||||
instr.decode(decoder);
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -19,16 +19,16 @@
|
|||
*/
|
||||
package ghidra.app.plugin.processors.sleigh.pattern;
|
||||
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.ParserWalker;
|
||||
import ghidra.app.plugin.processors.sleigh.SleighDebugLogger;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.program.model.pcode.Decoder;
|
||||
import ghidra.program.model.pcode.DecoderException;
|
||||
import ghidra.util.StringUtilities;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* Pattern which depends only on the non-instruction stream bits
|
||||
* of the context
|
||||
*/
|
||||
|
@ -36,9 +36,6 @@ public class ContextPattern extends DisjointPattern {
|
|||
|
||||
private PatternBlock maskvalue;
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.DisjointPattern#getBlock(boolean)
|
||||
*/
|
||||
@Override
|
||||
public PatternBlock getBlock(boolean context) {
|
||||
return context ? maskvalue : null;
|
||||
|
@ -56,49 +53,36 @@ public class ContextPattern extends DisjointPattern {
|
|||
return maskvalue;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#simplifyClone()
|
||||
*/
|
||||
@Override
|
||||
public Pattern simplifyClone() {
|
||||
return new ContextPattern((PatternBlock) maskvalue.clone());
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#shiftInstruction(int)
|
||||
*/
|
||||
@Override
|
||||
public void shiftInstruction(int sa) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#doOr(ghidra.app.plugin.processors.sleigh.Pattern, int)
|
||||
*/
|
||||
@Override
|
||||
public Pattern doOr(Pattern b, int sa) {
|
||||
if (!(b instanceof ContextPattern))
|
||||
if (!(b instanceof ContextPattern)) {
|
||||
return b.doOr(this, -sa);
|
||||
}
|
||||
|
||||
return new OrPattern((DisjointPattern) simplifyClone(),
|
||||
(DisjointPattern) b.simplifyClone());
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#doAnd(ghidra.app.plugin.processors.sleigh.Pattern, int)
|
||||
*/
|
||||
@Override
|
||||
public Pattern doAnd(Pattern b, int sa) {
|
||||
if (!(b instanceof ContextPattern))
|
||||
if (!(b instanceof ContextPattern)) {
|
||||
return b.doAnd(this, -sa);
|
||||
}
|
||||
|
||||
PatternBlock resblock = maskvalue.andBlock(((ContextPattern) b).maskvalue);
|
||||
return new ContextPattern(resblock);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.pattern.Pattern#isMatch(ghidra.app.plugin.processors.sleigh.ParserWalker, ghidra.app.plugin.processors.sleigh.SleighDebugLogger)
|
||||
*/
|
||||
@Override
|
||||
public boolean isMatch(ParserWalker walker, SleighDebugLogger debug)
|
||||
throws MemoryAccessException {
|
||||
|
@ -149,39 +133,27 @@ public class ContextPattern extends DisjointPattern {
|
|||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#alwaysTrue()
|
||||
*/
|
||||
@Override
|
||||
public boolean alwaysTrue() {
|
||||
return maskvalue.alwaysTrue();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#alwaysFalse()
|
||||
*/
|
||||
@Override
|
||||
public boolean alwaysFalse() {
|
||||
return maskvalue.alwaysFalse();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#alwaysInstructionTrue()
|
||||
*/
|
||||
@Override
|
||||
public boolean alwaysInstructionTrue() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#restoreXml(org.jdom.Element)
|
||||
*/
|
||||
@Override
|
||||
public void restoreXml(XmlPullParser parser) {
|
||||
XmlElement el = parser.start("context_pat");
|
||||
public void decode(Decoder decoder) throws DecoderException {
|
||||
int el = decoder.openElement(ELEM_CONTEXT_PAT);
|
||||
maskvalue = new PatternBlock(true);
|
||||
maskvalue.restoreXml(parser);
|
||||
parser.end(el);
|
||||
maskvalue.decode(decoder);
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -19,12 +19,12 @@
|
|||
*/
|
||||
package ghidra.app.plugin.processors.sleigh.pattern;
|
||||
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import ghidra.program.model.pcode.Decoder;
|
||||
import ghidra.program.model.pcode.DecoderException;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* A pattern with no ORs in it
|
||||
*/
|
||||
public abstract class DisjointPattern extends Pattern {
|
||||
|
@ -55,22 +55,25 @@ public abstract class DisjointPattern extends Pattern {
|
|||
|
||||
public int getMask(int startbit, int size, boolean context) {
|
||||
PatternBlock block = getBlock(context);
|
||||
if (block != null)
|
||||
if (block != null) {
|
||||
return block.getMask(startbit, size);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int getValue(int startbit, int size, boolean context) {
|
||||
PatternBlock block = getBlock(context);
|
||||
if (block != null)
|
||||
if (block != null) {
|
||||
return block.getValue(startbit, size);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int getLength(boolean context) {
|
||||
PatternBlock block = getBlock(context);
|
||||
if (block != null)
|
||||
if (block != null) {
|
||||
return block.getLength();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -80,18 +83,22 @@ public abstract class DisjointPattern extends Pattern {
|
|||
a = getBlock(false);
|
||||
b = op2.getBlock(false);
|
||||
if (b != null) { // a must match existing block
|
||||
if (a == null)
|
||||
if (a == null) {
|
||||
return false;
|
||||
if (!a.specializes(b))
|
||||
}
|
||||
if (!a.specializes(b)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
a = getBlock(true);
|
||||
b = op2.getBlock(true);
|
||||
if (b != null) { // a must match existing block
|
||||
if (a == null)
|
||||
if (a == null) {
|
||||
return false;
|
||||
if (!a.specializes(b))
|
||||
}
|
||||
if (!a.specializes(b)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -102,32 +109,39 @@ public abstract class DisjointPattern extends Pattern {
|
|||
a = getBlock(false);
|
||||
b = op2.getBlock(false);
|
||||
if (b != null) { // a must match existing block
|
||||
if (a == null)
|
||||
if (a == null) {
|
||||
return false;
|
||||
if (!a.identical(b))
|
||||
}
|
||||
if (!a.identical(b)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
a = getBlock(true);
|
||||
b = op2.getBlock(true);
|
||||
if (b != null) { // a must match existing block
|
||||
if (a == null)
|
||||
if (a == null) {
|
||||
return false;
|
||||
if (!a.identical(b))
|
||||
}
|
||||
if (!a.identical(b)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static public DisjointPattern restoreDisjoint(XmlPullParser parser) {
|
||||
XmlElement el = parser.peek();
|
||||
static public DisjointPattern decodeDisjoint(Decoder decoder) throws DecoderException {
|
||||
int el = decoder.peekElement();
|
||||
DisjointPattern res;
|
||||
if (el.getName().equals("instruct_pat"))
|
||||
if (el == ELEM_INSTRUCT_PAT.id()) {
|
||||
res = new InstructionPattern();
|
||||
else if (el.getName().equals("context_pat"))
|
||||
}
|
||||
else if (el == ELEM_CONTEXT_PAT.id()) {
|
||||
res = new ContextPattern();
|
||||
else
|
||||
}
|
||||
else {
|
||||
res = new CombinePattern();
|
||||
res.restoreXml(parser);
|
||||
}
|
||||
res.decode(decoder);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,26 +19,23 @@
|
|||
*/
|
||||
package ghidra.app.plugin.processors.sleigh.pattern;
|
||||
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.ParserWalker;
|
||||
import ghidra.app.plugin.processors.sleigh.SleighDebugLogger;
|
||||
import ghidra.program.model.mem.MemBuffer;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.program.model.pcode.Decoder;
|
||||
import ghidra.program.model.pcode.DecoderException;
|
||||
import ghidra.util.StringUtilities;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* Matches against the actual instruction bit stream
|
||||
*/
|
||||
public class InstructionPattern extends DisjointPattern {
|
||||
|
||||
private PatternBlock maskvalue;
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.DisjointPattern#getBlock(boolean)
|
||||
*/
|
||||
@Override
|
||||
public PatternBlock getBlock(boolean context) {
|
||||
return context ? null : maskvalue;
|
||||
|
@ -60,56 +57,51 @@ public class InstructionPattern extends DisjointPattern {
|
|||
return maskvalue;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#simplifyClone()
|
||||
*/
|
||||
@Override
|
||||
public Pattern simplifyClone() {
|
||||
return new InstructionPattern((PatternBlock) maskvalue.clone());
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#shiftInstruction()
|
||||
*/
|
||||
@Override
|
||||
public void shiftInstruction(int sa) {
|
||||
maskvalue.shift(sa);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#doOr(ghidra.app.plugin.processors.sleigh.Pattern, int)
|
||||
*/
|
||||
@Override
|
||||
public Pattern doOr(Pattern b, int sa) {
|
||||
if (b.numDisjoint() > 0)
|
||||
if (b.numDisjoint() > 0) {
|
||||
return b.doOr(this, -sa);
|
||||
}
|
||||
|
||||
if (b instanceof CombinePattern)
|
||||
if (b instanceof CombinePattern) {
|
||||
return b.doOr(this, -sa);
|
||||
}
|
||||
|
||||
DisjointPattern res1, res2;
|
||||
res1 = (DisjointPattern) simplifyClone();
|
||||
res2 = (DisjointPattern) b.simplifyClone();
|
||||
if (sa < 0)
|
||||
if (sa < 0) {
|
||||
res1.shiftInstruction(-sa);
|
||||
else
|
||||
}
|
||||
else {
|
||||
res2.shiftInstruction(sa);
|
||||
}
|
||||
return new OrPattern(res1, res2);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#doAnd(ghidra.app.plugin.processors.sleigh.Pattern, int)
|
||||
*/
|
||||
@Override
|
||||
public Pattern doAnd(Pattern b, int sa) {
|
||||
if (b.numDisjoint() > 0)
|
||||
if (b.numDisjoint() > 0) {
|
||||
return b.doAnd(this, -sa);
|
||||
if (b instanceof CombinePattern)
|
||||
}
|
||||
if (b instanceof CombinePattern) {
|
||||
return b.doAnd(this, -sa);
|
||||
}
|
||||
if (b instanceof ContextPattern) {
|
||||
InstructionPattern newpat = (InstructionPattern) simplifyClone();
|
||||
if (sa < 0)
|
||||
if (sa < 0) {
|
||||
newpat.shiftInstruction(-sa);
|
||||
}
|
||||
return new CombinePattern((ContextPattern) b.simplifyClone(), newpat);
|
||||
}
|
||||
// b must be an InstructionPattern if it reaches here
|
||||
|
@ -127,9 +119,6 @@ public class InstructionPattern extends DisjointPattern {
|
|||
return new InstructionPattern(respattern);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.pattern.Pattern#isMatch(ghidra.app.plugin.processors.sleigh.ParserWalker, ghidra.app.plugin.processors.sleigh.SleighDebugLogger)
|
||||
*/
|
||||
@Override
|
||||
public boolean isMatch(ParserWalker walker, SleighDebugLogger debug)
|
||||
throws MemoryAccessException {
|
||||
|
@ -176,39 +165,27 @@ public class InstructionPattern extends DisjointPattern {
|
|||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#alwaysTrue()
|
||||
*/
|
||||
@Override
|
||||
public boolean alwaysTrue() {
|
||||
return maskvalue.alwaysTrue();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#alwaysFalse()
|
||||
*/
|
||||
@Override
|
||||
public boolean alwaysFalse() {
|
||||
return maskvalue.alwaysFalse();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#alwaysInstructionTrue()
|
||||
*/
|
||||
@Override
|
||||
public boolean alwaysInstructionTrue() {
|
||||
return maskvalue.alwaysTrue();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#restoreXml(org.jdom.Element)
|
||||
*/
|
||||
@Override
|
||||
public void restoreXml(XmlPullParser parser) {
|
||||
XmlElement el = parser.start("instruct_pat");
|
||||
public void decode(Decoder decoder) throws DecoderException {
|
||||
int el = decoder.openElement(ELEM_INSTRUCT_PAT);
|
||||
maskvalue = new PatternBlock(true);
|
||||
maskvalue.restoreXml(parser);
|
||||
parser.end(el);
|
||||
maskvalue.decode(decoder);
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -20,127 +19,127 @@
|
|||
*/
|
||||
package ghidra.app.plugin.processors.sleigh.pattern;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.*;
|
||||
import ghidra.program.model.mem.*;
|
||||
import ghidra.xml.*;
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.ParserWalker;
|
||||
import ghidra.app.plugin.processors.sleigh.SleighDebugLogger;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.program.model.pcode.Decoder;
|
||||
import ghidra.program.model.pcode.DecoderException;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* A pattern that can be matched by matching any of a list of subpatterns
|
||||
*/
|
||||
public class OrPattern extends Pattern {
|
||||
|
||||
private DisjointPattern[] orlist;
|
||||
|
||||
public OrPattern() { orlist = null; } // For use with restoreXml
|
||||
|
||||
public OrPattern(DisjointPattern a,DisjointPattern b) {
|
||||
|
||||
public OrPattern() {
|
||||
orlist = null;
|
||||
}
|
||||
|
||||
public OrPattern(DisjointPattern a, DisjointPattern b) {
|
||||
orlist = new DisjointPattern[2];
|
||||
orlist[0] = a;
|
||||
orlist[1] = b;
|
||||
}
|
||||
|
||||
|
||||
public OrPattern(ArrayList<?> list) {
|
||||
orlist = new DisjointPattern[list.size()];
|
||||
for(int i=0;i<list.size();++i)
|
||||
orlist[i] = (DisjointPattern)list.get(i);
|
||||
for (int i = 0; i < list.size(); ++i) {
|
||||
orlist[i] = (DisjointPattern) list.get(i);
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#simplifyClone()
|
||||
*/
|
||||
|
||||
@Override
|
||||
public Pattern simplifyClone() {
|
||||
for(int i=0;i<orlist.length;++i) {
|
||||
if (orlist[i].alwaysTrue())
|
||||
public Pattern simplifyClone() {
|
||||
for (int i = 0; i < orlist.length; ++i) {
|
||||
if (orlist[i].alwaysTrue()) {
|
||||
return new InstructionPattern(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ArrayList<Object> newlist = new ArrayList<Object>();
|
||||
for(int i=0;i<orlist.length;++i) {
|
||||
if (!orlist[i].alwaysFalse())
|
||||
for (int i = 0; i < orlist.length; ++i) {
|
||||
if (!orlist[i].alwaysFalse()) {
|
||||
newlist.add(orlist[i].simplifyClone());
|
||||
}
|
||||
}
|
||||
if (newlist.size()==0)
|
||||
if (newlist.size() == 0) {
|
||||
return new InstructionPattern(false);
|
||||
else if (newlist.size()==1)
|
||||
return (Pattern)newlist.get(0);
|
||||
}
|
||||
else if (newlist.size() == 1) {
|
||||
return (Pattern) newlist.get(0);
|
||||
}
|
||||
return new OrPattern(newlist);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#shiftInstruction(int)
|
||||
*/
|
||||
@Override
|
||||
public void shiftInstruction(int sa) {
|
||||
for(int i=0;i<orlist.length;++i)
|
||||
public void shiftInstruction(int sa) {
|
||||
for (int i = 0; i < orlist.length; ++i) {
|
||||
orlist[i].shiftInstruction(sa);
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#doOr(ghidra.app.plugin.processors.sleigh.Pattern, int)
|
||||
*/
|
||||
@Override
|
||||
public Pattern doOr(Pattern b, int sa) {
|
||||
public Pattern doOr(Pattern b, int sa) {
|
||||
ArrayList<Object> newlist = new ArrayList<Object>();
|
||||
|
||||
for(int i=0;i<orlist.length;++i)
|
||||
|
||||
for (int i = 0; i < orlist.length; ++i) {
|
||||
newlist.add(orlist[i].simplifyClone());
|
||||
if (sa < 0) {
|
||||
for(int i=0;i<orlist.length;++i)
|
||||
orlist[i].shiftInstruction(-sa);
|
||||
}
|
||||
|
||||
if (sa < 0) {
|
||||
for (int i = 0; i < orlist.length; ++i) {
|
||||
orlist[i].shiftInstruction(-sa);
|
||||
}
|
||||
}
|
||||
|
||||
if (b instanceof OrPattern) {
|
||||
OrPattern b2 = (OrPattern)b;
|
||||
for(int i=0;i<b2.orlist.length;++i)
|
||||
OrPattern b2 = (OrPattern) b;
|
||||
for (int i = 0; i < b2.orlist.length; ++i) {
|
||||
newlist.add(b2.orlist[i].simplifyClone());
|
||||
}
|
||||
}
|
||||
else {
|
||||
newlist.add(b.simplifyClone());
|
||||
}
|
||||
if (sa > 0) {
|
||||
for(int i=0;i<newlist.size();++i)
|
||||
((Pattern)newlist.get(i)).shiftInstruction(sa);
|
||||
for (int i = 0; i < newlist.size(); ++i) {
|
||||
((Pattern) newlist.get(i)).shiftInstruction(sa);
|
||||
}
|
||||
}
|
||||
return new OrPattern(newlist);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#doAnd(ghidra.app.plugin.processors.sleigh.Pattern, int)
|
||||
*/
|
||||
@Override
|
||||
public Pattern doAnd(Pattern b, int sa) {
|
||||
public Pattern doAnd(Pattern b, int sa) {
|
||||
DisjointPattern tmp;
|
||||
ArrayList<Object> newlist = new ArrayList<Object>();
|
||||
if (b instanceof OrPattern) {
|
||||
OrPattern b2 = (OrPattern)b;
|
||||
for(int i=0;i<orlist.length;++i) {
|
||||
for(int j=0;j<b2.orlist.length;++j) {
|
||||
tmp = (DisjointPattern)orlist[i].doAnd(b2.orlist[j],sa);
|
||||
OrPattern b2 = (OrPattern) b;
|
||||
for (int i = 0; i < orlist.length; ++i) {
|
||||
for (int j = 0; j < b2.orlist.length; ++j) {
|
||||
tmp = (DisjointPattern) orlist[i].doAnd(b2.orlist[j], sa);
|
||||
newlist.add(tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for(int i=0;i<orlist.length;++i) {
|
||||
tmp = (DisjointPattern)orlist[i].doAnd(b,sa);
|
||||
for (int i = 0; i < orlist.length; ++i) {
|
||||
tmp = (DisjointPattern) orlist[i].doAnd(b, sa);
|
||||
newlist.add(tmp);
|
||||
}
|
||||
}
|
||||
return new OrPattern(newlist);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.pattern.Pattern#isMatch(ghidra.app.plugin.processors.sleigh.ParserWalker, ghidra.app.plugin.processors.sleigh.SleighDebugLogger)
|
||||
*/
|
||||
@Override
|
||||
public boolean isMatch(ParserWalker walker, SleighDebugLogger debug) throws MemoryAccessException {
|
||||
public boolean isMatch(ParserWalker walker, SleighDebugLogger debug)
|
||||
throws MemoryAccessException {
|
||||
boolean match = false;
|
||||
for(int i=0;i<orlist.length;++i) {
|
||||
for (int i = 0; i < orlist.length; ++i) {
|
||||
debugNextMatch(debug, i);
|
||||
if (orlist[i].isMatch(walker, debug)) {
|
||||
match = true;
|
||||
|
@ -148,9 +147,9 @@ public class OrPattern extends Pattern {
|
|||
}
|
||||
}
|
||||
debugDone(debug, match);
|
||||
return match;
|
||||
return match;
|
||||
}
|
||||
|
||||
|
||||
private void debugDone(SleighDebugLogger debug, boolean match) {
|
||||
if (debug != null) {
|
||||
debug.endPatternGroup(match);
|
||||
|
@ -175,72 +174,60 @@ public class OrPattern extends Pattern {
|
|||
debug.indent();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#numDisjoint()
|
||||
*/
|
||||
@Override
|
||||
public int numDisjoint() {
|
||||
public int numDisjoint() {
|
||||
return orlist.length;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#getDisjoint(int)
|
||||
*/
|
||||
@Override
|
||||
public DisjointPattern getDisjoint(int i) {
|
||||
public DisjointPattern getDisjoint(int i) {
|
||||
return orlist[i];
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#alwaysTrue()
|
||||
*/
|
||||
@Override
|
||||
public boolean alwaysTrue() {
|
||||
for(int i=0;i<orlist.length;++i) {
|
||||
if (orlist[i].alwaysTrue()) return true;
|
||||
public boolean alwaysTrue() {
|
||||
for (int i = 0; i < orlist.length; ++i) {
|
||||
if (orlist[i].alwaysTrue()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#alwaysFalse()
|
||||
*/
|
||||
@Override
|
||||
public boolean alwaysFalse() {
|
||||
for(int i=0;i<orlist.length;++i) {
|
||||
if (!orlist[i].alwaysFalse()) return false;
|
||||
public boolean alwaysFalse() {
|
||||
for (int i = 0; i < orlist.length; ++i) {
|
||||
if (!orlist[i].alwaysFalse()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#alwaysInstructionTrue()
|
||||
*/
|
||||
@Override
|
||||
public boolean alwaysInstructionTrue() {
|
||||
for(int i=0;i<orlist.length;++i) {
|
||||
if (!orlist[i].alwaysInstructionTrue()) return false;
|
||||
public boolean alwaysInstructionTrue() {
|
||||
for (int i = 0; i < orlist.length; ++i) {
|
||||
if (!orlist[i].alwaysInstructionTrue()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Pattern#restoreXml(org.jdom.Element)
|
||||
*/
|
||||
@Override
|
||||
public void restoreXml(XmlPullParser parser) {
|
||||
XmlElement el = parser.start("or_pat");
|
||||
ArrayList<DisjointPattern> ors = new ArrayList<DisjointPattern>();
|
||||
XmlElement peek = parser.peek();
|
||||
while (!peek.isEnd()) {
|
||||
ors.add(DisjointPattern.restoreDisjoint(parser));
|
||||
}
|
||||
public void decode(Decoder decoder) throws DecoderException {
|
||||
int el = decoder.openElement(ELEM_OR_PAT);
|
||||
ArrayList<DisjointPattern> ors = new ArrayList<DisjointPattern>();
|
||||
int peek = decoder.peekElement();
|
||||
while (peek != 0) {
|
||||
ors.add(DisjointPattern.decodeDisjoint(decoder));
|
||||
}
|
||||
orlist = new DisjointPattern[ors.size()];
|
||||
int i = 0;
|
||||
for (DisjointPattern pat : ors) {
|
||||
orlist[i++] = pat;
|
||||
}
|
||||
parser.end(el);
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -20,13 +19,13 @@
|
|||
*/
|
||||
package ghidra.app.plugin.processors.sleigh.pattern;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.*;
|
||||
import ghidra.program.model.mem.*;
|
||||
import ghidra.xml.*;
|
||||
import ghidra.app.plugin.processors.sleigh.ParserWalker;
|
||||
import ghidra.app.plugin.processors.sleigh.SleighDebugLogger;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.program.model.pcode.Decoder;
|
||||
import ghidra.program.model.pcode.DecoderException;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* A pattern which either matches or doesnt match a particular
|
||||
* InstructionContext. In particular, the bits comprising the
|
||||
* current instruction in the executable, and possible other
|
||||
|
@ -34,14 +33,25 @@ import ghidra.xml.*;
|
|||
*/
|
||||
public abstract class Pattern {
|
||||
public abstract Pattern simplifyClone();
|
||||
|
||||
public abstract void shiftInstruction(int sa);
|
||||
public abstract Pattern doOr(Pattern b,int sa);
|
||||
public abstract Pattern doAnd(Pattern b,int sa);
|
||||
public abstract boolean isMatch(ParserWalker walker, SleighDebugLogger debug) throws MemoryAccessException;
|
||||
|
||||
public abstract Pattern doOr(Pattern b, int sa);
|
||||
|
||||
public abstract Pattern doAnd(Pattern b, int sa);
|
||||
|
||||
public abstract boolean isMatch(ParserWalker walker, SleighDebugLogger debug)
|
||||
throws MemoryAccessException;
|
||||
|
||||
public abstract int numDisjoint();
|
||||
|
||||
public abstract DisjointPattern getDisjoint(int i);
|
||||
|
||||
public abstract boolean alwaysTrue();
|
||||
|
||||
public abstract boolean alwaysFalse();
|
||||
|
||||
public abstract boolean alwaysInstructionTrue();
|
||||
public abstract void restoreXml(XmlPullParser parser);
|
||||
|
||||
public abstract void decode(Decoder decoder) throws DecoderException;
|
||||
}
|
||||
|
|
|
@ -19,18 +19,17 @@
|
|||
*/
|
||||
package ghidra.app.plugin.processors.sleigh.pattern;
|
||||
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.ParserWalker;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.program.model.pcode.Decoder;
|
||||
import ghidra.program.model.pcode.DecoderException;
|
||||
import ghidra.util.NumericUtilities;
|
||||
import ghidra.util.xml.SpecXmlUtils;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* A mask/value pair viewed as two bitstreams
|
||||
*/
|
||||
public class PatternBlock {
|
||||
|
@ -43,10 +42,12 @@ public class PatternBlock {
|
|||
int delsize = end - start;
|
||||
int newsize = array.length - delsize;
|
||||
int[] res = new int[newsize];
|
||||
for (int i = 0; i < start; ++i)
|
||||
for (int i = 0; i < start; ++i) {
|
||||
res[i] = array[i];
|
||||
for (int i = end; i < array.length; ++i)
|
||||
}
|
||||
for (int i = end; i < array.length; ++i) {
|
||||
res[i - delsize] = array[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -104,8 +105,9 @@ public class PatternBlock {
|
|||
while (iter1 != 0) {
|
||||
--iter1;
|
||||
--iter2;
|
||||
if (maskvec[iter1] != 0)
|
||||
if (maskvec[iter1] != 0) {
|
||||
break; // Find last non-zero
|
||||
}
|
||||
}
|
||||
if (iter1 != maskvec.length) {
|
||||
iter1++; // Find first zero,in last zero chain
|
||||
|
@ -142,10 +144,12 @@ public class PatternBlock {
|
|||
|
||||
public PatternBlock(boolean tf) {
|
||||
offset = 0;
|
||||
if (tf)
|
||||
if (tf) {
|
||||
nonzerosize = 0;
|
||||
else
|
||||
}
|
||||
else {
|
||||
nonzerosize = -1;
|
||||
}
|
||||
maskvec = null;
|
||||
valvec = null;
|
||||
}
|
||||
|
@ -193,8 +197,9 @@ public class PatternBlock {
|
|||
int maxlength = (getLength() > b.getLength()) ? getLength() : b.getLength();
|
||||
|
||||
int asize = maxlength / 4;
|
||||
if (maxlength % 4 != 0)
|
||||
if (maxlength % 4 != 0) {
|
||||
asize += 1;
|
||||
}
|
||||
res.maskvec = new int[asize];
|
||||
res.valvec = new int[asize];
|
||||
res.offset = 0;
|
||||
|
@ -206,17 +211,20 @@ public class PatternBlock {
|
|||
val1 = getValue(offset1 * 8, 32);
|
||||
mask2 = b.getMask(offset1 * 8, 32);
|
||||
val2 = b.getValue(offset1 * 8, 32);
|
||||
if (((mask2 & mask1) & val2) != ((mask2 & mask1) & val1))
|
||||
if (((mask2 & mask1) & val2) != ((mask2 & mask1) & val1)) {
|
||||
break; // Impossible pattern
|
||||
}
|
||||
res.maskvec[i] = mask1 | mask2;
|
||||
res.valvec[i] = val1 | val2;
|
||||
offset1 += 4;
|
||||
i += 1;
|
||||
}
|
||||
if (offset1 < maxlength) // If pattern is impossible
|
||||
if (offset1 < maxlength) { // If pattern is impossible
|
||||
res.nonzerosize = -1;
|
||||
else
|
||||
}
|
||||
else { // If pattern is impossible
|
||||
res.nonzerosize = maxlength;
|
||||
}
|
||||
res.normalize();
|
||||
return res;
|
||||
}
|
||||
|
@ -228,16 +236,19 @@ public class PatternBlock {
|
|||
int sbit = 0;
|
||||
while (sbit < length) {
|
||||
tmplength = length - sbit;
|
||||
if (tmplength > 32)
|
||||
if (tmplength > 32) {
|
||||
tmplength = 32;
|
||||
}
|
||||
mask1 = getMask(sbit, tmplength);
|
||||
value1 = getValue(sbit, tmplength);
|
||||
mask2 = op2.getMask(sbit, tmplength);
|
||||
value2 = op2.getValue(sbit, tmplength);
|
||||
if ((mask1 & mask2) != mask2)
|
||||
if ((mask1 & mask2) != mask2) {
|
||||
return false;
|
||||
if ((value1 & mask2) != (value2 & mask2))
|
||||
}
|
||||
if ((value1 & mask2) != (value2 & mask2)) {
|
||||
return false;
|
||||
}
|
||||
sbit += tmplength;
|
||||
}
|
||||
return true;
|
||||
|
@ -250,16 +261,19 @@ public class PatternBlock {
|
|||
int sbit = 0;
|
||||
while (sbit < length) {
|
||||
tmplength = length - sbit;
|
||||
if (tmplength > 32)
|
||||
if (tmplength > 32) {
|
||||
tmplength = 32;
|
||||
}
|
||||
mask1 = getMask(sbit, tmplength);
|
||||
value1 = getValue(sbit, tmplength);
|
||||
mask2 = op2.getMask(sbit, tmplength);
|
||||
value2 = op2.getValue(sbit, tmplength);
|
||||
if (mask1 != mask2)
|
||||
if (mask1 != mask2) {
|
||||
return false;
|
||||
if ((mask1 & value1) != (mask2 & value2))
|
||||
}
|
||||
if ((mask1 & value1) != (mask2 & value2)) {
|
||||
return false;
|
||||
}
|
||||
sbit += tmplength;
|
||||
}
|
||||
return true;
|
||||
|
@ -281,17 +295,21 @@ public class PatternBlock {
|
|||
int wordnum2 = (startbit + size - 1) / 32;
|
||||
int res;
|
||||
|
||||
if ((wordnum1 < 0) || (wordnum1 >= maskvec.length))
|
||||
if ((wordnum1 < 0) || (wordnum1 >= maskvec.length)) {
|
||||
res = 0;
|
||||
else
|
||||
}
|
||||
else {
|
||||
res = maskvec[wordnum1];
|
||||
}
|
||||
res <<= shift;
|
||||
if (wordnum1 != wordnum2) {
|
||||
int tmp;
|
||||
if ((wordnum2 < 0) || (wordnum2 >= maskvec.length))
|
||||
if ((wordnum2 < 0) || (wordnum2 >= maskvec.length)) {
|
||||
tmp = 0;
|
||||
else
|
||||
}
|
||||
else {
|
||||
tmp = maskvec[wordnum2];
|
||||
}
|
||||
res |= (tmp >>> (32 - shift));
|
||||
}
|
||||
res >>>= 32 - size;
|
||||
|
@ -305,17 +323,21 @@ public class PatternBlock {
|
|||
int wordnum2 = (startbit + size - 1) / 32;
|
||||
int res;
|
||||
|
||||
if ((wordnum1 < 0) || (wordnum1 >= valvec.length))
|
||||
if ((wordnum1 < 0) || (wordnum1 >= valvec.length)) {
|
||||
res = 0;
|
||||
else
|
||||
}
|
||||
else {
|
||||
res = valvec[wordnum1];
|
||||
}
|
||||
res <<= shift;
|
||||
if (wordnum1 != wordnum2) {
|
||||
int tmp;
|
||||
if ((wordnum2 < 0) || (wordnum2 >= valvec.length))
|
||||
if ((wordnum2 < 0) || (wordnum2 >= valvec.length)) {
|
||||
tmp = 0;
|
||||
else
|
||||
}
|
||||
else {
|
||||
tmp = valvec[wordnum2];
|
||||
}
|
||||
res |= (tmp >>> (32 - shift));
|
||||
}
|
||||
res >>>= 32 - size;
|
||||
|
@ -331,14 +353,16 @@ public class PatternBlock {
|
|||
}
|
||||
|
||||
public boolean isInstructionMatch(ParserWalker walker) {
|
||||
if (nonzerosize <= 0)
|
||||
if (nonzerosize <= 0) {
|
||||
return (nonzerosize == 0);
|
||||
}
|
||||
int off = offset;
|
||||
try {
|
||||
for (int i = 0; i < maskvec.length; ++i) {
|
||||
int data = walker.getInstructionBytes(off, 4);
|
||||
if ((maskvec[i] & data) != valvec[i])
|
||||
if ((maskvec[i] & data) != valvec[i]) {
|
||||
return false;
|
||||
}
|
||||
off += 4;
|
||||
}
|
||||
return true;
|
||||
|
@ -349,37 +373,39 @@ public class PatternBlock {
|
|||
}
|
||||
|
||||
public boolean isContextMatch(ParserWalker walker) {
|
||||
if (nonzerosize <= 0)
|
||||
if (nonzerosize <= 0) {
|
||||
return (nonzerosize == 0);
|
||||
}
|
||||
int off = offset;
|
||||
for (int i = 0; i < maskvec.length; ++i) {
|
||||
int data = walker.getContextBytes(off, 4);
|
||||
if ((maskvec[i] & data) != valvec[i])
|
||||
if ((maskvec[i] & data) != valvec[i]) {
|
||||
return false;
|
||||
}
|
||||
off += 4;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void restoreXml(XmlPullParser parser) {
|
||||
XmlElement el = parser.start("pat_block");
|
||||
offset = SpecXmlUtils.decodeInt(el.getAttribute("offset"));
|
||||
nonzerosize = SpecXmlUtils.decodeInt(el.getAttribute("nonzero"));
|
||||
ArrayList<String> masks = new ArrayList<>();
|
||||
ArrayList<String> vals = new ArrayList<>();
|
||||
XmlElement subel;
|
||||
while ((subel = parser.softStart("mask_word")) != null) {
|
||||
masks.add(subel.getAttribute("mask"));
|
||||
vals.add(subel.getAttribute("val"));
|
||||
parser.end(subel);
|
||||
public void decode(Decoder decoder) throws DecoderException {
|
||||
int el = decoder.openElement(ELEM_PAT_BLOCK);
|
||||
offset = (int) decoder.readSignedInteger(ATTRIB_OFF);
|
||||
nonzerosize = (int) decoder.readSignedInteger(ATTRIB_NONZERO);
|
||||
ArrayList<Integer> masks = new ArrayList<>();
|
||||
ArrayList<Integer> vals = new ArrayList<>();
|
||||
while (decoder.peekElement() == ELEM_MASK_WORD.id()) {
|
||||
decoder.openElement();
|
||||
masks.add((int) decoder.readUnsignedInteger(ATTRIB_MASK));
|
||||
vals.add((int) decoder.readUnsignedInteger(ATTRIB_VAL));
|
||||
decoder.closeElement(ELEM_MASK_WORD.id());
|
||||
}
|
||||
maskvec = new int[masks.size()];
|
||||
valvec = new int[vals.size()];
|
||||
for (int i = 0; i < maskvec.length; ++i) {
|
||||
maskvec[i] = SpecXmlUtils.decodeInt(masks.get(i));
|
||||
valvec[i] = SpecXmlUtils.decodeInt(vals.get(i));
|
||||
maskvec[i] = masks.get(i);
|
||||
valvec[i] = vals.get(i);
|
||||
}
|
||||
parser.end(el);
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -19,15 +19,14 @@
|
|||
*/
|
||||
package ghidra.app.plugin.processors.sleigh.symbol;
|
||||
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
|
||||
import ghidra.app.plugin.processors.sleigh.expression.*;
|
||||
import ghidra.util.xml.SpecXmlUtils;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
import ghidra.program.model.pcode.Decoder;
|
||||
import ghidra.program.model.pcode.DecoderException;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* A ValueSymbol that gets its semantic value from contiguous bits
|
||||
* in a VarnodeSymbol. This serves as an embedding of a ContextOp
|
||||
* into an actual Varnode and is probably only relevant at compile time
|
||||
|
@ -35,11 +34,13 @@ import ghidra.xml.XmlPullParser;
|
|||
public class ContextSymbol extends ValueSymbol {
|
||||
|
||||
private VarnodeSymbol vn;
|
||||
private int low,high; // Bit range of context value
|
||||
private int low, high; // Bit range of context value
|
||||
private boolean flow = true; // indicates that context should follow flow
|
||||
|
||||
public VarnodeSymbol getVarnode() { return vn; }
|
||||
|
||||
|
||||
public VarnodeSymbol getVarnode() {
|
||||
return vn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get starting bit of context value within its context register.
|
||||
* @return the starting bit
|
||||
|
@ -74,20 +75,39 @@ public class ContextSymbol extends ValueSymbol {
|
|||
public int getInternalHigh() {
|
||||
return ((ContextField) patval).getEndBit();
|
||||
}
|
||||
public boolean followsFlow() { return flow; }
|
||||
|
||||
|
||||
public boolean followsFlow() {
|
||||
return flow;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreXml(XmlPullParser parser,SleighLanguage sleigh) {
|
||||
XmlElement el = parser.start("context_sym");
|
||||
int id = SpecXmlUtils.decodeInt(el.getAttribute("varnode"));
|
||||
public void decode(Decoder decoder, SleighLanguage sleigh) throws DecoderException {
|
||||
// int el = decoder.openElement(ELEM_CONTEXT_SYM);
|
||||
flow = false;
|
||||
int id = (int) decoder.readUnsignedInteger(ATTRIB_VARNODE);
|
||||
SymbolTable symtab = sleigh.getSymbolTable();
|
||||
vn = (VarnodeSymbol)symtab.findSymbol(id);
|
||||
low = SpecXmlUtils.decodeInt(el.getAttribute("low"));
|
||||
if (el.hasAttribute("flow")) {
|
||||
flow = SpecXmlUtils.decodeBoolean(el.getAttribute("flow"));
|
||||
vn = (VarnodeSymbol) symtab.findSymbol(id);
|
||||
int attrib = decoder.getNextAttributeId();
|
||||
boolean lowMissing = true;
|
||||
boolean highMissing = true;
|
||||
while (attrib != 0) {
|
||||
if (attrib == ATTRIB_LOW.id()) {
|
||||
low = (int) decoder.readSignedInteger();
|
||||
lowMissing = false;
|
||||
}
|
||||
else if (attrib == ATTRIB_HIGH.id()) {
|
||||
high = (int) decoder.readSignedInteger();
|
||||
highMissing = false;
|
||||
}
|
||||
else if (attrib == ATTRIB_FLOW.id()) {
|
||||
flow = decoder.readBool();
|
||||
}
|
||||
attrib = decoder.getNextAttributeId();
|
||||
}
|
||||
high = SpecXmlUtils.decodeInt(el.getAttribute("high"));
|
||||
patval = (PatternValue)PatternExpression.restoreExpression(parser,sleigh);
|
||||
parser.end(el);
|
||||
if (lowMissing || highMissing) {
|
||||
throw new DecoderException("Missing high/low attributes");
|
||||
}
|
||||
patval = (PatternValue) PatternExpression.decodeExpression(decoder, sleigh);
|
||||
decoder.closeElement(ELEM_CONTEXT_SYM.id());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -20,63 +19,54 @@
|
|||
*/
|
||||
package ghidra.app.plugin.processors.sleigh.symbol;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.*;
|
||||
import ghidra.app.plugin.processors.sleigh.expression.*;
|
||||
import ghidra.program.model.mem.*;
|
||||
import ghidra.xml.*;
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.*;
|
||||
import ghidra.app.plugin.processors.sleigh.expression.EndInstructionValue;
|
||||
import ghidra.app.plugin.processors.sleigh.expression.PatternExpression;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.program.model.pcode.Decoder;
|
||||
import ghidra.program.model.pcode.DecoderException;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* Symbol with semantic value equal to offset of address immediately
|
||||
* after current instruction
|
||||
*/
|
||||
public class EndSymbol extends SpecificSymbol {
|
||||
|
||||
private PatternExpression patexp;
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.symbol.TripleSymbol#getPatternExpression()
|
||||
*/
|
||||
|
||||
@Override
|
||||
public PatternExpression getPatternExpression() {
|
||||
public PatternExpression getPatternExpression() {
|
||||
return patexp;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.symbol.TripleSymbol#getFixedHandle(ghidra.app.plugin.processors.sleigh.FixedHandle, ghidra.app.plugin.processors.sleigh.ParserWalker)
|
||||
*/
|
||||
@Override
|
||||
public void getFixedHandle(FixedHandle hand, ParserWalker walker) {
|
||||
public void getFixedHandle(FixedHandle hand, ParserWalker walker) {
|
||||
hand.space = walker.getCurSpace();
|
||||
hand.offset_space = null;
|
||||
hand.offset_offset = walker.getNaddr().getOffset();
|
||||
hand.size = hand.space.getPointerSize();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.symbol.TripleSymbol#print(ghidra.app.plugin.processors.sleigh.ParserWalker)
|
||||
*/
|
||||
@Override
|
||||
public String print(ParserWalker walker) throws MemoryAccessException {
|
||||
public String print(ParserWalker walker) throws MemoryAccessException {
|
||||
long val = walker.getNaddr().getOffset();
|
||||
return "0x"+Long.toHexString(val);
|
||||
return "0x" + Long.toHexString(val);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printList(ParserWalker walker, ArrayList<Object> list) {
|
||||
public void printList(ParserWalker walker, ArrayList<Object> list) {
|
||||
list.add(walker.getParentHandle());
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.symbol.Symbol#restoreXml(org.jdom.Element, ghidra.app.plugin.processors.sleigh.SleighLanguage)
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void restoreXml(XmlPullParser parser, SleighLanguage sleigh) {
|
||||
XmlElement element = parser.start("end_sym");
|
||||
public void decode(Decoder decoder, SleighLanguage sleigh) throws DecoderException {
|
||||
// int el = decoder.openElement(ELEM_END_SYM);
|
||||
patexp = new EndInstructionValue();
|
||||
parser.end(element);
|
||||
decoder.closeElement(ELEM_END_SYM.id());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -20,50 +19,43 @@
|
|||
*/
|
||||
package ghidra.app.plugin.processors.sleigh.symbol;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.*;
|
||||
import ghidra.xml.*;
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.*;
|
||||
import ghidra.program.model.pcode.Decoder;
|
||||
import ghidra.program.model.pcode.DecoderException;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* A pattern with no semantic or printing content, that will match
|
||||
* any pattern.
|
||||
*/
|
||||
public class EpsilonSymbol extends PatternlessSymbol {
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.symbol.TripleSymbol#getFixedHandle(ghidra.app.plugin.processors.sleigh.FixedHandle, ghidra.app.plugin.processors.sleigh.ParserWalker)
|
||||
*/
|
||||
@Override
|
||||
public void getFixedHandle(FixedHandle hand, ParserWalker walker) {
|
||||
public void getFixedHandle(FixedHandle hand, ParserWalker walker) {
|
||||
hand.space = walker.getConstSpace();
|
||||
hand.offset_space = null; // Not a dynamic value
|
||||
hand.offset_offset = 0;
|
||||
hand.size = 0; // Cannot provide size
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.symbol.TripleSymbol#print(ghidra.app.plugin.processors.sleigh.ParserWalker)
|
||||
*/
|
||||
@Override
|
||||
public String print(ParserWalker walker) {
|
||||
public String print(ParserWalker walker) {
|
||||
return "0";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printList(ParserWalker walker, ArrayList<Object> list) {
|
||||
public void printList(ParserWalker walker, ArrayList<Object> list) {
|
||||
list.add(walker.getParentHandle());
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Symbol#restoreXml(org.jdom.Element, ghidra.program.model.address.AddressFactory)
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void restoreXml(XmlPullParser parser,SleighLanguage sleigh) {
|
||||
XmlElement element = parser.start("epsilon_sym");
|
||||
public void decode(Decoder decoder, SleighLanguage sleigh) throws DecoderException {
|
||||
// int element = decoder.openElement(ELEM_EPSILON_SYM);
|
||||
decoder.closeElement(ELEM_EPSILON_SYM.id());
|
||||
// Nothing to do
|
||||
parser.end(element);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
*/
|
||||
package ghidra.app.plugin.processors.sleigh.symbol;
|
||||
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.*;
|
||||
|
@ -26,12 +28,10 @@ import ghidra.app.plugin.processors.sleigh.expression.PatternExpression;
|
|||
import ghidra.app.plugin.processors.sleigh.expression.PatternValue;
|
||||
import ghidra.program.model.lang.UnknownInstructionException;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
import ghidra.program.model.pcode.Decoder;
|
||||
import ghidra.program.model.pcode.DecoderException;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* A ValueSymbol whose printing aspect is determined by looking
|
||||
* up the context value of the symbol in a table of strings
|
||||
*/
|
||||
|
@ -55,9 +55,6 @@ public class NameSymbol extends ValueSymbol {
|
|||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.symbol.TripleSymbol#resolve(ghidra.app.plugin.processors.sleigh.ParserWalker, ghidra.app.plugin.processors.sleigh.SleighDebugLogger)
|
||||
*/
|
||||
@Override
|
||||
public Constructor resolve(ParserWalker walker, SleighDebugLogger debug)
|
||||
throws MemoryAccessException, UnknownInstructionException {
|
||||
|
@ -75,42 +72,43 @@ public class NameSymbol extends ValueSymbol {
|
|||
return null;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.symbol.TripleSymbol#print(ghidra.app.plugin.processors.sleigh.ParserWalker)
|
||||
*/
|
||||
@Override
|
||||
public String print(ParserWalker walker) throws MemoryAccessException {
|
||||
int ind = (int) getPatternValue().getValue(walker);
|
||||
return nametable[ind];
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.symbol.TripleSymbol#printList(ghidra.app.plugin.processors.sleigh.ParserWalker, java.util.ArrayList)
|
||||
*/
|
||||
@Override
|
||||
public void printList(ParserWalker walker, ArrayList<Object> list)
|
||||
throws MemoryAccessException {
|
||||
int ind = (int) getPatternValue().getValue(walker);
|
||||
String token = nametable[ind];
|
||||
for (int i = 0; i < token.length(); ++i)
|
||||
for (int i = 0; i < token.length(); ++i) {
|
||||
list.add(Character.valueOf(token.charAt(i)));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreXml(XmlPullParser parser, SleighLanguage sleigh) {
|
||||
XmlElement el = parser.start("name_sym");
|
||||
patval = (PatternValue) PatternExpression.restoreExpression(parser, sleigh);
|
||||
public void decode(Decoder decoder, SleighLanguage sleigh) throws DecoderException {
|
||||
// int el = decoder.openElement(ELEM_NAME_SYM);
|
||||
patval = (PatternValue) PatternExpression.decodeExpression(decoder, sleigh);
|
||||
ArrayList<String> names = new ArrayList<>();
|
||||
XmlElement nametab;
|
||||
while ((nametab = parser.softStart("nametab")) != null) {
|
||||
names.add(nametab.getAttribute("name"));
|
||||
parser.end(nametab);
|
||||
while (decoder.peekElement() == ELEM_NAMETAB.id()) {
|
||||
decoder.openElement();
|
||||
int attrib = decoder.getNextAttributeId();
|
||||
if (attrib == ATTRIB_NAME.id()) {
|
||||
names.add(decoder.readString());
|
||||
}
|
||||
else {
|
||||
names.add(null);
|
||||
}
|
||||
decoder.closeElement(ELEM_NAMETAB.id());
|
||||
}
|
||||
nametable = new String[names.size()];
|
||||
for (int i = 0; i < nametable.length; ++i) {
|
||||
nametable[i] = names.get(i);
|
||||
}
|
||||
checkTableFill();
|
||||
parser.end(el);
|
||||
decoder.closeElement(ELEM_NAME_SYM.id());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,32 +15,32 @@
|
|||
*/
|
||||
package ghidra.app.plugin.processors.sleigh.symbol;
|
||||
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.*;
|
||||
import ghidra.app.plugin.processors.sleigh.expression.Next2InstructionValue;
|
||||
import ghidra.app.plugin.processors.sleigh.expression.PatternExpression;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
import ghidra.program.model.pcode.Decoder;
|
||||
import ghidra.program.model.pcode.DecoderException;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* Symbol with semantic value equal to offset of address immediately
|
||||
* after the next instruction (inst_next2)
|
||||
*/
|
||||
public class Next2Symbol extends SpecificSymbol {
|
||||
|
||||
private PatternExpression patexp;
|
||||
|
||||
|
||||
@Override
|
||||
public PatternExpression getPatternExpression() {
|
||||
public PatternExpression getPatternExpression() {
|
||||
return patexp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getFixedHandle(FixedHandle hand, ParserWalker walker) {
|
||||
public void getFixedHandle(FixedHandle hand, ParserWalker walker) {
|
||||
hand.space = walker.getCurSpace();
|
||||
hand.offset_space = null;
|
||||
hand.offset_offset = walker.getN2addr().getOffset();
|
||||
|
@ -48,21 +48,21 @@ public class Next2Symbol extends SpecificSymbol {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String print(ParserWalker walker) throws MemoryAccessException {
|
||||
public String print(ParserWalker walker) throws MemoryAccessException {
|
||||
long val = walker.getN2addr().getOffset();
|
||||
return "0x"+Long.toHexString(val);
|
||||
return "0x" + Long.toHexString(val);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printList(ParserWalker walker, ArrayList<Object> list) {
|
||||
public void printList(ParserWalker walker, ArrayList<Object> list) {
|
||||
list.add(walker.getParentHandle());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreXml(XmlPullParser parser, SleighLanguage sleigh) {
|
||||
XmlElement element = parser.start("next2_sym");
|
||||
public void decode(Decoder decoder, SleighLanguage sleigh) throws DecoderException {
|
||||
// int element = decoder.openElement(ELEM_NEXT2_SYM);
|
||||
patexp = new Next2InstructionValue();
|
||||
parser.end(element);
|
||||
decoder.closeElement(ELEM_NEXT2_SYM.id());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -19,21 +19,18 @@
|
|||
*/
|
||||
package ghidra.app.plugin.processors.sleigh.symbol;
|
||||
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.FixedHandle;
|
||||
import ghidra.app.plugin.processors.sleigh.ParserWalker;
|
||||
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
|
||||
import ghidra.app.plugin.processors.sleigh.*;
|
||||
import ghidra.app.plugin.processors.sleigh.expression.OperandValue;
|
||||
import ghidra.app.plugin.processors.sleigh.expression.PatternExpression;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.util.xml.SpecXmlUtils;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
import ghidra.program.model.pcode.Decoder;
|
||||
import ghidra.program.model.pcode.DecoderException;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* Variable representing an operand to a specific Constructor
|
||||
*/
|
||||
public class OperandSymbol extends SpecificSymbol {
|
||||
|
@ -77,17 +74,11 @@ public class OperandSymbol extends SpecificSymbol {
|
|||
return codeaddress;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.symbol.TripleSymbol#getPatternExpression()
|
||||
*/
|
||||
@Override
|
||||
public PatternExpression getPatternExpression() {
|
||||
return localexp;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.symbol.TripleSymbol#getFixedHandle(ghidra.app.plugin.processors.sleigh.FixedHandle, ghidra.app.plugin.processors.sleigh.ParserWalker)
|
||||
*/
|
||||
@Override
|
||||
public void getFixedHandle(FixedHandle hnd, ParserWalker walker) {
|
||||
FixedHandle h = walker.getFixedHandle(hand);
|
||||
|
@ -100,25 +91,26 @@ public class OperandSymbol extends SpecificSymbol {
|
|||
hnd.temp_offset = h.temp_offset;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.symbol.TripleSymbol#print(ghidra.app.plugin.processors.sleigh.ParserWalker)
|
||||
*/
|
||||
@Override
|
||||
public String print(ParserWalker walker) throws MemoryAccessException {
|
||||
String res;
|
||||
walker.pushOperand(hand);
|
||||
if (triple != null) {
|
||||
if (triple instanceof SubtableSymbol)
|
||||
if (triple instanceof SubtableSymbol) {
|
||||
res = walker.getConstructor().print(walker);
|
||||
else
|
||||
}
|
||||
else {
|
||||
res = triple.print(walker);
|
||||
}
|
||||
}
|
||||
else { // Must be expression resulting in a constant
|
||||
long val = defexp.getValue(walker);
|
||||
if (val >= 0)
|
||||
if (val >= 0) {
|
||||
res = "0x" + Long.toHexString(val);
|
||||
else
|
||||
}
|
||||
else {
|
||||
res = "-0x" + Long.toHexString(-val);
|
||||
}
|
||||
}
|
||||
walker.popOperand();
|
||||
return res;
|
||||
|
@ -129,10 +121,12 @@ public class OperandSymbol extends SpecificSymbol {
|
|||
throws MemoryAccessException {
|
||||
walker.pushOperand(hand);
|
||||
if (triple != null) {
|
||||
if (triple instanceof SubtableSymbol)
|
||||
if (triple instanceof SubtableSymbol) {
|
||||
walker.getConstructor().printList(walker, list);
|
||||
else
|
||||
}
|
||||
else {
|
||||
triple.printList(walker, list);
|
||||
}
|
||||
}
|
||||
else {
|
||||
FixedHandle handle = walker.getParentHandle();
|
||||
|
@ -144,32 +138,41 @@ public class OperandSymbol extends SpecificSymbol {
|
|||
walker.popOperand();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.symbol.Symbol#restoreXml(org.jdom.Element, ghidra.app.plugin.processors.sleigh.SleighLanguage)
|
||||
*/
|
||||
@Override
|
||||
public void restoreXml(XmlPullParser parser, SleighLanguage lang) {
|
||||
XmlElement el = parser.start("operand_sym");
|
||||
public void decode(Decoder decoder, SleighLanguage lang) throws DecoderException {
|
||||
// int el = decoder.openElement(ELEM_OPERAND_SYM);
|
||||
defexp = null;
|
||||
triple = null;
|
||||
codeaddress = false;
|
||||
|
||||
hand = SpecXmlUtils.decodeInt(el.getAttribute("index"));
|
||||
|
||||
reloffset = SpecXmlUtils.decodeInt(el.getAttribute("off"));
|
||||
offsetbase = SpecXmlUtils.decodeInt(el.getAttribute("base"));
|
||||
minimumlength = SpecXmlUtils.decodeInt(el.getAttribute("minlen"));
|
||||
String attrstr = el.getAttribute("subsym");
|
||||
if (attrstr != null) {
|
||||
int id = SpecXmlUtils.decodeInt(attrstr);
|
||||
triple = (TripleSymbol) lang.getSymbolTable().findSymbol(id);
|
||||
int attrib = decoder.getNextAttributeId();
|
||||
while (attrib != 0) {
|
||||
if (attrib == ATTRIB_INDEX.id()) {
|
||||
hand = (int) decoder.readSignedInteger();
|
||||
}
|
||||
else if (attrib == ATTRIB_OFF.id()) {
|
||||
reloffset = (int) decoder.readSignedInteger();
|
||||
}
|
||||
else if (attrib == ATTRIB_BASE.id()) {
|
||||
offsetbase = (int) decoder.readSignedInteger();
|
||||
}
|
||||
else if (attrib == ATTRIB_MINLEN.id()) {
|
||||
minimumlength = (int) decoder.readSignedInteger();
|
||||
}
|
||||
else if (attrib == ATTRIB_SUBSYM.id()) {
|
||||
int id = (int) decoder.readUnsignedInteger();
|
||||
triple = (TripleSymbol) lang.getSymbolTable().findSymbol(id);
|
||||
}
|
||||
else if (attrib == ATTRIB_CODE.id()) {
|
||||
codeaddress = decoder.readBool();
|
||||
}
|
||||
attrib = decoder.getNextAttributeId();
|
||||
}
|
||||
codeaddress = SpecXmlUtils.decodeBoolean(el.getAttribute("code"));
|
||||
|
||||
localexp = (OperandValue) PatternExpression.restoreExpression(parser, lang);
|
||||
if (!parser.peek().isEnd())
|
||||
defexp = PatternExpression.restoreExpression(parser, lang);
|
||||
parser.end(el);
|
||||
localexp = (OperandValue) PatternExpression.decodeExpression(decoder, lang);
|
||||
if (decoder.peekElement() != 0) {
|
||||
defexp = PatternExpression.decodeExpression(decoder, lang);
|
||||
}
|
||||
decoder.closeElement(ELEM_OPERAND_SYM.id());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -20,63 +19,54 @@
|
|||
*/
|
||||
package ghidra.app.plugin.processors.sleigh.symbol;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.*;
|
||||
import ghidra.app.plugin.processors.sleigh.expression.*;
|
||||
import ghidra.program.model.mem.*;
|
||||
import ghidra.xml.*;
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.*;
|
||||
import ghidra.app.plugin.processors.sleigh.expression.PatternExpression;
|
||||
import ghidra.app.plugin.processors.sleigh.expression.StartInstructionValue;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.program.model.pcode.Decoder;
|
||||
import ghidra.program.model.pcode.DecoderException;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* TripleSymbol with semantic value equal to offset of instruction's
|
||||
* current address
|
||||
*/
|
||||
public class StartSymbol extends SpecificSymbol {
|
||||
|
||||
private PatternExpression patexp;
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.symbol.TripleSymbol#getPatternExpression()
|
||||
*/
|
||||
|
||||
@Override
|
||||
public PatternExpression getPatternExpression() {
|
||||
public PatternExpression getPatternExpression() {
|
||||
return patexp;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.symbol.TripleSymbol#getFixedHandle(ghidra.app.plugin.processors.sleigh.FixedHandle, ghidra.app.plugin.processors.sleigh.ParserWalker)
|
||||
*/
|
||||
@Override
|
||||
public void getFixedHandle(FixedHandle hand, ParserWalker walker) {
|
||||
public void getFixedHandle(FixedHandle hand, ParserWalker walker) {
|
||||
hand.space = walker.getCurSpace();
|
||||
hand.offset_space = null;
|
||||
hand.offset_offset = walker.getAddr().getOffset();
|
||||
hand.size = hand.space.getPointerSize();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.symbol.TripleSymbol#print(ghidra.app.plugin.processors.sleigh.ParserWalker)
|
||||
*/
|
||||
@Override
|
||||
public String print(ParserWalker walker) throws MemoryAccessException {
|
||||
public String print(ParserWalker walker) throws MemoryAccessException {
|
||||
long val = walker.getAddr().getOffset();
|
||||
return "0x" + Long.toHexString(val);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printList(ParserWalker walker, ArrayList<Object> list) {
|
||||
public void printList(ParserWalker walker, ArrayList<Object> list) {
|
||||
list.add(walker.getParentHandle());
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.symbol.Symbol#restoreXml(org.jdom.Element, ghidra.app.plugin.processors.sleigh.SleighLanguage)
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void restoreXml(XmlPullParser parser, SleighLanguage sleigh) {
|
||||
XmlElement element = parser.start("start_sym");
|
||||
public void decode(Decoder decoder, SleighLanguage sleigh) throws DecoderException {
|
||||
// int element = decoder.openElement(ELEM_START_SYM);
|
||||
patexp = new StartInstructionValue();
|
||||
parser.end(element);
|
||||
decoder.closeElement(ELEM_START_SYM.id());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -20,18 +19,18 @@
|
|||
*/
|
||||
package ghidra.app.plugin.processors.sleigh.symbol;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.*;
|
||||
import ghidra.app.plugin.processors.sleigh.expression.*;
|
||||
import ghidra.program.model.lang.*;
|
||||
import ghidra.program.model.mem.*;
|
||||
import ghidra.util.xml.*;
|
||||
import ghidra.xml.*;
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.*;
|
||||
import ghidra.app.plugin.processors.sleigh.expression.PatternExpression;
|
||||
import ghidra.program.model.lang.UnknownInstructionException;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.program.model.pcode.Decoder;
|
||||
import ghidra.program.model.pcode.DecoderException;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* A collection of Constructors or a Symbol representing
|
||||
* one out of a family of Constructors, choosen based on InstructionContext
|
||||
*/
|
||||
|
@ -40,67 +39,61 @@ public class SubtableSymbol extends TripleSymbol {
|
|||
private Constructor[] construct; // All the constructors in this table
|
||||
private DecisionNode decisiontree; // The decision tree for this table
|
||||
|
||||
public DecisionNode getDecisionNode() { return decisiontree; }
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.symbol.TripleSymbol#resolve(ghidra.app.plugin.processors.sleigh.ParserWalker, ghidra.app.plugin.processors.sleigh.SleighDebugLogger)
|
||||
*/
|
||||
public DecisionNode getDecisionNode() {
|
||||
return decisiontree;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Constructor resolve(ParserWalker walker, SleighDebugLogger debug) throws MemoryAccessException, UnknownInstructionException {
|
||||
public Constructor resolve(ParserWalker walker, SleighDebugLogger debug)
|
||||
throws MemoryAccessException, UnknownInstructionException {
|
||||
return decisiontree.resolve(walker, debug);
|
||||
}
|
||||
|
||||
public int getNumConstructors() { return construct.length; }
|
||||
public Constructor getConstructor(int i) { return construct[i]; }
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.symbol.TripleSymbol#getPatternExpression()
|
||||
*/
|
||||
@Override
|
||||
public PatternExpression getPatternExpression() {
|
||||
throw new SleighException("Cannot use subtable in expression");
|
||||
|
||||
public int getNumConstructors() {
|
||||
return construct.length;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.symbol.TripleSymbol#getFixedHandle(ghidra.app.plugin.processors.sleigh.FixedHandle, ghidra.app.plugin.processors.sleigh.ParserWalker)
|
||||
*/
|
||||
@Override
|
||||
public void getFixedHandle(FixedHandle hand, ParserWalker walker) {
|
||||
throw new SleighException("Cannot use subtable in expression");
|
||||
public Constructor getConstructor(int i) {
|
||||
return construct[i];
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.symbol.TripleSymbol#print(ghidra.app.plugin.processors.sleigh.ParserWalker)
|
||||
*/
|
||||
@Override
|
||||
public String print(ParserWalker walker) throws MemoryAccessException {
|
||||
public PatternExpression getPatternExpression() {
|
||||
throw new SleighException("Cannot use subtable in expression");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printList(ParserWalker walker, ArrayList<Object> list) {
|
||||
public void getFixedHandle(FixedHandle hand, ParserWalker walker) {
|
||||
throw new SleighException("Cannot use subtable in expression");
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.symbol.Symbol#restoreXml(org.jdom.Element, ghidra.app.plugin.processors.sleigh.SleighLanguage)
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void restoreXml(XmlPullParser parser, SleighLanguage sleigh) throws UnknownInstructionException {
|
||||
XmlElement el = parser.start("subtable_sym");
|
||||
int numct = SpecXmlUtils.decodeInt(el.getAttribute("numct"));
|
||||
public String print(ParserWalker walker) throws MemoryAccessException {
|
||||
throw new SleighException("Cannot use subtable in expression");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printList(ParserWalker walker, ArrayList<Object> list) {
|
||||
throw new SleighException("Cannot use subtable in expression");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void decode(Decoder decoder, SleighLanguage sleigh) throws DecoderException {
|
||||
// int el = decoder.openElement(ELEM_SUBTABLE_SYM);
|
||||
int numct = (int) decoder.readSignedInteger(ATTRIB_NUMCT);
|
||||
construct = new Constructor[numct]; // Array must be built
|
||||
// before restoring constructors
|
||||
for(int i=0;i<numct;++i) {
|
||||
// before restoring constructors
|
||||
for (int i = 0; i < numct; ++i) {
|
||||
Constructor ct = new Constructor();
|
||||
ct.setId(i);
|
||||
construct[i] = ct;
|
||||
ct.restoreXml(parser,sleigh);
|
||||
ct.decode(decoder, sleigh);
|
||||
}
|
||||
if (!parser.peek().isEnd()) {
|
||||
if (decoder.peekElement() != 0) {
|
||||
decisiontree = new DecisionNode();
|
||||
decisiontree.restoreXml(parser,null,this);
|
||||
decisiontree.decode(decoder, null, this);
|
||||
}
|
||||
parser.end(el);
|
||||
decoder.closeElement(ELEM_SUBTABLE_SYM.id());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -20,32 +19,39 @@
|
|||
*/
|
||||
package ghidra.app.plugin.processors.sleigh.symbol;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.*;
|
||||
import ghidra.program.model.lang.*;
|
||||
import ghidra.util.xml.*;
|
||||
import ghidra.xml.*;
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
|
||||
import ghidra.program.model.pcode.Decoder;
|
||||
import ghidra.program.model.pcode.DecoderException;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* Base class for symbols in sleigh
|
||||
*/
|
||||
public abstract class Symbol {
|
||||
private String name;
|
||||
private int id; // Unique id across all symbols
|
||||
private int scopeid; // id of scope this symbol is in
|
||||
|
||||
public String getName() { return name; }
|
||||
public int getId() { return id; }
|
||||
public int getScopeId() { return scopeid; }
|
||||
|
||||
public void restoreHeaderXml(XmlPullParser parser) {
|
||||
XmlElement el = parser.start();
|
||||
name = el.getAttribute("name");
|
||||
id = SpecXmlUtils.decodeInt(el.getAttribute("id"));
|
||||
scopeid = SpecXmlUtils.decodeInt(el.getAttribute("scope"));
|
||||
parser.end(el);
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public abstract void restoreXml(XmlPullParser parser,SleighLanguage sleigh) throws UnknownInstructionException; // Always overridden by subclass
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public int getScopeId() {
|
||||
return scopeid;
|
||||
}
|
||||
|
||||
public void decodeHeader(Decoder decoder) throws DecoderException {
|
||||
int el = decoder.openElement();
|
||||
name = decoder.readString(ATTRIB_NAME);
|
||||
id = (int) decoder.readUnsignedInteger(ATTRIB_ID);
|
||||
scopeid = (int) decoder.readUnsignedInteger(ATTRIB_SCOPE);
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
|
||||
public abstract void decode(Decoder decoder, SleighLanguage sleigh) throws DecoderException;
|
||||
}
|
||||
|
|
|
@ -19,18 +19,16 @@
|
|||
*/
|
||||
package ghidra.app.plugin.processors.sleigh.symbol;
|
||||
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.SleighException;
|
||||
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
|
||||
import ghidra.program.model.lang.UnknownInstructionException;
|
||||
import ghidra.util.xml.SpecXmlUtils;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
import ghidra.program.model.pcode.Decoder;
|
||||
import ghidra.program.model.pcode.DecoderException;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* Full symbol table for sleigh
|
||||
*/
|
||||
public class SymbolTable {
|
||||
|
@ -38,127 +36,157 @@ public class SymbolTable {
|
|||
private UseropSymbol[] userOps; // List all user ops, indexed by index
|
||||
private SymbolScope[] table; // All SymbolScopes, indexed by id
|
||||
private SymbolScope curscope; // Current scope
|
||||
|
||||
|
||||
private SymbolScope skipScope(int i) {
|
||||
SymbolScope res = curscope;
|
||||
while(i>0) {
|
||||
if (res.getParent() == null)
|
||||
while (i > 0) {
|
||||
if (res.getParent() == null) {
|
||||
return res;
|
||||
}
|
||||
res = res.getParent();
|
||||
--i;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
private Symbol findSymbolInternal(SymbolScope scope,String nm) {
|
||||
while(scope != null) {
|
||||
|
||||
private Symbol findSymbolInternal(SymbolScope scope, String nm) {
|
||||
while (scope != null) {
|
||||
Symbol res = scope.findSymbol(nm);
|
||||
if (res != null)
|
||||
if (res != null) {
|
||||
return res;
|
||||
}
|
||||
scope = scope.getParent();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public SymbolTable() { curscope = null; }
|
||||
|
||||
public SymbolScope getCurrentScope() { return curscope; }
|
||||
|
||||
public SymbolScope getGlobalScope() { return table[0]; }
|
||||
|
||||
public void setCurrentScope(SymbolScope scope) { curscope = scope; }
|
||||
|
||||
|
||||
public SymbolTable() {
|
||||
curscope = null;
|
||||
}
|
||||
|
||||
public SymbolScope getCurrentScope() {
|
||||
return curscope;
|
||||
}
|
||||
|
||||
public SymbolScope getGlobalScope() {
|
||||
return table[0];
|
||||
}
|
||||
|
||||
public void setCurrentScope(SymbolScope scope) {
|
||||
curscope = scope;
|
||||
}
|
||||
|
||||
public Symbol findSymbol(String nm) {
|
||||
return findSymbolInternal(curscope,nm);
|
||||
return findSymbolInternal(curscope, nm);
|
||||
}
|
||||
|
||||
public Symbol findSymbol(String nm,int skip) {
|
||||
return findSymbolInternal(skipScope(skip),nm);
|
||||
public Symbol findSymbol(String nm, int skip) {
|
||||
return findSymbolInternal(skipScope(skip), nm);
|
||||
}
|
||||
|
||||
|
||||
public Symbol findGlobalSymbol(String nm) {
|
||||
return findSymbolInternal(table[0],nm);
|
||||
return findSymbolInternal(table[0], nm);
|
||||
}
|
||||
|
||||
public Symbol[] getSymbolList() {
|
||||
return symbollist;
|
||||
}
|
||||
|
||||
public Symbol[] getSymbolList() { return symbollist; }
|
||||
|
||||
public Symbol findSymbol(int id) {
|
||||
return symbollist[id];
|
||||
}
|
||||
|
||||
public void restoreXml(XmlPullParser parser, SleighLanguage sleigh) throws UnknownInstructionException {
|
||||
XmlElement el = parser.start("symbol_table");
|
||||
int scopesize = SpecXmlUtils.decodeInt(el.getAttribute("scopesize"));
|
||||
|
||||
public void decode(Decoder decoder, SleighLanguage sleigh) throws DecoderException {
|
||||
int el = decoder.openElement(ELEM_SYMBOL_TABLE);
|
||||
int scopesize = (int) decoder.readSignedInteger(ATTRIB_SCOPESIZE);
|
||||
table = new SymbolScope[scopesize];
|
||||
int symsize = SpecXmlUtils.decodeInt(el.getAttribute("symbolsize"));
|
||||
int symsize = (int) decoder.readSignedInteger(ATTRIB_SYMBOLSIZE);
|
||||
symbollist = new Symbol[symsize];
|
||||
|
||||
// Restore the scopes
|
||||
for(int i=0;i<scopesize;++i) {
|
||||
XmlElement subel = parser.start("scope");
|
||||
int id = SpecXmlUtils.decodeInt(subel.getAttribute("id"));
|
||||
int parent = SpecXmlUtils.decodeInt(subel.getAttribute("parent"));
|
||||
|
||||
// Decode the scopes
|
||||
for (int i = 0; i < scopesize; ++i) {
|
||||
int subel = decoder.openElement(ELEM_SCOPE);
|
||||
int id = (int) decoder.readUnsignedInteger(ATTRIB_ID);
|
||||
int parent = (int) decoder.readUnsignedInteger(ATTRIB_PARENT);
|
||||
SymbolScope sscope;
|
||||
if (parent==id)
|
||||
if (parent == id) {
|
||||
sscope = null;
|
||||
else
|
||||
}
|
||||
else {
|
||||
sscope = table[parent];
|
||||
table[id] = new SymbolScope(sscope,id);
|
||||
parser.end(subel);
|
||||
}
|
||||
table[id] = new SymbolScope(sscope, id);
|
||||
decoder.closeElement(subel);
|
||||
}
|
||||
curscope = table[0]; // Initial scope is global scope
|
||||
|
||||
for(int i=0;i<symsize;++i) { // Restore the symbol shells
|
||||
restoreSymbolHeader(parser);
|
||||
|
||||
for (int i = 0; i < symsize; ++i) { // Decode the symbol shells
|
||||
decodeSymbolHeader(decoder);
|
||||
}
|
||||
|
||||
ArrayList<UseropSymbol> userops = new ArrayList<UseropSymbol>();
|
||||
XmlElement subel = parser.peek();
|
||||
while(!subel.getName().equals("symbol_table")) { // Restore the symbol content
|
||||
int id = SpecXmlUtils.decodeInt(subel.getAttribute("id"));
|
||||
while (decoder.peekElement() != 0) { // Decode the symbol content
|
||||
decoder.openElement();
|
||||
int id = (int) decoder.readUnsignedInteger(ATTRIB_ID);
|
||||
Symbol sym = findSymbol(id);
|
||||
sym.restoreXml(parser,sleigh);
|
||||
if (sym instanceof UseropSymbol)
|
||||
userops.add((UseropSymbol)sym);
|
||||
subel = parser.peek();
|
||||
sym.decode(decoder, sleigh);
|
||||
// Tag closed by decode method
|
||||
// decoder.closeElement(subel);
|
||||
if (sym instanceof UseropSymbol) {
|
||||
userops.add((UseropSymbol) sym);
|
||||
}
|
||||
}
|
||||
userOps = new UseropSymbol[userops.size()];
|
||||
userops.toArray(userOps);
|
||||
parser.end(el);
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
|
||||
public void restoreSymbolHeader(XmlPullParser parser) {
|
||||
|
||||
public void decodeSymbolHeader(Decoder decoder) throws DecoderException {
|
||||
Symbol sym;
|
||||
XmlElement el = parser.peek();
|
||||
if (el.getName().equals("userop_head"))
|
||||
int el = decoder.peekElement();
|
||||
if (el == ELEM_USEROP_HEAD.id()) {
|
||||
sym = new UseropSymbol();
|
||||
else if (el.getName().equals("epsilon_sym_head"))
|
||||
}
|
||||
else if (el == ELEM_EPSILON_SYM_HEAD.id()) {
|
||||
sym = new EpsilonSymbol();
|
||||
else if (el.getName().equals("value_sym_head"))
|
||||
}
|
||||
else if (el == ELEM_VALUE_SYM_HEAD.id()) {
|
||||
sym = new ValueSymbol();
|
||||
else if (el.getName().equals("valuemap_sym_head"))
|
||||
}
|
||||
else if (el == ELEM_VALUEMAP_SYM_HEAD.id()) {
|
||||
sym = new ValueMapSymbol();
|
||||
else if (el.getName().equals("name_sym_head"))
|
||||
}
|
||||
else if (el == ELEM_NAME_SYM_HEAD.id()) {
|
||||
sym = new NameSymbol();
|
||||
else if (el.getName().equals("varnode_sym_head"))
|
||||
}
|
||||
else if (el == ELEM_VARNODE_SYM_HEAD.id()) {
|
||||
sym = new VarnodeSymbol();
|
||||
else if (el.getName().equals("context_sym_head"))
|
||||
}
|
||||
else if (el == ELEM_CONTEXT_SYM_HEAD.id()) {
|
||||
sym = new ContextSymbol();
|
||||
else if (el.getName().equals("varlist_sym_head"))
|
||||
}
|
||||
else if (el == ELEM_VARLIST_SYM_HEAD.id()) {
|
||||
sym = new VarnodeListSymbol();
|
||||
else if (el.getName().equals("operand_sym_head"))
|
||||
}
|
||||
else if (el == ELEM_OPERAND_SYM_HEAD.id()) {
|
||||
sym = new OperandSymbol();
|
||||
else if (el.getName().equals("start_sym_head"))
|
||||
}
|
||||
else if (el == ELEM_START_SYM_HEAD.id()) {
|
||||
sym = new StartSymbol();
|
||||
else if (el.getName().equals("end_sym_head"))
|
||||
}
|
||||
else if (el == ELEM_END_SYM_HEAD.id()) {
|
||||
sym = new EndSymbol();
|
||||
else if (el.getName().equals("next2_sym_head"))
|
||||
}
|
||||
else if (el == ELEM_NEXT2_SYM_HEAD.id()) {
|
||||
sym = new Next2Symbol();
|
||||
else if (el.getName().equals("subtable_sym_head"))
|
||||
}
|
||||
else if (el == ELEM_SUBTABLE_SYM_HEAD.id()) {
|
||||
sym = new SubtableSymbol();
|
||||
else
|
||||
throw new SleighException("Bad symbol xml");
|
||||
sym.restoreHeaderXml(parser); // Restore basic elements of symbol
|
||||
}
|
||||
else {
|
||||
throw new SleighException("Bad symbol encoding");
|
||||
}
|
||||
sym.decodeHeader(decoder); // Decode basic elements of symbol
|
||||
symbollist[sym.getId()] = sym;
|
||||
table[sym.getScopeId()].addSymbol(sym);
|
||||
}
|
||||
|
@ -166,10 +194,11 @@ public class SymbolTable {
|
|||
public int getNumberOfUserDefinedOpNames() {
|
||||
return userOps.length;
|
||||
}
|
||||
|
||||
|
||||
public String getUserDefinedOpName(int index) {
|
||||
if (index < userOps.length)
|
||||
if (index < userOps.length) {
|
||||
return userOps[index].getName();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -20,26 +19,28 @@
|
|||
*/
|
||||
package ghidra.app.plugin.processors.sleigh.symbol;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.*;
|
||||
import ghidra.util.xml.*;
|
||||
import ghidra.xml.*;
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
|
||||
import ghidra.program.model.pcode.Decoder;
|
||||
import ghidra.program.model.pcode.DecoderException;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* A user-defined pcode operation (PcodeOp)
|
||||
* This is implemented as a name and a unique id which is passed
|
||||
* as the first parameter to a PcodeOp with the opcode = "CALLOTHER".
|
||||
*/
|
||||
public class UseropSymbol extends Symbol {
|
||||
private int index; // Unique id for this userop
|
||||
|
||||
public int getIndex() { return index; }
|
||||
|
||||
|
||||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreXml(XmlPullParser parser,SleighLanguage sleigh) {
|
||||
XmlElement el = parser.start("userop");
|
||||
index = SpecXmlUtils.decodeInt(el.getAttribute("index"));
|
||||
parser.end(el);
|
||||
public void decode(Decoder decoder, SleighLanguage sleigh) throws DecoderException {
|
||||
// int el = decoder.openElement(ELEM_USEROP);
|
||||
index = (int) decoder.readSignedInteger(ATTRIB_INDEX);
|
||||
decoder.closeElement(ELEM_USEROP.id());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
*/
|
||||
package ghidra.app.plugin.processors.sleigh.symbol;
|
||||
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.*;
|
||||
|
@ -22,9 +24,8 @@ import ghidra.app.plugin.processors.sleigh.expression.PatternExpression;
|
|||
import ghidra.app.plugin.processors.sleigh.expression.PatternValue;
|
||||
import ghidra.program.model.lang.UnknownInstructionException;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.util.xml.SpecXmlUtils;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
import ghidra.program.model.pcode.Decoder;
|
||||
import ghidra.program.model.pcode.DecoderException;
|
||||
|
||||
public class ValueMapSymbol extends ValueSymbol {
|
||||
private long[] valuetable; // Map from natural encoding to attached values
|
||||
|
@ -43,14 +44,12 @@ public class ValueMapSymbol extends ValueSymbol {
|
|||
long max = getPatternValue().maxValue();
|
||||
tableisfilled = (min >= 0) && (max < valuetable.length);
|
||||
for (long element : valuetable) {
|
||||
if (element == 0xBADBEEF)
|
||||
if (element == 0xBADBEEF) {
|
||||
tableisfilled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.symbol.TripleSymbol#resolve(ghidra.app.plugin.processors.sleigh.ParserWalker, ghidra.app.plugin.processors.sleigh.SleighDebugLogger)
|
||||
*/
|
||||
@Override
|
||||
public Constructor resolve(ParserWalker walker, SleighDebugLogger debug)
|
||||
throws MemoryAccessException, UnknownInstructionException {
|
||||
|
@ -68,9 +67,6 @@ public class ValueMapSymbol extends ValueSymbol {
|
|||
return null;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.symbol.TripleSymbol#getFixedHandle(ghidra.app.plugin.processors.sleigh.FixedHandle, ghidra.app.plugin.processors.sleigh.ParserWalker)
|
||||
*/
|
||||
@Override
|
||||
public void getFixedHandle(FixedHandle hand, ParserWalker walker) throws MemoryAccessException {
|
||||
int ind = (int) getPatternValue().getValue(walker);
|
||||
|
@ -87,28 +83,30 @@ public class ValueMapSymbol extends ValueSymbol {
|
|||
// ind is already known to be a valid array index via resolve
|
||||
long val = valuetable[ind];
|
||||
String res;
|
||||
if (val >= 0)
|
||||
if (val >= 0) {
|
||||
res = "0x" + Long.toHexString(val);
|
||||
else
|
||||
}
|
||||
else {
|
||||
res = "-0x" + Long.toHexString(-val);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreXml(XmlPullParser parser, SleighLanguage sleigh) {
|
||||
XmlElement el = parser.start("valuemap_sym");
|
||||
patval = (PatternValue) PatternExpression.restoreExpression(parser, sleigh);
|
||||
ArrayList<String> values = new ArrayList<>();
|
||||
XmlElement valuetab;
|
||||
while ((valuetab = parser.softStart("valuetab")) != null) {
|
||||
values.add(valuetab.getAttribute("val"));
|
||||
parser.end(valuetab);
|
||||
public void decode(Decoder decoder, SleighLanguage sleigh) throws DecoderException {
|
||||
// int el = decoder.openElement(ELEM_VALUEMAP_SYM);
|
||||
patval = (PatternValue) PatternExpression.decodeExpression(decoder, sleigh);
|
||||
ArrayList<Long> values = new ArrayList<>();
|
||||
while (decoder.peekElement() == ELEM_VALUETAB.id()) {
|
||||
decoder.openElement();
|
||||
values.add(decoder.readSignedInteger(ATTRIB_VAL));
|
||||
decoder.closeElement(ELEM_VALUETAB.id());
|
||||
}
|
||||
valuetable = new long[values.size()];
|
||||
for (int i = 0; i < valuetable.length; ++i) {
|
||||
valuetable[i] = SpecXmlUtils.decodeLong(values.get(i));
|
||||
valuetable[i] = values.get(i);
|
||||
}
|
||||
checkTableFill();
|
||||
parser.end(el);
|
||||
decoder.closeElement(ELEM_VALUEMAP_SYM.id());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -20,80 +19,67 @@
|
|||
*/
|
||||
package ghidra.app.plugin.processors.sleigh.symbol;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.*;
|
||||
import ghidra.app.plugin.processors.sleigh.expression.*;
|
||||
import ghidra.program.model.mem.*;
|
||||
import ghidra.xml.*;
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.*;
|
||||
import ghidra.app.plugin.processors.sleigh.expression.PatternExpression;
|
||||
import ghidra.app.plugin.processors.sleigh.expression.PatternValue;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.program.model.pcode.Decoder;
|
||||
import ghidra.program.model.pcode.DecoderException;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* A variable with its semantic (and printing) value equal to a fixed
|
||||
* mapping of its pattern
|
||||
*/
|
||||
public class ValueSymbol extends FamilySymbol {
|
||||
|
||||
protected PatternValue patval;
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.FamilySymbol#getPatternValue()
|
||||
*/
|
||||
|
||||
@Override
|
||||
public PatternValue getPatternValue() {
|
||||
public PatternValue getPatternValue() {
|
||||
return patval;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.TripleSymbol#getPatternExpression()
|
||||
*/
|
||||
@Override
|
||||
public PatternExpression getPatternExpression() {
|
||||
public PatternExpression getPatternExpression() {
|
||||
return patval;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.symbol.TripleSymbol#getFixedHandle(ghidra.app.plugin.processors.sleigh.FixedHandle, ghidra.app.plugin.processors.sleigh.ParserWalker)
|
||||
*/
|
||||
@Override
|
||||
public void getFixedHandle(FixedHandle hand, ParserWalker walker) throws MemoryAccessException {
|
||||
public void getFixedHandle(FixedHandle hand, ParserWalker walker) throws MemoryAccessException {
|
||||
hand.space = walker.getConstSpace();
|
||||
hand.offset_space = null;
|
||||
hand.offset_offset = patval.getValue(walker);
|
||||
hand.size = 0; // Cannot provide size
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.symbol.TripleSymbol#print(ghidra.app.plugin.processors.sleigh.ParserWalker)
|
||||
*/
|
||||
@Override
|
||||
public String print(ParserWalker walker) throws MemoryAccessException {
|
||||
public String print(ParserWalker walker) throws MemoryAccessException {
|
||||
long val = patval.getValue(walker);
|
||||
String res;
|
||||
if (val >= 0)
|
||||
if (val >= 0) {
|
||||
res = "0x" + Long.toHexString(val);
|
||||
else
|
||||
}
|
||||
else {
|
||||
res = "-0x" + Long.toHexString(-val);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.symbol.TripleSymbol#printList(ghidra.app.plugin.processors.sleigh.ParserWalker, java.util.ArrayList)
|
||||
*/
|
||||
@Override
|
||||
public void printList(ParserWalker walker, ArrayList<Object> list) throws MemoryAccessException {
|
||||
public void printList(ParserWalker walker, ArrayList<Object> list)
|
||||
throws MemoryAccessException {
|
||||
list.add(walker.getParentHandle());
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.Symbol#restoreXml(org.jdom.Element, ghidra.program.model.address.AddressFactory)
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void restoreXml(XmlPullParser parser,SleighLanguage sleigh) {
|
||||
XmlElement el = parser.start("value_sym");
|
||||
patval = (PatternValue)PatternExpression.restoreExpression(parser,sleigh);
|
||||
parser.end(el);
|
||||
public void decode(Decoder decoder, SleighLanguage sleigh) throws DecoderException {
|
||||
// int el = decoder.openElement(ELEM_VALUE_SYM);
|
||||
patval = (PatternValue) PatternExpression.decodeExpression(decoder, sleigh);
|
||||
decoder.closeElementSkipping(ELEM_VALUE_SYM.id());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -19,28 +19,19 @@
|
|||
*/
|
||||
package ghidra.app.plugin.processors.sleigh.symbol;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.Constructor;
|
||||
import ghidra.app.plugin.processors.sleigh.FixedHandle;
|
||||
import ghidra.app.plugin.processors.sleigh.ParserWalker;
|
||||
import ghidra.app.plugin.processors.sleigh.SleighDebugLogger;
|
||||
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
|
||||
import ghidra.app.plugin.processors.sleigh.VarnodeData;
|
||||
import java.util.*;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.*;
|
||||
import ghidra.app.plugin.processors.sleigh.expression.PatternExpression;
|
||||
import ghidra.app.plugin.processors.sleigh.expression.PatternValue;
|
||||
import ghidra.program.model.lang.UnknownInstructionException;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.util.xml.SpecXmlUtils;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
import ghidra.program.model.pcode.Decoder;
|
||||
import ghidra.program.model.pcode.DecoderException;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* A ValueSymbol where the semantic context is obtained by looking
|
||||
* up the value in a table of VarnodeSymbols
|
||||
*/
|
||||
|
@ -58,14 +49,12 @@ public class VarnodeListSymbol extends ValueSymbol {
|
|||
long max = getPatternValue().maxValue();
|
||||
tableisfilled = (min >= 0) && (max < varnode_table.length);
|
||||
for (int i = 0; i < varnode_table.length; ++i) {
|
||||
if (varnode_table[i] == null)
|
||||
if (varnode_table[i] == null) {
|
||||
tableisfilled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.symbol.TripleSymbol#resolve(ghidra.app.plugin.processors.sleigh.ParserWalker, ghidra.app.plugin.processors.sleigh.SleighDebugLogger)
|
||||
*/
|
||||
@Override
|
||||
public Constructor resolve(ParserWalker walker, SleighDebugLogger debug)
|
||||
throws MemoryAccessException, UnknownInstructionException {
|
||||
|
@ -102,20 +91,21 @@ public class VarnodeListSymbol extends ValueSymbol {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void restoreXml(XmlPullParser parser, SleighLanguage sleigh) {
|
||||
XmlElement el = parser.start("varlist_sym");
|
||||
patval = (PatternValue) PatternExpression.restoreExpression(parser, sleigh);
|
||||
public void decode(Decoder decoder, SleighLanguage sleigh) throws DecoderException {
|
||||
// int el = decoder.openElement(ELEM_VARLIST_SYM);
|
||||
patval = (PatternValue) PatternExpression.decodeExpression(decoder, sleigh);
|
||||
ArrayList<VarnodeSymbol> varnodes = new ArrayList<>();
|
||||
SymbolTable symtab = sleigh.getSymbolTable();
|
||||
while (!parser.peek().isEnd()) {
|
||||
XmlElement subel = parser.start();
|
||||
if (subel.getName().equals("var")) {
|
||||
int id = SpecXmlUtils.decodeInt(subel.getAttribute("id"));
|
||||
while (decoder.peekElement() != 0) {
|
||||
int subel = decoder.openElement();
|
||||
if (subel == ELEM_VAR.id()) {
|
||||
int id = (int) decoder.readUnsignedInteger(ATTRIB_ID);
|
||||
varnodes.add((VarnodeSymbol) symtab.findSymbol(id));
|
||||
}
|
||||
else
|
||||
else {
|
||||
varnodes.add(null);
|
||||
parser.end(subel);
|
||||
}
|
||||
decoder.closeElement(subel);
|
||||
}
|
||||
varnode_table = new VarnodeSymbol[varnodes.size()];
|
||||
|
||||
|
@ -123,6 +113,6 @@ public class VarnodeListSymbol extends ValueSymbol {
|
|||
varnode_table[i] = varnodes.get(i);
|
||||
}
|
||||
checkTableFill();
|
||||
parser.end(el);
|
||||
decoder.closeElement(ELEM_VARLIST_SYM.id());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -20,61 +19,51 @@
|
|||
*/
|
||||
package ghidra.app.plugin.processors.sleigh.symbol;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.*;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.util.xml.*;
|
||||
import ghidra.xml.*;
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.*;
|
||||
import ghidra.program.model.pcode.Decoder;
|
||||
import ghidra.program.model.pcode.DecoderException;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* A symbol representing a global varnode, i.e. a named memory location
|
||||
*/
|
||||
public class VarnodeSymbol extends PatternlessSymbol {
|
||||
|
||||
private VarnodeData fix;
|
||||
|
||||
public VarnodeData getFixedVarnode() { return fix; }
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.symbol.TripleSymbol#getFixedHandle(ghidra.app.plugin.processors.sleigh.FixedHandle, ghidra.app.plugin.processors.sleigh.ParserWalker)
|
||||
*/
|
||||
|
||||
public VarnodeData getFixedVarnode() {
|
||||
return fix;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getFixedHandle(FixedHandle hand, ParserWalker walker) {
|
||||
public void getFixedHandle(FixedHandle hand, ParserWalker walker) {
|
||||
hand.space = fix.space;
|
||||
hand.offset_space = null; // Not a dynamic variable
|
||||
hand.offset_offset = fix.offset;
|
||||
hand.size = fix.size;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.symbol.TripleSymbol#print(ghidra.app.plugin.processors.sleigh.ParserWalker)
|
||||
*/
|
||||
@Override
|
||||
public String print(ParserWalker walker) {
|
||||
public String print(ParserWalker walker) {
|
||||
return getName(); // Use the symbol name for printing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printList(ParserWalker walker, ArrayList<Object> list) {
|
||||
public void printList(ParserWalker walker, ArrayList<Object> list) {
|
||||
list.add(walker.getParentHandle());
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.processors.sleigh.symbol.Symbol#restoreXml(org.jdom.Element, ghidra.program.model.address.AddressFactory)
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void restoreXml(XmlPullParser parser,SleighLanguage sleigh) {
|
||||
XmlElement el = parser.start("varnode_sym");
|
||||
public void decode(Decoder decoder, SleighLanguage sleigh) throws DecoderException {
|
||||
// int el = decoder.openElement(ELEM_VARNODE_SYM);
|
||||
fix = new VarnodeData();
|
||||
AddressFactory factory = sleigh.getAddressFactory();
|
||||
fix.space = factory.getAddressSpace(el.getAttribute("space"));
|
||||
fix.offset = SpecXmlUtils.decodeLong(el.getAttribute("offset"));
|
||||
fix.size = SpecXmlUtils.decodeInt(el.getAttribute("size"));
|
||||
// PatternlessSymbol does not need to be restored
|
||||
parser.end(el);
|
||||
fix.space = decoder.readSpace(ATTRIB_SPACE);
|
||||
fix.offset = decoder.readUnsignedInteger(ATTRIB_OFF);
|
||||
fix.size = (int) decoder.readSignedInteger(ATTRIB_SIZE);
|
||||
decoder.closeElement(ELEM_VARNODE_SYM.id());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -19,16 +19,14 @@
|
|||
*/
|
||||
package ghidra.app.plugin.processors.sleigh.template;
|
||||
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.*;
|
||||
import ghidra.program.model.address.AddressFactory;
|
||||
import ghidra.program.model.address.AddressSpace;
|
||||
import ghidra.util.xml.SpecXmlUtils;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
import ghidra.program.model.pcode.Decoder;
|
||||
import ghidra.program.model.pcode.DecoderException;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* A placeholder for what will resolve to a field of a Varnode
|
||||
* (an AddressSpace or integer offset or integer size)
|
||||
* given a particular InstructionContext
|
||||
|
@ -284,73 +282,62 @@ public class ConstTpl {
|
|||
}
|
||||
}
|
||||
|
||||
public void restoreXml(XmlPullParser parser, AddressFactory factory) {
|
||||
XmlElement el = parser.start("const_tpl");
|
||||
String typestr = el.getAttribute("type");
|
||||
if (typestr.equals("real")) {
|
||||
public void decode(Decoder decoder) throws DecoderException {
|
||||
int el = decoder.openElement();
|
||||
if (el == ELEM_CONST_REAL.id()) {
|
||||
type = REAL;
|
||||
value_real = SpecXmlUtils.decodeLong(el.getAttribute("val"));
|
||||
value_real = decoder.readUnsignedInteger(ATTRIB_VAL);
|
||||
}
|
||||
else if (typestr.equals("handle")) {
|
||||
else if (el == ELEM_CONST_HANDLE.id()) {
|
||||
type = HANDLE;
|
||||
handle_index = (short) SpecXmlUtils.decodeInt(el.getAttribute("val"));
|
||||
String selstr = el.getAttribute("s");
|
||||
if (selstr.equals("space")) {
|
||||
select = V_SPACE;
|
||||
handle_index = (short) decoder.readSignedInteger(ATTRIB_VAL);
|
||||
select = (short) decoder.readSignedInteger(ATTRIB_S);
|
||||
if (select < 0 || select > V_OFFSET_PLUS) {
|
||||
throw new DecoderException("Bad handle selector encoding");
|
||||
}
|
||||
else if (selstr.equals("offset")) {
|
||||
select = V_OFFSET;
|
||||
}
|
||||
else if (selstr.equals("size")) {
|
||||
select = V_SIZE;
|
||||
}
|
||||
else if (selstr.equals("offset_plus")) {
|
||||
select = V_OFFSET_PLUS;
|
||||
value_real = SpecXmlUtils.decodeLong(el.getAttribute("plus"));
|
||||
}
|
||||
else {
|
||||
throw new SleighException("Bad handle selector");
|
||||
if (select == V_OFFSET_PLUS) {
|
||||
value_real = decoder.readUnsignedInteger(ATTRIB_PLUS);
|
||||
}
|
||||
}
|
||||
else if (typestr.equals("start")) {
|
||||
else if (el == ELEM_CONST_START.id()) {
|
||||
type = J_START;
|
||||
}
|
||||
else if (typestr.equals("next")) {
|
||||
else if (el == ELEM_CONST_NEXT.id()) {
|
||||
type = J_NEXT;
|
||||
}
|
||||
else if (typestr.equals("next2")) {
|
||||
else if (el == ELEM_CONST_NEXT2.id()) {
|
||||
type = J_NEXT2;
|
||||
}
|
||||
else if (typestr.equals("curspace")) {
|
||||
else if (el == ELEM_CONST_CURSPACE.id()) {
|
||||
type = J_CURSPACE;
|
||||
}
|
||||
else if (typestr.equals("curspace_size")) {
|
||||
else if (el == ELEM_CONST_CURSPACE_SIZE.id()) {
|
||||
type = J_CURSPACE_SIZE;
|
||||
}
|
||||
else if (typestr.equals("spaceid")) {
|
||||
else if (el == ELEM_CONST_SPACEID.id()) {
|
||||
type = SPACEID;
|
||||
value_spaceid = factory.getAddressSpace(el.getAttribute("name"));
|
||||
value_spaceid = decoder.readSpace(ATTRIB_SPACE);
|
||||
}
|
||||
else if (typestr.equals("relative")) {
|
||||
else if (el == ELEM_CONST_RELATIVE.id()) {
|
||||
type = J_RELATIVE;
|
||||
value_real = SpecXmlUtils.decodeLong(el.getAttribute("val"));
|
||||
value_real = decoder.readUnsignedInteger(ATTRIB_VAL);
|
||||
}
|
||||
else if (typestr.equals("flowref")) {
|
||||
else if (el == ELEM_CONST_FLOWREF.id()) {
|
||||
type = J_FLOWREF;
|
||||
}
|
||||
else if (typestr.equals("flowref_size")) {
|
||||
else if (el == ELEM_CONST_FLOWREF_SIZE.id()) {
|
||||
type = J_FLOWREF_SIZE;
|
||||
}
|
||||
else if (typestr.equals("flowdest")) {
|
||||
else if (el == ELEM_CONST_FLOWDEST.id()) {
|
||||
type = J_FLOWDEST;
|
||||
}
|
||||
else if (typestr.equals("flowdest_size")) {
|
||||
else if (el == ELEM_CONST_FLOWDEST_SIZE.id()) {
|
||||
type = J_FLOWDEST_SIZE;
|
||||
}
|
||||
else {
|
||||
throw new SleighException("Bad xml for ConstTpl");
|
||||
throw new SleighException("Bad encoding for ConstTpl");
|
||||
}
|
||||
parser.end(el);
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -19,13 +19,12 @@
|
|||
*/
|
||||
package ghidra.app.plugin.processors.sleigh.template;
|
||||
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import ghidra.program.model.address.AddressFactory;
|
||||
import ghidra.program.model.lang.UnknownInstructionException;
|
||||
import ghidra.util.xml.SpecXmlUtils;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
import ghidra.program.model.pcode.Decoder;
|
||||
import ghidra.program.model.pcode.DecoderException;
|
||||
|
||||
/**
|
||||
* A constructor template, representing the semantic action of a SLEIGH constructor, without
|
||||
|
@ -40,7 +39,6 @@ import ghidra.xml.XmlPullParser;
|
|||
* The final PcodeOps are produced by handing this to the build() method of PcodeEmit which has
|
||||
* the InstructionContext necessary for final resolution.
|
||||
*/
|
||||
|
||||
public class ConstructTpl {
|
||||
|
||||
private int numlabels = 0; // Number of relative-offset labels in this template
|
||||
|
@ -48,7 +46,7 @@ public class ConstructTpl {
|
|||
private HandleTpl result; // The final semantic value
|
||||
|
||||
/**
|
||||
* Constructor for use with restoreXML
|
||||
* Constructor for use with decode
|
||||
*/
|
||||
public ConstructTpl() {
|
||||
}
|
||||
|
@ -98,42 +96,44 @@ public class ConstructTpl {
|
|||
}
|
||||
|
||||
/**
|
||||
* Restore this template from a \<construct_tpl> tag in an XML stream.
|
||||
* @param parser is the XML stream
|
||||
* @param factory is for manufacturing Address objects
|
||||
* Decode this template from a \<construct_tpl> tag in the stream.
|
||||
* @param decoder is the stream
|
||||
* @return the constructor section id described by the tag
|
||||
* @throws UnknownInstructionException if the p-code templates contain unknown op-codes
|
||||
* @throws DecoderException for errors in the encoding
|
||||
*/
|
||||
public int restoreXml(XmlPullParser parser, AddressFactory factory)
|
||||
throws UnknownInstructionException {
|
||||
public int decode(Decoder decoder) throws DecoderException {
|
||||
int sectionid = -1;
|
||||
XmlElement el = parser.start("construct_tpl");
|
||||
String nmlabelstr = el.getAttribute("labels");
|
||||
if (nmlabelstr != null) {
|
||||
numlabels = SpecXmlUtils.decodeInt(nmlabelstr);
|
||||
numlabels = 0;
|
||||
int el = decoder.openElement(ELEM_CONSTRUCT_TPL);
|
||||
int attrib = decoder.getNextAttributeId();
|
||||
while (attrib != 0) {
|
||||
if (attrib == ATTRIB_LABELS.id()) {
|
||||
numlabels = (int) decoder.readSignedInteger();
|
||||
}
|
||||
else if (attrib == ATTRIB_SECTION.id()) {
|
||||
sectionid = (int) decoder.readSignedInteger();
|
||||
}
|
||||
attrib = decoder.getNextAttributeId();
|
||||
}
|
||||
String sectionidstr = el.getAttribute("section");
|
||||
if (sectionidstr != null) {
|
||||
sectionid = SpecXmlUtils.decodeInt(sectionidstr);
|
||||
}
|
||||
XmlElement handel = parser.peek();
|
||||
if (handel.getName().equals("null")) {
|
||||
int handel = decoder.peekElement();
|
||||
if (handel == ELEM_NULL.id()) {
|
||||
decoder.openElement();
|
||||
decoder.closeElement(handel);
|
||||
result = null;
|
||||
parser.discardSubTree();
|
||||
}
|
||||
else {
|
||||
result = new HandleTpl();
|
||||
result.restoreXml(parser, factory);
|
||||
result.decode(decoder);
|
||||
}
|
||||
ArrayList<Object> oplist = new ArrayList<>();
|
||||
while (!parser.peek().isEnd()) {
|
||||
while (decoder.peekElement() != 0) {
|
||||
OpTpl op = new OpTpl();
|
||||
op.restoreXml(parser, factory);
|
||||
op.decode(decoder);
|
||||
oplist.add(op);
|
||||
}
|
||||
vec = new OpTpl[oplist.size()];
|
||||
oplist.toArray(vec);
|
||||
parser.end(el);
|
||||
decoder.closeElement(el);
|
||||
return sectionid;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,12 +19,13 @@
|
|||
*/
|
||||
package ghidra.app.plugin.processors.sleigh.template;
|
||||
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.*;
|
||||
import ghidra.program.model.address.AddressFactory;
|
||||
import ghidra.program.model.address.AddressSpace;
|
||||
import ghidra.program.model.lang.InstructionContext;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
import ghidra.program.model.pcode.Decoder;
|
||||
import ghidra.program.model.pcode.DecoderException;
|
||||
|
||||
/**
|
||||
* Placeholder that resolves for a specific {@link InstructionContext} into a {@link FixedHandle}
|
||||
|
@ -104,23 +105,23 @@ public class HandleTpl {
|
|||
}
|
||||
}
|
||||
|
||||
public void restoreXml(XmlPullParser parser, AddressFactory factory) {
|
||||
XmlElement el = parser.start("handle_tpl");
|
||||
public void decode(Decoder decoder) throws DecoderException {
|
||||
int el = decoder.openElement(ELEM_HANDLE_TPL);
|
||||
space = new ConstTpl();
|
||||
space.restoreXml(parser, factory);
|
||||
space.decode(decoder);
|
||||
size = new ConstTpl();
|
||||
size.restoreXml(parser, factory);
|
||||
size.decode(decoder);
|
||||
ptrspace = new ConstTpl();
|
||||
ptrspace.restoreXml(parser, factory);
|
||||
ptrspace.decode(decoder);
|
||||
ptroffset = new ConstTpl();
|
||||
ptroffset.restoreXml(parser, factory);
|
||||
ptroffset.decode(decoder);
|
||||
ptrsize = new ConstTpl();
|
||||
ptrsize.restoreXml(parser, factory);
|
||||
ptrsize.decode(decoder);
|
||||
temp_space = new ConstTpl();
|
||||
temp_space.restoreXml(parser, factory);
|
||||
temp_space.decode(decoder);
|
||||
temp_offset = new ConstTpl();
|
||||
temp_offset.restoreXml(parser, factory);
|
||||
parser.end(el);
|
||||
temp_offset.decode(decoder);
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
|
||||
public int getOffsetOperandIndex() {
|
||||
|
|
|
@ -19,17 +19,13 @@
|
|||
*/
|
||||
package ghidra.app.plugin.processors.sleigh.template;
|
||||
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import ghidra.program.model.address.AddressFactory;
|
||||
import ghidra.program.model.lang.UnknownInstructionException;
|
||||
import ghidra.program.model.pcode.PcodeOp;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
import ghidra.program.model.pcode.*;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* Placeholder for what will resolve to a PcodeOp
|
||||
* for a specific InstructionContext
|
||||
*/
|
||||
|
@ -60,28 +56,28 @@ public class OpTpl {
|
|||
return opcode;
|
||||
}
|
||||
|
||||
public void restoreXml(XmlPullParser parser, AddressFactory factory)
|
||||
throws UnknownInstructionException {
|
||||
XmlElement el = parser.start("op_tpl");
|
||||
opcode = PcodeOp.getOpcode(el.getAttribute("code"));
|
||||
XmlElement outel = parser.peek();
|
||||
if (outel.getName().equals("null")) {
|
||||
public void decode(Decoder decoder) throws DecoderException {
|
||||
int el = decoder.openElement(ELEM_OP_TPL);
|
||||
opcode = decoder.readOpcode(ATTRIB_CODE);
|
||||
int outel = decoder.peekElement();
|
||||
if (outel == ELEM_NULL.id()) {
|
||||
decoder.openElement();
|
||||
decoder.closeElement(outel);
|
||||
output = null;
|
||||
parser.discardSubTree();
|
||||
}
|
||||
else {
|
||||
output = new VarnodeTpl();
|
||||
output.restoreXml(parser, factory);
|
||||
output.decode(decoder);
|
||||
}
|
||||
ArrayList<Object> inputlist = new ArrayList<>();
|
||||
while (!parser.peek().isEnd()) {
|
||||
while (decoder.peekElement() != 0) {
|
||||
VarnodeTpl vn = new VarnodeTpl();
|
||||
vn.restoreXml(parser, factory);
|
||||
vn.decode(decoder);
|
||||
inputlist.add(vn);
|
||||
}
|
||||
input = new VarnodeTpl[inputlist.size()];
|
||||
inputlist.toArray(input);
|
||||
parser.end(el);
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -19,14 +19,13 @@
|
|||
*/
|
||||
package ghidra.app.plugin.processors.sleigh.template;
|
||||
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.ParserWalker;
|
||||
import ghidra.program.model.address.AddressFactory;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
import ghidra.program.model.pcode.Decoder;
|
||||
import ghidra.program.model.pcode.DecoderException;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* Placeholder for what will resolve to a Varnode instance given
|
||||
* a specific InstructionContext
|
||||
*/
|
||||
|
@ -57,8 +56,9 @@ public class VarnodeTpl {
|
|||
}
|
||||
|
||||
public boolean isDynamic(ParserWalker walker) {
|
||||
if (offset.getType() != ConstTpl.HANDLE)
|
||||
if (offset.getType() != ConstTpl.HANDLE) {
|
||||
return false;
|
||||
}
|
||||
// Technically we should probably check all three ConstTpls
|
||||
// for dynamic handles, but in all cases, if there is any
|
||||
// dynamic piece, then the offset is dynamic
|
||||
|
@ -70,15 +70,15 @@ public class VarnodeTpl {
|
|||
return (offset.getType() == ConstTpl.J_RELATIVE);
|
||||
}
|
||||
|
||||
public void restoreXml(XmlPullParser parser, AddressFactory factory) {
|
||||
XmlElement el = parser.start("varnode_tpl");
|
||||
public void decode(Decoder decoder) throws DecoderException {
|
||||
int el = decoder.openElement(ELEM_VARNODE_TPL);
|
||||
space = new ConstTpl();
|
||||
space.restoreXml(parser, factory);
|
||||
space.decode(decoder);
|
||||
offset = new ConstTpl();
|
||||
offset.restoreXml(parser, factory);
|
||||
offset.decode(decoder);
|
||||
size = new ConstTpl();
|
||||
size.restoreXml(parser, factory);
|
||||
parser.end(el);
|
||||
size.decode(decoder);
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,268 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.pcode.utils;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.zip.DeflaterOutputStream;
|
||||
import java.util.zip.InflaterInputStream;
|
||||
|
||||
import generic.jar.ResourceFile;
|
||||
import ghidra.program.model.pcode.*;
|
||||
|
||||
/**
|
||||
* Encoding values for the .sla file format
|
||||
*/
|
||||
public class SlaFormat {
|
||||
|
||||
/**
|
||||
* FORMAT_VERSION will be incremented whenever the format of the .sla
|
||||
* files change.
|
||||
* <p>
|
||||
* Version 4: Compressed and packed file format
|
||||
* Version 3: January 2021: added source file information for each constructor. <br>
|
||||
* Version 2: April 2019: Changed numbering of Overlay spaces.<br>
|
||||
* Version 1: Initial version.<br>
|
||||
*/
|
||||
public static final int FORMAT_VERSION = 4;
|
||||
|
||||
/**
|
||||
* Absolute limit on the number of bytes in a .sla file
|
||||
*/
|
||||
public static final int MAX_FILE_SIZE = 1 << 24; // 16 Megabytes
|
||||
// Attributes
|
||||
|
||||
// ATTRIB_CONTENT = 1 is reserved
|
||||
public static final AttributeId ATTRIB_VAL = new AttributeId("val", 2);
|
||||
public static final AttributeId ATTRIB_ID = new AttributeId("id", 3);
|
||||
public static final AttributeId ATTRIB_SPACE = new AttributeId("space", 4);
|
||||
public static final AttributeId ATTRIB_S = new AttributeId("s", 5);
|
||||
public static final AttributeId ATTRIB_OFF = new AttributeId("off", 6);
|
||||
public static final AttributeId ATTRIB_CODE = new AttributeId("code", 7);
|
||||
public static final AttributeId ATTRIB_MASK = new AttributeId("mask", 8);
|
||||
public static final AttributeId ATTRIB_INDEX = new AttributeId("index", 9);
|
||||
public static final AttributeId ATTRIB_NONZERO = new AttributeId("nonzero", 10);
|
||||
public static final AttributeId ATTRIB_PIECE = new AttributeId("piece", 11);
|
||||
public static final AttributeId ATTRIB_NAME = new AttributeId("name", 12);
|
||||
public static final AttributeId ATTRIB_SCOPE = new AttributeId("scope", 13);
|
||||
public static final AttributeId ATTRIB_STARTBIT = new AttributeId("startbit", 14);
|
||||
public static final AttributeId ATTRIB_SIZE = new AttributeId("size", 15);
|
||||
public static final AttributeId ATTRIB_TABLE = new AttributeId("table", 16);
|
||||
public static final AttributeId ATTRIB_CT = new AttributeId("ct", 17);
|
||||
public static final AttributeId ATTRIB_MINLEN = new AttributeId("minlen", 18);
|
||||
public static final AttributeId ATTRIB_BASE = new AttributeId("base", 19);
|
||||
public static final AttributeId ATTRIB_NUMBER = new AttributeId("number", 20);
|
||||
public static final AttributeId ATTRIB_CONTEXT = new AttributeId("context", 21);
|
||||
public static final AttributeId ATTRIB_PARENT = new AttributeId("parent", 22);
|
||||
public static final AttributeId ATTRIB_SUBSYM = new AttributeId("subsym", 23);
|
||||
public static final AttributeId ATTRIB_LINE = new AttributeId("line", 24);
|
||||
public static final AttributeId ATTRIB_SOURCE = new AttributeId("source", 25);
|
||||
public static final AttributeId ATTRIB_LENGTH = new AttributeId("length", 26);
|
||||
public static final AttributeId ATTRIB_FIRST = new AttributeId("first", 27);
|
||||
public static final AttributeId ATTRIB_PLUS = new AttributeId("plus", 28);
|
||||
public static final AttributeId ATTRIB_SHIFT = new AttributeId("shift", 29);
|
||||
public static final AttributeId ATTRIB_ENDBIT = new AttributeId("endbit", 30);
|
||||
public static final AttributeId ATTRIB_SIGNBIT = new AttributeId("signbit", 31);
|
||||
public static final AttributeId ATTRIB_ENDBYTE = new AttributeId("endbyte", 32);
|
||||
public static final AttributeId ATTRIB_STARTBYTE = new AttributeId("startbyte", 33);
|
||||
public static final AttributeId ATTRIB_VERSION = new AttributeId("version", 34);
|
||||
public static final AttributeId ATTRIB_BIGENDIAN = new AttributeId("bigendian", 35);
|
||||
public static final AttributeId ATTRIB_ALIGN = new AttributeId("align", 36);
|
||||
public static final AttributeId ATTRIB_UNIQBASE = new AttributeId("uniqbase", 37);
|
||||
public static final AttributeId ATTRIB_MAXDELAY = new AttributeId("maxdelay", 38);
|
||||
public static final AttributeId ATTRIB_UNIQMASK = new AttributeId("uniqmask", 39);
|
||||
public static final AttributeId ATTRIB_NUMSECTIONS = new AttributeId("numsections", 40);
|
||||
public static final AttributeId ATTRIB_DEFAULTSPACE = new AttributeId("defaultspace", 41);
|
||||
public static final AttributeId ATTRIB_DELAY = new AttributeId("delay", 42);
|
||||
public static final AttributeId ATTRIB_WORDSIZE = new AttributeId("wordsize", 43);
|
||||
public static final AttributeId ATTRIB_PHYSICAL = new AttributeId("physical", 44);
|
||||
public static final AttributeId ATTRIB_SCOPESIZE = new AttributeId("scopesize", 45);
|
||||
public static final AttributeId ATTRIB_SYMBOLSIZE = new AttributeId("symbolsize", 46);
|
||||
public static final AttributeId ATTRIB_VARNODE = new AttributeId("varnode", 47);
|
||||
public static final AttributeId ATTRIB_LOW = new AttributeId("low", 48);
|
||||
public static final AttributeId ATTRIB_HIGH = new AttributeId("high", 49);
|
||||
public static final AttributeId ATTRIB_FLOW = new AttributeId("flow", 50);
|
||||
public static final AttributeId ATTRIB_CONTAIN = new AttributeId("contain", 51);
|
||||
public static final AttributeId ATTRIB_I = new AttributeId("i", 52);
|
||||
public static final AttributeId ATTRIB_NUMCT = new AttributeId("numct", 53);
|
||||
public static final AttributeId ATTRIB_SECTION = new AttributeId("section", 54);
|
||||
public static final AttributeId ATTRIB_LABELS = new AttributeId("labels", 55);
|
||||
|
||||
public static final ElementId ELEM_CONST_REAL = new ElementId("const_real", 1);
|
||||
public static final ElementId ELEM_VARNODE_TPL = new ElementId("varnode_tpl", 2);
|
||||
public static final ElementId ELEM_CONST_SPACEID = new ElementId("const_spaceid", 3);
|
||||
public static final ElementId ELEM_CONST_HANDLE = new ElementId("const_handle", 4);
|
||||
public static final ElementId ELEM_OP_TPL = new ElementId("op_tpl", 5);
|
||||
public static final ElementId ELEM_MASK_WORD = new ElementId("mask_word", 6);
|
||||
public static final ElementId ELEM_PAT_BLOCK = new ElementId("pat_block", 7);
|
||||
public static final ElementId ELEM_PRINT = new ElementId("print", 8);
|
||||
public static final ElementId ELEM_PAIR = new ElementId("pair", 9);
|
||||
public static final ElementId ELEM_CONTEXT_PAT = new ElementId("context_pat", 10);
|
||||
public static final ElementId ELEM_NULL = new ElementId("null", 11);
|
||||
public static final ElementId ELEM_OPERAND_EXP = new ElementId("operand_exp", 12);
|
||||
public static final ElementId ELEM_OPERAND_SYM = new ElementId("operand_sym", 13);
|
||||
public static final ElementId ELEM_OPERAND_SYM_HEAD = new ElementId("operand_sym_head", 14);
|
||||
public static final ElementId ELEM_OPER = new ElementId("oper", 15);
|
||||
public static final ElementId ELEM_DECISION = new ElementId("decision", 16);
|
||||
public static final ElementId ELEM_OPPRINT = new ElementId("opprint", 17);
|
||||
public static final ElementId ELEM_INSTRUCT_PAT = new ElementId("instruct_pat", 18);
|
||||
public static final ElementId ELEM_COMBINE_PAT = new ElementId("combine_pat", 19);
|
||||
public static final ElementId ELEM_CONSTRUCTOR = new ElementId("constructor", 20);
|
||||
public static final ElementId ELEM_CONSTRUCT_TPL = new ElementId("construct_tpl", 21);
|
||||
public static final ElementId ELEM_SCOPE = new ElementId("scope", 22);
|
||||
public static final ElementId ELEM_VARNODE_SYM = new ElementId("varnode_sym", 23);
|
||||
public static final ElementId ELEM_VARNODE_SYM_HEAD = new ElementId("varnode_sym_head", 24);
|
||||
public static final ElementId ELEM_USEROP = new ElementId("userop", 25);
|
||||
public static final ElementId ELEM_USEROP_HEAD = new ElementId("userop_head", 26);
|
||||
public static final ElementId ELEM_TOKENFIELD = new ElementId("tokenfield", 27);
|
||||
public static final ElementId ELEM_VAR = new ElementId("var", 28);
|
||||
public static final ElementId ELEM_CONTEXTFIELD = new ElementId("contextfield", 29);
|
||||
public static final ElementId ELEM_HANDLE_TPL = new ElementId("handle_tpl", 30);
|
||||
public static final ElementId ELEM_CONST_RELATIVE = new ElementId("const_relative", 31);
|
||||
public static final ElementId ELEM_CONTEXT_OP = new ElementId("context_op", 32);
|
||||
|
||||
public static final ElementId ELEM_SLEIGH = new ElementId("sleigh", 33);
|
||||
public static final ElementId ELEM_SPACES = new ElementId("spaces", 34);
|
||||
public static final ElementId ELEM_SOURCEFILES = new ElementId("sourcefiles", 35);
|
||||
public static final ElementId ELEM_SOURCEFILE = new ElementId("sourcefile", 36);
|
||||
public static final ElementId ELEM_SPACE = new ElementId("space", 37);
|
||||
public static final ElementId ELEM_SYMBOL_TABLE = new ElementId("symbol_table", 38);
|
||||
public static final ElementId ELEM_VALUE_SYM = new ElementId("value_sym", 39);
|
||||
public static final ElementId ELEM_VALUE_SYM_HEAD = new ElementId("value_sym_head", 40);
|
||||
public static final ElementId ELEM_CONTEXT_SYM = new ElementId("context_sym", 41);
|
||||
public static final ElementId ELEM_CONTEXT_SYM_HEAD = new ElementId("context_sym_head", 42);
|
||||
public static final ElementId ELEM_END_SYM = new ElementId("end_sym", 43);
|
||||
public static final ElementId ELEM_END_SYM_HEAD = new ElementId("end_sym_head", 44);
|
||||
public static final ElementId ELEM_SPACE_OTHER = new ElementId("space_other", 45);
|
||||
public static final ElementId ELEM_SPACE_UNIQUE = new ElementId("space_unique", 46);
|
||||
public static final ElementId ELEM_AND_EXP = new ElementId("and_exp", 47);
|
||||
public static final ElementId ELEM_DIV_EXP = new ElementId("div_exp", 48);
|
||||
public static final ElementId ELEM_LSHIFT_EXP = new ElementId("lshift_exp", 49);
|
||||
public static final ElementId ELEM_MINUS_EXP = new ElementId("minus_exp", 50);
|
||||
public static final ElementId ELEM_MULT_EXP = new ElementId("mult_exp", 51);
|
||||
public static final ElementId ELEM_NOT_EXP = new ElementId("not_exp", 52);
|
||||
public static final ElementId ELEM_OR_EXP = new ElementId("or_exp", 53);
|
||||
public static final ElementId ELEM_PLUS_EXP = new ElementId("plus_exp", 54);
|
||||
public static final ElementId ELEM_RSHIFT_EXP = new ElementId("rshift_exp", 55);
|
||||
public static final ElementId ELEM_SUB_EXP = new ElementId("sub_exp", 56);
|
||||
public static final ElementId ELEM_XOR_EXP = new ElementId("xor_exp", 57);
|
||||
public static final ElementId ELEM_INTB = new ElementId("intb", 58);
|
||||
public static final ElementId ELEM_END_EXP = new ElementId("end_exp", 59);
|
||||
public static final ElementId ELEM_NEXT2_EXP = new ElementId("next2_exp", 60);
|
||||
public static final ElementId ELEM_START_EXP = new ElementId("start_exp", 61);
|
||||
public static final ElementId ELEM_EPSILON_SYM = new ElementId("epsilon_sym", 62);
|
||||
public static final ElementId ELEM_EPSILON_SYM_HEAD = new ElementId("epsilon_sym_head", 63);
|
||||
public static final ElementId ELEM_NAME_SYM = new ElementId("name_sym", 64);
|
||||
public static final ElementId ELEM_NAME_SYM_HEAD = new ElementId("name_sym_head", 65);
|
||||
public static final ElementId ELEM_NAMETAB = new ElementId("nametab", 66);
|
||||
public static final ElementId ELEM_NEXT2_SYM = new ElementId("next2_sym", 67);
|
||||
public static final ElementId ELEM_NEXT2_SYM_HEAD = new ElementId("next2_sym_head", 68);
|
||||
public static final ElementId ELEM_START_SYM = new ElementId("start_sym", 69);
|
||||
public static final ElementId ELEM_START_SYM_HEAD = new ElementId("start_sym_head", 70);
|
||||
public static final ElementId ELEM_SUBTABLE_SYM = new ElementId("subtable_sym", 71);
|
||||
public static final ElementId ELEM_SUBTABLE_SYM_HEAD = new ElementId("subtable_sym_head", 72);
|
||||
public static final ElementId ELEM_VALUEMAP_SYM = new ElementId("valuemap_sym", 73);
|
||||
public static final ElementId ELEM_VALUEMAP_SYM_HEAD = new ElementId("valuemap_sym_head", 74);
|
||||
public static final ElementId ELEM_VALUETAB = new ElementId("valuetab", 75);
|
||||
public static final ElementId ELEM_VARLIST_SYM = new ElementId("varlist_sym", 76);
|
||||
public static final ElementId ELEM_VARLIST_SYM_HEAD = new ElementId("varlist_sym_head", 77);
|
||||
public static final ElementId ELEM_OR_PAT = new ElementId("or_pat", 78);
|
||||
public static final ElementId ELEM_COMMIT = new ElementId("commit", 79);
|
||||
public static final ElementId ELEM_CONST_START = new ElementId("const_start", 80);
|
||||
public static final ElementId ELEM_CONST_NEXT = new ElementId("const_next", 81);
|
||||
public static final ElementId ELEM_CONST_NEXT2 = new ElementId("const_next2", 82);
|
||||
public static final ElementId ELEM_CONST_CURSPACE = new ElementId("const_curspace", 83);
|
||||
public static final ElementId ELEM_CONST_CURSPACE_SIZE =
|
||||
new ElementId("const_curspace_size", 84);
|
||||
public static final ElementId ELEM_CONST_FLOWREF = new ElementId("const_flowref", 85);
|
||||
public static final ElementId ELEM_CONST_FLOWREF_SIZE = new ElementId("const_flowref_size", 86);
|
||||
public static final ElementId ELEM_CONST_FLOWDEST = new ElementId("const_flowdest", 87);
|
||||
public static final ElementId ELEM_CONST_FLOWDEST_SIZE =
|
||||
new ElementId("const_flowdest_size", 88);
|
||||
|
||||
/**
|
||||
* Try to read the header bytes of the .sla format from the given stream. If the header bytes
|
||||
* and the version byte match, \b true is returned, and the stream can be passed to the decoder.
|
||||
* @param stream is the given stream
|
||||
* @return true if the .sla header bytes are found
|
||||
* @throws IOException for any errors reading from the stream
|
||||
*/
|
||||
public static boolean isSlaFormat(InputStream stream) throws IOException {
|
||||
byte[] header = new byte[4];
|
||||
int readLen = stream.read(header);
|
||||
if (readLen < 4) {
|
||||
return false;
|
||||
}
|
||||
if (header[0] != 's' || header[1] != 'l' || header[2] != 'a') {
|
||||
return false;
|
||||
}
|
||||
if (header[3] != FORMAT_VERSION) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a .sla file header,including the format version number to the given stream.
|
||||
* @param stream is the given stream
|
||||
* @throws IOException for problems writing to the stream
|
||||
*/
|
||||
public static void writeSlaHeader(OutputStream stream) throws IOException {
|
||||
stream.write("sla".getBytes());
|
||||
stream.write(FORMAT_VERSION);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the encoder for compressing and encoding a .sla file (as a stream).
|
||||
* The given file is opened and a header is immediately written. The returned
|
||||
* encoder is ready immediately to receive the .sla elements and attributes.
|
||||
* @param sleighFile is the .sla file (to be created)
|
||||
* @return the encoder
|
||||
* @throws IOException for any problems opening or writing to the file
|
||||
*/
|
||||
public static PackedEncode buildEncoder(ResourceFile sleighFile) throws IOException {
|
||||
OutputStream stream = sleighFile.getOutputStream();
|
||||
writeSlaHeader(stream);
|
||||
OutputStream compStream = new DeflaterOutputStream(stream);
|
||||
return new PackedEncode(compStream);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the decoder for decompressing and decoding the .sla file (as a stream).
|
||||
* The given file is opened and the header bytes are checked. The returned
|
||||
* decoder is immediately ready to read.
|
||||
* @param sleighFile is the given .sla file
|
||||
* @return the decoder
|
||||
* @throws IOException if the header is invalid or there are problems reading the file
|
||||
*/
|
||||
public static PackedDecode buildDecoder(ResourceFile sleighFile) throws IOException {
|
||||
InputStream stream = sleighFile.getInputStream();
|
||||
try {
|
||||
if (!isSlaFormat(stream)) {
|
||||
throw new IOException("Missing SLA format header");
|
||||
}
|
||||
InflaterInputStream inflaterStream = new InflaterInputStream(stream);
|
||||
PackedDecode decoder = new PackedDecode();
|
||||
decoder.open(MAX_FILE_SIZE, ".sla file loader");
|
||||
decoder.ingestStream(inflaterStream);
|
||||
decoder.endIngest();
|
||||
inflaterStream.close();
|
||||
return decoder;
|
||||
}
|
||||
finally {
|
||||
stream.close();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -15,17 +15,11 @@
|
|||
*/
|
||||
package ghidra.pcodeCPort.address;
|
||||
|
||||
import ghidra.pcodeCPort.pcoderaw.*;
|
||||
import ghidra.pcodeCPort.space.*;
|
||||
import ghidra.pcodeCPort.translate.*;
|
||||
import ghidra.pcodeCPort.utils.*;
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
import org.jdom.Element;
|
||||
|
||||
|
||||
|
||||
import ghidra.pcodeCPort.space.AddrSpace;
|
||||
import ghidra.pcodeCPort.space.spacetype;
|
||||
import ghidra.pcodeCPort.utils.AddrSpaceToIdSymmetryMap;
|
||||
|
||||
//For specifying a storage space. Could be RAM, ROM, cpu register, data
|
||||
//segment, coprocessor, stack, nvram, etc.
|
||||
|
@ -39,7 +33,7 @@ import org.jdom.Element;
|
|||
//a translation from a real machine language will typically simulate registers
|
||||
//by placing them in their own space, separate from RAM. Indirection
|
||||
//(i.e. pointers) must be simulated through the LOAD and STORE ops.
|
||||
public class Address implements Comparable<Address>{
|
||||
public class Address implements Comparable<Address> {
|
||||
public enum mach_extreme {
|
||||
m_minimal, m_maximal
|
||||
}
|
||||
|
@ -53,12 +47,12 @@ public class Address implements Comparable<Address>{
|
|||
base = AddrSpace.MIN_SPACE;
|
||||
}
|
||||
|
||||
public Address( AddrSpace id, long off ) {
|
||||
public Address(AddrSpace id, long off) {
|
||||
base = id;
|
||||
offset = off;
|
||||
offset = off;
|
||||
}
|
||||
|
||||
public Address( Address addr ) {
|
||||
public Address(Address addr) {
|
||||
base = addr.base;
|
||||
offset = addr.offset;
|
||||
}
|
||||
|
@ -68,7 +62,7 @@ public class Address implements Comparable<Address>{
|
|||
return (base == AddrSpace.MIN_SPACE || base == AddrSpace.MAX_SPACE);
|
||||
}
|
||||
|
||||
void setOffset( long o ) {
|
||||
void setOffset(long o) {
|
||||
offset = o;
|
||||
}
|
||||
|
||||
|
@ -80,39 +74,35 @@ public class Address implements Comparable<Address>{
|
|||
return base.isBigEndian();
|
||||
}
|
||||
|
||||
void printOffset( PrintStream s ) {
|
||||
base.printOffset( s, offset );
|
||||
void printOffset(PrintStream s) {
|
||||
base.printOffset(s, offset);
|
||||
}
|
||||
|
||||
public int printRaw( PrintStream s ) {
|
||||
return base.printRaw( s, offset );
|
||||
public int printRaw(PrintStream s) {
|
||||
return base.printRaw(s, offset);
|
||||
}
|
||||
|
||||
|
||||
// Convert address to most basic physical address
|
||||
// This routine is only present for backward compatibility
|
||||
// with SLED
|
||||
public void toPhysical() {
|
||||
AddrSpace phys = base.getContain();
|
||||
if ((phys != null)&&(base.getType()==spacetype.IPTR_SPACEBASE)) {
|
||||
base = phys;
|
||||
}
|
||||
AddrSpace phys = base.getContain();
|
||||
if ((phys != null) && (base.getType() == spacetype.IPTR_SPACEBASE)) {
|
||||
base = phys;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
public String toString() {
|
||||
return base.getName() + ":0x" + base.toString(offset);
|
||||
}
|
||||
|
||||
public String toString(boolean showAddressSpace) {
|
||||
if (showAddressSpace) {
|
||||
return base.getName() + ":0x" + base.toString(offset);
|
||||
}
|
||||
return "0x" + base.toString(offset);
|
||||
}
|
||||
public int read( String s ) {
|
||||
MutableInt size = new MutableInt( 0 );
|
||||
offset = base.read( s, size );
|
||||
return size.get();
|
||||
}
|
||||
|
||||
public AddrSpace getSpace() {
|
||||
return base;
|
||||
|
@ -127,7 +117,7 @@ public class Address implements Comparable<Address>{
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean equals( Object obj ) {
|
||||
public boolean equals(Object obj) {
|
||||
if (!(obj instanceof Address)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -138,57 +128,43 @@ public class Address implements Comparable<Address>{
|
|||
return base == other.base && offset == other.offset;
|
||||
}
|
||||
|
||||
public int compareTo( Address other ) {
|
||||
int result = base.compareTo( other.base );
|
||||
@Override
|
||||
public int compareTo(Address other) {
|
||||
int result = base.compareTo(other.base);
|
||||
if (result != 0) {
|
||||
return result;
|
||||
}
|
||||
return AddressUtils.unsignedCompare( offset, other.offset );
|
||||
return AddressUtils.unsignedCompare(offset, other.offset);
|
||||
}
|
||||
|
||||
public Address add( long off ) {
|
||||
return new Address( base, (offset + off) & base.getMask() );
|
||||
public Address add(long off) {
|
||||
return new Address(base, (offset + off) & base.getMask());
|
||||
}
|
||||
|
||||
public Address subtract( long off ) {
|
||||
return sub( off );
|
||||
public Address subtract(long off) {
|
||||
return sub(off);
|
||||
}
|
||||
|
||||
public Address sub( long off ) {
|
||||
return new Address( base, (offset - off) & base.getMask() );
|
||||
|
||||
public Address sub(long off) {
|
||||
return new Address(base, (offset - off) & base.getMask());
|
||||
}
|
||||
|
||||
public boolean isConstant() {
|
||||
return (base.getType() == spacetype.IPTR_CONSTANT);
|
||||
}
|
||||
|
||||
public void saveXml( PrintStream s ) {
|
||||
s.append( "<addr" );
|
||||
if (base != null) {
|
||||
base.saveXmlAttributes( s, offset );
|
||||
}
|
||||
s.append( "/>" );
|
||||
}
|
||||
|
||||
public void saveXml( PrintStream s, int size ) {
|
||||
s.append( "<addr" );
|
||||
if (base != null) {
|
||||
base.saveXmlAttributes( s, offset, size );
|
||||
}
|
||||
s.append( "/>" );
|
||||
}
|
||||
|
||||
public static AddrSpace getSpaceFromConst( Address addr ) {
|
||||
return (AddrSpace) AddrSpaceToIdSymmetryMap.getSpace( addr.offset );
|
||||
public static AddrSpace getSpaceFromConst(Address addr) {
|
||||
return AddrSpaceToIdSymmetryMap.getSpace(addr.offset);
|
||||
}
|
||||
|
||||
// Define pseudo-locations that have specific
|
||||
public Address( mach_extreme ex ) {
|
||||
public Address(mach_extreme ex) {
|
||||
// properties under comparion
|
||||
if (ex == mach_extreme.m_minimal) {
|
||||
base = AddrSpace.MIN_SPACE;
|
||||
offset = 0;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
base = AddrSpace.MAX_SPACE;
|
||||
offset = -1;
|
||||
}
|
||||
|
@ -196,7 +172,7 @@ public class Address implements Comparable<Address>{
|
|||
|
||||
// Return true if (op2,sz2) is endian aligned and contained
|
||||
// in (this,sz)
|
||||
public boolean endianContain( int sz, Address op2, int sz2 ) {
|
||||
public boolean endianContain(int sz, Address op2, int sz2) {
|
||||
if (base != op2.base) {
|
||||
return false;
|
||||
}
|
||||
|
@ -217,7 +193,7 @@ public class Address implements Comparable<Address>{
|
|||
return true;
|
||||
}
|
||||
|
||||
public int overlap( int skip, Address op, int size ) {// Where does this+skip fall in op to op+size
|
||||
public int overlap(int skip, Address op, int size) {// Where does this+skip fall in op to op+size
|
||||
|
||||
if (base != op.base) {
|
||||
return -1; // Must be in same address space to overlap
|
||||
|
@ -229,16 +205,10 @@ public class Address implements Comparable<Address>{
|
|||
long dist = offset + skip - op.offset;
|
||||
dist &= base.getMask();
|
||||
|
||||
if (dist >= size)
|
||||
if (dist >= size) {
|
||||
return -1; // but must fall before op+size
|
||||
}
|
||||
return (int) dist;
|
||||
}
|
||||
|
||||
public static VarnodeData restoreXml( Element el, Translate trans ) {
|
||||
VarnodeData var = new VarnodeData();
|
||||
|
||||
var.restoreXml( el, trans );
|
||||
return var;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -18,15 +17,8 @@ package ghidra.pcodeCPort.address;
|
|||
|
||||
import java.io.PrintStream;
|
||||
|
||||
import org.jdom.Element;
|
||||
|
||||
|
||||
import ghidra.pcodeCPort.error.*;
|
||||
import ghidra.pcodeCPort.pcoderaw.*;
|
||||
import ghidra.pcodeCPort.space.*;
|
||||
import ghidra.pcodeCPort.translate.*;
|
||||
import ghidra.pcodeCPort.utils.*;
|
||||
|
||||
import ghidra.pcodeCPort.space.AddrSpace;
|
||||
import ghidra.pcodeCPort.translate.Translate;
|
||||
|
||||
public class Range implements Comparable<Range> {
|
||||
private AddrSpace spc; // Space containing range
|
||||
|
@ -35,14 +27,14 @@ public class Range implements Comparable<Range> {
|
|||
|
||||
private long last;
|
||||
|
||||
public Range( AddrSpace s, long f, long l ) {
|
||||
public Range(AddrSpace s, long f, long l) {
|
||||
spc = s;
|
||||
first = f;
|
||||
last = l;
|
||||
}
|
||||
|
||||
public Range() {
|
||||
} // For use with restore_xml
|
||||
}
|
||||
|
||||
public AddrSpace getSpace() {
|
||||
return spc;
|
||||
|
@ -57,82 +49,46 @@ public class Range implements Comparable<Range> {
|
|||
}
|
||||
|
||||
public Address getFirstAddr() {
|
||||
return new Address( spc, first );
|
||||
return new Address(spc, first);
|
||||
}
|
||||
|
||||
public Address getLastAddr() {
|
||||
return new Address( spc, last );
|
||||
return new Address(spc, last);
|
||||
}
|
||||
|
||||
public int compareTo( Range other ) {
|
||||
int result = spc.compareTo( other.spc );
|
||||
@Override
|
||||
public int compareTo(Range other) {
|
||||
int result = spc.compareTo(other.spc);
|
||||
if (result != 0) {
|
||||
return result;
|
||||
}
|
||||
return AddressUtils.unsignedCompare( first, other.first );
|
||||
return AddressUtils.unsignedCompare(first, other.first);
|
||||
}
|
||||
|
||||
void printBounds( PrintStream s ) {
|
||||
s.append( spc.getName() );
|
||||
s.append( ": " );
|
||||
s.append( Long.toHexString( first ) );
|
||||
s.append( '-' );
|
||||
s.append( Long.toHexString( last ) );
|
||||
}
|
||||
|
||||
void saveXml( PrintStream s ) {
|
||||
s.append( "<range" );
|
||||
|
||||
XmlUtils.a_v( s, "space", spc.getName() );
|
||||
XmlUtils.a_v_u( s, "first", first );
|
||||
XmlUtils.a_v_u( s, "last", last );
|
||||
s.append( "/>\n" );
|
||||
void printBounds(PrintStream s) {
|
||||
s.append(spc.getName());
|
||||
s.append(": ");
|
||||
s.append(Long.toHexString(first));
|
||||
s.append('-');
|
||||
s.append(Long.toHexString(last));
|
||||
}
|
||||
|
||||
// Get the last address +1, updating the space, or returning
|
||||
public Address getLastAddrOpen( Translate trans ) {
|
||||
public Address getLastAddrOpen(Translate trans) {
|
||||
// the extremal address if necessary
|
||||
AddrSpace curspc = spc;
|
||||
long curlast = last;
|
||||
if (curlast == curspc.getMask()) {
|
||||
curspc = trans.getNextSpaceInOrder( curspc );
|
||||
curspc = trans.getNextSpaceInOrder(curspc);
|
||||
curlast = 0;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
curlast += 1;
|
||||
}
|
||||
if (curspc == null) {
|
||||
return new Address( Address.mach_extreme.m_maximal );
|
||||
return new Address(Address.mach_extreme.m_maximal);
|
||||
}
|
||||
return new Address( curspc, curlast );
|
||||
}
|
||||
|
||||
public void restoreXml( Element el, Translate trans ) {
|
||||
spc = null;
|
||||
first = 0;
|
||||
last = -1;
|
||||
String attrvalue = el.getAttributeValue("space");
|
||||
if (attrvalue != null) {
|
||||
spc = trans.getSpaceByName(attrvalue);
|
||||
if (spc == null)
|
||||
throw new LowlevelError("Undefined space: "+attrvalue);
|
||||
}
|
||||
attrvalue = el.getAttributeValue("first");
|
||||
if (attrvalue != null)
|
||||
first = XmlUtils.decodeUnknownLong(attrvalue);
|
||||
attrvalue = el.getAttributeValue("last");
|
||||
if (attrvalue != null)
|
||||
last = XmlUtils.decodeUnknownLong(attrvalue);
|
||||
attrvalue = el.getAttributeValue("name");
|
||||
if (attrvalue != null) {
|
||||
VarnodeData point = trans.getRegister(attrvalue);
|
||||
spc = point.space;
|
||||
first = point.offset;
|
||||
last = (first-1) + point.size;
|
||||
}
|
||||
if (spc == null)
|
||||
throw new LowlevelError( "No address space indicated in range tag");
|
||||
first &= spc.getMask();
|
||||
last &= spc.getMask();
|
||||
return new Address(curspc, curlast);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -16,22 +16,17 @@
|
|||
package ghidra.pcodeCPort.address;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.util.List;
|
||||
|
||||
import org.jdom.Element;
|
||||
|
||||
import generic.stl.*;
|
||||
import ghidra.pcodeCPort.space.AddrSpace;
|
||||
import ghidra.pcodeCPort.translate.Translate;
|
||||
import ghidra.pcodeCPort.utils.Utils;
|
||||
|
||||
|
||||
public class RangeList {
|
||||
|
||||
private SetSTL<Range> tree;
|
||||
|
||||
public RangeList( RangeList rangeList ) {
|
||||
tree = new SetSTL<>( rangeList.tree );
|
||||
public RangeList(RangeList rangeList) {
|
||||
tree = new SetSTL<>(rangeList.tree);
|
||||
}
|
||||
|
||||
public RangeList() {
|
||||
|
@ -41,9 +36,11 @@ public class RangeList {
|
|||
public void clear() {
|
||||
tree.clear();
|
||||
}
|
||||
|
||||
public IteratorSTL<Range> begin() {
|
||||
return tree.begin();
|
||||
}
|
||||
|
||||
public IteratorSTL<Range> end() {
|
||||
return tree.end();
|
||||
}
|
||||
|
@ -53,101 +50,101 @@ public class RangeList {
|
|||
}
|
||||
|
||||
// tree is disjoint list of ranges
|
||||
public void insertRange( AddrSpace spc, long first, long last ) {
|
||||
public void insertRange(AddrSpace spc, long first, long last) {
|
||||
// insert a new range
|
||||
|
||||
// we must have iter1.first > first
|
||||
IteratorSTL<Range> iter1 = tree.upper_bound( new Range( spc, first, first ) );
|
||||
IteratorSTL<Range> iter1 = tree.upper_bound(new Range(spc, first, first));
|
||||
|
||||
// Set iter1 to first range with range.last >=first
|
||||
// It is either current iter1 or the one before
|
||||
if ( !iter1.isBegin() ) {
|
||||
if (!iter1.isBegin()) {
|
||||
iter1.decrement();
|
||||
if ( (!iter1.get().getSpace().equals( spc ))
|
||||
|| (Utils.unsignedCompare( iter1.get().getLast(), first ) < 0) ) {
|
||||
if ((!iter1.get().getSpace().equals(spc)) ||
|
||||
(Utils.unsignedCompare(iter1.get().getLast(), first) < 0)) {
|
||||
iter1.increment();
|
||||
}
|
||||
}
|
||||
|
||||
// Set iter2 to first range with range.first > last
|
||||
IteratorSTL<Range> iter2 = tree.upper_bound( new Range( spc, last, last ) );
|
||||
IteratorSTL<Range> iter2 = tree.upper_bound(new Range(spc, last, last));
|
||||
|
||||
while ( !iter1.equals( iter2 ) ) {
|
||||
if ( Utils.unsignedCompare( iter1.get().getFirst(), first ) < 0 ) {
|
||||
while (!iter1.equals(iter2)) {
|
||||
if (Utils.unsignedCompare(iter1.get().getFirst(), first) < 0) {
|
||||
first = iter1.get().getFirst();
|
||||
}
|
||||
if ( Utils.unsignedCompare( iter1.get().getLast(), last ) > 0 ) {
|
||||
if (Utils.unsignedCompare(iter1.get().getLast(), last) > 0) {
|
||||
last = iter1.get().getLast();
|
||||
}
|
||||
tree.erase(iter1);
|
||||
iter1.increment();
|
||||
}
|
||||
tree.insert( new Range( spc, first, last ) );
|
||||
tree.insert(new Range(spc, first, last));
|
||||
|
||||
}
|
||||
|
||||
// remove a range
|
||||
public void removeRange( AddrSpace spc, long first, long last ) {
|
||||
public void removeRange(AddrSpace spc, long first, long last) {
|
||||
|
||||
if ( tree.isEmpty() ) {
|
||||
if (tree.isEmpty()) {
|
||||
return; // Nothing to do
|
||||
}
|
||||
|
||||
// we must have iter1.first > first
|
||||
IteratorSTL<Range> iter1 = tree.upper_bound( new Range( spc, first, first ) );
|
||||
IteratorSTL<Range> iter1 = tree.upper_bound(new Range(spc, first, first));
|
||||
// Set iter1 to first range with range.last >=first
|
||||
// It is either current iter1 or the one before
|
||||
if ( !iter1.isBegin() ) {
|
||||
if (!iter1.isBegin()) {
|
||||
iter1.decrement();
|
||||
if ( (!iter1.get().getSpace().equals( spc ))
|
||||
|| (Utils.unsignedCompare( iter1.get().getLast(), first ) < 0) ) {
|
||||
if ((!iter1.get().getSpace().equals(spc)) ||
|
||||
(Utils.unsignedCompare(iter1.get().getLast(), first) < 0)) {
|
||||
iter1.increment();
|
||||
}
|
||||
}
|
||||
|
||||
// Set iter2 to first range with range.first > last
|
||||
IteratorSTL<Range> iter2 = tree.upper_bound( new Range( spc, last, last ) );
|
||||
IteratorSTL<Range> iter2 = tree.upper_bound(new Range(spc, last, last));
|
||||
|
||||
while ( !iter1.equals( iter2 ) ) {
|
||||
while (!iter1.equals(iter2)) {
|
||||
|
||||
long a = iter1.get().getFirst();
|
||||
long b = iter1.get().getLast();
|
||||
tree.erase(iter1);
|
||||
iter1.increment();
|
||||
if ( Utils.unsignedCompare( a, first ) < 0 ) {
|
||||
tree.insert( new Range( spc, a, first - 1 ) );
|
||||
if (Utils.unsignedCompare(a, first) < 0) {
|
||||
tree.insert(new Range(spc, a, first - 1));
|
||||
}
|
||||
if ( Utils.unsignedCompare( b, last ) > 0 ) {
|
||||
tree.insert( new Range( spc, last + 1, b ) );
|
||||
if (Utils.unsignedCompare(b, last) > 0) {
|
||||
tree.insert(new Range(spc, last + 1, b));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure indicated range is
|
||||
// contained in the rangelist
|
||||
public boolean inRange( Address addr, int size ) {
|
||||
public boolean inRange(Address addr, int size) {
|
||||
|
||||
if ( addr.isInvalid() ) {
|
||||
if (addr.isInvalid()) {
|
||||
return true; // We don't really care
|
||||
}
|
||||
if ( tree.isEmpty() ) {
|
||||
if (tree.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// iter = first range with its first > addr
|
||||
IteratorSTL<Range> iter = tree.upper_bound( new Range( addr.getSpace(), addr.getOffset(),
|
||||
addr.getOffset() ) );
|
||||
if ( iter.isBegin() ) {
|
||||
IteratorSTL<Range> iter =
|
||||
tree.upper_bound(new Range(addr.getSpace(), addr.getOffset(), addr.getOffset()));
|
||||
if (iter.isBegin()) {
|
||||
return false;
|
||||
}
|
||||
// Set iter to last range with range.first <= addr
|
||||
iter.decrement();
|
||||
// if (iter == tree.end()) // iter can't be end if non-empty
|
||||
// return false;
|
||||
if ( !iter.get().getSpace().equals( addr.getSpace() ) ) {
|
||||
if (!iter.get().getSpace().equals(addr.getSpace())) {
|
||||
return false;
|
||||
}
|
||||
if ( Utils.unsignedCompare( iter.get().getLast(), addr.getOffset() + size - 1 ) >= 0 ) {
|
||||
if (Utils.unsignedCompare(iter.get().getLast(), addr.getOffset() + size - 1) >= 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -155,64 +152,65 @@ public class RangeList {
|
|||
|
||||
// Return size of biggest range (up to maxsize) starting at addr
|
||||
// which is completely covered by this rangelist
|
||||
public long longestFit( Address addr, long maxsize ) {
|
||||
if ( addr.isInvalid() ) {
|
||||
public long longestFit(Address addr, long maxsize) {
|
||||
if (addr.isInvalid()) {
|
||||
return 0;
|
||||
}
|
||||
if ( tree.isEmpty() ) {
|
||||
if (tree.isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// iter = first range with its first > addr
|
||||
long offset = addr.getOffset();
|
||||
IteratorSTL<Range> iter = tree.upper_bound( new Range( addr.getSpace(), offset, offset ) );
|
||||
if ( iter.isBegin() ) {
|
||||
IteratorSTL<Range> iter = tree.upper_bound(new Range(addr.getSpace(), offset, offset));
|
||||
if (iter.isBegin()) {
|
||||
return 0;
|
||||
}
|
||||
// Set iter to last range with range.first <= addr
|
||||
iter.decrement();
|
||||
long sizeres = 0;
|
||||
if ( Utils.unsignedCompare( iter.get().getLast(), offset ) < 0 ) {
|
||||
if (Utils.unsignedCompare(iter.get().getLast(), offset) < 0) {
|
||||
return sizeres;
|
||||
}
|
||||
do {
|
||||
if ( !iter.get().getSpace().equals( addr.getSpace() ) ) {
|
||||
if (!iter.get().getSpace().equals(addr.getSpace())) {
|
||||
break;
|
||||
}
|
||||
if ( Utils.unsignedCompare( iter.get().getFirst(), offset ) > 0 ) {
|
||||
if (Utils.unsignedCompare(iter.get().getFirst(), offset) > 0) {
|
||||
break;
|
||||
}
|
||||
sizeres += (iter.get().getLast() + 1 - offset); // Size extends to end of range
|
||||
offset = iter.get().getLast() + 1; // Try to chain on the next range
|
||||
if ( Utils.unsignedCompare( sizeres, maxsize ) >= 0 ) {
|
||||
if (Utils.unsignedCompare(sizeres, maxsize) >= 0) {
|
||||
break; // Don't bother if past maxsize
|
||||
}
|
||||
iter.increment(); // Next range in the chain
|
||||
} while ( !iter.isEnd() );
|
||||
}
|
||||
while (!iter.isEnd());
|
||||
return sizeres;
|
||||
}
|
||||
|
||||
public Range getFirstRange() {
|
||||
if ( tree.isEmpty() ) {
|
||||
if (tree.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return tree.begin().get();
|
||||
}
|
||||
|
||||
public Range getFirstRange( AddrSpace spaceid ) {
|
||||
Range range = new Range(spaceid,0,0);
|
||||
public Range getFirstRange(AddrSpace spaceid) {
|
||||
Range range = new Range(spaceid, 0, 0);
|
||||
IteratorSTL<Range> iter = tree.lower_bound(range);
|
||||
if (iter.equals( tree.end() ) ) {
|
||||
if (iter.equals(tree.end())) {
|
||||
return null;
|
||||
}
|
||||
if ( !iter.get().getSpace().equals( spaceid ) ) {
|
||||
if (!iter.get().getSpace().equals(spaceid)) {
|
||||
return null;
|
||||
}
|
||||
return iter.get();
|
||||
}
|
||||
|
||||
public Range getLastRange() {
|
||||
if ( tree.isEmpty() ) {
|
||||
if (tree.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
IteratorSTL<Range> iter = tree.end();
|
||||
|
@ -220,49 +218,29 @@ public class RangeList {
|
|||
return iter.get();
|
||||
}
|
||||
|
||||
public Range getLastRange( AddrSpace spaceid ) {
|
||||
Range range = new Range( spaceid, -1, -1 );
|
||||
public Range getLastRange(AddrSpace spaceid) {
|
||||
Range range = new Range(spaceid, -1, -1);
|
||||
IteratorSTL<Range> iter = tree.upper_bound(range);
|
||||
if (iter.equals( tree.begin() ) ) {
|
||||
if (iter.equals(tree.begin())) {
|
||||
return null;
|
||||
}
|
||||
iter.decrement();
|
||||
if ( !iter.get().getSpace().equals( spaceid ) ) {
|
||||
if (!iter.get().getSpace().equals(spaceid)) {
|
||||
return null;
|
||||
}
|
||||
return iter.get();
|
||||
}
|
||||
|
||||
public void printBounds( PrintStream s ) {
|
||||
if ( tree.isEmpty() ) {
|
||||
s.println( "all" );
|
||||
} else {
|
||||
IteratorSTL<Range> it;
|
||||
for ( it = tree.begin(); !it.isEnd(); it.increment() ) {
|
||||
public void printBounds(PrintStream s) {
|
||||
if (tree.isEmpty()) {
|
||||
s.println("all");
|
||||
}
|
||||
else {
|
||||
for (IteratorSTL<Range> it = tree.begin(); !it.isEnd(); it.increment()) {
|
||||
Range range = it.get();
|
||||
range.printBounds( s );
|
||||
range.printBounds(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void saveXml( PrintStream s ) {
|
||||
s.println( "<rangelist>" );
|
||||
IteratorSTL<Range> it;
|
||||
for ( it = tree.begin(); !it.isEnd(); it.increment() ) {
|
||||
Range range = it.get();
|
||||
range.saveXml( s );
|
||||
}
|
||||
s.println( "</rangelist>" );
|
||||
}
|
||||
|
||||
public void restoreXml( Element el, Translate trans ) {
|
||||
List<?> children = el.getChildren();
|
||||
for ( Object object : children ) {
|
||||
Element child = (Element) object;
|
||||
Range range = new Range();
|
||||
range.restoreXml( child, trans );
|
||||
tree.insert( range );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -18,31 +17,28 @@ package ghidra.pcodeCPort.globalcontext;
|
|||
|
||||
public class ContextBitRange {
|
||||
|
||||
private int word;
|
||||
private int startbit;
|
||||
private int endbit;
|
||||
private int shift;
|
||||
private int mask;
|
||||
private int word;
|
||||
private int startbit;
|
||||
private int endbit;
|
||||
private int shift;
|
||||
private int mask;
|
||||
|
||||
public ContextBitRange() { // For use with restoreXml
|
||||
}
|
||||
|
||||
public ContextBitRange(int sbit,int ebit) {
|
||||
word = sbit/(32);
|
||||
startbit = sbit - word*32;
|
||||
endbit = ebit - word*32;
|
||||
shift = 32-endbit-1;
|
||||
mask = -1 >>> (startbit+shift);
|
||||
}
|
||||
|
||||
public void setValue(int[] vec, int val) {
|
||||
int newval = vec[word];
|
||||
newval &= ~(mask<<shift);
|
||||
newval |= ((val & mask)<<shift);
|
||||
vec[word] = newval;
|
||||
}
|
||||
|
||||
public int getValue(int[] vec) {
|
||||
return ((vec[word]>>shift)&mask);
|
||||
}
|
||||
public ContextBitRange(int sbit, int ebit) {
|
||||
word = sbit / (32);
|
||||
startbit = sbit - word * 32;
|
||||
endbit = ebit - word * 32;
|
||||
shift = 32 - endbit - 1;
|
||||
mask = -1 >>> (startbit + shift);
|
||||
}
|
||||
|
||||
public void setValue(int[] vec, int val) {
|
||||
int newval = vec[word];
|
||||
newval &= ~(mask << shift);
|
||||
newval |= ((val & mask) << shift);
|
||||
vec[word] = newval;
|
||||
}
|
||||
|
||||
public int getValue(int[] vec) {
|
||||
return ((vec[word] >> shift) & mask);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,79 +0,0 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.pcodeCPort.globalcontext;
|
||||
|
||||
import ghidra.pcodeCPort.address.*;
|
||||
import ghidra.pcodeCPort.space.*;
|
||||
import ghidra.pcodeCPort.utils.*;
|
||||
|
||||
public class ContextCache {
|
||||
|
||||
private ContextDatabase database = null;
|
||||
private boolean allowset;
|
||||
private AddrSpace curspace = null;
|
||||
private long first;
|
||||
private long last;
|
||||
private int[] context; // Cached context
|
||||
|
||||
public void allowSet( boolean val ) {
|
||||
allowset = val;
|
||||
}
|
||||
|
||||
public ContextCache( ContextDatabase db ) {
|
||||
database = db;
|
||||
curspace = null; // Mark cache as invalid
|
||||
allowset = true;
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
}
|
||||
|
||||
public ContextDatabase getDatabase() {
|
||||
return database;
|
||||
}
|
||||
|
||||
public void getContext( Address addr, int[] buf ) {
|
||||
if ( (!addr.getSpace().equals( curspace ))
|
||||
|| (Utils.unsignedCompare( first, addr.getOffset() ) > 0)
|
||||
|| (Utils.unsignedCompare( last, addr.getOffset() ) < 0) ) {
|
||||
curspace = addr.getSpace();
|
||||
|
||||
MutableLong firstMutable = new MutableLong( first );
|
||||
MutableLong lastMutable = new MutableLong( last );
|
||||
context = database.getContext( addr, firstMutable, lastMutable );
|
||||
|
||||
first = firstMutable.get();
|
||||
last = lastMutable.get();
|
||||
}
|
||||
for ( int i = 0; i < database.getContextSize(); ++i ) {
|
||||
buf[i] = context[i];
|
||||
}
|
||||
}
|
||||
|
||||
public void setContext( Address addr, int num, int mask, int value ) {
|
||||
if ( !allowset ) {
|
||||
return;
|
||||
}
|
||||
database.setContextRange( addr, num, mask, value );
|
||||
if ( (addr.getSpace().equals( curspace ))
|
||||
&& (Utils.unsignedCompare( first, addr.getOffset() ) <= 0)
|
||||
&& (Utils.unsignedCompare( last, addr.getOffset() ) >= 0) ) {
|
||||
curspace = null; // Invalidate cache
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,200 +0,0 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.pcodeCPort.globalcontext;
|
||||
|
||||
import generic.stl.VectorSTL;
|
||||
import ghidra.pcodeCPort.address.Address;
|
||||
import ghidra.pcodeCPort.pcoderaw.VarnodeData;
|
||||
import ghidra.pcodeCPort.translate.Translate;
|
||||
import ghidra.pcodeCPort.utils.MutableLong;
|
||||
import ghidra.pcodeCPort.utils.Utils;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.jdom.Element;
|
||||
|
||||
/**
|
||||
* This is the interface and implementation for a database of memory locations which should be
|
||||
* treated likeants. These come in two flavors:
|
||||
* <p>
|
||||
* 1) Low-level context variables These can affect instruction decoding. These can be as small as a
|
||||
* single bit and need to be defined in the sleigh module (so that sleigh knows how they effect
|
||||
* disassembly). These variables are not mapped to normal memory locations with a space and offset.
|
||||
* (Although they often have a corresponding embedding into a normal memory location) The model to
|
||||
* keep in mind is special bitfields within a control register.
|
||||
* <p>
|
||||
* 2) High-level tracked variables These are normal memory locations that are to be treated asants
|
||||
* across some range of code. These are normally some register that is being kept track of be the
|
||||
* compiler outside the domain of normal local and global variables. They have a specific value
|
||||
* established by the compiler coming in to a function but are not supposed to be interpreted as a
|
||||
* high-level variable. Typical examples are the String instruction direction flag and segment
|
||||
* registers. These are all interpreted as aant value at the start of a function, but the function
|
||||
* can recycle the memory location for other calculations once theant has been used.
|
||||
*/
|
||||
public abstract class ContextDatabase {
|
||||
|
||||
public void dispose() {
|
||||
}
|
||||
|
||||
public abstract int getContextSize();
|
||||
|
||||
public abstract void registerVariable(String nm, int sbit, int ebit);
|
||||
|
||||
public abstract ContextBitRange getVariable(String nm);
|
||||
|
||||
public abstract void getRegion(VectorSTL<int[]> res, Address addr1, Address addr2);
|
||||
|
||||
public abstract int[] getContext(Address addr);
|
||||
|
||||
public abstract int[] getContext(Address addr, MutableLong first, MutableLong last);
|
||||
|
||||
public abstract int[] getDefaultValue();
|
||||
|
||||
public abstract int[] createContext(Address addr);
|
||||
|
||||
public abstract VectorSTL<TrackedContext> getTrackedDefault();
|
||||
|
||||
public abstract VectorSTL<TrackedContext> getTrackedSet(Address addr);
|
||||
|
||||
public abstract VectorSTL<TrackedContext> createSet(Address addr1, Address addr2);
|
||||
|
||||
public abstract void saveXml(PrintStream s);
|
||||
|
||||
public abstract void restoreXml(Element el, Translate translate);
|
||||
|
||||
public abstract void restoreFromSpec(Element el, Translate translate);
|
||||
|
||||
protected void saveTracked(PrintStream s, Address addr, VectorSTL<TrackedContext> vec) {
|
||||
if (vec.empty()) {
|
||||
return;
|
||||
}
|
||||
s.append("<tracked_pointset");
|
||||
addr.getSpace().saveXmlAttributes(s, addr.getOffset());
|
||||
s.append(">\n");
|
||||
for (int i = 0; i < vec.size(); ++i) {
|
||||
s.append(" ");
|
||||
vec.get(i).saveXml(s);
|
||||
}
|
||||
s.append("</tracked_pointset>\n");
|
||||
}
|
||||
|
||||
public void setVariableDefault(String nm, int val) {
|
||||
ContextBitRange var = getVariable(nm);
|
||||
var.setValue(getDefaultValue(), val);
|
||||
}
|
||||
|
||||
public int getDefaultValue(String nm) {
|
||||
ContextBitRange var = getVariable(nm);
|
||||
return var.getValue(getDefaultValue());
|
||||
}
|
||||
|
||||
/** Set value of context register, starting at addr */
|
||||
public void setVariable(String nm, Address addr, int value) {
|
||||
ContextBitRange bitrange = getVariable(nm);
|
||||
|
||||
int[] newcontext = createContext(addr);
|
||||
bitrange.setValue(newcontext, value);
|
||||
}
|
||||
|
||||
public int getVariable(String nm, Address addr) {
|
||||
ContextBitRange bitrange = getVariable(nm);
|
||||
|
||||
int[] context = getContext(addr);
|
||||
return bitrange.getValue(context);
|
||||
}
|
||||
|
||||
/** Set specific bits in context */
|
||||
public void setContextRange(Address addr, int num, int mask, int value) {
|
||||
int[] newcontext = createContext(addr);
|
||||
|
||||
int val = newcontext[num];
|
||||
val &= ~mask; // Clear range to zero
|
||||
val |= value;
|
||||
newcontext[num] = val;
|
||||
}
|
||||
|
||||
/** Set value of context register between begad and endad */
|
||||
public void setVariableRegion(String nm, Address begad, Address endad, int value) {
|
||||
ContextBitRange bitrange = getVariable(nm);
|
||||
|
||||
VectorSTL<int[]> vec = new VectorSTL<int[]>();
|
||||
getRegion(vec, begad, endad);
|
||||
for (int i = 0; i < vec.size(); ++i) {
|
||||
bitrange.setValue(vec.get(i), value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* For a particular tracked memory location, get the value at a particular point.
|
||||
*/
|
||||
public long getTrackedValue(VarnodeData mem, Address point) {
|
||||
VectorSTL<TrackedContext> tset = getTrackedSet(point);
|
||||
long endoff = mem.offset + mem.size - 1;
|
||||
long tendoff;
|
||||
for (int i = 0; i < tset.size(); ++i) {
|
||||
TrackedContext tcont = tset.get(i);
|
||||
if (tcont == null) {
|
||||
tcont = new TrackedContext();
|
||||
tset.set(i, tcont);
|
||||
}
|
||||
|
||||
// tcont must contain -mem-
|
||||
if (tcont.loc.space != mem.space) {
|
||||
continue;
|
||||
}
|
||||
if (tcont.loc.offset > mem.offset) {
|
||||
continue;
|
||||
}
|
||||
tendoff = tcont.loc.offset + tcont.loc.size - 1;
|
||||
if (tendoff < endoff) {
|
||||
continue;
|
||||
}
|
||||
|
||||
long res = tcont.val;
|
||||
// If we have proper containment, trim value based on endianness
|
||||
if (tcont.loc.space.isBigEndian()) {
|
||||
if (endoff != tendoff) {
|
||||
res >>>= (8 * (tendoff - mem.offset));
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (mem.offset != tcont.loc.offset) {
|
||||
res >>>= (8 * (mem.offset - tcont.loc.offset));
|
||||
}
|
||||
}
|
||||
res &= Utils.calc_mask(mem.size); // Final trim based on size
|
||||
return res;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static void restoreTracked(Element el, Translate trans, VectorSTL<TrackedContext> vec) {
|
||||
vec.clear();
|
||||
|
||||
List<?> list = el.getChildren();
|
||||
Iterator<?> iter = list.iterator();
|
||||
|
||||
while (iter.hasNext()) {
|
||||
Element subel = (Element) iter.next();
|
||||
vec.push_back(new TrackedContext());
|
||||
vec.back().restoreXml(subel, trans);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,6 +1,5 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -16,37 +15,9 @@
|
|||
*/
|
||||
package ghidra.pcodeCPort.globalcontext;
|
||||
|
||||
import ghidra.pcodeCPort.address.*;
|
||||
import ghidra.pcodeCPort.pcoderaw.*;
|
||||
import ghidra.pcodeCPort.translate.*;
|
||||
import ghidra.pcodeCPort.utils.*;
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
import org.jdom.Element;
|
||||
|
||||
|
||||
import ghidra.pcodeCPort.pcoderaw.VarnodeData;
|
||||
|
||||
public class TrackedContext {
|
||||
public VarnodeData loc = new VarnodeData();
|
||||
public long val;
|
||||
|
||||
public void saveXml( PrintStream s ) {
|
||||
s.append( "<set" );
|
||||
loc.space.saveXmlAttributes( s, loc.offset, loc.size );
|
||||
XmlUtils.a_v_u( s, "val", val );
|
||||
s.append( "/>\n" );
|
||||
}
|
||||
|
||||
public void restoreXml( Element el, Translate trans ) {
|
||||
VarnodeData varnodeData = Address.restoreXml( el, trans );
|
||||
Address addr = varnodeData.getAddress();
|
||||
int size = varnodeData.size;
|
||||
|
||||
val = XmlUtils.decodeUnknownLong( el.getAttributeValue( "val" ) );
|
||||
|
||||
loc.space = addr.getSpace();
|
||||
loc.offset = addr.getOffset();
|
||||
loc.size = size;
|
||||
}
|
||||
public VarnodeData loc = new VarnodeData();
|
||||
public long val;
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
*/
|
||||
package ghidra.pcodeCPort.opcodes;
|
||||
// Names of ops associated with their opcode number
|
||||
|
||||
// Some of the names have been replaced with special placeholder
|
||||
// ops for the sleigh compiler and interpreter these are as follows:
|
||||
// MULTIEQUAL = BUILD
|
||||
|
@ -23,7 +24,8 @@ package ghidra.pcodeCPort.opcodes;
|
|||
// PTRSUB = CROSSBUILD
|
||||
|
||||
public enum OpCode {
|
||||
DO_NOT_USE_ME_I_AM_ENUM_ELEMENT_ZERO, CPUI_COPY, // Copy one operand to another
|
||||
DO_NOT_USE_ME_I_AM_ENUM_ELEMENT_ZERO,
|
||||
CPUI_COPY, // Copy one operand to another
|
||||
CPUI_LOAD, // Dereference a pointer into specified space
|
||||
CPUI_STORE, // Store at a pointer into specified space
|
||||
|
||||
|
@ -127,9 +129,9 @@ public enum OpCode {
|
|||
public OpCode getOpCodeFlip()
|
||||
|
||||
{ // Return the complimentary opcode for boolean operations
|
||||
// (or CPUI_MAX if not boolean) Set reorder to true if
|
||||
// the complimentary operation would involve reordering
|
||||
// the input parameters
|
||||
// (or CPUI_MAX if not boolean) Set reorder to true if
|
||||
// the complimentary operation would involve reordering
|
||||
// the input parameters
|
||||
switch (this) {
|
||||
case CPUI_INT_EQUAL:
|
||||
return CPUI_INT_NOTEQUAL;
|
||||
|
@ -162,9 +164,9 @@ public enum OpCode {
|
|||
public boolean getBooleanFlip()
|
||||
|
||||
{ // Return the complimentary opcode for boolean operations
|
||||
// (or CPUI_MAX if not boolean) Set reorder to true if
|
||||
// the complimentary operation would involve reordering
|
||||
// the input parameters
|
||||
// (or CPUI_MAX if not boolean) Set reorder to true if
|
||||
// the complimentary operation would involve reordering
|
||||
// the input parameters
|
||||
switch (this) {
|
||||
case CPUI_INT_EQUAL:
|
||||
return false;
|
||||
|
@ -200,21 +202,20 @@ public enum OpCode {
|
|||
"INT_ADD", "INT_SUB", "INT_CARRY", "INT_SCARRY", "INT_SBORROW", "INT_2COMP", "INT_NEGATE",
|
||||
"INT_XOR", "INT_AND", "INT_OR", "INT_LEFT", "INT_RIGHT", "INT_SRIGHT", "INT_MULT",
|
||||
"INT_DIV", "INT_SDIV", "INT_REM", "INT_SREM", "BOOL_NEGATE", "BOOL_XOR", "BOOL_AND",
|
||||
"BOOL_OR", "FLOAT_EQUAL", "FLOAT_NOTEQUAL", "FLOAT_LESS", "FLOAT_LESSEQUAL",
|
||||
"UNUSED1", "FLOAT_NAN", "FLOAT_ADD", "FLOAT_DIV", "FLOAT_MULT", "FLOAT_SUB",
|
||||
"FLOAT_NEG", "FLOAT_ABS", "FLOAT_SQRT", "INT2FLOAT", "FLOAT2FLOAT", "TRUNC", "CEIL",
|
||||
"FLOOR", "ROUND", "BUILD", "DELAY_SLOT", "PIECE", "SUBPIECE", "CAST", "LABEL",
|
||||
"CROSSBUILD", "SEGMENTOP", "CPOOLREF", "NEW", "INSERT", "EXTRACT", "POPCOUNT",
|
||||
"LZCOUNT" };
|
||||
"BOOL_OR", "FLOAT_EQUAL", "FLOAT_NOTEQUAL", "FLOAT_LESS", "FLOAT_LESSEQUAL", "UNUSED1",
|
||||
"FLOAT_NAN", "FLOAT_ADD", "FLOAT_DIV", "FLOAT_MULT", "FLOAT_SUB", "FLOAT_NEG", "FLOAT_ABS",
|
||||
"FLOAT_SQRT", "INT2FLOAT", "FLOAT2FLOAT", "TRUNC", "CEIL", "FLOOR", "ROUND", "BUILD",
|
||||
"DELAY_SLOT", "PIECE", "SUBPIECE", "CAST", "LABEL", "CROSSBUILD", "SEGMENTOP", "CPOOLREF",
|
||||
"NEW", "INSERT", "EXTRACT", "POPCOUNT", "LZCOUNT" };
|
||||
|
||||
public static String get_opname(OpCode op) {
|
||||
return opcode_name[op.ordinal()];
|
||||
}
|
||||
|
||||
static final int opcode_indices[] = { 0, 39, 37, 40, 38, 4, 6, 60, 7, 8, 9, 64, 5, 57, 1, 68, 66,
|
||||
61, 71, 55, 52, 47, 48, 41, 43, 44, 49, 46, 51, 42, 53, 50, 58, 70, 54, 24, 19, 27, 21,
|
||||
33, 11, 29, 15, 16, 32, 25, 12, 28, 35, 30, 23, 22, 34, 18, 13, 14, 36, 31, 20, 26, 17,
|
||||
65, 2, 73, 69, 62, 72, 10, 59, 67, 3, 63, 56, 45 };
|
||||
static final int opcode_indices[] = { 0, 39, 37, 40, 38, 4, 6, 60, 7, 8, 9, 64, 5, 57, 1, 68,
|
||||
66, 61, 71, 55, 52, 47, 48, 41, 43, 44, 49, 46, 51, 42, 53, 50, 58, 70, 54, 24, 19, 27, 21,
|
||||
33, 11, 29, 15, 16, 32, 25, 12, 28, 35, 30, 23, 22, 34, 18, 13, 14, 36, 31, 20, 26, 17, 65,
|
||||
2, 73, 69, 62, 72, 10, 59, 67, 3, 63, 56, 45 };
|
||||
|
||||
public static OpCode get_opcode(String nm) { // Use binary search to find name
|
||||
int min = 1; // Don't include BLANK
|
||||
|
|
|
@ -15,12 +15,9 @@
|
|||
*/
|
||||
package ghidra.pcodeCPort.pcoderaw;
|
||||
|
||||
import org.jdom.Element;
|
||||
|
||||
import ghidra.pcodeCPort.address.*;
|
||||
import ghidra.pcodeCPort.error.*;
|
||||
import ghidra.pcodeCPort.space.*;
|
||||
import ghidra.pcodeCPort.translate.*;
|
||||
import ghidra.pcodeCPort.address.Address;
|
||||
import ghidra.pcodeCPort.address.AddressUtils;
|
||||
import ghidra.pcodeCPort.space.AddrSpace;
|
||||
|
||||
public class VarnodeData {
|
||||
// string name; // This field will be depracated when sleigh comes on line
|
||||
|
@ -29,17 +26,18 @@ public class VarnodeData {
|
|||
public long offset;
|
||||
|
||||
public int size;
|
||||
// for use before restoreXML
|
||||
public VarnodeData() {
|
||||
|
||||
public VarnodeData() {
|
||||
}
|
||||
public VarnodeData( AddrSpace base, long off, int size ) {
|
||||
|
||||
public VarnodeData(AddrSpace base, long off, int size) {
|
||||
space = base;
|
||||
offset = off;
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals( Object obj ) {
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
|
@ -52,53 +50,25 @@ public class VarnodeData {
|
|||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return space.hashCode() + (int) offset + size;
|
||||
return space.hashCode() + (int) offset + size;
|
||||
}
|
||||
|
||||
public int compareTo( VarnodeData other ) {
|
||||
int result = space.compareTo( other.space );
|
||||
|
||||
public int compareTo(VarnodeData other) {
|
||||
int result = space.compareTo(other.space);
|
||||
if (result != 0) {
|
||||
return result;
|
||||
}
|
||||
result = AddressUtils.unsignedCompare( offset, other.offset );
|
||||
result = AddressUtils.unsignedCompare(offset, other.offset);
|
||||
if (result != 0) {
|
||||
return result;
|
||||
}
|
||||
return other.size - size;// BIG sizes come first
|
||||
}
|
||||
|
||||
// Build this VarnodeData from an \b \<addr\> tag
|
||||
// \param el is the parsed tag
|
||||
// \param trans is the relevant processor translator
|
||||
public void restoreXml( Element el, Translate trans ) {
|
||||
String name = el.getAttributeValue( "name" );
|
||||
if (name != null) {
|
||||
VarnodeData vdata = trans.getRegister( name );
|
||||
space = vdata.space;
|
||||
offset = vdata.offset;
|
||||
size = vdata.size;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
String attributeValue = el.getAttributeValue( "space" );
|
||||
if ( attributeValue == null ) {
|
||||
return;
|
||||
}
|
||||
|
||||
space = trans.getSpaceByName( attributeValue );
|
||||
if (space == null) {
|
||||
throw new LowlevelError( "Unknown space name: " + attributeValue );
|
||||
}
|
||||
offset = AddrSpace.restore_xml_offset( el );
|
||||
size = AddrSpace.restore_xml_size( el );
|
||||
}
|
||||
|
||||
|
||||
public Address getAddress() {
|
||||
// if ( space == null ) {
|
||||
// return new Address( AddrSpace.MIN_SPACE, 0 );
|
||||
// }
|
||||
return new Address(this.space, this.offset);
|
||||
return new Address(this.space, this.offset);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,16 +15,15 @@
|
|||
*/
|
||||
package ghidra.pcodeCPort.semantics;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import org.jdom.Element;
|
||||
import java.io.IOException;
|
||||
|
||||
import generic.stl.VectorSTL;
|
||||
import ghidra.pcodeCPort.error.LowlevelError;
|
||||
import ghidra.pcodeCPort.space.AddrSpace;
|
||||
import ghidra.pcodeCPort.space.spacetype;
|
||||
import ghidra.pcodeCPort.translate.Translate;
|
||||
import ghidra.pcodeCPort.utils.XmlUtils;
|
||||
import ghidra.program.model.pcode.Encoder;
|
||||
|
||||
public class ConstTpl {
|
||||
@Override
|
||||
|
@ -89,8 +88,8 @@ public class ConstTpl {
|
|||
handle_index = ht;
|
||||
select = vf;
|
||||
}
|
||||
|
||||
public ConstTpl(const_type tp,int ht,v_field vf,long plus) {
|
||||
|
||||
public ConstTpl(const_type tp, int ht, v_field vf, long plus) {
|
||||
type = const_type.handle;
|
||||
handle_index = ht;
|
||||
select = vf;
|
||||
|
@ -117,7 +116,7 @@ public class ConstTpl {
|
|||
public const_type getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
|
||||
public v_field getSelect() {
|
||||
return select;
|
||||
}
|
||||
|
@ -224,168 +223,89 @@ public class ConstTpl {
|
|||
case v_offset_plus:
|
||||
long tmp = value_real;
|
||||
copyIntoMe(newhandle.getPtrOffset());
|
||||
if (type == const_type.real)
|
||||
if (type == const_type.real) {
|
||||
value_real += (tmp & 0xffff);
|
||||
else if ((type == const_type.handle)&&(select == v_field.v_offset)) {
|
||||
}
|
||||
else if ((type == const_type.handle) && (select == v_field.v_offset)) {
|
||||
select = v_field.v_offset_plus;
|
||||
value_real = tmp;
|
||||
}
|
||||
else
|
||||
else {
|
||||
throw new LowlevelError("Cannot truncate macro input in this way");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static void printHandleSelector(PrintStream s, v_field val) {
|
||||
switch (val) {
|
||||
case v_space:
|
||||
s.append("space");
|
||||
break;
|
||||
case v_offset:
|
||||
s.append("offset");
|
||||
break;
|
||||
case v_size:
|
||||
s.append("size");
|
||||
break;
|
||||
case v_offset_plus:
|
||||
s.append("offset_plus");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static v_field readHandleSelector(String name) {
|
||||
if (name.equals("space")) {
|
||||
return v_field.v_space;
|
||||
}
|
||||
if (name.equals("offset")) {
|
||||
return v_field.v_offset;
|
||||
}
|
||||
if (name.equals("size")) {
|
||||
return v_field.v_size;
|
||||
}
|
||||
if (name.equals("offset_plus")) {
|
||||
return v_field.v_offset_plus;
|
||||
}
|
||||
throw new LowlevelError("Bad handle selector");
|
||||
}
|
||||
|
||||
public void changeHandleIndex(VectorSTL<Integer> handmap) {
|
||||
if (type == const_type.handle) {
|
||||
handle_index = handmap.get(handle_index);
|
||||
}
|
||||
}
|
||||
|
||||
public void saveXml(PrintStream s) {
|
||||
s.append("<const_tpl type=\"");
|
||||
public void encode(Encoder encoder) throws IOException {
|
||||
switch (type) {
|
||||
case real:
|
||||
s.append("real\" val=\"0x");
|
||||
s.append(Long.toHexString(value_real));
|
||||
s.append("\"/>");
|
||||
encoder.openElement(ELEM_CONST_REAL);
|
||||
encoder.writeUnsignedInteger(ATTRIB_VAL, value_real);
|
||||
encoder.closeElement(ELEM_CONST_REAL);
|
||||
break;
|
||||
case handle:
|
||||
s.append("handle\" val=\"");
|
||||
s.print(handle_index);
|
||||
s.append("\" ");
|
||||
s.append("s=\"");
|
||||
printHandleSelector(s, select);
|
||||
s.append('\"');
|
||||
if (select == v_field.v_offset_plus)
|
||||
s.append(" plus=\"0x").append(Long.toHexString(value_real)).append('\"');
|
||||
s.append("/>");
|
||||
encoder.openElement(ELEM_CONST_HANDLE);
|
||||
encoder.writeSignedInteger(ATTRIB_VAL, handle_index);
|
||||
encoder.writeSignedInteger(ATTRIB_S, select.ordinal());
|
||||
if (select == v_field.v_offset_plus) {
|
||||
encoder.writeUnsignedInteger(ATTRIB_PLUS, value_real);
|
||||
}
|
||||
encoder.closeElement(ELEM_CONST_HANDLE);
|
||||
break;
|
||||
case j_start:
|
||||
s.append("start\"/>");
|
||||
encoder.openElement(ELEM_CONST_START);
|
||||
encoder.closeElement(ELEM_CONST_START);
|
||||
break;
|
||||
case j_next:
|
||||
s.append("next\"/>");
|
||||
encoder.openElement(ELEM_CONST_NEXT);
|
||||
encoder.closeElement(ELEM_CONST_NEXT);
|
||||
break;
|
||||
case j_next2:
|
||||
s.append("next2\"/>");
|
||||
encoder.openElement(ELEM_CONST_NEXT2);
|
||||
encoder.closeElement(ELEM_CONST_NEXT2);
|
||||
break;
|
||||
case j_curspace:
|
||||
s.append("curspace\"/>");
|
||||
encoder.openElement(ELEM_CONST_CURSPACE);
|
||||
encoder.closeElement(ELEM_CONST_CURSPACE);
|
||||
break;
|
||||
case j_curspace_size:
|
||||
s.append("curspace_size\"/>");
|
||||
encoder.openElement(ELEM_CONST_CURSPACE_SIZE);
|
||||
encoder.closeElement(ELEM_CONST_CURSPACE_SIZE);
|
||||
break;
|
||||
case spaceid:
|
||||
s.append("spaceid\" name=\"");
|
||||
s.append(spaceid.getName());
|
||||
s.append("\"/>");
|
||||
encoder.openElement(ELEM_CONST_SPACEID);
|
||||
encoder.writeSpace(ATTRIB_SPACE, spaceid.getIndex(), spaceid.getName());
|
||||
encoder.closeElement(ELEM_CONST_SPACEID);
|
||||
break;
|
||||
case j_relative:
|
||||
s.append("relative\" val=\"0x");
|
||||
s.append(Long.toHexString(value_real));
|
||||
s.append("\"/>");
|
||||
encoder.openElement(ELEM_CONST_RELATIVE);
|
||||
encoder.writeUnsignedInteger(ATTRIB_VAL, value_real);
|
||||
encoder.closeElement(ELEM_CONST_RELATIVE);
|
||||
break;
|
||||
case j_flowref:
|
||||
s.append("flowref\"/>");
|
||||
encoder.openElement(ELEM_CONST_FLOWREF);
|
||||
encoder.closeElement(ELEM_CONST_FLOWREF);
|
||||
break;
|
||||
case j_flowref_size:
|
||||
s.append("flowref_size\"/>");
|
||||
encoder.openElement(ELEM_CONST_FLOWREF_SIZE);
|
||||
encoder.closeElement(ELEM_CONST_FLOWREF_SIZE);
|
||||
break;
|
||||
case j_flowdest:
|
||||
s.append("flowdest\"/>");
|
||||
encoder.openElement(ELEM_CONST_FLOWDEST);
|
||||
encoder.closeElement(ELEM_CONST_FLOWDEST);
|
||||
break;
|
||||
case j_flowdest_size:
|
||||
s.append("flowdest_size\"/>");
|
||||
encoder.openElement(ELEM_CONST_FLOWDEST_SIZE);
|
||||
encoder.closeElement(ELEM_CONST_FLOWDEST_SIZE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void restoreXml(Element el, Translate trans) {
|
||||
String typestring = el.getAttributeValue("type");
|
||||
if (typestring.equals("real")) {
|
||||
type = const_type.real;
|
||||
value_real = XmlUtils.decodeUnknownLong(el.getAttributeValue("val"));
|
||||
}
|
||||
else if (typestring.equals("handle")) {
|
||||
type = const_type.handle;
|
||||
handle_index = XmlUtils.decodeUnknownInt(el.getAttributeValue("val"));
|
||||
select = readHandleSelector(el.getAttributeValue("s"));
|
||||
if (select == v_field.v_offset_plus) {
|
||||
value_real = XmlUtils.decodeUnknownLong(el.getAttributeValue("plus"));
|
||||
}
|
||||
}
|
||||
else if (typestring.equals("start")) {
|
||||
type = const_type.j_start;
|
||||
}
|
||||
else if (typestring.equals("next")) {
|
||||
type = const_type.j_next;
|
||||
}
|
||||
else if (typestring.equals("next2")) {
|
||||
type = const_type.j_next2;
|
||||
}
|
||||
else if (typestring.equals("curspace")) {
|
||||
type = const_type.j_curspace;
|
||||
}
|
||||
else if (typestring.equals("curspace_size")) {
|
||||
type = const_type.j_curspace_size;
|
||||
}
|
||||
else if (typestring.equals("spaceid")) {
|
||||
type = const_type.spaceid;
|
||||
spaceid = trans.getSpaceByName(el.getAttributeValue("name"));
|
||||
}
|
||||
else if (typestring.equals("relative")) {
|
||||
type = const_type.j_relative;
|
||||
value_real = XmlUtils.decodeUnknownLong(el.getAttributeValue("val"));
|
||||
}
|
||||
else if (typestring.equals("flowref")) {
|
||||
type = const_type.j_flowref;
|
||||
}
|
||||
else if (typestring.equals("flowref_size")) {
|
||||
type = const_type.j_flowref_size;
|
||||
}
|
||||
else if (typestring.equals("flowdest")) {
|
||||
type = const_type.j_flowdest;
|
||||
}
|
||||
else if (typestring.equals("flowdest_size")) {
|
||||
type = const_type.j_flowdest_size;
|
||||
}
|
||||
else {
|
||||
throw new LowlevelError("Bad constant type");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,16 +15,15 @@
|
|||
*/
|
||||
package ghidra.pcodeCPort.semantics;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.util.*;
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import org.jdom.Element;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import generic.stl.*;
|
||||
import ghidra.pcodeCPort.opcodes.OpCode;
|
||||
import ghidra.pcodeCPort.space.AddrSpace;
|
||||
import ghidra.pcodeCPort.translate.Translate;
|
||||
import ghidra.pcodeCPort.utils.XmlUtils;
|
||||
import ghidra.program.model.pcode.Encoder;
|
||||
import ghidra.sleigh.grammar.Location;
|
||||
import ghidra.sleigh.grammar.LocationUtil;
|
||||
|
||||
|
@ -49,7 +48,7 @@ public class ConstructTpl {
|
|||
public int numLabels() {
|
||||
return numlabels;
|
||||
}
|
||||
|
||||
|
||||
public void setNumLabels(int val) {
|
||||
numlabels = val;
|
||||
}
|
||||
|
@ -57,7 +56,7 @@ public class ConstructTpl {
|
|||
public void setOpvec(VectorSTL<OpTpl> opvec) {
|
||||
vec = opvec;
|
||||
}
|
||||
|
||||
|
||||
public VectorSTL<OpTpl> getOpvec() {
|
||||
return vec;
|
||||
}
|
||||
|
@ -127,9 +126,9 @@ public class ConstructTpl {
|
|||
for (int i = 0; i < check.size(); ++i) {
|
||||
if (check.get(i) == 0) { // Didn't see a BUILD statement
|
||||
op = new OpTpl(min, OpCode.CPUI_MULTIEQUAL);
|
||||
indvn =
|
||||
new VarnodeTpl(min, new ConstTpl(const_space), new ConstTpl(
|
||||
ConstTpl.const_type.real, i), new ConstTpl(ConstTpl.const_type.real, 4));
|
||||
indvn = new VarnodeTpl(min, new ConstTpl(const_space),
|
||||
new ConstTpl(ConstTpl.const_type.real, i),
|
||||
new ConstTpl(ConstTpl.const_type.real, 4));
|
||||
op.addInput(indvn);
|
||||
vec.insert(vec.begin(), op);
|
||||
}
|
||||
|
@ -205,67 +204,28 @@ public class ConstructTpl {
|
|||
}
|
||||
}
|
||||
|
||||
public void saveXml(PrintStream s, int sectionid) {
|
||||
s.append("<construct_tpl");
|
||||
public void encode(Encoder encoder, int sectionid) throws IOException {
|
||||
encoder.openElement(ELEM_CONSTRUCT_TPL);
|
||||
if (sectionid >= 0) {
|
||||
s.append(" section=\"");
|
||||
s.print(sectionid);
|
||||
s.append("\"");
|
||||
encoder.writeSignedInteger(ATTRIB_SECTION, sectionid);
|
||||
}
|
||||
if (delayslot != 0) {
|
||||
s.append(" delay=\"");
|
||||
s.print(delayslot);
|
||||
s.append("\"");
|
||||
encoder.writeSignedInteger(ATTRIB_DELAY, delayslot); // FIXME: Seems to be unused
|
||||
}
|
||||
if (numlabels != 0) {
|
||||
s.append(" labels=\"");
|
||||
s.print(numlabels);
|
||||
s.append("\"");
|
||||
encoder.writeSignedInteger(ATTRIB_LABELS, numlabels);
|
||||
}
|
||||
s.append(">\n");
|
||||
if (result != null) {
|
||||
result.saveXml(s);
|
||||
result.encode(encoder);
|
||||
}
|
||||
else {
|
||||
s.append("<null/>");
|
||||
encoder.openElement(ELEM_NULL);
|
||||
encoder.closeElement(ELEM_NULL);
|
||||
}
|
||||
for (int i = 0; i < vec.size(); ++i) {
|
||||
vec.get(i).saveXml(s);
|
||||
vec.get(i).encode(encoder);
|
||||
}
|
||||
s.append("</construct_tpl>\n");
|
||||
}
|
||||
|
||||
public int restoreXml(Element el, Translate trans) {
|
||||
int sectionid = -1;
|
||||
String str = el.getAttributeValue("delay");
|
||||
if (str != null) {
|
||||
delayslot = XmlUtils.decodeUnknownInt(str);
|
||||
}
|
||||
str = el.getAttributeValue("labels");
|
||||
if (str != null) {
|
||||
numlabels = XmlUtils.decodeUnknownInt(str);
|
||||
}
|
||||
str = el.getAttributeValue("section");
|
||||
if (str != null) {
|
||||
sectionid = XmlUtils.decodeUnknownInt(str);
|
||||
}
|
||||
List<?> list = el.getChildren();
|
||||
Iterator<?> it = list.iterator();
|
||||
Element child = (Element) it.next();
|
||||
if (child.getName().equals("null")) {
|
||||
result = null;
|
||||
}
|
||||
else {
|
||||
result = new HandleTpl();
|
||||
result.restoreXml(child, trans);
|
||||
}
|
||||
while (it.hasNext()) {
|
||||
child = (Element) it.next();
|
||||
OpTpl op = new OpTpl(null);
|
||||
op.restoreXml(child, trans);
|
||||
vec.push_back(op);
|
||||
}
|
||||
return sectionid;
|
||||
encoder.closeElement(ELEM_CONSTRUCT_TPL);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,14 +15,13 @@
|
|||
*/
|
||||
package ghidra.pcodeCPort.semantics;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.util.List;
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import org.jdom.Element;
|
||||
import java.io.IOException;
|
||||
|
||||
import generic.stl.VectorSTL;
|
||||
import ghidra.pcodeCPort.space.AddrSpace;
|
||||
import ghidra.pcodeCPort.translate.Translate;
|
||||
import ghidra.program.model.pcode.Encoder;
|
||||
|
||||
public class HandleTpl {
|
||||
|
||||
|
@ -120,27 +119,16 @@ public class HandleTpl {
|
|||
temp_offset.changeHandleIndex(handmap);
|
||||
}
|
||||
|
||||
public void saveXml(PrintStream s) {
|
||||
s.append("<handle_tpl>");
|
||||
space.saveXml(s);
|
||||
size.saveXml(s);
|
||||
ptrspace.saveXml(s);
|
||||
ptroffset.saveXml(s);
|
||||
ptrsize.saveXml(s);
|
||||
temp_space.saveXml(s);
|
||||
temp_offset.saveXml(s);
|
||||
s.append("</handle_tpl>\n");
|
||||
}
|
||||
|
||||
public void restoreXml(Element el, Translate trans) {
|
||||
List<?> list = el.getChildren();
|
||||
space.restoreXml((Element) list.get(0), trans);
|
||||
size.restoreXml((Element) list.get(1), trans);
|
||||
ptrspace.restoreXml((Element) list.get(2), trans);
|
||||
ptroffset.restoreXml((Element) list.get(3), trans);
|
||||
ptrsize.restoreXml((Element) list.get(4), trans);
|
||||
temp_space.restoreXml((Element) list.get(5), trans);
|
||||
temp_offset.restoreXml((Element) list.get(6), trans);
|
||||
public void encode(Encoder encoder) throws IOException {
|
||||
encoder.openElement(ELEM_HANDLE_TPL);
|
||||
space.encode(encoder);
|
||||
size.encode(encoder);
|
||||
ptrspace.encode(encoder);
|
||||
ptroffset.encode(encoder);
|
||||
ptrsize.encode(encoder);
|
||||
temp_space.encode(encoder);
|
||||
temp_offset.encode(encoder);
|
||||
encoder.closeElement(ELEM_HANDLE_TPL);
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -16,32 +15,29 @@
|
|||
*/
|
||||
package ghidra.pcodeCPort.semantics;
|
||||
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import generic.stl.IteratorSTL;
|
||||
import generic.stl.VectorSTL;
|
||||
import ghidra.pcodeCPort.opcodes.*;
|
||||
import ghidra.pcodeCPort.translate.*;
|
||||
import ghidra.sleigh.grammar.*;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
|
||||
import org.jdom.*;
|
||||
|
||||
import ghidra.pcodeCPort.opcodes.OpCode;
|
||||
import ghidra.program.model.pcode.Encoder;
|
||||
import ghidra.sleigh.grammar.Location;
|
||||
|
||||
public class OpTpl {
|
||||
public final Location location;
|
||||
public final Location location;
|
||||
|
||||
private VarnodeTpl output;
|
||||
private OpCode opc;
|
||||
private VectorSTL<VarnodeTpl> input = new VectorSTL<VarnodeTpl>();
|
||||
|
||||
public OpTpl(Location location) {
|
||||
this.location = location;
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
public OpTpl( Location location, OpCode oc ) {
|
||||
this.location = location;
|
||||
public OpTpl(Location location, OpCode oc) {
|
||||
this.location = location;
|
||||
opc = oc;
|
||||
output = null;
|
||||
}
|
||||
|
@ -50,7 +46,7 @@ public class OpTpl {
|
|||
public String toString() {
|
||||
return "OpTpl[opcode=" + opc + "]";
|
||||
}
|
||||
|
||||
|
||||
public VarnodeTpl getOut() {
|
||||
return output;
|
||||
}
|
||||
|
@ -59,19 +55,19 @@ public class OpTpl {
|
|||
return input.size();
|
||||
}
|
||||
|
||||
public VarnodeTpl getIn( int i ) {
|
||||
return input.get( i );
|
||||
public VarnodeTpl getIn(int i) {
|
||||
return input.get(i);
|
||||
}
|
||||
|
||||
public OpCode getOpcode() {
|
||||
return opc;
|
||||
}
|
||||
|
||||
public void setOpcode( OpCode o ) {
|
||||
public void setOpcode(OpCode o) {
|
||||
opc = o;
|
||||
}
|
||||
|
||||
public void setOutput( VarnodeTpl vt ) {
|
||||
public void setOutput(VarnodeTpl vt) {
|
||||
output = vt;
|
||||
}
|
||||
|
||||
|
@ -80,82 +76,71 @@ public class OpTpl {
|
|||
output = null;
|
||||
}
|
||||
|
||||
public void addInput( VarnodeTpl vt ) {
|
||||
input.push_back( vt );
|
||||
public void addInput(VarnodeTpl vt) {
|
||||
input.push_back(vt);
|
||||
}
|
||||
|
||||
public void setInput( VarnodeTpl vt, int slot ) {
|
||||
input.set( slot, vt );
|
||||
public void setInput(VarnodeTpl vt, int slot) {
|
||||
input.set(slot, vt);
|
||||
}
|
||||
|
||||
// An OpTpl owns its varnode_tpls
|
||||
public void dispose() {
|
||||
if ( output != null ) {
|
||||
if (output != null) {
|
||||
output.dispose();
|
||||
}
|
||||
IteratorSTL<VarnodeTpl> iter;
|
||||
for ( iter = input.begin(); !iter.isEnd(); iter.increment() )
|
||||
for (iter = input.begin(); !iter.isEnd(); iter.increment()) {
|
||||
iter.get().dispose();
|
||||
}
|
||||
}
|
||||
|
||||
// Return if any input or output has zero size
|
||||
public boolean isZeroSize() {
|
||||
if ( output != null ) {
|
||||
if ( output.isZeroSize() )
|
||||
if (output != null) {
|
||||
if (output.isZeroSize()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
IteratorSTL<VarnodeTpl> iter;
|
||||
for ( iter = input.begin(); !iter.isEnd(); iter.increment() )
|
||||
if ( iter.get().isZeroSize() )
|
||||
for (iter = input.begin(); !iter.isEnd(); iter.increment()) {
|
||||
if (iter.get().isZeroSize()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Remove the indicated input
|
||||
public void removeInput( int index ) {
|
||||
input.get( index ).dispose();
|
||||
input.erase( index );
|
||||
public void removeInput(int index) {
|
||||
input.get(index).dispose();
|
||||
input.erase(index);
|
||||
}
|
||||
|
||||
public void changeHandleIndex( VectorSTL<Integer> handmap ) {
|
||||
if ( output != null ) {
|
||||
output.changeHandleIndex( handmap );
|
||||
public void changeHandleIndex(VectorSTL<Integer> handmap) {
|
||||
if (output != null) {
|
||||
output.changeHandleIndex(handmap);
|
||||
}
|
||||
IteratorSTL<VarnodeTpl> iter;
|
||||
for ( iter = input.begin(); !iter.isEnd(); iter.increment() )
|
||||
iter.get().changeHandleIndex( handmap );
|
||||
for (iter = input.begin(); !iter.isEnd(); iter.increment()) {
|
||||
iter.get().changeHandleIndex(handmap);
|
||||
}
|
||||
}
|
||||
|
||||
public void saveXml( PrintStream s ) {
|
||||
s.append( "<op_tpl code=\"" );
|
||||
s.append( OpCode.get_opname( opc ) );
|
||||
s.append( "\">" );
|
||||
if ( output == null )
|
||||
s.append( "<null/>\n" );
|
||||
else
|
||||
output.saveXml( s );
|
||||
for ( int i = 0; i < input.size(); ++i )
|
||||
input.get( i ).saveXml( s );
|
||||
s.append( "</op_tpl>\n" );
|
||||
}
|
||||
|
||||
public void restoreXml( Element el, Translate trans ) {
|
||||
opc = OpCode.get_opcode( el.getAttributeValue( "code" ) );
|
||||
List<?> list = el.getChildren();
|
||||
Iterator<?> iter = list.iterator();
|
||||
Element child = (Element) iter.next();
|
||||
if ( child.getName().equals( "null" ) )
|
||||
output = null;
|
||||
public void encode(Encoder encoder) throws IOException {
|
||||
encoder.openElement(ELEM_OP_TPL);
|
||||
encoder.writeOpcode(ATTRIB_CODE, opc.ordinal());
|
||||
if (output == null) {
|
||||
encoder.openElement(ELEM_NULL);
|
||||
encoder.closeElement(ELEM_NULL);
|
||||
}
|
||||
else {
|
||||
output = new VarnodeTpl(null);
|
||||
output.restoreXml( child, trans );
|
||||
output.encode(encoder);
|
||||
}
|
||||
while ( iter.hasNext() ) {
|
||||
child = (Element) iter.next();
|
||||
VarnodeTpl vn = new VarnodeTpl(null);
|
||||
vn.restoreXml( child, trans );
|
||||
input.push_back( vn );
|
||||
for (int i = 0; i < input.size(); ++i) {
|
||||
input.get(i).encode(encoder);
|
||||
}
|
||||
encoder.closeElement(ELEM_OP_TPL);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,16 +15,15 @@
|
|||
*/
|
||||
package ghidra.pcodeCPort.semantics;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.List;
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import org.jdom.Element;
|
||||
import java.io.IOException;
|
||||
|
||||
import generic.stl.VectorSTL;
|
||||
import ghidra.pcodeCPort.semantics.ConstTpl.const_type;
|
||||
import ghidra.pcodeCPort.semantics.ConstTpl.v_field;
|
||||
import ghidra.pcodeCPort.space.spacetype;
|
||||
import ghidra.pcodeCPort.translate.Translate;
|
||||
import ghidra.program.model.pcode.Encoder;
|
||||
import ghidra.sleigh.grammar.Location;
|
||||
|
||||
public class VarnodeTpl {
|
||||
|
@ -129,22 +128,25 @@ public class VarnodeTpl {
|
|||
|
||||
public int transfer(VectorSTL<HandleTpl> params) {
|
||||
boolean doesOffsetPlus = false;
|
||||
int handleIndex=0;
|
||||
int plus=0;
|
||||
|
||||
if ((offset.getType()==const_type.handle)&&(offset.getSelect()==v_field.v_offset_plus)) {
|
||||
int handleIndex = 0;
|
||||
int plus = 0;
|
||||
|
||||
if ((offset.getType() == const_type.handle) &&
|
||||
(offset.getSelect() == v_field.v_offset_plus)) {
|
||||
handleIndex = offset.getHandleIndex();
|
||||
plus = (int)offset.getReal();
|
||||
plus = (int) offset.getReal();
|
||||
doesOffsetPlus = true;
|
||||
}
|
||||
space.transfer(params);
|
||||
offset.transfer(params);
|
||||
size.transfer(params);
|
||||
if (doesOffsetPlus) {
|
||||
if (isLocalTemp())
|
||||
if (isLocalTemp()) {
|
||||
return plus; // A positive number indicates truncation of a local temp
|
||||
if (params.get(handleIndex).getSize().isZero())
|
||||
}
|
||||
if (params.get(handleIndex).getSize().isZero()) {
|
||||
return plus; // or a zerosize object
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
@ -155,60 +157,40 @@ public class VarnodeTpl {
|
|||
size.changeHandleIndex(handmap);
|
||||
}
|
||||
|
||||
public boolean adjustTruncation(int sz,boolean isbigendian) {
|
||||
public boolean adjustTruncation(int sz, boolean isbigendian) {
|
||||
// We know this.offset is an v_field.offset_plus, check that the truncation is in bounds (given -sz-)
|
||||
// adjust plus for endianness if necessary
|
||||
// return true if truncation is in bounds
|
||||
if (size.getType() != const_type.real)
|
||||
if (size.getType() != const_type.real) {
|
||||
return false;
|
||||
int numbytes = (int)size.getReal();
|
||||
}
|
||||
int numbytes = (int) size.getReal();
|
||||
int byteoffset = (int) offset.getReal();
|
||||
if (numbytes + byteoffset > sz) return false;
|
||||
|
||||
if (numbytes + byteoffset > sz) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Encode the original truncation amount with the plus value
|
||||
long val = byteoffset;
|
||||
val <<= 16;
|
||||
if (isbigendian)
|
||||
if (isbigendian) {
|
||||
val |= (sz - (numbytes + byteoffset));
|
||||
else
|
||||
}
|
||||
else {
|
||||
val |= byteoffset;
|
||||
|
||||
offset = new ConstTpl(const_type.handle,offset.getHandleIndex(),v_field.v_offset_plus,val);
|
||||
}
|
||||
|
||||
offset =
|
||||
new ConstTpl(const_type.handle, offset.getHandleIndex(), v_field.v_offset_plus, val);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void saveXml(PrintStream s) {
|
||||
s.append("<varnode_tpl>");
|
||||
// s.append( "<varnode_tpl id=\"" + id + "\">" );
|
||||
space.saveXml(s);
|
||||
offset.saveXml(s);
|
||||
size.saveXml(s);
|
||||
s.append("</varnode_tpl>\n");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
PrintStream ps = new PrintStream(baos, true);
|
||||
saveXml(ps);
|
||||
ps.flush();
|
||||
String result = baos.toString();
|
||||
ps.close();
|
||||
try {
|
||||
baos.close();
|
||||
}
|
||||
catch (IOException e) {
|
||||
// whatever
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public void restoreXml(Element el, Translate trans) {
|
||||
List<?> list = el.getChildren();
|
||||
|
||||
space.restoreXml((Element) list.get(0), trans);
|
||||
offset.restoreXml((Element) list.get(1), trans);
|
||||
size.restoreXml((Element) list.get(2), trans);
|
||||
public void encode(Encoder encoder) throws IOException {
|
||||
encoder.openElement(ELEM_VARNODE_TPL);
|
||||
space.encode(encoder);
|
||||
offset.encode(encoder);
|
||||
size.encode(encoder);
|
||||
encoder.closeElement(ELEM_VARNODE_TPL);
|
||||
}
|
||||
|
||||
public int compareTo(VarnodeTpl op2) {
|
||||
|
|
|
@ -15,7 +15,9 @@
|
|||
*/
|
||||
package ghidra.pcodeCPort.sleighbase;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import generic.stl.*;
|
||||
|
@ -26,20 +28,15 @@ import ghidra.pcodeCPort.slghsymbol.*;
|
|||
import ghidra.pcodeCPort.space.AddrSpace;
|
||||
import ghidra.pcodeCPort.space.spacetype;
|
||||
import ghidra.pcodeCPort.translate.Translate;
|
||||
import ghidra.pcodeCPort.utils.XmlUtils;
|
||||
import ghidra.program.model.pcode.Encoder;
|
||||
import ghidra.sleigh.grammar.SourceFileIndexer;
|
||||
|
||||
public abstract class SleighBase extends Translate implements NamedSymbolProvider {
|
||||
|
||||
// NOTE: restoreXml method removed as it is only used by the decompiler's
|
||||
// implementation
|
||||
|
||||
/**
|
||||
* Note: The values of {@link #SLA_FORMAT_VERSION} and {@link #MAX_UNIQUE_SIZE}
|
||||
* must match the corresponding values defined by sleighbase.cc
|
||||
* Note: The value of {@link #MAX_UNIQUE_SIZE} must match the corresponding value
|
||||
* defined by sleighbase.cc
|
||||
*/
|
||||
public static final int SLA_FORMAT_VERSION = 3;
|
||||
|
||||
public static final long MAX_UNIQUE_SIZE = 128; //Maximum size of a varnode in the unique space.
|
||||
//Should match value in sleighbase.cc
|
||||
|
||||
|
@ -181,37 +178,35 @@ public abstract class SleighBase extends Translate implements NamedSymbolProvide
|
|||
}
|
||||
}
|
||||
|
||||
public void saveXml(PrintStream s) {
|
||||
s.append("<sleigh");
|
||||
XmlUtils.a_v_i(s, "version", SLA_FORMAT_VERSION);
|
||||
XmlUtils.a_v_b(s, "bigendian", isBigEndian());
|
||||
XmlUtils.a_v_i(s, "align", alignment);
|
||||
XmlUtils.a_v_u(s, "uniqbase", getUniqueBase());
|
||||
public void encode(Encoder encoder) throws IOException {
|
||||
encoder.openElement(ELEM_SLEIGH);
|
||||
encoder.writeSignedInteger(ATTRIB_VERSION, FORMAT_VERSION);
|
||||
encoder.writeBool(ATTRIB_BIGENDIAN, isBigEndian());
|
||||
encoder.writeSignedInteger(ATTRIB_ALIGN, alignment);
|
||||
encoder.writeUnsignedInteger(ATTRIB_UNIQBASE, getUniqueBase());
|
||||
if (maxdelayslotbytes > 0) {
|
||||
XmlUtils.a_v_u(s, "maxdelay", maxdelayslotbytes);
|
||||
encoder.writeUnsignedInteger(ATTRIB_MAXDELAY, maxdelayslotbytes);
|
||||
}
|
||||
if (unique_allocatemask != 0) {
|
||||
XmlUtils.a_v_u(s, "uniqmask", unique_allocatemask);
|
||||
encoder.writeUnsignedInteger(ATTRIB_UNIQMASK, unique_allocatemask);
|
||||
}
|
||||
if (numSections != 0) {
|
||||
XmlUtils.a_v_u(s, "numsections", numSections);
|
||||
encoder.writeUnsignedInteger(ATTRIB_NUMSECTIONS, numSections);
|
||||
}
|
||||
s.append(">\n");
|
||||
indexer.saveXml(s);
|
||||
s.append("<spaces");
|
||||
XmlUtils.a_v(s, "defaultspace", getDefaultSpace().getName());
|
||||
s.append(">\n");
|
||||
indexer.encode(encoder);
|
||||
encoder.openElement(ELEM_SPACES);
|
||||
encoder.writeString(ATTRIB_DEFAULTSPACE, getDefaultSpace().getName());
|
||||
for (int i = 0; i < numSpaces(); ++i) {
|
||||
AddrSpace spc = getSpace(i);
|
||||
if ((spc.getType() == spacetype.IPTR_CONSTANT) ||
|
||||
(spc.getType() == spacetype.IPTR_FSPEC) || (spc.getType() == spacetype.IPTR_IOP)) {
|
||||
continue;
|
||||
}
|
||||
spc.saveXml(s);
|
||||
spc.encode(encoder);
|
||||
}
|
||||
s.append("</spaces>\n");
|
||||
symtab.saveXml(s);
|
||||
s.append("</sleigh>\n");
|
||||
encoder.closeElement(ELEM_SPACES);
|
||||
symtab.encode(encoder);
|
||||
encoder.closeElement(ELEM_SLEIGH);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -22,10 +22,11 @@ import java.util.stream.Collectors;
|
|||
|
||||
import org.antlr.runtime.*;
|
||||
import org.antlr.runtime.tree.CommonTreeNodeStream;
|
||||
import org.jdom.JDOMException;
|
||||
|
||||
import generic.jar.ResourceFile;
|
||||
import generic.stl.*;
|
||||
import ghidra.pcode.utils.MessageFormattingUtils;
|
||||
import ghidra.pcode.utils.SlaFormat;
|
||||
import ghidra.pcodeCPort.address.Address;
|
||||
import ghidra.pcodeCPort.context.SleighError;
|
||||
import ghidra.pcodeCPort.error.LowlevelError;
|
||||
|
@ -36,8 +37,9 @@ import ghidra.pcodeCPort.slghpatexpress.*;
|
|||
import ghidra.pcodeCPort.slghsymbol.*;
|
||||
import ghidra.pcodeCPort.space.*;
|
||||
import ghidra.pcodeCPort.utils.Utils;
|
||||
import ghidra.pcodeCPort.xml.DocumentStorage;
|
||||
import ghidra.program.model.lang.SpaceNames;
|
||||
import ghidra.program.model.pcode.PackedEncode;
|
||||
import ghidra.program.model.pcode.XmlEncode;
|
||||
import ghidra.sleigh.grammar.*;
|
||||
import ghidra.util.Msg;
|
||||
import utilities.util.FileResolutionResult;
|
||||
|
@ -255,6 +257,7 @@ public class SleighCompile extends SleighBase {
|
|||
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 boolean debugoutput; // True if output .sla is written in XML debug format
|
||||
private VectorSTL<String> noplist = new VectorSTL<>();
|
||||
|
||||
private Deque<WithBlock> withstack = new LinkedList<>();
|
||||
|
@ -702,6 +705,7 @@ public class SleighCompile extends SleighBase {
|
|||
largetemporarywarning = false;
|
||||
warnallnops = false;
|
||||
failinsensitivedups = true;
|
||||
debugoutput = false;
|
||||
root = null;
|
||||
pcode.resetLabelCount();
|
||||
}
|
||||
|
@ -800,6 +804,11 @@ public class SleighCompile extends SleighBase {
|
|||
failinsensitivedups = val;
|
||||
}
|
||||
|
||||
public void setDebugOutput(boolean val) {
|
||||
entry("setDebugOutput", val);
|
||||
debugoutput = val;
|
||||
}
|
||||
|
||||
// Do all post processing on the parsed data structures
|
||||
private void process() {
|
||||
entry("process");
|
||||
|
@ -1759,12 +1768,6 @@ public class SleighCompile extends SleighBase {
|
|||
macrotable.push_back(rtl);
|
||||
}
|
||||
|
||||
// Virtual functions (not used by the compiler)
|
||||
@Override
|
||||
public void initialize(DocumentStorage store) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public int instructionLength(Address baseaddr) {
|
||||
return 0;
|
||||
|
@ -1778,7 +1781,8 @@ public class SleighCompile extends SleighBase {
|
|||
public void setAllOptions(Map<String, String> preprocs, boolean unnecessaryPcodeWarning,
|
||||
boolean lenientConflict, boolean allCollisionWarning, boolean allNopWarning,
|
||||
boolean deadTempWarning, boolean unusedFieldWarning, boolean enforceLocalKeyWord,
|
||||
boolean largeTemporaryWarning, boolean caseSensitiveRegisterNames) {
|
||||
boolean largeTemporaryWarning, boolean caseSensitiveRegisterNames,
|
||||
boolean debugOutput) {
|
||||
Set<Entry<String, String>> entrySet = preprocs.entrySet();
|
||||
for (Entry<String, String> entry : entrySet) {
|
||||
setPreprocValue(entry.getKey(), entry.getValue());
|
||||
|
@ -1792,6 +1796,7 @@ public class SleighCompile extends SleighBase {
|
|||
setEnforceLocalKeyWord(enforceLocalKeyWord);
|
||||
setLargeTemporaryWarning(largeTemporaryWarning);
|
||||
setInsensitiveDuplicateError(!caseSensitiveRegisterNames);
|
||||
setDebugOutput(debugOutput);
|
||||
}
|
||||
|
||||
public int run_compilation(String filein, String fileout)
|
||||
|
@ -1837,9 +1842,21 @@ public class SleighCompile extends SleighBase {
|
|||
}
|
||||
if ((parseres == 0) && (numErrors() == 0)) {
|
||||
// If no errors
|
||||
PrintStream s = new PrintStream(new FileOutputStream(new File(fileout)));
|
||||
saveXml(s); // Dump output xml
|
||||
s.close();
|
||||
ResourceFile resourceFile = new ResourceFile(fileout);
|
||||
if (debugoutput) {
|
||||
// If the debug output format was requested, use XML encoder
|
||||
XmlEncode encoder = new XmlEncode();
|
||||
encode(encoder);
|
||||
OutputStream stream = resourceFile.getOutputStream();
|
||||
encoder.writeTo(stream);
|
||||
stream.close();
|
||||
}
|
||||
else {
|
||||
// Use the standard .sla format encoder
|
||||
PackedEncode encoder = SlaFormat.buildEncoder(resourceFile);
|
||||
encode(encoder); // Dump compiler output
|
||||
encoder.getOutputStream().close();
|
||||
}
|
||||
}
|
||||
else {
|
||||
Msg.error(SleighCompile.class, "No output produced");
|
||||
|
@ -1867,11 +1884,10 @@ public class SleighCompile extends SleighBase {
|
|||
* compiler without using the launcher. The full SoftwareModeling classpath
|
||||
* must be established including any dependencies.
|
||||
* @param args compiler command line arguments
|
||||
* @throws JDOMException for XML errors
|
||||
* @throws IOException for file access errors
|
||||
* @throws RecognitionException for parsing errors
|
||||
*/
|
||||
public static void main(String[] args) throws JDOMException, IOException, RecognitionException {
|
||||
public static void main(String[] args) throws IOException, RecognitionException {
|
||||
System.exit(SleighCompileLauncher.runMain(args));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,12 +55,10 @@ public class SleighCompileLauncher implements GhidraLaunchable {
|
|||
*
|
||||
* @param args sleigh compiler command line arguments
|
||||
* @return exit code (TODO: exit codes are not well defined)
|
||||
* @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 {
|
||||
public static int runMain(String[] args) throws IOException, RecognitionException {
|
||||
int retval;
|
||||
String filein = null;
|
||||
String fileout = null;
|
||||
|
@ -80,6 +78,7 @@ public class SleighCompileLauncher implements GhidraLaunchable {
|
|||
Msg.info(SleighCompile.class, " <directory-path> directory to have all slaspec files compiled");
|
||||
Msg.info(SleighCompile.class, " options:");
|
||||
Msg.info(SleighCompile.class, " -x turns on parser debugging");
|
||||
Msg.info(SleighCompile.class, " -y write .sla using XML debug format");
|
||||
Msg.info(SleighCompile.class, " -u print warnings for unnecessary pcode instructions");
|
||||
Msg.info(SleighCompile.class, " -l report pattern conflicts");
|
||||
Msg.info(SleighCompile.class, " -n print warnings for all NOP constructors");
|
||||
|
@ -105,6 +104,7 @@ public class SleighCompileLauncher implements GhidraLaunchable {
|
|||
boolean unusedFieldWarning = false;
|
||||
boolean largeTemporaryWarning = false;
|
||||
boolean caseSensitiveRegisterNames = false;
|
||||
boolean debugOutput = false;
|
||||
|
||||
int i;
|
||||
for (i = 0; i < args.length; ++i) {
|
||||
|
@ -171,6 +171,9 @@ public class SleighCompileLauncher implements GhidraLaunchable {
|
|||
else if (args[i].charAt(1) == 's') {
|
||||
caseSensitiveRegisterNames = true;
|
||||
}
|
||||
else if (args[i].charAt(1) == 'y') {
|
||||
debugOutput = true;
|
||||
}
|
||||
else if (args[i].charAt(1) == 'x') {
|
||||
SleighCompile.yydebug = true; // Debug option
|
||||
}
|
||||
|
@ -205,7 +208,8 @@ public class SleighCompileLauncher implements GhidraLaunchable {
|
|||
SleighCompile compiler = new SleighCompile();
|
||||
compiler.setAllOptions(preprocs, unnecessaryPcodeWarning, lenientConflict,
|
||||
allCollisionWarning, allNopWarning, deadTempWarning, unusedFieldWarning,
|
||||
enforceLocalKeyWord, largeTemporaryWarning, caseSensitiveRegisterNames);
|
||||
enforceLocalKeyWord, largeTemporaryWarning, caseSensitiveRegisterNames,
|
||||
debugOutput);
|
||||
|
||||
String outname = input.getName().replace(".slaspec", ".sla");
|
||||
File output = new File(input.getParent(), outname);
|
||||
|
@ -234,7 +238,7 @@ public class SleighCompileLauncher implements GhidraLaunchable {
|
|||
SleighCompile compiler = new SleighCompile();
|
||||
compiler.setAllOptions(preprocs, unnecessaryPcodeWarning, lenientConflict,
|
||||
allCollisionWarning, allNopWarning, deadTempWarning, unusedFieldWarning,
|
||||
enforceLocalKeyWord, largeTemporaryWarning, caseSensitiveRegisterNames);
|
||||
enforceLocalKeyWord, largeTemporaryWarning, caseSensitiveRegisterNames, debugOutput);
|
||||
if (i == args.length) {
|
||||
Msg.error(SleighCompile.class, "Missing input file name");
|
||||
return 1;
|
||||
|
|
|
@ -15,10 +15,13 @@
|
|||
*/
|
||||
package ghidra.pcodeCPort.slghpatexpress;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import generic.stl.VectorSTL;
|
||||
import ghidra.pcodeCPort.utils.MutableInt;
|
||||
import ghidra.program.model.pcode.Encoder;
|
||||
import ghidra.sleigh.grammar.Location;
|
||||
|
||||
public class AndExpression extends BinaryExpression {
|
||||
|
@ -39,10 +42,10 @@ public class AndExpression extends BinaryExpression {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void saveXml(PrintStream s) {
|
||||
s.append("<and_exp>\n");
|
||||
super.saveXml(s);
|
||||
s.append("</and_exp>\n");
|
||||
public void encode(Encoder encoder) throws IOException {
|
||||
encoder.openElement(ELEM_AND_EXP);
|
||||
super.encode(encoder);
|
||||
encoder.closeElement(ELEM_AND_EXP);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -16,26 +15,22 @@
|
|||
*/
|
||||
package ghidra.pcodeCPort.slghpatexpress;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import generic.stl.VectorSTL;
|
||||
import ghidra.pcodeCPort.translate.*;
|
||||
import ghidra.program.model.pcode.Encoder;
|
||||
import ghidra.sleigh.grammar.Location;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.util.List;
|
||||
|
||||
import org.jdom.Element;
|
||||
|
||||
|
||||
public abstract class BinaryExpression extends PatternExpression {
|
||||
|
||||
private PatternExpression left;
|
||||
private PatternExpression right;
|
||||
|
||||
public BinaryExpression(Location location) {
|
||||
super(location);
|
||||
super(location);
|
||||
left = null;
|
||||
right = null;
|
||||
} // For use with restoreXml
|
||||
}
|
||||
|
||||
public PatternExpression getLeft() {
|
||||
return left;
|
||||
|
@ -46,52 +41,44 @@ public abstract class BinaryExpression extends PatternExpression {
|
|||
}
|
||||
|
||||
@Override
|
||||
public TokenPattern genMinPattern( VectorSTL<TokenPattern> ops ) {
|
||||
public TokenPattern genMinPattern(VectorSTL<TokenPattern> ops) {
|
||||
return new TokenPattern(location);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void listValues( VectorSTL<PatternValue> list ) {
|
||||
left.listValues( list );
|
||||
right.listValues( list );
|
||||
public void listValues(VectorSTL<PatternValue> list) {
|
||||
left.listValues(list);
|
||||
right.listValues(list);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getMinMax( VectorSTL<Long> minlist, VectorSTL<Long> maxlist ) {
|
||||
left.getMinMax( minlist, maxlist );
|
||||
right.getMinMax( minlist, maxlist );
|
||||
public void getMinMax(VectorSTL<Long> minlist, VectorSTL<Long> maxlist) {
|
||||
left.getMinMax(minlist, maxlist);
|
||||
right.getMinMax(minlist, maxlist);
|
||||
}
|
||||
|
||||
public BinaryExpression( Location location, PatternExpression l, PatternExpression r ) {
|
||||
super(location);
|
||||
public BinaryExpression(Location location, PatternExpression l, PatternExpression r) {
|
||||
super(location);
|
||||
(left = l).layClaim();
|
||||
(right = r).layClaim();
|
||||
}
|
||||
|
||||
// Delete only non-pattern values
|
||||
@Override
|
||||
public void dispose() {
|
||||
if ( left != null )
|
||||
PatternExpression.release( left );
|
||||
if ( right != null )
|
||||
PatternExpression.release( right );
|
||||
public void dispose() {
|
||||
if (left != null) {
|
||||
PatternExpression.release(left);
|
||||
}
|
||||
if (right != null) {
|
||||
PatternExpression.release(right);
|
||||
}
|
||||
}
|
||||
|
||||
// Outer tag is generated by derived classes
|
||||
@Override
|
||||
public void saveXml( PrintStream s ) {
|
||||
left.saveXml( s );
|
||||
right.saveXml( s );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreXml( Element el, Translate trans ) {
|
||||
List<?> list = el.getChildren();
|
||||
|
||||
left = PatternExpression.restoreExpression( (Element) list.get( 0 ), trans );
|
||||
right = PatternExpression.restoreExpression( (Element) list.get( 1 ), trans );
|
||||
left.layClaim();
|
||||
right.layClaim();
|
||||
public void encode(Encoder encoder) throws IOException {
|
||||
left.encode(encoder);
|
||||
right.encode(encoder);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,13 +15,12 @@
|
|||
*/
|
||||
package ghidra.pcodeCPort.slghpatexpress;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import org.jdom.Element;
|
||||
import java.io.IOException;
|
||||
|
||||
import generic.stl.VectorSTL;
|
||||
import ghidra.pcodeCPort.translate.Translate;
|
||||
import ghidra.pcodeCPort.utils.XmlUtils;
|
||||
import ghidra.program.model.pcode.Encoder;
|
||||
import ghidra.sleigh.grammar.Location;
|
||||
|
||||
public class ConstantValue extends PatternValue {
|
||||
|
@ -30,7 +29,7 @@ public class ConstantValue extends PatternValue {
|
|||
|
||||
public ConstantValue(Location location) {
|
||||
super(location);
|
||||
} // For use with restoreXml
|
||||
}
|
||||
|
||||
public ConstantValue(Location location, long v) {
|
||||
super(location);
|
||||
|
@ -58,15 +57,10 @@ public class ConstantValue extends PatternValue {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void saveXml(PrintStream s) {
|
||||
s.append("<intb val=\"");
|
||||
s.print(val);
|
||||
s.append("\"/>\n");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreXml(Element el, Translate trans) {
|
||||
val = XmlUtils.decodeUnknownLong(el.getAttributeValue("val"));
|
||||
public void encode(Encoder encoder) throws IOException {
|
||||
encoder.openElement(ELEM_INTB);
|
||||
encoder.writeSignedInteger(ATTRIB_VAL, val);
|
||||
encoder.closeElement(ELEM_INTB);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,14 +15,13 @@
|
|||
*/
|
||||
package ghidra.pcodeCPort.slghpatexpress;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import org.jdom.Element;
|
||||
import java.io.IOException;
|
||||
|
||||
import generic.stl.VectorSTL;
|
||||
import ghidra.pcodeCPort.translate.Translate;
|
||||
import ghidra.pcodeCPort.utils.Utils;
|
||||
import ghidra.pcodeCPort.utils.XmlUtils;
|
||||
import ghidra.program.model.pcode.Encoder;
|
||||
import ghidra.sleigh.grammar.Location;
|
||||
|
||||
public class ContextField extends PatternValue {
|
||||
|
@ -34,7 +33,7 @@ public class ContextField extends PatternValue {
|
|||
|
||||
public ContextField(Location location) {
|
||||
super(location);
|
||||
} // For use with restoreXml
|
||||
}
|
||||
|
||||
public int getStartBit() {
|
||||
return startbit;
|
||||
|
@ -90,37 +89,15 @@ public class ContextField extends PatternValue {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void saveXml(PrintStream s) {
|
||||
s.append("<contextfield");
|
||||
s.append(" signbit=\"");
|
||||
if (signbit) {
|
||||
s.append("true\"");
|
||||
}
|
||||
else {
|
||||
s.append("false\"");
|
||||
}
|
||||
s.append(" startbit=\"");
|
||||
s.print(startbit);
|
||||
s.append("\"");
|
||||
s.append(" endbit=\"");
|
||||
s.print(endbit);
|
||||
s.append("\"");
|
||||
s.append(" startbyte=\"").print(startbyte);
|
||||
s.append("\"");
|
||||
s.append(" endbyte=\"").print(endbyte);
|
||||
s.append("\"");
|
||||
s.append(" shift=\"").print(shift);
|
||||
s.append("\"/>\n");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreXml(Element el, Translate trans) {
|
||||
signbit = XmlUtils.decodeBoolean(el.getAttributeValue("signbit"));
|
||||
startbit = XmlUtils.decodeUnknownInt(el.getAttributeValue("startbit"));
|
||||
endbit = XmlUtils.decodeUnknownInt(el.getAttributeValue("endbit"));
|
||||
startbyte = XmlUtils.decodeUnknownInt(el.getAttributeValue("startbyte"));
|
||||
endbyte = XmlUtils.decodeUnknownInt(el.getAttributeValue("endbyte"));
|
||||
shift = XmlUtils.decodeUnknownInt(el.getAttributeValue("shift"));
|
||||
public void encode(Encoder encoder) throws IOException {
|
||||
encoder.openElement(ELEM_CONTEXTFIELD);
|
||||
encoder.writeBool(ATTRIB_SIGNBIT, signbit);
|
||||
encoder.writeSignedInteger(ATTRIB_STARTBIT, startbit);
|
||||
encoder.writeSignedInteger(ATTRIB_ENDBIT, endbit);
|
||||
encoder.writeSignedInteger(ATTRIB_STARTBYTE, startbyte);
|
||||
encoder.writeSignedInteger(ATTRIB_ENDBYTE, endbyte);
|
||||
encoder.writeSignedInteger(ATTRIB_SHIFT, shift);
|
||||
encoder.closeElement(ELEM_CONTEXTFIELD);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,10 +15,13 @@
|
|||
*/
|
||||
package ghidra.pcodeCPort.slghpatexpress;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import generic.stl.VectorSTL;
|
||||
import ghidra.pcodeCPort.utils.MutableInt;
|
||||
import ghidra.program.model.pcode.Encoder;
|
||||
import ghidra.sleigh.grammar.Location;
|
||||
|
||||
public class DivExpression extends BinaryExpression {
|
||||
|
@ -39,10 +42,10 @@ public class DivExpression extends BinaryExpression {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void saveXml(PrintStream s) {
|
||||
s.append("<div_exp>\n");
|
||||
super.saveXml(s);
|
||||
s.append("</div_exp>\n");
|
||||
public void encode(Encoder encoder) throws IOException {
|
||||
encoder.openElement(ELEM_DIV_EXP);
|
||||
super.encode(encoder);
|
||||
encoder.closeElement(ELEM_DIV_EXP);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,12 +15,12 @@
|
|||
*/
|
||||
package ghidra.pcodeCPort.slghpatexpress;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import org.jdom.Element;
|
||||
import java.io.IOException;
|
||||
|
||||
import generic.stl.VectorSTL;
|
||||
import ghidra.pcodeCPort.translate.Translate;
|
||||
import ghidra.program.model.pcode.Encoder;
|
||||
import ghidra.sleigh.grammar.Location;
|
||||
|
||||
public class EndInstructionValue extends PatternValue {
|
||||
|
@ -50,12 +50,9 @@ public class EndInstructionValue extends PatternValue {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void saveXml(PrintStream s) {
|
||||
s.append("<end_exp/>");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreXml(Element el, Translate trans) {
|
||||
public void encode(Encoder encoder) throws IOException {
|
||||
encoder.openElement(ELEM_END_EXP);
|
||||
encoder.closeElement(ELEM_END_EXP);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,10 +15,13 @@
|
|||
*/
|
||||
package ghidra.pcodeCPort.slghpatexpress;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import generic.stl.VectorSTL;
|
||||
import ghidra.pcodeCPort.utils.MutableInt;
|
||||
import ghidra.program.model.pcode.Encoder;
|
||||
import ghidra.sleigh.grammar.Location;
|
||||
|
||||
public class LeftShiftExpression extends BinaryExpression {
|
||||
|
@ -39,10 +42,10 @@ public class LeftShiftExpression extends BinaryExpression {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void saveXml(PrintStream s) {
|
||||
s.append("<lshift_exp>\n");
|
||||
super.saveXml(s);
|
||||
s.append("</lshift_exp>\n");
|
||||
public void encode(Encoder encoder) throws IOException {
|
||||
encoder.openElement(ELEM_LSHIFT_EXP);
|
||||
super.encode(encoder);
|
||||
encoder.closeElement(ELEM_LSHIFT_EXP);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,10 +15,13 @@
|
|||
*/
|
||||
package ghidra.pcodeCPort.slghpatexpress;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import generic.stl.VectorSTL;
|
||||
import ghidra.pcodeCPort.utils.MutableInt;
|
||||
import ghidra.program.model.pcode.Encoder;
|
||||
import ghidra.sleigh.grammar.Location;
|
||||
|
||||
public class MinusExpression extends UnaryExpression {
|
||||
|
@ -38,10 +41,10 @@ public class MinusExpression extends UnaryExpression {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void saveXml(PrintStream s) {
|
||||
s.append("<minus_exp>\n");
|
||||
super.saveXml(s);
|
||||
s.append("</minus_exp>\n");
|
||||
public void encode(Encoder encoder) throws IOException {
|
||||
encoder.openElement(ELEM_MINUS_EXP);
|
||||
super.encode(encoder);
|
||||
encoder.closeElement(ELEM_MINUS_EXP);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,17 +15,20 @@
|
|||
*/
|
||||
package ghidra.pcodeCPort.slghpatexpress;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import generic.stl.VectorSTL;
|
||||
import ghidra.pcodeCPort.utils.MutableInt;
|
||||
import ghidra.program.model.pcode.Encoder;
|
||||
import ghidra.sleigh.grammar.Location;
|
||||
|
||||
public class MultExpression extends BinaryExpression {
|
||||
|
||||
public MultExpression(Location location) {
|
||||
super(location);
|
||||
} // For use with restoreXml
|
||||
}
|
||||
|
||||
public MultExpression(Location location, PatternExpression l, PatternExpression r) {
|
||||
super(location, l, r);
|
||||
|
@ -39,10 +42,10 @@ public class MultExpression extends BinaryExpression {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void saveXml(PrintStream s) {
|
||||
s.append("<mult_exp>\n");
|
||||
super.saveXml(s);
|
||||
s.append("</mult_exp>\n");
|
||||
public void encode(Encoder encoder) throws IOException {
|
||||
encoder.openElement(ELEM_MULT_EXP);
|
||||
super.encode(encoder);
|
||||
encoder.closeElement(ELEM_MULT_EXP);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,12 +15,12 @@
|
|||
*/
|
||||
package ghidra.pcodeCPort.slghpatexpress;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import org.jdom.Element;
|
||||
import java.io.IOException;
|
||||
|
||||
import generic.stl.VectorSTL;
|
||||
import ghidra.pcodeCPort.translate.Translate;
|
||||
import ghidra.program.model.pcode.Encoder;
|
||||
import ghidra.sleigh.grammar.Location;
|
||||
|
||||
public class Next2InstructionValue extends PatternValue {
|
||||
|
@ -50,12 +50,9 @@ public class Next2InstructionValue extends PatternValue {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void saveXml(PrintStream s) {
|
||||
s.append("<next2_exp/>");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreXml(Element el, Translate trans) {
|
||||
public void encode(Encoder encoder) throws IOException {
|
||||
encoder.openElement(ELEM_NEXT2_EXP);
|
||||
encoder.closeElement(ELEM_NEXT2_EXP);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,10 +15,13 @@
|
|||
*/
|
||||
package ghidra.pcodeCPort.slghpatexpress;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import generic.stl.VectorSTL;
|
||||
import ghidra.pcodeCPort.utils.MutableInt;
|
||||
import ghidra.program.model.pcode.Encoder;
|
||||
import ghidra.sleigh.grammar.Location;
|
||||
|
||||
public class NotExpression extends UnaryExpression {
|
||||
|
@ -38,10 +41,10 @@ public class NotExpression extends UnaryExpression {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void saveXml(PrintStream s) {
|
||||
s.append("<not_exp>\n");
|
||||
super.saveXml(s);
|
||||
s.append("</not_exp>\n");
|
||||
public void encode(Encoder encoder) throws IOException {
|
||||
encoder.openElement(ELEM_NOT_EXP);
|
||||
super.encode(encoder);
|
||||
encoder.closeElement(ELEM_NOT_EXP);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,17 +15,16 @@
|
|||
*/
|
||||
package ghidra.pcodeCPort.slghpatexpress;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import org.jdom.Element;
|
||||
import java.io.IOException;
|
||||
|
||||
import generic.stl.VectorSTL;
|
||||
import ghidra.pcodeCPort.context.SleighError;
|
||||
import ghidra.pcodeCPort.sleighbase.SleighBase;
|
||||
import ghidra.pcodeCPort.slghsymbol.*;
|
||||
import ghidra.pcodeCPort.translate.Translate;
|
||||
import ghidra.pcodeCPort.slghsymbol.Constructor;
|
||||
import ghidra.pcodeCPort.slghsymbol.OperandSymbol;
|
||||
import ghidra.pcodeCPort.utils.MutableInt;
|
||||
import ghidra.pcodeCPort.utils.XmlUtils;
|
||||
import ghidra.program.model.pcode.Encoder;
|
||||
import ghidra.sleigh.grammar.Location;
|
||||
|
||||
public class OperandValue extends PatternValue {
|
||||
|
@ -35,7 +34,7 @@ public class OperandValue extends PatternValue {
|
|||
|
||||
public OperandValue(Location location) {
|
||||
super(location);
|
||||
} // For use with restoreXml
|
||||
}
|
||||
|
||||
public OperandValue(Location location, int ind, Constructor c) {
|
||||
super(location);
|
||||
|
@ -96,29 +95,14 @@ public class OperandValue extends PatternValue {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void saveXml(PrintStream s) {
|
||||
s.append("<operand_exp");
|
||||
s.append(" index=\"");
|
||||
s.print(index);
|
||||
s.append("\"");
|
||||
s.append(" table=\"0x");
|
||||
public void encode(Encoder encoder) throws IOException {
|
||||
encoder.openElement(ELEM_OPERAND_EXP);
|
||||
encoder.writeSignedInteger(ATTRIB_INDEX, index);
|
||||
int id = (ct == null ? 0 : ct.getParent().getId());
|
||||
s.append(Long.toHexString(id));
|
||||
s.append("\"");
|
||||
s.append(" ct=\"0x");
|
||||
encoder.writeUnsignedInteger(ATTRIB_TABLE, id);
|
||||
long ctid = (ct == null ? 0 : ct.getId());
|
||||
s.append(Long.toHexString(ctid));
|
||||
s.append("\"/>\n"); // Save id of our constructor
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreXml(Element el, Translate trans) {
|
||||
index = XmlUtils.decodeUnknownInt(el.getAttributeValue("index"));
|
||||
long tabid = XmlUtils.decodeUnknownLong(el.getAttributeValue("table"));
|
||||
long ctid = XmlUtils.decodeUnknownLong(el.getAttributeValue("ct"));
|
||||
SleighBase sleigh = (SleighBase) trans;
|
||||
SubtableSymbol tab = (SubtableSymbol) (sleigh.findSymbol((int) tabid));
|
||||
ct = tab.getConstructor((int) ctid);
|
||||
encoder.writeUnsignedInteger(ATTRIB_CT, ctid);
|
||||
encoder.closeElement(ELEM_OPERAND_EXP);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,10 +15,13 @@
|
|||
*/
|
||||
package ghidra.pcodeCPort.slghpatexpress;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import generic.stl.VectorSTL;
|
||||
import ghidra.pcodeCPort.utils.MutableInt;
|
||||
import ghidra.program.model.pcode.Encoder;
|
||||
import ghidra.sleigh.grammar.Location;
|
||||
|
||||
public class OrExpression extends BinaryExpression {
|
||||
|
@ -39,12 +42,12 @@ public class OrExpression extends BinaryExpression {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void saveXml(PrintStream s)
|
||||
public void encode(Encoder encoder) throws IOException
|
||||
|
||||
{
|
||||
s.append("<or_exp>\n");
|
||||
super.saveXml(s);
|
||||
s.append("</or_exp>\n");
|
||||
encoder.openElement(ELEM_OR_EXP);
|
||||
super.encode(encoder);
|
||||
encoder.closeElement(ELEM_OR_EXP);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,13 +15,11 @@
|
|||
*/
|
||||
package ghidra.pcodeCPort.slghpatexpress;
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
import org.jdom.Element;
|
||||
import java.io.IOException;
|
||||
|
||||
import generic.stl.VectorSTL;
|
||||
import ghidra.pcodeCPort.translate.Translate;
|
||||
import ghidra.pcodeCPort.utils.MutableInt;
|
||||
import ghidra.program.model.pcode.Encoder;
|
||||
import ghidra.sleigh.grammar.Location;
|
||||
|
||||
public abstract class PatternExpression {
|
||||
|
@ -45,9 +43,7 @@ public abstract class PatternExpression {
|
|||
|
||||
public abstract long getSubValue(VectorSTL<Long> replace, MutableInt listpos);
|
||||
|
||||
public abstract void saveXml(PrintStream s);
|
||||
|
||||
public abstract void restoreXml(Element el, Translate trans);
|
||||
public abstract void encode(Encoder encoder) throws IOException;
|
||||
|
||||
public long getSubValue(VectorSTL<Long> replace) {
|
||||
MutableInt listpos = new MutableInt(0);
|
||||
|
@ -65,70 +61,4 @@ public abstract class PatternExpression {
|
|||
}
|
||||
}
|
||||
|
||||
public static PatternExpression restoreExpression(Element el, Translate trans) {
|
||||
PatternExpression res;
|
||||
String nm = el.getName();
|
||||
|
||||
if (nm.equals("tokenfield")) {
|
||||
res = new TokenField(null);
|
||||
}
|
||||
else if (nm.equals("contextfield")) {
|
||||
res = new ContextField(null);
|
||||
}
|
||||
else if (nm.equals("intb")) {
|
||||
res = new ConstantValue(null);
|
||||
}
|
||||
else if (nm.equals("operand_exp")) {
|
||||
res = new OperandValue(null);
|
||||
}
|
||||
else if (nm.equals("start_exp")) {
|
||||
res = new StartInstructionValue(null);
|
||||
}
|
||||
else if (nm.equals("end_exp")) {
|
||||
res = new EndInstructionValue(null);
|
||||
}
|
||||
else if (nm.equals("next2_exp")) {
|
||||
res = new Next2InstructionValue(null);
|
||||
}
|
||||
else if (nm.equals("plus_exp")) {
|
||||
res = new PlusExpression(null);
|
||||
}
|
||||
else if (nm.equals("sub_exp")) {
|
||||
res = new SubExpression(null);
|
||||
}
|
||||
else if (nm.equals("mult_exp")) {
|
||||
res = new MultExpression(null);
|
||||
}
|
||||
else if (nm.equals("lshift_exp")) {
|
||||
res = new LeftShiftExpression(null);
|
||||
}
|
||||
else if (nm.equals("rshift_exp")) {
|
||||
res = new RightShiftExpression(null);
|
||||
}
|
||||
else if (nm.equals("and_exp")) {
|
||||
res = new AndExpression(null);
|
||||
}
|
||||
else if (nm.equals("or_exp")) {
|
||||
res = new OrExpression(null);
|
||||
}
|
||||
else if (nm.equals("xor_exp")) {
|
||||
res = new XorExpression(null);
|
||||
}
|
||||
else if (nm.equals("div_exp")) {
|
||||
res = new DivExpression(null);
|
||||
}
|
||||
else if (nm.equals("minus_exp")) {
|
||||
res = new MinusExpression(null);
|
||||
}
|
||||
else if (nm.equals("not_exp")) {
|
||||
res = new NotExpression(null);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
|
||||
res.restoreXml(el, trans);
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,17 +15,20 @@
|
|||
*/
|
||||
package ghidra.pcodeCPort.slghpatexpress;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import generic.stl.VectorSTL;
|
||||
import ghidra.pcodeCPort.utils.MutableInt;
|
||||
import ghidra.program.model.pcode.Encoder;
|
||||
import ghidra.sleigh.grammar.Location;
|
||||
|
||||
public class PlusExpression extends BinaryExpression {
|
||||
|
||||
public PlusExpression(Location location) {
|
||||
super(location);
|
||||
} // For use by restoreXml
|
||||
}
|
||||
|
||||
public PlusExpression(Location location, PatternExpression l, PatternExpression r) {
|
||||
super(location, l, r);
|
||||
|
@ -39,10 +42,10 @@ public class PlusExpression extends BinaryExpression {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void saveXml(PrintStream s) {
|
||||
s.append("<plus_exp>\n");
|
||||
super.saveXml(s);
|
||||
s.append("</plus_exp>\n");
|
||||
public void encode(Encoder encoder) throws IOException {
|
||||
encoder.openElement(ELEM_PLUS_EXP);
|
||||
super.encode(encoder);
|
||||
encoder.closeElement(ELEM_PLUS_EXP);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,10 +15,13 @@
|
|||
*/
|
||||
package ghidra.pcodeCPort.slghpatexpress;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import generic.stl.VectorSTL;
|
||||
import ghidra.pcodeCPort.utils.MutableInt;
|
||||
import ghidra.program.model.pcode.Encoder;
|
||||
import ghidra.sleigh.grammar.Location;
|
||||
|
||||
public class RightShiftExpression extends BinaryExpression {
|
||||
|
@ -39,10 +42,10 @@ public class RightShiftExpression extends BinaryExpression {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void saveXml(PrintStream s) {
|
||||
s.append("<rshift_exp>\n");
|
||||
super.saveXml(s);
|
||||
s.append("</rshift_exp>\n");
|
||||
public void encode(Encoder encoder) throws IOException {
|
||||
encoder.openElement(ELEM_RSHIFT_EXP);
|
||||
super.encode(encoder);
|
||||
encoder.closeElement(ELEM_RSHIFT_EXP);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,12 +15,12 @@
|
|||
*/
|
||||
package ghidra.pcodeCPort.slghpatexpress;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import org.jdom.Element;
|
||||
import java.io.IOException;
|
||||
|
||||
import generic.stl.VectorSTL;
|
||||
import ghidra.pcodeCPort.translate.Translate;
|
||||
import ghidra.program.model.pcode.Encoder;
|
||||
import ghidra.sleigh.grammar.Location;
|
||||
|
||||
public class StartInstructionValue extends PatternValue {
|
||||
|
@ -50,12 +50,9 @@ public class StartInstructionValue extends PatternValue {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void saveXml(PrintStream s) {
|
||||
s.append("<start_exp/>");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreXml(Element el, Translate trans) {
|
||||
public void encode(Encoder encoder) throws IOException {
|
||||
encoder.openElement(ELEM_START_EXP);
|
||||
encoder.closeElement(ELEM_START_EXP);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,17 +15,20 @@
|
|||
*/
|
||||
package ghidra.pcodeCPort.slghpatexpress;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import generic.stl.VectorSTL;
|
||||
import ghidra.pcodeCPort.utils.MutableInt;
|
||||
import ghidra.program.model.pcode.Encoder;
|
||||
import ghidra.sleigh.grammar.Location;
|
||||
|
||||
public class SubExpression extends BinaryExpression {
|
||||
|
||||
public SubExpression(Location location) {
|
||||
super(location);
|
||||
} // For use with restoreXml
|
||||
}
|
||||
|
||||
public SubExpression(Location location, PatternExpression l, PatternExpression r) {
|
||||
super(location, l, r);
|
||||
|
@ -39,10 +42,10 @@ public class SubExpression extends BinaryExpression {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void saveXml(PrintStream s) {
|
||||
s.append("<sub_exp>\n");
|
||||
super.saveXml(s);
|
||||
s.append("</sub_exp>\n");
|
||||
public void encode(Encoder encoder) throws IOException {
|
||||
encoder.openElement(ELEM_SUB_EXP);
|
||||
super.encode(encoder);
|
||||
encoder.closeElement(ELEM_SUB_EXP);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,15 +15,14 @@
|
|||
*/
|
||||
package ghidra.pcodeCPort.slghpatexpress;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import org.jdom.Element;
|
||||
import java.io.IOException;
|
||||
|
||||
import generic.stl.VectorSTL;
|
||||
import ghidra.pcodeCPort.context.Token;
|
||||
import ghidra.pcodeCPort.translate.Translate;
|
||||
import ghidra.pcodeCPort.utils.Utils;
|
||||
import ghidra.pcodeCPort.utils.XmlUtils;
|
||||
import ghidra.program.model.pcode.Encoder;
|
||||
import ghidra.sleigh.grammar.Location;
|
||||
|
||||
public class TokenField extends PatternValue {
|
||||
|
@ -37,7 +36,7 @@ public class TokenField extends PatternValue {
|
|||
|
||||
public TokenField(Location location) {
|
||||
super(location);
|
||||
} // For use with restoreXml
|
||||
}
|
||||
|
||||
@Override
|
||||
public TokenPattern genMinPattern(VectorSTL<TokenPattern> ops) {
|
||||
|
@ -82,44 +81,16 @@ public class TokenField extends PatternValue {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void saveXml(PrintStream s) {
|
||||
s.append("<tokenfield");
|
||||
s.append(" bigendian=\"");
|
||||
if (bigendian) {
|
||||
s.append("true\"");
|
||||
}
|
||||
else {
|
||||
s.append("false\"");
|
||||
}
|
||||
s.append(" signbit=\"");
|
||||
if (signbit) {
|
||||
s.append("true\"");
|
||||
}
|
||||
else {
|
||||
s.append("false\"");
|
||||
}
|
||||
s.append(" bitstart=\"").print(bitstart);
|
||||
s.append("\"");
|
||||
s.append(" bitend=\"").print(bitend);
|
||||
s.append("\"");
|
||||
s.append(" bytestart=\"").print(bytestart);
|
||||
s.append("\"");
|
||||
s.append(" byteend=\"").print(byteend);
|
||||
s.append("\"");
|
||||
s.append(" shift=\"").print(shift);
|
||||
s.append("\"/>\n");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreXml(Element el, Translate trans) {
|
||||
tok = null;
|
||||
bigendian = XmlUtils.decodeBoolean(el.getAttributeValue("bigendian"));
|
||||
signbit = XmlUtils.decodeBoolean(el.getAttributeValue("signbit"));
|
||||
bitstart = XmlUtils.decodeUnknownInt(el.getAttributeValue("bitstart"));
|
||||
bitend = XmlUtils.decodeUnknownInt(el.getAttributeValue("bitend"));
|
||||
bytestart = XmlUtils.decodeUnknownInt(el.getAttributeValue("bytestart"));
|
||||
byteend = XmlUtils.decodeUnknownInt(el.getAttributeValue("byteend"));
|
||||
shift = XmlUtils.decodeUnknownInt(el.getAttributeValue("shift"));
|
||||
public void encode(Encoder encoder) throws IOException {
|
||||
encoder.openElement(ELEM_TOKENFIELD);
|
||||
encoder.writeBool(ATTRIB_BIGENDIAN, bigendian);
|
||||
encoder.writeBool(ATTRIB_SIGNBIT, signbit);
|
||||
encoder.writeSignedInteger(ATTRIB_STARTBIT, bitstart);
|
||||
encoder.writeSignedInteger(ATTRIB_ENDBIT, bitend);
|
||||
encoder.writeSignedInteger(ATTRIB_STARTBYTE, bytestart);
|
||||
encoder.writeSignedInteger(ATTRIB_ENDBYTE, byteend);
|
||||
encoder.writeSignedInteger(ATTRIB_SHIFT, shift);
|
||||
encoder.closeElement(ELEM_TOKENFIELD);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -16,65 +15,55 @@
|
|||
*/
|
||||
package ghidra.pcodeCPort.slghpatexpress;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import generic.stl.VectorSTL;
|
||||
import ghidra.pcodeCPort.translate.*;
|
||||
import ghidra.program.model.pcode.Encoder;
|
||||
import ghidra.sleigh.grammar.Location;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.util.List;
|
||||
|
||||
import org.jdom.Element;
|
||||
|
||||
|
||||
public abstract class UnaryExpression extends PatternExpression {
|
||||
|
||||
private PatternExpression unary;
|
||||
|
||||
public UnaryExpression(Location location) {
|
||||
super(location);
|
||||
super(location);
|
||||
unary = null;
|
||||
} // For use with restoreXml
|
||||
}
|
||||
|
||||
public PatternExpression getUnary() {
|
||||
return unary;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TokenPattern genMinPattern( VectorSTL<TokenPattern> ops ) {
|
||||
public TokenPattern genMinPattern(VectorSTL<TokenPattern> ops) {
|
||||
return new TokenPattern(location);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void listValues( VectorSTL<PatternValue> list ) {
|
||||
unary.listValues( list );
|
||||
public void listValues(VectorSTL<PatternValue> list) {
|
||||
unary.listValues(list);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getMinMax( VectorSTL<Long> minlist, VectorSTL<Long> maxlist ) {
|
||||
unary.getMinMax( minlist, maxlist );
|
||||
public void getMinMax(VectorSTL<Long> minlist, VectorSTL<Long> maxlist) {
|
||||
unary.getMinMax(minlist, maxlist);
|
||||
}
|
||||
|
||||
public UnaryExpression( Location location, PatternExpression u ) {
|
||||
super(location);
|
||||
public UnaryExpression(Location location, PatternExpression u) {
|
||||
super(location);
|
||||
(unary = u).layClaim();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() { // Delete only non-pattern values
|
||||
if ( unary != null )
|
||||
PatternExpression.release( unary );
|
||||
public void dispose() { // Delete only non-pattern values
|
||||
if (unary != null) {
|
||||
PatternExpression.release(unary);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveXml( PrintStream s ) { // Outer tag is generated by derived classes
|
||||
unary.saveXml( s );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreXml( Element el, Translate trans ) {
|
||||
List<?> list = el.getChildren();
|
||||
unary = PatternExpression.restoreExpression( (Element) list.get( 0 ), trans );
|
||||
unary.layClaim();
|
||||
public void encode(Encoder encoder) throws IOException { // Outer tag is generated by derived classes
|
||||
unary.encode(encoder);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,10 +15,13 @@
|
|||
*/
|
||||
package ghidra.pcodeCPort.slghpatexpress;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import generic.stl.VectorSTL;
|
||||
import ghidra.pcodeCPort.utils.MutableInt;
|
||||
import ghidra.program.model.pcode.Encoder;
|
||||
import ghidra.sleigh.grammar.Location;
|
||||
|
||||
public class XorExpression extends BinaryExpression {
|
||||
|
@ -39,10 +42,10 @@ public class XorExpression extends BinaryExpression {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void saveXml(PrintStream s) {
|
||||
s.append("<xor_exp>\n");
|
||||
super.saveXml(s);
|
||||
s.append("</xor_exp>\n");
|
||||
public void encode(Encoder encoder) throws IOException {
|
||||
encoder.openElement(ELEM_XOR_EXP);
|
||||
super.encode(encoder);
|
||||
encoder.closeElement(ELEM_XOR_EXP);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,10 +15,11 @@
|
|||
*/
|
||||
package ghidra.pcodeCPort.slghpattern;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.util.List;
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import org.jdom.Element;
|
||||
import java.io.IOException;
|
||||
|
||||
import ghidra.program.model.pcode.Encoder;
|
||||
|
||||
public class CombinePattern extends DisjointPattern {
|
||||
|
||||
|
@ -162,22 +163,11 @@ public class CombinePattern extends DisjointPattern {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void saveXml(PrintStream s) {
|
||||
s.append("<combine_pat>\n");
|
||||
context.saveXml(s);
|
||||
instr.saveXml(s);
|
||||
s.append("</combine_pat>\n");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreXml(Element el) {
|
||||
List<?> list = el.getChildren();
|
||||
Element child = (Element) list.get(0);
|
||||
context = new ContextPattern();
|
||||
context.restoreXml(child);
|
||||
child = (Element) list.get(1);
|
||||
instr = new InstructionPattern();
|
||||
instr.restoreXml(child);
|
||||
public void encode(Encoder encoder) throws IOException {
|
||||
encoder.openElement(ELEM_COMBINE_PAT);
|
||||
context.encode(encoder);
|
||||
instr.encode(encoder);
|
||||
encoder.closeElement(ELEM_COMBINE_PAT);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,10 +15,11 @@
|
|||
*/
|
||||
package ghidra.pcodeCPort.slghpattern;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.util.List;
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import org.jdom.Element;
|
||||
import java.io.IOException;
|
||||
|
||||
import ghidra.program.model.pcode.Encoder;
|
||||
|
||||
public class ContextPattern extends DisjointPattern {
|
||||
|
||||
|
@ -31,7 +32,7 @@ public class ContextPattern extends DisjointPattern {
|
|||
|
||||
public ContextPattern() {
|
||||
maskvalue = null;
|
||||
} // For use with restoreXml
|
||||
}
|
||||
|
||||
public ContextPattern(PatternBlock mv) {
|
||||
maskvalue = mv;
|
||||
|
@ -104,18 +105,10 @@ public class ContextPattern extends DisjointPattern {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void saveXml(PrintStream s) {
|
||||
s.append("<context_pat>\n");
|
||||
maskvalue.saveXml(s);
|
||||
s.append("</context_pat>\n");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreXml(Element el) {
|
||||
List<?> list = el.getChildren();
|
||||
Element child = (Element) list.get(0);
|
||||
maskvalue = new PatternBlock(true);
|
||||
maskvalue.restoreXml(child);
|
||||
public void encode(Encoder encoder) throws IOException {
|
||||
encoder.openElement(ELEM_CONTEXT_PAT);
|
||||
maskvalue.encode(encoder);
|
||||
encoder.closeElement(ELEM_CONTEXT_PAT);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,8 +15,6 @@
|
|||
*/
|
||||
package ghidra.pcodeCPort.slghpattern;
|
||||
|
||||
import org.jdom.Element;
|
||||
|
||||
public abstract class DisjointPattern extends Pattern {
|
||||
|
||||
protected abstract PatternBlock getBlock(boolean context);
|
||||
|
@ -87,29 +85,35 @@ public abstract class DisjointPattern extends Pattern {
|
|||
PatternBlock b = op2.getBlock(false);
|
||||
if (b != null) { // a must match existing block
|
||||
if (a == null) {
|
||||
if (!b.alwaysTrue())
|
||||
if (!b.alwaysTrue()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (!a.identical(b))
|
||||
else if (!a.identical(b)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ((a != null) && (!a.alwaysTrue()))
|
||||
if ((a != null) && (!a.alwaysTrue())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
a = getBlock(true);
|
||||
b = op2.getBlock(true);
|
||||
if (b != null) { // a must match existing block
|
||||
if (a == null) {
|
||||
if (!b.alwaysTrue())
|
||||
if (!b.alwaysTrue()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (!a.identical(b))
|
||||
else if (!a.identical(b)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ((a != null) && (!a.alwaysTrue()))
|
||||
if ((a != null) && (!a.alwaysTrue())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -119,47 +123,37 @@ public abstract class DisjointPattern extends Pattern {
|
|||
PatternBlock inter;
|
||||
boolean res = true;
|
||||
|
||||
if (bl1 == null)
|
||||
if (bl1 == null) {
|
||||
inter = bl2;
|
||||
else if (bl2 == null)
|
||||
}
|
||||
else if (bl2 == null) {
|
||||
inter = bl1;
|
||||
}
|
||||
else {
|
||||
inter = bl1.intersect(bl2);
|
||||
}
|
||||
if (inter == null) {
|
||||
if (thisblock != null)
|
||||
if (thisblock != null) {
|
||||
res = false;
|
||||
}
|
||||
}
|
||||
else if (thisblock == null)
|
||||
else if (thisblock == null) {
|
||||
res = false;
|
||||
else
|
||||
}
|
||||
else {
|
||||
res = thisblock.identical(inter);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
public boolean resolvesIntersect(DisjointPattern op1, DisjointPattern op2) {
|
||||
// Is this pattern equal to the intersection of -op1- and -op2-
|
||||
if (!resolveIntersectBlock(op1.getBlock(false), op2.getBlock(false), getBlock(false)))
|
||||
if (!resolveIntersectBlock(op1.getBlock(false), op2.getBlock(false), getBlock(false))) {
|
||||
return false;
|
||||
}
|
||||
return resolveIntersectBlock(op1.getBlock(true), op2.getBlock(true), getBlock(true));
|
||||
}
|
||||
|
||||
// DisjointPattern factory
|
||||
public static DisjointPattern restoreDisjoint(Element el) {
|
||||
DisjointPattern res;
|
||||
if (el.getName().equals("instruct_pat")) {
|
||||
res = new InstructionPattern();
|
||||
}
|
||||
else if (el.getName().equals("context_pat")) {
|
||||
res = new ContextPattern();
|
||||
}
|
||||
else {
|
||||
res = new CombinePattern();
|
||||
}
|
||||
res.restoreXml(el);
|
||||
return res;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DisjointPattern{" + getBlock(true) + " : " + getBlock(false) + "}";
|
||||
|
|
|
@ -15,10 +15,11 @@
|
|||
*/
|
||||
package ghidra.pcodeCPort.slghpattern;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.util.List;
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import org.jdom.Element;
|
||||
import java.io.IOException;
|
||||
|
||||
import ghidra.program.model.pcode.Encoder;
|
||||
|
||||
public class InstructionPattern extends DisjointPattern {
|
||||
|
||||
|
@ -36,7 +37,7 @@ public class InstructionPattern extends DisjointPattern {
|
|||
|
||||
public InstructionPattern() {
|
||||
maskvalue = null;
|
||||
} // For use with restoreXml
|
||||
}
|
||||
|
||||
public InstructionPattern(PatternBlock mv) {
|
||||
maskvalue = mv;
|
||||
|
@ -169,18 +170,10 @@ public class InstructionPattern extends DisjointPattern {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void saveXml(PrintStream s) {
|
||||
s.append("<instruct_pat>\n");
|
||||
maskvalue.saveXml(s);
|
||||
s.append("</instruct_pat>\n");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreXml(Element el) {
|
||||
List<?> list = el.getChildren();
|
||||
Element child = (Element) list.get(0);
|
||||
maskvalue = new PatternBlock(true);
|
||||
maskvalue.restoreXml(child);
|
||||
public void encode(Encoder encoder) throws IOException {
|
||||
encoder.openElement(ELEM_INSTRUCT_PAT);
|
||||
maskvalue.encode(encoder);
|
||||
encoder.closeElement(ELEM_INSTRUCT_PAT);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,21 +15,20 @@
|
|||
*/
|
||||
package ghidra.pcodeCPort.slghpattern;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import org.jdom.Element;
|
||||
import java.io.IOException;
|
||||
|
||||
import generic.stl.IteratorSTL;
|
||||
import generic.stl.VectorSTL;
|
||||
import ghidra.program.model.pcode.Encoder;
|
||||
|
||||
public class OrPattern extends Pattern {
|
||||
|
||||
private VectorSTL<DisjointPattern> orlist = new VectorSTL<DisjointPattern>();
|
||||
|
||||
public OrPattern() {
|
||||
} // For use with restoreXml
|
||||
}
|
||||
|
||||
@Override
|
||||
public int numDisjoint() {
|
||||
|
@ -210,23 +209,11 @@ public class OrPattern extends Pattern {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void saveXml(PrintStream s) {
|
||||
s.append("<or_pat>\n");
|
||||
public void encode(Encoder encoder) throws IOException {
|
||||
encoder.openElement(ELEM_OR_PAT);
|
||||
for (int i = 0; i < orlist.size(); ++i) {
|
||||
orlist.get(i).saveXml(s);
|
||||
orlist.get(i).encode(encoder);
|
||||
}
|
||||
s.append("</or_pat>\n");
|
||||
encoder.closeElement(ELEM_OR_PAT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreXml(Element el) {
|
||||
List<?> list = el.getChildren();
|
||||
Iterator<?> iter = list.iterator();
|
||||
while (iter.hasNext()) {
|
||||
Element element = (Element) iter.next();
|
||||
DisjointPattern pat = DisjointPattern.restoreDisjoint(element);
|
||||
orlist.push_back(pat);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,9 +15,9 @@
|
|||
*/
|
||||
package ghidra.pcodeCPort.slghpattern;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.jdom.Element;
|
||||
import ghidra.program.model.pcode.Encoder;
|
||||
|
||||
public abstract class Pattern {
|
||||
|
||||
|
@ -44,8 +44,6 @@ public abstract class Pattern {
|
|||
|
||||
public abstract boolean alwaysInstructionTrue();
|
||||
|
||||
public abstract void saveXml(PrintStream s);
|
||||
|
||||
public abstract void restoreXml(Element el);
|
||||
public abstract void encode(Encoder encoder) throws IOException;
|
||||
|
||||
}
|
||||
|
|
|
@ -15,16 +15,14 @@
|
|||
*/
|
||||
package ghidra.pcodeCPort.slghpattern;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import org.jdom.Element;
|
||||
import java.io.IOException;
|
||||
|
||||
import generic.stl.IteratorSTL;
|
||||
import generic.stl.VectorSTL;
|
||||
import ghidra.pcodeCPort.utils.Utils;
|
||||
import ghidra.pcodeCPort.utils.XmlUtils;
|
||||
import ghidra.program.model.pcode.Encoder;
|
||||
|
||||
public class PatternBlock {
|
||||
|
||||
|
@ -363,41 +361,17 @@ public class PatternBlock {
|
|||
return res;
|
||||
}
|
||||
|
||||
public void saveXml(PrintStream s) {
|
||||
s.append("<pat_block ");
|
||||
s.append("offset=\"");
|
||||
s.print(offset);
|
||||
s.append("\" ");
|
||||
s.append("nonzero=\"");
|
||||
s.print(nonzerosize);
|
||||
s.append("\">\n");
|
||||
public void encode(Encoder encoder) throws IOException {
|
||||
encoder.openElement(ELEM_PAT_BLOCK);
|
||||
encoder.writeSignedInteger(ATTRIB_OFF, offset);
|
||||
encoder.writeSignedInteger(ATTRIB_NONZERO, nonzerosize);
|
||||
for (int i = 0; i < maskvec.size(); ++i) {
|
||||
s.append(" <mask_word ");
|
||||
s.append("mask=\"0x");
|
||||
s.append(Utils.toUnsignedIntHex(maskvec.get(i)));
|
||||
s.append("\" ");
|
||||
s.append("val=\"0x");
|
||||
s.append(Utils.toUnsignedIntHex(valvec.get(i)));
|
||||
s.append("\"/>\n");
|
||||
encoder.openElement(ELEM_MASK_WORD);
|
||||
encoder.writeUnsignedInteger(ATTRIB_MASK, Utils.unsignedInt(maskvec.get(i)));
|
||||
encoder.writeUnsignedInteger(ATTRIB_VAL, Utils.unsignedInt(valvec.get(i)));
|
||||
encoder.closeElement(ELEM_MASK_WORD);
|
||||
}
|
||||
s.append("</pat_block>\n");
|
||||
}
|
||||
|
||||
public void restoreXml(Element el) {
|
||||
offset = XmlUtils.decodeUnknownInt(el.getAttributeValue("offset"));
|
||||
nonzerosize = XmlUtils.decodeUnknownInt(el.getAttributeValue("nonzero"));
|
||||
|
||||
List<?> list = el.getChildren();
|
||||
Iterator<?> it = list.iterator();
|
||||
|
||||
while (it.hasNext()) {
|
||||
Element subel = (Element) it.next();
|
||||
int mask = XmlUtils.decodeUnknownInt(subel.getAttributeValue("mask"));
|
||||
int val = XmlUtils.decodeUnknownInt(subel.getAttributeValue("val"));
|
||||
maskvec.push_back(mask);
|
||||
valvec.push_back(val);
|
||||
}
|
||||
normalize();
|
||||
encoder.closeElement(ELEM_PAT_BLOCK);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -26,11 +25,11 @@ public class BitrangeSymbol extends SleighSymbol {
|
|||
int numbits; // number of bits in the range
|
||||
|
||||
public BitrangeSymbol(Location location) {
|
||||
super(location);
|
||||
} // For use with restoreXml
|
||||
super(location);
|
||||
}
|
||||
|
||||
public BitrangeSymbol( Location location, String nm, VarnodeSymbol sym, int bitoff, int num ) {
|
||||
super( location, nm );
|
||||
public BitrangeSymbol(Location location, String nm, VarnodeSymbol sym, int bitoff, int num) {
|
||||
super(location, nm);
|
||||
varsym = sym;
|
||||
bitoffset = bitoff;
|
||||
numbits = num;
|
||||
|
@ -49,7 +48,7 @@ public class BitrangeSymbol extends SleighSymbol {
|
|||
}
|
||||
|
||||
@Override
|
||||
public symbol_type getType() {
|
||||
public symbol_type getType() {
|
||||
return symbol_type.bitrange_symbol;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,10 +15,11 @@
|
|||
*/
|
||||
package ghidra.pcodeCPort.slghsymbol;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.util.*;
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import org.jdom.Element;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import generic.stl.IteratorSTL;
|
||||
import generic.stl.VectorSTL;
|
||||
|
@ -26,9 +27,8 @@ import ghidra.pcodeCPort.context.SleighError;
|
|||
import ghidra.pcodeCPort.semantics.ConstTpl.const_type;
|
||||
import ghidra.pcodeCPort.semantics.ConstructTpl;
|
||||
import ghidra.pcodeCPort.semantics.HandleTpl;
|
||||
import ghidra.pcodeCPort.sleighbase.SleighBase;
|
||||
import ghidra.pcodeCPort.slghpatexpress.*;
|
||||
import ghidra.pcodeCPort.utils.XmlUtils;
|
||||
import ghidra.program.model.pcode.Encoder;
|
||||
import ghidra.sleigh.grammar.Location;
|
||||
|
||||
public class Constructor {
|
||||
|
@ -298,105 +298,46 @@ public class Constructor {
|
|||
// printpiece.pop_back();
|
||||
}
|
||||
|
||||
public void saveXml(PrintStream s) {
|
||||
s.append("<constructor");
|
||||
s.append(" parent=\"0x");
|
||||
s.append(Long.toHexString(parent.getId()));
|
||||
s.append("\"");
|
||||
s.append(" first=\"");
|
||||
s.print(firstwhitespace);
|
||||
s.append("\"");
|
||||
s.append(" length=\"");
|
||||
s.print(minimumlength);
|
||||
s.append("\"");
|
||||
s.append(" line=\"");
|
||||
s.print(sourceFileIndex);
|
||||
s.append(":");
|
||||
s.print(getLineno());
|
||||
s.append("\">\n");
|
||||
public void encode(Encoder encoder) throws IOException {
|
||||
encoder.openElement(ELEM_CONSTRUCTOR);
|
||||
encoder.writeUnsignedInteger(ATTRIB_PARENT, parent.getId());
|
||||
encoder.writeSignedInteger(ATTRIB_FIRST, firstwhitespace);
|
||||
encoder.writeSignedInteger(ATTRIB_LENGTH, minimumlength);
|
||||
encoder.writeSignedInteger(ATTRIB_SOURCE, sourceFileIndex);
|
||||
encoder.writeSignedInteger(ATTRIB_LINE, getLineno());
|
||||
for (int i = 0; i < operands.size(); ++i) {
|
||||
s.append("<oper id=\"0x");
|
||||
s.append(Long.toHexString(operands.get(i).getId()));
|
||||
s.append("\"/>\n");
|
||||
encoder.openElement(ELEM_OPER);
|
||||
encoder.writeUnsignedInteger(ATTRIB_ID, operands.get(i).getId());
|
||||
encoder.closeElement(ELEM_OPER);
|
||||
}
|
||||
final int printpieces = printpiece.size();
|
||||
for (int i = 0; i < printpieces; ++i) {
|
||||
String piece = printpiece.get(i);
|
||||
if (piece.length() > 0 && piece.charAt(0) == '\n') {
|
||||
int index = piece.charAt(1) - 'A';
|
||||
s.append("<opprint id=\"");
|
||||
s.print(index);
|
||||
s.append("\"/>\n");
|
||||
encoder.openElement(ELEM_OPPRINT);
|
||||
encoder.writeSignedInteger(ATTRIB_ID, index);
|
||||
encoder.closeElement(ELEM_OPPRINT);
|
||||
}
|
||||
else {
|
||||
s.append("<print piece=\"");
|
||||
XmlUtils.xml_escape(s, piece);
|
||||
s.append("\"/>\n");
|
||||
encoder.openElement(ELEM_PRINT);
|
||||
encoder.writeString(ATTRIB_PIECE, piece);
|
||||
encoder.closeElement(ELEM_PRINT);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < context.size(); ++i) {
|
||||
context.get(i).saveXml(s);
|
||||
context.get(i).encode(encoder);
|
||||
}
|
||||
if (templ != null) {
|
||||
templ.saveXml(s, -1);
|
||||
templ.encode(encoder, -1);
|
||||
}
|
||||
for (int i = 0; i < namedtempl.size(); ++i) {
|
||||
if (namedtempl.get(i) == null) {
|
||||
continue;
|
||||
}
|
||||
namedtempl.get(i).saveXml(s, i);
|
||||
}
|
||||
s.append("</constructor>\n");
|
||||
}
|
||||
|
||||
public void restoreXml(Element el, SleighBase trans) {
|
||||
int id = XmlUtils.decodeUnknownInt(el.getAttributeValue("parent"));
|
||||
parent = (SubtableSymbol) trans.findSymbol(id);
|
||||
|
||||
firstwhitespace = XmlUtils.decodeUnknownInt(el.getAttributeValue("first"));
|
||||
minimumlength = XmlUtils.decodeUnknownInt(el.getAttributeValue("length"));
|
||||
int lineno = XmlUtils.decodeUnknownInt(el.getAttributeValue("line"));
|
||||
|
||||
List<?> list = el.getChildren();
|
||||
Iterator<?> iter = list.iterator();
|
||||
while (iter.hasNext()) {
|
||||
Element child = (Element) iter.next();
|
||||
if (child.getName().equals("oper")) {
|
||||
id = XmlUtils.decodeUnknownInt(child.getAttributeValue("id"));
|
||||
OperandSymbol sym = (OperandSymbol) trans.findSymbol(id);
|
||||
operands.push_back(sym);
|
||||
}
|
||||
else if (child.getName().equals("print")) {
|
||||
printpiece.push_back(child.getAttributeValue("piece"));
|
||||
}
|
||||
else if (child.getName().equals("opprint")) {
|
||||
int index = XmlUtils.decodeUnknownInt(child.getAttributeValue("id"));
|
||||
char c = (char) ('A' + index);
|
||||
String operstring = "\n" + c;
|
||||
printpiece.push_back(operstring);
|
||||
}
|
||||
else if (child.getName().equals("context_op")) {
|
||||
ContextOp c_op = new ContextOp(location);
|
||||
c_op.restoreXml(child, trans);
|
||||
context.push_back(c_op);
|
||||
}
|
||||
else if (child.getName().equals("commit")) {
|
||||
ContextCommit c_op = new ContextCommit();
|
||||
c_op.restoreXml(child, trans);
|
||||
context.push_back(c_op);
|
||||
}
|
||||
else {
|
||||
templ = new ConstructTpl(null);
|
||||
templ.restoreXml(child, trans);
|
||||
}
|
||||
}
|
||||
pattern = null;
|
||||
if ((printpiece.size() == 1) && (printpiece.get(0).charAt(0) == '\n')) {
|
||||
flowthruindex = printpiece.get(0).charAt(1) - 'A';
|
||||
}
|
||||
else {
|
||||
flowthruindex = -1;
|
||||
namedtempl.get(i).encode(encoder, i);
|
||||
}
|
||||
encoder.closeElement(ELEM_CONSTRUCTOR);
|
||||
}
|
||||
|
||||
private void orderOperands() {
|
||||
|
|
|
@ -15,11 +15,9 @@
|
|||
*/
|
||||
package ghidra.pcodeCPort.slghsymbol;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.jdom.Element;
|
||||
|
||||
import ghidra.pcodeCPort.sleighbase.SleighBase;
|
||||
import ghidra.program.model.pcode.Encoder;
|
||||
|
||||
// Change to context command
|
||||
public abstract class ContextChange {
|
||||
|
@ -29,9 +27,7 @@ public abstract class ContextChange {
|
|||
|
||||
public abstract void validate();
|
||||
|
||||
public abstract void saveXml(PrintStream s);
|
||||
|
||||
public abstract void restoreXml(Element el, SleighBase trans);
|
||||
public abstract void encode(Encoder encoder) throws IOException;
|
||||
|
||||
public void dispose() {
|
||||
}
|
||||
|
|
|
@ -15,12 +15,13 @@
|
|||
*/
|
||||
package ghidra.pcodeCPort.slghsymbol;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import org.jdom.Element;
|
||||
import java.io.IOException;
|
||||
|
||||
import ghidra.pcodeCPort.sleighbase.SleighBase;
|
||||
import ghidra.pcodeCPort.utils.*;
|
||||
import ghidra.pcodeCPort.utils.MutableInt;
|
||||
import ghidra.pcodeCPort.utils.Utils;
|
||||
import ghidra.program.model.pcode.Encoder;
|
||||
|
||||
public class ContextCommit extends ContextChange {
|
||||
|
||||
|
@ -30,7 +31,7 @@ public class ContextCommit extends ContextChange {
|
|||
private boolean flow; // Whether the context "flows" from the point of change
|
||||
|
||||
public ContextCommit() {
|
||||
} // For use with restoreXml
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validate() {
|
||||
|
@ -48,29 +49,13 @@ public class ContextCommit extends ContextChange {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void saveXml(PrintStream s) {
|
||||
s.append("<commit");
|
||||
XmlUtils.a_v_u(s, "id", sym.getId());
|
||||
XmlUtils.a_v_i(s, "num", num);
|
||||
XmlUtils.a_v_u(s, "mask", Utils.unsignedInt(mask));
|
||||
XmlUtils.a_v_b(s, "flow", flow);
|
||||
s.append("/>\n");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreXml(Element el, SleighBase trans) {
|
||||
int id = XmlUtils.decodeUnknownInt(el.getAttributeValue("id"));
|
||||
sym = (TripleSymbol) trans.findSymbol(id);
|
||||
|
||||
num = XmlUtils.decodeUnknownInt(el.getAttributeValue("num"));
|
||||
mask = XmlUtils.decodeUnknownInt(el.getAttributeValue("mask"));
|
||||
String value = el.getAttributeValue("flow");
|
||||
if (value != null) {
|
||||
flow = XmlUtils.decodeBoolean(value);
|
||||
}
|
||||
else {
|
||||
flow = true;
|
||||
}
|
||||
public void encode(Encoder encoder) throws IOException {
|
||||
encoder.openElement(ELEM_COMMIT);
|
||||
encoder.writeUnsignedInteger(ATTRIB_ID, sym.getId());
|
||||
encoder.writeSignedInteger(ATTRIB_NUMBER, num);
|
||||
encoder.writeUnsignedInteger(ATTRIB_MASK, Utils.unsignedInt(mask));
|
||||
encoder.writeBool(ATTRIB_FLOW, flow);
|
||||
encoder.closeElement(ELEM_COMMIT);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,15 +15,16 @@
|
|||
*/
|
||||
package ghidra.pcodeCPort.slghsymbol;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import org.jdom.Element;
|
||||
import java.io.IOException;
|
||||
|
||||
import generic.stl.VectorSTL;
|
||||
import ghidra.pcodeCPort.context.SleighError;
|
||||
import ghidra.pcodeCPort.sleighbase.SleighBase;
|
||||
import ghidra.pcodeCPort.slghpatexpress.*;
|
||||
import ghidra.pcodeCPort.utils.*;
|
||||
import ghidra.pcodeCPort.utils.MutableInt;
|
||||
import ghidra.pcodeCPort.utils.Utils;
|
||||
import ghidra.program.model.pcode.Encoder;
|
||||
import ghidra.sleigh.grammar.Location;
|
||||
|
||||
public class ContextOp extends ContextChange {
|
||||
|
@ -36,7 +37,7 @@ public class ContextOp extends ContextChange {
|
|||
|
||||
public ContextOp(Location location) {
|
||||
this.location = location;
|
||||
} // For use with restoreXml
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
|
@ -78,29 +79,13 @@ public class ContextOp extends ContextChange {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void saveXml(PrintStream s) {
|
||||
s.append("<context_op");
|
||||
s.append(" i=\"");
|
||||
s.print(num);
|
||||
s.append("\"");
|
||||
s.append(" shift=\"");
|
||||
s.print(shift);
|
||||
s.append("\"");
|
||||
s.append(" mask=\"0x");
|
||||
s.append(Utils.toUnsignedIntHex(mask));
|
||||
s.append("\" >\n");
|
||||
patexp.saveXml(s);
|
||||
s.append("</context_op>\n");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreXml(Element el, SleighBase trans) {
|
||||
num = XmlUtils.decodeUnknownInt(el.getAttributeValue("i"));
|
||||
shift = XmlUtils.decodeUnknownInt(el.getAttributeValue("shift"));
|
||||
mask = XmlUtils.decodeUnknownInt(el.getAttributeValue("mask"));
|
||||
Element child = (Element) el.getChildren().get(0);
|
||||
patexp = PatternExpression.restoreExpression(child, trans);
|
||||
patexp.layClaim();
|
||||
public void encode(Encoder encoder) throws IOException {
|
||||
encoder.openElement(ELEM_CONTEXT_OP);
|
||||
encoder.writeSignedInteger(ATTRIB_I, num);
|
||||
encoder.writeSignedInteger(ATTRIB_SHIFT, shift);
|
||||
encoder.writeUnsignedInteger(ATTRIB_MASK, Utils.unsignedInt(mask));
|
||||
patexp.encode(encoder);
|
||||
encoder.closeElement(ELEM_CONTEXT_OP);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -16,16 +15,14 @@
|
|||
*/
|
||||
package ghidra.pcodeCPort.slghsymbol;
|
||||
|
||||
import ghidra.pcodeCPort.sleighbase.*;
|
||||
import ghidra.pcodeCPort.slghpatexpress.*;
|
||||
import ghidra.pcodeCPort.utils.*;
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import ghidra.pcodeCPort.slghpatexpress.ContextField;
|
||||
import ghidra.program.model.pcode.Encoder;
|
||||
import ghidra.sleigh.grammar.Location;
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
import org.jdom.Element;
|
||||
|
||||
|
||||
public class ContextSymbol extends ValueSymbol {
|
||||
|
||||
private VarnodeSymbol vn;
|
||||
|
@ -33,8 +30,8 @@ public class ContextSymbol extends ValueSymbol {
|
|||
private boolean flow;
|
||||
|
||||
public ContextSymbol(Location location) {
|
||||
super(location);
|
||||
} // For use with restoreXml
|
||||
super(location);
|
||||
}
|
||||
|
||||
public VarnodeSymbol getVarnode() {
|
||||
return vn;
|
||||
|
@ -49,16 +46,17 @@ public class ContextSymbol extends ValueSymbol {
|
|||
}
|
||||
|
||||
public boolean isFlow() {
|
||||
return flow;
|
||||
return flow;
|
||||
}
|
||||
|
||||
@Override
|
||||
public symbol_type getType() {
|
||||
public symbol_type getType() {
|
||||
return symbol_type.context_symbol;
|
||||
}
|
||||
|
||||
public ContextSymbol( Location location, String nm, ContextField pate, VarnodeSymbol v, int l, int h, boolean flow ) {
|
||||
super( location, nm, pate );
|
||||
public ContextSymbol(Location location, String nm, ContextField pate, VarnodeSymbol v, int l,
|
||||
int h, boolean flow) {
|
||||
super(location, nm, pate);
|
||||
vn = v;
|
||||
low = l;
|
||||
high = h;
|
||||
|
@ -66,39 +64,22 @@ public class ContextSymbol extends ValueSymbol {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void saveXml( PrintStream s ) {
|
||||
s.append( "<context_sym" );
|
||||
saveSleighSymbolXmlHeader(s);
|
||||
s.append( " varnode=\"0x" );
|
||||
s.append( Long.toHexString( vn.getId() ) );
|
||||
s.append( "\"" );
|
||||
s.append( " low=\"" );
|
||||
s.print( low );
|
||||
s.append( "\"" );
|
||||
s.append( " high=\"" );
|
||||
s.print( high );
|
||||
s.append( "\" flow=\"" );
|
||||
s.print( flow );
|
||||
s.println( "\">" );
|
||||
patval.saveXml( s );
|
||||
s.println( "</context_sym>" );
|
||||
public void encode(Encoder encoder) throws IOException {
|
||||
encoder.openElement(ELEM_CONTEXT_SYM);
|
||||
encoder.writeUnsignedInteger(ATTRIB_ID, id);
|
||||
encoder.writeUnsignedInteger(ATTRIB_VARNODE, vn.getId());
|
||||
encoder.writeSignedInteger(ATTRIB_LOW, low);
|
||||
encoder.writeSignedInteger(ATTRIB_HIGH, high);
|
||||
encoder.writeBool(ATTRIB_FLOW, flow);
|
||||
patval.encode(encoder);
|
||||
encoder.closeElement(ELEM_CONTEXT_SYM);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveXmlHeader( PrintStream s ) {
|
||||
s.append( "<context_sym_head" );
|
||||
saveSleighSymbolXmlHeader(s);
|
||||
s.println( "/>" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreXml( Element el, SleighBase trans ) {
|
||||
super.restoreXml( el, trans );
|
||||
|
||||
int id = XmlUtils.decodeUnknownInt( el.getAttributeValue( "varnode" ) );
|
||||
vn = (VarnodeSymbol) trans.findSymbol( id );
|
||||
low = XmlUtils.decodeUnknownInt( el.getAttributeValue( "low" ) );
|
||||
high = XmlUtils.decodeUnknownInt( el.getAttributeValue( "high" ) );
|
||||
public void encodeHeader(Encoder encoder) throws IOException {
|
||||
encoder.openElement(ELEM_CONTEXT_SYM_HEAD);
|
||||
encodeSleighSymbolHeader(encoder);
|
||||
encoder.closeElement(ELEM_CONTEXT_SYM_HEAD);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,21 +15,18 @@
|
|||
*/
|
||||
package ghidra.pcodeCPort.slghsymbol;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import org.jdom.Element;
|
||||
import java.io.IOException;
|
||||
|
||||
import generic.stl.*;
|
||||
import ghidra.pcodeCPort.error.LowlevelError;
|
||||
import ghidra.pcodeCPort.slghpattern.DisjointPattern;
|
||||
import ghidra.pcodeCPort.utils.XmlUtils;
|
||||
import ghidra.program.model.pcode.Encoder;
|
||||
|
||||
public class DecisionNode {
|
||||
|
||||
private VectorSTL<Pair<DisjointPattern, Constructor>> list =
|
||||
new VectorSTL<>();
|
||||
private VectorSTL<Pair<DisjointPattern, Constructor>> list = new VectorSTL<>();
|
||||
private VectorSTL<DecisionNode> children = new VectorSTL<>();
|
||||
private int num; // Total number of patterns we distinguish
|
||||
private boolean contextdecision; // True if this is decision based on context
|
||||
|
@ -37,7 +34,7 @@ public class DecisionNode {
|
|||
private DecisionNode parent;
|
||||
|
||||
public DecisionNode() {
|
||||
} // For use with restoreXml
|
||||
}
|
||||
|
||||
public DecisionNode(DecisionNode p) {
|
||||
parent = p;
|
||||
|
@ -213,7 +210,7 @@ public class DecisionNode {
|
|||
long dontCareMask = m ^ commonMask;
|
||||
|
||||
for (int i = 0; i <= dontCareMask; ++i) { // Iterate over values that contain all don't
|
||||
// care bits
|
||||
// care bits
|
||||
if ((i & dontCareMask) != i) {
|
||||
continue; // If all 1 bits in the value are don't cares
|
||||
}
|
||||
|
@ -284,8 +281,7 @@ public class DecisionNode {
|
|||
public void orderPatterns(DecisionProperties props) {
|
||||
int i, j, k;
|
||||
VectorSTL<Pair<DisjointPattern, Constructor>> newlist = list.copy();
|
||||
VectorSTL<Pair<DisjointPattern, Constructor>> conflictlist =
|
||||
new VectorSTL<>();
|
||||
VectorSTL<Pair<DisjointPattern, Constructor>> conflictlist = new VectorSTL<>();
|
||||
|
||||
// Check for identical patterns
|
||||
for (i = 0; i < list.size(); ++i) {
|
||||
|
@ -312,10 +308,8 @@ public class DecisionNode {
|
|||
// So there is no conflict
|
||||
}
|
||||
else { // A true conflict that needs to be resolved
|
||||
conflictlist.push_back(
|
||||
new Pair<>(ipat, iconst));
|
||||
conflictlist.push_back(
|
||||
new Pair<>(jpat, jconst));
|
||||
conflictlist.push_back(new Pair<>(ipat, iconst));
|
||||
conflictlist.push_back(new Pair<>(jpat, jconst));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -354,65 +348,22 @@ public class DecisionNode {
|
|||
}
|
||||
}
|
||||
|
||||
void saveXml(PrintStream s) {
|
||||
s.append("<decision");
|
||||
s.append(" number=\"");
|
||||
s.print(num);
|
||||
s.append("\"");
|
||||
s.append(" context=\"");
|
||||
if (contextdecision) {
|
||||
s.append("true\"");
|
||||
}
|
||||
else {
|
||||
s.append("false\"");
|
||||
}
|
||||
s.append(" start=\"");
|
||||
s.print(startbit);
|
||||
s.append("\"");
|
||||
s.append(" size=\"");
|
||||
s.print(bitsize);
|
||||
s.append("\"");
|
||||
s.append(">\n");
|
||||
void encode(Encoder encoder) throws IOException {
|
||||
encoder.openElement(ELEM_DECISION);
|
||||
encoder.writeSignedInteger(ATTRIB_NUMBER, num);
|
||||
encoder.writeBool(ATTRIB_CONTEXT, contextdecision);
|
||||
encoder.writeSignedInteger(ATTRIB_STARTBIT, startbit);
|
||||
encoder.writeSignedInteger(ATTRIB_SIZE, bitsize);
|
||||
for (int i = 0; i < list.size(); ++i) {
|
||||
s.append("<pair id=\"");
|
||||
s.print(list.get(i).second.getId());
|
||||
s.append("\">\n");
|
||||
list.get(i).first.saveXml(s);
|
||||
s.append("</pair>\n");
|
||||
encoder.openElement(ELEM_PAIR);
|
||||
encoder.writeSignedInteger(ATTRIB_ID, list.get(i).second.getId());
|
||||
list.get(i).first.encode(encoder);
|
||||
encoder.closeElement(ELEM_PAIR);
|
||||
}
|
||||
for (int i = 0; i < children.size(); ++i) {
|
||||
children.get(i).saveXml(s);
|
||||
}
|
||||
s.append("</decision>\n");
|
||||
}
|
||||
|
||||
void restoreXml(Element el, DecisionNode par, SubtableSymbol sub) {
|
||||
parent = par;
|
||||
num = XmlUtils.decodeUnknownInt(el.getAttributeValue("number"));
|
||||
|
||||
contextdecision = XmlUtils.decodeBoolean(el.getAttributeValue("context"));
|
||||
startbit = XmlUtils.decodeUnknownInt(el.getAttributeValue("start"));
|
||||
bitsize = XmlUtils.decodeUnknownInt(el.getAttributeValue("size"));
|
||||
|
||||
List<?> childlist = el.getChildren();
|
||||
Iterator<?> iter = childlist.iterator();
|
||||
while (iter.hasNext()) {
|
||||
Element child = (Element) iter.next();
|
||||
if (child.getName().equals("pair")) {
|
||||
int id = XmlUtils.decodeUnknownInt(child.getAttributeValue("id"));
|
||||
Constructor ct = sub.getConstructor(id);
|
||||
DisjointPattern pat =
|
||||
DisjointPattern.restoreDisjoint((Element) child.getChildren().get(0));
|
||||
// This increments num addConstructorPair(pat,ct);
|
||||
list.push_back(new Pair<>(pat, ct));
|
||||
// delete pat; // addConstructorPair makes its own copy
|
||||
}
|
||||
else if (child.getName().equals("decision")) {
|
||||
DecisionNode subnode = new DecisionNode();
|
||||
subnode.restoreXml(child, this, sub);
|
||||
children.push_back(subnode);
|
||||
}
|
||||
children.get(i).encode(encoder);
|
||||
}
|
||||
encoder.closeElement(ELEM_DECISION);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,16 +15,16 @@
|
|||
*/
|
||||
package ghidra.pcodeCPort.slghsymbol;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import org.jdom.Element;
|
||||
import java.io.IOException;
|
||||
|
||||
import ghidra.pcodeCPort.semantics.ConstTpl;
|
||||
import ghidra.pcodeCPort.semantics.VarnodeTpl;
|
||||
import ghidra.pcodeCPort.sleighbase.SleighBase;
|
||||
import ghidra.pcodeCPort.slghpatexpress.EndInstructionValue;
|
||||
import ghidra.pcodeCPort.slghpatexpress.PatternExpression;
|
||||
import ghidra.pcodeCPort.space.AddrSpace;
|
||||
import ghidra.program.model.pcode.Encoder;
|
||||
import ghidra.sleigh.grammar.Location;
|
||||
|
||||
public class EndSymbol extends SpecificSymbol {
|
||||
|
@ -34,7 +34,7 @@ public class EndSymbol extends SpecificSymbol {
|
|||
public EndSymbol(Location location) {
|
||||
super(location);
|
||||
patexp = null;
|
||||
} // For use with restoreXml
|
||||
}
|
||||
|
||||
@Override
|
||||
public PatternExpression getPatternExpression() {
|
||||
|
@ -70,24 +70,17 @@ public class EndSymbol extends SpecificSymbol {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void saveXml(PrintStream s) {
|
||||
s.append("<end_sym");
|
||||
saveSleighSymbolXmlHeader(s);
|
||||
s.println("/>");
|
||||
public void encode(Encoder encoder) throws IOException {
|
||||
encoder.openElement(ELEM_END_SYM);
|
||||
encoder.writeUnsignedInteger(ATTRIB_ID, id);
|
||||
encoder.closeElement(ELEM_END_SYM);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveXmlHeader(PrintStream s) {
|
||||
s.append("<end_sym_head");
|
||||
saveSleighSymbolXmlHeader(s);
|
||||
s.println("/>");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreXml(Element el, SleighBase trans) {
|
||||
const_space = trans.getConstantSpace();
|
||||
patexp = new EndInstructionValue(null);
|
||||
patexp.layClaim();
|
||||
public void encodeHeader(Encoder encoder) throws IOException {
|
||||
encoder.openElement(ELEM_END_SYM_HEAD);
|
||||
encodeSleighSymbolHeader(encoder);
|
||||
encoder.closeElement(ELEM_END_SYM_HEAD);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,14 +15,14 @@
|
|||
*/
|
||||
package ghidra.pcodeCPort.slghsymbol;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import org.jdom.Element;
|
||||
import java.io.IOException;
|
||||
|
||||
import ghidra.pcodeCPort.semantics.ConstTpl;
|
||||
import ghidra.pcodeCPort.semantics.VarnodeTpl;
|
||||
import ghidra.pcodeCPort.sleighbase.SleighBase;
|
||||
import ghidra.pcodeCPort.space.AddrSpace;
|
||||
import ghidra.program.model.pcode.Encoder;
|
||||
import ghidra.sleigh.grammar.Location;
|
||||
|
||||
// Another name for zero pattern/value
|
||||
|
@ -32,7 +32,7 @@ public class EpsilonSymbol extends PatternlessSymbol {
|
|||
|
||||
public EpsilonSymbol(Location location) {
|
||||
super(location);
|
||||
} // For use with restoreXml
|
||||
}
|
||||
|
||||
public EpsilonSymbol(Location location, String nm, AddrSpace spc) {
|
||||
super(location, nm);
|
||||
|
@ -46,27 +46,22 @@ public class EpsilonSymbol extends PatternlessSymbol {
|
|||
|
||||
@Override
|
||||
public VarnodeTpl getVarnode() {
|
||||
return new VarnodeTpl(location, new ConstTpl(const_space), new ConstTpl(
|
||||
ConstTpl.const_type.real, 0), new ConstTpl(ConstTpl.const_type.real, 0));
|
||||
return new VarnodeTpl(location, new ConstTpl(const_space),
|
||||
new ConstTpl(ConstTpl.const_type.real, 0), new ConstTpl(ConstTpl.const_type.real, 0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveXml(PrintStream s) {
|
||||
s.append("<epsilon_sym");
|
||||
saveSleighSymbolXmlHeader(s);
|
||||
s.println("/>");
|
||||
public void encode(Encoder encoder) throws IOException {
|
||||
encoder.openElement(ELEM_EPSILON_SYM);
|
||||
encoder.writeUnsignedInteger(ATTRIB_ID, id);
|
||||
encoder.closeElement(ELEM_EPSILON_SYM);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveXmlHeader(PrintStream s) {
|
||||
s.append("<epsilon_sym_head");
|
||||
saveSleighSymbolXmlHeader(s);
|
||||
s.println("/>");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreXml(Element el, SleighBase trans) {
|
||||
const_space = trans.getConstantSpace();
|
||||
public void encodeHeader(Encoder encoder) throws IOException {
|
||||
encoder.openElement(ELEM_EPSILON_SYM_HEAD);
|
||||
encodeSleighSymbolHeader(encoder);
|
||||
encoder.closeElement(ELEM_EPSILON_SYM_HEAD);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,16 +15,13 @@
|
|||
*/
|
||||
package ghidra.pcodeCPort.slghsymbol;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import static ghidra.pcode.utils.SlaFormat.*;
|
||||
|
||||
import org.jdom.Element;
|
||||
import java.io.IOException;
|
||||
|
||||
import generic.stl.VectorSTL;
|
||||
import ghidra.pcodeCPort.sleighbase.SleighBase;
|
||||
import ghidra.pcodeCPort.slghpatexpress.PatternExpression;
|
||||
import ghidra.pcodeCPort.slghpatexpress.PatternValue;
|
||||
import ghidra.program.model.pcode.Encoder;
|
||||
import ghidra.sleigh.grammar.Location;
|
||||
|
||||
public class NameSymbol extends ValueSymbol {
|
||||
|
@ -34,7 +31,7 @@ public class NameSymbol extends ValueSymbol {
|
|||
|
||||
public NameSymbol(Location location) {
|
||||
super(location);
|
||||
} // For use with restoreXml
|
||||
}
|
||||
|
||||
public NameSymbol(Location location, String nm, PatternValue pv, VectorSTL<String> nt) {
|
||||
super(location, nm, pv);
|
||||
|
@ -60,44 +57,26 @@ public class NameSymbol extends ValueSymbol {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void saveXml(PrintStream s) {
|
||||
s.append("<name_sym");
|
||||
saveSleighSymbolXmlHeader(s);
|
||||
s.println(">");
|
||||
patval.saveXml(s);
|
||||
public void encode(Encoder encoder) throws IOException {
|
||||
encoder.openElement(ELEM_NAME_SYM);
|
||||
encoder.writeUnsignedInteger(ATTRIB_ID, id);
|
||||
patval.encode(encoder);
|
||||
for (int i = 0; i < nametable.size(); ++i) {
|
||||
String name = nametable.get(i);
|
||||
encoder.openElement(ELEM_NAMETAB);
|
||||
if (name != null) {
|
||||
s.append("<nametab name=\"");
|
||||
s.append(name);
|
||||
s.println("\"/>");
|
||||
}
|
||||
else {
|
||||
s.println("<nametab/>");
|
||||
encoder.writeString(ATTRIB_NAME, name);
|
||||
}
|
||||
encoder.closeElement(ELEM_NAMETAB);
|
||||
}
|
||||
s.println("</name_sym>");
|
||||
encoder.closeElement(ELEM_NAME_SYM);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveXmlHeader(PrintStream s) {
|
||||
s.append("<name_sym_head");
|
||||
saveSleighSymbolXmlHeader(s);
|
||||
s.println("/>");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreXml(Element el, SleighBase trans) {
|
||||
List<?> list = el.getChildren();
|
||||
Iterator<?> iter = list.iterator();
|
||||
Element element = (Element) iter.next();
|
||||
patval = (PatternValue) PatternExpression.restoreExpression(element, trans);
|
||||
patval.layClaim();
|
||||
while (iter.hasNext()) {
|
||||
Element child = (Element) iter.next();
|
||||
nametable.push_back(child.getAttributeValue("name"));
|
||||
}
|
||||
checkTableFill();
|
||||
public void encodeHeader(Encoder encoder) throws IOException {
|
||||
encoder.openElement(ELEM_NAME_SYM_HEAD);
|
||||
encodeSleighSymbolHeader(encoder);
|
||||
encoder.closeElement(ELEM_NAME_SYM_HEAD);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue