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

View file

@ -29,6 +29,8 @@
class GhidraCommand; class GhidraCommand;
extern ElementId ELEM_DOC; ///< Marshaling element \<doc>
/// \brief Registration point and dispatcher for commands sent to the decompiler /// \brief Registration point and dispatcher for commands sent to the decompiler
/// ///
/// This is the base class for \b command \b capabilities (sets of commands). /// 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_VALUE = AttributeId("value",25);
AttributeId ATTRIB_WORDSIZE = AttributeId("wordsize",26); 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_DATA = ElementId("data",1);
ElementId ELEM_INPUT = ElementId("input",2); ElementId ELEM_INPUT = ElementId("input",2);
@ -513,4 +513,4 @@ ElementId ELEM_VAL = ElementId("val",8);
ElementId ELEM_VALUE = ElementId("value",9); ElementId ELEM_VALUE = ElementId("value",9);
ElementId ELEM_VOID = ElementId("void",10); 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 /// \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. /// 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. /// Parse via getNextAttributeId is reset.
/// \param attribId is the specific attribute id to match /// \param attribId is the specific attribute id to match
/// \return the address space associated with the attribute /// \return the address space associated with the attribute

View file

@ -1,6 +1,5 @@
/* ### /* ###
* IP: GHIDRA * IP: GHIDRA
* REVIEWED: YES
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -17,8 +16,6 @@
package ghidra.app.decompiler; package ghidra.app.decompiler;
import ghidra.program.model.pcode.*; import ghidra.program.model.pcode.*;
import ghidra.util.xml.*;
import ghidra.xml.*;
public class ClangBreak extends ClangToken { public class ClangBreak extends ClangToken {
@ -29,16 +26,18 @@ public class ClangBreak extends ClangToken {
indent = 0; indent = 0;
} }
public ClangBreak(ClangNode par,int indent) { public ClangBreak(ClangNode par, int indent) {
super(par); super(par);
this.indent = indent; this.indent = indent;
} }
public int getIndent() { return indent; } public int getIndent() {
return indent;
}
@Override @Override
public void restoreFromXML(XmlElement el,XmlElement end,PcodeFactory pfactory) { public void decode(Decoder decoder, PcodeFactory pfactory) throws PcodeXMLException {
super.restoreFromXML(el,end,pfactory); indent = (int) decoder.readSignedInteger(AttributeId.ATTRIB_INDENT);
indent = SpecXmlUtils.decodeInt(el.getAttribute("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.Address;
import ghidra.program.model.address.AddressSpace; import ghidra.program.model.address.AddressSpace;
import ghidra.program.model.pcode.PcodeFactory; import ghidra.program.model.pcode.*;
import ghidra.util.xml.SpecXmlUtils;
import ghidra.xml.XmlElement;
public class ClangCommentToken extends ClangToken { public class ClangCommentToken extends ClangToken {
@ -58,12 +56,11 @@ public class ClangCommentToken extends ClangToken {
} }
@Override @Override
public void restoreFromXML(XmlElement el, XmlElement end, PcodeFactory pfactory) { public void decode(Decoder decoder, PcodeFactory pfactory) throws PcodeXMLException {
super.restoreFromXML(el, end, pfactory); AddressSpace spc = decoder.readSpace(AttributeId.ATTRIB_SPACE);
String name = el.getAttribute(ClangXML.SPACE); long offset = decoder.readUnsignedInteger(AttributeId.ATTRIB_OFF);
AddressSpace spc = pfactory.getAddressFactory().getAddressSpace(name);
long offset = SpecXmlUtils.decodeLong(el.getAttribute(ClangXML.OFFSET));
srcaddr = spc.getAddress(offset); srcaddr = spc.getAddress(offset);
super.decode(decoder, pfactory);
} }
} }

View file

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

View file

@ -1,6 +1,5 @@
/* ### /* ###
* IP: GHIDRA * IP: GHIDRA
* REVIEWED: YES
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -22,10 +21,8 @@
*/ */
package ghidra.app.decompiler; package ghidra.app.decompiler;
import ghidra.program.model.address.*; import ghidra.program.model.address.Address;
import ghidra.program.model.pcode.*; 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 HighFunction hfunc; // Overall reference to function
private PcodeOp op; // Local reference to function op private PcodeOp op; // Local reference to function op
public ClangFuncNameToken(ClangNode par,HighFunction hf) { public ClangFuncNameToken(ClangNode par, HighFunction hf) {
super(par); super(par);
hfunc = hf; hfunc = hf;
op = null; op = null;
} }
public HighFunction getHighFunction() { return hfunc; }
public HighFunction getHighFunction() {
return hfunc;
}
@Override @Override
public PcodeOp getPcodeOp() { return op; } public PcodeOp getPcodeOp() {
return op;
}
@Override @Override
public Address getMinAddress() { public Address getMinAddress() {
if (op==null) return null; if (op == null) {
return op.getSeqnum().getTarget().getPhysicalAddress(); return null;
} }
@Override
public Address getMaxAddress() {
if (op==null) return null;
return op.getSeqnum().getTarget().getPhysicalAddress(); return op.getSeqnum().getTarget().getPhysicalAddress();
} }
@Override @Override
public void restoreFromXML(XmlElement el,XmlElement end,PcodeFactory pfactory) { public Address getMaxAddress() {
super.restoreFromXML(el,end,pfactory); if (op == null) {
String oprefstring = el.getAttribute(ClangXML.OPREF); return null;
if (oprefstring != null) {
int refid = SpecXmlUtils.decodeInt(oprefstring);
op = pfactory.getOpRef(refid);
} }
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 * IP: GHIDRA
* REVIEWED: YES
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,10 +15,9 @@
*/ */
package ghidra.app.decompiler; 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.program.model.pcode.*;
import ghidra.util.xml.*;
import ghidra.xml.*;
public class ClangLabelToken extends ClangToken { public class ClangLabelToken extends ClangToken {
private Address blockaddr; // Address this is labelling private Address blockaddr; // Address this is labelling
@ -30,22 +28,26 @@ public class ClangLabelToken extends ClangToken {
} }
@Override @Override
public boolean isVariableRef() { return false; } 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);
} }
@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 * IP: GHIDRA
* REVIEWED: YES
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -22,10 +21,8 @@
*/ */
package ghidra.app.decompiler; package ghidra.app.decompiler;
import ghidra.program.model.address.*; import ghidra.program.model.address.Address;
import ghidra.program.model.pcode.*; import ghidra.program.model.pcode.*;
import ghidra.util.xml.*;
import ghidra.xml.*;
/** /**
* *
@ -43,26 +40,39 @@ public class ClangOpToken extends ClangToken {
} }
@Override @Override
public PcodeOp getPcodeOp() { return op; } public PcodeOp getPcodeOp() {
return op;
}
@Override @Override
public Address getMinAddress() { public Address getMinAddress() {
if (op==null) return null; if (op == null) {
return op.getSeqnum().getTarget().getPhysicalAddress(); return null;
} }
@Override
public Address getMaxAddress() {
if (op==null) return null;
return op.getSeqnum().getTarget().getPhysicalAddress(); return op.getSeqnum().getTarget().getPhysicalAddress();
} }
@Override @Override
public void restoreFromXML(XmlElement el,XmlElement end,PcodeFactory pfactory) { public Address getMaxAddress() {
super.restoreFromXML(el,end,pfactory); if (op == null) {
String oprefstring = el.getAttribute(ClangXML.OPREF); return null;
if (oprefstring != null) { }
int refid = SpecXmlUtils.decodeInt(oprefstring); 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); op = pfactory.getOpRef(refid);
} }
} }
decoder.rewindAttributes();
super.decode(decoder, pfactory);
}
} }

View file

@ -1,6 +1,5 @@
/* ### /* ###
* IP: GHIDRA * IP: GHIDRA
* REVIEWED: YES
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -22,11 +21,10 @@
*/ */
package ghidra.app.decompiler; package ghidra.app.decompiler;
import ghidra.program.model.data.*; import ghidra.program.model.data.DataType;
import ghidra.program.model.pcode.*; import ghidra.program.model.pcode.*;
import ghidra.util.*; import ghidra.util.Msg;
import ghidra.util.xml.*;
import ghidra.xml.*;
/** /**
* *
* *
@ -43,16 +41,23 @@ public class ClangReturnType extends ClangTokenGroup {
datatype = null; datatype = null;
} }
public DataType getDataType() { return datatype; } public DataType getDataType() {
public Varnode getVarnode() { return varnode; } return datatype;
}
public Varnode getVarnode() {
return varnode;
}
@Override @Override
public void restoreFromXML(XmlPullParser parser,PcodeFactory pfactory) { public void decode(Decoder decoder, PcodeFactory pfactory) throws PcodeXMLException {
XmlElement node = parser.peek(); for (;;) {
super.restoreFromXML(parser,pfactory); int attribId = decoder.getNextAttributeId();
String varrefstring = node.getAttribute(ClangXML.VARNODEREF); if (attribId == 0) {
if (varrefstring != null) { break;
int refid = SpecXmlUtils.decodeInt(varrefstring); }
if (attribId == AttributeId.ATTRIB_VARREF.getId()) {
int refid = (int) decoder.readUnsignedInteger();
varnode = pfactory.getRef(refid); varnode = pfactory.getRef(refid);
if (varnode != null) { if (varnode != null) {
if (varnode.getHigh() == null) { if (varnode.getHigh() == null) {
@ -61,6 +66,9 @@ public class ClangReturnType extends ClangTokenGroup {
} }
datatype = varnode.getHigh().getDataType(); datatype = varnode.getHigh().getDataType();
} }
break;
} }
} }
super.decode(decoder, pfactory);
}
} }

View file

@ -1,6 +1,5 @@
/* ### /* ###
* IP: GHIDRA * IP: GHIDRA
* REVIEWED: YES
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -23,8 +22,7 @@
package ghidra.app.decompiler; package ghidra.app.decompiler;
import ghidra.program.model.pcode.*; import ghidra.program.model.pcode.*;
import ghidra.util.xml.*;
import ghidra.xml.*;
/** /**
* *
* *
@ -40,16 +38,28 @@ import ghidra.xml.*;
public class ClangStatement extends ClangTokenGroup { public class ClangStatement extends ClangTokenGroup {
private PcodeOp op; // Root op of C-statement private PcodeOp op; // Root op of C-statement
public ClangStatement(ClangNode par) { super(par); op = null; } public ClangStatement(ClangNode par) {
public PcodeOp getPcodeOp() { return op; } super(par);
@Override op = null;
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);
} }
super.restoreFromXML(parser,pfactory);
public PcodeOp getPcodeOp() {
return op;
}
@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;
}
}
super.decode(decoder, pfactory);
} }
} }

View file

@ -1,6 +1,5 @@
/* ### /* ###
* IP: GHIDRA * IP: GHIDRA
* REVIEWED: YES
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -23,8 +22,6 @@
package ghidra.app.decompiler; package ghidra.app.decompiler;
import ghidra.program.model.pcode.*; 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 * A SyntaxToken may be or may include spacing
*/ */
public class ClangSyntaxToken extends ClangToken { public class ClangSyntaxToken extends ClangToken {
private int open,close; private int open, close;
public ClangSyntaxToken(ClangNode par) { public ClangSyntaxToken(ClangNode par) {
super(par); super(par);
open = close = -1; open = close = -1;
} }
public ClangSyntaxToken(ClangNode par,String txt) {
super(par,txt); public ClangSyntaxToken(ClangNode par, String txt) {
super(par, txt);
open = close = -1; 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; open = close = -1;
} }
@Override @Override
public boolean isVariableRef() { public boolean isVariableRef() {
if (Parent() instanceof ClangVariableDecl) return true; if (Parent() instanceof ClangVariableDecl) {
return true;
}
return false; return false;
} }
@Override @Override
public void restoreFromXML(XmlElement el,XmlElement end,PcodeFactory pfactory) { public void decode(Decoder decoder, PcodeFactory pfactory) throws PcodeXMLException {
super.restoreFromXML(el,end,pfactory); for (;;) {
String str = el.getAttribute("open"); int attribId = decoder.getNextAttributeId();
if (str != null) if (attribId == 0) {
open = SpecXmlUtils.decodeInt(str); break;
str = el.getAttribute("close"); }
if (str != null) if (attribId == AttributeId.ATTRIB_OPEN.getId()) {
close = SpecXmlUtils.decodeInt(str); 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 getOpen() {
public int getClose() { return close; } 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.app.plugin.core.decompile.*;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.pcode.*; 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; this.text = text;
} }
public void restoreFromXML(XmlElement el, XmlElement end, PcodeFactory pfactory) { public void decode(Decoder decoder, PcodeFactory pfactory) throws PcodeXMLException {
text = end.getText(); String col = null;
String col = el.getAttribute(ClangXML.COLOR); 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); syntax_type = getColor(col);
} }
@ -165,70 +173,67 @@ public class ClangToken implements ClangNode {
list.add(this); list.add(this);
} }
static public ClangToken buildToken(ClangNode par, XmlPullParser parser, static public ClangToken buildToken(int node, ClangNode par, Decoder decoder,
PcodeFactory pfactory) { PcodeFactory pfactory) throws PcodeXMLException {
XmlElement node =
parser.start(ClangXML.VARIABLE, ClangXML.OP, ClangXML.SYNTAX, ClangXML.BREAK,
ClangXML.FUNCNAME, ClangXML.TYPE, ClangXML.COMMENT, ClangXML.LABEL, ClangXML.FIELD);
ClangToken token = null; ClangToken token = null;
if (node.getName().equals(ClangXML.VARIABLE)) { if (node == ElementId.ELEM_VARIABLE.getId()) {
token = new ClangVariableToken(par); token = new ClangVariableToken(par);
} }
else if (node.getName().equals(ClangXML.OP)) { else if (node == ElementId.ELEM_OP.getId()) {
token = new ClangOpToken(par); token = new ClangOpToken(par);
} }
else if (node.getName().equals(ClangXML.SYNTAX)) { else if (node == ElementId.ELEM_SYNTAX.getId()) {
token = new ClangSyntaxToken(par); token = new ClangSyntaxToken(par);
} }
else if (node.getName().equals(ClangXML.BREAK)) { else if (node == ElementId.ELEM_BREAK.getId()) {
token = new ClangBreak(par); token = new ClangBreak(par);
} }
else if (node.getName().equals(ClangXML.FUNCNAME)) { else if (node == ElementId.ELEM_FUNCNAME.getId()) {
token = new ClangFuncNameToken(par, null); token = new ClangFuncNameToken(par, null);
} }
else if (node.getName().equals(ClangXML.TYPE)) { else if (node == ElementId.ELEM_TYPE.getId()) {
token = new ClangTypeToken(par); token = new ClangTypeToken(par);
} }
else if (node.getName().equals(ClangXML.COMMENT)) { else if (node == ElementId.ELEM_COMMENT.getId()) {
token = new ClangCommentToken(par); token = new ClangCommentToken(par);
} }
else if (node.getName().equals(ClangXML.LABEL)) { else if (node == ElementId.ELEM_LABEL.getId()) {
token = new ClangLabelToken(par); token = new ClangLabelToken(par);
} }
else if (node.getName().equals(ClangXML.FIELD)) { else if (node == ElementId.ELEM_FIELD.getId()) {
token = new ClangFieldToken(par); token = new ClangFieldToken(par);
} }
XmlElement end = parser.end(node); else {
if (token != null) { throw new PcodeXMLException("Expecting token element");
token.restoreFromXML(node, end, pfactory);
} }
token.decode(decoder, pfactory);
return token; return token;
} }
public static int getColor(String col) { public static int getColor(String col) {
if (col != null) { if (col != null) {
if (col.equals(ClangXML.KEYWORD_COLOR)) { if (col.equals(ClangMarkup.KEYWORD_COLOR)) {
return KEYWORD_COLOR; return KEYWORD_COLOR;
} }
else if (col.equals(ClangXML.VARIABLE_COLOR)) { else if (col.equals(ClangMarkup.VARIABLE_COLOR)) {
return VARIABLE_COLOR; return VARIABLE_COLOR;
} }
else if (col.equals(ClangXML.CONST_COLOR)) { else if (col.equals(ClangMarkup.CONST_COLOR)) {
return CONST_COLOR; return CONST_COLOR;
} }
else if (col.equals(ClangXML.PARAMETER_COLOR)) { else if (col.equals(ClangMarkup.PARAMETER_COLOR)) {
return PARAMETER_COLOR; return PARAMETER_COLOR;
} }
else if (col.equals(ClangXML.GLOBAL_COLOR)) { else if (col.equals(ClangMarkup.GLOBAL_COLOR)) {
return GLOBAL_COLOR; return GLOBAL_COLOR;
} }
else if (col.equals(ClangXML.TYPE_COLOR)) { else if (col.equals(ClangMarkup.TYPE_COLOR)) {
return TYPE_COLOR; return TYPE_COLOR;
} }
else if (col.equals(ClangXML.COMMENT_COLOR)) { else if (col.equals(ClangMarkup.COMMENT_COLOR)) {
return COMMENT_COLOR; return COMMENT_COLOR;
} }
else if (col.equals(ClangXML.FUNCNAME_COLOR)) { else if (col.equals(ClangMarkup.FUNCNAME_COLOR)) {
return FUNCTION_COLOR; return FUNCTION_COLOR;
} }
} }

View file

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

View file

@ -1,6 +1,5 @@
/* ### /* ###
* IP: GHIDRA * IP: GHIDRA
* REVIEWED: YES
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -22,9 +21,9 @@
*/ */
package ghidra.app.decompiler; package ghidra.app.decompiler;
import ghidra.program.model.data.*; import ghidra.program.model.data.DataType;
import ghidra.program.model.pcode.*; import ghidra.program.model.pcode.*;
import ghidra.xml.*;
/** /**
* *
* *
@ -41,7 +40,9 @@ public class ClangTypeToken extends ClangToken {
@Override @Override
public boolean isVariableRef() { public boolean isVariableRef() {
if (Parent() instanceof ClangVariableDecl) return true; if (Parent() instanceof ClangVariableDecl) {
return true;
}
return false; return false;
} }
@ -50,8 +51,20 @@ public class ClangTypeToken extends ClangToken {
} }
@Override @Override
public void restoreFromXML(XmlElement el,XmlElement end,PcodeFactory pfactory) { public void decode(Decoder decoder, PcodeFactory pfactory) throws PcodeXMLException {
super.restoreFromXML(el,end,pfactory); int id = 0;
datatype = pfactory.getDataTypeManager().findBaseType(getText(),el.getAttribute("id")); 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.data.DataType;
import ghidra.program.model.pcode.*; import ghidra.program.model.pcode.*;
import ghidra.util.Msg; 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 @Override
public void restoreFromXML(XmlPullParser parser, PcodeFactory pfactory) { public void decode(Decoder decoder, PcodeFactory pfactory) throws PcodeXMLException {
XmlElement node = parser.peek(); long symref = decoder.readUnsignedInteger(AttributeId.ATTRIB_SYMREF);
super.restoreFromXML(parser, pfactory); super.decode(decoder, pfactory);
long symref = SpecXmlUtils.decodeLong(node.getAttribute(ClangXML.SYMREF));
HighSymbol sym = pfactory.getSymbol(symref); HighSymbol sym = pfactory.getSymbol(symref);
if (sym == null) { if (sym == null) {
Msg.error(this, "Invalid symbol reference: " + symref + " in " + Parent()); Msg.error(this, "Invalid symbol reference: " + symref + " in " + Parent());

View file

@ -1,6 +1,5 @@
/* ### /* ###
* IP: GHIDRA * IP: GHIDRA
* REVIEWED: YES
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -22,10 +21,9 @@
*/ */
package ghidra.app.decompiler; package ghidra.app.decompiler;
import ghidra.program.model.address.*; import ghidra.program.model.address.Address;
import ghidra.program.model.pcode.*; import ghidra.program.model.pcode.*;
import ghidra.util.xml.*;
import ghidra.xml.*;
/** /**
* *
* *
@ -58,14 +56,20 @@ public class ClangVariableToken extends ClangToken {
@Override @Override
public Address getMinAddress() { public Address getMinAddress() {
if (op==null) return null; if (op == null) {
return null;
}
return op.getSeqnum().getTarget().getPhysicalAddress(); return op.getSeqnum().getTarget().getPhysicalAddress();
} }
@Override @Override
public Address getMaxAddress() { public Address getMaxAddress() {
if (op==null) return null; if (op == null) {
return null;
}
return op.getSeqnum().getTarget().getPhysicalAddress(); return op.getSeqnum().getTarget().getPhysicalAddress();
} }
@Override @Override
public HighVariable getHighVariable() { public HighVariable getHighVariable() {
Varnode inst = getVarnode(); Varnode inst = getVarnode();
@ -82,17 +86,22 @@ public class ClangVariableToken extends ClangToken {
} }
@Override @Override
public void restoreFromXML(XmlElement el,XmlElement end,PcodeFactory pfactory) { public void decode(Decoder decoder, PcodeFactory pfactory) throws PcodeXMLException {
super.restoreFromXML(el,end,pfactory); for (;;) {
String varrefstring = el.getAttribute(ClangXML.VARNODEREF); int attribId = decoder.getNextAttributeId();
if (varrefstring != null) { if (attribId == 0) {
int refid = SpecXmlUtils.decodeInt(varrefstring); break;
}
if (attribId == AttributeId.ATTRIB_VARREF.getId()) {
int refid = (int) decoder.readUnsignedInteger();
varnode = pfactory.getRef(refid); varnode = pfactory.getRef(refid);
} }
String oprefstring = el.getAttribute(ClangXML.OPREF); else if (attribId == AttributeId.ATTRIB_OPREF.getId()) {
if (oprefstring != null) { int refid = (int) decoder.readUnsignedInteger();
int refid = SpecXmlUtils.decodeInt(oprefstring);
op = pfactory.getOpRef(refid); 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.program.model.pcode.*;
import ghidra.util.task.CancelledListener; import ghidra.util.task.CancelledListener;
import ghidra.util.task.TaskMonitor; import ghidra.util.task.TaskMonitor;
import ghidra.xml.XmlPullParser;
/** /**
* This is a self-contained interface to a single decompile * This is a self-contained interface to a single decompile
@ -669,10 +668,10 @@ public class DecompInterface {
timeoutSecs); timeoutSecs);
decompileMessage = decompCallback.getNativeMessage(); decompileMessage = decompCallback.getNativeMessage();
if (res != null) { if (res != null) {
XmlPullParser parser = HighFunction.stringTree(res.getInputStream(), XmlDecode decoder = new XmlDecode(factory);
HighFunction.getErrorHandler(this, "Results for structureGraph command")); decoder.ingestStream(res.getInputStream(), "structureGraph results");
resgraph = new BlockGraph(); resgraph = new BlockGraph();
resgraph.restoreXml(parser, factory); resgraph.restoreXml(decoder);
resgraph.transferObjectRef(ingraph); resgraph.transferObjectRef(ingraph);
} }
} }

View file

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

View file

@ -22,6 +22,7 @@ import ghidra.program.model.lang.PackedBytes;
import ghidra.util.Msg; import ghidra.util.Msg;
import ghidra.util.timer.GTimer; import ghidra.util.timer.GTimer;
import ghidra.util.timer.GTimerMonitor; import ghidra.util.timer.GTimerMonitor;
import ghidra.util.xml.SpecXmlUtils;
/** /**
* *
@ -787,7 +788,7 @@ public class DecompileProcess {
private void getType() throws IOException { private void getType() throws IOException {
String name = readQueryString(); String name = readQueryString();
String id = readQueryString(); long id = SpecXmlUtils.decodeLong(readQueryString());
String res = callback.getType(name, id); String res = callback.getType(name, id);
write(query_response_start); write(query_response_start);
if ((res != null) && (res.length() != 0)) { if ((res != null) && (res.length() != 0)) {
@ -816,7 +817,7 @@ public class DecompileProcess {
private void getStringData() throws IOException { private void getStringData() throws IOException {
String addr = readQueryString(); String addr = readQueryString();
String dtName = readQueryString(); String dtName = readQueryString();
String dtId = readQueryString(); long dtId = SpecXmlUtils.decodeLong(readQueryString());
DecompileCallback.StringData stringData = callback.getStringData(addr, dtName, dtId); DecompileCallback.StringData stringData = callback.getStringData(addr, dtName, dtId);
write(query_response_start); write(query_response_start);
if (stringData != null) { 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.lang.Language;
import ghidra.program.model.listing.Function; import ghidra.program.model.listing.Function;
import ghidra.program.model.pcode.*; import ghidra.program.model.pcode.*;
import ghidra.xml.XmlElement;
import ghidra.xml.XmlPullParser;
/** /**
* Class for getting at the various structures returned * Class for getting at the various structures returned
@ -75,7 +73,7 @@ public class DecompileResults {
hparamid = null; hparamid = null;
docroot = null; docroot = null;
//dumpResults(raw); //dumpResults(raw);
parseRawString(raw); decodeStream(raw);
} }
// private void dumpResults(String raw) { // private void dumpResults(String raw) {
@ -203,45 +201,45 @@ public class DecompileResults {
return printer.print(true); return printer.print(true);
} }
private void parseRawString(InputStream rawxml) { private void decodeStream(InputStream rawstream) {
if (rawxml == null) { if (rawstream == null) {
return; return;
} }
XmlPullParser parser = null; XmlDecode decoder = new XmlDecode(function.getProgram().getAddressFactory());
try { try {
try { decoder.ingestStream(rawstream,
parser = "Decompiler results for function at " + function.getEntryPoint());
HighFunction.stringTree(
rawxml,
HighFunction.getErrorHandler(this, "decompiler results for function at " +
function.getEntryPoint()));
hfunc = null; hfunc = null;
hparamid = null; hparamid = null;
docroot = null; docroot = null;
parser.start("doc"); int docel = decoder.openElement(ElementId.ELEM_DOC);
while(parser.peek().isStart()) { for (;;) {
XmlElement el = parser.peek(); int el = decoder.peekElement();
if (el.getName().equals("function")) { if (el == 0) {
break;
}
if (el == ElementId.ELEM_FUNCTION.getId()) {
if (hfunc == null) { if (hfunc == null) {
hfunc = new HighFunction(function, language, compilerSpec, dtmanage); hfunc = new HighFunction(function, language, compilerSpec, dtmanage);
hfunc.readXML(parser); hfunc.decode(decoder);
} }
else { // TODO: This is an ugly kludge to get around duplicate XML tag names else { // TODO: This is an ugly kludge to get around duplicate XML tag names
docroot = ClangXML.buildClangTree(parser, hfunc); docroot = ClangMarkup.buildClangTree(decoder, hfunc);
if (docroot == null) { if (docroot == null) {
errMsg = "Unable to parse C (xml)"; errMsg = "Unable to decode C markup";
} }
} }
} }
else if (el.getName().equals("parammeasures")) { else if (el == ElementId.ELEM_PARAMMEASURES.getId()) {
hparamid = new HighParamID(function, language, compilerSpec, dtmanage); hparamid = new HighParamID(function, language, compilerSpec, dtmanage);
hparamid.readXML(parser); hparamid.decode(decoder);
} }
else { else {
errMsg = "Unknown decompiler tag: "+el.getName(); errMsg = "Unknown decompiler tag";
return; return;
} }
} }
decoder.closeElement(docel);
} }
catch (PcodeXMLException e) { // Error while walking the DOM catch (PcodeXMLException e) { // Error while walking the DOM
errMsg = e.getMessage(); errMsg = e.getMessage();
@ -256,10 +254,4 @@ public class DecompileResults {
return; return;
} }
} }
finally {
if (parser != null) {
parser.dispose();
}
}
}
} }

View file

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

View file

@ -15,73 +15,13 @@
*/ */
package ghidra.program.model.lang; package ghidra.program.model.lang;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList; 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.app.plugin.processors.sleigh.SleighLanguage;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressFactory;
import ghidra.program.model.pcode.*; import ghidra.program.model.pcode.*;
import ghidra.util.xml.SpecXmlUtils;
public class InjectContext { 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 SleighLanguage language;
public Address baseAddr; // Base address of op (call,userop) causing the inject public Address baseAddr; // Base address of op (call,userop) causing the inject
@ -94,18 +34,44 @@ public class InjectContext {
public InjectContext() { public InjectContext() {
} }
public void restoreXml(SAXParser parser, String xml, AddressFactory addrFactory) public void decode(Decoder decoder) throws PcodeXMLException {
throws PcodeXMLException { int el = decoder.openElement(ElementId.ELEM_CONTEXT);
Handler handler = new Handler(addrFactory); baseAddr = AddressXML.decode(decoder);
try { callAddr = AddressXML.decode(decoder);
parser.parse(new InputSource(new StringReader(xml)), handler); int subel = decoder.peekElement();
if (subel == ElementId.ELEM_INPUT.getId()) {
decoder.openElement();
inputlist = new ArrayList<>();
for (;;) {
int addrel = decoder.peekElement();
if (addrel == 0) {
break;
} }
catch (SAXException e) { decoder.openElement();
throw new PcodeXMLException("Problem parsing inject context: " + e.getMessage()); Address addr = AddressXML.decodeFromAttributes(decoder);
int size = (int) decoder.readSignedInteger(AttributeId.ATTRIB_SIZE);
decoder.closeElement(addrel);
inputlist.add(new Varnode(addr, size));
} }
catch (IOException e) { decoder.closeElement(subel);
throw new PcodeXMLException("Problem parsing inject context: " + e.getMessage()); subel = decoder.peekElement();
} }
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);
}
decoder.closeElement(el);
} }
} }

View file

@ -17,9 +17,8 @@ package ghidra.program.model.pcode;
import java.util.ArrayList; import java.util.ArrayList;
import org.xml.sax.Attributes; import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSpace;
import ghidra.program.model.address.*;
import ghidra.program.model.lang.*; import ghidra.program.model.lang.*;
import ghidra.util.xml.SpecXmlUtils; import ghidra.util.xml.SpecXmlUtils;
import ghidra.xml.XmlElement; import ghidra.xml.XmlElement;
@ -358,155 +357,74 @@ public class AddressXML {
} }
/** /**
* Parse String containing an XML tag representing an Address. * Create an address from "space" and "offset" attributes of the current element
* The format options are simple enough that we don't try to invoke * @param decoder is the stream decoder
* an actual XML parser but just walk the string. This recognizes * @return the decoded Address
* - \<addr> * @throws PcodeXMLException for any problems decoding the stream
* - \<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
*/ */
public static Address readXML(String addrstring, AddressFactory addrfactory) public static Address decodeFromAttributes(Decoder decoder) throws PcodeXMLException {
throws PcodeXMLException { AddressSpace spc = null;
long offset = -1;
int tagstart = addrstring.indexOf('<'); for (;;) {
if (tagstart >= 0) { int attribId = decoder.getNextAttributeId();
tagstart += 1; if (attribId == 0) {
if (addrstring.startsWith("spaceid", tagstart)) { break;
tagstart += 8; }
int attrstart = addrstring.indexOf("name=\"", tagstart); if (attribId == AttributeId.ATTRIB_SPACE.getId()) {
if (attrstart >= 0) { spc = decoder.readSpace();
attrstart += 6; }
int nameend = addrstring.indexOf('\"', attrstart); else if (attribId == AttributeId.ATTRIB_OFFSET.getId()) {
if (nameend >= 0) { offset = decoder.readUnsignedInteger();
AddressSpace spc =
addrfactory.getAddressSpace(addrstring.substring(attrstart, nameend));
int spaceid = spc.getSpaceID();
spc = addrfactory.getConstantSpace();
return spc.getAddress(spaceid);
} }
} }
}
// 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) { if (spc == null) {
return Address.NO_ADDRESS; return Address.NO_ADDRESS;
} }
long offset = SpecXmlUtils.decodeLong(offstr);
return spc.getAddress(offset); return spc.getAddress(offset);
} }
}
}
}
}
throw new PcodeXMLException("Badly formed address: " + addrstring);
}
/** /**
* Read the (first) size attribute from an XML tag string as an integer * Create an address from a stream encoding. This recognizes elements
* @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> * - \<addr>
* - \<spaceid> * - \<spaceid>
* - \<iop> or * - \<iop> or
* - any tag with "space" and "offset" attributes * - any element with "space" and "offset" attributes
* *
* An empty \<addr> tag, with no attributes, results in Address.NO_ADDRESS being returned. * An empty \<addr> element, with no attributes, results in Address.NO_ADDRESS being returned.
* @param el is the parse tree element * @param decoder is the stream decoder
* @param addrFactory address factory used to create valid addresses
* @return Address created from XML info * @return Address created from XML info
* @throws PcodeXMLException for any problems decoding the stream
*/ */
public static Address readXML(XmlElement el, AddressFactory addrFactory) { public static Address decode(Decoder decoder) throws PcodeXMLException {
String localName = el.getName(); int el = decoder.openElement();
if (localName.equals("spaceid")) { if (el == ElementId.ELEM_SPACEID.getId()) {
AddressSpace spc = addrFactory.getAddressSpace(el.getAttribute("name")); AddressSpace spc = decoder.readSpace(AttributeId.ATTRIB_NAME);
decoder.closeElement(el);
int spaceid = spc.getSpaceID(); int spaceid = spc.getSpaceID();
spc = addrFactory.getConstantSpace(); spc = decoder.getAddressFactory().getConstantSpace();
return spc.getAddress(spaceid); return spc.getAddress(spaceid);
} }
else if (localName.equals("iop")) { else if (el == ElementId.ELEM_IOP.getId()) {
int ref = SpecXmlUtils.decodeInt(el.getAttribute("value")); int ref = (int) decoder.readUnsignedInteger(AttributeId.ATTRIB_VALUE);
AddressSpace spc = addrFactory.getConstantSpace(); decoder.closeElement(el);
AddressSpace spc = decoder.getAddressFactory().getConstantSpace();
return spc.getAddress(ref); return spc.getAddress(ref);
} }
String space = el.getAttribute("space"); AddressSpace spc = null;
if (space == null) { long offset = -1;
return Address.NO_ADDRESS; for (;;) {
int attribId = decoder.getNextAttributeId();
if (attribId == 0) {
break;
} }
long offset = SpecXmlUtils.decodeLong(el.getAttribute("offset")); if (attribId == AttributeId.ATTRIB_SPACE.getId()) {
AddressSpace spc = addrFactory.getAddressSpace(space); spc = decoder.readSpace();
if (spc == null) {
return null;
} }
return spc.getAddress(offset); else if (attribId == AttributeId.ATTRIB_OFFSET.getId()) {
offset = decoder.readUnsignedInteger();
} }
/**
* Read an Address given an XML tag name and its attributes. This recognizes XML tags
* - \<addr>
* - \<spaceid>
* - \<iop>
* - any tag with "space" or "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
*/
public static Address readXML(String localName, Attributes attr, AddressFactory addrFactory) {
if (localName.equals("spaceid")) {
AddressSpace spc = addrFactory.getAddressSpace(attr.getValue("name"));
int spaceid = spc.getSpaceID();
spc = addrFactory.getConstantSpace();
return spc.getAddress(spaceid);
} }
else if (localName.equals("iop")) { decoder.closeElement(el);
int ref = SpecXmlUtils.decodeInt(attr.getValue("value"));
AddressSpace spc = addrFactory.getConstantSpace();
return spc.getAddress(ref);
}
String space = attr.getValue("space");
if (space == null) {
return Address.NO_ADDRESS;
}
long offset = SpecXmlUtils.decodeLong(attr.getValue("offset"));
AddressSpace spc = addrFactory.getAddressSpace(space);
if (spc == null) { if (spc == null) {
return Address.NO_ADDRESS; 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.program.model.lang.UnknownInstructionException;
import ghidra.util.xml.SpecXmlUtils; import ghidra.util.xml.SpecXmlUtils;
import ghidra.xml.XmlElement;
/** /**
* Block representing and '&amp;&amp;' or '||' control flow path within a conditional expression * Block representing and '&amp;&amp;' or '||' control flow path within a conditional expression
@ -49,12 +48,13 @@ public class BlockCondition extends BlockGraph {
} }
@Override @Override
public void restoreXmlHeader(XmlElement el) throws PcodeXMLException { public void decodeHeader(Decoder decoder) throws PcodeXMLException {
super.restoreXmlHeader(el); super.decodeHeader(decoder);
String opcodename = el.getAttribute("opcode"); String opcodename = decoder.readString(AttributeId.ATTRIB_OPCODE);
try { try {
opcode = PcodeOp.getOpcode(opcodename); opcode = PcodeOp.getOpcode(opcodename);
} catch (UnknownInstructionException e) { }
catch (UnknownInstructionException e) {
opcode = PcodeOp.BOOL_AND; opcode = PcodeOp.BOOL_AND;
} }
} }

View file

@ -17,7 +17,6 @@ package ghidra.program.model.pcode;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.util.xml.SpecXmlUtils; import ghidra.util.xml.SpecXmlUtils;
import ghidra.xml.XmlElement;
/** /**
* Placeholder for a basic block (BlockBasic) within a structured * Placeholder for a basic block (BlockBasic) within a structured
@ -37,7 +36,7 @@ public class BlockCopy extends PcodeBlock {
ref = null; ref = null;
} }
public BlockCopy(Object r,Address addr) { public BlockCopy(Object r, Address addr) {
super(); super();
ref = r; ref = r;
blocktype = PcodeBlock.COPY; blocktype = PcodeBlock.COPY;
@ -85,8 +84,8 @@ public class BlockCopy extends PcodeBlock {
} }
@Override @Override
public void restoreXmlHeader(XmlElement el) throws PcodeXMLException { public void decodeHeader(Decoder decoder) throws PcodeXMLException {
super.restoreXmlHeader(el); super.decodeHeader(decoder);
altindex = SpecXmlUtils.decodeInt(el.getAttribute("altindex")); altindex = (int) decoder.readSignedInteger(AttributeId.ATTRIB_ALTINDEX);
} }
} }

View file

@ -19,8 +19,6 @@ import java.io.IOException;
import java.io.Writer; import java.io.Writer;
import ghidra.util.xml.SpecXmlUtils; import ghidra.util.xml.SpecXmlUtils;
import ghidra.xml.XmlElement;
import ghidra.xml.XmlPullParser;
/** /**
* A "plain" goto block * A "plain" goto block
@ -67,13 +65,13 @@ public class BlockGoto extends BlockGraph {
} }
@Override @Override
public void restoreXmlBody(XmlPullParser parser, BlockMap resolver) throws PcodeXMLException { public void decodeBody(Decoder decoder, BlockMap resolver) throws PcodeXMLException {
super.restoreXmlBody(parser, resolver); super.decodeBody(decoder, resolver);
XmlElement el = parser.start("target"); int el = decoder.openElement(ElementId.ELEM_TARGET);
int target = SpecXmlUtils.decodeInt(el.getAttribute("index")); int target = (int) decoder.readSignedInteger(AttributeId.ATTRIB_INDEX);
int depth = SpecXmlUtils.decodeInt(el.getAttribute("depth")); int depth = (int) decoder.readSignedInteger(AttributeId.ATTRIB_DEPTH);
gototype = SpecXmlUtils.decodeInt(el.getAttribute("type")); gototype = (int) decoder.readUnsignedInteger(AttributeId.ATTRIB_TYPE);
parser.end(el); decoder.closeElement(el);
resolver.addGotoRef(this, target, depth); resolver.addGotoRef(this, target, depth);
} }
} }

View file

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

View file

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

View file

@ -20,8 +20,6 @@ import java.io.Writer;
import java.util.ArrayList; import java.util.ArrayList;
import ghidra.util.xml.SpecXmlUtils; import ghidra.util.xml.SpecXmlUtils;
import ghidra.xml.XmlElement;
import ghidra.xml.XmlPullParser;
/** /**
* A block representing a 2-or-more control flow branchpoint * A block representing a 2-or-more control flow branchpoint
@ -38,7 +36,7 @@ public class BlockMultiGoto extends BlockGraph {
public BlockMultiGoto() { public BlockMultiGoto() {
super(); super();
targets = new ArrayList<PcodeBlock>(); targets = new ArrayList<>();
blocktype = PcodeBlock.MULTIGOTO; blocktype = PcodeBlock.MULTIGOTO;
} }
@ -49,9 +47,8 @@ public class BlockMultiGoto extends BlockGraph {
@Override @Override
public void saveXmlBody(Writer writer) throws IOException { public void saveXmlBody(Writer writer) throws IOException {
super.saveXmlBody(writer); super.saveXmlBody(writer);
for(int i=0;i<targets.size();++i) { for (PcodeBlock gototarget : targets) {
PcodeBlock gototarget = targets.get(i);
StringBuilder buf = new StringBuilder(); StringBuilder buf = new StringBuilder();
buf.append("<target"); buf.append("<target");
PcodeBlock leaf = gototarget.getFrontLeaf(); PcodeBlock leaf = gototarget.getFrontLeaf();
@ -65,14 +62,17 @@ public class BlockMultiGoto extends BlockGraph {
} }
@Override @Override
public void restoreXmlBody(XmlPullParser parser, BlockMap resolver) throws PcodeXMLException { public void decodeBody(Decoder decoder, BlockMap resolver) throws PcodeXMLException {
super.restoreXmlBody(parser, resolver); super.decodeBody(decoder, resolver);
while(parser.peek().isStart()) { for (;;) {
XmlElement el = parser.start("target"); int el = decoder.peekElement();
int target = SpecXmlUtils.decodeInt(el.getAttribute("index")); if (el != ElementId.ELEM_TARGET.getId()) {
int depth = SpecXmlUtils.decodeInt(el.getAttribute("depth")); break;
// int gototype = SpecXmlUtils.decodeInt(el.getAttribute("type")); }
parser.end(el); 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); 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.program.model.listing.VariableStorage;
import ghidra.util.exception.AssertException; import ghidra.util.exception.AssertException;
import ghidra.util.exception.InvalidInputException; 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 * A HighSymbol mapping based on local hashing of the symbol's Varnode within a
@ -63,11 +60,11 @@ public class DynamicEntry extends SymbolEntry {
} }
@Override @Override
public void restoreXML(XmlPullParser parser) throws PcodeXMLException { public void decode(Decoder decoder) throws PcodeXMLException {
XmlElement addrel = parser.start("hash"); int addrel = decoder.openElement(ElementId.ELEM_HASH);
hash = SpecXmlUtils.decodeLong(addrel.getAttribute("val")); hash = decoder.readUnsignedInteger(AttributeId.ATTRIB_VAL);
parser.end(addrel); decoder.closeElement(addrel);
parseRangeList(parser); decodeRangeList(decoder);
} }
@Override @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.address.Address;
import ghidra.program.model.data.DataType; import ghidra.program.model.data.DataType;
import ghidra.util.xml.SpecXmlUtils; import ghidra.util.xml.SpecXmlUtils;
import ghidra.xml.XmlElement;
import ghidra.xml.XmlPullParser;
public class EquateSymbol extends HighSymbol { public class EquateSymbol extends HighSymbol {
@ -66,12 +64,22 @@ public class EquateSymbol extends HighSymbol {
} }
@Override @Override
public void restoreXML(XmlPullParser parser) throws PcodeXMLException { public void decode(Decoder decoder) throws PcodeXMLException {
XmlElement symel = parser.start("equatesymbol"); int symel = decoder.openElement(ElementId.ELEM_EQUATESYMBOL);
restoreXMLHeader(symel); decodeHeader(decoder);
type = DataType.DEFAULT; type = DataType.DEFAULT;
convert = FORMAT_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 != null) {
if (formString.equals("hex")) { if (formString.equals("hex")) {
convert = FORMAT_HEX; convert = FORMAT_HEX;
@ -89,9 +97,10 @@ public class EquateSymbol extends HighSymbol {
convert = FORMAT_BIN; convert = FORMAT_BIN;
} }
} }
parser.start("value"); int valel = decoder.openElement(ElementId.ELEM_VALUE);
value = SpecXmlUtils.decodeLong(parser.end().getText()); // End <value> tag value = decoder.readUnsignedInteger(AttributeId.ATTRIB_CONTENT);
parser.end(symel); decoder.closeElement(valel);
decoder.closeElement(symel);
} }
@Override @Override

View file

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

View file

@ -21,7 +21,6 @@ import ghidra.program.model.data.DataType;
import ghidra.program.model.listing.*; import ghidra.program.model.listing.*;
import ghidra.program.model.symbol.SymbolUtilities; import ghidra.program.model.symbol.SymbolUtilities;
import ghidra.util.exception.InvalidInputException; 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 * 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 @Override
public void restoreXML(XmlPullParser parser) throws PcodeXMLException { public void decode(Decoder decoder) throws PcodeXMLException {
super.restoreXML(parser); super.decode(decoder);
symbol = null; symbol = null;
} }

View file

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

View file

@ -15,12 +15,9 @@
*/ */
package ghidra.program.model.pcode; package ghidra.program.model.pcode;
import java.io.InputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.xml.sax.*;
import ghidra.program.database.function.FunctionDB; import ghidra.program.database.function.FunctionDB;
import ghidra.program.database.symbol.CodeSymbol; import ghidra.program.database.symbol.CodeSymbol;
import ghidra.program.model.address.Address; 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.lang.*;
import ghidra.program.model.listing.*; import ghidra.program.model.listing.*;
import ghidra.program.model.symbol.*; import ghidra.program.model.symbol.*;
import ghidra.util.Msg;
import ghidra.util.exception.DuplicateNameException; import ghidra.util.exception.DuplicateNameException;
import ghidra.util.exception.InvalidInputException; import ghidra.util.exception.InvalidInputException;
import ghidra.util.xml.SpecXmlUtils; import ghidra.util.xml.SpecXmlUtils;
import ghidra.xml.*;
/** /**
* *
@ -219,9 +214,9 @@ public class HighFunction extends PcodeSyntaxTree {
return super.newVarnode(sz, addr, id); return super.newVarnode(sz, addr, id);
} }
private void readHighXML(XmlPullParser parser) throws PcodeXMLException { private void decodeHigh(Decoder decoder) throws PcodeXMLException {
XmlElement el = parser.peek(); int el = decoder.openElement(ElementId.ELEM_HIGH);
String classstring = el.getAttribute("class"); String classstring = decoder.readString(AttributeId.ATTRIB_CLASS);
HighVariable var; HighVariable var;
switch (classstring.charAt(0)) { switch (classstring.charAt(0)) {
case 'o': case 'o':
@ -242,81 +237,80 @@ public class HighFunction extends PcodeSyntaxTree {
default: default:
throw new PcodeXMLException("Unknown HighVariable class string: " + classstring); throw new PcodeXMLException("Unknown HighVariable class string: " + classstring);
} }
var.restoreXml(parser); var.decode(decoder);
decoder.closeElement(el);
} }
private void readHighlistXML(XmlPullParser parser) throws PcodeXMLException { private void decodeHighlist(Decoder decoder) throws PcodeXMLException {
XmlElement el = parser.start("highlist"); int el = decoder.openElement(ElementId.ELEM_HIGHLIST);
while (parser.peek().isStart()) { while (decoder.peekElement() != 0) {
readHighXML(parser); decodeHigh(decoder);
} }
parser.end(el); decoder.closeElement(el);
} }
/* (non-Javadoc)
* @see ghidra.program.model.pcode.PcodeSyntaxTree#readXML(org.jdom.Element)
*/
@Override @Override
public void readXML(XmlPullParser parser) throws PcodeXMLException { public void decode(Decoder decoder) throws PcodeXMLException {
XmlElement start = parser.start("function"); int start = decoder.openElement(ElementId.ELEM_FUNCTION);
String name = start.getAttribute("name"); String name = decoder.readString(AttributeId.ATTRIB_NAME);
if (!func.getName().equals(name)) { if (!func.getName().equals(name)) {
throw new PcodeXMLException("Function name mismatch: " + func.getName() + " + " + name); throw new PcodeXMLException("Function name mismatch: " + func.getName() + " + " + name);
} }
while (!parser.peek().isEnd()) { for (;;) {
XmlElement subel = parser.peek(); int subel = decoder.peekElement();
if (subel.getName().equals("addr")) { if (subel == 0) {
subel = parser.start("addr"); break;
Address addr = AddressXML.readXML(subel, getAddressFactory()); }
parser.end(subel); if (subel == ElementId.ELEM_ADDR.getId()) {
Address addr = AddressXML.decode(decoder);
addr = func.getEntryPoint().getAddressSpace().getOverlayAddress(addr); addr = func.getEntryPoint().getAddressSpace().getOverlayAddress(addr);
if (!func.getEntryPoint().equals(addr)) { if (!func.getEntryPoint().equals(addr)) {
throw new PcodeXMLException("Mismatched address in function tag"); throw new PcodeXMLException("Mismatched address in function tag");
} }
} }
else if (subel.getName().equals("prototype")) { else if (subel == ElementId.ELEM_PROTOTYPE.getId()) {
proto.readPrototypeXML(parser, getDataTypeManager()); proto.decodePrototype(decoder, getDataTypeManager());
} }
else if (subel.getName().equals("localdb")) { else if (subel == ElementId.ELEM_LOCALDB.getId()) {
localSymbols.parseScopeXML(parser); localSymbols.decodeScope(decoder);
} }
else if (subel.getName().equals("ast")) { else if (subel == ElementId.ELEM_AST.getId()) {
super.readXML(parser); super.decode(decoder);
} }
else if (subel.getName().equals("highlist")) { else if (subel == ElementId.ELEM_HIGHLIST.getId()) {
readHighlistXML(parser); decodeHighlist(decoder);
} }
else if (subel.getName().equals("jumptablelist")) { else if (subel == ElementId.ELEM_JUMPTABLELIST.getId()) {
readJumpTableListXML(parser); decodeJumpTableList(decoder);
} }
else if (subel.getName().equals("override")) { else if (subel == ElementId.ELEM_OVERRIDE.getId()) {
// Do nothing with override at the moment // 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 // This must be a subscope of the local scope
// Currently this can only hold static variables of the function // Currently this can only hold static variables of the function
// which ghidra already knows about // which ghidra already knows about
parser.discardSubTree(); decoder.skipElement();
} }
else { 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 * @param decoder is the stream decoder
* @throws PcodeXMLException for any format errors * @throws PcodeXMLException for invalid encodings
*/ */
private void readJumpTableListXML(XmlPullParser parser) throws PcodeXMLException { private void decodeJumpTableList(Decoder decoder) throws PcodeXMLException {
XmlElement el = parser.start("jumptablelist"); int el = decoder.openElement(ElementId.ELEM_JUMPTABLELIST);
while (parser.peek().isStart()) { while (decoder.peekElement() != 0) {
JumpTable table = new JumpTable(func.getEntryPoint().getAddressSpace()); JumpTable table = new JumpTable(func.getEntryPoint().getAddressSpace());
table.restoreXml(parser, getAddressFactory()); table.decode(decoder);
if (!table.isEmpty()) { if (!table.isEmpty()) {
if (jumpTables == null) { if (jumpTables == null) {
jumpTables = new ArrayList<>(); jumpTables = new ArrayList<>();
@ -324,7 +318,7 @@ public class HighFunction extends PcodeSyntaxTree {
jumpTables.add(table); jumpTables.add(table);
} }
} }
parser.end(el); decoder.closeElement(el);
} }
protected Address getPCAddress(Varnode rep) { protected Address getPCAddress(Varnode rep) {
@ -495,26 +489,6 @@ public class HighFunction extends PcodeSyntaxTree {
return resBuf.toString(); 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) { public static Namespace findOverrideSpace(Function func) {
SymbolTable symtab = func.getProgram().getSymbolTable(); SymbolTable symtab = func.getProgram().getSymbolTable();
return findNamespace(symtab, func, "override"); return findNamespace(symtab, func, "override");
@ -592,29 +566,6 @@ public class HighFunction extends PcodeSyntaxTree {
return res; 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. * The decompiler treats some namespaces as equivalent to the "global" namespace.
* Return true if the given namespace is treated as equivalent. * 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.address.Address;
import ghidra.program.model.data.DataType; import ghidra.program.model.data.DataType;
import ghidra.util.Msg; 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 @Override
public void restoreXml(XmlPullParser parser) throws PcodeXMLException { public void decode(Decoder decoder) throws PcodeXMLException {
XmlElement el = parser.start("high"); // int el = decoder.openElement(ElementId.ELEM_HIGH);
long symref = SpecXmlUtils.decodeLong(el.getAttribute("symref")); long symref = 0;
String attrString = el.getAttribute("offset");
offset = -1; offset = -1;
if (attrString != null) { for (;;) {
offset = SpecXmlUtils.decodeInt(attrString); int attribId = decoder.getNextAttributeId();
if (attribId == 0) {
break;
} }
restoreInstances(parser, el); if (attribId == AttributeId.ATTRIB_OFFSET.getId()) {
offset = (int) decoder.readSignedInteger();
}
else if (attribId == AttributeId.ATTRIB_SYMREF.getId()) {
symref = decoder.readUnsignedInteger();
}
}
decodeInstances(decoder);
if (symref != 0) { if (symref != 0) {
symbol = function.getGlobalSymbolMap().getSymbol(symref); symbol = function.getGlobalSymbolMap().getSymbol(symref);
} }
@ -94,6 +99,6 @@ public class HighGlobal extends HighVariable {
} }
symbol.setHighVariable(this); 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.address.Address;
import ghidra.program.model.data.DataType; import ghidra.program.model.data.DataType;
import ghidra.util.xml.SpecXmlUtils;
import ghidra.xml.XmlElement;
import ghidra.xml.XmlPullParser;
public class HighLocal extends HighVariable { public class HighLocal extends HighVariable {
@ -53,15 +50,21 @@ public class HighLocal extends HighVariable {
} }
@Override @Override
public void restoreXml(XmlPullParser parser) throws PcodeXMLException { public void decode(Decoder decoder) throws PcodeXMLException {
XmlElement el = parser.start("high"); //int el = decoder.openElement(ElementId.ELEM_HIGH);
long symref = SpecXmlUtils.decodeLong(el.getAttribute("symref")); long symref = decoder.readUnsignedInteger(AttributeId.ATTRIB_SYMREF);
offset = -1; offset = -1;
String attrString = el.getAttribute("offset"); for (;;) {
if (attrString != null) { int attribId = decoder.getNextAttributeId();
offset = SpecXmlUtils.decodeInt(attrString); if (attribId == 0) {
break;
} }
restoreInstances(parser, el); if (attribId == AttributeId.ATTRIB_OFFSET.getId()) {
offset = (int) decoder.readUnsignedInteger();
break;
}
}
decodeInstances(decoder);
symbol = function.getLocalSymbolMap().getSymbol(symref); symbol = function.getLocalSymbolMap().getSymbol(symref);
if (symbol == null) { if (symbol == null) {
throw new PcodeXMLException("HighLocal is missing symbol"); throw new PcodeXMLException("HighLocal is missing symbol");
@ -75,7 +78,7 @@ public class HighLocal extends HighVariable {
pcaddr = symbol.getPCAddress(); pcaddr = symbol.getPCAddress();
symbol.setHighVariable(this); 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.address.Address;
import ghidra.program.model.data.DataType; 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 @Override
public void restoreXml(XmlPullParser parser) throws PcodeXMLException { public void decode(Decoder decoder) throws PcodeXMLException {
XmlElement el = parser.start("high"); // int el = decoder.openElement(ElementId.ELEM_HIGH);
long symref = SpecXmlUtils.decodeLong(el.getAttribute("symref")); long symref = 0;
offset = -1; offset = -1;
String attrString = el.getAttribute("offset"); for (;;) {
restoreInstances(parser, el); 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"; name = "UNNAMED";
pcaddr = function.getPCAddress(represent); pcaddr = function.getPCAddress(represent);
if (symref != 0) { if (symref != 0) {
offset = -1;
if (attrString != null) {
offset = SpecXmlUtils.decodeInt(attrString);
}
symbol = function.getLocalSymbolMap().getSymbol(symref); symbol = function.getLocalSymbolMap().getSymbol(symref);
if (symbol != null && offset < 0) { if (symbol != null && offset < 0) {
name = symbol.getName(); 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.address.Address;
import ghidra.program.model.data.DataType; import ghidra.program.model.data.DataType;
import ghidra.xml.XmlPullParser;
/** /**
* *
@ -55,8 +54,8 @@ public class HighParam extends HighLocal {
} }
@Override @Override
public void restoreXml(XmlPullParser parser) throws PcodeXMLException { public void decode(Decoder decoder) throws PcodeXMLException {
super.restoreXml(parser); super.decode(decoder);
HighSymbol sym = getSymbol(); HighSymbol sym = getSymbol();
slot = sym.getCategoryIndex(); slot = sym.getCategoryIndex();
} }

View file

@ -30,7 +30,6 @@ import ghidra.util.Msg;
import ghidra.util.exception.DuplicateNameException; import ghidra.util.exception.DuplicateNameException;
import ghidra.util.exception.InvalidInputException; import ghidra.util.exception.InvalidInputException;
import ghidra.util.xml.SpecXmlUtils; 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) * @see ghidra.program.model.pcode.PcodeSyntaxTree#readXML(org.jdom.Element)
*/ */
@Override @Override
public void readXML(XmlPullParser parser) throws PcodeXMLException { public void decode(Decoder decoder) throws PcodeXMLException {
XmlElement start = parser.start("parammeasures"); int start = decoder.openElement(ElementId.ELEM_PARAMMEASURES);
functionname = start.getAttribute("name"); functionname = decoder.readString(AttributeId.ATTRIB_NAME);
if (!func.getName().equals(functionname)) { if (!func.getName().equals(functionname)) {
throw new PcodeXMLException( throw new PcodeXMLException(
"Function name mismatch: " + func.getName() + " + " + functionname); "Function name mismatch: " + func.getName() + " + " + functionname);
} }
while (!parser.peek().isEnd()) { for (;;) {
XmlElement subel = parser.peek(); int subel = decoder.peekElement();
if (subel.getName().equals("addr")) { if (subel == 0) {
subel = parser.start("addr"); break;
functionaddress = AddressXML.readXML(subel, getAddressFactory()); }
parser.end(subel); if (subel == ElementId.ELEM_ADDR.getId()) {
functionaddress = AddressXML.decode(decoder);
functionaddress = functionaddress =
func.getEntryPoint().getAddressSpace().getOverlayAddress(functionaddress); func.getEntryPoint().getAddressSpace().getOverlayAddress(functionaddress);
if (!func.getEntryPoint().equals(functionaddress)) { if (!func.getEntryPoint().equals(functionaddress)) {
throw new PcodeXMLException("Mismatched address in function tag"); throw new PcodeXMLException("Mismatched address in function tag");
} }
} }
else if (subel.getName().equals("proto")) { else if (subel == ElementId.ELEM_PROTO.getId()) {
subel = parser.start("proto"); decoder.openElement();
modelname = subel.getAttribute("model"); modelname = decoder.readString(AttributeId.ATTRIB_MODEL);
String val = subel.getAttribute("extrapop"); String val = decoder.readString(AttributeId.ATTRIB_EXTRAPOP);
if (val.equals("unknown")) { if (val.equals("unknown")) {
protoextrapop = PrototypeModel.UNKNOWN_EXTRAPOP; protoextrapop = PrototypeModel.UNKNOWN_EXTRAPOP;
} }
else { else {
protoextrapop = SpecXmlUtils.decodeInt(val); protoextrapop = SpecXmlUtils.decodeInt(val);
} }
parser.end(subel); decoder.closeElement(subel);
} }
else if (subel.getName().equals("input")) { else if (subel == ElementId.ELEM_INPUT.getId()) {
parseParamMeasureXML(parser, inputlist, "input"); decodeParamMeasure(decoder, inputlist);
} }
else if (subel.getName().equals("output")) { else if (subel == ElementId.ELEM_OUTPUT.getId()) {
parseParamMeasureXML(parser, outputlist, "output"); decodeParamMeasure(decoder, outputlist);
} }
else { 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 * Decode the inputs or outputs list for this function from a stream.
* @param parser is the XML parser * @param decoder is the stream decoder
* @param pmlist is populated with the resulting list * @param pmlist is populated with the resulting list
* @param tag is the name of the tag * @throws PcodeXMLException for invalid encodings
* @throws PcodeXMLException for improperly formed XML
*/ */
private void parseParamMeasureXML(XmlPullParser parser, List<ParamMeasure> pmlist, String tag) private void decodeParamMeasure(Decoder decoder, List<ParamMeasure> pmlist)
throws PcodeXMLException { throws PcodeXMLException {
XmlElement el = parser.start(tag); int el = decoder.openElement();
ParamMeasure pm = new ParamMeasure(); ParamMeasure pm = new ParamMeasure();
pm.readXml(parser, this); pm.decode(decoder, this);
if (!pm.isEmpty()) { if (!pm.isEmpty()) {
pmlist.add(pm); pmlist.add(pm);
} }
parser.end(el); decoder.closeElement(el);
} }
public static ErrorHandler getErrorHandler(final Object errOriginator, 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. * 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 * @param srctype function signature source
*/ */
public void storeReturnToDatabase(boolean storeDataTypes, SourceType srctype) { public void storeReturnToDatabase(boolean storeDataTypes, SourceType srctype) {
PcodeDataTypeManager dtManage = getDataTypeManager();
try { try {
//TODO: Currently, only storing one output, so looking for the best to report. When possible, change this to report all //TODO: Currently, only storing one output, so looking for the best to report. When possible, change this to report all
int best_index = 0; int best_index = 0;
@ -285,7 +260,6 @@ public class HighParamID extends PcodeSyntaxTree {
* @param srctype function signature source * @param srctype function signature source
*/ */
public void storeParametersToDatabase(boolean storeDataTypes, SourceType srctype) { public void storeParametersToDatabase(boolean storeDataTypes, SourceType srctype) {
PcodeDataTypeManager dtManage = getDataTypeManager();
try { try {
List<Variable> params = new ArrayList<>(); List<Variable> params = new ArrayList<>();
for (ParamMeasure pm : inputlist) { for (ParamMeasure pm : inputlist) {

View file

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

View file

@ -18,9 +18,6 @@ package ghidra.program.model.pcode;
import java.util.ArrayList; import java.util.ArrayList;
import ghidra.program.model.data.DataType; 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() { protected void setHighOnInstances() {
for (Varnode instance : instances) { for (Varnode instance : instances) {
if (instance instanceof VarnodeAST) { 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. * The "representative" Varnode is also populated.
* @param parser is the XML stream * @param decoder is the stream decoder
* @param el is the root {@code <high>} tag * @throws PcodeXMLException for invalid encodings
* @throws PcodeXMLException if the XML is not valid
*/ */
protected void restoreInstances(XmlPullParser parser, XmlElement el) protected void decodeInstances(Decoder decoder) throws PcodeXMLException {
throws PcodeXMLException { int repref = (int) decoder.readUnsignedInteger(AttributeId.ATTRIB_REPREF);
int repref = SpecXmlUtils.decodeInt(el.getAttribute("repref"));
Varnode rep = function.getRef(repref); Varnode rep = function.getRef(repref);
if (rep == null) { if (rep == null) {
throw new PcodeXMLException("Undefined varnode reference"); throw new PcodeXMLException("Undefined varnode reference");
@ -157,17 +152,15 @@ public abstract class HighVariable {
type = null; type = null;
ArrayList<Varnode> vnlist = new ArrayList<Varnode>(); ArrayList<Varnode> vnlist = new ArrayList<>();
if (parser.peek().isStart()) { type = function.getDataTypeManager().decodeDataType(decoder);
type = function.getDataTypeManager().readXMLDataType(parser);
}
if (type == null) { for (;;) {
throw new PcodeXMLException("Missing <type> for HighVariable"); int subel = decoder.peekElement();
if (subel == 0) {
break;
} }
Varnode vn = Varnode.decode(decoder, function);
while (parser.peek().isStart()) {
Varnode vn = Varnode.readXML(parser, function);
vnlist.add(vn); vnlist.add(vn);
} }
Varnode[] vnarray = new Varnode[vnlist.size()]; Varnode[] vnarray = new Varnode[vnlist.size()];
@ -193,9 +186,9 @@ public abstract class HighVariable {
} }
/** /**
* Restore this HighVariable from a {@code <high>} XML tag * Decode this HighVariable from a {@code <high>} element in the stream
* @param parser is the XML stream * @param decoder is the stream decoder
* @throws PcodeXMLException if the XML is not valid * @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.listing.Program;
import ghidra.program.model.symbol.*; import ghidra.program.model.symbol.*;
import ghidra.util.exception.InvalidInputException; 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 * JumpTable found as part of the decompilation of a function
@ -78,14 +75,12 @@ public class JumpTable {
return num; return num;
} }
public void restoreXml(XmlPullParser parser, AddressFactory addrFactory) { public void decode(Decoder decoder) throws PcodeXMLException {
XmlElement el = parser.start("loadtable"); int el = decoder.openElement(ElementId.ELEM_LOADTABLE);
size = SpecXmlUtils.decodeInt(el.getAttribute("size")); size = (int) decoder.readSignedInteger(AttributeId.ATTRIB_SIZE);
num = SpecXmlUtils.decodeInt(el.getAttribute("num")); num = (int) decoder.readSignedInteger(AttributeId.ATTRIB_NUM);
XmlElement subel = parser.start("addr"); addr = translateOverlayAddress(AddressXML.decode(decoder));
addr = translateOverlayAddress(AddressXML.readXML(subel, addrFactory)); decoder.closeElement(el);
parser.end(subel);
parser.end(el);
} }
} }
@ -159,47 +154,51 @@ public class JumpTable {
} }
/** /**
* Create a JumpTable object by parsing the XML elements * Decode a JumpTable object from the stream.
* @param parser is the XML parser * @param decoder is the stream decoder
* @param addrFactory is used to look-up address spaces * @throws PcodeXMLException for invalid encodings
* @throws PcodeXMLException for improperly formed XML
*/ */
public void restoreXml(XmlPullParser parser, AddressFactory addrFactory) public void decode(Decoder decoder) throws PcodeXMLException {
throws PcodeXMLException { int el = decoder.openElement(ElementId.ELEM_JUMPTABLE);
XmlElement el = parser.start("jumptable"); if (decoder.peekElement() == 0) { // Empty jumptable
try { decoder.closeElement(el);
return;
}
ArrayList<Address> aTable = new ArrayList<>(); ArrayList<Address> aTable = new ArrayList<>();
ArrayList<Integer> lTable = new ArrayList<>(); ArrayList<Integer> lTable = new ArrayList<>();
ArrayList<LoadTable> ldTable = new ArrayList<>(); ArrayList<LoadTable> ldTable = new ArrayList<>();
if (!parser.peek().isStart()) { // Empty jumptable Address switchAddr = translateOverlayAddress(AddressXML.decode(decoder));
return;
for (;;) {
int subel = decoder.peekElement();
if (subel == 0) {
break;
} }
if (subel == ElementId.ELEM_DEST.getId()) {
XmlElement addrel = parser.start("addr"); decoder.openElement();
Address switchAddr = translateOverlayAddress(AddressXML.readXML(addrel, addrFactory)); Address caseAddr = translateOverlayAddress(AddressXML.decodeFromAttributes(decoder));
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); aTable.add(caseAddr);
String slabel = subel.getAttribute("label"); decoder.rewindAttributes();
if (slabel != null) { for (;;) {
int label = SpecXmlUtils.decodeInt(slabel); int attribId = decoder.getNextAttributeId();
if (attribId == 0) {
break;
}
if (attribId == AttributeId.ATTRIB_LABEL.getId()) {
int label = (int) decoder.readUnsignedInteger();
lTable.add(label); lTable.add(label);
} }
parser.end(subel);
} }
else if (parser.peek().getName().equals("loadtable")) { decoder.closeElement(subel);
}
else if (subel == ElementId.ELEM_LOADTABLE.getId()) {
LoadTable loadtable = new LoadTable(); LoadTable loadtable = new LoadTable();
loadtable.restoreXml(parser, addrFactory); loadtable.decode(decoder);
ldTable.add(loadtable); ldTable.add(loadtable);
} }
else { else {
parser.discardSubTree(); decoder.skipElement();
} }
} }
@ -210,10 +209,7 @@ public class JumpTable {
lTable.toArray(labelTable); lTable.toArray(labelTable);
loadTable = new LoadTable[ldTable.size()]; loadTable = new LoadTable[ldTable.size()];
ldTable.toArray(loadTable); ldTable.toArray(loadTable);
} decoder.closeElement(el);
finally {
parser.end(el);
}
} }
public void buildXml(StringBuilder buf) { public void buildXml(StringBuilder buf) {

View file

@ -24,8 +24,6 @@ import ghidra.program.model.listing.*;
import ghidra.program.model.symbol.*; import ghidra.program.model.symbol.*;
import ghidra.util.SystemUtilities; import ghidra.util.SystemUtilities;
import ghidra.util.xml.SpecXmlUtils; 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 * 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 * Decode a &lt;mapsym&gt; element from the stream.
* @param parser is the XML parser * @param decoder is the stream decoder
* @return the reconstructed HighSymbol * @return the reconstructed HighSymbol
* @throws PcodeXMLException for problems sub tags * @throws PcodeXMLException for problems sub tags
*/ */
private HighSymbol parseSymbolXML(XmlPullParser parser) throws PcodeXMLException { private HighSymbol decodeSymbol(Decoder decoder) throws PcodeXMLException {
HighSymbol res = HighSymbol.restoreMapSymXML(parser, false, func); HighSymbol res = HighSymbol.decodeMapSym(decoder, false, func);
insertSymbol(res); insertSymbol(res);
return 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 * @param decoder is the stream decoder
* @throws PcodeXMLException for problems parsing individual tags * @throws PcodeXMLException for invalid encodings
*/ */
public void parseScopeXML(XmlPullParser parser) throws PcodeXMLException { public void decodeScope(Decoder decoder) throws PcodeXMLException {
XmlElement el = parser.start("localdb"); int el = decoder.openElement(ElementId.ELEM_LOCALDB);
spacename = el.getAttribute("main"); spacename = decoder.readString(AttributeId.ATTRIB_MAIN);
XmlElement scopeel = parser.start("scope"); int scopeel = decoder.openElement(ElementId.ELEM_SCOPE);
parser.discardSubTree(); // This is the parent scope path decoder.skipElement(); // This is the parent scope path
parser.discardSubTree(); // This is the address range decoder.skipElement(); // This is the address range
addrMappedSymbols.clear(); // Clear out any old map addrMappedSymbols.clear(); // Clear out any old map
symbolMap.clear(); // Clear out any old map symbolMap.clear(); // Clear out any old map
XmlElement nextEl = parser.peek(); int nextEl = decoder.peekElement();
if (nextEl != null && nextEl.isStart() && "symbollist".equals(nextEl.getName())) { if (nextEl == ElementId.ELEM_SYMBOLLIST.getId()) {
parseSymbolList(parser); decodeSymbolList(decoder);
} }
parser.end(scopeel); decoder.closeElement(scopeel);
parser.end(el); decoder.closeElement(el);
} }
private static final Comparator<HighSymbol> PARAM_SYMBOL_SLOT_COMPARATOR = new Comparator<>() { 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. * Add mapped symbols to this LocalVariableMap, by decoding the &lt;symbollist&gt; and &lt;mapsym&gt; elements
* @param parser is the XML parser * @param decoder is the stream decoder
* @throws PcodeXMLException for problems parsing a tag * @throws PcodeXMLException for invalid encodings
*/ */
public void parseSymbolList(XmlPullParser parser) throws PcodeXMLException { public void decodeSymbolList(Decoder decoder) throws PcodeXMLException {
XmlElement el = parser.start("symbollist"); int el = decoder.openElement(ElementId.ELEM_SYMBOLLIST);
ArrayList<HighSymbol> parms = new ArrayList<>(); ArrayList<HighSymbol> parms = new ArrayList<>();
while (parser.peek().isStart()) { while (decoder.peekElement() != 0) {
HighSymbol sym = parseSymbolXML(parser); HighSymbol sym = decodeSymbol(decoder);
if (sym.isParameter()) { if (sym.isParameter()) {
parms.add(sym); parms.add(sym);
} }
@ -321,7 +319,7 @@ public class LocalSymbolMap {
paramSymbols = new HighSymbol[parms.size()]; paramSymbols = new HighSymbol[parms.size()];
parms.toArray(paramSymbols); parms.toArray(paramSymbols);
Arrays.sort(paramSymbols, PARAM_SYMBOL_SLOT_COMPARATOR); 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.Data;
import ghidra.program.model.listing.VariableStorage; import ghidra.program.model.listing.VariableStorage;
import ghidra.xml.XmlPullParser;
/** /**
* A normal address based HighSymbol mapping with an associated Data object * A normal address based HighSymbol mapping with an associated Data object
@ -52,8 +51,8 @@ public class MappedDataEntry extends MappedEntry {
} }
@Override @Override
public void restoreXML(XmlPullParser parser) throws PcodeXMLException { public void decode(Decoder decoder) throws PcodeXMLException {
super.restoreXML(parser); super.decode(decoder);
data = symbol.getProgram().getListing().getDataAt(storage.getMinAddress()); data = symbol.getProgram().getListing().getDataAt(storage.getMinAddress());
} }

View file

@ -15,7 +15,8 @@
*/ */
package ghidra.program.model.pcode; 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.data.AbstractFloatDataType;
import ghidra.program.model.listing.Program; import ghidra.program.model.listing.Program;
import ghidra.program.model.listing.VariableStorage; 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.Reference;
import ghidra.program.model.symbol.ReferenceIterator; import ghidra.program.model.symbol.ReferenceIterator;
import ghidra.util.exception.InvalidInputException; 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 * 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 @Override
public void restoreXML(XmlPullParser parser) throws PcodeXMLException { public void decode(Decoder decoder) throws PcodeXMLException {
HighFunction function = symbol.function; HighFunction function = symbol.function;
Program program = function.getFunction().getProgram(); 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(); int sz = symbol.type.getLength();
if (sz == 0) { if (sz == 0) {
throw new PcodeXMLException( throw new PcodeXMLException(
"Invalid symbol 0-sized data-type: " + symbol.type.getName()); "Invalid symbol 0-sized data-type: " + symbol.type.getName());
} }
try { try {
Address varAddr = AddressXML.readXML(addrel, addrFactory); Address varAddr = AddressXML.decodeFromAttributes(decoder);
AddressSpace spc = varAddr.getAddressSpace(); AddressSpace spc = varAddr.getAddressSpace();
if ((spc == null) || (spc.getType() != AddressSpace.TYPE_VARIABLE)) { if ((spc == null) || (spc.getType() != AddressSpace.TYPE_VARIABLE)) {
storage = new VariableStorage(program, varAddr, sz); storage = new VariableStorage(program, varAddr, sz);
} }
else { else {
storage = function.readXMLVarnodePieces(addrel, varAddr); decoder.rewindAttributes();
storage = function.decodeVarnodePieces(decoder, varAddr);
} }
} }
catch (InvalidInputException e) { catch (InvalidInputException e) {
throw new PcodeXMLException("Invalid storage: " + e.getMessage()); throw new PcodeXMLException("Invalid storage: " + e.getMessage());
} }
parser.end(addrel); decoder.closeElement(addrel);
parseRangeList(parser); decodeRangeList(decoder);
} }
@Override @Override

View file

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

View file

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

View file

@ -21,8 +21,7 @@ import java.util.Iterator;
import ghidra.program.model.address.*; import ghidra.program.model.address.*;
import ghidra.util.xml.SpecXmlUtils; import ghidra.util.xml.SpecXmlUtils;
import ghidra.xml.XmlElement;
import ghidra.xml.XmlPullParser;
/** /**
* *
* *
@ -35,7 +34,7 @@ public class PcodeBlockBasic extends PcodeBlock {
PcodeBlockBasic() { PcodeBlockBasic() {
super(); super();
blocktype = PcodeBlock.BASIC; blocktype = PcodeBlock.BASIC;
oplist = new ListLinked<PcodeOp>(); oplist = new ListLinked<>();
cover = new AddressSet(); cover = new AddressSet();
} }
@ -64,9 +63,9 @@ public class PcodeBlockBasic extends PcodeBlock {
* @param op is the new PcodeOp to insert * @param op is the new PcodeOp to insert
*/ */
protected void insertBefore(Iterator<PcodeOp> iter, PcodeOp op) { protected void insertBefore(Iterator<PcodeOp> iter, PcodeOp op) {
PcodeOpAST opast = (PcodeOpAST)op; PcodeOpAST opast = (PcodeOpAST) op;
opast.setParent(this); opast.setParent(this);
Iterator<PcodeOp> newiter = oplist.insertBefore(iter,op); Iterator<PcodeOp> newiter = oplist.insertBefore(iter, op);
opast.setBasicIter(newiter); opast.setBasicIter(newiter);
} }
@ -76,9 +75,9 @@ public class PcodeBlockBasic extends PcodeBlock {
* @param op is the new PcodeOp to insert * @param op is the new PcodeOp to insert
*/ */
protected void insertAfter(Iterator<PcodeOp> iter, PcodeOp op) { protected void insertAfter(Iterator<PcodeOp> iter, PcodeOp op) {
PcodeOpAST opast = (PcodeOpAST)op; PcodeOpAST opast = (PcodeOpAST) op;
opast.setParent(this); opast.setParent(this);
Iterator<PcodeOp> newiter = oplist.insertAfter(iter,opast); Iterator<PcodeOp> newiter = oplist.insertAfter(iter, opast);
opast.setBasicIter(newiter); opast.setBasicIter(newiter);
} }
@ -87,7 +86,7 @@ public class PcodeBlockBasic extends PcodeBlock {
* @param op is the PcodeOp to insert * @param op is the PcodeOp to insert
*/ */
protected void insertEnd(PcodeOp op) { protected void insertEnd(PcodeOp op) {
PcodeOpAST opast = (PcodeOpAST)op; PcodeOpAST opast = (PcodeOpAST) op;
opast.setParent(this); opast.setParent(this);
Iterator<PcodeOp> newiter = oplist.add(opast); Iterator<PcodeOp> newiter = oplist.add(opast);
opast.setBasicIter(newiter); opast.setBasicIter(newiter);
@ -98,7 +97,7 @@ public class PcodeBlockBasic extends PcodeBlock {
* @param op is the PcodeOp to remove * @param op is the PcodeOp to remove
*/ */
protected void remove(PcodeOp op) { protected void remove(PcodeOp op) {
PcodeOpAST opast = (PcodeOpAST)op; PcodeOpAST opast = (PcodeOpAST) op;
opast.setParent(null); opast.setParent(null);
oplist.remove(op.getBasicIter()); oplist.remove(op.getBasicIter());
} }
@ -129,21 +128,23 @@ public class PcodeBlockBasic extends PcodeBlock {
} }
@Override @Override
public void restoreXmlBody(XmlPullParser parser, BlockMap resolver) throws PcodeXMLException { public void decodeBody(Decoder decoder, BlockMap resolver) throws PcodeXMLException {
AddressFactory addressFactory = resolver.getAddressFactory(); int rangelistel = decoder.openElement(ElementId.ELEM_RANGELIST);
XmlElement rangelistel = parser.start("rangelist"); for (;;) {
while (parser.peek().isStart()) { int rangeel = decoder.peekElement();
XmlElement rangeel = parser.start("range"); if (rangeel != ElementId.ELEM_RANGE.getId()) {
String spc = rangeel.getAttribute("space"); break;
long offset = SpecXmlUtils.decodeLong(rangeel.getAttribute("first")); }
AddressSpace addressSpace = addressFactory.getAddressSpace(spc); decoder.openElement();
AddressSpace addressSpace = decoder.readSpace(AttributeId.ATTRIB_SPACE);
long offset = decoder.readUnsignedInteger(AttributeId.ATTRIB_FIRST);
Address start = addressSpace.getAddress(offset); Address start = addressSpace.getAddress(offset);
offset = SpecXmlUtils.decodeLong(rangeel.getAttribute("last")); offset = decoder.readUnsignedInteger(AttributeId.ATTRIB_LAST);
Address stop = addressSpace.getAddress(offset); Address stop = addressSpace.getAddress(offset);
cover.addRange(start, stop); 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.lang.DecompilerLanguage;
import ghidra.program.model.listing.Program; import ghidra.program.model.listing.Program;
import ghidra.util.xml.SpecXmlUtils; 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 * a corresponding data-type exists, this data-type is returned. Otherwise the first
* built-in data-type with a matching name is returned * built-in data-type with a matching name is returned
* @param nm name of data-type * @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 * @return the data-type object or null if no matching data-type exists
*/ */
public DataType findBaseType(String nm, String idstr) { public DataType findBaseType(String nm, long id) {
long id = 0; if (id != 0) {
if (idstr != null) {
id = SpecXmlUtils.decodeLong(idstr);
if (id > 0) { if (id > 0) {
DataType dt = progDataTypes.getDataType(id); DataType dt = progDataTypes.getDataType(id);
if (dt != null) { if (dt != null) {
@ -156,50 +152,62 @@ public class PcodeDataTypeManager {
} }
/** /**
* Get the data type that corresponds to the given XML element. * Decode a data-type from the stream
* @param parser the xml parser * @param decoder is the stream decoder
* @return the read data type * @return the decoded data-type object
* @throws PcodeXMLException if the data type could be resolved from the * @throws PcodeXMLException for invalid encodings
* element
*/ */
public DataType readXMLDataType(XmlPullParser parser) throws PcodeXMLException { public DataType decodeDataType(Decoder decoder) throws PcodeXMLException {
XmlElement el = parser.start("type", "void", "typeref", "def"); int el = decoder.openElement();
try { if (el == ElementId.ELEM_VOID.getId()) {
if (el == null) { decoder.closeElement(el);
throw new PcodeXMLException("Bad <type> tag");
}
if (el.getName().equals("void")) {
return voidDt; return voidDt;
} }
if (el.getName().equals("typeref")) { String name = "";
return findBaseType(el.getAttribute("name"), el.getAttribute("id")); long id = 0;
for (;;) {
int attribId = decoder.getNextAttributeId();
if (attribId == 0) {
break;
} }
if (el.getName().equals("def")) { if (attribId == AttributeId.ATTRIB_NAME.getId()) {
String nameStr = el.getAttribute("name"); name = decoder.readString();
String idStr = el.getAttribute("id");
parser.discardSubTree(); // Get rid of unused <typeref>
return findBaseType(nameStr, idStr);
} }
String name = el.getAttribute("name"); 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 (name.length() != 0) { if (name.length() != 0) {
return findBaseType(name, el.getAttribute("id")); decoder.closeElementSkipping(el);
return findBaseType(name, id);
} }
String meta = el.getAttribute("metatype"); String meta = decoder.readString(AttributeId.ATTRIB_METATYPE);
DataType restype = null; DataType restype = null;
if (meta.equals("ptr")) { if (meta.equals("ptr")) {
int size = SpecXmlUtils.decodeInt(el.getAttribute("size")); int size = (int) decoder.readSignedInteger(AttributeId.ATTRIB_SIZE);
if (parser.peek().isStart()) { if (decoder.peekElement() != 0) {
DataType dt = readXMLDataType(parser); DataType dt = decodeDataType(decoder);
boolean useDefaultSize = (size == dataOrganization.getPointerSize() || boolean useDefaultSize = (size == dataOrganization.getPointerSize() ||
size > PointerDataType.MAX_POINTER_SIZE_BYTES); size > PointerDataType.MAX_POINTER_SIZE_BYTES);
restype = new PointerDataType(dt, useDefaultSize ? -1 : size, progDataTypes); restype = new PointerDataType(dt, useDefaultSize ? -1 : size, progDataTypes);
} }
} }
else if (meta.equals("array")) { else if (meta.equals("array")) {
int arrsize = SpecXmlUtils.decodeInt(el.getAttribute("arraysize")); int arrsize = (int) decoder.readSignedInteger(AttributeId.ATTRIB_ARRAYSIZE);
if (parser.peek().isStart()) { if (decoder.peekElement() != 0) {
DataType dt = readXMLDataType(parser); DataType dt = decodeDataType(decoder);
if (dt == null || dt.getLength() == 0) { if (dt == null || dt.getLength() == 0) {
dt = DataType.DEFAULT; dt = DataType.DEFAULT;
} }
@ -207,47 +215,44 @@ public class PcodeDataTypeManager {
} }
} }
else if (meta.equals("spacebase")) { // Typically the type of "the whole stack" else if (meta.equals("spacebase")) { // Typically the type of "the whole stack"
parser.discardSubTree(); // get rid of unused "addr" element decoder.closeElementSkipping(el); // get rid of unused "addr" element
return voidDt; return voidDt;
} }
else if (meta.equals("struct")) { else if (meta.equals("struct")) {
// we now can reach here with the decompiler inventing structures, apparently // We reach here if the decompiler invents a structure, apparently
// this is a band-aid so that we don't blow up // this is a band-aid so that we don't blow up
// just make an undefined data type of the appropriate size // just make an undefined data type of the appropriate size
int size = SpecXmlUtils.decodeInt(el.getAttribute("size")); int size = (int) decoder.readSignedInteger(AttributeId.ATTRIB_SIZE);
decoder.closeElementSkipping(el);
return Undefined.getUndefinedDataType(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")) { else if (meta.equals("int")) {
int size = SpecXmlUtils.decodeInt(el.getAttribute("size")); int size = (int) decoder.readSignedInteger(AttributeId.ATTRIB_SIZE);
decoder.closeElement(el);
return AbstractIntegerDataType.getSignedDataType(size, progDataTypes); return AbstractIntegerDataType.getSignedDataType(size, progDataTypes);
} }
else if (meta.equals("uint")) { else if (meta.equals("uint")) {
int size = SpecXmlUtils.decodeInt(el.getAttribute("size")); int size = (int) decoder.readSignedInteger(AttributeId.ATTRIB_SIZE);
decoder.closeElement(el);
return AbstractIntegerDataType.getUnsignedDataType(size, progDataTypes); return AbstractIntegerDataType.getUnsignedDataType(size, progDataTypes);
} }
else if (meta.equals("float")) { else if (meta.equals("float")) {
int size = SpecXmlUtils.decodeInt(el.getAttribute("size")); int size = (int) decoder.readSignedInteger(AttributeId.ATTRIB_SIZE);
decoder.closeElement(el);
return AbstractFloatDataType.getFloatDataType(size, progDataTypes); return AbstractFloatDataType.getFloatDataType(size, progDataTypes);
} }
else { // We typically reach here if the decompiler invents a new type else { // We typically reach here if the decompiler invents a new type
// probably an unknown with a non-standard size // probably an unknown with a non-standard size
int size = SpecXmlUtils.decodeInt(el.getAttribute("size")); int size = (int) decoder.readSignedInteger(AttributeId.ATTRIB_SIZE);
decoder.closeElement(el);
return Undefined.getUndefinedDataType(size).clone(progDataTypes); return Undefined.getUndefinedDataType(size).clone(progDataTypes);
} }
if (restype == null) { if (restype == null) {
throw new PcodeXMLException("Unable to resolve DataType"); throw new PcodeXMLException("Unable to resolve DataType");
} }
decoder.closeElementSkipping(el);
return restype; return restype;
} }
finally {
parser.discardSubTree(el);
// parser.end(el);
}
}
/** /**
* Get the inner data-type being referred to by an offset from a relative/shifted pointer. * Get the inner data-type being referred to by an offset from a relative/shifted pointer.

View file

@ -23,7 +23,7 @@ import ghidra.program.model.data.DataType;
import ghidra.program.model.lang.UnknownInstructionException; import ghidra.program.model.lang.UnknownInstructionException;
import ghidra.program.model.listing.VariableStorage; import ghidra.program.model.listing.VariableStorage;
import ghidra.util.exception.InvalidInputException; import ghidra.util.exception.InvalidInputException;
import ghidra.xml.XmlElement;
/** /**
* *
* *
@ -49,24 +49,46 @@ public interface PcodeFactory {
* *
* @return a new varnode * @return a new varnode
*/ */
public Varnode newVarnode(int sz,Address addr); 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 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 VariableStorage buildStorage(Varnode vn) throws InvalidInputException; public VariableStorage buildStorage(Varnode vn) throws InvalidInputException;
public Varnode getRef(int refid); public Varnode getRef(int refid);
public PcodeOp getOpRef(int refid); public PcodeOp getOpRef(int refid);
public HighSymbol getSymbol(long symbolId); public HighSymbol getSymbol(long symbolId);
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) 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; throws UnknownInstructionException;
} }

View file

@ -20,8 +20,6 @@ import java.util.*;
import ghidra.program.model.address.*; import ghidra.program.model.address.*;
import ghidra.program.model.lang.UnknownInstructionException; import ghidra.program.model.lang.UnknownInstructionException;
import ghidra.util.xml.SpecXmlUtils; import ghidra.util.xml.SpecXmlUtils;
import ghidra.xml.XmlElement;
import ghidra.xml.XmlPullParser;
/** /**
* *
@ -418,7 +416,7 @@ public class PcodeOp {
output = vn; output = vn;
} }
public void buildXML(StringBuilder resBuf,AddressFactory addrFactory) { public void buildXML(StringBuilder resBuf, AddressFactory addrFactory) {
resBuf.append("<op"); resBuf.append("<op");
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "code", opcode); SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "code", opcode);
resBuf.append('>'); 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 * @param pfact factory used to create p-code correctly
* *
* @return new PcodeOp * @return new PcodeOp
* @throws PcodeXMLException if XML layout is incorrect * @throws PcodeXMLException if encodings are invalid
*/ */
public static PcodeOp readXML(XmlPullParser parser, PcodeFactory pfact) public static PcodeOp decode(Decoder decoder, PcodeFactory pfact) throws PcodeXMLException {
throws PcodeXMLException { int el = decoder.openElement(ElementId.ELEM_OP);
XmlElement el = parser.start("op"); int opc = (int) decoder.readSignedInteger(AttributeId.ATTRIB_CODE);
int opc = SpecXmlUtils.decodeInt(el.getAttribute("code")); SequenceNumber seqnum = SequenceNumber.decode(decoder);
if (!parser.peek().isStart()) { Varnode output = Varnode.decode(decoder, pfact);
throw new PcodeXMLException("Missing <seqnum> in PcodeOp"); ArrayList<Varnode> inputlist = new ArrayList<>();
for (;;) {
int subel = decoder.peekElement();
if (subel == 0) {
break;
} }
SequenceNumber seqnum = SequenceNumber.readXML(parser, pfact.getAddressFactory()); Varnode vn = Varnode.decode(decoder, pfact);
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);
inputlist.add(vn); inputlist.add(vn);
} }
PcodeOp res; PcodeOp res;
@ -478,7 +473,7 @@ public class PcodeOp {
catch (UnknownInstructionException e) { catch (UnknownInstructionException e) {
throw new PcodeXMLException("Bad opcode: " + e.getMessage(), e); throw new PcodeXMLException("Bad opcode: " + e.getMessage(), e);
} }
parser.end(el); decoder.closeElement(el);
return res; return res;
} }
@ -522,7 +517,7 @@ public class PcodeOp {
* Generate a lookup table that maps pcode mnemonic strings to pcode operation codes. * Generate a lookup table that maps pcode mnemonic strings to pcode operation codes.
*/ */
private static void generateOpcodeTable() { private static void generateOpcodeTable() {
opcodeTable = new Hashtable<String, Integer>(); opcodeTable = new Hashtable<>();
for (int i = 0; i < PCODE_MAX; i++) { for (int i = 0; i < PCODE_MAX; i++) {
opcodeTable.put(getMnemonic(i), 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.lang.UnknownInstructionException;
import ghidra.program.model.listing.VariableStorage; import ghidra.program.model.listing.VariableStorage;
import ghidra.util.exception.InvalidInputException; 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); 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 @Override
public VariableStorage readXMLVarnodePieces(XmlElement el, Address addr) public VariableStorage decodeVarnodePieces(Decoder decoder, Address addr)
throws PcodeXMLException, InvalidInputException { throws PcodeXMLException, InvalidInputException {
ArrayList<Varnode> list = new ArrayList<>(); ArrayList<Varnode> list = new ArrayList<>();
int index = 1; for (;;) {
String nextPiece = "piece" + index; int attribId = decoder.getNextAttributeId();
while (el.hasAttribute(nextPiece)) { if (attribId == 0) {
String pieceStr = el.getAttribute(nextPiece); break;
list.add(getVarnodePiece(pieceStr, addrFactory)); }
nextPiece = "piece" + ++index; 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()]; Varnode[] pieces = new Varnode[list.size()];
list.toArray(pieces); list.toArray(pieces);
@ -526,23 +520,30 @@ public class PcodeSyntaxTree implements PcodeFactory {
return op; return op;
} }
private void readVarnodeXML(XmlPullParser parser) throws PcodeXMLException { private void decodeVarnode(Decoder decoder) throws PcodeXMLException {
XmlElement el = parser.start("varnodes"); int el = decoder.openElement(ElementId.ELEM_VARNODES);
while (parser.peek().isStart()) { for (;;) {
Varnode.readXML(parser, this); int subId = decoder.peekElement();
if (subId == 0) {
break;
} }
parser.end(el); Varnode.decode(decoder, this);
}
decoder.closeElement(el);
} }
private void readBasicBlockXML(XmlPullParser parser, BlockMap resolver) private void decodeBasicBlock(Decoder decoder, BlockMap resolver) throws PcodeXMLException {
throws PcodeXMLException { int el = decoder.openElement(ElementId.ELEM_BLOCK);
XmlElement el = parser.start("block");
int order = 0; int order = 0;
PcodeBlockBasic bl = new PcodeBlockBasic(); PcodeBlockBasic bl = new PcodeBlockBasic();
bl.restoreXmlHeader(el); bl.decodeHeader(decoder);
bl.restoreXmlBody(parser, resolver); bl.decodeBody(decoder, resolver);
while (parser.peek().isStart()) { for (;;) {
PcodeOp op = PcodeOp.readXML(parser, this); int subel = decoder.peekElement();
if (subel == 0) {
break;
}
PcodeOp op = PcodeOp.decode(decoder, this);
op.setOrder(order); op.setOrder(order);
order += 1; order += 1;
bl.insertEnd(op); bl.insertEnd(op);
@ -552,37 +553,44 @@ public class PcodeSyntaxTree implements PcodeFactory {
bblocks.add(null); bblocks.add(null);
} }
bblocks.set(index, bl); bblocks.set(index, bl);
parser.end(el); decoder.closeElement(el);
} }
private void readBlockEdgeXML(XmlPullParser parser) throws PcodeXMLException { private void decodeBlockEdge(Decoder decoder) throws PcodeXMLException {
XmlElement el = parser.start("blockedge"); int el = decoder.openElement(ElementId.ELEM_BLOCKEDGE);
int blockInd = SpecXmlUtils.decodeInt(el.getAttribute("index")); int blockInd = (int) decoder.readSignedInteger(AttributeId.ATTRIB_INDEX);
PcodeBlockBasic curBlock = bblocks.get(blockInd); PcodeBlockBasic curBlock = bblocks.get(blockInd);
while (parser.peek().isStart()) { for (;;) {
curBlock.restoreNextInEdge(parser, bblocks); int subel = decoder.peekElement();
if (subel == 0) {
break;
} }
parser.end(el); curBlock.decodeNextInEdge(decoder, bblocks);
}
decoder.closeElement(el);
} }
public void readXML(XmlPullParser parser) throws PcodeXMLException { public void decode(Decoder decoder) throws PcodeXMLException {
XmlElement el = parser.start("ast"); int el = decoder.openElement(ElementId.ELEM_AST);
if (!vbank.isEmpty()) { if (!vbank.isEmpty()) {
clear(); clear();
} }
readVarnodeXML(parser); decodeVarnode(decoder);
buildVarnodeRefs(); // Build the HashMap buildVarnodeRefs(); // Build the HashMap
BlockMap blockMap = new BlockMap(addrFactory); BlockMap blockMap = new BlockMap(addrFactory);
while (parser.peek().isStart()) { for (;;) {
XmlElement subel = parser.peek(); int subel = decoder.peekElement();
if (subel.getName().equals("block")) { if (subel == 0) {
readBasicBlockXML(parser, blockMap); // Read a basic block and all its PcodeOps break;
}
else if (subel == ElementId.ELEM_BLOCK.getId()) {
decodeBasicBlock(decoder, blockMap); // Read a basic block and all its PcodeOps
} }
else { else {
readBlockEdgeXML(parser); decodeBlockEdge(decoder);
} }
} }
parser.end(el); decoder.closeElement(el);
} }
} }

View file

@ -15,9 +15,9 @@
*/ */
package ghidra.program.model.pcode; package ghidra.program.model.pcode;
import ghidra.program.model.address.*; import ghidra.program.model.address.Address;
import ghidra.util.xml.*; import ghidra.program.model.address.AddressSpace;
import ghidra.xml.*; import ghidra.util.xml.SpecXmlUtils;
/** /**
* *
@ -99,19 +99,28 @@ public class SequenceNumber implements Comparable<SequenceNumber> {
*/ */
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (!(o instanceof SequenceNumber)) return false; if (!(o instanceof SequenceNumber)) {
return false;
}
SequenceNumber sq = (SequenceNumber) o; SequenceNumber sq = (SequenceNumber) o;
return (pc.equals(sq.pc)&&(uniq==sq.uniq)); return (pc.equals(sq.pc) && (uniq == sq.uniq));
} }
/* (non-Javadoc) /* (non-Javadoc)
* @see java.lang.Comparable#compareTo(java.lang.Object) * @see java.lang.Comparable#compareTo(java.lang.Object)
*/ */
@Override
public int compareTo(SequenceNumber sq) { public int compareTo(SequenceNumber sq) {
int val = pc.compareTo(sq.pc); int val = pc.compareTo(sq.pc);
if (val != 0) return val; if (val != 0) {
if (uniq < sq.uniq) return -1; return val;
if (sq.uniq < uniq) return 1; }
if (uniq < sq.uniq) {
return -1;
}
if (sq.uniq < uniq) {
return 1;
}
return 0; return 0;
} }
@ -124,33 +133,37 @@ public class SequenceNumber implements Comparable<SequenceNumber> {
AddressSpace space = pc.getAddressSpace(); AddressSpace space = pc.getAddressSpace();
SpecXmlUtils.encodeStringAttribute(resBuf, "space", space.getName()); SpecXmlUtils.encodeStringAttribute(resBuf, "space", space.getName());
SpecXmlUtils.encodeUnsignedIntegerAttribute(resBuf, "offset", pc.getOffset()); SpecXmlUtils.encodeUnsignedIntegerAttribute(resBuf, "offset", pc.getOffset());
if (uniq != -1) if (uniq != -1) {
SpecXmlUtils.encodeUnsignedIntegerAttribute(resBuf, "uniq", uniq); SpecXmlUtils.encodeUnsignedIntegerAttribute(resBuf, "uniq", uniq);
}
resBuf.append("/>"); 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 decoder is the stream decoder
* @param factory pcode factory used to create new pcode
* *
* @return new sequence number * @return new sequence number
* @throws PcodeXMLException for an invalid encoding
*/ */
public static SequenceNumber readXML(XmlPullParser parser,AddressFactory factory) { public static SequenceNumber decode(Decoder decoder) throws PcodeXMLException {
XmlElement el = parser.start("seqnum"); int el = decoder.openElement(ElementId.ELEM_SEQNUM);
String attrstring = el.getAttribute("uniq"); int uniq = -1;
int uniq; for (;;) {
if (attrstring != null) int attribId = decoder.getNextAttributeId();
uniq = SpecXmlUtils.decodeInt(attrstring); if (attribId == 0) {
else break;
uniq = -1; // Should fill in with something from factory }
String space = el.getAttribute("space"); else if (attribId == AttributeId.ATTRIB_UNIQ.getId()) {
AddressSpace spc = factory.getAddressSpace(space); uniq = (int) decoder.readUnsignedInteger();
long offset = SpecXmlUtils.decodeLong(el.getAttribute("offset")); }
parser.end(el); }
return new SequenceNumber(spc.getAddress(offset),uniq); 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) /* (non-Javadoc)
@ -158,15 +171,8 @@ public class SequenceNumber implements Comparable<SequenceNumber> {
*/ */
@Override @Override
public String toString() { public String toString() {
return ("(" return ("(" + pc.getAddressSpace().getName() + ", 0x" + Long.toHexString(pc.getOffset()) +
+ pc.getAddressSpace().getName() ", " + uniq + ", " + order + ")");
+ ", 0x"
+ Long.toHexString(pc.getOffset())
+ ", "
+ uniq
+ ", "
+ order
+ ")");
} }
/* (non-Javadoc) /* (non-Javadoc)

View file

@ -19,8 +19,6 @@ import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSpace; import ghidra.program.model.address.AddressSpace;
import ghidra.program.model.listing.VariableStorage; import ghidra.program.model.listing.VariableStorage;
import ghidra.util.xml.SpecXmlUtils; 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. * 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 * Decode this entry from the stream. Typically more than one element is consumed.
* @param parser is the given XML stream * @param decoder is the stream decoder
* @throws PcodeXMLException if the XML is invalid * @throws PcodeXMLException for invalid encodings
*/ */
public abstract void restoreXML(XmlPullParser parser) public abstract void decode(Decoder decoder) throws PcodeXMLException;
throws PcodeXMLException;
/** /**
* Save this entry as (a set of) XML tags to the given stream * Save this entry as (a set of) XML tags to the given stream
@ -83,21 +80,22 @@ public abstract class SymbolEntry {
return pcaddr; return pcaddr;
} }
protected void parseRangeList(XmlPullParser parser) { protected void decodeRangeList(Decoder decoder) throws PcodeXMLException {
XmlElement rangelistel = parser.start("rangelist"); int rangelistel = decoder.openElement(ElementId.ELEM_RANGELIST);
if (parser.peek().isStart()) { if (decoder.peekElement() != 0) {
// we only use this to establish first-use // we only use this to establish first-use
XmlElement rangeel = parser.start("range"); int rangeel = decoder.openElement(ElementId.ELEM_RANGE);
String spc = rangeel.getAttribute("space"); AddressSpace spc = decoder.readSpace(AttributeId.ATTRIB_SPACE);
long offset = SpecXmlUtils.decodeLong(rangeel.getAttribute("first")); long offset = decoder.readUnsignedInteger(AttributeId.ATTRIB_FIRST);
pcaddr = symbol.function.getAddressFactory().getAddressSpace(spc).getAddress(offset); pcaddr = spc.getAddress(offset);
pcaddr = pcaddr = symbol.function.getFunction()
symbol.function.getFunction().getEntryPoint().getAddressSpace().getOverlayAddress( .getEntryPoint()
pcaddr); .getAddressSpace()
parser.end(rangeel); .getOverlayAddress(pcaddr);
decoder.closeElement(rangeel);
} }
parser.end(rangelistel); decoder.closeElement(rangelistel);
} }
protected void buildRangelistXML(StringBuilder res) { 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.Language;
import ghidra.program.model.lang.Register; import ghidra.program.model.lang.Register;
import ghidra.util.exception.InvalidInputException; import ghidra.util.exception.InvalidInputException;
import ghidra.util.xml.SpecXmlUtils;
import ghidra.xml.XmlElement;
import ghidra.xml.XmlPullParser;
/** /**
* *
@ -322,42 +319,48 @@ 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 * @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 * @throws PcodeXMLException if XML is improperly formed
*/ */
public static Varnode readXML(XmlPullParser parser, PcodeFactory factory) public static Varnode decode(Decoder decoder, PcodeFactory factory) throws PcodeXMLException {
throws PcodeXMLException { int el = decoder.peekElement();
XmlElement el = parser.start(); if (el == ElementId.ELEM_VOID.getId()) {
try { decoder.openElement();
if (el.getName().equals("void")) { decoder.closeElement(el);
return null; return null;
} }
Varnode vn; else if (el == ElementId.ELEM_SPACEID.getId() || el == ElementId.ELEM_IOP.getId()) {
String attrstring = el.getAttribute("ref"); Address addr = AddressXML.decode(decoder);
return factory.newVarnode(4, addr);
}
el = decoder.openElement();
int ref = -1; int ref = -1;
if (attrstring != null) { int sz = 4;
ref = SpecXmlUtils.decodeInt(attrstring); // If we have a reference for (;;) {
vn = factory.getRef(ref); // The varnode may already exist int attribId = decoder.getNextAttributeId();
if (attribId == 0) {
break;
}
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) { if (vn != null) {
decoder.closeElement(el);
return vn; return vn;
} }
} }
Address addr = AddressXML.readXML(el, factory.getAddressFactory()); else if (attribId == AttributeId.ATTRIB_SIZE.getId()) {
if (addr == null) { sz = (int) decoder.readSignedInteger();
return null;
} }
int sz;
attrstring = el.getAttribute("size");
if (attrstring != null) {
sz = SpecXmlUtils.decodeInt(attrstring);
}
else {
sz = 4;
} }
decoder.rewindAttributes();
Varnode vn;
Address addr = AddressXML.decodeFromAttributes(decoder);
if (ref != -1) { if (ref != -1) {
vn = factory.newVarnode(sz, addr, ref); vn = factory.newVarnode(sz, addr, ref);
} }
@ -366,40 +369,48 @@ public class Varnode {
} }
AddressSpace spc = addr.getAddressSpace(); AddressSpace spc = addr.getAddressSpace();
if ((spc != null) && (spc.getType() == AddressSpace.TYPE_VARIABLE)) { // Check for a composite Address if ((spc != null) && (spc.getType() == AddressSpace.TYPE_VARIABLE)) { // Check for a composite Address
decoder.rewindAttributes();
try { try {
factory.readXMLVarnodePieces(el, addr); factory.decodeVarnodePieces(decoder, addr);
} }
catch (InvalidInputException e) { catch (InvalidInputException e) {
throw new PcodeXMLException("Invalid varnode pieces: " + e.getMessage()); throw new PcodeXMLException("Invalid varnode pieces: " + e.getMessage());
} }
} }
attrstring = el.getAttribute("grp"); decoder.rewindAttributes();
if (attrstring != null) { for (;;) {
short val = (short) SpecXmlUtils.decodeInt(attrstring); int attribId = decoder.getNextAttributeId();
if (attribId == 0) {
break;
}
else if (attribId == AttributeId.ATTRIB_GRP.getId()) {
short val = (short) decoder.readSignedInteger();
factory.setMergeGroup(vn, val); factory.setMergeGroup(vn, val);
} }
attrstring = el.getAttribute("persists"); else if (attribId == AttributeId.ATTRIB_PERSISTS.getId()) {
if ((attrstring != null) && (SpecXmlUtils.decodeBoolean(attrstring))) { if (decoder.readBool()) {
factory.setPersistent(vn, true); factory.setPersistent(vn, true);
} }
attrstring = el.getAttribute("addrtied"); }
if ((attrstring != null) && (SpecXmlUtils.decodeBoolean(attrstring))) { else if (attribId == AttributeId.ATTRIB_ADDRTIED.getId()) {
if (decoder.readBool()) {
factory.setAddrTied(vn, true); factory.setAddrTied(vn, true);
} }
attrstring = el.getAttribute("unaff"); }
if ((attrstring != null) && (SpecXmlUtils.decodeBoolean(attrstring))) { else if (attribId == AttributeId.ATTRIB_UNAFF.getId()) {
if (decoder.readBool()) {
factory.setUnaffected(vn, true); factory.setUnaffected(vn, true);
} }
attrstring = el.getAttribute("input"); }
if ((attrstring != null) && (SpecXmlUtils.decodeBoolean(attrstring))) { else if (attribId == AttributeId.ATTRIB_INPUT.getId()) {
if (decoder.readBool()) {
vn = factory.setInput(vn, true); vn = factory.setInput(vn, true);
} }
}
}
decoder.closeElement(sz);
return vn; return vn;
} }
finally {
parser.end(el);
}
}
/** /**
* Trim a varnode in a constant space to the correct starting offset. * Trim a varnode in a constant space to the correct starting offset.

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 * IP: GHIDRA
* REVIEWED: YES
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,6 +15,7 @@
*/ */
package ghidra.xml; package ghidra.xml;
import java.util.Iterator;
import java.util.Map; import java.util.Map;
public interface XmlElement { public interface XmlElement {
@ -31,6 +31,8 @@ public interface XmlElement {
public Map<String, String> getAttributes(); public Map<String, String> getAttributes();
public Iterator<Map.Entry<String, String>> getAttributeIterator();
public boolean hasAttribute(String key); public boolean hasAttribute(String key);
public String getAttribute(String key); public String getAttribute(String key);

View file

@ -1,6 +1,5 @@
/* ### /* ###
* IP: GHIDRA * IP: GHIDRA
* REVIEWED: YES
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,8 +15,7 @@
*/ */
package ghidra.xml; package ghidra.xml;
import java.util.LinkedHashMap; import java.util.*;
import java.util.Map;
public class XmlElementImpl implements XmlElement { public class XmlElementImpl implements XmlElement {
private final String name; private final String name;
@ -31,7 +29,8 @@ public class XmlElementImpl implements XmlElement {
private final int lineNumber; private final int lineNumber;
public XmlElementImpl(boolean isStart, boolean isEnd, String name, int level, 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) { if (isStart && isEnd) {
throw new XmlException( throw new XmlException(
"empty elements must be split into separate start and end elements (see splitEmptyElement)"); "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; this.lineNumber = lineNumber;
} }
@Override
public int getColumnNumber() { public int getColumnNumber() {
return columnNumber; return columnNumber;
} }
@Override
public int getLineNumber() { public int getLineNumber() {
return lineNumber; return lineNumber;
} }
@Override
public boolean hasAttribute(String key) { public boolean hasAttribute(String key) {
if (attributes == null) { if (attributes == null) {
return false; return false;
@ -62,6 +64,7 @@ public class XmlElementImpl implements XmlElement {
return attributes.containsKey(key); return attributes.containsKey(key);
} }
@Override
public String getAttribute(String key) { public String getAttribute(String key) {
if (attributes == null) { if (attributes == null) {
return null; return null;
@ -69,34 +72,50 @@ public class XmlElementImpl implements XmlElement {
return attributes.get(key); return attributes.get(key);
} }
@Override
public LinkedHashMap<String, String> getAttributes() { public LinkedHashMap<String, String> getAttributes() {
return attributes == null ? null : new LinkedHashMap<String, String>(attributes); 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) { public void setAttribute(String key, String value) {
attributes.put(key, value); attributes.put(key, value);
} }
@Override
public int getLevel() { public int getLevel() {
return level; return level;
} }
@Override
public String getName() { public String getName() {
return name; return name;
} }
@Override
public String getText() { public String getText() {
return text; return text;
} }
@Override
public boolean isContent() { public boolean isContent() {
return isContent; return isContent;
} }
@Override
public boolean isEnd() { public boolean isEnd() {
return isEnd; return isEnd;
} }
@Override
public boolean isStart() { public boolean isStart() {
return isStart; return isStart;
} }
@ -158,13 +177,12 @@ public class XmlElementImpl implements XmlElement {
public static XmlElement[] splitEmptyElement(final XmlElementImpl element) { public static XmlElement[] splitEmptyElement(final XmlElementImpl element) {
XmlElement[] result; XmlElement[] result;
if (element.isStart() && element.isEnd()) { if (element.isStart() && element.isEnd()) {
result = result = new XmlElement[] {
new XmlElement[] {
new XmlElementImpl(true, false, element.getName(), element.getLevel(), new XmlElementImpl(true, false, element.getName(), element.getLevel(),
element.getAttributes(), null, element.getColumnNumber(), element.getAttributes(), null, element.getColumnNumber(),
element.getLineNumber()), element.getLineNumber()),
new XmlElementImpl(false, true, element.getName(), element.getLevel(), null, new XmlElementImpl(false, true, element.getName(), element.getLevel(), null, "",
"", element.getColumnNumber(), element.getLineNumber()) }; element.getColumnNumber(), element.getLineNumber()) };
} }
else { else {
result = new XmlElement[] { element }; result = new XmlElement[] { element };