GP-4285 Compressed SLEIGH

This commit is contained in:
caheckman 2024-01-10 22:53:12 +00:00
parent b380fd5fa6
commit 8fbd171cdf
207 changed files with 15233 additions and 6055 deletions

View file

@ -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;

View file

@ -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;
}

View file

@ -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);
}
}

View file

@ -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() {

View file

@ -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));

View file

@ -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() {

View file

@ -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);

View file

@ -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);
}
}

View file

@ -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

View file

@ -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;

View file

@ -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
}

View file

@ -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
}

View file

@ -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

View file

@ -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;
}

View file

@ -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
}

View file

@ -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;

View file

@ -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);
}
}

View file

@ -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

View file

@ -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

View file

@ -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;
}
}

View file

@ -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

View file

@ -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);
}
}

View file

@ -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;
}

View file

@ -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

View file

@ -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());
}
}

View file

@ -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());
}
}

View file

@ -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);
}
}

View file

@ -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());
}
}

View file

@ -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());
}
}

View file

@ -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

View file

@ -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());
}
}

View file

@ -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());
}
}

View file

@ -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;
}

View file

@ -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;
}
}

View file

@ -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());
}
}

View file

@ -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());
}
}

View file

@ -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());
}
}

View file

@ -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());
}
}

View file

@ -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());
}
}

View file

@ -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

View file

@ -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;
}

View file

@ -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() {

View file

@ -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

View file

@ -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

View file

@ -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();
}
}
}

View file

@ -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;
}
}

View file

@ -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);
}
}

View file

@ -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 );
}
}
}

View file

@ -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);
}
}

View file

@ -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
}
}
}

View file

@ -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);
}
}
}

View file

@ -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;
}

View file

@ -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

View file

@ -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);
}
}

View file

@ -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");
}
}
}

View file

@ -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);
}
}

View file

@ -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() {

View file

@ -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);
}
}

View file

@ -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) {

View file

@ -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);
}
}

View file

@ -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));
}
}

View file

@ -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;

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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;
}
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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) + "}";

View file

@ -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);
}
}

View file

@ -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);
}
}
}

View file

@ -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;
}

View file

@ -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

View file

@ -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;
}

View file

@ -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() {

View file

@ -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() {
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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