GP-2262 Marshaling refactor - java-side

This commit is contained in:
caheckman 2022-06-29 18:28:53 -04:00
parent 0123c85d9f
commit ae79857b42
68 changed files with 3131 additions and 1597 deletions

View File

@ -21,6 +21,7 @@
#include "ifacedecomp.hh"
static IfaceStatus *ghidra_dcp = (IfaceStatus *)0;
static RemoteSocket *remote = (RemoteSocket *)0;
@ -62,6 +63,8 @@ void connect_to_console(Funcdata *fd)
#endif
ElementId ELEM_DOC = ElementId("doc",218);
vector<ArchitectureGhidra *> archlist; // List of architectures currently running
map<string,GhidraCommand *> GhidraCapability::commandmap; // List of commands we can receive from Ghidra proper
@ -300,10 +303,10 @@ void DecompileAt::rawAction(void)
}
sout.write("\000\000\001\016",4);
// Write output XML directly to outstream
if (fd->isProcComplete()) {
sout << "<doc>\n";
XmlEncode encoder(sout);
encoder.openElement(ELEM_DOC);
if (ghidra->getSendParamMeasures() && (ghidra->allacts.getCurrentName() == "paramid")) {
ParamIDAnalysis pidanalysis( fd, true ); // Only send back final prototype
pidanalysis.encode( encoder, true );
@ -318,7 +321,7 @@ void DecompileAt::rawAction(void)
(ghidra->allacts.getCurrentName() == "decompile"))
ghidra->print->docFunction(fd);
}
sout << "</doc>\n";
encoder.closeElement(ELEM_DOC);
}
sout.write("\000\000\001\017",4);
}

View File

@ -29,6 +29,8 @@
class GhidraCommand;
extern ElementId ELEM_DOC; ///< Marshaling element \<doc>
/// \brief Registration point and dispatcher for commands sent to the decompiler
///
/// This is the base class for \b command \b capabilities (sets of commands).

View File

@ -500,7 +500,7 @@ AttributeId ATTRIB_VAL = AttributeId("val",24);
AttributeId ATTRIB_VALUE = AttributeId("value",25);
AttributeId ATTRIB_WORDSIZE = AttributeId("wordsize",26);
AttributeId ATTRIB_UNKNOWN = AttributeId("XMLunknown",144); // Number serves as next open index
AttributeId ATTRIB_UNKNOWN = AttributeId("XMLunknown",147); // Number serves as next open index
ElementId ELEM_DATA = ElementId("data",1);
ElementId ELEM_INPUT = ElementId("input",2);
@ -513,4 +513,4 @@ ElementId ELEM_VAL = ElementId("val",8);
ElementId ELEM_VALUE = ElementId("value",9);
ElementId ELEM_VOID = ElementId("void",10);
ElementId ELEM_UNKNOWN = ElementId("XMLunknown",218); // Number serves as next open index
ElementId ELEM_UNKNOWN = ElementId("XMLunknown",231); // Number serves as next open index

View File

@ -232,7 +232,7 @@ public:
/// \brief Find the specific attribute in the current element and return it as an address space
///
/// Search attributes from the current element for a match to the given attribute id.
/// Return this attribute as an address space. If there is no attribute matching the id, an exception is throw.
/// Return this attribute as an address space. If there is no attribute matching the id, an exception is thrown.
/// Parse via getNextAttributeId is reset.
/// \param attribId is the specific attribute id to match
/// \return the address space associated with the attribute

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,28 +16,28 @@
package ghidra.app.decompiler;
import ghidra.program.model.pcode.*;
import ghidra.util.xml.*;
import ghidra.xml.*;
public class ClangBreak extends ClangToken {
private int indent; // Number of characters of indent
public ClangBreak(ClangNode par) {
super(par);
indent = 0;
}
public ClangBreak(ClangNode par,int indent) {
public ClangBreak(ClangNode par, int indent) {
super(par);
this.indent = indent;
}
public int getIndent() { return indent; }
public int getIndent() {
return indent;
}
@Override
public void restoreFromXML(XmlElement el,XmlElement end,PcodeFactory pfactory) {
super.restoreFromXML(el,end,pfactory);
indent = SpecXmlUtils.decodeInt(el.getAttribute("indent"));
public void decode(Decoder decoder, PcodeFactory pfactory) throws PcodeXMLException {
indent = (int) decoder.readSignedInteger(AttributeId.ATTRIB_INDENT);
super.decode(decoder, pfactory);
}
}

View File

@ -17,9 +17,7 @@ package ghidra.app.decompiler;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSpace;
import ghidra.program.model.pcode.PcodeFactory;
import ghidra.util.xml.SpecXmlUtils;
import ghidra.xml.XmlElement;
import ghidra.program.model.pcode.*;
public class ClangCommentToken extends ClangToken {
@ -58,12 +56,11 @@ public class ClangCommentToken extends ClangToken {
}
@Override
public void restoreFromXML(XmlElement el, XmlElement end, PcodeFactory pfactory) {
super.restoreFromXML(el, end, pfactory);
String name = el.getAttribute(ClangXML.SPACE);
AddressSpace spc = pfactory.getAddressFactory().getAddressSpace(name);
long offset = SpecXmlUtils.decodeLong(el.getAttribute(ClangXML.OFFSET));
public void decode(Decoder decoder, PcodeFactory pfactory) throws PcodeXMLException {
AddressSpace spc = decoder.readSpace(AttributeId.ATTRIB_SPACE);
long offset = decoder.readUnsignedInteger(AttributeId.ATTRIB_OFF);
srcaddr = spc.getAddress(offset);
super.decode(decoder, pfactory);
}
}

View File

@ -16,10 +16,7 @@
package ghidra.app.decompiler;
import ghidra.program.model.data.DataType;
import ghidra.program.model.pcode.PcodeFactory;
import ghidra.program.model.pcode.PcodeOp;
import ghidra.util.xml.SpecXmlUtils;
import ghidra.xml.XmlElement;
import ghidra.program.model.pcode.*;
/**
* A C code token representing a structure field.
@ -55,22 +52,33 @@ public class ClangFieldToken extends ClangToken {
}
@Override
public void restoreFromXML(XmlElement el, XmlElement end, PcodeFactory pfactory) {
super.restoreFromXML(el, end, pfactory);
String datatypestring = el.getAttribute("name"); // Name of the structure
public void decode(Decoder decoder, PcodeFactory pfactory) throws PcodeXMLException {
String datatypestring = null;
long id = 0;
for (;;) {
int attribId = decoder.getNextAttributeId();
if (attribId == 0) {
break;
}
if (attribId == AttributeId.ATTRIB_NAME.getId()) { // Name of the structure
datatypestring = decoder.readString();
}
else if (attribId == AttributeId.ATTRIB_ID.getId()) {
id = decoder.readUnsignedInteger();
}
else if (attribId == AttributeId.ATTRIB_OFF.getId()) {
offset = (int) decoder.readSignedInteger();
}
else if (attribId == AttributeId.ATTRIB_OPREF.getId()) {
int refid = (int) decoder.readUnsignedInteger();
op = pfactory.getOpRef(refid);
}
}
if (datatypestring != null) {
datatype =
pfactory.getDataTypeManager().findBaseType(datatypestring, el.getAttribute("id"));
}
String offsetstring = el.getAttribute(ClangXML.OFFSET);
if (offsetstring != null) {
offset = SpecXmlUtils.decodeInt(offsetstring);
}
String oprefstring = el.getAttribute(ClangXML.OPREF);
if (oprefstring != null) {
int refid = SpecXmlUtils.decodeInt(oprefstring);
op = pfactory.getOpRef(refid);
datatype = pfactory.getDataTypeManager().findBaseType(datatypestring, id);
}
decoder.rewindAttributes();
super.decode(decoder, pfactory);
}
}

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.
@ -22,10 +21,8 @@
*/
package ghidra.app.decompiler;
import ghidra.program.model.address.*;
import ghidra.program.model.address.Address;
import ghidra.program.model.pcode.*;
import ghidra.util.xml.*;
import ghidra.xml.*;
/**
*
@ -37,34 +34,51 @@ public class ClangFuncNameToken extends ClangToken {
private HighFunction hfunc; // Overall reference to function
private PcodeOp op; // Local reference to function op
public ClangFuncNameToken(ClangNode par,HighFunction hf) {
public ClangFuncNameToken(ClangNode par, HighFunction hf) {
super(par);
hfunc = hf;
op = null;
}
public HighFunction getHighFunction() { return hfunc; }
@Override
public PcodeOp getPcodeOp() { return op; }
@Override
public Address getMinAddress() {
if (op==null) return null;
return op.getSeqnum().getTarget().getPhysicalAddress();
public HighFunction getHighFunction() {
return hfunc;
}
@Override
public Address getMaxAddress() {
if (op==null) return null;
return op.getSeqnum().getTarget().getPhysicalAddress();
public PcodeOp getPcodeOp() {
return op;
}
@Override
public void restoreFromXML(XmlElement el,XmlElement end,PcodeFactory pfactory) {
super.restoreFromXML(el,end,pfactory);
String oprefstring = el.getAttribute(ClangXML.OPREF);
if (oprefstring != null) {
int refid = SpecXmlUtils.decodeInt(oprefstring);
op = pfactory.getOpRef(refid);
public Address getMinAddress() {
if (op == null) {
return null;
}
return op.getSeqnum().getTarget().getPhysicalAddress();
}
@Override
public Address getMaxAddress() {
if (op == null) {
return null;
}
return op.getSeqnum().getTarget().getPhysicalAddress();
}
@Override
public void decode(Decoder decoder, PcodeFactory pfactory) throws PcodeXMLException {
for (;;) {
int attribId = decoder.getNextAttributeId();
if (attribId == 0) {
break;
}
if (attribId == AttributeId.ATTRIB_OPREF.getId()) {
int refid = (int) decoder.readUnsignedInteger();
op = pfactory.getOpRef(refid);
break;
}
}
decoder.rewindAttributes();
super.decode(decoder, pfactory);
}
}

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,36 +15,39 @@
*/
package ghidra.app.decompiler;
import ghidra.program.model.address.*;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSpace;
import ghidra.program.model.pcode.*;
import ghidra.util.xml.*;
import ghidra.xml.*;
public class ClangLabelToken extends ClangToken {
private Address blockaddr; // Address this is labelling
public ClangLabelToken(ClangNode par) {
super(par);
blockaddr = null;
}
@Override
public boolean isVariableRef() { return false; }
@Override
public Address getMinAddress() { return blockaddr; }
@Override
public Address getMaxAddress() { return blockaddr; }
@Override
public void restoreFromXML(XmlElement el,XmlElement end,PcodeFactory pfactory) {
super.restoreFromXML(el, end, pfactory);
String name = el.getAttribute(ClangXML.SPACE);
AddressSpace spc = pfactory.getAddressFactory().getAddressSpace(name);
long offset = SpecXmlUtils.decodeLong(el.getAttribute(ClangXML.OFFSET));
blockaddr = spc.getAddress(offset);
public boolean isVariableRef() {
return false;
}
@Override
public Address getMinAddress() {
return blockaddr;
}
@Override
public Address getMaxAddress() {
return blockaddr;
}
@Override
public void decode(Decoder decoder, PcodeFactory pfactory) throws PcodeXMLException {
AddressSpace spc = decoder.readSpace(AttributeId.ATTRIB_SPACE);
long offset = decoder.readUnsignedInteger(AttributeId.ATTRIB_OFF);
blockaddr = spc.getAddress(offset);
super.decode(decoder, pfactory);
}
}

View File

@ -0,0 +1,53 @@
/* ###
* 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.
*/
/*
* Created on Jun 18, 2003
*
* To change the template for this generated file go to
* Window>Preferences>Java>Code Generation>Code and Comments
*/
package ghidra.app.decompiler;
import ghidra.program.model.pcode.*;
public abstract class ClangMarkup { // Placeholder for CLANG XML identifiers
// Attribute values
public static final String KEYWORD_COLOR = "keyword";
public static final String COMMENT_COLOR = "comment";
public static final String TYPE_COLOR = "type";
public static final String FUNCNAME_COLOR = "funcname";
public static final String VARIABLE_COLOR = "var";
public static final String CONST_COLOR = "const";
public static final String PARAMETER_COLOR = "param";
public static final String GLOBAL_COLOR = "global";
public static ClangTokenGroup buildClangTree(Decoder decoder, HighFunction hfunc)
throws PcodeXMLException {
ClangTokenGroup docroot;
int el = decoder.openElement();
if (el == ElementId.ELEM_FUNCTION.getId()) {
docroot = new ClangFunction(null, hfunc);
}
else {
docroot = new ClangTokenGroup(null);
}
docroot.decode(decoder, hfunc);
decoder.closeElement(el);
return docroot;
}
}

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.
@ -22,10 +21,8 @@
*/
package ghidra.app.decompiler;
import ghidra.program.model.address.*;
import ghidra.program.model.address.Address;
import ghidra.program.model.pcode.*;
import ghidra.util.xml.*;
import ghidra.xml.*;
/**
*
@ -41,28 +38,41 @@ public class ClangOpToken extends ClangToken {
super(par);
op = null;
}
@Override
public PcodeOp getPcodeOp() { return op; }
@Override
public Address getMinAddress() {
if (op==null) return null;
return op.getSeqnum().getTarget().getPhysicalAddress();
public PcodeOp getPcodeOp() {
return op;
}
@Override
public Address getMaxAddress() {
if (op==null) return null;
return op.getSeqnum().getTarget().getPhysicalAddress();
}
@Override
public void restoreFromXML(XmlElement el,XmlElement end,PcodeFactory pfactory) {
super.restoreFromXML(el,end,pfactory);
String oprefstring = el.getAttribute(ClangXML.OPREF);
if (oprefstring != null) {
int refid = SpecXmlUtils.decodeInt(oprefstring);
op = pfactory.getOpRef(refid);
public Address getMinAddress() {
if (op == null) {
return null;
}
return op.getSeqnum().getTarget().getPhysicalAddress();
}
@Override
public Address getMaxAddress() {
if (op == null) {
return null;
}
return op.getSeqnum().getTarget().getPhysicalAddress();
}
@Override
public void decode(Decoder decoder, PcodeFactory pfactory) throws PcodeXMLException {
for (;;) {
int attribId = decoder.getNextAttributeId();
if (attribId == 0) {
break;
}
if (attribId == AttributeId.ATTRIB_OPREF.getId()) {
int refid = (int) decoder.readUnsignedInteger();
op = pfactory.getOpRef(refid);
}
}
decoder.rewindAttributes();
super.decode(decoder, pfactory);
}
}

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.
@ -22,11 +21,10 @@
*/
package ghidra.app.decompiler;
import ghidra.program.model.data.*;
import ghidra.program.model.data.DataType;
import ghidra.program.model.pcode.*;
import ghidra.util.*;
import ghidra.util.xml.*;
import ghidra.xml.*;
import ghidra.util.Msg;
/**
*
*
@ -42,25 +40,35 @@ public class ClangReturnType extends ClangTokenGroup {
varnode = null;
datatype = null;
}
public DataType getDataType() { return datatype; }
public Varnode getVarnode() { return varnode; }
public DataType getDataType() {
return datatype;
}
public Varnode getVarnode() {
return varnode;
}
@Override
public void restoreFromXML(XmlPullParser parser,PcodeFactory pfactory) {
XmlElement node = parser.peek();
super.restoreFromXML(parser,pfactory);
String varrefstring = node.getAttribute(ClangXML.VARNODEREF);
if (varrefstring != null) {
int refid = SpecXmlUtils.decodeInt(varrefstring);
varnode = pfactory.getRef(refid);
if (varnode != null) {
if (varnode.getHigh() == null) {
Msg.warn(this, "VOID high variable problem at " + varnode.getAddress());
return;
public void decode(Decoder decoder, PcodeFactory pfactory) throws PcodeXMLException {
for (;;) {
int attribId = decoder.getNextAttributeId();
if (attribId == 0) {
break;
}
if (attribId == AttributeId.ATTRIB_VARREF.getId()) {
int refid = (int) decoder.readUnsignedInteger();
varnode = pfactory.getRef(refid);
if (varnode != null) {
if (varnode.getHigh() == null) {
Msg.warn(this, "VOID high variable problem at " + varnode.getAddress());
return;
}
datatype = varnode.getHigh().getDataType();
}
datatype = varnode.getHigh().getDataType();
break;
}
}
super.decode(decoder, pfactory);
}
}

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.
@ -23,8 +22,7 @@
package ghidra.app.decompiler;
import ghidra.program.model.pcode.*;
import ghidra.util.xml.*;
import ghidra.xml.*;
/**
*
*
@ -40,16 +38,28 @@ import ghidra.xml.*;
public class ClangStatement extends ClangTokenGroup {
private PcodeOp op; // Root op of C-statement
public ClangStatement(ClangNode par) { super(par); op = null; }
public PcodeOp getPcodeOp() { return op; }
public ClangStatement(ClangNode par) {
super(par);
op = null;
}
public PcodeOp getPcodeOp() {
return op;
}
@Override
public void restoreFromXML(XmlPullParser parser,PcodeFactory pfactory) {
XmlElement node = parser.peek();
String oprefstring = node.getAttribute(ClangXML.OPREF);
if (oprefstring != null) {
int refid = SpecXmlUtils.decodeInt(oprefstring);
op = pfactory.getOpRef(refid);
public void decode(Decoder decoder, PcodeFactory pfactory) throws PcodeXMLException {
for (;;) {
int attribId = decoder.getNextAttributeId();
if (attribId == 0) {
break;
}
if (attribId == AttributeId.ATTRIB_OPREF.getId()) {
int refid = (int) decoder.readUnsignedInteger();
op = pfactory.getOpRef(refid);
break;
}
}
super.restoreFromXML(parser,pfactory);
super.decode(decoder, pfactory);
}
}

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.
@ -23,8 +22,6 @@
package ghidra.app.decompiler;
import ghidra.program.model.pcode.*;
import ghidra.util.xml.*;
import ghidra.xml.*;
/**
*
@ -33,38 +30,54 @@ import ghidra.xml.*;
* A SyntaxToken may be or may include spacing
*/
public class ClangSyntaxToken extends ClangToken {
private int open,close;
private int open, close;
public ClangSyntaxToken(ClangNode par) {
super(par);
open = close = -1;
}
public ClangSyntaxToken(ClangNode par,String txt) {
super(par,txt);
public ClangSyntaxToken(ClangNode par, String txt) {
super(par, txt);
open = close = -1;
}
public ClangSyntaxToken(ClangNode par,String txt,String col) {
super(par,txt,col);
public ClangSyntaxToken(ClangNode par, String txt, String col) {
super(par, txt, col);
open = close = -1;
}
@Override
public boolean isVariableRef() {
if (Parent() instanceof ClangVariableDecl) return true;
return false;
public boolean isVariableRef() {
if (Parent() instanceof ClangVariableDecl) {
return true;
}
return false;
}
@Override
public void restoreFromXML(XmlElement el,XmlElement end,PcodeFactory pfactory) {
super.restoreFromXML(el,end,pfactory);
String str = el.getAttribute("open");
if (str != null)
open = SpecXmlUtils.decodeInt(str);
str = el.getAttribute("close");
if (str != null)
close = SpecXmlUtils.decodeInt(str);
public void decode(Decoder decoder, PcodeFactory pfactory) throws PcodeXMLException {
for (;;) {
int attribId = decoder.getNextAttributeId();
if (attribId == 0) {
break;
}
if (attribId == AttributeId.ATTRIB_OPEN.getId()) {
open = (int) decoder.readSignedInteger();
}
else if (attribId == AttributeId.ATTRIB_CLOSE.getId()) {
close = (int) decoder.readSignedInteger();
}
}
decoder.rewindAttributes();
super.decode(decoder, pfactory);
}
public int getOpen() {
return open;
}
public int getClose() {
return close;
}
public int getOpen() { return open; }
public int getClose() { return close; }
}

View File

@ -27,8 +27,6 @@ import java.util.List;
//import ghidra.app.plugin.core.decompile.*;
import ghidra.program.model.address.Address;
import ghidra.program.model.pcode.*;
import ghidra.xml.XmlElement;
import ghidra.xml.XmlPullParser;
/**
*
@ -154,9 +152,19 @@ public class ClangToken implements ClangNode {
this.text = text;
}
public void restoreFromXML(XmlElement el, XmlElement end, PcodeFactory pfactory) {
text = end.getText();
String col = el.getAttribute(ClangXML.COLOR);
public void decode(Decoder decoder, PcodeFactory pfactory) throws PcodeXMLException {
String col = null;
for (;;) {
int attribId = decoder.getNextAttributeId();
if (attribId == 0) {
break;
}
if (attribId == AttributeId.ATTRIB_COLOR.getId()) {
col = decoder.readString();
break;
}
}
text = decoder.readString(AttributeId.ATTRIB_CONTENT);
syntax_type = getColor(col);
}
@ -165,70 +173,67 @@ public class ClangToken implements ClangNode {
list.add(this);
}
static public ClangToken buildToken(ClangNode par, XmlPullParser parser,
PcodeFactory pfactory) {
XmlElement node =
parser.start(ClangXML.VARIABLE, ClangXML.OP, ClangXML.SYNTAX, ClangXML.BREAK,
ClangXML.FUNCNAME, ClangXML.TYPE, ClangXML.COMMENT, ClangXML.LABEL, ClangXML.FIELD);
static public ClangToken buildToken(int node, ClangNode par, Decoder decoder,
PcodeFactory pfactory) throws PcodeXMLException {
ClangToken token = null;
if (node.getName().equals(ClangXML.VARIABLE)) {
if (node == ElementId.ELEM_VARIABLE.getId()) {
token = new ClangVariableToken(par);
}
else if (node.getName().equals(ClangXML.OP)) {
else if (node == ElementId.ELEM_OP.getId()) {
token = new ClangOpToken(par);
}
else if (node.getName().equals(ClangXML.SYNTAX)) {
else if (node == ElementId.ELEM_SYNTAX.getId()) {
token = new ClangSyntaxToken(par);
}
else if (node.getName().equals(ClangXML.BREAK)) {
else if (node == ElementId.ELEM_BREAK.getId()) {
token = new ClangBreak(par);
}
else if (node.getName().equals(ClangXML.FUNCNAME)) {
else if (node == ElementId.ELEM_FUNCNAME.getId()) {
token = new ClangFuncNameToken(par, null);
}
else if (node.getName().equals(ClangXML.TYPE)) {
else if (node == ElementId.ELEM_TYPE.getId()) {
token = new ClangTypeToken(par);
}
else if (node.getName().equals(ClangXML.COMMENT)) {
else if (node == ElementId.ELEM_COMMENT.getId()) {
token = new ClangCommentToken(par);
}
else if (node.getName().equals(ClangXML.LABEL)) {
else if (node == ElementId.ELEM_LABEL.getId()) {
token = new ClangLabelToken(par);
}
else if (node.getName().equals(ClangXML.FIELD)) {
else if (node == ElementId.ELEM_FIELD.getId()) {
token = new ClangFieldToken(par);
}
XmlElement end = parser.end(node);
if (token != null) {
token.restoreFromXML(node, end, pfactory);
else {
throw new PcodeXMLException("Expecting token element");
}
token.decode(decoder, pfactory);
return token;
}
public static int getColor(String col) {
if (col != null) {
if (col.equals(ClangXML.KEYWORD_COLOR)) {
if (col.equals(ClangMarkup.KEYWORD_COLOR)) {
return KEYWORD_COLOR;
}
else if (col.equals(ClangXML.VARIABLE_COLOR)) {
else if (col.equals(ClangMarkup.VARIABLE_COLOR)) {
return VARIABLE_COLOR;
}
else if (col.equals(ClangXML.CONST_COLOR)) {
else if (col.equals(ClangMarkup.CONST_COLOR)) {
return CONST_COLOR;
}
else if (col.equals(ClangXML.PARAMETER_COLOR)) {
else if (col.equals(ClangMarkup.PARAMETER_COLOR)) {
return PARAMETER_COLOR;
}
else if (col.equals(ClangXML.GLOBAL_COLOR)) {
else if (col.equals(ClangMarkup.GLOBAL_COLOR)) {
return GLOBAL_COLOR;
}
else if (col.equals(ClangXML.TYPE_COLOR)) {
else if (col.equals(ClangMarkup.TYPE_COLOR)) {
return TYPE_COLOR;
}
else if (col.equals(ClangXML.COMMENT_COLOR)) {
else if (col.equals(ClangMarkup.COMMENT_COLOR)) {
return COMMENT_COLOR;
}
else if (col.equals(ClangXML.FUNCNAME_COLOR)) {
else if (col.equals(ClangMarkup.FUNCNAME_COLOR)) {
return FUNCTION_COLOR;
}
}

View File

@ -20,9 +20,7 @@ import java.util.*;
import java.util.stream.Stream;
import ghidra.program.model.address.Address;
import ghidra.program.model.pcode.PcodeFactory;
import ghidra.xml.XmlElement;
import ghidra.xml.XmlPullParser;
import ghidra.program.model.pcode.*;
/**
* A node in a tree of C code tokens.
@ -106,44 +104,43 @@ public class ClangTokenGroup implements ClangNode, Iterable<ClangNode> {
}
}
public void restoreFromXML(XmlPullParser parser, PcodeFactory pfactory) {
XmlElement node = parser.start(ClangXML.FUNCTION, ClangXML.RETURN_TYPE, ClangXML.VARDECL,
ClangXML.STATEMENT, ClangXML.FUNCPROTO, ClangXML.BLOCK, ClangXML.VARIABLE, ClangXML.OP,
ClangXML.SYNTAX, ClangXML.BREAK, ClangXML.FUNCNAME, ClangXML.TYPE, ClangXML.COMMENT,
ClangXML.LABEL);
while (parser.peek().isStart()) {
XmlElement elem = parser.peek();
if (elem.getName().equals(ClangXML.RETURN_TYPE)) {
public void decode(Decoder decoder, PcodeFactory pfactory) throws PcodeXMLException {
for (;;) {
int elem = decoder.openElement();
if (elem == 0) {
break;
}
if (elem == ElementId.ELEM_RETURN_TYPE.getId()) {
ClangReturnType child = new ClangReturnType(this);
child.restoreFromXML(parser, pfactory);
child.decode(decoder, pfactory);
AddTokenGroup(child);
}
else if (elem.getName().equals(ClangXML.VARDECL)) {
else if (elem == ElementId.ELEM_VARDECL.getId()) {
ClangVariableDecl child = new ClangVariableDecl(this);
child.restoreFromXML(parser, pfactory);
child.decode(decoder, pfactory);
AddTokenGroup(child);
}
else if (elem.getName().equals(ClangXML.STATEMENT)) {
else if (elem == ElementId.ELEM_STATEMENT.getId()) {
ClangStatement child = new ClangStatement(this);
child.restoreFromXML(parser, pfactory);
child.decode(decoder, pfactory);
AddTokenGroup(child);
}
else if (elem.getName().equals(ClangXML.FUNCPROTO)) {
else if (elem == ElementId.ELEM_FUNCPROTO.getId()) {
ClangFuncProto child = new ClangFuncProto(this);
child.restoreFromXML(parser, pfactory);
child.decode(decoder, pfactory);
AddTokenGroup(child);
}
else if (elem.getName().equals(ClangXML.BLOCK)) {
else if (elem == ElementId.ELEM_BLOCK.getId()) {
ClangTokenGroup child = new ClangTokenGroup(this);
child.restoreFromXML(parser, pfactory);
child.decode(decoder, pfactory);
AddTokenGroup(child);
}
else {
ClangToken tok = ClangToken.buildToken(this, parser, pfactory);
ClangToken tok = ClangToken.buildToken(elem, this, decoder, pfactory);
AddTokenGroup(tok);
}
decoder.closeElement(elem);
}
parser.end(node);
}
private boolean isLetterDigitOrUnderscore(char c) {

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.
@ -22,9 +21,9 @@
*/
package ghidra.app.decompiler;
import ghidra.program.model.data.*;
import ghidra.program.model.data.DataType;
import ghidra.program.model.pcode.*;
import ghidra.xml.*;
/**
*
*
@ -38,20 +37,34 @@ public class ClangTypeToken extends ClangToken {
super(par);
datatype = null;
}
@Override
public boolean isVariableRef() {
if (Parent() instanceof ClangVariableDecl) return true;
return false;
public boolean isVariableRef() {
if (Parent() instanceof ClangVariableDecl) {
return true;
}
return false;
}
public DataType getDataType() {
return datatype;
}
@Override
public void restoreFromXML(XmlElement el,XmlElement end,PcodeFactory pfactory) {
super.restoreFromXML(el,end,pfactory);
datatype = pfactory.getDataTypeManager().findBaseType(getText(),el.getAttribute("id"));
public void decode(Decoder decoder, PcodeFactory pfactory) throws PcodeXMLException {
int id = 0;
for (;;) {
int attribId = decoder.getNextAttributeId();
if (attribId == 0) {
break;
}
if (attribId == AttributeId.ATTRIB_ID.getId()) {
id = (int) decoder.readUnsignedInteger();
break;
}
}
decoder.rewindAttributes();
super.decode(decoder, pfactory);
datatype = pfactory.getDataTypeManager().findBaseType(getText(), id);
}
}

View File

@ -24,9 +24,6 @@ package ghidra.app.decompiler;
import ghidra.program.model.data.DataType;
import ghidra.program.model.pcode.*;
import ghidra.util.Msg;
import ghidra.util.xml.SpecXmlUtils;
import ghidra.xml.XmlElement;
import ghidra.xml.XmlPullParser;
/**
*
@ -54,10 +51,9 @@ public class ClangVariableDecl extends ClangTokenGroup {
}
@Override
public void restoreFromXML(XmlPullParser parser, PcodeFactory pfactory) {
XmlElement node = parser.peek();
super.restoreFromXML(parser, pfactory);
long symref = SpecXmlUtils.decodeLong(node.getAttribute(ClangXML.SYMREF));
public void decode(Decoder decoder, PcodeFactory pfactory) throws PcodeXMLException {
long symref = decoder.readUnsignedInteger(AttributeId.ATTRIB_SYMREF);
super.decode(decoder, pfactory);
HighSymbol sym = pfactory.getSymbol(symref);
if (sym == null) {
Msg.error(this, "Invalid symbol reference: " + symref + " in " + Parent());

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.
@ -22,10 +21,9 @@
*/
package ghidra.app.decompiler;
import ghidra.program.model.address.*;
import ghidra.program.model.address.Address;
import ghidra.program.model.pcode.*;
import ghidra.util.xml.*;
import ghidra.xml.*;
/**
*
*
@ -34,40 +32,46 @@ import ghidra.xml.*;
public class ClangVariableToken extends ClangToken {
private Varnode varnode;
private PcodeOp op;
public ClangVariableToken(ClangNode par) {
super(par);
varnode = null;
op = null;
}
@Override
public Varnode getVarnode() {
public Varnode getVarnode() {
return varnode;
}
@Override
public PcodeOp getPcodeOp() {
return op;
}
@Override
public boolean isVariableRef() {
public boolean isVariableRef() {
return true;
}
@Override
public Address getMinAddress() {
if (op==null) return null;
public Address getMinAddress() {
if (op == null) {
return null;
}
return op.getSeqnum().getTarget().getPhysicalAddress();
}
@Override
public Address getMaxAddress() {
if (op==null) return null;
public Address getMaxAddress() {
if (op == null) {
return null;
}
return op.getSeqnum().getTarget().getPhysicalAddress();
}
@Override
public HighVariable getHighVariable() {
public HighVariable getHighVariable() {
Varnode inst = getVarnode();
if (inst != null) {
HighVariable hvar = inst.getHigh();
@ -80,19 +84,24 @@ public class ClangVariableToken extends ClangToken {
}
return super.getHighVariable();
}
@Override
public void restoreFromXML(XmlElement el,XmlElement end,PcodeFactory pfactory) {
super.restoreFromXML(el,end,pfactory);
String varrefstring = el.getAttribute(ClangXML.VARNODEREF);
if (varrefstring != null) {
int refid = SpecXmlUtils.decodeInt(varrefstring);
varnode = pfactory.getRef(refid);
}
String oprefstring = el.getAttribute(ClangXML.OPREF);
if (oprefstring != null) {
int refid = SpecXmlUtils.decodeInt(oprefstring);
op = pfactory.getOpRef(refid);
public void decode(Decoder decoder, PcodeFactory pfactory) throws PcodeXMLException {
for (;;) {
int attribId = decoder.getNextAttributeId();
if (attribId == 0) {
break;
}
if (attribId == AttributeId.ATTRIB_VARREF.getId()) {
int refid = (int) decoder.readUnsignedInteger();
varnode = pfactory.getRef(refid);
}
else if (attribId == AttributeId.ATTRIB_OPREF.getId()) {
int refid = (int) decoder.readUnsignedInteger();
op = pfactory.getOpRef(refid);
}
}
decoder.rewindAttributes();
super.decode(decoder, pfactory);
}
}

View File

@ -1,82 +0,0 @@
/* ###
* 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.
*/
/*
* Created on Jun 18, 2003
*
* To change the template for this generated file go to
* Window>Preferences>Java>Code Generation>Code and Comments
*/
package ghidra.app.decompiler;
import ghidra.program.model.pcode.*;
import ghidra.xml.*;
/**
*
*
* To change the template for this generated type comment go to
*{@literal Window>Preferences>Java>Code Generation>Code and Comments}
*/
public abstract class ClangXML { // Placeholder for CLANG XML identifiers
public static final String DOCUMENT = "clang_document";
public static final String FUNCTION = "function";
public static final String BLOCK = "block";
public static final String RETURN_TYPE = "return_type";
public static final String VARDECL = "vardecl";
public static final String STATEMENT = "statement";
public static final String FUNCPROTO = "funcproto";
public static final String SYNTAX = "syntax";
public static final String BREAK = "break";
public static final String VARIABLE = "variable";
public static final String OP = "op";
public static final String FUNCNAME="funcname";
public static final String TYPE = "type";
public static final String FIELD = "field";
public static final String COMMENT = "comment";
public static final String LABEL = "label";
// Attributes
public static final String INDENT="indent";
public static final String COLOR="color";
public static final String OPREF = "opref";
public static final String BLOCKREF = "blockref";
public static final String VARNODEREF="varref";
public static final String SPACE="space";
public static final String OFFSET="off";
public static final String PCSPACE="pcspace";
public static final String PCOFFSET="pcoff";
public static final String SYMREF="symref";
// Attribute values
public static final String KEYWORD_COLOR = "keyword";
public static final String COMMENT_COLOR ="comment";
public static final String TYPE_COLOR = "type";
public static final String FUNCNAME_COLOR = "funcname";
public static final String VARIABLE_COLOR = "var";
public static final String CONST_COLOR = "const";
public static final String PARAMETER_COLOR = "param";
public static final String GLOBAL_COLOR = "global";
public static ClangTokenGroup buildClangTree(XmlPullParser parser,HighFunction hfunc) {
ClangTokenGroup docroot;
if (parser.peek().getName().equals("function"))
docroot = new ClangFunction(null,hfunc);
else
docroot = new ClangTokenGroup(null);
docroot.restoreFromXML(parser,hfunc);
return docroot;
}
}

View File

@ -34,7 +34,6 @@ import ghidra.program.model.listing.Program;
import ghidra.program.model.pcode.*;
import ghidra.util.task.CancelledListener;
import ghidra.util.task.TaskMonitor;
import ghidra.xml.XmlPullParser;
/**
* This is a self-contained interface to a single decompile
@ -669,10 +668,10 @@ public class DecompInterface {
timeoutSecs);
decompileMessage = decompCallback.getNativeMessage();
if (res != null) {
XmlPullParser parser = HighFunction.stringTree(res.getInputStream(),
HighFunction.getErrorHandler(this, "Results for structureGraph command"));
XmlDecode decoder = new XmlDecode(factory);
decoder.ingestStream(res.getInputStream(), "structureGraph results");
resgraph = new BlockGraph();
resgraph.restoreXml(parser, factory);
resgraph.restoreXml(decoder);
resgraph.transferObjectRef(ingraph);
}
}

View File

@ -80,6 +80,7 @@ public class DecompileCallback {
private Charset utf8Charset;
private String nativeMessage;
private XmlDecodeLight lightDecoder;
private InstructionBlock lastPseudoInstructionBlock;
private Disassembler pseudoDisassembler;
@ -96,6 +97,7 @@ public class DecompileCallback {
nativeMessage = null;
debug = null;
utf8Charset = Charset.availableCharsets().get(CharsetInfo.UTF8);
lightDecoder = new XmlDecodeLight(addrfactory);
}
private static SAXParser getSAXParser() throws PcodeXMLException {
@ -170,8 +172,10 @@ public class DecompileCallback {
public byte[] getBytes(String addrxml) {
try {
Address addr = AddressXML.readXML(addrxml, addrfactory);
int size = AddressXML.readXMLSize(addrxml);
lightDecoder.ingestString(addrxml);
lightDecoder.openElement();
Address addr = AddressXML.decodeFromAttributes(lightDecoder);
int size = (int) lightDecoder.readSignedInteger(AttributeId.ATTRIB_SIZE);
if (overlaySpace != null) {
addr = overlaySpace.getOverlayAddress(addr);
}
@ -220,7 +224,8 @@ public class DecompileCallback {
Address addr;
int flags;
try {
addr = AddressXML.readXML(addrstring, addrfactory);
lightDecoder.ingestString(addrstring);
addr = AddressXML.decode(lightDecoder);
if (overlaySpace != null) {
addr = overlaySpace.getOverlayAddress(addr);
}
@ -263,7 +268,8 @@ public class DecompileCallback {
public PackedBytes getPcodePacked(String addrstring) {
Address addr = null;
try {
addr = AddressXML.readXML(addrstring, addrfactory);
lightDecoder.ingestString(addrstring);
addr = AddressXML.decode(lightDecoder);
if (overlaySpace != null) {
addr = overlaySpace.getOverlayAddress(addr);
}
@ -351,7 +357,8 @@ public class DecompileCallback {
InjectContext con = snippetLibrary.buildInjectContext();
PcodeOp[] pcode;
try {
con.restoreXml(getSAXParser(), context, addrfactory);
lightDecoder.ingestString(context);
con.decode(lightDecoder);
}
catch (PcodeXMLException e) {
Msg.error(this, "Decompiling " + funcEntry + ": " + e.getMessage());
@ -484,7 +491,8 @@ public class DecompileCallback {
public String getSymbol(String addrstring) { // Return first symbol name at this address
Address addr;
try {
addr = AddressXML.readXML(addrstring, addrfactory);
lightDecoder.ingestString(addrstring);
addr = AddressXML.decode(lightDecoder);
if (overlaySpace != null) {
addr = overlaySpace.getOverlayAddress(addr);
}
@ -701,7 +709,8 @@ public class DecompileCallback {
public String getMappedSymbolsXML(String addrstring) { // Return XML describing data or functions at addr
Address addr;
try {
addr = AddressXML.readXML(addrstring, addrfactory);
lightDecoder.ingestString(addrstring);
addr = AddressXML.decode(lightDecoder);
if (overlaySpace != null) {
addr = overlaySpace.getOverlayAddress(addr);
}
@ -746,7 +755,8 @@ public class DecompileCallback {
public String getExternalRefXML(String addrstring) { // Return any external reference at addr
Address addr;
try {
addr = AddressXML.readXML(addrstring, addrfactory);
lightDecoder.ingestString(addrstring);
addr = AddressXML.decode(lightDecoder);
if (overlaySpace != null) {
addr = overlaySpace.getOverlayAddress(addr);
}
@ -809,8 +819,8 @@ public class DecompileCallback {
return null;
}
public String getType(String name, String idstr) {
DataType type = dtmanage.findBaseType(name, idstr);
public String getType(String name, long id) {
DataType type = dtmanage.findBaseType(name, id);
if (type == null) {
return null;
}
@ -836,9 +846,10 @@ public class DecompileCallback {
public String getRegisterName(String addrstring) {
try {
Address addr = AddressXML.readXML(addrstring, addrfactory);
int size = AddressXML.readXMLSize(addrstring);
lightDecoder.ingestString(addrstring);
lightDecoder.openElement();
Address addr = AddressXML.decodeFromAttributes(lightDecoder);
int size = (int) lightDecoder.readSignedInteger(AttributeId.ATTRIB_SIZE);
Register reg = pcodelanguage.getRegister(addr, size);
if (reg == null) {
return null;
@ -855,7 +866,8 @@ public class DecompileCallback {
public String getTrackedRegisters(String addrstring) {
Address addr;
try {
addr = AddressXML.readXML(addrstring, addrfactory);
lightDecoder.ingestString(addrstring);
addr = AddressXML.decode(lightDecoder);
if (overlaySpace != null) {
addr = overlaySpace.getOverlayAddress(addr);
}
@ -1312,12 +1324,14 @@ public class DecompileCallback {
* @param dtId is the id associated with the character data-type
* @return the UTF8 encoded byte array or null
*/
public StringData getStringData(String addrString, String dtName, String dtId) {
public StringData getStringData(String addrString, String dtName, long dtId) {
Address addr;
int maxChars;
try {
addr = AddressXML.readXML(addrString, addrfactory);
maxChars = AddressXML.readXMLSize(addrString);
lightDecoder.ingestString(addrString);
lightDecoder.openElement();
addr = AddressXML.decodeFromAttributes(lightDecoder);
maxChars = (int) lightDecoder.readSignedInteger(AttributeId.ATTRIB_SIZE);
if (overlaySpace != null) {
addr = overlaySpace.getOverlayAddress(addr);
}

View File

@ -22,6 +22,7 @@ import ghidra.program.model.lang.PackedBytes;
import ghidra.util.Msg;
import ghidra.util.timer.GTimer;
import ghidra.util.timer.GTimerMonitor;
import ghidra.util.xml.SpecXmlUtils;
/**
*
@ -787,7 +788,7 @@ public class DecompileProcess {
private void getType() throws IOException {
String name = readQueryString();
String id = readQueryString();
long id = SpecXmlUtils.decodeLong(readQueryString());
String res = callback.getType(name, id);
write(query_response_start);
if ((res != null) && (res.length() != 0)) {
@ -816,7 +817,7 @@ public class DecompileProcess {
private void getStringData() throws IOException {
String addr = readQueryString();
String dtName = readQueryString();
String dtId = readQueryString();
long dtId = SpecXmlUtils.decodeLong(readQueryString());
DecompileCallback.StringData stringData = callback.getStringData(addr, dtName, dtId);
write(query_response_start);
if (stringData != null) {

View File

@ -21,8 +21,6 @@ import ghidra.program.model.lang.CompilerSpec;
import ghidra.program.model.lang.Language;
import ghidra.program.model.listing.Function;
import ghidra.program.model.pcode.*;
import ghidra.xml.XmlElement;
import ghidra.xml.XmlPullParser;
/**
* Class for getting at the various structures returned
@ -75,7 +73,7 @@ public class DecompileResults {
hparamid = null;
docroot = null;
//dumpResults(raw);
parseRawString(raw);
decodeStream(raw);
}
// private void dumpResults(String raw) {
@ -203,63 +201,57 @@ public class DecompileResults {
return printer.print(true);
}
private void parseRawString(InputStream rawxml) {
if (rawxml == null) {
private void decodeStream(InputStream rawstream) {
if (rawstream == null) {
return;
}
XmlPullParser parser = null;
XmlDecode decoder = new XmlDecode(function.getProgram().getAddressFactory());
try {
try {
parser =
HighFunction.stringTree(
rawxml,
HighFunction.getErrorHandler(this, "decompiler results for function at " +
function.getEntryPoint()));
hfunc = null;
hparamid = null;
docroot = null;
parser.start("doc");
while(parser.peek().isStart()) {
XmlElement el = parser.peek();
if (el.getName().equals("function")) {
if (hfunc == null) {
hfunc = new HighFunction(function, language, compilerSpec, dtmanage);
hfunc.readXML(parser);
}
else { // TODO: This is an ugly kludge to get around duplicate XML tag names
docroot = ClangXML.buildClangTree(parser, hfunc);
if (docroot == null) {
errMsg = "Unable to parse C (xml)";
}
}
decoder.ingestStream(rawstream,
"Decompiler results for function at " + function.getEntryPoint());
hfunc = null;
hparamid = null;
docroot = null;
int docel = decoder.openElement(ElementId.ELEM_DOC);
for (;;) {
int el = decoder.peekElement();
if (el == 0) {
break;
}
if (el == ElementId.ELEM_FUNCTION.getId()) {
if (hfunc == null) {
hfunc = new HighFunction(function, language, compilerSpec, dtmanage);
hfunc.decode(decoder);
}
else if (el.getName().equals("parammeasures")) {
hparamid = new HighParamID(function, language, compilerSpec, dtmanage);
hparamid.readXML(parser);
}
else {
errMsg = "Unknown decompiler tag: "+el.getName();
return;
else { // TODO: This is an ugly kludge to get around duplicate XML tag names
docroot = ClangMarkup.buildClangTree(decoder, hfunc);
if (docroot == null) {
errMsg = "Unable to decode C markup";
}
}
}
else if (el == ElementId.ELEM_PARAMMEASURES.getId()) {
hparamid = new HighParamID(function, language, compilerSpec, dtmanage);
hparamid.decode(decoder);
}
else {
errMsg = "Unknown decompiler tag";
return;
}
}
catch (PcodeXMLException e) { // Error while walking the DOM
errMsg = e.getMessage();
hfunc = null;
hparamid = null;
return;
}
catch (RuntimeException e) { // Exception from the raw parser
errMsg = e.getMessage();
hfunc = null;
hparamid = null;
return;
}
decoder.closeElement(docel);
}
finally {
if (parser != null) {
parser.dispose();
}
catch (PcodeXMLException e) { // Error while walking the DOM
errMsg = e.getMessage();
hfunc = null;
hparamid = null;
return;
}
catch (RuntimeException e) { // Exception from the raw parser
errMsg = e.getMessage();
hfunc = null;
hparamid = null;
return;
}
}
}

View File

@ -340,7 +340,7 @@ public class ClangLayoutController implements LayoutModel, LayoutModelListener {
ClangTokenGroup line = new ClangTokenGroup(docroot);
ClangBreak lineBreak = new ClangBreak(line, 1);
ClangSyntaxToken message =
new ClangSyntaxToken(line, errline, ClangXML.COMMENT_COLOR);
new ClangSyntaxToken(line, errline, ClangMarkup.COMMENT_COLOR);
line.AddTokenGroup(lineBreak);
line.AddTokenGroup(message);
docroot.AddTokenGroup(line);

View File

@ -15,73 +15,13 @@
*/
package ghidra.program.model.lang;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import javax.xml.parsers.SAXParser;
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressFactory;
import ghidra.program.model.pcode.*;
import ghidra.util.xml.SpecXmlUtils;
public class InjectContext {
private class Handler extends DefaultHandler {
private AddressFactory addrFactory;
private Address curaddr;
private int state;
Handler(AddressFactory adFact) {
super();
state = 0;
addrFactory = adFact;
}
@Override
public void startElement(String uri, String localName, String rawName, Attributes attr)
throws SAXException {
if (rawName.equals("context")) {
state = 1;
}
else if (rawName.equals("input")) {
inputlist = new ArrayList<>();
state = 3;
}
else if (rawName.equals("output")) {
output = new ArrayList<>();
state = 4;
}
else if (rawName.equals("addr")) {
curaddr = AddressXML.readXML(rawName, attr, addrFactory);
if (state == 1) {
baseAddr = curaddr;
state = 2;
}
else if (state == 2) {
callAddr = curaddr;
}
else if (state == 3) {
int size = SpecXmlUtils.decodeInt(attr.getValue("size"));
Varnode vn = new Varnode(curaddr, size);
inputlist.add(vn);
}
else if (state == 4) {
int size = SpecXmlUtils.decodeInt(attr.getValue("size"));
Varnode vn = new Varnode(curaddr, size);
output.add(vn);
}
}
else {
throw new SAXException("Unrecognized inject tag: " + rawName);
}
}
}
public SleighLanguage language;
public Address baseAddr; // Base address of op (call,userop) causing the inject
@ -94,18 +34,44 @@ public class InjectContext {
public InjectContext() {
}
public void restoreXml(SAXParser parser, String xml, AddressFactory addrFactory)
throws PcodeXMLException {
Handler handler = new Handler(addrFactory);
try {
parser.parse(new InputSource(new StringReader(xml)), handler);
public void decode(Decoder decoder) throws PcodeXMLException {
int el = decoder.openElement(ElementId.ELEM_CONTEXT);
baseAddr = AddressXML.decode(decoder);
callAddr = AddressXML.decode(decoder);
int subel = decoder.peekElement();
if (subel == ElementId.ELEM_INPUT.getId()) {
decoder.openElement();
inputlist = new ArrayList<>();
for (;;) {
int addrel = decoder.peekElement();
if (addrel == 0) {
break;
}
decoder.openElement();
Address addr = AddressXML.decodeFromAttributes(decoder);
int size = (int) decoder.readSignedInteger(AttributeId.ATTRIB_SIZE);
decoder.closeElement(addrel);
inputlist.add(new Varnode(addr, size));
}
decoder.closeElement(subel);
subel = decoder.peekElement();
}
catch (SAXException e) {
throw new PcodeXMLException("Problem parsing inject context: " + e.getMessage());
if (subel == ElementId.ELEM_OUTPUT.getId()) {
decoder.openElement();
output = new ArrayList<>();
for (;;) {
int addrel = decoder.peekElement();
if (addrel == 0) {
break;
}
decoder.openElement();
Address addr = AddressXML.decodeFromAttributes(decoder);
int size = (int) decoder.readSignedInteger(AttributeId.ATTRIB_SIZE);
decoder.closeElement(addrel);
output.add(new Varnode(addr, size));
}
decoder.closeElement(subel);
}
catch (IOException e) {
throw new PcodeXMLException("Problem parsing inject context: " + e.getMessage());
}
decoder.closeElement(el);
}
}

View File

@ -17,9 +17,8 @@ package ghidra.program.model.pcode;
import java.util.ArrayList;
import org.xml.sax.Attributes;
import ghidra.program.model.address.*;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSpace;
import ghidra.program.model.lang.*;
import ghidra.util.xml.SpecXmlUtils;
import ghidra.xml.XmlElement;
@ -358,155 +357,74 @@ public class AddressXML {
}
/**
* Parse String containing an XML tag representing an Address.
* The format options are simple enough that we don't try to invoke
* an actual XML parser but just walk the string. This recognizes
* - \<addr>
* - \<spaceid> or
* - any tag with a "space" and "offset" attribute
*
* @param addrstring is the string containing the XML tag
* @param addrfactory is the factory that can produce addresses
* @return the created Address or Address.NO_ADDRESS in some special cases
* @throws PcodeXMLException for a badly formed Address
* Create an address from "space" and "offset" attributes of the current element
* @param decoder is the stream decoder
* @return the decoded Address
* @throws PcodeXMLException for any problems decoding the stream
*/
public static Address readXML(String addrstring, AddressFactory addrfactory)
throws PcodeXMLException {
int tagstart = addrstring.indexOf('<');
if (tagstart >= 0) {
tagstart += 1;
if (addrstring.startsWith("spaceid", tagstart)) {
tagstart += 8;
int attrstart = addrstring.indexOf("name=\"", tagstart);
if (attrstart >= 0) {
attrstart += 6;
int nameend = addrstring.indexOf('\"', attrstart);
if (nameend >= 0) {
AddressSpace spc =
addrfactory.getAddressSpace(addrstring.substring(attrstart, nameend));
int spaceid = spc.getSpaceID();
spc = addrfactory.getConstantSpace();
return spc.getAddress(spaceid);
}
}
public static Address decodeFromAttributes(Decoder decoder) throws PcodeXMLException {
AddressSpace spc = null;
long offset = -1;
for (;;) {
int attribId = decoder.getNextAttributeId();
if (attribId == 0) {
break;
}
// There are several tag forms where we essentially want to just look for 'space' and 'offset' attributes
// don't explicitly check the tag name
int spacestart = addrstring.indexOf("space=\"");
if (spacestart >= 4) {
spacestart += 7;
int spaceend = addrstring.indexOf('"', spacestart);
if (spaceend >= spacestart) {
String spcname = addrstring.substring(spacestart, spaceend);
int offstart = addrstring.indexOf("offset=\"");
if (offstart >= 4) {
offstart += 8;
int offend = addrstring.indexOf('"', offstart);
if (offend >= offstart) {
String offstr = addrstring.substring(offstart, offend);
AddressSpace spc = addrfactory.getAddressSpace(spcname);
// Unknown spaces may result from "spacebase" registers defined in cspec
if (spc == null) {
return Address.NO_ADDRESS;
}
long offset = SpecXmlUtils.decodeLong(offstr);
return spc.getAddress(offset);
}
}
}
if (attribId == AttributeId.ATTRIB_SPACE.getId()) {
spc = decoder.readSpace();
}
else if (attribId == AttributeId.ATTRIB_OFFSET.getId()) {
offset = decoder.readUnsignedInteger();
}
}
throw new PcodeXMLException("Badly formed address: " + addrstring);
}
/**
* Read the (first) size attribute from an XML tag string as an integer
* @param addrxml is the XML string
* @return the decoded integer or zero if the attribute doesn't exist
*/
public static int readXMLSize(String addrxml) {
int attrstart = addrxml.indexOf("size=\"");
if (attrstart >= 4) {
attrstart += 6;
int attrend = addrxml.indexOf('\"', attrstart);
if (attrend > attrstart) {
int size = SpecXmlUtils.decodeInt(addrxml.substring(attrstart, attrend));
return size;
}
}
return 0;
}
/**
* Create an address from an XML parse tree node. This recognizes XML tags
* - \<addr>
* - \<spaceid>
* - \<iop> or
* - any tag with "space" and "offset" attributes
*
* An empty \<addr> tag, with no attributes, results in Address.NO_ADDRESS being returned.
* @param el is the parse tree element
* @param addrFactory address factory used to create valid addresses
* @return Address created from XML info
*/
public static Address readXML(XmlElement el, AddressFactory addrFactory) {
String localName = el.getName();
if (localName.equals("spaceid")) {
AddressSpace spc = addrFactory.getAddressSpace(el.getAttribute("name"));
int spaceid = spc.getSpaceID();
spc = addrFactory.getConstantSpace();
return spc.getAddress(spaceid);
}
else if (localName.equals("iop")) {
int ref = SpecXmlUtils.decodeInt(el.getAttribute("value"));
AddressSpace spc = addrFactory.getConstantSpace();
return spc.getAddress(ref);
}
String space = el.getAttribute("space");
if (space == null) {
return Address.NO_ADDRESS;
}
long offset = SpecXmlUtils.decodeLong(el.getAttribute("offset"));
AddressSpace spc = addrFactory.getAddressSpace(space);
if (spc == null) {
return null;
return Address.NO_ADDRESS;
}
return spc.getAddress(offset);
}
/**
* Read an Address given an XML tag name and its attributes. This recognizes XML tags
* Create an address from a stream encoding. This recognizes elements
* - \<addr>
* - \<spaceid>
* - \<iop>
* - any tag with "space" or "offset" attributes
* - \<iop> or
* - any element with "space" and "offset" attributes
*
* An empty \<addr> tag, with no attributes, results in Address.NO_ADDRESS being returned.
* @param localName is the name of the tag
* @param attr is the collection of attributes for the tag
* @param addrFactory is an Address factory
* @return the scanned address
* An empty \<addr> element, with no attributes, results in Address.NO_ADDRESS being returned.
* @param decoder is the stream decoder
* @return Address created from XML info
* @throws PcodeXMLException for any problems decoding the stream
*/
public static Address readXML(String localName, Attributes attr, AddressFactory addrFactory) {
if (localName.equals("spaceid")) {
AddressSpace spc = addrFactory.getAddressSpace(attr.getValue("name"));
public static Address decode(Decoder decoder) throws PcodeXMLException {
int el = decoder.openElement();
if (el == ElementId.ELEM_SPACEID.getId()) {
AddressSpace spc = decoder.readSpace(AttributeId.ATTRIB_NAME);
decoder.closeElement(el);
int spaceid = spc.getSpaceID();
spc = addrFactory.getConstantSpace();
spc = decoder.getAddressFactory().getConstantSpace();
return spc.getAddress(spaceid);
}
else if (localName.equals("iop")) {
int ref = SpecXmlUtils.decodeInt(attr.getValue("value"));
AddressSpace spc = addrFactory.getConstantSpace();
else if (el == ElementId.ELEM_IOP.getId()) {
int ref = (int) decoder.readUnsignedInteger(AttributeId.ATTRIB_VALUE);
decoder.closeElement(el);
AddressSpace spc = decoder.getAddressFactory().getConstantSpace();
return spc.getAddress(ref);
}
String space = attr.getValue("space");
if (space == null) {
return Address.NO_ADDRESS;
AddressSpace spc = null;
long offset = -1;
for (;;) {
int attribId = decoder.getNextAttributeId();
if (attribId == 0) {
break;
}
if (attribId == AttributeId.ATTRIB_SPACE.getId()) {
spc = decoder.readSpace();
}
else if (attribId == AttributeId.ATTRIB_OFFSET.getId()) {
offset = decoder.readUnsignedInteger();
}
}
long offset = SpecXmlUtils.decodeLong(attr.getValue("offset"));
AddressSpace spc = addrFactory.getAddressSpace(space);
decoder.closeElement(el);
if (spc == null) {
return Address.NO_ADDRESS;
}

View File

@ -0,0 +1,242 @@
/* ###
* 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.program.model.pcode;
import java.util.HashMap;
/**
* An annotation for a data element being transferred to/from a stream
*
* This class parallels the XML concept of an attribute on an element. An AttributeId describes
* a particular piece of data associated with an ElementId. The defining characteristic of the AttributeId is
* its name. Internally this name is associated with an integer id. The name (and id) uniquely determine
* the data being labeled, within the context of a specific ElementId. Within this context, an AttributeId labels either
* - An unsigned integer
* - A signed integer
* - A boolean value
* - A string
*
* The same AttributeId can be used to label a different type of data when associated with a different ElementId.
*/
public class AttributeId {
private static HashMap<String, Integer> lookupAttributeId = new HashMap<>();
private final String name; // The name of the attribute
private final int id; // The (internal) id of the attribute
public AttributeId(String nm, int i) {
name = nm;
id = i;
lookupAttributeId.put(nm, i);
}
public final String getName() {
return name;
}
public final int getId() {
return id;
}
/**
* Find the id associated with a specific attribute name
* @param nm the attribute name
* @return the associated id
*/
public static int find(String nm) {
Integer res = lookupAttributeId.get(nm);
if (res != null) {
return res.intValue();
}
return ATTRIB_UNKNOWN.id;
}
// Common attributes. Attributes with multiple uses
public static final AttributeId ATTRIB_CONTENT = new AttributeId("XMLcontent", 1);
public static final AttributeId ATTRIB_ALIGN = new AttributeId("align", 2);
public static final AttributeId ATTRIB_BIGENDIAN = new AttributeId("bigendian", 3);
public static final AttributeId ATTRIB_CONSTRUCTOR = new AttributeId("constructor", 4);
public static final AttributeId ATTRIB_DESTRUCTOR = new AttributeId("destructor", 5);
public static final AttributeId ATTRIB_EXTRAPOP = new AttributeId("extrapop", 6);
public static final AttributeId ATTRIB_FORMAT = new AttributeId("format", 7);
public static final AttributeId ATTRIB_HIDDENRETPARM = new AttributeId("hiddenretparm", 8);
public static final AttributeId ATTRIB_ID = new AttributeId("id", 9);
public static final AttributeId ATTRIB_INDEX = new AttributeId("index", 10);
public static final AttributeId ATTRIB_INDIRECTSTORAGE = new AttributeId("indirectstorage", 11);
public static final AttributeId ATTRIB_METATYPE = new AttributeId("metatype", 12);
public static final AttributeId ATTRIB_MODEL = new AttributeId("model", 13);
public static final AttributeId ATTRIB_NAME = new AttributeId("name", 14);
public static final AttributeId ATTRIB_NAMELOCK = new AttributeId("namelock", 15);
public static final AttributeId ATTRIB_OFFSET = new AttributeId("offset", 16);
public static final AttributeId ATTRIB_READONLY = new AttributeId("readonly", 17);
public static final AttributeId ATTRIB_REF = new AttributeId("ref", 18);
public static final AttributeId ATTRIB_SIZE = new AttributeId("size", 19);
public static final AttributeId ATTRIB_SPACE = new AttributeId("space", 20);
public static final AttributeId ATTRIB_THISPTR = new AttributeId("thisptr", 21);
public static final AttributeId ATTRIB_TYPE = new AttributeId("type", 22);
public static final AttributeId ATTRIB_TYPELOCK = new AttributeId("typelock", 23);
public static final AttributeId ATTRIB_VAL = new AttributeId("val", 24);
public static final AttributeId ATTRIB_VALUE = new AttributeId("value", 25);
public static final AttributeId ATTRIB_WORDSIZE = new AttributeId("wordsize", 26);
// address
public static final AttributeId ATTRIB_FIRST = new AttributeId("first", 27);
public static final AttributeId ATTRIB_LAST = new AttributeId("last", 28);
public static final AttributeId ATTRIB_UNIQ = new AttributeId("uniq", 29);
// architecture
public static final AttributeId ATTRIB_ADJUSTVMA = new AttributeId("adjustvma", 30);
public static final AttributeId ATTRIB_ENABLE = new AttributeId("enable", 31);
public static final AttributeId ATTRIB_GROUP = new AttributeId("group", 32);
public static final AttributeId ATTRIB_GROWTH = new AttributeId("growth", 33);
public static final AttributeId ATTRIB_LOADERSYMBOLS = new AttributeId("loadersymbols", 34);
public static final AttributeId ATTRIB_PARENT = new AttributeId("parent", 35);
public static final AttributeId ATTRIB_REGISTER = new AttributeId("register", 36);
public static final AttributeId ATTRIB_REVERSEJUSTIFY = new AttributeId("reversejustify", 37);
public static final AttributeId ATTRIB_SIGNEXT = new AttributeId("signext", 38);
public static final AttributeId ATTRIB_STYLE = new AttributeId("style", 39);
// block
public static final AttributeId ATTRIB_ALTINDEX = new AttributeId("altindex", 40);
public static final AttributeId ATTRIB_DEPTH = new AttributeId("depth", 41);
public static final AttributeId ATTRIB_END = new AttributeId("end", 42);
public static final AttributeId ATTRIB_OPCODE = new AttributeId("opcode", 43);
public static final AttributeId ATTRIB_REV = new AttributeId("rev", 44);
// cpool
public static final AttributeId ATTRIB_A = new AttributeId("a", 45);
public static final AttributeId ATTRIB_B = new AttributeId("b", 46);
public static final AttributeId ATTRIB_LENGTH = new AttributeId("length", 47);
public static final AttributeId ATTRIB_TAG = new AttributeId("tag", 48);
// database
public static final AttributeId ATTRIB_CAT = new AttributeId("cat", 49);
public static final AttributeId ATTRIB_FIELD = new AttributeId("field", 50);
public static final AttributeId ATTRIB_MERGE = new AttributeId("merge", 51);
public static final AttributeId ATTRIB_SCOPEIDBYNAME = new AttributeId("scopeidbyname", 52);
public static final AttributeId ATTRIB_VOLATILE = new AttributeId("volatile", 53);
// fspec
public static final AttributeId ATTRIB_CUSTOM = new AttributeId("custom", 54);
public static final AttributeId ATTRIB_DOTDOTDOT = new AttributeId("dotdotdot", 55);
public static final AttributeId ATTRIB_EXTENSION = new AttributeId("extension", 56);
public static final AttributeId ATTRIB_HASTHIS = new AttributeId("hasthis", 57);
public static final AttributeId ATTRIB_INLINE = new AttributeId("inline", 58);
public static final AttributeId ATTRIB_KILLEDBYCALL = new AttributeId("killedbycall", 59);
public static final AttributeId ATTRIB_MAXSIZE = new AttributeId("maxsize", 60);
public static final AttributeId ATTRIB_MINSIZE = new AttributeId("minsize", 61);
public static final AttributeId ATTRIB_MODELLOCK = new AttributeId("modellock", 62);
public static final AttributeId ATTRIB_NORETURN = new AttributeId("noreturn", 63);
public static final AttributeId ATTRIB_POINTERMAX = new AttributeId("pointermax", 64);
public static final AttributeId ATTRIB_SEPARATEFLOAT = new AttributeId("separatefloat", 65);
public static final AttributeId ATTRIB_STACKSHIFT = new AttributeId("stackshift", 66);
public static final AttributeId ATTRIB_STRATEGY = new AttributeId("strategy", 67);
public static final AttributeId ATTRIB_THISBEFORERETPOINTER =
new AttributeId("thisbeforeretpointer", 68);
public static final AttributeId ATTRIB_VOIDLOCK = new AttributeId("voidlock", 69);
// funcdata
public static final AttributeId ATTRIB_NOCODE = new AttributeId("nocode", 70);
// jumptable
public static final AttributeId ATTRIB_LABEL = new AttributeId("label", 71);
public static final AttributeId ATTRIB_NUM = new AttributeId("num", 72);
// pcodeinject
public static final AttributeId ATTRIB_DYNAMIC = new AttributeId("dynamic", 74);
public static final AttributeId ATTRIB_INCIDENTALCOPY = new AttributeId("incidentalcopy", 75);
public static final AttributeId ATTRIB_INJECT = new AttributeId("inject", 76);
public static final AttributeId ATTRIB_PARAMSHIFT = new AttributeId("paramshift", 77);
public static final AttributeId ATTRIB_TARGETOP = new AttributeId("targetop", 78);
// space
public static final AttributeId ATTRIB_BASE = new AttributeId("base", 88);
public static final AttributeId ATTRIB_DEADCODEDELAY = new AttributeId("deadcodedelay", 89);
public static final AttributeId ATTRIB_DELAY = new AttributeId("delay", 90);
public static final AttributeId ATTRIB_LOGICALSIZE = new AttributeId("logicalsize", 91);
public static final AttributeId ATTRIB_PHYSICAL = new AttributeId("physical", 92);
public static final AttributeId ATTRIB_PIECE1 = new AttributeId("piece1", 93);
public static final AttributeId ATTRIB_PIECE2 = new AttributeId("piece2", 94);
public static final AttributeId ATTRIB_PIECE3 = new AttributeId("piece3", 95);
public static final AttributeId ATTRIB_PIECE4 = new AttributeId("piece4", 96);
public static final AttributeId ATTRIB_PIECE5 = new AttributeId("piece5", 97);
public static final AttributeId ATTRIB_PIECE6 = new AttributeId("piece6", 98);
public static final AttributeId ATTRIB_PIECE7 = new AttributeId("piece7", 99);
public static final AttributeId ATTRIB_PIECE8 = new AttributeId("piece8", 100);
public static final AttributeId ATTRIB_PIECE9 = new AttributeId("piece9", 101);
// stringmanage
public static final AttributeId ATTRIB_TRUNC = new AttributeId("trunc", 102);
// transform
public static final AttributeId ATTRIB_VECTOR_LANE_SIZES =
new AttributeId("vector_lane_sizes", 103);
// translate
public static final AttributeId ATTRIB_CODE = new AttributeId("code", 104);
public static final AttributeId ATTRIB_CONTAIN = new AttributeId("contain", 105);
public static final AttributeId ATTRIB_DEFAULTSPACE = new AttributeId("defaultspace", 106);
public static final AttributeId ATTRIB_UNIQBASE = new AttributeId("uniqbase", 107);
// type
public static final AttributeId ATTRIB_ALIGNMENT = new AttributeId("alignment", 108);
public static final AttributeId ATTRIB_ARRAYSIZE = new AttributeId("arraysize", 109);
public static final AttributeId ATTRIB_CHAR = new AttributeId("char", 110);
public static final AttributeId ATTRIB_CORE = new AttributeId("core", 111);
public static final AttributeId ATTRIB_ENUM = new AttributeId("enum", 112);
public static final AttributeId ATTRIB_ENUMSIGNED = new AttributeId("enumsigned", 113);
public static final AttributeId ATTRIB_ENUMSIZE = new AttributeId("enumsize", 114);
public static final AttributeId ATTRIB_INTSIZE = new AttributeId("intsize", 115);
public static final AttributeId ATTRIB_LONGSIZE = new AttributeId("longsize", 116);
public static final AttributeId ATTRIB_OPAQUESTRING = new AttributeId("opaquestring", 117);
public static final AttributeId ATTRIB_SIGNED = new AttributeId("signed", 118);
public static final AttributeId ATTRIB_STRUCTALIGN = new AttributeId("structalign", 119);
public static final AttributeId ATTRIB_UTF = new AttributeId("utf", 120);
public static final AttributeId ATTRIB_VARLENGTH = new AttributeId("varlength", 121);
// userop
public static final AttributeId ATTRIB_FARPOINTER = new AttributeId("farpointer", 122);
public static final AttributeId ATTRIB_INPUTOP = new AttributeId("inputop", 123);
public static final AttributeId ATTRIB_OUTPUTOP = new AttributeId("outputop", 124);
public static final AttributeId ATTRIB_USEROP = new AttributeId("userop", 125);
// variable
public static final AttributeId ATTRIB_CLASS = new AttributeId("class", 126);
public static final AttributeId ATTRIB_REPREF = new AttributeId("repref", 127);
public static final AttributeId ATTRIB_SYMREF = new AttributeId("symref", 128);
// varmap
public static final AttributeId ATTRIB_LOCK = new AttributeId("lock", 129);
public static final AttributeId ATTRIB_MAIN = new AttributeId("main", 130);
// varnode
public static final AttributeId ATTRIB_ADDRTIED = new AttributeId("addrtied", 131);
public static final AttributeId ATTRIB_GRP = new AttributeId("grp", 132);
public static final AttributeId ATTRIB_INPUT = new AttributeId("input", 133);
public static final AttributeId ATTRIB_PERSISTS = new AttributeId("persists", 134);
public static final AttributeId ATTRIB_UNAFF = new AttributeId("unaff", 135);
// prettyprint
public static final AttributeId ATTRIB_BLOCKREF = new AttributeId("blockref", 136);
public static final AttributeId ATTRIB_CLOSE = new AttributeId("close", 137);
public static final AttributeId ATTRIB_COLOR = new AttributeId("color", 138);
public static final AttributeId ATTRIB_INDENT = new AttributeId("indent", 139);
public static final AttributeId ATTRIB_OFF = new AttributeId("off", 140);
public static final AttributeId ATTRIB_OPEN = new AttributeId("open", 141);
public static final AttributeId ATTRIB_OPREF = new AttributeId("opref", 142);
public static final AttributeId ATTRIB_VARREF = new AttributeId("varref", 143);
public static final AttributeId ATTRIB_UNKNOWN = new AttributeId("XMLunknown", 147);
}

View File

@ -17,7 +17,6 @@ package ghidra.program.model.pcode;
import ghidra.program.model.lang.UnknownInstructionException;
import ghidra.util.xml.SpecXmlUtils;
import ghidra.xml.XmlElement;
/**
* Block representing and '&amp;&amp;' or '||' control flow path within a conditional expression
@ -30,13 +29,13 @@ import ghidra.xml.XmlElement;
*/
public class BlockCondition extends BlockGraph {
private int opcode; // Type of boolean operation
public BlockCondition() {
super();
blocktype = PcodeBlock.CONDITION;
opcode = PcodeOp.BOOL_AND;
}
public int getOpcode() {
return opcode;
}
@ -45,17 +44,18 @@ public class BlockCondition extends BlockGraph {
public void saveXmlHeader(StringBuilder buffer) {
super.saveXmlHeader(buffer);
String opcodename = PcodeOp.getMnemonic(opcode);
SpecXmlUtils.encodeStringAttribute(buffer, "opcode", opcodename);
SpecXmlUtils.encodeStringAttribute(buffer, "opcode", opcodename);
}
@Override
public void restoreXmlHeader(XmlElement el) throws PcodeXMLException {
super.restoreXmlHeader(el);
String opcodename = el.getAttribute("opcode");
public void decodeHeader(Decoder decoder) throws PcodeXMLException {
super.decodeHeader(decoder);
String opcodename = decoder.readString(AttributeId.ATTRIB_OPCODE);
try {
opcode = PcodeOp.getOpcode(opcodename);
} catch (UnknownInstructionException e) {
}
catch (UnknownInstructionException e) {
opcode = PcodeOp.BOOL_AND;
}
}
}
}

View File

@ -17,7 +17,6 @@ package ghidra.program.model.pcode;
import ghidra.program.model.address.Address;
import ghidra.util.xml.SpecXmlUtils;
import ghidra.xml.XmlElement;
/**
* Placeholder for a basic block (BlockBasic) within a structured
@ -29,15 +28,15 @@ public class BlockCopy extends PcodeBlock {
private Object ref; // Reference to basic block of which this is a copy
private Address address; // Address upon entry to the basic block
private int altindex; // Alternate index for correlating this block with result structure
public BlockCopy() {
super();
blocktype = PcodeBlock.COPY;
address = Address.NO_ADDRESS;
ref = null;
}
public BlockCopy(Object r,Address addr) {
public BlockCopy(Object r, Address addr) {
super();
ref = r;
blocktype = PcodeBlock.COPY;
@ -60,7 +59,7 @@ public class BlockCopy extends PcodeBlock {
public Object getRef() {
return ref;
}
/**
* Used (by BlockGraph.transferObjectRef) to reset the internal Object and Address
* @param r is the internal Object
@ -85,8 +84,8 @@ public class BlockCopy extends PcodeBlock {
}
@Override
public void restoreXmlHeader(XmlElement el) throws PcodeXMLException {
super.restoreXmlHeader(el);
altindex = SpecXmlUtils.decodeInt(el.getAttribute("altindex"));
public void decodeHeader(Decoder decoder) throws PcodeXMLException {
super.decodeHeader(decoder);
altindex = (int) decoder.readSignedInteger(AttributeId.ATTRIB_ALTINDEX);
}
}

View File

@ -19,8 +19,6 @@ import java.io.IOException;
import java.io.Writer;
import ghidra.util.xml.SpecXmlUtils;
import ghidra.xml.XmlElement;
import ghidra.xml.XmlPullParser;
/**
* A "plain" goto block
@ -32,22 +30,22 @@ import ghidra.xml.XmlPullParser;
public class BlockGoto extends BlockGraph {
private PcodeBlock gototarget;
private int gototype; // Type of goto (1=plaingoto 2=break 4=continue)
public BlockGoto() {
super();
gototarget = null;
gototype = 1;
blocktype = PcodeBlock.GOTO;
}
public PcodeBlock getGotoTarget() {
return gototarget;
}
public int getGotoType() {
return gototype;
}
public void setGotoTarget(PcodeBlock gt) {
gototarget = gt;
}
@ -67,13 +65,13 @@ public class BlockGoto extends BlockGraph {
}
@Override
public void restoreXmlBody(XmlPullParser parser, BlockMap resolver) throws PcodeXMLException {
super.restoreXmlBody(parser, resolver);
XmlElement el = parser.start("target");
int target = SpecXmlUtils.decodeInt(el.getAttribute("index"));
int depth = SpecXmlUtils.decodeInt(el.getAttribute("depth"));
gototype = SpecXmlUtils.decodeInt(el.getAttribute("type"));
parser.end(el);
public void decodeBody(Decoder decoder, BlockMap resolver) throws PcodeXMLException {
super.decodeBody(decoder, resolver);
int el = decoder.openElement(ElementId.ELEM_TARGET);
int target = (int) decoder.readSignedInteger(AttributeId.ATTRIB_INDEX);
int depth = (int) decoder.readSignedInteger(AttributeId.ATTRIB_DEPTH);
gototype = (int) decoder.readUnsignedInteger(AttributeId.ATTRIB_TYPE);
decoder.closeElement(el);
resolver.addGotoRef(this, target, depth);
}
}

View File

@ -19,10 +19,7 @@ import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import ghidra.program.model.address.AddressFactory;
import ghidra.util.xml.SpecXmlUtils;
import ghidra.xml.XmlElement;
import ghidra.xml.XmlPullParser;
/**
* A block (with in edges and out edges) that contains other blocks
@ -31,23 +28,23 @@ import ghidra.xml.XmlPullParser;
public class BlockGraph extends PcodeBlock {
private ArrayList<PcodeBlock> list; // List of blocks within the super-block
private int maxindex; // -index- contains minimum -maxindex- contains max
public BlockGraph() {
super();
blocktype = PcodeBlock.GRAPH;
list = new ArrayList<PcodeBlock>();
list = new ArrayList<>();
maxindex = -1;
}
/**
* Add a block to this container. There are (initially) no edges between
* it and any other block in the container.
* @param bl is the new block to add
*/
public void addBlock(PcodeBlock bl) {
int min,max;
int min, max;
if (bl instanceof BlockGraph) {
BlockGraph gbl = (BlockGraph)bl;
BlockGraph gbl = (BlockGraph) bl;
min = gbl.index;
max = gbl.maxindex;
}
@ -55,16 +52,18 @@ public class BlockGraph extends PcodeBlock {
min = bl.index;
max = min;
}
if (list.isEmpty()) {
index = min;
maxindex = max;
}
else {
if (min < index)
if (min < index) {
index = min;
if (max > maxindex)
}
if (max > maxindex) {
maxindex = max;
}
}
bl.parent = this;
list.add(bl);
@ -75,24 +74,24 @@ public class BlockGraph extends PcodeBlock {
* getBlock(i) will return the block that satisfies block.getIndex() == i
*/
public void setIndices() {
for(int i=0;i<list.size();++i) {
for (int i = 0; i < list.size(); ++i) {
list.get(i).index = i;
}
index = 0;
maxindex = list.size()-1;
maxindex = list.size() - 1;
}
/**
* @return the number of blocks in this container
*/
public int getSize() {
return list.size();
}
/**
* Retrieve the i-th block from this container
* @param i is the index of the block to fetch
* @return
* @return the block
*/
public PcodeBlock getBlock(int i) {
return list.get(i);
@ -103,7 +102,7 @@ public class BlockGraph extends PcodeBlock {
* @param begin is the "from" block of the edge
* @param end is the "to" block of the edge
*/
public void addEdge(PcodeBlock begin,PcodeBlock end) {
public void addEdge(PcodeBlock begin, PcodeBlock end) {
end.addInEdge(begin, 0);
}
@ -114,7 +113,7 @@ public class BlockGraph extends PcodeBlock {
* @param ingraph is the original flow graph
*/
public void transferObjectRef(BlockGraph ingraph) {
ArrayList<BlockGraph> queue = new ArrayList<BlockGraph>();
ArrayList<BlockGraph> queue = new ArrayList<>();
int pos = 0;
queue.add(this);
while (pos < queue.size()) {
@ -134,8 +133,9 @@ public class BlockGraph extends PcodeBlock {
}
}
}
else if (block instanceof BlockGraph)
else if (block instanceof BlockGraph) {
queue.add((BlockGraph) block);
}
}
}
}
@ -143,8 +143,7 @@ public class BlockGraph extends PcodeBlock {
@Override
public void saveXmlBody(Writer writer) throws IOException {
super.saveXmlBody(writer);
for(int i=0;i<list.size();++i) {
PcodeBlock bl = list.get(i);
for (PcodeBlock bl : list) {
StringBuilder buf = new StringBuilder();
buf.append("<bhead");
SpecXmlUtils.encodeSignedIntegerAttribute(buf, "index", bl.getIndex());
@ -153,44 +152,43 @@ public class BlockGraph extends PcodeBlock {
buf.append("/>\n");
writer.write(buf.toString());
}
for(int i=0;i<list.size();++i) {
PcodeBlock bl = list.get(i);
for (PcodeBlock bl : list) {
bl.saveXml(writer);
}
}
@Override
public void restoreXmlBody(XmlPullParser parser, BlockMap resolver) throws PcodeXMLException {
public void decodeBody(Decoder decoder, BlockMap resolver) throws PcodeXMLException {
BlockMap newresolver = new BlockMap(resolver);
super.restoreXmlBody(parser, newresolver);
ArrayList<PcodeBlock> tmplist = new ArrayList<PcodeBlock>();
while(parser.peek().isStart()) {
if (!parser.peek().getName().equals("bhead"))
super.decodeBody(decoder, newresolver);
ArrayList<PcodeBlock> tmplist = new ArrayList<>();
for (;;) {
int el = decoder.peekElement();
if (el != ElementId.ELEM_BHEAD.getId()) {
break;
XmlElement el = parser.start();
int ind = SpecXmlUtils.decodeInt(el.getAttribute("index"));
String name = el.getAttribute("type");
}
decoder.openElement();
int ind = (int) decoder.readSignedInteger(AttributeId.ATTRIB_INDEX);
String name = decoder.readString(AttributeId.ATTRIB_TYPE);
PcodeBlock newbl = newresolver.createBlock(name, ind);
tmplist.add(newbl);
parser.end(el);
decoder.closeElement(el);
}
newresolver.sortLevelList();
for(int i=0;i<tmplist.size();++i) {
PcodeBlock bl = tmplist.get(i);
bl.restoreXml(parser, newresolver);
for (PcodeBlock bl : tmplist) {
bl.decode(decoder, newresolver);
addBlock(bl);
}
}
/**
* Restore all blocks and edges in this container from an XML stream.
* @param parser is the XML stream parser
* @param factory is the AddressFactory used to construct any Address
* @throws PcodeXMLException if part of the XML description is invalid
* Decode all blocks and edges in this container from a stream.
* @param decoder is the stream decoder
* @throws PcodeXMLException if there are invalid encodings
*/
public void restoreXml(XmlPullParser parser, AddressFactory factory) throws PcodeXMLException {
BlockMap resolver = new BlockMap(factory);
restoreXml(parser,resolver);
public void restoreXml(Decoder decoder) throws PcodeXMLException {
BlockMap resolver = new BlockMap(decoder.getAddressFactory());
decode(decoder, resolver);
resolver.resolveGotoReferences();
}
}

View File

@ -19,8 +19,6 @@ import java.io.IOException;
import java.io.Writer;
import ghidra.util.xml.SpecXmlUtils;
import ghidra.xml.XmlElement;
import ghidra.xml.XmlPullParser;
/**
* Block representing an if () goto control flow
@ -35,22 +33,22 @@ import ghidra.xml.XmlPullParser;
public class BlockIfGoto extends BlockGraph {
private PcodeBlock gototarget;
private int gototype; // type of goto 1=plaingoto 2=break 3=continue
public BlockIfGoto() {
super();
blocktype = PcodeBlock.IFGOTO;
gototarget = null;
gototype = 1;
}
public void setGotoTarget(PcodeBlock bl) {
gototarget = bl;
}
public PcodeBlock getGotoTarget() {
return gototarget;
}
public int getGotoType() {
return gototype;
}
@ -70,13 +68,13 @@ public class BlockIfGoto extends BlockGraph {
}
@Override
public void restoreXmlBody(XmlPullParser parser, BlockMap resolver) throws PcodeXMLException {
super.restoreXmlBody(parser,resolver);
XmlElement el = parser.start("target");
int target = SpecXmlUtils.decodeInt(el.getAttribute("index"));
int depth = SpecXmlUtils.decodeInt(el.getAttribute("depth"));
gototype = SpecXmlUtils.decodeInt(el.getAttribute("type"));
parser.end(el);
public void decodeBody(Decoder decoder, BlockMap resolver) throws PcodeXMLException {
super.decodeBody(decoder, resolver);
int el = decoder.openElement(ElementId.ELEM_TARGET);
int target = (int) decoder.readSignedInteger(AttributeId.ATTRIB_INDEX);
int depth = (int) decoder.readSignedInteger(AttributeId.ATTRIB_DEPTH);
gototype = (int) decoder.readUnsignedInteger(AttributeId.ATTRIB_TYPE);
decoder.closeElement(el);
gototarget = null;
resolver.addGotoRef(this, target, depth);
}

View File

@ -20,8 +20,6 @@ import java.io.Writer;
import java.util.ArrayList;
import ghidra.util.xml.SpecXmlUtils;
import ghidra.xml.XmlElement;
import ghidra.xml.XmlPullParser;
/**
* A block representing a 2-or-more control flow branchpoint
@ -35,23 +33,22 @@ import ghidra.xml.XmlPullParser;
*/
public class BlockMultiGoto extends BlockGraph {
protected ArrayList<PcodeBlock> targets;
public BlockMultiGoto() {
super();
targets = new ArrayList<PcodeBlock>();
targets = new ArrayList<>();
blocktype = PcodeBlock.MULTIGOTO;
}
public void addGotoTarget(PcodeBlock target) {
targets.add(target);
}
@Override
public void saveXmlBody(Writer writer) throws IOException {
super.saveXmlBody(writer);
for(int i=0;i<targets.size();++i) {
PcodeBlock gototarget = targets.get(i);
for (PcodeBlock gototarget : targets) {
StringBuilder buf = new StringBuilder();
buf.append("<target");
PcodeBlock leaf = gototarget.getFrontLeaf();
@ -65,14 +62,17 @@ public class BlockMultiGoto extends BlockGraph {
}
@Override
public void restoreXmlBody(XmlPullParser parser, BlockMap resolver) throws PcodeXMLException {
super.restoreXmlBody(parser, resolver);
while(parser.peek().isStart()) {
XmlElement el = parser.start("target");
int target = SpecXmlUtils.decodeInt(el.getAttribute("index"));
int depth = SpecXmlUtils.decodeInt(el.getAttribute("depth"));
// int gototype = SpecXmlUtils.decodeInt(el.getAttribute("type"));
parser.end(el);
public void decodeBody(Decoder decoder, BlockMap resolver) throws PcodeXMLException {
super.decodeBody(decoder, resolver);
for (;;) {
int el = decoder.peekElement();
if (el != ElementId.ELEM_TARGET.getId()) {
break;
}
decoder.openElement();
int target = (int) decoder.readSignedInteger(AttributeId.ATTRIB_INDEX);
int depth = (int) decoder.readSignedInteger(AttributeId.ATTRIB_DEPTH);
decoder.closeElement(el);
resolver.addGotoRef(this, target, depth);
}
}

View File

@ -0,0 +1,227 @@
/* ###
* 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.program.model.pcode;
import java.io.InputStream;
import ghidra.program.model.address.AddressFactory;
import ghidra.program.model.address.AddressSpace;
/**
* An interface for reading structured data from a stream
*
* All data is loosely structured as with an XML document. A document contains a nested set
* of elements, with labels corresponding to the ElementId class. A single element can hold
* zero or more attributes and zero or more child elements. An attribute holds a primitive
* data element (boolean, long, String) and is labeled by an AttributeId. The document is traversed
* using a sequence of openElement() and closeElement() calls, intermixed with read*() calls to extract
* the data. The elements are traversed in a depth first order. Attributes within an element can
* be traversed in order using repeated calls to the getNextAttributeId() method, followed by a calls to
* one of the read*(void) methods to extract the data. Alternately a read*(AttributeId) call can be used
* to extract data for an attribute known to be in the element. There is a special content attribute
* whose data can be extracted using a read*(AttributeId) call that is passed the special ATTRIB_CONTENT id.
* This attribute will not be traversed by getNextAttribute().
*/
public interface Decoder {
public AddressFactory getAddressFactory();
/**
* Clear any current decoding state.
* Allows the same decoder to be reused. Object is ready for new call to ingestStream.
*/
public void clear();
/**
* Prepare to decode a given stream.
* Called once before any decoding. Currently this is assumed to make an internal copy of
* the stream data, i.e. the input stream is cleared before any decoding takes place.
* @param stream is the given input stream to be decode
* @param source is a label describing the source of the input stream
* @throws PcodeXMLException for errors reading the stream
*/
public void ingestStream(InputStream stream, String source) throws PcodeXMLException;
/**
* Peek at the next child element of the current parent, without traversing in (opening) it.
* The element id is returned, which can be compared to ElementId labels.
* If there are no remaining child elements to traverse, 0 is returned.
* @return the element id or 0
*/
public int peekElement();
/**
* Open (traverse into) the next child element of the current parent.
* The child becomes the current parent.
* The list of attributes is initialized for use with getNextAttributeId.
* @return the id of the child element
*/
public int openElement();
/**
* Open (traverse into) the next child element, which must be of a specific type
* The child becomes the current parent, and its attributes are initialized for use with
* getNextAttributeId. The child must match the given element id or an exception is thrown.
* @param elemId is the given element id to match
* @return the id of the child element
* @throws PcodeXMLException if the expected element is not the next element
*/
public int openElement(ElementId elemId) throws PcodeXMLException;
/**
* Close the current element
* The data for the current element is considered fully processed. If the element has additional
* children, an exception is thrown. The stream must indicate the end of the element in some way.
* @param id is the id of the element to close (which must be the current element)
* @throws PcodeXMLException if not at end of expected element
*/
public void closeElement(int id) throws PcodeXMLException;
/**
* Close the current element, skipping any child elements that have not yet been parsed.
* This closes the given element, which must be current. If there are child elements that have
* not been parsed, this is not considered an error, and they are skipped over in the parse.
* @param id is the id of the element to close (which must be the current element)
* @throws PcodeXMLException if the indicated element is not the current element
*/
public void closeElementSkipping(int id) throws PcodeXMLException;
/**
* Get the next attribute id for the current element
* Attributes are automatically set up for traversal using this method, when the element is
* opened. If all attributes have been traversed (or there are no attributes), 0 is returned.
* @return the id of the next attribute or 0
*/
public int getNextAttributeId();
/**
* Reset attribute traversal for the current element
* Attributes for a single element can be traversed more than once using the getNextAttributeId
* method.
*/
public void rewindAttributes();
/**
* Parse the current attribute as a boolean value
* The last attribute, as returned by getNextAttributeId, is treated as a boolean, and its
* value is returned.
* @return the boolean value associated with the current attribute.
* @throws PcodeXMLException if the expected value is not present
*/
public boolean readBool() throws PcodeXMLException;
/**
* Find and parse a specific attribute in the current element as a boolean value
* The set of attributes for the current element is searched for a match to the given attribute
* id. This attribute is then parsed as a boolean and its value returned.
* If there is no attribute matching the id, an exception is thrown.
* Parsing via getNextAttributeId is reset.
* @param attribId is the specific attribute id to match
* @return the boolean value
* @throws PcodeXMLException if the expected value is not present
*/
public boolean readBool(AttributeId attribId) throws PcodeXMLException;
/**
* Parse the current attribute as a signed integer value
* The last attribute, as returned by getNextAttributeId, is treated as a signed integer,
* and its value is returned.
* @return the signed integer value associated with the current attribute.
* @throws PcodeXMLException if the expected value is not present
*/
public long readSignedInteger() throws PcodeXMLException;
/**
* Find and parse a specific attribute in the current element as a signed integer
* The set of attributes for the current element is searched for a match to the given attribute
* id. This attribute is then parsed as a signed integer and its value returned.
* If there is no attribute matching the id, an exception is thrown.
* Parsing via getNextAttributeId is reset.
* @param attribId is the specific attribute id to match
* @return the signed integer value
* @throws PcodeXMLException if the expected value is not present
*/
public long readSignedInteger(AttributeId attribId) throws PcodeXMLException;
/**
* Parse the current attribute as an unsigned integer value
* The last attribute, as returned by getNextAttributeId, is treated as an unsigned integer,
* and its value is returned.
* @return the unsigned integer value associated with the current attribute.
* @throws PcodeXMLException if the expected value is not present
*/
public long readUnsignedInteger() throws PcodeXMLException;
/**
* Find and parse a specific attribute in the current element as an unsigned integer
* The set of attributes for the current element is searched for a match to the given attribute
* id. This attribute is then parsed as an unsigned integer and its value returned.
* If there is no attribute matching the id, an exception is thrown.
* Parsing via getNextAttributeId is reset.
* @param attribId is the specific attribute id to match
* @return the unsigned integer value
* @throws PcodeXMLException if the expected value is not present
*/
public long readUnsignedInteger(AttributeId attribId) throws PcodeXMLException;
/**
* Parse the current attribute as a string
* The last attribute, as returned by getNextAttributeId, is returned as a string.
* @return the string associated with the current attribute.
* @throws PcodeXMLException if the expected value is not present
*/
public String readString() throws PcodeXMLException;
/**
* Find the specific attribute in the current element and return it as a string
* The set of attributes for the current element is searched for a match to the given attribute
* id. This attribute is then returned as a string. If there is no attribute matching the id,
* and exception is thrown. Parse via getNextAttributeId is reset.
* @param attribId is the specific attribute id to match
* @return the string associated with the attribute
* @throws PcodeXMLException if the expected value is not present
*/
public String readString(AttributeId attribId) throws PcodeXMLException;
/**
* Parse the current attribute as an address space
* The last attribute, as returned by getNextAttributeId, is returned as an address space.
* @return the address space associated with the current attribute.
* @throws PcodeXMLException if the expected value is not present
*/
public AddressSpace readSpace() throws PcodeXMLException;
/**
* Find the specific attribute in the current element and return it as an address space
* Search attributes from the current element for a match to the given attribute id.
* Return this attribute as an address space. If there is no attribute matching the id, an
* exception is thrown. Parse via getNextAttributeId is reset.
* @param attribId is the specific attribute id to match
* @return the address space associated with the attribute
* @throws PcodeXMLException if the expected value is not present
*/
public AddressSpace readSpace(AttributeId attribId) throws PcodeXMLException;
/**
* Skip parsing of the next element
* The element skipped is the one that would be opened by the next call to openElement.
* @throws PcodeXMLException if there is no new element
*/
public default void skipElement() throws PcodeXMLException {
int elemId = openElement();
closeElementSkipping(elemId);
}
}

View File

@ -21,9 +21,6 @@ import ghidra.program.model.listing.Program;
import ghidra.program.model.listing.VariableStorage;
import ghidra.util.exception.AssertException;
import ghidra.util.exception.InvalidInputException;
import ghidra.util.xml.SpecXmlUtils;
import ghidra.xml.XmlElement;
import ghidra.xml.XmlPullParser;
/**
* A HighSymbol mapping based on local hashing of the symbol's Varnode within a
@ -63,11 +60,11 @@ public class DynamicEntry extends SymbolEntry {
}
@Override
public void restoreXML(XmlPullParser parser) throws PcodeXMLException {
XmlElement addrel = parser.start("hash");
hash = SpecXmlUtils.decodeLong(addrel.getAttribute("val"));
parser.end(addrel);
parseRangeList(parser);
public void decode(Decoder decoder) throws PcodeXMLException {
int addrel = decoder.openElement(ElementId.ELEM_HASH);
hash = decoder.readUnsignedInteger(AttributeId.ATTRIB_VAL);
decoder.closeElement(addrel);
decodeRangeList(decoder);
}
@Override

View File

@ -0,0 +1,335 @@
/* ###
* 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.program.model.pcode;
import java.util.HashMap;
/**
* An annotation for a specific collection of hierarchical data
*
* This class parallels the XML concept of an element. An ElementId describes a collection of data, where each
* piece is annotated by a specific AttributeId. In addition, each ElementId can contain zero or more child
* ElementId objects, forming a hierarchy of annotated data. Each ElementId has a name, which is unique at least
* within the context of its parent ElementId. Internally this name is associated with an integer id. A special
* AttributeId ATTRIB_CONTENT is used to label the XML element's text content, which is traditionally not labeled
* as an attribute.
*/
public class ElementId {
private static HashMap<String, Integer> lookupElementId = new HashMap<>();
private String name; // The name of the element
private int id; // The (internal) id of the element
public ElementId(String nm, int i) {
name = nm;
id = i;
lookupElementId.put(nm, i);
}
public String getName() {
return name;
}
public int getId() {
return id;
}
/**
* Find the id associated with a specific element name
* @param nm the element name
* @return the associated id
*/
public static int find(String nm) {
Integer res = lookupElementId.get(nm);
if (res != null) {
return res.intValue();
}
return ELEM_UNKNOWN.id;
}
public static final ElementId ELEM_DATA = new ElementId("data", 1);
public static final ElementId ELEM_INPUT = new ElementId("input", 2);
public static final ElementId ELEM_OFF = new ElementId("off", 3);
public static final ElementId ELEM_OUTPUT = new ElementId("output", 4);
public static final ElementId ELEM_RETURNADDRESS = new ElementId("returnaddress", 5);
public static final ElementId ELEM_SYMBOL = new ElementId("symbol", 6);
public static final ElementId ELEM_TARGET = new ElementId("target", 7);
public static final ElementId ELEM_VAL = new ElementId("val", 8);
public static final ElementId ELEM_VALUE = new ElementId("value", 9);
public static final ElementId ELEM_VOID = new ElementId("void", 10);
// address
public static final ElementId ELEM_ADDR = new ElementId("addr", 11);
public static final ElementId ELEM_RANGE = new ElementId("range", 12);
public static final ElementId ELEM_RANGELIST = new ElementId("rangelist", 13);
public static final ElementId ELEM_REGISTER = new ElementId("register", 14);
public static final ElementId ELEM_SEQNUM = new ElementId("seqnum", 15);
public static final ElementId ELEM_VARNODE = new ElementId("varnode", 16);
// architecture
public static final ElementId ELEM_ADDRESS_SHIFT_AMOUNT =
new ElementId("address_shift_amount", 17);
public static final ElementId ELEM_AGGRESSIVETRIM = new ElementId("aggressivetrim", 18);
public static final ElementId ELEM_COMPILER_SPEC = new ElementId("compiler_spec", 19);
public static final ElementId ELEM_DATA_SPACE = new ElementId("data_space", 20);
public static final ElementId ELEM_DEFAULT_MEMORY_BLOCKS =
new ElementId("default_memory_blocks", 21);
public static final ElementId ELEM_DEFAULT_PROTO = new ElementId("default_proto", 22);
public static final ElementId ELEM_DEFAULT_SYMBOLS = new ElementId("default_symbols", 23);
public static final ElementId ELEM_EVAL_CALLED_PROTOTYPE =
new ElementId("eval_called_prototype", 24);
public static final ElementId ELEM_EVAL_CURRENT_PROTOTYPE =
new ElementId("eval_current_prototype", 25);
public static final ElementId ELEM_EXPERIMENTAL_RULES = new ElementId("experimental_rules", 26);
public static final ElementId ELEM_FLOWOVERRIDELIST = new ElementId("flowoverridelist", 27);
public static final ElementId ELEM_FUNCPTR = new ElementId("funcptr", 28);
public static final ElementId ELEM_GLOBAL = new ElementId("global", 29);
public static final ElementId ELEM_INCIDENTALCOPY = new ElementId("incidentalcopy", 30);
public static final ElementId ELEM_INFERPTRBOUNDS = new ElementId("inferptrbounds", 31);
public static final ElementId ELEM_MODELALIAS = new ElementId("modelalias", 32);
public static final ElementId ELEM_NOHIGHPTR = new ElementId("nohighptr", 33);
public static final ElementId ELEM_PROCESSOR_SPEC = new ElementId("processor_spec", 34);
public static final ElementId ELEM_PROGRAMCOUNTER = new ElementId("programcounter", 35);
public static final ElementId ELEM_PROPERTIES = new ElementId("properties", 36);
public static final ElementId ELEM_READONLY = new ElementId("readonly", 37);
public static final ElementId ELEM_REGISTER_DATA = new ElementId("register_data", 38);
public static final ElementId ELEM_RULE = new ElementId("rule", 39);
public static final ElementId ELEM_SAVE_STATE = new ElementId("save_state", 40);
public static final ElementId ELEM_SEGMENTED_ADDRESS = new ElementId("segmented_address", 41);
public static final ElementId ELEM_SPACEBASE = new ElementId("spacebase", 42);
public static final ElementId ELEM_SPECEXTENSIONS = new ElementId("specextensions", 43);
public static final ElementId ELEM_STACKPOINTER = new ElementId("stackpointer", 44);
public static final ElementId ELEM_VOLATILE = new ElementId("volatile", 45);
// block
public static final ElementId ELEM_BHEAD = new ElementId("bhead", 47);
public static final ElementId ELEM_BLOCK = new ElementId("block", 48);
public static final ElementId ELEM_BLOCKEDGE = new ElementId("blockedge", 49);
public static final ElementId ELEM_EDGE = new ElementId("edge", 50);
// callgraph
public static final ElementId ELEM_CALLGRAPH = new ElementId("callgraph", 51);
public static final ElementId ELEM_NODE = new ElementId("node", 52);
// comment
public static final ElementId ELEM_COMMENT = new ElementId("comment", 53);
public static final ElementId ELEM_COMMENTDB = new ElementId("commentdb", 54);
public static final ElementId ELEM_TEXT = new ElementId("text", 55);
// cpool
public static final ElementId ELEM_CONSTANTPOOL = new ElementId("constantpool", 56);
public static final ElementId ELEM_CPOOLREC = new ElementId("cpoolrec", 57);
public static final ElementId ELEM_REF = new ElementId("ref", 58);
public static final ElementId ELEM_TOKEN = new ElementId("token", 59);
// database
public static final ElementId ELEM_COLLISION = new ElementId("collision", 60);
public static final ElementId ELEM_DB = new ElementId("db", 61);
public static final ElementId ELEM_EQUATESYMBOL = new ElementId("equatesymbol", 62);
public static final ElementId ELEM_EXTERNREFSYMBOL = new ElementId("externrefsymbol", 63);
public static final ElementId ELEM_FACETSYMBOL = new ElementId("facetsymbol", 64);
public static final ElementId ELEM_FUNCTIONSHELL = new ElementId("functionshell", 65);
public static final ElementId ELEM_HASH = new ElementId("hash", 66);
public static final ElementId ELEM_HOLE = new ElementId("hole", 67);
public static final ElementId ELEM_LABELSYM = new ElementId("labelsym", 68);
public static final ElementId ELEM_MAPSYM = new ElementId("mapsym", 69);
public static final ElementId ELEM_PARENT = new ElementId("parent", 70);
public static final ElementId ELEM_PROPERTY_CHANGEPOINT =
new ElementId("property_changepoint", 71);
public static final ElementId ELEM_RANGEEQUALSSYMBOLS = new ElementId("rangeequalssymbols", 72);
public static final ElementId ELEM_SCOPE = new ElementId("scope", 73);
public static final ElementId ELEM_SYMBOLLIST = new ElementId("symbollist", 74);
// fspec
public static final ElementId ELEM_GROUP = new ElementId("group", 75);
public static final ElementId ELEM_INTERNALLIST = new ElementId("internallist", 76);
public static final ElementId ELEM_KILLEDBYCALL = new ElementId("killedbycall", 77);
public static final ElementId ELEM_LIKELYTRASH = new ElementId("likelytrash", 78);
public static final ElementId ELEM_LOCALRANGE = new ElementId("localrange", 79);
public static final ElementId ELEM_MODEL = new ElementId("model", 80);
public static final ElementId ELEM_PARAM = new ElementId("param", 81);
public static final ElementId ELEM_PARAMRANGE = new ElementId("paramrange", 82);
public static final ElementId ELEM_PENTRY = new ElementId("pentry", 83);
public static final ElementId ELEM_PROTOTYPE = new ElementId("prototype", 84);
public static final ElementId ELEM_RESOLVEPROTOTYPE = new ElementId("resolveprototype", 85);
public static final ElementId ELEM_RETPARAM = new ElementId("retparam", 86);
public static final ElementId ELEM_RETURNSYM = new ElementId("returnsym", 87);
public static final ElementId ELEM_UNAFFECTED = new ElementId("unaffected", 88);
// funcdata
public static final ElementId ELEM_AST = new ElementId("ast", 89);
public static final ElementId ELEM_FUNCTION = new ElementId("function", 90);
public static final ElementId ELEM_HIGHLIST = new ElementId("highlist", 91);
public static final ElementId ELEM_JUMPTABLELIST = new ElementId("jumptablelist", 92);
public static final ElementId ELEM_VARNODES = new ElementId("varnodes", 93);
// globalcontext
public static final ElementId ELEM_CONTEXT_DATA = new ElementId("context_data", 94);
public static final ElementId ELEM_CONTEXT_POINTS = new ElementId("context_points", 95);
public static final ElementId ELEM_CONTEXT_POINTSET = new ElementId("context_pointset", 96);
public static final ElementId ELEM_CONTEXT_SET = new ElementId("context_set", 97);
public static final ElementId ELEM_SET = new ElementId("set", 98);
public static final ElementId ELEM_TRACKED_POINTSET = new ElementId("tracked_pointset", 99);
public static final ElementId ELEM_TRACKED_SET = new ElementId("tracked_set", 100);
// jumptable
public static final ElementId ELEM_BASICOVERRIDE = new ElementId("basicoverride", 101);
public static final ElementId ELEM_DEST = new ElementId("dest", 102);
public static final ElementId ELEM_JUMPTABLE = new ElementId("jumptable", 103);
public static final ElementId ELEM_LOADTABLE = new ElementId("loadtable", 104);
public static final ElementId ELEM_NORMADDR = new ElementId("normaddr", 105);
public static final ElementId ELEM_NORMHASH = new ElementId("normhash", 106);
public static final ElementId ELEM_STARTVAL = new ElementId("startval", 107);
// op
public static final ElementId ELEM_IOP = new ElementId("iop", 110);
// options
public static final ElementId ELEM_ALIASBLOCK = new ElementId("aliasblock", 111);
public static final ElementId ELEM_ALLOWCONTEXTSET = new ElementId("allowcontextset", 112);
public static final ElementId ELEM_ANALYZEFORLOOPS = new ElementId("analyzeforloops", 113);
public static final ElementId ELEM_COMMENTHEADER = new ElementId("commentheader", 114);
public static final ElementId ELEM_COMMENTINDENT = new ElementId("commentindent", 115);
public static final ElementId ELEM_COMMENTINSTRUCTION =
new ElementId("commentinstruction", 116);
public static final ElementId ELEM_COMMENTSTYLE = new ElementId("commentstyle", 117);
public static final ElementId ELEM_CONVENTIONPRINTING =
new ElementId("conventionprinting", 118);
public static final ElementId ELEM_CURRENTACTION = new ElementId("currentaction", 119);
public static final ElementId ELEM_DEFAULTPROTOTYPE = new ElementId("defaultprototype", 120);
public static final ElementId ELEM_ERRORREINTERPRETED =
new ElementId("errorreinterpreted", 121);
public static final ElementId ELEM_ERRORTOOMANYINSTRUCTIONS =
new ElementId("errortoomanyinstructions", 122);
public static final ElementId ELEM_ERRORUNIMPLEMENTED =
new ElementId("errorunimplemented", 123);
public static final ElementId ELEM_EXTRAPOP = new ElementId("extrapop", 124);
public static final ElementId ELEM_IGNOREUNIMPLEMENTED =
new ElementId("ignoreunimplemented", 125);
public static final ElementId ELEM_INDENTINCREMENT = new ElementId("indentincrement", 126);
public static final ElementId ELEM_INFERCONSTPTR = new ElementId("inferconstptr", 127);
public static final ElementId ELEM_INLINE = new ElementId("inline", 128);
public static final ElementId ELEM_INPLACEOPS = new ElementId("inplaceops", 129);
public static final ElementId ELEM_INTEGERFORMAT = new ElementId("integerformat", 130);
public static final ElementId ELEM_JUMPLOAD = new ElementId("jumpload", 131);
public static final ElementId ELEM_MAXINSTRUCTION = new ElementId("maxinstruction", 132);
public static final ElementId ELEM_MAXLINEWIDTH = new ElementId("maxlinewidth", 133);
public static final ElementId ELEM_NAMESPACESTRATEGY = new ElementId("namespacestrategy", 134);
public static final ElementId ELEM_NOCASTPRINTING = new ElementId("nocastprinting", 135);
public static final ElementId ELEM_NORETURN = new ElementId("noreturn", 136);
public static final ElementId ELEM_NULLPRINTING = new ElementId("nullprinting", 137);
public static final ElementId ELEM_OPTIONSLIST = new ElementId("optionslist", 138);
public static final ElementId ELEM_PARAM1 = new ElementId("param1", 139);
public static final ElementId ELEM_PARAM2 = new ElementId("param2", 140);
public static final ElementId ELEM_PARAM3 = new ElementId("param3", 141);
public static final ElementId ELEM_PROTOEVAL = new ElementId("protoeval", 142);
public static final ElementId ELEM_SETACTION = new ElementId("setaction", 143);
public static final ElementId ELEM_SETLANGUAGE = new ElementId("setlanguage", 144);
public static final ElementId ELEM_STRUCTALIGN = new ElementId("structalign", 145);
public static final ElementId ELEM_TOGGLERULE = new ElementId("togglerule", 146);
public static final ElementId ELEM_WARNING = new ElementId("warning", 147);
// override
public static final ElementId ELEM_DEADCODEDELAY = new ElementId("deadcodedelay", 148);
public static final ElementId ELEM_FLOW = new ElementId("flow", 149);
public static final ElementId ELEM_FORCEGOTO = new ElementId("forcegoto", 150);
public static final ElementId ELEM_INDIRECTOVERRIDE = new ElementId("indirectoverride", 151);
public static final ElementId ELEM_MULTISTAGEJUMP = new ElementId("multistagejump", 152);
public static final ElementId ELEM_OVERRIDE = new ElementId("override", 153);
public static final ElementId ELEM_PROTOOVERRIDE = new ElementId("protooverride", 154);
// paramid
public static final ElementId ELEM_PARAMMEASURES = new ElementId("parammeasures", 155);
public static final ElementId ELEM_PROTO = new ElementId("proto", 156);
public static final ElementId ELEM_RANK = new ElementId("rank", 157);
// pcodeinject
public static final ElementId ELEM_ADDR_PCODE = new ElementId("addr_pcode", 158);
public static final ElementId ELEM_BODY = new ElementId("body", 159);
public static final ElementId ELEM_CALLFIXUP = new ElementId("callfixup", 160);
public static final ElementId ELEM_CALLOTHERFIXUP = new ElementId("callotherfixup", 161);
public static final ElementId ELEM_CASE_PCODE = new ElementId("case_pcode", 162);
public static final ElementId ELEM_CONTEXT = new ElementId("context", 163);
public static final ElementId ELEM_DEFAULT_PCODE = new ElementId("default_pcode", 164);
public static final ElementId ELEM_INJECT = new ElementId("inject", 165);
public static final ElementId ELEM_INJECTDEBUG = new ElementId("injectdebug", 166);
public static final ElementId ELEM_INST = new ElementId("inst", 167);
public static final ElementId ELEM_PAYLOAD = new ElementId("payload", 168);
public static final ElementId ELEM_PCODE = new ElementId("pcode", 169);
public static final ElementId ELEM_SIZE_PCODE = new ElementId("size_pcode", 170);
// prefersplit
public static final ElementId ELEM_PREFERSPLIT = new ElementId("prefersplit", 171);
// stringmanage
public static final ElementId ELEM_BYTES = new ElementId("bytes", 177);
public static final ElementId ELEM_STRING = new ElementId("string", 178);
public static final ElementId ELEM_STRINGMANAGE = new ElementId("stringmanage", 179);
// translate
public static final ElementId ELEM_OP = new ElementId("op", 180);
public static final ElementId ELEM_SLEIGH = new ElementId("sleigh", 181);
public static final ElementId ELEM_SPACE = new ElementId("space", 182);
public static final ElementId ELEM_SPACEID = new ElementId("spaceid", 183);
public static final ElementId ELEM_SPACES = new ElementId("spaces", 184);
public static final ElementId ELEM_SPACE_BASE = new ElementId("space_base", 185);
public static final ElementId ELEM_SPACE_OTHER = new ElementId("space_other", 186);
public static final ElementId ELEM_SPACE_OVERLAY = new ElementId("space_overlay", 187);
public static final ElementId ELEM_SPACE_UNIQUE = new ElementId("space_unique", 188);
public static final ElementId ELEM_TRUNCATE_SPACE = new ElementId("truncate_space", 189);
// type
public static final ElementId ELEM_CORETYPES = new ElementId("coretypes", 190);
public static final ElementId ELEM_DATA_ORGANIZATION = new ElementId("data_organization", 191);
public static final ElementId ELEM_DEF = new ElementId("def", 192);
public static final ElementId ELEM_ENTRY = new ElementId("entry", 193);
public static final ElementId ELEM_ENUM = new ElementId("enum", 194);
public static final ElementId ELEM_FIELD = new ElementId("field", 195);
public static final ElementId ELEM_INTEGER_SIZE = new ElementId("integer_size", 196);
public static final ElementId ELEM_LONG_SIZE = new ElementId("long_size", 197);
public static final ElementId ELEM_SIZE_ALIGNMENT_MAP =
new ElementId("size_alignment_map", 198);
public static final ElementId ELEM_TYPE = new ElementId("type", 199);
public static final ElementId ELEM_TYPEGRP = new ElementId("typegrp", 200);
public static final ElementId ELEM_TYPEREF = new ElementId("typeref", 201);
// userop
public static final ElementId ELEM_CONSTRESOLVE = new ElementId("constresolve", 202);
public static final ElementId ELEM_JUMPASSIST = new ElementId("jumpassist", 203);
public static final ElementId ELEM_SEGMENTOP = new ElementId("segmentop", 204);
// variable
public static final ElementId ELEM_HIGH = new ElementId("high", 205);
// varmap
public static final ElementId ELEM_LOCALDB = new ElementId("localdb", 206);
// prettyprint
public static final ElementId ELEM_BREAK = new ElementId("break", 208);
public static final ElementId ELEM_CLANG_DOCUMENT = new ElementId("clang_document", 209);
public static final ElementId ELEM_FUNCNAME = new ElementId("funcname", 210);
public static final ElementId ELEM_FUNCPROTO = new ElementId("funcproto", 211);
public static final ElementId ELEM_LABEL = new ElementId("label", 212);
public static final ElementId ELEM_RETURN_TYPE = new ElementId("return_type", 213);
public static final ElementId ELEM_STATEMENT = new ElementId("statement", 214);
public static final ElementId ELEM_SYNTAX = new ElementId("syntax", 215);
public static final ElementId ELEM_VARDECL = new ElementId("vardecl", 216);
public static final ElementId ELEM_VARIABLE = new ElementId("variable", 217);
// ghidra_process
public static final ElementId ELEM_DOC = new ElementId("doc", 218);
public static final ElementId ELEM_UNKNOWN = new ElementId("XMLunknown", 231);
}

View File

@ -0,0 +1,94 @@
/* ###
* 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.program.model.pcode;
import ghidra.program.model.address.AddressSpace;
/**
* An interface for writing structured data to a stream
*
* The resulting encoded data is structured similarly to an XML document. The document contains a nested set
* of \elements, with labels corresponding to the ElementId class. A single element can hold
* zero or more attributes and zero or more child elements. An attribute holds a primitive
* data element (boolean, long, String) and is labeled by an AttributeId. The document is written
* using a sequence of openElement() and closeElement() calls, intermixed with write*() calls to encode
* the data primitives. All primitives written using a write*() call are associated with current open element,
* and all write*() calls for one element must come before opening any child element.
* The traditional XML element text content can be written using the special ATTRIB_CONTENT AttributeId, which
* must be the last write*() call associated with the specific element.
*/
public interface Encoder {
/**
* Clear any state associated with the encoder
* The encoder should be ready to write a new document after this call.
*/
void clear();
/**
* Begin a new element in the encoding
* The element will have the given ElementId annotation and becomes the \e current element.
* @param elemId is the given ElementId annotation
*/
void openElement(ElementId elemId);
/**
* End the current element in the encoding
* The current element must match the given annotation or an exception is thrown.
* @param elemId is the given (expected) annotation for the current element
*/
void closeElement(ElementId elemId);
/**
* Write an annotated boolean value into the encoding
* The boolean data is associated with the given AttributeId annotation and the current open element.
* @param attribId is the given AttributeId annotation
* @param val is boolean value to encode
*/
void writeBool(AttributeId attribId, boolean val);
/**
* Write an annotated signed integer value into the encoding
* The integer is associated with the given AttributeId annotation and the current open element.
* @param attribId is the given AttributeId annotation
* @param val is the signed integer value to encode
*/
void writeSignedInteger(AttributeId attribId, long val);
/**
* Write an annotated unsigned integer value into the encoding
* The integer is associated with the given AttributeId annotation and the current open element.
* @param attribId is the given AttributeId annotation
* @param val is the unsigned integer value to encode
*/
void writeUnsignedInteger(AttributeId attribId, long val);
/**
* Write an annotated string into the encoding
* The string is associated with the given AttributeId annotation and the current open element.
* @param attribId is the given AttributeId annotation
* @param val is the string to encode
*/
void writeString(AttributeId attribId, String val);
/**
* Write an address space reference into the encoding
* The address space is associated with the given AttributeId annotation and the current open element.
* @param attribId is the given AttributeId annotation
* @param spc is the address space to encode
*/
void writeSpace(AttributeId attribId, AddressSpace spc);
}

View File

@ -18,8 +18,6 @@ package ghidra.program.model.pcode;
import ghidra.program.model.address.Address;
import ghidra.program.model.data.DataType;
import ghidra.util.xml.SpecXmlUtils;
import ghidra.xml.XmlElement;
import ghidra.xml.XmlPullParser;
public class EquateSymbol extends HighSymbol {
@ -66,12 +64,22 @@ public class EquateSymbol extends HighSymbol {
}
@Override
public void restoreXML(XmlPullParser parser) throws PcodeXMLException {
XmlElement symel = parser.start("equatesymbol");
restoreXMLHeader(symel);
public void decode(Decoder decoder) throws PcodeXMLException {
int symel = decoder.openElement(ElementId.ELEM_EQUATESYMBOL);
decodeHeader(decoder);
type = DataType.DEFAULT;
convert = FORMAT_DEFAULT;
String formString = symel.getAttribute("format");
decoder.rewindAttributes();
String formString = null;
for (;;) {
int attribId = decoder.getNextAttributeId();
if (attribId == 0) {
break;
}
if (attribId == AttributeId.ATTRIB_FORMAT.getId()) {
formString = decoder.readString();
}
}
if (formString != null) {
if (formString.equals("hex")) {
convert = FORMAT_HEX;
@ -89,9 +97,10 @@ public class EquateSymbol extends HighSymbol {
convert = FORMAT_BIN;
}
}
parser.start("value");
value = SpecXmlUtils.decodeLong(parser.end().getText()); // End <value> tag
parser.end(symel);
int valel = decoder.openElement(ElementId.ELEM_VALUE);
value = decoder.readUnsignedInteger(AttributeId.ATTRIB_CONTENT);
decoder.closeElement(valel);
decoder.closeElement(symel);
}
@Override

View File

@ -21,8 +21,6 @@ import ghidra.program.model.listing.*;
import ghidra.program.model.symbol.SourceType;
import ghidra.util.Msg;
import ghidra.util.xml.SpecXmlUtils;
import ghidra.xml.XmlElement;
import ghidra.xml.XmlPullParser;
/**
*
@ -152,7 +150,7 @@ public class FunctionPrototype {
if ((returnstorage == null) || (!returnstorage.isValid())) { // Unassigned or otherwise invalid storage
outputlock = false;
returnstorage = VariableStorage.VOID_STORAGE; // Treat as unlocked void
returntype = DataType.VOID;
returntype = VoidDataType.dataType;
}
voidinputlock =
(f.getSignatureSource() != SourceType.DEFAULT) && f.getParameterCount() == 0;
@ -413,22 +411,22 @@ public class FunctionPrototype {
}
/**
* Parse the function prototype from {@code <prototype>} tag.
* @param parser is the XML document to parse
* Decode the function prototype from a {@code <prototype>} element in the stream.
* @param decoder is the stream decoder
* @param dtmanage is the DataTypeManager used to parse data-type tags
* @throws PcodeXMLException for any problems parsing
* @throws PcodeXMLException for invalid encodings
*/
public void readPrototypeXML(XmlPullParser parser, PcodeDataTypeManager dtmanage)
public void decodePrototype(Decoder decoder, PcodeDataTypeManager dtmanage)
throws PcodeXMLException {
XmlElement node = parser.start("prototype");
modelname = node.getAttribute("model");
int node = decoder.openElement(ElementId.ELEM_PROTOTYPE);
modelname = decoder.readString(AttributeId.ATTRIB_MODEL);
PrototypeModel protoModel =
dtmanage.getProgram().getCompilerSpec().getCallingConvention(modelname);
if (protoModel == null) {
throw new PcodeXMLException("Bad prototype model name: " + modelname);
}
hasThis = protoModel.hasThisPointer();
String val = node.getAttribute("extrapop");
String val = decoder.readString(AttributeId.ATTRIB_EXTRAPOP);
if (val.equals("unknown")) {
extrapop = PrototypeModel.UNKNOWN_EXTRAPOP;
}
@ -436,52 +434,61 @@ public class FunctionPrototype {
extrapop = SpecXmlUtils.decodeInt(val);
}
modellock = false;
if (node.hasAttribute("modellock")) {
modellock = SpecXmlUtils.decodeBoolean(node.getAttribute("modellock"));
}
dotdotdot = false;
if (node.hasAttribute("dotdotdot")) {
dotdotdot = SpecXmlUtils.decodeBoolean(node.getAttribute("dotdotdot"));
}
voidinputlock = false;
if (node.hasAttribute("voidlock")) {
voidinputlock = SpecXmlUtils.decodeBoolean(node.getAttribute("voidlock"));
}
isinline = false;
if (node.hasAttribute("inline")) {
isinline = SpecXmlUtils.decodeBoolean(node.getAttribute("inline"));
}
noreturn = false;
if (node.hasAttribute("noreturn")) {
noreturn = SpecXmlUtils.decodeBoolean(node.getAttribute("noreturn"));
}
custom = false;
if (node.hasAttribute("custom")) {
custom = SpecXmlUtils.decodeBoolean(node.getAttribute("custom"));
}
isConstruct = false;
if (node.hasAttribute("constructor")) {
isConstruct = SpecXmlUtils.decodeBoolean(node.getAttribute("constructor"));
}
isDestruct = false;
if (node.hasAttribute("destructor")) {
isDestruct = SpecXmlUtils.decodeBoolean(node.getAttribute("destructor"));
for (;;) {
int attribId = decoder.getNextAttributeId();
if (attribId == 0) {
break;
}
if (attribId == AttributeId.ATTRIB_MODELLOCK.getId()) {
modellock = decoder.readBool();
}
else if (attribId == AttributeId.ATTRIB_DOTDOTDOT.getId()) {
dotdotdot = decoder.readBool();
}
else if (attribId == AttributeId.ATTRIB_VOIDLOCK.getId()) {
voidinputlock = decoder.readBool();
}
else if (attribId == AttributeId.ATTRIB_INLINE.getId()) {
isinline = decoder.readBool();
}
else if (attribId == AttributeId.ATTRIB_NORETURN.getId()) {
noreturn = decoder.readBool();
}
else if (attribId == AttributeId.ATTRIB_CUSTOM.getId()) {
custom = decoder.readBool();
}
else if (attribId == AttributeId.ATTRIB_CONSTRUCTOR.getId()) {
isConstruct = decoder.readBool();
}
else if (attribId == AttributeId.ATTRIB_DESTRUCTOR.getId()) {
isDestruct = decoder.readBool();
}
}
XmlElement retel = parser.start("returnsym");
int retel = decoder.openElement(ElementId.ELEM_RETURNSYM);
outputlock = false;
if (retel.hasAttribute("typelock")) {
outputlock = SpecXmlUtils.decodeBoolean(retel.getAttribute("typelock"));
for (;;) {
int attribId = decoder.getNextAttributeId();
if (attribId == 0) {
break;
}
if (attribId == AttributeId.ATTRIB_TYPELOCK.getId()) {
outputlock = decoder.readBool();
}
}
parser.discardSubTree();
returnstorage = null; // For now don't use decompiler's return storage
returntype = dtmanage.readXMLDataType(parser);
parser.end(retel);
XmlElement peeknode = parser.peek();
if ((peeknode != null) && peeknode.isStart()) {
parser.discardSubTree(); // The decompiler may return an <inject> tag
}
parser.end(node);
decoder.skipElement();
returnstorage = null; // For now don't use decompiler's return storage
returntype = dtmanage.decodeDataType(decoder);
decoder.closeElement(retel);
decoder.closeElementSkipping(node);
}
}

View File

@ -21,7 +21,6 @@ import ghidra.program.model.data.DataType;
import ghidra.program.model.listing.*;
import ghidra.program.model.symbol.SymbolUtilities;
import ghidra.util.exception.InvalidInputException;
import ghidra.xml.XmlPullParser;
/**
* A global symbol as part of the decompiler's model of a function. This symbol can
@ -149,8 +148,8 @@ public class HighCodeSymbol extends HighSymbol {
}
@Override
public void restoreXML(XmlPullParser parser) throws PcodeXMLException {
super.restoreXML(parser);
public void decode(Decoder decoder) throws PcodeXMLException {
super.decode(decoder);
symbol = null;
}

View File

@ -20,9 +20,6 @@ import ghidra.program.model.data.AbstractIntegerDataType;
import ghidra.program.model.data.DataType;
import ghidra.program.model.listing.Program;
import ghidra.program.model.scalar.Scalar;
import ghidra.util.xml.SpecXmlUtils;
import ghidra.xml.XmlElement;
import ghidra.xml.XmlPullParser;
/**
*
@ -88,10 +85,19 @@ public class HighConstant extends HighVariable {
}
@Override
public void restoreXml(XmlPullParser parser) throws PcodeXMLException {
XmlElement el = parser.start("high");
long symref = SpecXmlUtils.decodeLong(el.getAttribute("symref"));
restoreInstances(parser, el);
public void decode(Decoder decoder) throws PcodeXMLException {
//int el = decoder.openElement(ElementId.ELEM_HIGH);
long symref = 0;
for (;;) {
int attribId = decoder.getNextAttributeId();
if (attribId == 0) {
break;
}
if (attribId == AttributeId.ATTRIB_SYMREF.getId()) {
symref = decoder.readUnsignedInteger();
}
}
decodeInstances(decoder);
pcaddr = function.getPCAddress(represent);
if (symref != 0) {
symbol = function.getLocalSymbolMap().getSymbol(symref);
@ -115,7 +121,7 @@ public class HighConstant extends HighVariable {
symbol.setHighVariable(this);
}
}
parser.end(el);
//decoder.closeElement(el);
}
}

View File

@ -15,12 +15,9 @@
*/
package ghidra.program.model.pcode;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import org.xml.sax.*;
import ghidra.program.database.function.FunctionDB;
import ghidra.program.database.symbol.CodeSymbol;
import ghidra.program.model.address.Address;
@ -28,11 +25,9 @@ import ghidra.program.model.address.AddressOutOfBoundsException;
import ghidra.program.model.lang.*;
import ghidra.program.model.listing.*;
import ghidra.program.model.symbol.*;
import ghidra.util.Msg;
import ghidra.util.exception.DuplicateNameException;
import ghidra.util.exception.InvalidInputException;
import ghidra.util.xml.SpecXmlUtils;
import ghidra.xml.*;
/**
*
@ -219,9 +214,9 @@ public class HighFunction extends PcodeSyntaxTree {
return super.newVarnode(sz, addr, id);
}
private void readHighXML(XmlPullParser parser) throws PcodeXMLException {
XmlElement el = parser.peek();
String classstring = el.getAttribute("class");
private void decodeHigh(Decoder decoder) throws PcodeXMLException {
int el = decoder.openElement(ElementId.ELEM_HIGH);
String classstring = decoder.readString(AttributeId.ATTRIB_CLASS);
HighVariable var;
switch (classstring.charAt(0)) {
case 'o':
@ -242,81 +237,80 @@ public class HighFunction extends PcodeSyntaxTree {
default:
throw new PcodeXMLException("Unknown HighVariable class string: " + classstring);
}
var.restoreXml(parser);
var.decode(decoder);
decoder.closeElement(el);
}
private void readHighlistXML(XmlPullParser parser) throws PcodeXMLException {
XmlElement el = parser.start("highlist");
while (parser.peek().isStart()) {
readHighXML(parser);
private void decodeHighlist(Decoder decoder) throws PcodeXMLException {
int el = decoder.openElement(ElementId.ELEM_HIGHLIST);
while (decoder.peekElement() != 0) {
decodeHigh(decoder);
}
parser.end(el);
decoder.closeElement(el);
}
/* (non-Javadoc)
* @see ghidra.program.model.pcode.PcodeSyntaxTree#readXML(org.jdom.Element)
*/
@Override
public void readXML(XmlPullParser parser) throws PcodeXMLException {
XmlElement start = parser.start("function");
String name = start.getAttribute("name");
public void decode(Decoder decoder) throws PcodeXMLException {
int start = decoder.openElement(ElementId.ELEM_FUNCTION);
String name = decoder.readString(AttributeId.ATTRIB_NAME);
if (!func.getName().equals(name)) {
throw new PcodeXMLException("Function name mismatch: " + func.getName() + " + " + name);
}
while (!parser.peek().isEnd()) {
XmlElement subel = parser.peek();
if (subel.getName().equals("addr")) {
subel = parser.start("addr");
Address addr = AddressXML.readXML(subel, getAddressFactory());
parser.end(subel);
for (;;) {
int subel = decoder.peekElement();
if (subel == 0) {
break;
}
if (subel == ElementId.ELEM_ADDR.getId()) {
Address addr = AddressXML.decode(decoder);
addr = func.getEntryPoint().getAddressSpace().getOverlayAddress(addr);
if (!func.getEntryPoint().equals(addr)) {
throw new PcodeXMLException("Mismatched address in function tag");
}
}
else if (subel.getName().equals("prototype")) {
proto.readPrototypeXML(parser, getDataTypeManager());
else if (subel == ElementId.ELEM_PROTOTYPE.getId()) {
proto.decodePrototype(decoder, getDataTypeManager());
}
else if (subel.getName().equals("localdb")) {
localSymbols.parseScopeXML(parser);
else if (subel == ElementId.ELEM_LOCALDB.getId()) {
localSymbols.decodeScope(decoder);
}
else if (subel.getName().equals("ast")) {
super.readXML(parser);
else if (subel == ElementId.ELEM_AST.getId()) {
super.decode(decoder);
}
else if (subel.getName().equals("highlist")) {
readHighlistXML(parser);
else if (subel == ElementId.ELEM_HIGHLIST.getId()) {
decodeHighlist(decoder);
}
else if (subel.getName().equals("jumptablelist")) {
readJumpTableListXML(parser);
else if (subel == ElementId.ELEM_JUMPTABLELIST.getId()) {
decodeJumpTableList(decoder);
}
else if (subel.getName().equals("override")) {
else if (subel == ElementId.ELEM_OVERRIDE.getId()) {
// Do nothing with override at the moment
parser.discardSubTree();
decoder.skipElement();
}
else if (subel.getName().equals("scope")) {
else if (subel == ElementId.ELEM_SCOPE.getId()) {
// This must be a subscope of the local scope
// Currently this can only hold static variables of the function
// which ghidra already knows about
parser.discardSubTree();
decoder.skipElement();
}
else {
throw new PcodeXMLException("Unknown tag in function: " + subel.getName());
throw new PcodeXMLException("Unknown element in function");
}
}
parser.end(start);
decoder.closeElement(start);
}
/**
* Read in the Jump Table list for this function from XML
* Decode the Jump Table list for this function from the stream
*
* @param parser is the XML stream
* @throws PcodeXMLException for any format errors
* @param decoder is the stream decoder
* @throws PcodeXMLException for invalid encodings
*/
private void readJumpTableListXML(XmlPullParser parser) throws PcodeXMLException {
XmlElement el = parser.start("jumptablelist");
while (parser.peek().isStart()) {
private void decodeJumpTableList(Decoder decoder) throws PcodeXMLException {
int el = decoder.openElement(ElementId.ELEM_JUMPTABLELIST);
while (decoder.peekElement() != 0) {
JumpTable table = new JumpTable(func.getEntryPoint().getAddressSpace());
table.restoreXml(parser, getAddressFactory());
table.decode(decoder);
if (!table.isEmpty()) {
if (jumpTables == null) {
jumpTables = new ArrayList<>();
@ -324,7 +318,7 @@ public class HighFunction extends PcodeSyntaxTree {
jumpTables.add(table);
}
}
parser.end(el);
decoder.closeElement(el);
}
protected Address getPCAddress(Varnode rep) {
@ -495,26 +489,6 @@ public class HighFunction extends PcodeSyntaxTree {
return resBuf.toString();
}
public static ErrorHandler getErrorHandler(final Object errOriginator,
final String targetName) {
return new ErrorHandler() {
@Override
public void error(SAXParseException exception) throws SAXException {
Msg.error(errOriginator, "Error parsing " + targetName, exception);
}
@Override
public void fatalError(SAXParseException exception) throws SAXException {
Msg.error(errOriginator, "Fatal error parsing " + targetName, exception);
}
@Override
public void warning(SAXParseException exception) throws SAXException {
Msg.warn(errOriginator, "Warning parsing " + targetName, exception);
}
};
}
public static Namespace findOverrideSpace(Function func) {
SymbolTable symtab = func.getProgram().getSymbolTable();
return findNamespace(symtab, func, "override");
@ -592,29 +566,6 @@ public class HighFunction extends PcodeSyntaxTree {
return res;
}
/**
* Create XML parse tree from an input XML string
*
* TODO: this probably doesn't belong here.
*
* @param xml is the XML string to parse
* @param handler is the handler to use for parsing errors
* @return the XML tree
*
* @throws PcodeXMLException for format errors in the XML
*/
static public XmlPullParser stringTree(InputStream xml, ErrorHandler handler)
throws PcodeXMLException {
try {
XmlPullParser parser =
XmlPullParserFactory.create(xml, "Decompiler Result Parser", handler, false);
return parser;
}
catch (Exception e) {
throw new PcodeXMLException("XML parsing error: " + e.getMessage(), e);
}
}
/**
* The decompiler treats some namespaces as equivalent to the "global" namespace.
* Return true if the given namespace is treated as equivalent.

View File

@ -18,9 +18,6 @@ package ghidra.program.model.pcode;
import ghidra.program.model.address.Address;
import ghidra.program.model.data.DataType;
import ghidra.util.Msg;
import ghidra.util.xml.SpecXmlUtils;
import ghidra.xml.XmlElement;
import ghidra.xml.XmlPullParser;
/**
*
@ -50,15 +47,23 @@ public class HighGlobal extends HighVariable {
}
@Override
public void restoreXml(XmlPullParser parser) throws PcodeXMLException {
XmlElement el = parser.start("high");
long symref = SpecXmlUtils.decodeLong(el.getAttribute("symref"));
String attrString = el.getAttribute("offset");
public void decode(Decoder decoder) throws PcodeXMLException {
// int el = decoder.openElement(ElementId.ELEM_HIGH);
long symref = 0;
offset = -1;
if (attrString != null) {
offset = SpecXmlUtils.decodeInt(attrString);
for (;;) {
int attribId = decoder.getNextAttributeId();
if (attribId == 0) {
break;
}
if (attribId == AttributeId.ATTRIB_OFFSET.getId()) {
offset = (int) decoder.readSignedInteger();
}
else if (attribId == AttributeId.ATTRIB_SYMREF.getId()) {
symref = decoder.readUnsignedInteger();
}
}
restoreInstances(parser, el);
decodeInstances(decoder);
if (symref != 0) {
symbol = function.getGlobalSymbolMap().getSymbol(symref);
}
@ -94,6 +99,6 @@ public class HighGlobal extends HighVariable {
}
symbol.setHighVariable(this);
parser.end(el);
// decoder.closeElement(el);
}
}

View File

@ -17,9 +17,6 @@ package ghidra.program.model.pcode;
import ghidra.program.model.address.Address;
import ghidra.program.model.data.DataType;
import ghidra.util.xml.SpecXmlUtils;
import ghidra.xml.XmlElement;
import ghidra.xml.XmlPullParser;
public class HighLocal extends HighVariable {
@ -53,15 +50,21 @@ public class HighLocal extends HighVariable {
}
@Override
public void restoreXml(XmlPullParser parser) throws PcodeXMLException {
XmlElement el = parser.start("high");
long symref = SpecXmlUtils.decodeLong(el.getAttribute("symref"));
public void decode(Decoder decoder) throws PcodeXMLException {
//int el = decoder.openElement(ElementId.ELEM_HIGH);
long symref = decoder.readUnsignedInteger(AttributeId.ATTRIB_SYMREF);
offset = -1;
String attrString = el.getAttribute("offset");
if (attrString != null) {
offset = SpecXmlUtils.decodeInt(attrString);
for (;;) {
int attribId = decoder.getNextAttributeId();
if (attribId == 0) {
break;
}
if (attribId == AttributeId.ATTRIB_OFFSET.getId()) {
offset = (int) decoder.readUnsignedInteger();
break;
}
}
restoreInstances(parser, el);
decodeInstances(decoder);
symbol = function.getLocalSymbolMap().getSymbol(symref);
if (symbol == null) {
throw new PcodeXMLException("HighLocal is missing symbol");
@ -75,7 +78,7 @@ public class HighLocal extends HighVariable {
pcaddr = symbol.getPCAddress();
symbol.setHighVariable(this);
parser.end(el);
//decoder.closeElement(el);
}
}

View File

@ -17,9 +17,6 @@ package ghidra.program.model.pcode;
import ghidra.program.model.address.Address;
import ghidra.program.model.data.DataType;
import ghidra.util.xml.SpecXmlUtils;
import ghidra.xml.XmlElement;
import ghidra.xml.XmlPullParser;
/**
*
@ -66,25 +63,32 @@ public class HighOther extends HighVariable {
}
@Override
public void restoreXml(XmlPullParser parser) throws PcodeXMLException {
XmlElement el = parser.start("high");
long symref = SpecXmlUtils.decodeLong(el.getAttribute("symref"));
public void decode(Decoder decoder) throws PcodeXMLException {
// int el = decoder.openElement(ElementId.ELEM_HIGH);
long symref = 0;
offset = -1;
String attrString = el.getAttribute("offset");
restoreInstances(parser, el);
for (;;) {
int attribId = decoder.getNextAttributeId();
if (attribId == 0) {
break;
}
if (attribId == AttributeId.ATTRIB_OFFSET.getId()) {
offset = (int) decoder.readSignedInteger();
}
else if (attribId == AttributeId.ATTRIB_SYMREF.getId()) {
symref = decoder.readUnsignedInteger();
}
}
decodeInstances(decoder);
name = "UNNAMED";
pcaddr = function.getPCAddress(represent);
if (symref != 0) {
offset = -1;
if (attrString != null) {
offset = SpecXmlUtils.decodeInt(attrString);
}
symbol = function.getLocalSymbolMap().getSymbol(symref);
if (symbol != null && offset < 0) {
name = symbol.getName();
}
}
parser.end(el);
// decoder.closeElement(el);
}
}

View File

@ -17,7 +17,6 @@ package ghidra.program.model.pcode;
import ghidra.program.model.address.Address;
import ghidra.program.model.data.DataType;
import ghidra.xml.XmlPullParser;
/**
*
@ -55,8 +54,8 @@ public class HighParam extends HighLocal {
}
@Override
public void restoreXml(XmlPullParser parser) throws PcodeXMLException {
super.restoreXml(parser);
public void decode(Decoder decoder) throws PcodeXMLException {
super.decode(decoder);
HighSymbol sym = getSymbol();
slot = sym.getCategoryIndex();
}

View File

@ -30,7 +30,6 @@ import ghidra.util.Msg;
import ghidra.util.exception.DuplicateNameException;
import ghidra.util.exception.InvalidInputException;
import ghidra.util.xml.SpecXmlUtils;
import ghidra.xml.*;
/**
*
@ -132,66 +131,66 @@ public class HighParamID extends PcodeSyntaxTree {
* @see ghidra.program.model.pcode.PcodeSyntaxTree#readXML(org.jdom.Element)
*/
@Override
public void readXML(XmlPullParser parser) throws PcodeXMLException {
XmlElement start = parser.start("parammeasures");
functionname = start.getAttribute("name");
public void decode(Decoder decoder) throws PcodeXMLException {
int start = decoder.openElement(ElementId.ELEM_PARAMMEASURES);
functionname = decoder.readString(AttributeId.ATTRIB_NAME);
if (!func.getName().equals(functionname)) {
throw new PcodeXMLException(
"Function name mismatch: " + func.getName() + " + " + functionname);
}
while (!parser.peek().isEnd()) {
XmlElement subel = parser.peek();
if (subel.getName().equals("addr")) {
subel = parser.start("addr");
functionaddress = AddressXML.readXML(subel, getAddressFactory());
parser.end(subel);
for (;;) {
int subel = decoder.peekElement();
if (subel == 0) {
break;
}
if (subel == ElementId.ELEM_ADDR.getId()) {
functionaddress = AddressXML.decode(decoder);
functionaddress =
func.getEntryPoint().getAddressSpace().getOverlayAddress(functionaddress);
if (!func.getEntryPoint().equals(functionaddress)) {
throw new PcodeXMLException("Mismatched address in function tag");
}
}
else if (subel.getName().equals("proto")) {
subel = parser.start("proto");
modelname = subel.getAttribute("model");
String val = subel.getAttribute("extrapop");
else if (subel == ElementId.ELEM_PROTO.getId()) {
decoder.openElement();
modelname = decoder.readString(AttributeId.ATTRIB_MODEL);
String val = decoder.readString(AttributeId.ATTRIB_EXTRAPOP);
if (val.equals("unknown")) {
protoextrapop = PrototypeModel.UNKNOWN_EXTRAPOP;
}
else {
protoextrapop = SpecXmlUtils.decodeInt(val);
}
parser.end(subel);
decoder.closeElement(subel);
}
else if (subel.getName().equals("input")) {
parseParamMeasureXML(parser, inputlist, "input");
else if (subel == ElementId.ELEM_INPUT.getId()) {
decodeParamMeasure(decoder, inputlist);
}
else if (subel.getName().equals("output")) {
parseParamMeasureXML(parser, outputlist, "output");
else if (subel == ElementId.ELEM_OUTPUT.getId()) {
decodeParamMeasure(decoder, outputlist);
}
else {
throw new PcodeXMLException("Unknown tag in parammeasures: " + subel.getName());
throw new PcodeXMLException("Unknown tag in parammeasures");
}
}
parser.end(start);
decoder.closeElement(start);
}
/**
* Read in the inputs or outputs list for this function from an XML rep
* @param parser is the XML parser
* Decode the inputs or outputs list for this function from a stream.
* @param decoder is the stream decoder
* @param pmlist is populated with the resulting list
* @param tag is the name of the tag
* @throws PcodeXMLException for improperly formed XML
* @throws PcodeXMLException for invalid encodings
*/
private void parseParamMeasureXML(XmlPullParser parser, List<ParamMeasure> pmlist, String tag)
private void decodeParamMeasure(Decoder decoder, List<ParamMeasure> pmlist)
throws PcodeXMLException {
XmlElement el = parser.start(tag);
int el = decoder.openElement();
ParamMeasure pm = new ParamMeasure();
pm.readXml(parser, this);
pm.decode(decoder, this);
if (!pm.isEmpty()) {
pmlist.add(pm);
}
parser.end(el);
decoder.closeElement(el);
}
public static ErrorHandler getErrorHandler(final Object errOriginator,
@ -214,29 +213,6 @@ public class HighParamID extends PcodeSyntaxTree {
};
}
/**
* Create and XML SAX parse tree from an input XML string
*
* TODO: this probably doesn't belong here.
*
* @param xml string to parse
* @param handler is the error handler
* @return an XML tree element
*
* @throws PcodeXMLException for improper XML
*/
static public XmlPullParser stringTree(String xml, ErrorHandler handler)
throws PcodeXMLException {
try {
XmlPullParser parser =
XmlPullParserFactory.create(xml, "Decompiler Result Parser", handler, false);
return parser;
}
catch (Exception e) {
throw new PcodeXMLException("XML parsing error: " + e.getMessage(), e);
}
}
/**
* Update any parameters for this Function from parameters defined in this map.
*
@ -244,7 +220,6 @@ public class HighParamID extends PcodeSyntaxTree {
* @param srctype function signature source
*/
public void storeReturnToDatabase(boolean storeDataTypes, SourceType srctype) {
PcodeDataTypeManager dtManage = getDataTypeManager();
try {
//TODO: Currently, only storing one output, so looking for the best to report. When possible, change this to report all
int best_index = 0;
@ -285,7 +260,6 @@ public class HighParamID extends PcodeSyntaxTree {
* @param srctype function signature source
*/
public void storeParametersToDatabase(boolean storeDataTypes, SourceType srctype) {
PcodeDataTypeManager dtManage = getDataTypeManager();
try {
List<Variable> params = new ArrayList<>();
for (ParamMeasure pm : inputlist) {

View File

@ -23,8 +23,6 @@ import ghidra.program.model.symbol.Namespace;
import ghidra.program.model.symbol.Symbol;
import ghidra.util.exception.InvalidInputException;
import ghidra.util.xml.SpecXmlUtils;
import ghidra.xml.XmlElement;
import ghidra.xml.XmlPullParser;
/**
* A symbol within the decompiler's model of a particular function. The symbol has a name and a data-type
@ -405,69 +403,74 @@ public class HighSymbol {
buf.append("</symbol>\n");
}
protected void restoreXMLHeader(XmlElement symel) throws PcodeXMLException {
id = SpecXmlUtils.decodeLong(symel.getAttribute("id"));
if (id == 0) {
throw new PcodeXMLException("missing unique symbol id");
}
protected void decodeHeader(Decoder decoder) throws PcodeXMLException {
name = null;
id = 0;
typelock = false;
String typelockstr = symel.getAttribute("typelock");
if ((typelockstr != null) && (SpecXmlUtils.decodeBoolean(typelockstr))) {
typelock = true;
}
namelock = false;
String namelockstr = symel.getAttribute("namelock");
if ((namelockstr != null) && (SpecXmlUtils.decodeBoolean(namelockstr))) {
namelock = true;
}
isThis = false;
String thisstring = symel.getAttribute("thisptr");
if ((thisstring != null) && (SpecXmlUtils.decodeBoolean(thisstring))) {
isThis = true;
}
isHidden = false;
String hiddenstring = symel.getAttribute("hiddenretparm");
if ((hiddenstring != null) && (SpecXmlUtils.decodeBoolean(hiddenstring))) {
isHidden = true;
}
// isolate = false;
// String isolatestr = symel.getAttribute("merge");
// if ((isolatestr != null) && !SpecXmlUtils.decodeBoolean(isolatestr)) {
// isolate = true;
// }
name = symel.getAttribute("name");
categoryIndex = -1;
category = -1;
if (symel.hasAttribute("cat")) {
category = SpecXmlUtils.decodeInt(symel.getAttribute("cat"));
if (category == 0) {
categoryIndex = SpecXmlUtils.decodeInt(symel.getAttribute("index"));
for (;;) {
int attribId = decoder.getNextAttributeId();
if (attribId == 0) {
break;
}
if (attribId == AttributeId.ATTRIB_ID.getId()) {
id = decoder.readUnsignedInteger();
}
else if (attribId == AttributeId.ATTRIB_TYPELOCK.getId()) {
typelock = decoder.readBool();
}
else if (attribId == AttributeId.ATTRIB_NAMELOCK.getId()) {
namelock = decoder.readBool();
}
else if (attribId == AttributeId.ATTRIB_THISPTR.getId()) {
isThis = decoder.readBool();
}
else if (attribId == AttributeId.ATTRIB_HIDDENRETPARM.getId()) {
isHidden = decoder.readBool();
}
else if (attribId == AttributeId.ATTRIB_NAME.getId()) {
name = decoder.readString();
}
else if (attribId == AttributeId.ATTRIB_CAT.getId()) {
category = (int) decoder.readSignedInteger();
}
else if (attribId == AttributeId.ATTRIB_INDEX.getId()) {
categoryIndex = (int) decoder.readUnsignedInteger();
}
}
if (id == 0) {
throw new PcodeXMLException("missing unique symbol id");
}
}
/**
* Restore this symbol object and its associated mappings from an XML description
* in the given stream.
* @param parser is the given XML stream
* @throws PcodeXMLException if the XML description is invalid
* Decode this symbol object and its associated mappings from the stream.
* @param decoder is the stream decoder
* @throws PcodeXMLException for invalid encodings
*/
public void restoreXML(XmlPullParser parser) throws PcodeXMLException {
XmlElement symel = parser.start("symbol");
restoreXMLHeader(symel);
type = dtmanage.readXMLDataType(parser);
parser.end(symel);
public void decode(Decoder decoder) throws PcodeXMLException {
int symel = decoder.openElement(ElementId.ELEM_SYMBOL);
decodeHeader(decoder);
type = dtmanage.decodeDataType(decoder);
decoder.closeElement(symel);
if (categoryIndex >= 0 && name.startsWith("$$undef")) {
// use default parameter name
name = "param_" + Integer.toString(categoryIndex + 1);
}
while (parser.peek().isStart()) {
XmlElement el = parser.peek();
for (;;) {
int el = decoder.peekElement();
if (el == 0) {
break;
}
SymbolEntry entry;
if (el.getName().equals("hash")) {
if (el == ElementId.ELEM_HASH.getId()) {
entry = new DynamicEntry(this);
}
else if (this instanceof HighCodeSymbol) {
@ -476,7 +479,7 @@ public class HighSymbol {
else {
entry = new MappedEntry(this);
}
entry.restoreXML(parser);
entry.decode(decoder);
addMapEntry(entry);
}
if ((isThis || isHidden) && entryList != null) {
@ -496,21 +499,21 @@ public class HighSymbol {
}
/**
* Restore a full HighSymbol from the next &lt;mapsym&gt; tag in the given XML stream.
* This method acts as an XML based HighSymbol factory, instantiating the correct class
* based on the particular tags.
* @param parser is the given XML stream
* Restore a full HighSymbol from the next &lt;mapsym&gt; element in the stream.
* This method acts as a HighSymbol factory, instantiating the correct class
* based on the particular elements.
* @param decoder is the stream decoder
* @param isGlobal is true if this symbol is being read into a global scope
* @param high is the function model that will own the new symbol
* @return the new symbol
* @throws PcodeXMLException if the XML description is invalid
* @throws PcodeXMLException for invalid encodings
*/
public static HighSymbol restoreMapSymXML(XmlPullParser parser, boolean isGlobal,
HighFunction high) throws PcodeXMLException {
public static HighSymbol decodeMapSym(Decoder decoder, boolean isGlobal, HighFunction high)
throws PcodeXMLException {
HighSymbol res = null;
parser.start("mapsym");
XmlElement symel = parser.peek();
if (symel.getName().equals("equatesymbol")) {
int mapel = decoder.openElement(ElementId.ELEM_MAPSYM);
int symel = decoder.peekElement();
if (symel == ElementId.ELEM_EQUATESYMBOL.getId()) {
res = new EquateSymbol(high);
}
else if (isGlobal) {
@ -520,19 +523,23 @@ public class HighSymbol {
else {
res = new HighSymbol(high);
}
res.restoreXML(parser);
while (parser.peek().isStart()) {
res.decode(decoder);
for (;;) {
SymbolEntry entry;
if (parser.peek().getName().equals("hash")) {
int subid = decoder.peekElement();
if (subid == 0) {
break;
}
if (subid == ElementId.ELEM_HASH.getId()) {
entry = new DynamicEntry(res);
}
else {
entry = new MappedEntry(res);
}
entry.restoreXML(parser);
entry.decode(decoder);
res.addMapEntry(entry);
}
parser.end();
decoder.closeElement(mapel);
return res;
}

View File

@ -18,9 +18,6 @@ package ghidra.program.model.pcode;
import java.util.ArrayList;
import ghidra.program.model.data.DataType;
import ghidra.util.xml.SpecXmlUtils;
import ghidra.xml.XmlElement;
import ghidra.xml.XmlPullParser;
/**
*
@ -58,7 +55,7 @@ public abstract class HighVariable {
protected void setHighOnInstances() {
for (Varnode instance : instances) {
if (instance instanceof VarnodeAST) {
((VarnodeAST)instance).setHigh(this);
((VarnodeAST) instance).setHigh(this);
}
}
}
@ -141,15 +138,13 @@ public abstract class HighVariable {
}
/**
* Restore the data-type and the Varnode instances of this HighVariable.
* Decode the data-type and the Varnode instances of this HighVariable.
* The "representative" Varnode is also populated.
* @param parser is the XML stream
* @param el is the root {@code <high>} tag
* @throws PcodeXMLException if the XML is not valid
* @param decoder is the stream decoder
* @throws PcodeXMLException for invalid encodings
*/
protected void restoreInstances(XmlPullParser parser, XmlElement el)
throws PcodeXMLException {
int repref = SpecXmlUtils.decodeInt(el.getAttribute("repref"));
protected void decodeInstances(Decoder decoder) throws PcodeXMLException {
int repref = (int) decoder.readUnsignedInteger(AttributeId.ATTRIB_REPREF);
Varnode rep = function.getRef(repref);
if (rep == null) {
throw new PcodeXMLException("Undefined varnode reference");
@ -157,17 +152,15 @@ public abstract class HighVariable {
type = null;
ArrayList<Varnode> vnlist = new ArrayList<Varnode>();
if (parser.peek().isStart()) {
type = function.getDataTypeManager().readXMLDataType(parser);
}
ArrayList<Varnode> vnlist = new ArrayList<>();
type = function.getDataTypeManager().decodeDataType(decoder);
if (type == null) {
throw new PcodeXMLException("Missing <type> for HighVariable");
}
while (parser.peek().isStart()) {
Varnode vn = Varnode.readXML(parser, function);
for (;;) {
int subel = decoder.peekElement();
if (subel == 0) {
break;
}
Varnode vn = Varnode.decode(decoder, function);
vnlist.add(vn);
}
Varnode[] vnarray = new Varnode[vnlist.size()];
@ -193,9 +186,9 @@ public abstract class HighVariable {
}
/**
* Restore this HighVariable from a {@code <high>} XML tag
* @param parser is the XML stream
* @throws PcodeXMLException if the XML is not valid
* Decode this HighVariable from a {@code <high>} element in the stream
* @param decoder is the stream decoder
* @throws PcodeXMLException for invalid encodings
*/
public abstract void restoreXml(XmlPullParser parser) throws PcodeXMLException;
public abstract void decode(Decoder decoder) throws PcodeXMLException;
}

View File

@ -23,9 +23,6 @@ import ghidra.program.model.listing.Function;
import ghidra.program.model.listing.Program;
import ghidra.program.model.symbol.*;
import ghidra.util.exception.InvalidInputException;
import ghidra.util.xml.SpecXmlUtils;
import ghidra.xml.XmlElement;
import ghidra.xml.XmlPullParser;
/**
* JumpTable found as part of the decompilation of a function
@ -78,14 +75,12 @@ public class JumpTable {
return num;
}
public void restoreXml(XmlPullParser parser, AddressFactory addrFactory) {
XmlElement el = parser.start("loadtable");
size = SpecXmlUtils.decodeInt(el.getAttribute("size"));
num = SpecXmlUtils.decodeInt(el.getAttribute("num"));
XmlElement subel = parser.start("addr");
addr = translateOverlayAddress(AddressXML.readXML(subel, addrFactory));
parser.end(subel);
parser.end(el);
public void decode(Decoder decoder) throws PcodeXMLException {
int el = decoder.openElement(ElementId.ELEM_LOADTABLE);
size = (int) decoder.readSignedInteger(AttributeId.ATTRIB_SIZE);
num = (int) decoder.readSignedInteger(AttributeId.ATTRIB_NUM);
addr = translateOverlayAddress(AddressXML.decode(decoder));
decoder.closeElement(el);
}
}
@ -159,61 +154,62 @@ public class JumpTable {
}
/**
* Create a JumpTable object by parsing the XML elements
* @param parser is the XML parser
* @param addrFactory is used to look-up address spaces
* @throws PcodeXMLException for improperly formed XML
* Decode a JumpTable object from the stream.
* @param decoder is the stream decoder
* @throws PcodeXMLException for invalid encodings
*/
public void restoreXml(XmlPullParser parser, AddressFactory addrFactory)
throws PcodeXMLException {
XmlElement el = parser.start("jumptable");
try {
ArrayList<Address> aTable = new ArrayList<>();
ArrayList<Integer> lTable = new ArrayList<>();
ArrayList<LoadTable> ldTable = new ArrayList<>();
public void decode(Decoder decoder) throws PcodeXMLException {
int el = decoder.openElement(ElementId.ELEM_JUMPTABLE);
if (decoder.peekElement() == 0) { // Empty jumptable
decoder.closeElement(el);
return;
}
ArrayList<Address> aTable = new ArrayList<>();
ArrayList<Integer> lTable = new ArrayList<>();
ArrayList<LoadTable> ldTable = new ArrayList<>();
if (!parser.peek().isStart()) { // Empty jumptable
return;
Address switchAddr = translateOverlayAddress(AddressXML.decode(decoder));
for (;;) {
int subel = decoder.peekElement();
if (subel == 0) {
break;
}
XmlElement addrel = parser.start("addr");
Address switchAddr = translateOverlayAddress(AddressXML.readXML(addrel, addrFactory));
parser.end(addrel);
while (parser.peek().isStart()) {
if (parser.peek().getName().equals("dest")) {
XmlElement subel = parser.start("dest");
Address caseAddr =
translateOverlayAddress(AddressXML.readXML(subel, addrFactory));
aTable.add(caseAddr);
String slabel = subel.getAttribute("label");
if (slabel != null) {
int label = SpecXmlUtils.decodeInt(slabel);
if (subel == ElementId.ELEM_DEST.getId()) {
decoder.openElement();
Address caseAddr = translateOverlayAddress(AddressXML.decodeFromAttributes(decoder));
aTable.add(caseAddr);
decoder.rewindAttributes();
for (;;) {
int attribId = decoder.getNextAttributeId();
if (attribId == 0) {
break;
}
if (attribId == AttributeId.ATTRIB_LABEL.getId()) {
int label = (int) decoder.readUnsignedInteger();
lTable.add(label);
}
parser.end(subel);
}
else if (parser.peek().getName().equals("loadtable")) {
LoadTable loadtable = new LoadTable();
loadtable.restoreXml(parser, addrFactory);
ldTable.add(loadtable);
}
else {
parser.discardSubTree();
}
decoder.closeElement(subel);
}
else if (subel == ElementId.ELEM_LOADTABLE.getId()) {
LoadTable loadtable = new LoadTable();
loadtable.decode(decoder);
ldTable.add(loadtable);
}
else {
decoder.skipElement();
}
}
opAddress = switchAddr;
addressTable = new Address[aTable.size()];
aTable.toArray(addressTable);
labelTable = new Integer[lTable.size()];
lTable.toArray(labelTable);
loadTable = new LoadTable[ldTable.size()];
ldTable.toArray(loadTable);
}
finally {
parser.end(el);
}
opAddress = switchAddr;
addressTable = new Address[aTable.size()];
aTable.toArray(addressTable);
labelTable = new Integer[lTable.size()];
lTable.toArray(labelTable);
loadTable = new LoadTable[ldTable.size()];
ldTable.toArray(loadTable);
decoder.closeElement(el);
}
public void buildXml(StringBuilder buf) {

View File

@ -24,8 +24,6 @@ import ghidra.program.model.listing.*;
import ghidra.program.model.symbol.*;
import ghidra.util.SystemUtilities;
import ghidra.util.xml.SpecXmlUtils;
import ghidra.xml.XmlElement;
import ghidra.xml.XmlPullParser;
/**
* A container for local symbols within the decompiler's model of a function. It contains HighSymbol
@ -261,40 +259,40 @@ public class LocalSymbolMap {
}
/**
* Parse a &lt;mapsym&gt; tag in XML
* @param parser is the XML parser
* Decode a &lt;mapsym&gt; element from the stream.
* @param decoder is the stream decoder
* @return the reconstructed HighSymbol
* @throws PcodeXMLException for problems sub tags
*/
private HighSymbol parseSymbolXML(XmlPullParser parser) throws PcodeXMLException {
HighSymbol res = HighSymbol.restoreMapSymXML(parser, false, func);
private HighSymbol decodeSymbol(Decoder decoder) throws PcodeXMLException {
HighSymbol res = HighSymbol.decodeMapSym(decoder, false, func);
insertSymbol(res);
return res;
}
/**
* Parse a local symbol scope in XML from the &lt;localdb&gt; tag.
* Decode a local symbol scope from the stream
*
* @param parser is the XML parser
* @throws PcodeXMLException for problems parsing individual tags
* @param decoder is the stream decoder
* @throws PcodeXMLException for invalid encodings
*/
public void parseScopeXML(XmlPullParser parser) throws PcodeXMLException {
XmlElement el = parser.start("localdb");
spacename = el.getAttribute("main");
XmlElement scopeel = parser.start("scope");
public void decodeScope(Decoder decoder) throws PcodeXMLException {
int el = decoder.openElement(ElementId.ELEM_LOCALDB);
spacename = decoder.readString(AttributeId.ATTRIB_MAIN);
int scopeel = decoder.openElement(ElementId.ELEM_SCOPE);
parser.discardSubTree(); // This is the parent scope path
parser.discardSubTree(); // This is the address range
decoder.skipElement(); // This is the parent scope path
decoder.skipElement(); // This is the address range
addrMappedSymbols.clear(); // Clear out any old map
symbolMap.clear(); // Clear out any old map
addrMappedSymbols.clear(); // Clear out any old map
symbolMap.clear(); // Clear out any old map
XmlElement nextEl = parser.peek();
if (nextEl != null && nextEl.isStart() && "symbollist".equals(nextEl.getName())) {
parseSymbolList(parser);
int nextEl = decoder.peekElement();
if (nextEl == ElementId.ELEM_SYMBOLLIST.getId()) {
decodeSymbolList(decoder);
}
parser.end(scopeel);
parser.end(el);
decoder.closeElement(scopeel);
decoder.closeElement(el);
}
private static final Comparator<HighSymbol> PARAM_SYMBOL_SLOT_COMPARATOR = new Comparator<>() {
@ -305,15 +303,15 @@ public class LocalSymbolMap {
};
/**
* Add mapped symbols to this LocalVariableMap, by parsing the &lt;symbollist&gt; and &lt;mapsym&gt; tags.
* @param parser is the XML parser
* @throws PcodeXMLException for problems parsing a tag
* Add mapped symbols to this LocalVariableMap, by decoding the &lt;symbollist&gt; and &lt;mapsym&gt; elements
* @param decoder is the stream decoder
* @throws PcodeXMLException for invalid encodings
*/
public void parseSymbolList(XmlPullParser parser) throws PcodeXMLException {
XmlElement el = parser.start("symbollist");
public void decodeSymbolList(Decoder decoder) throws PcodeXMLException {
int el = decoder.openElement(ElementId.ELEM_SYMBOLLIST);
ArrayList<HighSymbol> parms = new ArrayList<>();
while (parser.peek().isStart()) {
HighSymbol sym = parseSymbolXML(parser);
while (decoder.peekElement() != 0) {
HighSymbol sym = decodeSymbol(decoder);
if (sym.isParameter()) {
parms.add(sym);
}
@ -321,7 +319,7 @@ public class LocalSymbolMap {
paramSymbols = new HighSymbol[parms.size()];
parms.toArray(paramSymbols);
Arrays.sort(paramSymbols, PARAM_SYMBOL_SLOT_COMPARATOR);
parser.end(el);
decoder.closeElement(el);
}
/**

View File

@ -17,7 +17,6 @@ package ghidra.program.model.pcode;
import ghidra.program.model.listing.Data;
import ghidra.program.model.listing.VariableStorage;
import ghidra.xml.XmlPullParser;
/**
* A normal address based HighSymbol mapping with an associated Data object
@ -52,8 +51,8 @@ public class MappedDataEntry extends MappedEntry {
}
@Override
public void restoreXML(XmlPullParser parser) throws PcodeXMLException {
super.restoreXML(parser);
public void decode(Decoder decoder) throws PcodeXMLException {
super.decode(decoder);
data = symbol.getProgram().getListing().getDataAt(storage.getMinAddress());
}

View File

@ -15,7 +15,8 @@
*/
package ghidra.program.model.pcode;
import ghidra.program.model.address.*;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSpace;
import ghidra.program.model.data.AbstractFloatDataType;
import ghidra.program.model.listing.Program;
import ghidra.program.model.listing.VariableStorage;
@ -23,8 +24,6 @@ import ghidra.program.model.mem.MemoryBlock;
import ghidra.program.model.symbol.Reference;
import ghidra.program.model.symbol.ReferenceIterator;
import ghidra.util.exception.InvalidInputException;
import ghidra.xml.XmlElement;
import ghidra.xml.XmlPullParser;
/**
* A normal mapping of a HighSymbol to a particular Address, consuming a set number of bytes
@ -53,33 +52,33 @@ public class MappedEntry extends SymbolEntry {
}
@Override
public void restoreXML(XmlPullParser parser) throws PcodeXMLException {
public void decode(Decoder decoder) throws PcodeXMLException {
HighFunction function = symbol.function;
Program program = function.getFunction().getProgram();
AddressFactory addrFactory = function.getAddressFactory();
XmlElement addrel = parser.start("addr");
int addrel = decoder.openElement(ElementId.ELEM_ADDR);
int sz = symbol.type.getLength();
if (sz == 0) {
throw new PcodeXMLException(
"Invalid symbol 0-sized data-type: " + symbol.type.getName());
}
try {
Address varAddr = AddressXML.readXML(addrel, addrFactory);
Address varAddr = AddressXML.decodeFromAttributes(decoder);
AddressSpace spc = varAddr.getAddressSpace();
if ((spc == null) || (spc.getType() != AddressSpace.TYPE_VARIABLE)) {
storage = new VariableStorage(program, varAddr, sz);
}
else {
storage = function.readXMLVarnodePieces(addrel, varAddr);
decoder.rewindAttributes();
storage = function.decodeVarnodePieces(decoder, varAddr);
}
}
catch (InvalidInputException e) {
throw new PcodeXMLException("Invalid storage: " + e.getMessage());
}
parser.end(addrel);
decoder.closeElement(addrel);
parseRangeList(parser);
decodeRangeList(decoder);
}
@Override

View File

@ -16,9 +16,6 @@
package ghidra.program.model.pcode;
import ghidra.program.model.data.DataType;
import ghidra.util.xml.SpecXmlUtils;
import ghidra.xml.XmlElement;
import ghidra.xml.XmlPullParser;
/**
* ParamMeasure
@ -43,24 +40,24 @@ public class ParamMeasure {
}
public boolean isEmpty() {
if (vn == null)
if (vn == null) {
return true;
}
return false;
}
/**
* Create a ParamMeasure object by parsing the XML elements
* @param parser xml parser
* Decode a ParamMeasure object from the stream.
* @param decoder is the stream decoder
* @param factory pcode factory
* @throws PcodeXMLException if an error occurs when reading the xml.
* @throws PcodeXMLException for an invalid encoding
*/
public void readXml(XmlPullParser parser, PcodeFactory factory) throws PcodeXMLException {
vn = Varnode.readXML(parser, factory);
dt = factory.getDataTypeManager().readXMLDataType(parser);
XmlElement rankel = parser.start("rank");
String strVal = rankel.getAttribute("val");
rank = SpecXmlUtils.decodeInt(strVal);
parser.end(rankel);
public void decode(Decoder decoder, PcodeFactory factory) throws PcodeXMLException {
vn = Varnode.decode(decoder, factory);
dt = factory.getDataTypeManager().decodeDataType(decoder);
int rankel = decoder.openElement(ElementId.ELEM_RANK);
rank = (int) decoder.readSignedInteger(AttributeId.ATTRIB_VAL);
decoder.closeElement(rankel);
}
public Varnode getVarnode() {

View File

@ -21,8 +21,6 @@ import java.util.ArrayList;
import ghidra.program.model.address.Address;
import ghidra.util.xml.SpecXmlUtils;
import ghidra.xml.XmlElement;
import ghidra.xml.XmlPullParser;
/**
*
@ -160,32 +158,34 @@ public class PcodeBlock {
}
/**
* Restore meta-data for a single edge
* @param parser
* Decode a single edge
* @param decoder is the stream decoder
* @param resolver used to recover PcodeBlock reference
* @throws PcodeXMLException
* @throws PcodeXMLException for invalid encodings
*/
public void restoreXml(XmlPullParser parser, BlockMap resolver) throws PcodeXMLException {
XmlElement el = parser.start("edge");
public void decode(Decoder decoder, BlockMap resolver) throws PcodeXMLException {
int el = decoder.openElement(ElementId.ELEM_EDGE);
label = 0; // Tag does not currently contain info about label
int endIndex = SpecXmlUtils.decodeInt(el.getAttribute("end"));
int endIndex = (int) decoder.readSignedInteger(AttributeId.ATTRIB_END);
point = resolver.findLevelBlock(endIndex);
if (point == null)
if (point == null) {
throw new PcodeXMLException("Bad serialized edge in block graph");
reverse_index = SpecXmlUtils.decodeInt(el.getAttribute("rev"));
parser.end(el);
}
reverse_index = (int) decoder.readSignedInteger(AttributeId.ATTRIB_REV);
decoder.closeElement(el);
}
public void restoreXml(XmlPullParser parser, ArrayList<? extends PcodeBlock> blockList)
public void decode(Decoder decoder, ArrayList<? extends PcodeBlock> blockList)
throws PcodeXMLException {
XmlElement el = parser.start("edge");
int el = decoder.openElement(ElementId.ELEM_EDGE);
label = 0; // Tag does not currently contain info about label
int endIndex = SpecXmlUtils.decodeInt(el.getAttribute("end"));
int endIndex = (int) decoder.readSignedInteger(AttributeId.ATTRIB_END);
point = blockList.get(endIndex);
if (point == null)
if (point == null) {
throw new PcodeXMLException("Bad serialized edge in block list");
reverse_index = SpecXmlUtils.decodeInt(el.getAttribute("rev"));
parser.end(el);
}
reverse_index = (int) decoder.readSignedInteger(AttributeId.ATTRIB_REV);
decoder.closeElement(el);
}
@Override
@ -198,8 +198,8 @@ public class PcodeBlock {
index = -1;
blocktype = PLAIN;
parent = null;
intothis = new ArrayList<BlockEdge>();
outofthis = new ArrayList<BlockEdge>();
intothis = new ArrayList<>();
outofthis = new ArrayList<>();
}
public int getType() {
@ -240,38 +240,37 @@ public class PcodeBlock {
}
/**
* Restore the next input edge via XML
* @param parser
* @param resolver
* @throws PcodeXMLException
* Decode the next input edge from the stream
* @param decoder is the stream decoder
* @param resolver is used to find PcodeBlocks
* @throws PcodeXMLException for any invalid encoding
*/
protected void restoreNextInEdge(XmlPullParser parser, BlockMap resolver)
throws PcodeXMLException {
protected void decodeNextInEdge(Decoder decoder, BlockMap resolver) throws PcodeXMLException {
BlockEdge inEdge = new BlockEdge();
intothis.add(inEdge);
inEdge.restoreXml(parser, resolver);
while(inEdge.point.outofthis.size() <= inEdge.reverse_index) {
inEdge.decode(decoder, resolver);
while (inEdge.point.outofthis.size() <= inEdge.reverse_index) {
inEdge.point.outofthis.add(null);
}
BlockEdge outEdge = new BlockEdge(this,0,intothis.size()-1);
BlockEdge outEdge = new BlockEdge(this, 0, intothis.size() - 1);
inEdge.point.outofthis.set(inEdge.reverse_index, outEdge);
}
/**
* Restore the next input edge via XML. Resolve block indices via a blockList
* @param parser
* Decode the next input edge from the stream. Resolve block indices via a blockList
* @param decoder is the stream decoder
* @param blockList allows lookup of PcodeBlock via index
* @throws PcodeXMLException
* @throws PcodeXMLException for any invalid encoding
*/
protected void restoreNextInEdge(XmlPullParser parser,
ArrayList<? extends PcodeBlock> blockList) throws PcodeXMLException {
protected void decodeNextInEdge(Decoder decoder, ArrayList<? extends PcodeBlock> blockList)
throws PcodeXMLException {
BlockEdge inEdge = new BlockEdge();
intothis.add(inEdge);
inEdge.restoreXml(parser, blockList);
while(inEdge.point.outofthis.size() <= inEdge.reverse_index) {
inEdge.decode(decoder, blockList);
while (inEdge.point.outofthis.size() <= inEdge.reverse_index) {
inEdge.point.outofthis.add(null);
}
BlockEdge outEdge = new BlockEdge(this,0,intothis.size()-1);
BlockEdge outEdge = new BlockEdge(this, 0, intothis.size() - 1);
inEdge.point.outofthis.set(inEdge.reverse_index, outEdge);
}
@ -349,8 +348,8 @@ public class PcodeBlock {
SpecXmlUtils.encodeSignedIntegerAttribute(buffer, "index", index);
}
public void restoreXmlHeader(XmlElement el) throws PcodeXMLException {
index = SpecXmlUtils.decodeInt(el.getAttribute("index"));
public void decodeHeader(Decoder decoder) throws PcodeXMLException {
index = (int) decoder.readSignedInteger(AttributeId.ATTRIB_INDEX);
}
/**
@ -365,28 +364,29 @@ public class PcodeBlock {
public void saveXmlEdges(Writer writer) throws IOException {
StringBuilder buf = new StringBuilder();
for (int i = 0; i < intothis.size(); ++i) {
intothis.get(i).saveXml(buf);
for (BlockEdge element : intothis) {
element.saveXml(buf);
}
writer.write(buf.toString());
}
/**
* Restore the any additional information beyond header and edges from XML
* @param parser is the XML parser
* Restore the any additional information beyond header and edges from stream
* @param decoder is the stream decoder
* @param resolver is for looking up edge references
* @throws PcodeXMLException for invalid XML descriptions
* @throws PcodeXMLException for invalid encoding
*/
public void restoreXmlBody(XmlPullParser parser, BlockMap resolver) throws PcodeXMLException {
public void decodeBody(Decoder decoder, BlockMap resolver) throws PcodeXMLException {
// No body to restore by default
}
public void restoreXmlEdges(XmlPullParser parser, BlockMap resolver) throws PcodeXMLException {
while (parser.peek().isStart()) {
if (!parser.peek().getName().equals("edge")) {
return;
public void decodeEdges(Decoder decoder, BlockMap resolver) throws PcodeXMLException {
for (;;) {
int el = decoder.peekElement();
if (el != ElementId.ELEM_EDGE.getId()) {
break;
}
restoreNextInEdge(parser, resolver);
decodeNextInEdge(decoder, resolver);
}
}
@ -401,11 +401,11 @@ public class PcodeBlock {
writer.write("</block>\n");
}
public void restoreXml(XmlPullParser parser, BlockMap resolver) throws PcodeXMLException {
XmlElement el = parser.start("block");
restoreXmlHeader(el);
restoreXmlBody(parser, resolver);
restoreXmlEdges(parser, resolver);
parser.end(el);
public void decode(Decoder decoder, BlockMap resolver) throws PcodeXMLException {
int el = decoder.openElement(ElementId.ELEM_BLOCK);
decodeHeader(decoder);
decodeBody(decoder, resolver);
decodeEdges(decoder, resolver);
decoder.closeElement(el);
}
}

View File

@ -21,8 +21,7 @@ import java.util.Iterator;
import ghidra.program.model.address.*;
import ghidra.util.xml.SpecXmlUtils;
import ghidra.xml.XmlElement;
import ghidra.xml.XmlPullParser;
/**
*
*
@ -31,11 +30,11 @@ import ghidra.xml.XmlPullParser;
public class PcodeBlockBasic extends PcodeBlock {
private ListLinked<PcodeOp> oplist; // List of PcodeOps making up the basic block
private AddressSet cover; // Addresses of instructions making up the block
PcodeBlockBasic() {
super();
blocktype = PcodeBlock.BASIC;
oplist = new ListLinked<PcodeOp>();
oplist = new ListLinked<>();
cover = new AddressSet();
}
@ -64,21 +63,21 @@ public class PcodeBlockBasic extends PcodeBlock {
* @param op is the new PcodeOp to insert
*/
protected void insertBefore(Iterator<PcodeOp> iter, PcodeOp op) {
PcodeOpAST opast = (PcodeOpAST)op;
PcodeOpAST opast = (PcodeOpAST) op;
opast.setParent(this);
Iterator<PcodeOp> newiter = oplist.insertBefore(iter,op);
Iterator<PcodeOp> newiter = oplist.insertBefore(iter, op);
opast.setBasicIter(newiter);
}
/**
* Insert a new PcodeOp after a specific point in the list of PcodeOps
* @param iter points to the PcodeOp to insert after
* @param op is the new PcodeOp to insert
*/
protected void insertAfter(Iterator<PcodeOp> iter, PcodeOp op) {
PcodeOpAST opast = (PcodeOpAST)op;
PcodeOpAST opast = (PcodeOpAST) op;
opast.setParent(this);
Iterator<PcodeOp> newiter = oplist.insertAfter(iter,opast);
Iterator<PcodeOp> newiter = oplist.insertAfter(iter, opast);
opast.setBasicIter(newiter);
}
@ -87,22 +86,22 @@ public class PcodeBlockBasic extends PcodeBlock {
* @param op is the PcodeOp to insert
*/
protected void insertEnd(PcodeOp op) {
PcodeOpAST opast = (PcodeOpAST)op;
PcodeOpAST opast = (PcodeOpAST) op;
opast.setParent(this);
Iterator<PcodeOp> newiter = oplist.add(opast);
opast.setBasicIter(newiter);
}
/**
* Remove a PcodeOp from the block
* @param op is the PcodeOp to remove
*/
protected void remove(PcodeOp op) {
PcodeOpAST opast = (PcodeOpAST)op;
PcodeOpAST opast = (PcodeOpAST) op;
opast.setParent(null);
oplist.remove(op.getBasicIter());
}
/**
* @return an iterator over the PcodeOps in this basic block
*/
@ -129,21 +128,23 @@ public class PcodeBlockBasic extends PcodeBlock {
}
@Override
public void restoreXmlBody(XmlPullParser parser, BlockMap resolver) throws PcodeXMLException {
AddressFactory addressFactory = resolver.getAddressFactory();
XmlElement rangelistel = parser.start("rangelist");
while (parser.peek().isStart()) {
XmlElement rangeel = parser.start("range");
String spc = rangeel.getAttribute("space");
long offset = SpecXmlUtils.decodeLong(rangeel.getAttribute("first"));
AddressSpace addressSpace = addressFactory.getAddressSpace(spc);
public void decodeBody(Decoder decoder, BlockMap resolver) throws PcodeXMLException {
int rangelistel = decoder.openElement(ElementId.ELEM_RANGELIST);
for (;;) {
int rangeel = decoder.peekElement();
if (rangeel != ElementId.ELEM_RANGE.getId()) {
break;
}
decoder.openElement();
AddressSpace addressSpace = decoder.readSpace(AttributeId.ATTRIB_SPACE);
long offset = decoder.readUnsignedInteger(AttributeId.ATTRIB_FIRST);
Address start = addressSpace.getAddress(offset);
offset = SpecXmlUtils.decodeLong(rangeel.getAttribute("last"));
offset = decoder.readUnsignedInteger(AttributeId.ATTRIB_LAST);
Address stop = addressSpace.getAddress(offset);
cover.addRange(start, stop);
parser.end(rangeel);
decoder.closeElement(rangeel);
}
parser.end(rangelistel);
decoder.closeElement(rangelistel);
}
}

View File

@ -28,8 +28,6 @@ import ghidra.program.model.lang.CompilerSpec;
import ghidra.program.model.lang.DecompilerLanguage;
import ghidra.program.model.listing.Program;
import ghidra.util.xml.SpecXmlUtils;
import ghidra.xml.XmlElement;
import ghidra.xml.XmlPullParser;
/**
*
@ -123,13 +121,11 @@ public class PcodeDataTypeManager {
* a corresponding data-type exists, this data-type is returned. Otherwise the first
* built-in data-type with a matching name is returned
* @param nm name of data-type
* @param idstr is an optional string containing a data-type id number
* @param id is an optional data-type id number
* @return the data-type object or null if no matching data-type exists
*/
public DataType findBaseType(String nm, String idstr) {
long id = 0;
if (idstr != null) {
id = SpecXmlUtils.decodeLong(idstr);
public DataType findBaseType(String nm, long id) {
if (id != 0) {
if (id > 0) {
DataType dt = progDataTypes.getDataType(id);
if (dt != null) {
@ -156,97 +152,106 @@ public class PcodeDataTypeManager {
}
/**
* Get the data type that corresponds to the given XML element.
* @param parser the xml parser
* @return the read data type
* @throws PcodeXMLException if the data type could be resolved from the
* element
* Decode a data-type from the stream
* @param decoder is the stream decoder
* @return the decoded data-type object
* @throws PcodeXMLException for invalid encodings
*/
public DataType readXMLDataType(XmlPullParser parser) throws PcodeXMLException {
XmlElement el = parser.start("type", "void", "typeref", "def");
try {
if (el == null) {
throw new PcodeXMLException("Bad <type> tag");
public DataType decodeDataType(Decoder decoder) throws PcodeXMLException {
int el = decoder.openElement();
if (el == ElementId.ELEM_VOID.getId()) {
decoder.closeElement(el);
return voidDt;
}
String name = "";
long id = 0;
for (;;) {
int attribId = decoder.getNextAttributeId();
if (attribId == 0) {
break;
}
if (attribId == AttributeId.ATTRIB_NAME.getId()) {
name = decoder.readString();
}
else if (attribId == AttributeId.ATTRIB_ID.getId()) {
id = decoder.readUnsignedInteger();
}
}
if (el == ElementId.ELEM_TYPEREF.getId()) {
decoder.closeElement(el);
return findBaseType(name, id);
}
if (el == ElementId.ELEM_DEF.getId()) {
decoder.closeElementSkipping(el);
return findBaseType(name, id);
}
if (el != ElementId.ELEM_TYPE.getId()) {
throw new PcodeXMLException("Expecting <type> element");
}
if (el.getName().equals("void")) {
return voidDt;
}
if (el.getName().equals("typeref")) {
return findBaseType(el.getAttribute("name"), el.getAttribute("id"));
}
if (el.getName().equals("def")) {
String nameStr = el.getAttribute("name");
String idStr = el.getAttribute("id");
parser.discardSubTree(); // Get rid of unused <typeref>
return findBaseType(nameStr, idStr);
}
String name = el.getAttribute("name");
if (name.length() != 0) {
return findBaseType(name, el.getAttribute("id"));
}
String meta = el.getAttribute("metatype");
DataType restype = null;
if (meta.equals("ptr")) {
int size = SpecXmlUtils.decodeInt(el.getAttribute("size"));
if (parser.peek().isStart()) {
DataType dt = readXMLDataType(parser);
boolean useDefaultSize = (size == dataOrganization.getPointerSize() ||
size > PointerDataType.MAX_POINTER_SIZE_BYTES);
restype = new PointerDataType(dt, useDefaultSize ? -1 : size, progDataTypes);
}
}
else if (meta.equals("array")) {
int arrsize = SpecXmlUtils.decodeInt(el.getAttribute("arraysize"));
if (parser.peek().isStart()) {
DataType dt = readXMLDataType(parser);
if (dt == null || dt.getLength() == 0) {
dt = DataType.DEFAULT;
}
restype = new ArrayDataType(dt, arrsize, dt.getLength(), progDataTypes);
}
}
else if (meta.equals("spacebase")) { // Typically the type of "the whole stack"
parser.discardSubTree(); // get rid of unused "addr" element
return voidDt;
}
else if (meta.equals("struct")) {
// we now can reach here with the decompiler inventing structures, apparently
// this is a band-aid so that we don't blow up
// just make an undefined data type of the appropriate size
int size = SpecXmlUtils.decodeInt(el.getAttribute("size"));
return Undefined.getUndefinedDataType(size);
// OLD COMMENT:
// Structures should always be named so we should never reach here
// if all the structures are contained in ghidra. I should probably add the
// parsing here so the decompiler can pass new structures into ghidra
}
else if (meta.equals("int")) {
int size = SpecXmlUtils.decodeInt(el.getAttribute("size"));
return AbstractIntegerDataType.getSignedDataType(size, progDataTypes);
}
else if (meta.equals("uint")) {
int size = SpecXmlUtils.decodeInt(el.getAttribute("size"));
return AbstractIntegerDataType.getUnsignedDataType(size, progDataTypes);
}
else if (meta.equals("float")) {
int size = SpecXmlUtils.decodeInt(el.getAttribute("size"));
return AbstractFloatDataType.getFloatDataType(size, progDataTypes);
}
else { // We typically reach here if the decompiler invents a new type
// probably an unknown with a non-standard size
int size = SpecXmlUtils.decodeInt(el.getAttribute("size"));
return Undefined.getUndefinedDataType(size).clone(progDataTypes);
}
if (restype == null) {
throw new PcodeXMLException("Unable to resolve DataType");
}
return restype;
if (name.length() != 0) {
decoder.closeElementSkipping(el);
return findBaseType(name, id);
}
finally {
parser.discardSubTree(el);
// parser.end(el);
String meta = decoder.readString(AttributeId.ATTRIB_METATYPE);
DataType restype = null;
if (meta.equals("ptr")) {
int size = (int) decoder.readSignedInteger(AttributeId.ATTRIB_SIZE);
if (decoder.peekElement() != 0) {
DataType dt = decodeDataType(decoder);
boolean useDefaultSize = (size == dataOrganization.getPointerSize() ||
size > PointerDataType.MAX_POINTER_SIZE_BYTES);
restype = new PointerDataType(dt, useDefaultSize ? -1 : size, progDataTypes);
}
}
else if (meta.equals("array")) {
int arrsize = (int) decoder.readSignedInteger(AttributeId.ATTRIB_ARRAYSIZE);
if (decoder.peekElement() != 0) {
DataType dt = decodeDataType(decoder);
if (dt == null || dt.getLength() == 0) {
dt = DataType.DEFAULT;
}
restype = new ArrayDataType(dt, arrsize, dt.getLength(), progDataTypes);
}
}
else if (meta.equals("spacebase")) { // Typically the type of "the whole stack"
decoder.closeElementSkipping(el); // get rid of unused "addr" element
return voidDt;
}
else if (meta.equals("struct")) {
// We reach here if the decompiler invents a structure, apparently
// this is a band-aid so that we don't blow up
// just make an undefined data type of the appropriate size
int size = (int) decoder.readSignedInteger(AttributeId.ATTRIB_SIZE);
decoder.closeElementSkipping(el);
return Undefined.getUndefinedDataType(size);
}
else if (meta.equals("int")) {
int size = (int) decoder.readSignedInteger(AttributeId.ATTRIB_SIZE);
decoder.closeElement(el);
return AbstractIntegerDataType.getSignedDataType(size, progDataTypes);
}
else if (meta.equals("uint")) {
int size = (int) decoder.readSignedInteger(AttributeId.ATTRIB_SIZE);
decoder.closeElement(el);
return AbstractIntegerDataType.getUnsignedDataType(size, progDataTypes);
}
else if (meta.equals("float")) {
int size = (int) decoder.readSignedInteger(AttributeId.ATTRIB_SIZE);
decoder.closeElement(el);
return AbstractFloatDataType.getFloatDataType(size, progDataTypes);
}
else { // We typically reach here if the decompiler invents a new type
// probably an unknown with a non-standard size
int size = (int) decoder.readSignedInteger(AttributeId.ATTRIB_SIZE);
decoder.closeElement(el);
return Undefined.getUndefinedDataType(size).clone(progDataTypes);
}
if (restype == null) {
throw new PcodeXMLException("Unable to resolve DataType");
}
decoder.closeElementSkipping(el);
return restype;
}
/**

View File

@ -23,7 +23,7 @@ import ghidra.program.model.data.DataType;
import ghidra.program.model.lang.UnknownInstructionException;
import ghidra.program.model.listing.VariableStorage;
import ghidra.util.exception.InvalidInputException;
import ghidra.xml.XmlElement;
/**
*
*
@ -35,12 +35,12 @@ public interface PcodeFactory {
* @return Address factory
*/
public AddressFactory getAddressFactory();
/**
* @return pcode data type manager used to convert strings to Ghidra data types
*/
public PcodeDataTypeManager getDataTypeManager();
/**
* Create a new Varnode with the given size an location
*
@ -49,24 +49,46 @@ public interface PcodeFactory {
*
* @return a new varnode
*/
public Varnode newVarnode(int sz,Address addr);
public Varnode newVarnode(int sz,Address addr,int refId);
public VariableStorage readXMLVarnodePieces(XmlElement el, Address addr) throws PcodeXMLException, InvalidInputException;
public Varnode createFromStorage(Address addr,VariableStorage storage, int logicalSize);
public Varnode newVarnode(int sz, Address addr);
public Varnode newVarnode(int sz, Address addr, int refId);
/**
* Decode a join address from "piece" attributes
*
* @param decoder is the stream decoder
* @param addr join address associated with pieces
*
* @return the decoded VariableStorage
* @throws PcodeXMLException for an improperly encoded stream
* @throws InvalidInputException if the pieces are not valid storage locations
*/
public VariableStorage decodeVarnodePieces(Decoder decoder, Address addr)
throws PcodeXMLException, InvalidInputException;
public Varnode createFromStorage(Address addr, VariableStorage storage, int logicalSize);
public VariableStorage buildStorage(Varnode vn) throws InvalidInputException;
public Varnode getRef(int refid);
public PcodeOp getOpRef(int refid);
public HighSymbol getSymbol(long symbolId);
public Varnode setInput(Varnode vn,boolean val);
public void setAddrTied(Varnode vn,boolean val);
public Varnode setInput(Varnode vn, boolean val);
public void setAddrTied(Varnode vn, boolean val);
public void setPersistent(Varnode vn, boolean val);
public void setUnaffected(Varnode vn,boolean val);
public void setMergeGroup(Varnode vn,short val);
public void setDataType(Varnode vn,DataType type);
public PcodeOp newOp(SequenceNumber sq,int opc,ArrayList<Varnode> inputs,Varnode output)
throws UnknownInstructionException;
public void setUnaffected(Varnode vn, boolean val);
public void setMergeGroup(Varnode vn, short val);
public void setDataType(Varnode vn, DataType type);
public PcodeOp newOp(SequenceNumber sq, int opc, ArrayList<Varnode> inputs, Varnode output)
throws UnknownInstructionException;
}

View File

@ -20,8 +20,6 @@ import java.util.*;
import ghidra.program.model.address.*;
import ghidra.program.model.lang.UnknownInstructionException;
import ghidra.util.xml.SpecXmlUtils;
import ghidra.xml.XmlElement;
import ghidra.xml.XmlPullParser;
/**
*
@ -418,7 +416,7 @@ public class PcodeOp {
output = vn;
}
public void buildXML(StringBuilder resBuf,AddressFactory addrFactory) {
public void buildXML(StringBuilder resBuf, AddressFactory addrFactory) {
resBuf.append("<op");
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "code", opcode);
resBuf.append('>');
@ -446,29 +444,26 @@ public class PcodeOp {
}
/**
* Read p-code from XML stream
* Decode p-code from a stream
*
* @param parser is the XML stream
* @param decoder is the stream decoder
* @param pfact factory used to create p-code correctly
*
* @return new PcodeOp
* @throws PcodeXMLException if XML layout is incorrect
* @throws PcodeXMLException if encodings are invalid
*/
public static PcodeOp readXML(XmlPullParser parser, PcodeFactory pfact)
throws PcodeXMLException {
XmlElement el = parser.start("op");
int opc = SpecXmlUtils.decodeInt(el.getAttribute("code"));
if (!parser.peek().isStart()) {
throw new PcodeXMLException("Missing <seqnum> in PcodeOp");
}
SequenceNumber seqnum = SequenceNumber.readXML(parser, pfact.getAddressFactory());
if (!parser.peek().isStart()) {
throw new PcodeXMLException("Missing output in PcodeOp");
}
Varnode output = Varnode.readXML(parser, pfact);
ArrayList<Varnode> inputlist = new ArrayList<Varnode>();
while (parser.peek().isStart()) {
Varnode vn = Varnode.readXML(parser, pfact);
public static PcodeOp decode(Decoder decoder, PcodeFactory pfact) throws PcodeXMLException {
int el = decoder.openElement(ElementId.ELEM_OP);
int opc = (int) decoder.readSignedInteger(AttributeId.ATTRIB_CODE);
SequenceNumber seqnum = SequenceNumber.decode(decoder);
Varnode output = Varnode.decode(decoder, pfact);
ArrayList<Varnode> inputlist = new ArrayList<>();
for (;;) {
int subel = decoder.peekElement();
if (subel == 0) {
break;
}
Varnode vn = Varnode.decode(decoder, pfact);
inputlist.add(vn);
}
PcodeOp res;
@ -478,7 +473,7 @@ public class PcodeOp {
catch (UnknownInstructionException e) {
throw new PcodeXMLException("Bad opcode: " + e.getMessage(), e);
}
parser.end(el);
decoder.closeElement(el);
return res;
}
@ -522,7 +517,7 @@ public class PcodeOp {
* Generate a lookup table that maps pcode mnemonic strings to pcode operation codes.
*/
private static void generateOpcodeTable() {
opcodeTable = new Hashtable<String, Integer>();
opcodeTable = new Hashtable<>();
for (int i = 0; i < PCODE_MAX; i++) {
opcodeTable.put(getMnemonic(i), i);
}

View File

@ -22,9 +22,6 @@ import ghidra.program.model.data.DataType;
import ghidra.program.model.lang.UnknownInstructionException;
import ghidra.program.model.listing.VariableStorage;
import ghidra.util.exception.InvalidInputException;
import ghidra.util.xml.SpecXmlUtils;
import ghidra.xml.XmlElement;
import ghidra.xml.XmlPullParser;
/**
*
@ -99,26 +96,23 @@ public class PcodeSyntaxTree implements PcodeFactory {
return new Varnode(space.getAddress(offset), size);
}
/**
* Read an XML join address with "piece" attributes
*
* @param el SAX parse tree element
* @param addr join address associated with pieces
*
* @return the VariableStorage associated with xml
* @throws PcodeXMLException for improperly formatted XML
* @throws InvalidInputException if the pieces are not valid storage locations
*/
@Override
public VariableStorage readXMLVarnodePieces(XmlElement el, Address addr)
public VariableStorage decodeVarnodePieces(Decoder decoder, Address addr)
throws PcodeXMLException, InvalidInputException {
ArrayList<Varnode> list = new ArrayList<>();
int index = 1;
String nextPiece = "piece" + index;
while (el.hasAttribute(nextPiece)) {
String pieceStr = el.getAttribute(nextPiece);
list.add(getVarnodePiece(pieceStr, addrFactory));
nextPiece = "piece" + ++index;
for (;;) {
int attribId = decoder.getNextAttributeId();
if (attribId == 0) {
break;
}
else if (attribId >= AttributeId.ATTRIB_PIECE1.getId() &&
attribId <= AttributeId.ATTRIB_PIECE9.getId()) {
int index = attribId - AttributeId.ATTRIB_PIECE1.getId();
if (index != list.size()) {
throw new PcodeXMLException("\"piece\" attributes must be in order");
}
list.add(getVarnodePiece(decoder.readString(), decoder.getAddressFactory()));
}
}
Varnode[] pieces = new Varnode[list.size()];
list.toArray(pieces);
@ -526,23 +520,30 @@ public class PcodeSyntaxTree implements PcodeFactory {
return op;
}
private void readVarnodeXML(XmlPullParser parser) throws PcodeXMLException {
XmlElement el = parser.start("varnodes");
while (parser.peek().isStart()) {
Varnode.readXML(parser, this);
private void decodeVarnode(Decoder decoder) throws PcodeXMLException {
int el = decoder.openElement(ElementId.ELEM_VARNODES);
for (;;) {
int subId = decoder.peekElement();
if (subId == 0) {
break;
}
Varnode.decode(decoder, this);
}
parser.end(el);
decoder.closeElement(el);
}
private void readBasicBlockXML(XmlPullParser parser, BlockMap resolver)
throws PcodeXMLException {
XmlElement el = parser.start("block");
private void decodeBasicBlock(Decoder decoder, BlockMap resolver) throws PcodeXMLException {
int el = decoder.openElement(ElementId.ELEM_BLOCK);
int order = 0;
PcodeBlockBasic bl = new PcodeBlockBasic();
bl.restoreXmlHeader(el);
bl.restoreXmlBody(parser, resolver);
while (parser.peek().isStart()) {
PcodeOp op = PcodeOp.readXML(parser, this);
bl.decodeHeader(decoder);
bl.decodeBody(decoder, resolver);
for (;;) {
int subel = decoder.peekElement();
if (subel == 0) {
break;
}
PcodeOp op = PcodeOp.decode(decoder, this);
op.setOrder(order);
order += 1;
bl.insertEnd(op);
@ -552,37 +553,44 @@ public class PcodeSyntaxTree implements PcodeFactory {
bblocks.add(null);
}
bblocks.set(index, bl);
parser.end(el);
decoder.closeElement(el);
}
private void readBlockEdgeXML(XmlPullParser parser) throws PcodeXMLException {
XmlElement el = parser.start("blockedge");
int blockInd = SpecXmlUtils.decodeInt(el.getAttribute("index"));
private void decodeBlockEdge(Decoder decoder) throws PcodeXMLException {
int el = decoder.openElement(ElementId.ELEM_BLOCKEDGE);
int blockInd = (int) decoder.readSignedInteger(AttributeId.ATTRIB_INDEX);
PcodeBlockBasic curBlock = bblocks.get(blockInd);
while (parser.peek().isStart()) {
curBlock.restoreNextInEdge(parser, bblocks);
for (;;) {
int subel = decoder.peekElement();
if (subel == 0) {
break;
}
curBlock.decodeNextInEdge(decoder, bblocks);
}
parser.end(el);
decoder.closeElement(el);
}
public void readXML(XmlPullParser parser) throws PcodeXMLException {
XmlElement el = parser.start("ast");
public void decode(Decoder decoder) throws PcodeXMLException {
int el = decoder.openElement(ElementId.ELEM_AST);
if (!vbank.isEmpty()) {
clear();
}
readVarnodeXML(parser);
decodeVarnode(decoder);
buildVarnodeRefs(); // Build the HashMap
BlockMap blockMap = new BlockMap(addrFactory);
while (parser.peek().isStart()) {
XmlElement subel = parser.peek();
if (subel.getName().equals("block")) {
readBasicBlockXML(parser, blockMap); // Read a basic block and all its PcodeOps
for (;;) {
int subel = decoder.peekElement();
if (subel == 0) {
break;
}
else if (subel == ElementId.ELEM_BLOCK.getId()) {
decodeBasicBlock(decoder, blockMap); // Read a basic block and all its PcodeOps
}
else {
readBlockEdgeXML(parser);
decodeBlockEdge(decoder);
}
}
parser.end(el);
decoder.closeElement(el);
}
}

View File

@ -15,9 +15,9 @@
*/
package ghidra.program.model.pcode;
import ghidra.program.model.address.*;
import ghidra.util.xml.*;
import ghidra.xml.*;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSpace;
import ghidra.util.xml.SpecXmlUtils;
/**
*
@ -29,10 +29,10 @@ import ghidra.xml.*;
public class SequenceNumber implements Comparable<SequenceNumber> {
private Address pc; // Address of assembly language instruction
private int uniq; // Sub-address for distinguishing multiple PcodeOps at one
// instruction address. Does not change over lifetime of PcodeOp
// instruction address. Does not change over lifetime of PcodeOp
private int order; // Contains relative position information of PcodeOps within
// a basic block, may change as basic block is edited.
// a basic block, may change as basic block is edited.
/**
* Construct a sequence number for an instruction at an address and sequence of pcode op within
* that instructions set of pcode.
@ -44,14 +44,14 @@ public class SequenceNumber implements Comparable<SequenceNumber> {
pc = instrAddr;
uniq = sequenceNum;
}
/**
* @return get address of instruction this sequence belongs to
*/
public Address getTarget() {
return pc;
}
/**
* Get unique Sub-address for distinguishing multiple PcodeOps at one
* instruction address.
@ -71,9 +71,9 @@ public class SequenceNumber implements Comparable<SequenceNumber> {
* @param t unique id
*/
public void setTime(int t) {
uniq = t;
uniq = t;
}
/**
* Get relative position information of PcodeOps within
* a basic block, may change as basic block is edited.
@ -83,7 +83,7 @@ public class SequenceNumber implements Comparable<SequenceNumber> {
public int getOrder() {
return order;
}
/**
* Set relative position information of PcodeOps within
* a basic block, may change as basic block is edited.
@ -93,25 +93,34 @@ public class SequenceNumber implements Comparable<SequenceNumber> {
public void setOrder(int o) {
order = o;
}
/* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object o) {
if (!(o instanceof SequenceNumber)) return false;
public boolean equals(Object o) {
if (!(o instanceof SequenceNumber)) {
return false;
}
SequenceNumber sq = (SequenceNumber) o;
return (pc.equals(sq.pc)&&(uniq==sq.uniq));
return (pc.equals(sq.pc) && (uniq == sq.uniq));
}
/* (non-Javadoc)
* @see java.lang.Comparable#compareTo(java.lang.Object)
*/
public int compareTo(SequenceNumber sq) {
@Override
public int compareTo(SequenceNumber sq) {
int val = pc.compareTo(sq.pc);
if (val != 0) return val;
if (uniq < sq.uniq) return -1;
if (sq.uniq < uniq) return 1;
if (val != 0) {
return val;
}
if (uniq < sq.uniq) {
return -1;
}
if (sq.uniq < uniq) {
return 1;
}
return 0;
}
@ -124,56 +133,53 @@ public class SequenceNumber implements Comparable<SequenceNumber> {
AddressSpace space = pc.getAddressSpace();
SpecXmlUtils.encodeStringAttribute(resBuf, "space", space.getName());
SpecXmlUtils.encodeUnsignedIntegerAttribute(resBuf, "offset", pc.getOffset());
if (uniq != -1)
if (uniq != -1) {
SpecXmlUtils.encodeUnsignedIntegerAttribute(resBuf, "uniq", uniq);
}
resBuf.append("/>");
return resBuf;
return resBuf;
}
/**
* Create a new Sequence number from XML SAX tree element.
* Decode a new Sequence number from the stream
*
* @param parser the xml parser
* @param factory pcode factory used to create new pcode
* @param decoder is the stream decoder
*
* @return new sequence number
* @throws PcodeXMLException for an invalid encoding
*/
public static SequenceNumber readXML(XmlPullParser parser,AddressFactory factory) {
XmlElement el = parser.start("seqnum");
String attrstring = el.getAttribute("uniq");
int uniq;
if (attrstring != null)
uniq = SpecXmlUtils.decodeInt(attrstring);
else
uniq = -1; // Should fill in with something from factory
String space = el.getAttribute("space");
AddressSpace spc = factory.getAddressSpace(space);
long offset = SpecXmlUtils.decodeLong(el.getAttribute("offset"));
parser.end(el);
return new SequenceNumber(spc.getAddress(offset),uniq);
public static SequenceNumber decode(Decoder decoder) throws PcodeXMLException {
int el = decoder.openElement(ElementId.ELEM_SEQNUM);
int uniq = -1;
for (;;) {
int attribId = decoder.getNextAttributeId();
if (attribId == 0) {
break;
}
else if (attribId == AttributeId.ATTRIB_UNIQ.getId()) {
uniq = (int) decoder.readUnsignedInteger();
}
}
AddressSpace spc = decoder.readSpace(AttributeId.ATTRIB_SPACE);
long offset = decoder.readUnsignedInteger(AttributeId.ATTRIB_OFFSET);
decoder.closeElement(el);
return new SequenceNumber(spc.getAddress(offset), uniq);
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return ("("
+ pc.getAddressSpace().getName()
+ ", 0x"
+ Long.toHexString(pc.getOffset())
+ ", "
+ uniq
+ ", "
+ order
+ ")");
public String toString() {
return ("(" + pc.getAddressSpace().getName() + ", 0x" + Long.toHexString(pc.getOffset()) +
", " + uniq + ", " + order + ")");
}
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
public int hashCode() {
return pc.hashCode() + uniq; // Don't hash order, as this is mutable
}

View File

@ -19,8 +19,6 @@ import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSpace;
import ghidra.program.model.listing.VariableStorage;
import ghidra.util.xml.SpecXmlUtils;
import ghidra.xml.XmlElement;
import ghidra.xml.XmlPullParser;
/**
* A mapping from a HighSymbol object to the storage that holds the symbol's value.
@ -39,12 +37,11 @@ public abstract class SymbolEntry {
}
/**
* Restore this entry from the given XML stream. Typically more than one tag is consumed
* @param parser is the given XML stream
* @throws PcodeXMLException if the XML is invalid
* Decode this entry from the stream. Typically more than one element is consumed.
* @param decoder is the stream decoder
* @throws PcodeXMLException for invalid encodings
*/
public abstract void restoreXML(XmlPullParser parser)
throws PcodeXMLException;
public abstract void decode(Decoder decoder) throws PcodeXMLException;
/**
* Save this entry as (a set of) XML tags to the given stream
@ -83,21 +80,22 @@ public abstract class SymbolEntry {
return pcaddr;
}
protected void parseRangeList(XmlPullParser parser) {
XmlElement rangelistel = parser.start("rangelist");
if (parser.peek().isStart()) {
protected void decodeRangeList(Decoder decoder) throws PcodeXMLException {
int rangelistel = decoder.openElement(ElementId.ELEM_RANGELIST);
if (decoder.peekElement() != 0) {
// we only use this to establish first-use
XmlElement rangeel = parser.start("range");
String spc = rangeel.getAttribute("space");
long offset = SpecXmlUtils.decodeLong(rangeel.getAttribute("first"));
pcaddr = symbol.function.getAddressFactory().getAddressSpace(spc).getAddress(offset);
pcaddr =
symbol.function.getFunction().getEntryPoint().getAddressSpace().getOverlayAddress(
pcaddr);
parser.end(rangeel);
int rangeel = decoder.openElement(ElementId.ELEM_RANGE);
AddressSpace spc = decoder.readSpace(AttributeId.ATTRIB_SPACE);
long offset = decoder.readUnsignedInteger(AttributeId.ATTRIB_FIRST);
pcaddr = spc.getAddress(offset);
pcaddr = symbol.function.getFunction()
.getEntryPoint()
.getAddressSpace()
.getOverlayAddress(pcaddr);
decoder.closeElement(rangeel);
}
parser.end(rangelistel);
decoder.closeElement(rangelistel);
}
protected void buildRangelistXML(StringBuilder res) {

View File

@ -21,9 +21,6 @@ import ghidra.program.model.address.*;
import ghidra.program.model.lang.Language;
import ghidra.program.model.lang.Register;
import ghidra.util.exception.InvalidInputException;
import ghidra.util.xml.SpecXmlUtils;
import ghidra.xml.XmlElement;
import ghidra.xml.XmlPullParser;
/**
*
@ -322,83 +319,97 @@ public class Varnode {
}
/**
* Build a Varnode from an XML stream
* Decode a Varnode from a stream
*
* @param parser the parser
* @param decoder is the stream decoder
* @param factory pcode factory used to create valid pcode
* @return new varnode element based on info in the XML.
* @return the new Varnode
* @throws PcodeXMLException if XML is improperly formed
*/
public static Varnode readXML(XmlPullParser parser, PcodeFactory factory)
throws PcodeXMLException {
XmlElement el = parser.start();
try {
if (el.getName().equals("void")) {
return null;
public static Varnode decode(Decoder decoder, PcodeFactory factory) throws PcodeXMLException {
int el = decoder.peekElement();
if (el == ElementId.ELEM_VOID.getId()) {
decoder.openElement();
decoder.closeElement(el);
return null;
}
else if (el == ElementId.ELEM_SPACEID.getId() || el == ElementId.ELEM_IOP.getId()) {
Address addr = AddressXML.decode(decoder);
return factory.newVarnode(4, addr);
}
el = decoder.openElement();
int ref = -1;
int sz = 4;
for (;;) {
int attribId = decoder.getNextAttributeId();
if (attribId == 0) {
break;
}
Varnode vn;
String attrstring = el.getAttribute("ref");
int ref = -1;
if (attrstring != null) {
ref = SpecXmlUtils.decodeInt(attrstring); // If we have a reference
vn = factory.getRef(ref); // The varnode may already exist
else if (attribId == AttributeId.ATTRIB_REF.getId()) { // If we have a reference
ref = (int) decoder.readUnsignedInteger();
Varnode vn = factory.getRef(ref); // The varnode may already exit
if (vn != null) {
decoder.closeElement(el);
return vn;
}
}
Address addr = AddressXML.readXML(el, factory.getAddressFactory());
if (addr == null) {
return null;
else if (attribId == AttributeId.ATTRIB_SIZE.getId()) {
sz = (int) decoder.readSignedInteger();
}
int sz;
attrstring = el.getAttribute("size");
if (attrstring != null) {
sz = SpecXmlUtils.decodeInt(attrstring);
}
decoder.rewindAttributes();
Varnode vn;
Address addr = AddressXML.decodeFromAttributes(decoder);
if (ref != -1) {
vn = factory.newVarnode(sz, addr, ref);
}
else {
vn = factory.newVarnode(sz, addr);
}
AddressSpace spc = addr.getAddressSpace();
if ((spc != null) && (spc.getType() == AddressSpace.TYPE_VARIABLE)) { // Check for a composite Address
decoder.rewindAttributes();
try {
factory.decodeVarnodePieces(decoder, addr);
}
else {
sz = 4;
catch (InvalidInputException e) {
throw new PcodeXMLException("Invalid varnode pieces: " + e.getMessage());
}
if (ref != -1) {
vn = factory.newVarnode(sz, addr, ref);
}
decoder.rewindAttributes();
for (;;) {
int attribId = decoder.getNextAttributeId();
if (attribId == 0) {
break;
}
else {
vn = factory.newVarnode(sz, addr);
}
AddressSpace spc = addr.getAddressSpace();
if ((spc != null) && (spc.getType() == AddressSpace.TYPE_VARIABLE)) { // Check for a composite Address
try {
factory.readXMLVarnodePieces(el, addr);
}
catch (InvalidInputException e) {
throw new PcodeXMLException("Invalid varnode pieces: " + e.getMessage());
}
}
attrstring = el.getAttribute("grp");
if (attrstring != null) {
short val = (short) SpecXmlUtils.decodeInt(attrstring);
else if (attribId == AttributeId.ATTRIB_GRP.getId()) {
short val = (short) decoder.readSignedInteger();
factory.setMergeGroup(vn, val);
}
attrstring = el.getAttribute("persists");
if ((attrstring != null) && (SpecXmlUtils.decodeBoolean(attrstring))) {
factory.setPersistent(vn, true);
else if (attribId == AttributeId.ATTRIB_PERSISTS.getId()) {
if (decoder.readBool()) {
factory.setPersistent(vn, true);
}
}
attrstring = el.getAttribute("addrtied");
if ((attrstring != null) && (SpecXmlUtils.decodeBoolean(attrstring))) {
factory.setAddrTied(vn, true);
else if (attribId == AttributeId.ATTRIB_ADDRTIED.getId()) {
if (decoder.readBool()) {
factory.setAddrTied(vn, true);
}
}
attrstring = el.getAttribute("unaff");
if ((attrstring != null) && (SpecXmlUtils.decodeBoolean(attrstring))) {
factory.setUnaffected(vn, true);
else if (attribId == AttributeId.ATTRIB_UNAFF.getId()) {
if (decoder.readBool()) {
factory.setUnaffected(vn, true);
}
}
attrstring = el.getAttribute("input");
if ((attrstring != null) && (SpecXmlUtils.decodeBoolean(attrstring))) {
vn = factory.setInput(vn, true);
else if (attribId == AttributeId.ATTRIB_INPUT.getId()) {
if (decoder.readBool()) {
vn = factory.setInput(vn, true);
}
}
return vn;
}
finally {
parser.end(el);
}
decoder.closeElement(sz);
return vn;
}
/**

View File

@ -0,0 +1,289 @@
/* ###
* 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.program.model.pcode;
import java.io.InputStream;
import java.util.Iterator;
import java.util.Map;
import org.xml.sax.*;
import ghidra.program.model.address.AddressFactory;
import ghidra.program.model.address.AddressSpace;
import ghidra.util.Msg;
import ghidra.util.xml.SpecXmlUtils;
import ghidra.xml.*;
public class XmlDecode implements Decoder {
private XmlPullParser parser;
private XmlElement currentEl;
private Iterator<Map.Entry<String, String>> attribIterator;
private String attribValue;
private AddressFactory spcManager;
public XmlDecode(AddressFactory factory) {
parser = null;
currentEl = null;
attribIterator = null;
attribValue = null;
spcManager = factory;
}
@Override
public AddressFactory getAddressFactory() {
return spcManager;
}
@Override
public void clear() {
parser = null;
currentEl = null;
attribIterator = null;
}
@Override
public void ingestStream(InputStream stream, String source) throws PcodeXMLException {
ErrorHandler handler = new ErrorHandler() {
@Override
public void error(SAXParseException exception) throws SAXException {
Msg.error(this, "Error parsing " + source, exception);
}
@Override
public void fatalError(SAXParseException exception) throws SAXException {
Msg.error(this, "Fatal error parsing " + source, exception);
}
@Override
public void warning(SAXParseException exception) throws SAXException {
Msg.warn(this, "Warning parsing " + source, exception);
}
};
try {
parser = XmlPullParserFactory.create(stream, source, handler, false);
}
catch (Exception e) {
throw new PcodeXMLException("XML parsing error: " + e.getMessage(), e);
}
}
@Override
public int peekElement() {
XmlElement el = parser.peek();
if (!el.isStart()) {
return 0;
}
return ElementId.find(el.getName());
}
@Override
public int openElement() {
XmlElement el = parser.softStart();
if (el == null) {
return 0;
}
currentEl = el;
attribIterator = null;
return ElementId.find(currentEl.getName());
}
@Override
public int openElement(ElementId elemId) throws PcodeXMLException {
XmlElement el = parser.softStart(elemId.getName());
if (el == null) {
throw new PcodeXMLException("Expecting element <" + elemId.getName() + '>');
}
currentEl = el;
attribIterator = null;
return ElementId.find(currentEl.getName());
}
@Override
public void closeElement(int id) throws PcodeXMLException {
XmlElement el = parser.next();
if (!el.isEnd()) {
throw new PcodeXMLException("Expecting end, but got start <" + el.getName() + '>');
}
currentEl = null;
// int elemId = ElementId.find(el.getName());
// if (elemId != id) {
// throw new PcodeXMLException("Unexpected end, <" + el.getName() + '>');
// }
}
@Override
public void closeElementSkipping(int id) throws PcodeXMLException {
currentEl = null;
XmlElement el = parser.peek();
if (el == null) {
throw new PcodeXMLException("No more elements");
}
int level = el.getLevel();
if (el.isStart()) {
level -= 1;
}
for (;;) {
el = parser.next();
int curlevel = el.getLevel();
if (curlevel > level) {
continue;
}
if (curlevel < level) {
throw new PcodeXMLException("Missing end element");
}
if (el.isEnd()) {
break;
}
}
int elemId = ElementId.find(el.getName());
if (elemId != id) {
throw new PcodeXMLException("Unexpected element end: " + el.getName());
}
}
@Override
public int getNextAttributeId() {
if (attribIterator == null) {
attribIterator = currentEl.getAttributeIterator();
}
if (!attribIterator.hasNext()) {
return 0;
}
Map.Entry<String, String> entry = attribIterator.next();
attribValue = entry.getValue();
return AttributeId.find(entry.getKey());
}
@Override
public void rewindAttributes() {
attribIterator = null;
}
private String readContent() throws PcodeXMLException {
XmlElement el = parser.peek();
if (el == null || !el.isEnd()) {
throw new PcodeXMLException("Cannot request ATTRIB_CONTENT here");
}
return el.getText();
}
@Override
public boolean readBool() throws PcodeXMLException {
return SpecXmlUtils.decodeBoolean(attribValue);
}
@Override
public boolean readBool(AttributeId attribId) throws PcodeXMLException {
String value;
if (attribId == AttributeId.ATTRIB_CONTENT) {
value = readContent();
}
else {
value = currentEl.getAttribute(attribId.getName());
}
if (value == null) {
throw new PcodeXMLException("Missing attribute: " + attribId.getName());
}
attribIterator = null;
return SpecXmlUtils.decodeBoolean(value);
}
@Override
public long readSignedInteger() throws PcodeXMLException {
return SpecXmlUtils.decodeLong(attribValue);
}
@Override
public long readSignedInteger(AttributeId attribId) throws PcodeXMLException {
String value;
if (attribId == AttributeId.ATTRIB_CONTENT) {
value = readContent();
}
else {
value = currentEl.getAttribute(attribId.getName());
}
if (value == null) {
throw new PcodeXMLException("Missing attribute: " + attribId.getName());
}
attribIterator = null;
return SpecXmlUtils.decodeLong(value);
}
@Override
public long readUnsignedInteger() throws PcodeXMLException {
return SpecXmlUtils.decodeLong(attribValue);
}
@Override
public long readUnsignedInteger(AttributeId attribId) throws PcodeXMLException {
String value;
if (attribId == AttributeId.ATTRIB_CONTENT) {
value = readContent();
}
else {
value = currentEl.getAttribute(attribId.getName());
}
if (value == null) {
throw new PcodeXMLException("Missing attribute: " + attribId.getName());
}
attribIterator = null;
return SpecXmlUtils.decodeLong(value);
}
@Override
public String readString() throws PcodeXMLException {
return attribValue;
}
@Override
public String readString(AttributeId attribId) throws PcodeXMLException {
String value;
if (attribId == AttributeId.ATTRIB_CONTENT) {
value = readContent();
}
else {
value = currentEl.getAttribute(attribId.getName());
}
if (value == null) {
throw new PcodeXMLException("Missing attribute: " + attribId.getName());
}
attribIterator = null;
return value;
}
@Override
public AddressSpace readSpace() throws PcodeXMLException {
return spcManager.getAddressSpace(attribValue);
}
@Override
public AddressSpace readSpace(AttributeId attribId) throws PcodeXMLException {
String value;
if (attribId == AttributeId.ATTRIB_CONTENT) {
value = readContent();
}
else {
value = currentEl.getAttribute(attribId.getName());
}
if (value == null) {
throw new PcodeXMLException("Missing attribute: " + attribId.getName());
}
attribIterator = null;
return spcManager.getAddressSpace(value);
}
}

View File

@ -0,0 +1,398 @@
/* ###
* 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.program.model.pcode;
import java.io.InputStream;
import ghidra.program.model.address.AddressFactory;
import ghidra.program.model.address.AddressSpace;
import ghidra.util.xml.SpecXmlUtils;
/**
* Lightweight XML decoder.
* - Element and attribute identifiers must contain only letters or digits
* - No XML comments
* - No escape codes
* - No content (except white space)
*/
public class XmlDecodeLight implements Decoder {
private AddressFactory addressFactory;
private String raw;
private int currentPos;
private boolean startOpen;
private int attribStart;
private int currentElement;
public XmlDecodeLight(AddressFactory addrFactory) {
addressFactory = addrFactory;
}
@Override
public AddressFactory getAddressFactory() {
return addressFactory;
}
@Override
public void clear() {
raw = null;
}
public void ingestString(String data) {
raw = data;
currentPos = 0;
startOpen = false;
attribStart = -1;
}
private int scanWhiteSpace(int start) throws PcodeXMLException {
while (start < raw.length()) {
char tok = raw.charAt(start);
if (!Character.isWhitespace(tok)) {
return start;
}
start += 1;
}
throw new PcodeXMLException("Premature end of stream");
}
private int scanIdentifier(int start) throws PcodeXMLException {
while (start < raw.length()) {
char tok = raw.charAt(start);
if (!Character.isLetterOrDigit(tok)) {
return start;
}
start += 1;
}
throw new PcodeXMLException("Premature end of stream");
}
private int scanToEndOfStart(int start) throws PcodeXMLException {
int state = 0;
while (start < raw.length()) {
char tok = raw.charAt(start);
if (state == 0) {
if (tok == '/' || tok == '>') {
return start;
}
if (tok == '\"') {
state = 1;
}
}
else if (state == 1) {
if (tok == '\"') {
state = 0;
}
}
start += 1;
}
throw new PcodeXMLException("Premature end of stream");
}
private String scanElement() throws PcodeXMLException {
int pos = currentPos;
if (startOpen) {
pos = scanToEndOfStart(pos);
if (raw.charAt(pos) == '>') {
pos += 1;
}
}
pos = scanWhiteSpace(pos);
if (raw.charAt(pos) != '<') {
throw new PcodeXMLException("Expecting start of element");
}
pos += 1;
if (pos < raw.length() && raw.charAt(pos) == '/') {
return null;
}
pos = scanWhiteSpace(pos);
int endPos = scanIdentifier(pos);
if (pos == endPos) {
throw new PcodeXMLException("Parse error");
}
currentPos = endPos;
startOpen = true;
return raw.substring(pos, endPos);
}
private int scanQuote() throws PcodeXMLException {
int pos = currentPos + 1;
while (pos < raw.length()) {
if (raw.charAt(pos) == '\"') {
return pos + 1;
}
pos += 1;
}
throw new PcodeXMLException("Premature end of stream");
}
private String scanAttribute() throws PcodeXMLException {
int pos = currentPos;
currentPos = scanQuote();
return raw.substring(pos + 1, currentPos - 1);
}
@Override
public void ingestStream(InputStream stream, String source) throws PcodeXMLException {
throw new PcodeXMLException("Unimplemented method");
}
@Override
public int peekElement() {
int savePos = currentPos;
boolean saveStartOpen = startOpen;
String el;
try {
el = scanElement();
currentPos = savePos;
startOpen = saveStartOpen;
if (el == null) {
return 0;
}
}
catch (PcodeXMLException e) {
currentPos = savePos;
startOpen = saveStartOpen;
return 0;
}
return ElementId.find(el);
}
@Override
public int openElement() {
String el;
try {
el = scanElement();
if (el == null) {
return 0;
}
}
catch (PcodeXMLException e) {
return 0;
}
attribStart = currentPos;
currentElement = ElementId.find(el);
return currentElement;
}
@Override
public int openElement(ElementId elemId) throws PcodeXMLException {
String el = scanElement();
if (el == null) {
throw new PcodeXMLException("Expecting start of " + elemId.getName());
}
attribStart = currentPos;
currentElement = ElementId.find(el);
if (currentElement != elemId.getId()) {
throw new PcodeXMLException("Expecting element " + elemId.getName());
}
return currentElement;
}
@Override
public void closeElement(int id) throws PcodeXMLException {
int pos = currentPos;
if (startOpen) {
pos = scanToEndOfStart(currentPos);
char tok = raw.charAt(pos);
if (tok == '/') {
pos += 1;
if (pos >= raw.length()) {
throw new PcodeXMLException("Premature end of stream");
}
if (raw.charAt(pos) != '>') {
throw new PcodeXMLException("Parse error");
}
currentPos = pos + 1;
if (id != currentElement) {
throw new PcodeXMLException("Parse error");
}
startOpen = false;
return;
}
if (tok != '>') {
throw new PcodeXMLException("Parse error");
}
startOpen = false;
}
pos = scanWhiteSpace(pos);
if (raw.charAt(pos) != '<') {
throw new PcodeXMLException("Parse error");
}
pos += 1;
if (pos >= raw.length() || raw.charAt(pos) != '/') {
throw new PcodeXMLException("Parse error");
}
pos = scanWhiteSpace(pos + 1);
int endpos = scanIdentifier(pos);
String ident = raw.substring(pos, endpos);
if (id != ElementId.find(ident)) {
throw new PcodeXMLException("Expecting end token");
}
pos = scanWhiteSpace(endpos);
if (raw.charAt(pos) != '>') {
throw new PcodeXMLException("Parse error");
}
currentPos = pos + 1;
}
@Override
public void closeElementSkipping(int id) throws PcodeXMLException {
throw new PcodeXMLException("closeElementSkipping unimplemented");
}
@Override
public int getNextAttributeId() {
if (!startOpen) {
return 0;
}
try {
int pos = scanWhiteSpace(currentPos);
char tok = raw.charAt(pos);
if (tok == '\"') {
pos = scanQuote();
pos = scanWhiteSpace(pos);
tok = raw.charAt(pos);
}
if (tok == '>' || tok == '/') {
currentPos = pos;
return 0;
}
int endPos = scanIdentifier(pos);
if (pos == endPos) {
throw new PcodeXMLException("Parse error");
}
String ident = raw.substring(pos, endPos);
pos = scanWhiteSpace(endPos);
if (raw.charAt(pos) != '=') {
throw new PcodeXMLException("Parse error");
}
pos = scanWhiteSpace(pos + 1);
if (raw.charAt(pos) != '\"') {
throw new PcodeXMLException("Parse error");
}
currentPos = pos;
return AttributeId.find(ident);
}
catch (PcodeXMLException e) {
return 0;
}
}
private void findAttribute(AttributeId attribId) throws PcodeXMLException {
currentPos = attribStart;
startOpen = true;
for (;;) {
int id = getNextAttributeId();
if (id == 0) {
break;
}
if (id == attribId.getId()) {
return;
}
}
throw new PcodeXMLException("Missing attribute: " + attribId.getName());
}
@Override
public void rewindAttributes() {
currentPos = attribStart;
startOpen = true;
}
@Override
public boolean readBool() throws PcodeXMLException {
String value = scanAttribute();
return SpecXmlUtils.decodeBoolean(value);
}
@Override
public boolean readBool(AttributeId attribId) throws PcodeXMLException {
findAttribute(attribId);
String value = scanAttribute();
currentPos = attribStart;
startOpen = true;
return SpecXmlUtils.decodeBoolean(value);
}
@Override
public long readSignedInteger() throws PcodeXMLException {
String value = scanAttribute();
return SpecXmlUtils.decodeLong(value);
}
@Override
public long readSignedInteger(AttributeId attribId) throws PcodeXMLException {
findAttribute(attribId);
String value = scanAttribute();
currentPos = attribStart;
startOpen = true;
return SpecXmlUtils.decodeLong(value);
}
@Override
public long readUnsignedInteger() throws PcodeXMLException {
String value = scanAttribute();
return SpecXmlUtils.decodeLong(value);
}
@Override
public long readUnsignedInteger(AttributeId attribId) throws PcodeXMLException {
findAttribute(attribId);
String value = scanAttribute();
currentPos = attribStart;
startOpen = true;
return SpecXmlUtils.decodeLong(value);
}
@Override
public String readString() throws PcodeXMLException {
return scanAttribute();
}
@Override
public String readString(AttributeId attribId) throws PcodeXMLException {
findAttribute(attribId);
String value = scanAttribute();
currentPos = attribStart;
startOpen = true;
return value;
}
@Override
public AddressSpace readSpace() throws PcodeXMLException {
String value = scanAttribute();
AddressSpace spc = addressFactory.getAddressSpace(value);
if (spc == null) {
throw new PcodeXMLException("Unknown address space: " + value);
}
return spc;
}
@Override
public AddressSpace readSpace(AttributeId attribId) throws PcodeXMLException {
findAttribute(attribId);
String value = scanAttribute();
currentPos = attribStart;
startOpen = true;
AddressSpace spc = addressFactory.getAddressSpace(value);
if (spc == null) {
throw new PcodeXMLException("Unknown address space: " + value);
}
return spc;
}
}

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,6 +15,7 @@
*/
package ghidra.xml;
import java.util.Iterator;
import java.util.Map;
public interface XmlElement {
@ -31,6 +31,8 @@ public interface XmlElement {
public Map<String, String> getAttributes();
public Iterator<Map.Entry<String, String>> getAttributeIterator();
public boolean hasAttribute(String key);
public String getAttribute(String key);

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,8 +15,7 @@
*/
package ghidra.xml;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.*;
public class XmlElementImpl implements XmlElement {
private final String name;
@ -31,7 +29,8 @@ public class XmlElementImpl implements XmlElement {
private final int lineNumber;
public XmlElementImpl(boolean isStart, boolean isEnd, String name, int level,
LinkedHashMap<String, String> attributes, String text, int columnNumber, int lineNumber) {
LinkedHashMap<String, String> attributes, String text, int columnNumber,
int lineNumber) {
if (isStart && isEnd) {
throw new XmlException(
"empty elements must be split into separate start and end elements (see splitEmptyElement)");
@ -47,14 +46,17 @@ public class XmlElementImpl implements XmlElement {
this.lineNumber = lineNumber;
}
@Override
public int getColumnNumber() {
return columnNumber;
}
@Override
public int getLineNumber() {
return lineNumber;
}
@Override
public boolean hasAttribute(String key) {
if (attributes == null) {
return false;
@ -62,6 +64,7 @@ public class XmlElementImpl implements XmlElement {
return attributes.containsKey(key);
}
@Override
public String getAttribute(String key) {
if (attributes == null) {
return null;
@ -69,34 +72,50 @@ public class XmlElementImpl implements XmlElement {
return attributes.get(key);
}
@Override
public LinkedHashMap<String, String> getAttributes() {
return attributes == null ? null : new LinkedHashMap<String, String>(attributes);
}
@Override
public Iterator<Map.Entry<String, String>> getAttributeIterator() {
if (attributes == null) {
return Collections.emptyIterator();
}
return attributes.entrySet().iterator();
}
@Override
public void setAttribute(String key, String value) {
attributes.put(key, value);
}
@Override
public int getLevel() {
return level;
}
@Override
public String getName() {
return name;
}
@Override
public String getText() {
return text;
}
@Override
public boolean isContent() {
return isContent;
}
@Override
public boolean isEnd() {
return isEnd;
}
@Override
public boolean isStart() {
return isStart;
}
@ -158,13 +177,12 @@ public class XmlElementImpl implements XmlElement {
public static XmlElement[] splitEmptyElement(final XmlElementImpl element) {
XmlElement[] result;
if (element.isStart() && element.isEnd()) {
result =
new XmlElement[] {
new XmlElementImpl(true, false, element.getName(), element.getLevel(),
element.getAttributes(), null, element.getColumnNumber(),
element.getLineNumber()),
new XmlElementImpl(false, true, element.getName(), element.getLevel(), null,
"", element.getColumnNumber(), element.getLineNumber()) };
result = new XmlElement[] {
new XmlElementImpl(true, false, element.getName(), element.getLevel(),
element.getAttributes(), null, element.getColumnNumber(),
element.getLineNumber()),
new XmlElementImpl(false, true, element.getName(), element.getLevel(), null, "",
element.getColumnNumber(), element.getLineNumber()) };
}
else {
result = new XmlElement[] { element };