mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-01-08 10:41:12 +00:00
GP-2262 Marshaling refactor - java-side
This commit is contained in:
parent
0123c85d9f
commit
ae79857b42
@ -21,6 +21,7 @@
|
||||
|
||||
#include "ifacedecomp.hh"
|
||||
|
||||
|
||||
static IfaceStatus *ghidra_dcp = (IfaceStatus *)0;
|
||||
static RemoteSocket *remote = (RemoteSocket *)0;
|
||||
|
||||
@ -62,6 +63,8 @@ void connect_to_console(Funcdata *fd)
|
||||
|
||||
#endif
|
||||
|
||||
ElementId ELEM_DOC = ElementId("doc",218);
|
||||
|
||||
vector<ArchitectureGhidra *> archlist; // List of architectures currently running
|
||||
|
||||
map<string,GhidraCommand *> GhidraCapability::commandmap; // List of commands we can receive from Ghidra proper
|
||||
@ -300,10 +303,10 @@ void DecompileAt::rawAction(void)
|
||||
}
|
||||
|
||||
sout.write("\000\000\001\016",4);
|
||||
// Write output XML directly to outstream
|
||||
|
||||
if (fd->isProcComplete()) {
|
||||
sout << "<doc>\n";
|
||||
XmlEncode encoder(sout);
|
||||
encoder.openElement(ELEM_DOC);
|
||||
if (ghidra->getSendParamMeasures() && (ghidra->allacts.getCurrentName() == "paramid")) {
|
||||
ParamIDAnalysis pidanalysis( fd, true ); // Only send back final prototype
|
||||
pidanalysis.encode( encoder, true );
|
||||
@ -318,7 +321,7 @@ void DecompileAt::rawAction(void)
|
||||
(ghidra->allacts.getCurrentName() == "decompile"))
|
||||
ghidra->print->docFunction(fd);
|
||||
}
|
||||
sout << "</doc>\n";
|
||||
encoder.closeElement(ELEM_DOC);
|
||||
}
|
||||
sout.write("\000\000\001\017",4);
|
||||
}
|
||||
|
@ -29,6 +29,8 @@
|
||||
|
||||
class GhidraCommand;
|
||||
|
||||
extern ElementId ELEM_DOC; ///< Marshaling element \<doc>
|
||||
|
||||
/// \brief Registration point and dispatcher for commands sent to the decompiler
|
||||
///
|
||||
/// This is the base class for \b command \b capabilities (sets of commands).
|
||||
|
@ -500,7 +500,7 @@ AttributeId ATTRIB_VAL = AttributeId("val",24);
|
||||
AttributeId ATTRIB_VALUE = AttributeId("value",25);
|
||||
AttributeId ATTRIB_WORDSIZE = AttributeId("wordsize",26);
|
||||
|
||||
AttributeId ATTRIB_UNKNOWN = AttributeId("XMLunknown",144); // Number serves as next open index
|
||||
AttributeId ATTRIB_UNKNOWN = AttributeId("XMLunknown",147); // Number serves as next open index
|
||||
|
||||
ElementId ELEM_DATA = ElementId("data",1);
|
||||
ElementId ELEM_INPUT = ElementId("input",2);
|
||||
@ -513,4 +513,4 @@ ElementId ELEM_VAL = ElementId("val",8);
|
||||
ElementId ELEM_VALUE = ElementId("value",9);
|
||||
ElementId ELEM_VOID = ElementId("void",10);
|
||||
|
||||
ElementId ELEM_UNKNOWN = ElementId("XMLunknown",218); // Number serves as next open index
|
||||
ElementId ELEM_UNKNOWN = ElementId("XMLunknown",231); // Number serves as next open index
|
||||
|
@ -232,7 +232,7 @@ public:
|
||||
/// \brief Find the specific attribute in the current element and return it as an address space
|
||||
///
|
||||
/// Search attributes from the current element for a match to the given attribute id.
|
||||
/// Return this attribute as an address space. If there is no attribute matching the id, an exception is throw.
|
||||
/// Return this attribute as an address space. If there is no attribute matching the id, an exception is thrown.
|
||||
/// Parse via getNextAttributeId is reset.
|
||||
/// \param attribId is the specific attribute id to match
|
||||
/// \return the address space associated with the attribute
|
||||
|
@ -1,6 +1,5 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -17,28 +16,28 @@
|
||||
package ghidra.app.decompiler;
|
||||
|
||||
import ghidra.program.model.pcode.*;
|
||||
import ghidra.util.xml.*;
|
||||
import ghidra.xml.*;
|
||||
|
||||
public class ClangBreak extends ClangToken {
|
||||
|
||||
|
||||
private int indent; // Number of characters of indent
|
||||
|
||||
|
||||
public ClangBreak(ClangNode par) {
|
||||
super(par);
|
||||
indent = 0;
|
||||
}
|
||||
|
||||
public ClangBreak(ClangNode par,int indent) {
|
||||
|
||||
public ClangBreak(ClangNode par, int indent) {
|
||||
super(par);
|
||||
this.indent = indent;
|
||||
}
|
||||
|
||||
public int getIndent() { return indent; }
|
||||
|
||||
|
||||
public int getIndent() {
|
||||
return indent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreFromXML(XmlElement el,XmlElement end,PcodeFactory pfactory) {
|
||||
super.restoreFromXML(el,end,pfactory);
|
||||
indent = SpecXmlUtils.decodeInt(el.getAttribute("indent"));
|
||||
public void decode(Decoder decoder, PcodeFactory pfactory) throws PcodeXMLException {
|
||||
indent = (int) decoder.readSignedInteger(AttributeId.ATTRIB_INDENT);
|
||||
super.decode(decoder, pfactory);
|
||||
}
|
||||
}
|
||||
|
@ -17,9 +17,7 @@ package ghidra.app.decompiler;
|
||||
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressSpace;
|
||||
import ghidra.program.model.pcode.PcodeFactory;
|
||||
import ghidra.util.xml.SpecXmlUtils;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.program.model.pcode.*;
|
||||
|
||||
public class ClangCommentToken extends ClangToken {
|
||||
|
||||
@ -58,12 +56,11 @@ public class ClangCommentToken extends ClangToken {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreFromXML(XmlElement el, XmlElement end, PcodeFactory pfactory) {
|
||||
super.restoreFromXML(el, end, pfactory);
|
||||
String name = el.getAttribute(ClangXML.SPACE);
|
||||
AddressSpace spc = pfactory.getAddressFactory().getAddressSpace(name);
|
||||
long offset = SpecXmlUtils.decodeLong(el.getAttribute(ClangXML.OFFSET));
|
||||
public void decode(Decoder decoder, PcodeFactory pfactory) throws PcodeXMLException {
|
||||
AddressSpace spc = decoder.readSpace(AttributeId.ATTRIB_SPACE);
|
||||
long offset = decoder.readUnsignedInteger(AttributeId.ATTRIB_OFF);
|
||||
srcaddr = spc.getAddress(offset);
|
||||
super.decode(decoder, pfactory);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -16,10 +16,7 @@
|
||||
package ghidra.app.decompiler;
|
||||
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.program.model.pcode.PcodeFactory;
|
||||
import ghidra.program.model.pcode.PcodeOp;
|
||||
import ghidra.util.xml.SpecXmlUtils;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.program.model.pcode.*;
|
||||
|
||||
/**
|
||||
* A C code token representing a structure field.
|
||||
@ -55,22 +52,33 @@ public class ClangFieldToken extends ClangToken {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreFromXML(XmlElement el, XmlElement end, PcodeFactory pfactory) {
|
||||
super.restoreFromXML(el, end, pfactory);
|
||||
String datatypestring = el.getAttribute("name"); // Name of the structure
|
||||
public void decode(Decoder decoder, PcodeFactory pfactory) throws PcodeXMLException {
|
||||
String datatypestring = null;
|
||||
long id = 0;
|
||||
for (;;) {
|
||||
int attribId = decoder.getNextAttributeId();
|
||||
if (attribId == 0) {
|
||||
break;
|
||||
}
|
||||
if (attribId == AttributeId.ATTRIB_NAME.getId()) { // Name of the structure
|
||||
datatypestring = decoder.readString();
|
||||
}
|
||||
else if (attribId == AttributeId.ATTRIB_ID.getId()) {
|
||||
id = decoder.readUnsignedInteger();
|
||||
}
|
||||
else if (attribId == AttributeId.ATTRIB_OFF.getId()) {
|
||||
offset = (int) decoder.readSignedInteger();
|
||||
}
|
||||
else if (attribId == AttributeId.ATTRIB_OPREF.getId()) {
|
||||
int refid = (int) decoder.readUnsignedInteger();
|
||||
op = pfactory.getOpRef(refid);
|
||||
}
|
||||
}
|
||||
if (datatypestring != null) {
|
||||
datatype =
|
||||
pfactory.getDataTypeManager().findBaseType(datatypestring, el.getAttribute("id"));
|
||||
}
|
||||
String offsetstring = el.getAttribute(ClangXML.OFFSET);
|
||||
if (offsetstring != null) {
|
||||
offset = SpecXmlUtils.decodeInt(offsetstring);
|
||||
}
|
||||
String oprefstring = el.getAttribute(ClangXML.OPREF);
|
||||
if (oprefstring != null) {
|
||||
int refid = SpecXmlUtils.decodeInt(oprefstring);
|
||||
op = pfactory.getOpRef(refid);
|
||||
datatype = pfactory.getDataTypeManager().findBaseType(datatypestring, id);
|
||||
}
|
||||
decoder.rewindAttributes();
|
||||
super.decode(decoder, pfactory);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -22,10 +21,8 @@
|
||||
*/
|
||||
package ghidra.app.decompiler;
|
||||
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.pcode.*;
|
||||
import ghidra.util.xml.*;
|
||||
import ghidra.xml.*;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -37,34 +34,51 @@ public class ClangFuncNameToken extends ClangToken {
|
||||
private HighFunction hfunc; // Overall reference to function
|
||||
private PcodeOp op; // Local reference to function op
|
||||
|
||||
public ClangFuncNameToken(ClangNode par,HighFunction hf) {
|
||||
public ClangFuncNameToken(ClangNode par, HighFunction hf) {
|
||||
super(par);
|
||||
hfunc = hf;
|
||||
op = null;
|
||||
}
|
||||
public HighFunction getHighFunction() { return hfunc; }
|
||||
|
||||
@Override
|
||||
public PcodeOp getPcodeOp() { return op; }
|
||||
|
||||
@Override
|
||||
public Address getMinAddress() {
|
||||
if (op==null) return null;
|
||||
return op.getSeqnum().getTarget().getPhysicalAddress();
|
||||
|
||||
public HighFunction getHighFunction() {
|
||||
return hfunc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Address getMaxAddress() {
|
||||
if (op==null) return null;
|
||||
return op.getSeqnum().getTarget().getPhysicalAddress();
|
||||
public PcodeOp getPcodeOp() {
|
||||
return op;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void restoreFromXML(XmlElement el,XmlElement end,PcodeFactory pfactory) {
|
||||
super.restoreFromXML(el,end,pfactory);
|
||||
String oprefstring = el.getAttribute(ClangXML.OPREF);
|
||||
if (oprefstring != null) {
|
||||
int refid = SpecXmlUtils.decodeInt(oprefstring);
|
||||
op = pfactory.getOpRef(refid);
|
||||
public Address getMinAddress() {
|
||||
if (op == null) {
|
||||
return null;
|
||||
}
|
||||
return op.getSeqnum().getTarget().getPhysicalAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Address getMaxAddress() {
|
||||
if (op == null) {
|
||||
return null;
|
||||
}
|
||||
return op.getSeqnum().getTarget().getPhysicalAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void decode(Decoder decoder, PcodeFactory pfactory) throws PcodeXMLException {
|
||||
for (;;) {
|
||||
int attribId = decoder.getNextAttributeId();
|
||||
if (attribId == 0) {
|
||||
break;
|
||||
}
|
||||
if (attribId == AttributeId.ATTRIB_OPREF.getId()) {
|
||||
int refid = (int) decoder.readUnsignedInteger();
|
||||
op = pfactory.getOpRef(refid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
decoder.rewindAttributes();
|
||||
super.decode(decoder, pfactory);
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -16,36 +15,39 @@
|
||||
*/
|
||||
package ghidra.app.decompiler;
|
||||
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressSpace;
|
||||
import ghidra.program.model.pcode.*;
|
||||
import ghidra.util.xml.*;
|
||||
import ghidra.xml.*;
|
||||
|
||||
public class ClangLabelToken extends ClangToken {
|
||||
private Address blockaddr; // Address this is labelling
|
||||
|
||||
|
||||
public ClangLabelToken(ClangNode par) {
|
||||
super(par);
|
||||
blockaddr = null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isVariableRef() { return false; }
|
||||
|
||||
@Override
|
||||
public Address getMinAddress() { return blockaddr; }
|
||||
|
||||
@Override
|
||||
public Address getMaxAddress() { return blockaddr; }
|
||||
|
||||
@Override
|
||||
public void restoreFromXML(XmlElement el,XmlElement end,PcodeFactory pfactory) {
|
||||
super.restoreFromXML(el, end, pfactory);
|
||||
String name = el.getAttribute(ClangXML.SPACE);
|
||||
AddressSpace spc = pfactory.getAddressFactory().getAddressSpace(name);
|
||||
long offset = SpecXmlUtils.decodeLong(el.getAttribute(ClangXML.OFFSET));
|
||||
blockaddr = spc.getAddress(offset);
|
||||
public boolean isVariableRef() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Address getMinAddress() {
|
||||
return blockaddr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Address getMaxAddress() {
|
||||
return blockaddr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void decode(Decoder decoder, PcodeFactory pfactory) throws PcodeXMLException {
|
||||
AddressSpace spc = decoder.readSpace(AttributeId.ATTRIB_SPACE);
|
||||
long offset = decoder.readUnsignedInteger(AttributeId.ATTRIB_OFF);
|
||||
blockaddr = spc.getAddress(offset);
|
||||
super.decode(decoder, pfactory);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -22,10 +21,8 @@
|
||||
*/
|
||||
package ghidra.app.decompiler;
|
||||
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.pcode.*;
|
||||
import ghidra.util.xml.*;
|
||||
import ghidra.xml.*;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -41,28 +38,41 @@ public class ClangOpToken extends ClangToken {
|
||||
super(par);
|
||||
op = null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public PcodeOp getPcodeOp() { return op; }
|
||||
|
||||
@Override
|
||||
public Address getMinAddress() {
|
||||
if (op==null) return null;
|
||||
return op.getSeqnum().getTarget().getPhysicalAddress();
|
||||
public PcodeOp getPcodeOp() {
|
||||
return op;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Address getMaxAddress() {
|
||||
if (op==null) return null;
|
||||
return op.getSeqnum().getTarget().getPhysicalAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreFromXML(XmlElement el,XmlElement end,PcodeFactory pfactory) {
|
||||
super.restoreFromXML(el,end,pfactory);
|
||||
String oprefstring = el.getAttribute(ClangXML.OPREF);
|
||||
if (oprefstring != null) {
|
||||
int refid = SpecXmlUtils.decodeInt(oprefstring);
|
||||
op = pfactory.getOpRef(refid);
|
||||
public Address getMinAddress() {
|
||||
if (op == null) {
|
||||
return null;
|
||||
}
|
||||
return op.getSeqnum().getTarget().getPhysicalAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Address getMaxAddress() {
|
||||
if (op == null) {
|
||||
return null;
|
||||
}
|
||||
return op.getSeqnum().getTarget().getPhysicalAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void decode(Decoder decoder, PcodeFactory pfactory) throws PcodeXMLException {
|
||||
for (;;) {
|
||||
int attribId = decoder.getNextAttributeId();
|
||||
if (attribId == 0) {
|
||||
break;
|
||||
}
|
||||
if (attribId == AttributeId.ATTRIB_OPREF.getId()) {
|
||||
int refid = (int) decoder.readUnsignedInteger();
|
||||
op = pfactory.getOpRef(refid);
|
||||
}
|
||||
}
|
||||
decoder.rewindAttributes();
|
||||
super.decode(decoder, pfactory);
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -22,11 +21,10 @@
|
||||
*/
|
||||
package ghidra.app.decompiler;
|
||||
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.program.model.pcode.*;
|
||||
import ghidra.util.*;
|
||||
import ghidra.util.xml.*;
|
||||
import ghidra.xml.*;
|
||||
import ghidra.util.Msg;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
@ -42,25 +40,35 @@ public class ClangReturnType extends ClangTokenGroup {
|
||||
varnode = null;
|
||||
datatype = null;
|
||||
}
|
||||
|
||||
public DataType getDataType() { return datatype; }
|
||||
public Varnode getVarnode() { return varnode; }
|
||||
|
||||
|
||||
public DataType getDataType() {
|
||||
return datatype;
|
||||
}
|
||||
|
||||
public Varnode getVarnode() {
|
||||
return varnode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreFromXML(XmlPullParser parser,PcodeFactory pfactory) {
|
||||
XmlElement node = parser.peek();
|
||||
super.restoreFromXML(parser,pfactory);
|
||||
String varrefstring = node.getAttribute(ClangXML.VARNODEREF);
|
||||
if (varrefstring != null) {
|
||||
int refid = SpecXmlUtils.decodeInt(varrefstring);
|
||||
varnode = pfactory.getRef(refid);
|
||||
if (varnode != null) {
|
||||
if (varnode.getHigh() == null) {
|
||||
Msg.warn(this, "VOID high variable problem at " + varnode.getAddress());
|
||||
return;
|
||||
public void decode(Decoder decoder, PcodeFactory pfactory) throws PcodeXMLException {
|
||||
for (;;) {
|
||||
int attribId = decoder.getNextAttributeId();
|
||||
if (attribId == 0) {
|
||||
break;
|
||||
}
|
||||
if (attribId == AttributeId.ATTRIB_VARREF.getId()) {
|
||||
int refid = (int) decoder.readUnsignedInteger();
|
||||
varnode = pfactory.getRef(refid);
|
||||
if (varnode != null) {
|
||||
if (varnode.getHigh() == null) {
|
||||
Msg.warn(this, "VOID high variable problem at " + varnode.getAddress());
|
||||
return;
|
||||
}
|
||||
datatype = varnode.getHigh().getDataType();
|
||||
}
|
||||
datatype = varnode.getHigh().getDataType();
|
||||
break;
|
||||
}
|
||||
}
|
||||
super.decode(decoder, pfactory);
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -23,8 +22,7 @@
|
||||
package ghidra.app.decompiler;
|
||||
|
||||
import ghidra.program.model.pcode.*;
|
||||
import ghidra.util.xml.*;
|
||||
import ghidra.xml.*;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
@ -40,16 +38,28 @@ import ghidra.xml.*;
|
||||
public class ClangStatement extends ClangTokenGroup {
|
||||
private PcodeOp op; // Root op of C-statement
|
||||
|
||||
public ClangStatement(ClangNode par) { super(par); op = null; }
|
||||
public PcodeOp getPcodeOp() { return op; }
|
||||
public ClangStatement(ClangNode par) {
|
||||
super(par);
|
||||
op = null;
|
||||
}
|
||||
|
||||
public PcodeOp getPcodeOp() {
|
||||
return op;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreFromXML(XmlPullParser parser,PcodeFactory pfactory) {
|
||||
XmlElement node = parser.peek();
|
||||
String oprefstring = node.getAttribute(ClangXML.OPREF);
|
||||
if (oprefstring != null) {
|
||||
int refid = SpecXmlUtils.decodeInt(oprefstring);
|
||||
op = pfactory.getOpRef(refid);
|
||||
public void decode(Decoder decoder, PcodeFactory pfactory) throws PcodeXMLException {
|
||||
for (;;) {
|
||||
int attribId = decoder.getNextAttributeId();
|
||||
if (attribId == 0) {
|
||||
break;
|
||||
}
|
||||
if (attribId == AttributeId.ATTRIB_OPREF.getId()) {
|
||||
int refid = (int) decoder.readUnsignedInteger();
|
||||
op = pfactory.getOpRef(refid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
super.restoreFromXML(parser,pfactory);
|
||||
super.decode(decoder, pfactory);
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -23,8 +22,6 @@
|
||||
package ghidra.app.decompiler;
|
||||
|
||||
import ghidra.program.model.pcode.*;
|
||||
import ghidra.util.xml.*;
|
||||
import ghidra.xml.*;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -33,38 +30,54 @@ import ghidra.xml.*;
|
||||
* A SyntaxToken may be or may include spacing
|
||||
*/
|
||||
public class ClangSyntaxToken extends ClangToken {
|
||||
private int open,close;
|
||||
private int open, close;
|
||||
|
||||
public ClangSyntaxToken(ClangNode par) {
|
||||
super(par);
|
||||
open = close = -1;
|
||||
}
|
||||
public ClangSyntaxToken(ClangNode par,String txt) {
|
||||
super(par,txt);
|
||||
|
||||
public ClangSyntaxToken(ClangNode par, String txt) {
|
||||
super(par, txt);
|
||||
open = close = -1;
|
||||
}
|
||||
public ClangSyntaxToken(ClangNode par,String txt,String col) {
|
||||
super(par,txt,col);
|
||||
|
||||
public ClangSyntaxToken(ClangNode par, String txt, String col) {
|
||||
super(par, txt, col);
|
||||
open = close = -1;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isVariableRef() {
|
||||
if (Parent() instanceof ClangVariableDecl) return true;
|
||||
return false;
|
||||
public boolean isVariableRef() {
|
||||
if (Parent() instanceof ClangVariableDecl) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void restoreFromXML(XmlElement el,XmlElement end,PcodeFactory pfactory) {
|
||||
super.restoreFromXML(el,end,pfactory);
|
||||
String str = el.getAttribute("open");
|
||||
if (str != null)
|
||||
open = SpecXmlUtils.decodeInt(str);
|
||||
str = el.getAttribute("close");
|
||||
if (str != null)
|
||||
close = SpecXmlUtils.decodeInt(str);
|
||||
public void decode(Decoder decoder, PcodeFactory pfactory) throws PcodeXMLException {
|
||||
for (;;) {
|
||||
int attribId = decoder.getNextAttributeId();
|
||||
if (attribId == 0) {
|
||||
break;
|
||||
}
|
||||
if (attribId == AttributeId.ATTRIB_OPEN.getId()) {
|
||||
open = (int) decoder.readSignedInteger();
|
||||
}
|
||||
else if (attribId == AttributeId.ATTRIB_CLOSE.getId()) {
|
||||
close = (int) decoder.readSignedInteger();
|
||||
}
|
||||
}
|
||||
decoder.rewindAttributes();
|
||||
super.decode(decoder, pfactory);
|
||||
}
|
||||
|
||||
public int getOpen() {
|
||||
return open;
|
||||
}
|
||||
|
||||
public int getClose() {
|
||||
return close;
|
||||
}
|
||||
|
||||
public int getOpen() { return open; }
|
||||
public int getClose() { return close; }
|
||||
}
|
||||
|
||||
|
@ -27,8 +27,6 @@ import java.util.List;
|
||||
//import ghidra.app.plugin.core.decompile.*;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.pcode.*;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -154,9 +152,19 @@ public class ClangToken implements ClangNode {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public void restoreFromXML(XmlElement el, XmlElement end, PcodeFactory pfactory) {
|
||||
text = end.getText();
|
||||
String col = el.getAttribute(ClangXML.COLOR);
|
||||
public void decode(Decoder decoder, PcodeFactory pfactory) throws PcodeXMLException {
|
||||
String col = null;
|
||||
for (;;) {
|
||||
int attribId = decoder.getNextAttributeId();
|
||||
if (attribId == 0) {
|
||||
break;
|
||||
}
|
||||
if (attribId == AttributeId.ATTRIB_COLOR.getId()) {
|
||||
col = decoder.readString();
|
||||
break;
|
||||
}
|
||||
}
|
||||
text = decoder.readString(AttributeId.ATTRIB_CONTENT);
|
||||
syntax_type = getColor(col);
|
||||
}
|
||||
|
||||
@ -165,70 +173,67 @@ public class ClangToken implements ClangNode {
|
||||
list.add(this);
|
||||
}
|
||||
|
||||
static public ClangToken buildToken(ClangNode par, XmlPullParser parser,
|
||||
PcodeFactory pfactory) {
|
||||
XmlElement node =
|
||||
parser.start(ClangXML.VARIABLE, ClangXML.OP, ClangXML.SYNTAX, ClangXML.BREAK,
|
||||
ClangXML.FUNCNAME, ClangXML.TYPE, ClangXML.COMMENT, ClangXML.LABEL, ClangXML.FIELD);
|
||||
static public ClangToken buildToken(int node, ClangNode par, Decoder decoder,
|
||||
PcodeFactory pfactory) throws PcodeXMLException {
|
||||
ClangToken token = null;
|
||||
if (node.getName().equals(ClangXML.VARIABLE)) {
|
||||
if (node == ElementId.ELEM_VARIABLE.getId()) {
|
||||
token = new ClangVariableToken(par);
|
||||
}
|
||||
else if (node.getName().equals(ClangXML.OP)) {
|
||||
else if (node == ElementId.ELEM_OP.getId()) {
|
||||
token = new ClangOpToken(par);
|
||||
}
|
||||
else if (node.getName().equals(ClangXML.SYNTAX)) {
|
||||
else if (node == ElementId.ELEM_SYNTAX.getId()) {
|
||||
token = new ClangSyntaxToken(par);
|
||||
}
|
||||
else if (node.getName().equals(ClangXML.BREAK)) {
|
||||
else if (node == ElementId.ELEM_BREAK.getId()) {
|
||||
token = new ClangBreak(par);
|
||||
}
|
||||
else if (node.getName().equals(ClangXML.FUNCNAME)) {
|
||||
else if (node == ElementId.ELEM_FUNCNAME.getId()) {
|
||||
token = new ClangFuncNameToken(par, null);
|
||||
}
|
||||
else if (node.getName().equals(ClangXML.TYPE)) {
|
||||
else if (node == ElementId.ELEM_TYPE.getId()) {
|
||||
token = new ClangTypeToken(par);
|
||||
}
|
||||
else if (node.getName().equals(ClangXML.COMMENT)) {
|
||||
else if (node == ElementId.ELEM_COMMENT.getId()) {
|
||||
token = new ClangCommentToken(par);
|
||||
}
|
||||
else if (node.getName().equals(ClangXML.LABEL)) {
|
||||
else if (node == ElementId.ELEM_LABEL.getId()) {
|
||||
token = new ClangLabelToken(par);
|
||||
}
|
||||
else if (node.getName().equals(ClangXML.FIELD)) {
|
||||
else if (node == ElementId.ELEM_FIELD.getId()) {
|
||||
token = new ClangFieldToken(par);
|
||||
}
|
||||
XmlElement end = parser.end(node);
|
||||
if (token != null) {
|
||||
token.restoreFromXML(node, end, pfactory);
|
||||
else {
|
||||
throw new PcodeXMLException("Expecting token element");
|
||||
}
|
||||
token.decode(decoder, pfactory);
|
||||
return token;
|
||||
}
|
||||
|
||||
public static int getColor(String col) {
|
||||
if (col != null) {
|
||||
if (col.equals(ClangXML.KEYWORD_COLOR)) {
|
||||
if (col.equals(ClangMarkup.KEYWORD_COLOR)) {
|
||||
return KEYWORD_COLOR;
|
||||
}
|
||||
else if (col.equals(ClangXML.VARIABLE_COLOR)) {
|
||||
else if (col.equals(ClangMarkup.VARIABLE_COLOR)) {
|
||||
return VARIABLE_COLOR;
|
||||
}
|
||||
else if (col.equals(ClangXML.CONST_COLOR)) {
|
||||
else if (col.equals(ClangMarkup.CONST_COLOR)) {
|
||||
return CONST_COLOR;
|
||||
}
|
||||
else if (col.equals(ClangXML.PARAMETER_COLOR)) {
|
||||
else if (col.equals(ClangMarkup.PARAMETER_COLOR)) {
|
||||
return PARAMETER_COLOR;
|
||||
}
|
||||
else if (col.equals(ClangXML.GLOBAL_COLOR)) {
|
||||
else if (col.equals(ClangMarkup.GLOBAL_COLOR)) {
|
||||
return GLOBAL_COLOR;
|
||||
}
|
||||
else if (col.equals(ClangXML.TYPE_COLOR)) {
|
||||
else if (col.equals(ClangMarkup.TYPE_COLOR)) {
|
||||
return TYPE_COLOR;
|
||||
}
|
||||
else if (col.equals(ClangXML.COMMENT_COLOR)) {
|
||||
else if (col.equals(ClangMarkup.COMMENT_COLOR)) {
|
||||
return COMMENT_COLOR;
|
||||
}
|
||||
else if (col.equals(ClangXML.FUNCNAME_COLOR)) {
|
||||
else if (col.equals(ClangMarkup.FUNCNAME_COLOR)) {
|
||||
return FUNCTION_COLOR;
|
||||
}
|
||||
}
|
||||
|
@ -20,9 +20,7 @@ import java.util.*;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.pcode.PcodeFactory;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
import ghidra.program.model.pcode.*;
|
||||
|
||||
/**
|
||||
* A node in a tree of C code tokens.
|
||||
@ -106,44 +104,43 @@ public class ClangTokenGroup implements ClangNode, Iterable<ClangNode> {
|
||||
}
|
||||
}
|
||||
|
||||
public void restoreFromXML(XmlPullParser parser, PcodeFactory pfactory) {
|
||||
XmlElement node = parser.start(ClangXML.FUNCTION, ClangXML.RETURN_TYPE, ClangXML.VARDECL,
|
||||
ClangXML.STATEMENT, ClangXML.FUNCPROTO, ClangXML.BLOCK, ClangXML.VARIABLE, ClangXML.OP,
|
||||
ClangXML.SYNTAX, ClangXML.BREAK, ClangXML.FUNCNAME, ClangXML.TYPE, ClangXML.COMMENT,
|
||||
ClangXML.LABEL);
|
||||
while (parser.peek().isStart()) {
|
||||
XmlElement elem = parser.peek();
|
||||
if (elem.getName().equals(ClangXML.RETURN_TYPE)) {
|
||||
public void decode(Decoder decoder, PcodeFactory pfactory) throws PcodeXMLException {
|
||||
for (;;) {
|
||||
int elem = decoder.openElement();
|
||||
if (elem == 0) {
|
||||
break;
|
||||
}
|
||||
if (elem == ElementId.ELEM_RETURN_TYPE.getId()) {
|
||||
ClangReturnType child = new ClangReturnType(this);
|
||||
child.restoreFromXML(parser, pfactory);
|
||||
child.decode(decoder, pfactory);
|
||||
AddTokenGroup(child);
|
||||
}
|
||||
else if (elem.getName().equals(ClangXML.VARDECL)) {
|
||||
else if (elem == ElementId.ELEM_VARDECL.getId()) {
|
||||
ClangVariableDecl child = new ClangVariableDecl(this);
|
||||
child.restoreFromXML(parser, pfactory);
|
||||
child.decode(decoder, pfactory);
|
||||
AddTokenGroup(child);
|
||||
}
|
||||
else if (elem.getName().equals(ClangXML.STATEMENT)) {
|
||||
else if (elem == ElementId.ELEM_STATEMENT.getId()) {
|
||||
ClangStatement child = new ClangStatement(this);
|
||||
child.restoreFromXML(parser, pfactory);
|
||||
child.decode(decoder, pfactory);
|
||||
AddTokenGroup(child);
|
||||
}
|
||||
else if (elem.getName().equals(ClangXML.FUNCPROTO)) {
|
||||
else if (elem == ElementId.ELEM_FUNCPROTO.getId()) {
|
||||
ClangFuncProto child = new ClangFuncProto(this);
|
||||
child.restoreFromXML(parser, pfactory);
|
||||
child.decode(decoder, pfactory);
|
||||
AddTokenGroup(child);
|
||||
}
|
||||
else if (elem.getName().equals(ClangXML.BLOCK)) {
|
||||
else if (elem == ElementId.ELEM_BLOCK.getId()) {
|
||||
ClangTokenGroup child = new ClangTokenGroup(this);
|
||||
child.restoreFromXML(parser, pfactory);
|
||||
child.decode(decoder, pfactory);
|
||||
AddTokenGroup(child);
|
||||
}
|
||||
else {
|
||||
ClangToken tok = ClangToken.buildToken(this, parser, pfactory);
|
||||
ClangToken tok = ClangToken.buildToken(elem, this, decoder, pfactory);
|
||||
AddTokenGroup(tok);
|
||||
}
|
||||
decoder.closeElement(elem);
|
||||
}
|
||||
parser.end(node);
|
||||
}
|
||||
|
||||
private boolean isLetterDigitOrUnderscore(char c) {
|
||||
|
@ -1,6 +1,5 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -22,9 +21,9 @@
|
||||
*/
|
||||
package ghidra.app.decompiler;
|
||||
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.program.model.pcode.*;
|
||||
import ghidra.xml.*;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
@ -38,20 +37,34 @@ public class ClangTypeToken extends ClangToken {
|
||||
super(par);
|
||||
datatype = null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isVariableRef() {
|
||||
if (Parent() instanceof ClangVariableDecl) return true;
|
||||
return false;
|
||||
public boolean isVariableRef() {
|
||||
if (Parent() instanceof ClangVariableDecl) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public DataType getDataType() {
|
||||
return datatype;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void restoreFromXML(XmlElement el,XmlElement end,PcodeFactory pfactory) {
|
||||
super.restoreFromXML(el,end,pfactory);
|
||||
datatype = pfactory.getDataTypeManager().findBaseType(getText(),el.getAttribute("id"));
|
||||
public void decode(Decoder decoder, PcodeFactory pfactory) throws PcodeXMLException {
|
||||
int id = 0;
|
||||
for (;;) {
|
||||
int attribId = decoder.getNextAttributeId();
|
||||
if (attribId == 0) {
|
||||
break;
|
||||
}
|
||||
if (attribId == AttributeId.ATTRIB_ID.getId()) {
|
||||
id = (int) decoder.readUnsignedInteger();
|
||||
break;
|
||||
}
|
||||
}
|
||||
decoder.rewindAttributes();
|
||||
super.decode(decoder, pfactory);
|
||||
datatype = pfactory.getDataTypeManager().findBaseType(getText(), id);
|
||||
}
|
||||
}
|
||||
|
@ -24,9 +24,6 @@ package ghidra.app.decompiler;
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.program.model.pcode.*;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.xml.SpecXmlUtils;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -54,10 +51,9 @@ public class ClangVariableDecl extends ClangTokenGroup {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreFromXML(XmlPullParser parser, PcodeFactory pfactory) {
|
||||
XmlElement node = parser.peek();
|
||||
super.restoreFromXML(parser, pfactory);
|
||||
long symref = SpecXmlUtils.decodeLong(node.getAttribute(ClangXML.SYMREF));
|
||||
public void decode(Decoder decoder, PcodeFactory pfactory) throws PcodeXMLException {
|
||||
long symref = decoder.readUnsignedInteger(AttributeId.ATTRIB_SYMREF);
|
||||
super.decode(decoder, pfactory);
|
||||
HighSymbol sym = pfactory.getSymbol(symref);
|
||||
if (sym == null) {
|
||||
Msg.error(this, "Invalid symbol reference: " + symref + " in " + Parent());
|
||||
|
@ -1,6 +1,5 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -22,10 +21,9 @@
|
||||
*/
|
||||
package ghidra.app.decompiler;
|
||||
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.pcode.*;
|
||||
import ghidra.util.xml.*;
|
||||
import ghidra.xml.*;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
@ -34,40 +32,46 @@ import ghidra.xml.*;
|
||||
public class ClangVariableToken extends ClangToken {
|
||||
private Varnode varnode;
|
||||
private PcodeOp op;
|
||||
|
||||
|
||||
public ClangVariableToken(ClangNode par) {
|
||||
super(par);
|
||||
varnode = null;
|
||||
op = null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Varnode getVarnode() {
|
||||
public Varnode getVarnode() {
|
||||
return varnode;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public PcodeOp getPcodeOp() {
|
||||
return op;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isVariableRef() {
|
||||
public boolean isVariableRef() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Address getMinAddress() {
|
||||
if (op==null) return null;
|
||||
public Address getMinAddress() {
|
||||
if (op == null) {
|
||||
return null;
|
||||
}
|
||||
return op.getSeqnum().getTarget().getPhysicalAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Address getMaxAddress() {
|
||||
if (op==null) return null;
|
||||
public Address getMaxAddress() {
|
||||
if (op == null) {
|
||||
return null;
|
||||
}
|
||||
return op.getSeqnum().getTarget().getPhysicalAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public HighVariable getHighVariable() {
|
||||
public HighVariable getHighVariable() {
|
||||
Varnode inst = getVarnode();
|
||||
if (inst != null) {
|
||||
HighVariable hvar = inst.getHigh();
|
||||
@ -80,19 +84,24 @@ public class ClangVariableToken extends ClangToken {
|
||||
}
|
||||
return super.getHighVariable();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void restoreFromXML(XmlElement el,XmlElement end,PcodeFactory pfactory) {
|
||||
super.restoreFromXML(el,end,pfactory);
|
||||
String varrefstring = el.getAttribute(ClangXML.VARNODEREF);
|
||||
if (varrefstring != null) {
|
||||
int refid = SpecXmlUtils.decodeInt(varrefstring);
|
||||
varnode = pfactory.getRef(refid);
|
||||
}
|
||||
String oprefstring = el.getAttribute(ClangXML.OPREF);
|
||||
if (oprefstring != null) {
|
||||
int refid = SpecXmlUtils.decodeInt(oprefstring);
|
||||
op = pfactory.getOpRef(refid);
|
||||
public void decode(Decoder decoder, PcodeFactory pfactory) throws PcodeXMLException {
|
||||
for (;;) {
|
||||
int attribId = decoder.getNextAttributeId();
|
||||
if (attribId == 0) {
|
||||
break;
|
||||
}
|
||||
if (attribId == AttributeId.ATTRIB_VARREF.getId()) {
|
||||
int refid = (int) decoder.readUnsignedInteger();
|
||||
varnode = pfactory.getRef(refid);
|
||||
}
|
||||
else if (attribId == AttributeId.ATTRIB_OPREF.getId()) {
|
||||
int refid = (int) decoder.readUnsignedInteger();
|
||||
op = pfactory.getOpRef(refid);
|
||||
}
|
||||
}
|
||||
decoder.rewindAttributes();
|
||||
super.decode(decoder, pfactory);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -34,7 +34,6 @@ import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.model.pcode.*;
|
||||
import ghidra.util.task.CancelledListener;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
|
||||
/**
|
||||
* This is a self-contained interface to a single decompile
|
||||
@ -669,10 +668,10 @@ public class DecompInterface {
|
||||
timeoutSecs);
|
||||
decompileMessage = decompCallback.getNativeMessage();
|
||||
if (res != null) {
|
||||
XmlPullParser parser = HighFunction.stringTree(res.getInputStream(),
|
||||
HighFunction.getErrorHandler(this, "Results for structureGraph command"));
|
||||
XmlDecode decoder = new XmlDecode(factory);
|
||||
decoder.ingestStream(res.getInputStream(), "structureGraph results");
|
||||
resgraph = new BlockGraph();
|
||||
resgraph.restoreXml(parser, factory);
|
||||
resgraph.restoreXml(decoder);
|
||||
resgraph.transferObjectRef(ingraph);
|
||||
}
|
||||
}
|
||||
|
@ -80,6 +80,7 @@ public class DecompileCallback {
|
||||
private Charset utf8Charset;
|
||||
private String nativeMessage;
|
||||
|
||||
private XmlDecodeLight lightDecoder;
|
||||
private InstructionBlock lastPseudoInstructionBlock;
|
||||
private Disassembler pseudoDisassembler;
|
||||
|
||||
@ -96,6 +97,7 @@ public class DecompileCallback {
|
||||
nativeMessage = null;
|
||||
debug = null;
|
||||
utf8Charset = Charset.availableCharsets().get(CharsetInfo.UTF8);
|
||||
lightDecoder = new XmlDecodeLight(addrfactory);
|
||||
}
|
||||
|
||||
private static SAXParser getSAXParser() throws PcodeXMLException {
|
||||
@ -170,8 +172,10 @@ public class DecompileCallback {
|
||||
|
||||
public byte[] getBytes(String addrxml) {
|
||||
try {
|
||||
Address addr = AddressXML.readXML(addrxml, addrfactory);
|
||||
int size = AddressXML.readXMLSize(addrxml);
|
||||
lightDecoder.ingestString(addrxml);
|
||||
lightDecoder.openElement();
|
||||
Address addr = AddressXML.decodeFromAttributes(lightDecoder);
|
||||
int size = (int) lightDecoder.readSignedInteger(AttributeId.ATTRIB_SIZE);
|
||||
if (overlaySpace != null) {
|
||||
addr = overlaySpace.getOverlayAddress(addr);
|
||||
}
|
||||
@ -220,7 +224,8 @@ public class DecompileCallback {
|
||||
Address addr;
|
||||
int flags;
|
||||
try {
|
||||
addr = AddressXML.readXML(addrstring, addrfactory);
|
||||
lightDecoder.ingestString(addrstring);
|
||||
addr = AddressXML.decode(lightDecoder);
|
||||
if (overlaySpace != null) {
|
||||
addr = overlaySpace.getOverlayAddress(addr);
|
||||
}
|
||||
@ -263,7 +268,8 @@ public class DecompileCallback {
|
||||
public PackedBytes getPcodePacked(String addrstring) {
|
||||
Address addr = null;
|
||||
try {
|
||||
addr = AddressXML.readXML(addrstring, addrfactory);
|
||||
lightDecoder.ingestString(addrstring);
|
||||
addr = AddressXML.decode(lightDecoder);
|
||||
if (overlaySpace != null) {
|
||||
addr = overlaySpace.getOverlayAddress(addr);
|
||||
}
|
||||
@ -351,7 +357,8 @@ public class DecompileCallback {
|
||||
InjectContext con = snippetLibrary.buildInjectContext();
|
||||
PcodeOp[] pcode;
|
||||
try {
|
||||
con.restoreXml(getSAXParser(), context, addrfactory);
|
||||
lightDecoder.ingestString(context);
|
||||
con.decode(lightDecoder);
|
||||
}
|
||||
catch (PcodeXMLException e) {
|
||||
Msg.error(this, "Decompiling " + funcEntry + ": " + e.getMessage());
|
||||
@ -484,7 +491,8 @@ public class DecompileCallback {
|
||||
public String getSymbol(String addrstring) { // Return first symbol name at this address
|
||||
Address addr;
|
||||
try {
|
||||
addr = AddressXML.readXML(addrstring, addrfactory);
|
||||
lightDecoder.ingestString(addrstring);
|
||||
addr = AddressXML.decode(lightDecoder);
|
||||
if (overlaySpace != null) {
|
||||
addr = overlaySpace.getOverlayAddress(addr);
|
||||
}
|
||||
@ -701,7 +709,8 @@ public class DecompileCallback {
|
||||
public String getMappedSymbolsXML(String addrstring) { // Return XML describing data or functions at addr
|
||||
Address addr;
|
||||
try {
|
||||
addr = AddressXML.readXML(addrstring, addrfactory);
|
||||
lightDecoder.ingestString(addrstring);
|
||||
addr = AddressXML.decode(lightDecoder);
|
||||
if (overlaySpace != null) {
|
||||
addr = overlaySpace.getOverlayAddress(addr);
|
||||
}
|
||||
@ -746,7 +755,8 @@ public class DecompileCallback {
|
||||
public String getExternalRefXML(String addrstring) { // Return any external reference at addr
|
||||
Address addr;
|
||||
try {
|
||||
addr = AddressXML.readXML(addrstring, addrfactory);
|
||||
lightDecoder.ingestString(addrstring);
|
||||
addr = AddressXML.decode(lightDecoder);
|
||||
if (overlaySpace != null) {
|
||||
addr = overlaySpace.getOverlayAddress(addr);
|
||||
}
|
||||
@ -809,8 +819,8 @@ public class DecompileCallback {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getType(String name, String idstr) {
|
||||
DataType type = dtmanage.findBaseType(name, idstr);
|
||||
public String getType(String name, long id) {
|
||||
DataType type = dtmanage.findBaseType(name, id);
|
||||
if (type == null) {
|
||||
return null;
|
||||
}
|
||||
@ -836,9 +846,10 @@ public class DecompileCallback {
|
||||
|
||||
public String getRegisterName(String addrstring) {
|
||||
try {
|
||||
|
||||
Address addr = AddressXML.readXML(addrstring, addrfactory);
|
||||
int size = AddressXML.readXMLSize(addrstring);
|
||||
lightDecoder.ingestString(addrstring);
|
||||
lightDecoder.openElement();
|
||||
Address addr = AddressXML.decodeFromAttributes(lightDecoder);
|
||||
int size = (int) lightDecoder.readSignedInteger(AttributeId.ATTRIB_SIZE);
|
||||
Register reg = pcodelanguage.getRegister(addr, size);
|
||||
if (reg == null) {
|
||||
return null;
|
||||
@ -855,7 +866,8 @@ public class DecompileCallback {
|
||||
public String getTrackedRegisters(String addrstring) {
|
||||
Address addr;
|
||||
try {
|
||||
addr = AddressXML.readXML(addrstring, addrfactory);
|
||||
lightDecoder.ingestString(addrstring);
|
||||
addr = AddressXML.decode(lightDecoder);
|
||||
if (overlaySpace != null) {
|
||||
addr = overlaySpace.getOverlayAddress(addr);
|
||||
}
|
||||
@ -1312,12 +1324,14 @@ public class DecompileCallback {
|
||||
* @param dtId is the id associated with the character data-type
|
||||
* @return the UTF8 encoded byte array or null
|
||||
*/
|
||||
public StringData getStringData(String addrString, String dtName, String dtId) {
|
||||
public StringData getStringData(String addrString, String dtName, long dtId) {
|
||||
Address addr;
|
||||
int maxChars;
|
||||
try {
|
||||
addr = AddressXML.readXML(addrString, addrfactory);
|
||||
maxChars = AddressXML.readXMLSize(addrString);
|
||||
lightDecoder.ingestString(addrString);
|
||||
lightDecoder.openElement();
|
||||
addr = AddressXML.decodeFromAttributes(lightDecoder);
|
||||
maxChars = (int) lightDecoder.readSignedInteger(AttributeId.ATTRIB_SIZE);
|
||||
if (overlaySpace != null) {
|
||||
addr = overlaySpace.getOverlayAddress(addr);
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ import ghidra.program.model.lang.PackedBytes;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.timer.GTimer;
|
||||
import ghidra.util.timer.GTimerMonitor;
|
||||
import ghidra.util.xml.SpecXmlUtils;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -787,7 +788,7 @@ public class DecompileProcess {
|
||||
|
||||
private void getType() throws IOException {
|
||||
String name = readQueryString();
|
||||
String id = readQueryString();
|
||||
long id = SpecXmlUtils.decodeLong(readQueryString());
|
||||
String res = callback.getType(name, id);
|
||||
write(query_response_start);
|
||||
if ((res != null) && (res.length() != 0)) {
|
||||
@ -816,7 +817,7 @@ public class DecompileProcess {
|
||||
private void getStringData() throws IOException {
|
||||
String addr = readQueryString();
|
||||
String dtName = readQueryString();
|
||||
String dtId = readQueryString();
|
||||
long dtId = SpecXmlUtils.decodeLong(readQueryString());
|
||||
DecompileCallback.StringData stringData = callback.getStringData(addr, dtName, dtId);
|
||||
write(query_response_start);
|
||||
if (stringData != null) {
|
||||
|
@ -21,8 +21,6 @@ import ghidra.program.model.lang.CompilerSpec;
|
||||
import ghidra.program.model.lang.Language;
|
||||
import ghidra.program.model.listing.Function;
|
||||
import ghidra.program.model.pcode.*;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
|
||||
/**
|
||||
* Class for getting at the various structures returned
|
||||
@ -75,7 +73,7 @@ public class DecompileResults {
|
||||
hparamid = null;
|
||||
docroot = null;
|
||||
//dumpResults(raw);
|
||||
parseRawString(raw);
|
||||
decodeStream(raw);
|
||||
}
|
||||
|
||||
// private void dumpResults(String raw) {
|
||||
@ -203,63 +201,57 @@ public class DecompileResults {
|
||||
return printer.print(true);
|
||||
}
|
||||
|
||||
private void parseRawString(InputStream rawxml) {
|
||||
if (rawxml == null) {
|
||||
private void decodeStream(InputStream rawstream) {
|
||||
if (rawstream == null) {
|
||||
return;
|
||||
}
|
||||
XmlPullParser parser = null;
|
||||
XmlDecode decoder = new XmlDecode(function.getProgram().getAddressFactory());
|
||||
try {
|
||||
try {
|
||||
parser =
|
||||
HighFunction.stringTree(
|
||||
rawxml,
|
||||
HighFunction.getErrorHandler(this, "decompiler results for function at " +
|
||||
function.getEntryPoint()));
|
||||
hfunc = null;
|
||||
hparamid = null;
|
||||
docroot = null;
|
||||
parser.start("doc");
|
||||
while(parser.peek().isStart()) {
|
||||
XmlElement el = parser.peek();
|
||||
if (el.getName().equals("function")) {
|
||||
if (hfunc == null) {
|
||||
hfunc = new HighFunction(function, language, compilerSpec, dtmanage);
|
||||
hfunc.readXML(parser);
|
||||
}
|
||||
else { // TODO: This is an ugly kludge to get around duplicate XML tag names
|
||||
docroot = ClangXML.buildClangTree(parser, hfunc);
|
||||
if (docroot == null) {
|
||||
errMsg = "Unable to parse C (xml)";
|
||||
}
|
||||
}
|
||||
decoder.ingestStream(rawstream,
|
||||
"Decompiler results for function at " + function.getEntryPoint());
|
||||
hfunc = null;
|
||||
hparamid = null;
|
||||
docroot = null;
|
||||
int docel = decoder.openElement(ElementId.ELEM_DOC);
|
||||
for (;;) {
|
||||
int el = decoder.peekElement();
|
||||
if (el == 0) {
|
||||
break;
|
||||
}
|
||||
if (el == ElementId.ELEM_FUNCTION.getId()) {
|
||||
if (hfunc == null) {
|
||||
hfunc = new HighFunction(function, language, compilerSpec, dtmanage);
|
||||
hfunc.decode(decoder);
|
||||
}
|
||||
else if (el.getName().equals("parammeasures")) {
|
||||
hparamid = new HighParamID(function, language, compilerSpec, dtmanage);
|
||||
hparamid.readXML(parser);
|
||||
}
|
||||
else {
|
||||
errMsg = "Unknown decompiler tag: "+el.getName();
|
||||
return;
|
||||
else { // TODO: This is an ugly kludge to get around duplicate XML tag names
|
||||
docroot = ClangMarkup.buildClangTree(decoder, hfunc);
|
||||
if (docroot == null) {
|
||||
errMsg = "Unable to decode C markup";
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (el == ElementId.ELEM_PARAMMEASURES.getId()) {
|
||||
hparamid = new HighParamID(function, language, compilerSpec, dtmanage);
|
||||
hparamid.decode(decoder);
|
||||
}
|
||||
else {
|
||||
errMsg = "Unknown decompiler tag";
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (PcodeXMLException e) { // Error while walking the DOM
|
||||
errMsg = e.getMessage();
|
||||
hfunc = null;
|
||||
hparamid = null;
|
||||
return;
|
||||
}
|
||||
catch (RuntimeException e) { // Exception from the raw parser
|
||||
errMsg = e.getMessage();
|
||||
hfunc = null;
|
||||
hparamid = null;
|
||||
return;
|
||||
}
|
||||
decoder.closeElement(docel);
|
||||
}
|
||||
finally {
|
||||
if (parser != null) {
|
||||
parser.dispose();
|
||||
}
|
||||
catch (PcodeXMLException e) { // Error while walking the DOM
|
||||
errMsg = e.getMessage();
|
||||
hfunc = null;
|
||||
hparamid = null;
|
||||
return;
|
||||
}
|
||||
catch (RuntimeException e) { // Exception from the raw parser
|
||||
errMsg = e.getMessage();
|
||||
hfunc = null;
|
||||
hparamid = null;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -340,7 +340,7 @@ public class ClangLayoutController implements LayoutModel, LayoutModelListener {
|
||||
ClangTokenGroup line = new ClangTokenGroup(docroot);
|
||||
ClangBreak lineBreak = new ClangBreak(line, 1);
|
||||
ClangSyntaxToken message =
|
||||
new ClangSyntaxToken(line, errline, ClangXML.COMMENT_COLOR);
|
||||
new ClangSyntaxToken(line, errline, ClangMarkup.COMMENT_COLOR);
|
||||
line.AddTokenGroup(lineBreak);
|
||||
line.AddTokenGroup(message);
|
||||
docroot.AddTokenGroup(line);
|
||||
|
@ -15,73 +15,13 @@
|
||||
*/
|
||||
package ghidra.program.model.lang;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import javax.xml.parsers.SAXParser;
|
||||
|
||||
import org.xml.sax.*;
|
||||
import org.xml.sax.helpers.DefaultHandler;
|
||||
|
||||
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressFactory;
|
||||
import ghidra.program.model.pcode.*;
|
||||
import ghidra.util.xml.SpecXmlUtils;
|
||||
|
||||
public class InjectContext {
|
||||
private class Handler extends DefaultHandler {
|
||||
private AddressFactory addrFactory;
|
||||
private Address curaddr;
|
||||
private int state;
|
||||
|
||||
Handler(AddressFactory adFact) {
|
||||
super();
|
||||
state = 0;
|
||||
addrFactory = adFact;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startElement(String uri, String localName, String rawName, Attributes attr)
|
||||
throws SAXException {
|
||||
if (rawName.equals("context")) {
|
||||
state = 1;
|
||||
}
|
||||
else if (rawName.equals("input")) {
|
||||
inputlist = new ArrayList<>();
|
||||
state = 3;
|
||||
}
|
||||
else if (rawName.equals("output")) {
|
||||
output = new ArrayList<>();
|
||||
state = 4;
|
||||
}
|
||||
else if (rawName.equals("addr")) {
|
||||
curaddr = AddressXML.readXML(rawName, attr, addrFactory);
|
||||
if (state == 1) {
|
||||
baseAddr = curaddr;
|
||||
state = 2;
|
||||
}
|
||||
else if (state == 2) {
|
||||
callAddr = curaddr;
|
||||
}
|
||||
else if (state == 3) {
|
||||
int size = SpecXmlUtils.decodeInt(attr.getValue("size"));
|
||||
Varnode vn = new Varnode(curaddr, size);
|
||||
inputlist.add(vn);
|
||||
}
|
||||
else if (state == 4) {
|
||||
int size = SpecXmlUtils.decodeInt(attr.getValue("size"));
|
||||
Varnode vn = new Varnode(curaddr, size);
|
||||
output.add(vn);
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new SAXException("Unrecognized inject tag: " + rawName);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public SleighLanguage language;
|
||||
public Address baseAddr; // Base address of op (call,userop) causing the inject
|
||||
@ -94,18 +34,44 @@ public class InjectContext {
|
||||
public InjectContext() {
|
||||
}
|
||||
|
||||
public void restoreXml(SAXParser parser, String xml, AddressFactory addrFactory)
|
||||
throws PcodeXMLException {
|
||||
Handler handler = new Handler(addrFactory);
|
||||
try {
|
||||
parser.parse(new InputSource(new StringReader(xml)), handler);
|
||||
public void decode(Decoder decoder) throws PcodeXMLException {
|
||||
int el = decoder.openElement(ElementId.ELEM_CONTEXT);
|
||||
baseAddr = AddressXML.decode(decoder);
|
||||
callAddr = AddressXML.decode(decoder);
|
||||
int subel = decoder.peekElement();
|
||||
if (subel == ElementId.ELEM_INPUT.getId()) {
|
||||
decoder.openElement();
|
||||
inputlist = new ArrayList<>();
|
||||
for (;;) {
|
||||
int addrel = decoder.peekElement();
|
||||
if (addrel == 0) {
|
||||
break;
|
||||
}
|
||||
decoder.openElement();
|
||||
Address addr = AddressXML.decodeFromAttributes(decoder);
|
||||
int size = (int) decoder.readSignedInteger(AttributeId.ATTRIB_SIZE);
|
||||
decoder.closeElement(addrel);
|
||||
inputlist.add(new Varnode(addr, size));
|
||||
}
|
||||
decoder.closeElement(subel);
|
||||
subel = decoder.peekElement();
|
||||
}
|
||||
catch (SAXException e) {
|
||||
throw new PcodeXMLException("Problem parsing inject context: " + e.getMessage());
|
||||
if (subel == ElementId.ELEM_OUTPUT.getId()) {
|
||||
decoder.openElement();
|
||||
output = new ArrayList<>();
|
||||
for (;;) {
|
||||
int addrel = decoder.peekElement();
|
||||
if (addrel == 0) {
|
||||
break;
|
||||
}
|
||||
decoder.openElement();
|
||||
Address addr = AddressXML.decodeFromAttributes(decoder);
|
||||
int size = (int) decoder.readSignedInteger(AttributeId.ATTRIB_SIZE);
|
||||
decoder.closeElement(addrel);
|
||||
output.add(new Varnode(addr, size));
|
||||
}
|
||||
decoder.closeElement(subel);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new PcodeXMLException("Problem parsing inject context: " + e.getMessage());
|
||||
}
|
||||
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
}
|
||||
|
@ -17,9 +17,8 @@ package ghidra.program.model.pcode;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.xml.sax.Attributes;
|
||||
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressSpace;
|
||||
import ghidra.program.model.lang.*;
|
||||
import ghidra.util.xml.SpecXmlUtils;
|
||||
import ghidra.xml.XmlElement;
|
||||
@ -358,155 +357,74 @@ public class AddressXML {
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse String containing an XML tag representing an Address.
|
||||
* The format options are simple enough that we don't try to invoke
|
||||
* an actual XML parser but just walk the string. This recognizes
|
||||
* - \<addr>
|
||||
* - \<spaceid> or
|
||||
* - any tag with a "space" and "offset" attribute
|
||||
*
|
||||
* @param addrstring is the string containing the XML tag
|
||||
* @param addrfactory is the factory that can produce addresses
|
||||
* @return the created Address or Address.NO_ADDRESS in some special cases
|
||||
* @throws PcodeXMLException for a badly formed Address
|
||||
* Create an address from "space" and "offset" attributes of the current element
|
||||
* @param decoder is the stream decoder
|
||||
* @return the decoded Address
|
||||
* @throws PcodeXMLException for any problems decoding the stream
|
||||
*/
|
||||
public static Address readXML(String addrstring, AddressFactory addrfactory)
|
||||
throws PcodeXMLException {
|
||||
|
||||
int tagstart = addrstring.indexOf('<');
|
||||
if (tagstart >= 0) {
|
||||
tagstart += 1;
|
||||
if (addrstring.startsWith("spaceid", tagstart)) {
|
||||
tagstart += 8;
|
||||
int attrstart = addrstring.indexOf("name=\"", tagstart);
|
||||
if (attrstart >= 0) {
|
||||
attrstart += 6;
|
||||
int nameend = addrstring.indexOf('\"', attrstart);
|
||||
if (nameend >= 0) {
|
||||
AddressSpace spc =
|
||||
addrfactory.getAddressSpace(addrstring.substring(attrstart, nameend));
|
||||
int spaceid = spc.getSpaceID();
|
||||
spc = addrfactory.getConstantSpace();
|
||||
return spc.getAddress(spaceid);
|
||||
}
|
||||
}
|
||||
|
||||
public static Address decodeFromAttributes(Decoder decoder) throws PcodeXMLException {
|
||||
AddressSpace spc = null;
|
||||
long offset = -1;
|
||||
for (;;) {
|
||||
int attribId = decoder.getNextAttributeId();
|
||||
if (attribId == 0) {
|
||||
break;
|
||||
}
|
||||
// There are several tag forms where we essentially want to just look for 'space' and 'offset' attributes
|
||||
// don't explicitly check the tag name
|
||||
int spacestart = addrstring.indexOf("space=\"");
|
||||
if (spacestart >= 4) {
|
||||
spacestart += 7;
|
||||
int spaceend = addrstring.indexOf('"', spacestart);
|
||||
if (spaceend >= spacestart) {
|
||||
String spcname = addrstring.substring(spacestart, spaceend);
|
||||
int offstart = addrstring.indexOf("offset=\"");
|
||||
if (offstart >= 4) {
|
||||
offstart += 8;
|
||||
int offend = addrstring.indexOf('"', offstart);
|
||||
if (offend >= offstart) {
|
||||
String offstr = addrstring.substring(offstart, offend);
|
||||
AddressSpace spc = addrfactory.getAddressSpace(spcname);
|
||||
// Unknown spaces may result from "spacebase" registers defined in cspec
|
||||
if (spc == null) {
|
||||
return Address.NO_ADDRESS;
|
||||
}
|
||||
long offset = SpecXmlUtils.decodeLong(offstr);
|
||||
return spc.getAddress(offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (attribId == AttributeId.ATTRIB_SPACE.getId()) {
|
||||
spc = decoder.readSpace();
|
||||
}
|
||||
else if (attribId == AttributeId.ATTRIB_OFFSET.getId()) {
|
||||
offset = decoder.readUnsignedInteger();
|
||||
}
|
||||
}
|
||||
throw new PcodeXMLException("Badly formed address: " + addrstring);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the (first) size attribute from an XML tag string as an integer
|
||||
* @param addrxml is the XML string
|
||||
* @return the decoded integer or zero if the attribute doesn't exist
|
||||
*/
|
||||
public static int readXMLSize(String addrxml) {
|
||||
int attrstart = addrxml.indexOf("size=\"");
|
||||
if (attrstart >= 4) {
|
||||
attrstart += 6;
|
||||
int attrend = addrxml.indexOf('\"', attrstart);
|
||||
if (attrend > attrstart) {
|
||||
int size = SpecXmlUtils.decodeInt(addrxml.substring(attrstart, attrend));
|
||||
return size;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an address from an XML parse tree node. This recognizes XML tags
|
||||
* - \<addr>
|
||||
* - \<spaceid>
|
||||
* - \<iop> or
|
||||
* - any tag with "space" and "offset" attributes
|
||||
*
|
||||
* An empty \<addr> tag, with no attributes, results in Address.NO_ADDRESS being returned.
|
||||
* @param el is the parse tree element
|
||||
* @param addrFactory address factory used to create valid addresses
|
||||
* @return Address created from XML info
|
||||
*/
|
||||
public static Address readXML(XmlElement el, AddressFactory addrFactory) {
|
||||
String localName = el.getName();
|
||||
if (localName.equals("spaceid")) {
|
||||
AddressSpace spc = addrFactory.getAddressSpace(el.getAttribute("name"));
|
||||
int spaceid = spc.getSpaceID();
|
||||
spc = addrFactory.getConstantSpace();
|
||||
return spc.getAddress(spaceid);
|
||||
}
|
||||
else if (localName.equals("iop")) {
|
||||
int ref = SpecXmlUtils.decodeInt(el.getAttribute("value"));
|
||||
AddressSpace spc = addrFactory.getConstantSpace();
|
||||
return spc.getAddress(ref);
|
||||
}
|
||||
String space = el.getAttribute("space");
|
||||
if (space == null) {
|
||||
return Address.NO_ADDRESS;
|
||||
}
|
||||
long offset = SpecXmlUtils.decodeLong(el.getAttribute("offset"));
|
||||
AddressSpace spc = addrFactory.getAddressSpace(space);
|
||||
if (spc == null) {
|
||||
return null;
|
||||
return Address.NO_ADDRESS;
|
||||
}
|
||||
return spc.getAddress(offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read an Address given an XML tag name and its attributes. This recognizes XML tags
|
||||
* Create an address from a stream encoding. This recognizes elements
|
||||
* - \<addr>
|
||||
* - \<spaceid>
|
||||
* - \<iop>
|
||||
* - any tag with "space" or "offset" attributes
|
||||
* - \<iop> or
|
||||
* - any element with "space" and "offset" attributes
|
||||
*
|
||||
* An empty \<addr> tag, with no attributes, results in Address.NO_ADDRESS being returned.
|
||||
* @param localName is the name of the tag
|
||||
* @param attr is the collection of attributes for the tag
|
||||
* @param addrFactory is an Address factory
|
||||
* @return the scanned address
|
||||
* An empty \<addr> element, with no attributes, results in Address.NO_ADDRESS being returned.
|
||||
* @param decoder is the stream decoder
|
||||
* @return Address created from XML info
|
||||
* @throws PcodeXMLException for any problems decoding the stream
|
||||
*/
|
||||
public static Address readXML(String localName, Attributes attr, AddressFactory addrFactory) {
|
||||
if (localName.equals("spaceid")) {
|
||||
AddressSpace spc = addrFactory.getAddressSpace(attr.getValue("name"));
|
||||
public static Address decode(Decoder decoder) throws PcodeXMLException {
|
||||
int el = decoder.openElement();
|
||||
if (el == ElementId.ELEM_SPACEID.getId()) {
|
||||
AddressSpace spc = decoder.readSpace(AttributeId.ATTRIB_NAME);
|
||||
decoder.closeElement(el);
|
||||
int spaceid = spc.getSpaceID();
|
||||
spc = addrFactory.getConstantSpace();
|
||||
spc = decoder.getAddressFactory().getConstantSpace();
|
||||
return spc.getAddress(spaceid);
|
||||
}
|
||||
else if (localName.equals("iop")) {
|
||||
int ref = SpecXmlUtils.decodeInt(attr.getValue("value"));
|
||||
AddressSpace spc = addrFactory.getConstantSpace();
|
||||
else if (el == ElementId.ELEM_IOP.getId()) {
|
||||
int ref = (int) decoder.readUnsignedInteger(AttributeId.ATTRIB_VALUE);
|
||||
decoder.closeElement(el);
|
||||
AddressSpace spc = decoder.getAddressFactory().getConstantSpace();
|
||||
return spc.getAddress(ref);
|
||||
}
|
||||
String space = attr.getValue("space");
|
||||
if (space == null) {
|
||||
return Address.NO_ADDRESS;
|
||||
AddressSpace spc = null;
|
||||
long offset = -1;
|
||||
for (;;) {
|
||||
int attribId = decoder.getNextAttributeId();
|
||||
if (attribId == 0) {
|
||||
break;
|
||||
}
|
||||
if (attribId == AttributeId.ATTRIB_SPACE.getId()) {
|
||||
spc = decoder.readSpace();
|
||||
}
|
||||
else if (attribId == AttributeId.ATTRIB_OFFSET.getId()) {
|
||||
offset = decoder.readUnsignedInteger();
|
||||
}
|
||||
}
|
||||
long offset = SpecXmlUtils.decodeLong(attr.getValue("offset"));
|
||||
AddressSpace spc = addrFactory.getAddressSpace(space);
|
||||
decoder.closeElement(el);
|
||||
if (spc == null) {
|
||||
return Address.NO_ADDRESS;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
@ -17,7 +17,6 @@ package ghidra.program.model.pcode;
|
||||
|
||||
import ghidra.program.model.lang.UnknownInstructionException;
|
||||
import ghidra.util.xml.SpecXmlUtils;
|
||||
import ghidra.xml.XmlElement;
|
||||
|
||||
/**
|
||||
* Block representing and '&&' or '||' control flow path within a conditional expression
|
||||
@ -30,13 +29,13 @@ import ghidra.xml.XmlElement;
|
||||
*/
|
||||
public class BlockCondition extends BlockGraph {
|
||||
private int opcode; // Type of boolean operation
|
||||
|
||||
|
||||
public BlockCondition() {
|
||||
super();
|
||||
blocktype = PcodeBlock.CONDITION;
|
||||
opcode = PcodeOp.BOOL_AND;
|
||||
}
|
||||
|
||||
|
||||
public int getOpcode() {
|
||||
return opcode;
|
||||
}
|
||||
@ -45,17 +44,18 @@ public class BlockCondition extends BlockGraph {
|
||||
public void saveXmlHeader(StringBuilder buffer) {
|
||||
super.saveXmlHeader(buffer);
|
||||
String opcodename = PcodeOp.getMnemonic(opcode);
|
||||
SpecXmlUtils.encodeStringAttribute(buffer, "opcode", opcodename);
|
||||
SpecXmlUtils.encodeStringAttribute(buffer, "opcode", opcodename);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreXmlHeader(XmlElement el) throws PcodeXMLException {
|
||||
super.restoreXmlHeader(el);
|
||||
String opcodename = el.getAttribute("opcode");
|
||||
public void decodeHeader(Decoder decoder) throws PcodeXMLException {
|
||||
super.decodeHeader(decoder);
|
||||
String opcodename = decoder.readString(AttributeId.ATTRIB_OPCODE);
|
||||
try {
|
||||
opcode = PcodeOp.getOpcode(opcodename);
|
||||
} catch (UnknownInstructionException e) {
|
||||
}
|
||||
catch (UnknownInstructionException e) {
|
||||
opcode = PcodeOp.BOOL_AND;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,6 @@ package ghidra.program.model.pcode;
|
||||
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.util.xml.SpecXmlUtils;
|
||||
import ghidra.xml.XmlElement;
|
||||
|
||||
/**
|
||||
* Placeholder for a basic block (BlockBasic) within a structured
|
||||
@ -29,15 +28,15 @@ public class BlockCopy extends PcodeBlock {
|
||||
private Object ref; // Reference to basic block of which this is a copy
|
||||
private Address address; // Address upon entry to the basic block
|
||||
private int altindex; // Alternate index for correlating this block with result structure
|
||||
|
||||
|
||||
public BlockCopy() {
|
||||
super();
|
||||
blocktype = PcodeBlock.COPY;
|
||||
address = Address.NO_ADDRESS;
|
||||
ref = null;
|
||||
}
|
||||
|
||||
public BlockCopy(Object r,Address addr) {
|
||||
|
||||
public BlockCopy(Object r, Address addr) {
|
||||
super();
|
||||
ref = r;
|
||||
blocktype = PcodeBlock.COPY;
|
||||
@ -60,7 +59,7 @@ public class BlockCopy extends PcodeBlock {
|
||||
public Object getRef() {
|
||||
return ref;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Used (by BlockGraph.transferObjectRef) to reset the internal Object and Address
|
||||
* @param r is the internal Object
|
||||
@ -85,8 +84,8 @@ public class BlockCopy extends PcodeBlock {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreXmlHeader(XmlElement el) throws PcodeXMLException {
|
||||
super.restoreXmlHeader(el);
|
||||
altindex = SpecXmlUtils.decodeInt(el.getAttribute("altindex"));
|
||||
public void decodeHeader(Decoder decoder) throws PcodeXMLException {
|
||||
super.decodeHeader(decoder);
|
||||
altindex = (int) decoder.readSignedInteger(AttributeId.ATTRIB_ALTINDEX);
|
||||
}
|
||||
}
|
||||
|
@ -19,8 +19,6 @@ import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
|
||||
import ghidra.util.xml.SpecXmlUtils;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
|
||||
/**
|
||||
* A "plain" goto block
|
||||
@ -32,22 +30,22 @@ import ghidra.xml.XmlPullParser;
|
||||
public class BlockGoto extends BlockGraph {
|
||||
private PcodeBlock gototarget;
|
||||
private int gototype; // Type of goto (1=plaingoto 2=break 4=continue)
|
||||
|
||||
|
||||
public BlockGoto() {
|
||||
super();
|
||||
gototarget = null;
|
||||
gototype = 1;
|
||||
blocktype = PcodeBlock.GOTO;
|
||||
}
|
||||
|
||||
|
||||
public PcodeBlock getGotoTarget() {
|
||||
return gototarget;
|
||||
}
|
||||
|
||||
|
||||
public int getGotoType() {
|
||||
return gototype;
|
||||
}
|
||||
|
||||
|
||||
public void setGotoTarget(PcodeBlock gt) {
|
||||
gototarget = gt;
|
||||
}
|
||||
@ -67,13 +65,13 @@ public class BlockGoto extends BlockGraph {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreXmlBody(XmlPullParser parser, BlockMap resolver) throws PcodeXMLException {
|
||||
super.restoreXmlBody(parser, resolver);
|
||||
XmlElement el = parser.start("target");
|
||||
int target = SpecXmlUtils.decodeInt(el.getAttribute("index"));
|
||||
int depth = SpecXmlUtils.decodeInt(el.getAttribute("depth"));
|
||||
gototype = SpecXmlUtils.decodeInt(el.getAttribute("type"));
|
||||
parser.end(el);
|
||||
public void decodeBody(Decoder decoder, BlockMap resolver) throws PcodeXMLException {
|
||||
super.decodeBody(decoder, resolver);
|
||||
int el = decoder.openElement(ElementId.ELEM_TARGET);
|
||||
int target = (int) decoder.readSignedInteger(AttributeId.ATTRIB_INDEX);
|
||||
int depth = (int) decoder.readSignedInteger(AttributeId.ATTRIB_DEPTH);
|
||||
gototype = (int) decoder.readUnsignedInteger(AttributeId.ATTRIB_TYPE);
|
||||
decoder.closeElement(el);
|
||||
resolver.addGotoRef(this, target, depth);
|
||||
}
|
||||
}
|
||||
|
@ -19,10 +19,7 @@ import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import ghidra.program.model.address.AddressFactory;
|
||||
import ghidra.util.xml.SpecXmlUtils;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
|
||||
/**
|
||||
* A block (with in edges and out edges) that contains other blocks
|
||||
@ -31,23 +28,23 @@ import ghidra.xml.XmlPullParser;
|
||||
public class BlockGraph extends PcodeBlock {
|
||||
private ArrayList<PcodeBlock> list; // List of blocks within the super-block
|
||||
private int maxindex; // -index- contains minimum -maxindex- contains max
|
||||
|
||||
|
||||
public BlockGraph() {
|
||||
super();
|
||||
blocktype = PcodeBlock.GRAPH;
|
||||
list = new ArrayList<PcodeBlock>();
|
||||
list = new ArrayList<>();
|
||||
maxindex = -1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add a block to this container. There are (initially) no edges between
|
||||
* it and any other block in the container.
|
||||
* @param bl is the new block to add
|
||||
*/
|
||||
public void addBlock(PcodeBlock bl) {
|
||||
int min,max;
|
||||
int min, max;
|
||||
if (bl instanceof BlockGraph) {
|
||||
BlockGraph gbl = (BlockGraph)bl;
|
||||
BlockGraph gbl = (BlockGraph) bl;
|
||||
min = gbl.index;
|
||||
max = gbl.maxindex;
|
||||
}
|
||||
@ -55,16 +52,18 @@ public class BlockGraph extends PcodeBlock {
|
||||
min = bl.index;
|
||||
max = min;
|
||||
}
|
||||
|
||||
|
||||
if (list.isEmpty()) {
|
||||
index = min;
|
||||
maxindex = max;
|
||||
}
|
||||
else {
|
||||
if (min < index)
|
||||
if (min < index) {
|
||||
index = min;
|
||||
if (max > maxindex)
|
||||
}
|
||||
if (max > maxindex) {
|
||||
maxindex = max;
|
||||
}
|
||||
}
|
||||
bl.parent = this;
|
||||
list.add(bl);
|
||||
@ -75,24 +74,24 @@ public class BlockGraph extends PcodeBlock {
|
||||
* getBlock(i) will return the block that satisfies block.getIndex() == i
|
||||
*/
|
||||
public void setIndices() {
|
||||
for(int i=0;i<list.size();++i) {
|
||||
for (int i = 0; i < list.size(); ++i) {
|
||||
list.get(i).index = i;
|
||||
}
|
||||
index = 0;
|
||||
maxindex = list.size()-1;
|
||||
maxindex = list.size() - 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the number of blocks in this container
|
||||
*/
|
||||
public int getSize() {
|
||||
return list.size();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve the i-th block from this container
|
||||
* @param i is the index of the block to fetch
|
||||
* @return
|
||||
* @return the block
|
||||
*/
|
||||
public PcodeBlock getBlock(int i) {
|
||||
return list.get(i);
|
||||
@ -103,7 +102,7 @@ public class BlockGraph extends PcodeBlock {
|
||||
* @param begin is the "from" block of the edge
|
||||
* @param end is the "to" block of the edge
|
||||
*/
|
||||
public void addEdge(PcodeBlock begin,PcodeBlock end) {
|
||||
public void addEdge(PcodeBlock begin, PcodeBlock end) {
|
||||
end.addInEdge(begin, 0);
|
||||
}
|
||||
|
||||
@ -114,7 +113,7 @@ public class BlockGraph extends PcodeBlock {
|
||||
* @param ingraph is the original flow graph
|
||||
*/
|
||||
public void transferObjectRef(BlockGraph ingraph) {
|
||||
ArrayList<BlockGraph> queue = new ArrayList<BlockGraph>();
|
||||
ArrayList<BlockGraph> queue = new ArrayList<>();
|
||||
int pos = 0;
|
||||
queue.add(this);
|
||||
while (pos < queue.size()) {
|
||||
@ -134,8 +133,9 @@ public class BlockGraph extends PcodeBlock {
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (block instanceof BlockGraph)
|
||||
else if (block instanceof BlockGraph) {
|
||||
queue.add((BlockGraph) block);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -143,8 +143,7 @@ public class BlockGraph extends PcodeBlock {
|
||||
@Override
|
||||
public void saveXmlBody(Writer writer) throws IOException {
|
||||
super.saveXmlBody(writer);
|
||||
for(int i=0;i<list.size();++i) {
|
||||
PcodeBlock bl = list.get(i);
|
||||
for (PcodeBlock bl : list) {
|
||||
StringBuilder buf = new StringBuilder();
|
||||
buf.append("<bhead");
|
||||
SpecXmlUtils.encodeSignedIntegerAttribute(buf, "index", bl.getIndex());
|
||||
@ -153,44 +152,43 @@ public class BlockGraph extends PcodeBlock {
|
||||
buf.append("/>\n");
|
||||
writer.write(buf.toString());
|
||||
}
|
||||
for(int i=0;i<list.size();++i) {
|
||||
PcodeBlock bl = list.get(i);
|
||||
for (PcodeBlock bl : list) {
|
||||
bl.saveXml(writer);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreXmlBody(XmlPullParser parser, BlockMap resolver) throws PcodeXMLException {
|
||||
public void decodeBody(Decoder decoder, BlockMap resolver) throws PcodeXMLException {
|
||||
BlockMap newresolver = new BlockMap(resolver);
|
||||
super.restoreXmlBody(parser, newresolver);
|
||||
ArrayList<PcodeBlock> tmplist = new ArrayList<PcodeBlock>();
|
||||
while(parser.peek().isStart()) {
|
||||
if (!parser.peek().getName().equals("bhead"))
|
||||
super.decodeBody(decoder, newresolver);
|
||||
ArrayList<PcodeBlock> tmplist = new ArrayList<>();
|
||||
for (;;) {
|
||||
int el = decoder.peekElement();
|
||||
if (el != ElementId.ELEM_BHEAD.getId()) {
|
||||
break;
|
||||
XmlElement el = parser.start();
|
||||
int ind = SpecXmlUtils.decodeInt(el.getAttribute("index"));
|
||||
String name = el.getAttribute("type");
|
||||
}
|
||||
decoder.openElement();
|
||||
int ind = (int) decoder.readSignedInteger(AttributeId.ATTRIB_INDEX);
|
||||
String name = decoder.readString(AttributeId.ATTRIB_TYPE);
|
||||
PcodeBlock newbl = newresolver.createBlock(name, ind);
|
||||
tmplist.add(newbl);
|
||||
parser.end(el);
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
newresolver.sortLevelList();
|
||||
for(int i=0;i<tmplist.size();++i) {
|
||||
PcodeBlock bl = tmplist.get(i);
|
||||
bl.restoreXml(parser, newresolver);
|
||||
for (PcodeBlock bl : tmplist) {
|
||||
bl.decode(decoder, newresolver);
|
||||
addBlock(bl);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore all blocks and edges in this container from an XML stream.
|
||||
* @param parser is the XML stream parser
|
||||
* @param factory is the AddressFactory used to construct any Address
|
||||
* @throws PcodeXMLException if part of the XML description is invalid
|
||||
* Decode all blocks and edges in this container from a stream.
|
||||
* @param decoder is the stream decoder
|
||||
* @throws PcodeXMLException if there are invalid encodings
|
||||
*/
|
||||
public void restoreXml(XmlPullParser parser, AddressFactory factory) throws PcodeXMLException {
|
||||
BlockMap resolver = new BlockMap(factory);
|
||||
restoreXml(parser,resolver);
|
||||
public void restoreXml(Decoder decoder) throws PcodeXMLException {
|
||||
BlockMap resolver = new BlockMap(decoder.getAddressFactory());
|
||||
decode(decoder, resolver);
|
||||
resolver.resolveGotoReferences();
|
||||
}
|
||||
}
|
||||
|
@ -19,8 +19,6 @@ import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
|
||||
import ghidra.util.xml.SpecXmlUtils;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
|
||||
/**
|
||||
* Block representing an if () goto control flow
|
||||
@ -35,22 +33,22 @@ import ghidra.xml.XmlPullParser;
|
||||
public class BlockIfGoto extends BlockGraph {
|
||||
private PcodeBlock gototarget;
|
||||
private int gototype; // type of goto 1=plaingoto 2=break 3=continue
|
||||
|
||||
|
||||
public BlockIfGoto() {
|
||||
super();
|
||||
blocktype = PcodeBlock.IFGOTO;
|
||||
gototarget = null;
|
||||
gototype = 1;
|
||||
}
|
||||
|
||||
|
||||
public void setGotoTarget(PcodeBlock bl) {
|
||||
gototarget = bl;
|
||||
}
|
||||
|
||||
|
||||
public PcodeBlock getGotoTarget() {
|
||||
return gototarget;
|
||||
}
|
||||
|
||||
|
||||
public int getGotoType() {
|
||||
return gototype;
|
||||
}
|
||||
@ -70,13 +68,13 @@ public class BlockIfGoto extends BlockGraph {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreXmlBody(XmlPullParser parser, BlockMap resolver) throws PcodeXMLException {
|
||||
super.restoreXmlBody(parser,resolver);
|
||||
XmlElement el = parser.start("target");
|
||||
int target = SpecXmlUtils.decodeInt(el.getAttribute("index"));
|
||||
int depth = SpecXmlUtils.decodeInt(el.getAttribute("depth"));
|
||||
gototype = SpecXmlUtils.decodeInt(el.getAttribute("type"));
|
||||
parser.end(el);
|
||||
public void decodeBody(Decoder decoder, BlockMap resolver) throws PcodeXMLException {
|
||||
super.decodeBody(decoder, resolver);
|
||||
int el = decoder.openElement(ElementId.ELEM_TARGET);
|
||||
int target = (int) decoder.readSignedInteger(AttributeId.ATTRIB_INDEX);
|
||||
int depth = (int) decoder.readSignedInteger(AttributeId.ATTRIB_DEPTH);
|
||||
gototype = (int) decoder.readUnsignedInteger(AttributeId.ATTRIB_TYPE);
|
||||
decoder.closeElement(el);
|
||||
gototarget = null;
|
||||
resolver.addGotoRef(this, target, depth);
|
||||
}
|
||||
|
@ -20,8 +20,6 @@ import java.io.Writer;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import ghidra.util.xml.SpecXmlUtils;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
|
||||
/**
|
||||
* A block representing a 2-or-more control flow branchpoint
|
||||
@ -35,23 +33,22 @@ import ghidra.xml.XmlPullParser;
|
||||
*/
|
||||
public class BlockMultiGoto extends BlockGraph {
|
||||
protected ArrayList<PcodeBlock> targets;
|
||||
|
||||
|
||||
public BlockMultiGoto() {
|
||||
super();
|
||||
targets = new ArrayList<PcodeBlock>();
|
||||
targets = new ArrayList<>();
|
||||
blocktype = PcodeBlock.MULTIGOTO;
|
||||
}
|
||||
|
||||
|
||||
public void addGotoTarget(PcodeBlock target) {
|
||||
targets.add(target);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void saveXmlBody(Writer writer) throws IOException {
|
||||
super.saveXmlBody(writer);
|
||||
for(int i=0;i<targets.size();++i) {
|
||||
|
||||
PcodeBlock gototarget = targets.get(i);
|
||||
for (PcodeBlock gototarget : targets) {
|
||||
|
||||
StringBuilder buf = new StringBuilder();
|
||||
buf.append("<target");
|
||||
PcodeBlock leaf = gototarget.getFrontLeaf();
|
||||
@ -65,14 +62,17 @@ public class BlockMultiGoto extends BlockGraph {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreXmlBody(XmlPullParser parser, BlockMap resolver) throws PcodeXMLException {
|
||||
super.restoreXmlBody(parser, resolver);
|
||||
while(parser.peek().isStart()) {
|
||||
XmlElement el = parser.start("target");
|
||||
int target = SpecXmlUtils.decodeInt(el.getAttribute("index"));
|
||||
int depth = SpecXmlUtils.decodeInt(el.getAttribute("depth"));
|
||||
// int gototype = SpecXmlUtils.decodeInt(el.getAttribute("type"));
|
||||
parser.end(el);
|
||||
public void decodeBody(Decoder decoder, BlockMap resolver) throws PcodeXMLException {
|
||||
super.decodeBody(decoder, resolver);
|
||||
for (;;) {
|
||||
int el = decoder.peekElement();
|
||||
if (el != ElementId.ELEM_TARGET.getId()) {
|
||||
break;
|
||||
}
|
||||
decoder.openElement();
|
||||
int target = (int) decoder.readSignedInteger(AttributeId.ATTRIB_INDEX);
|
||||
int depth = (int) decoder.readSignedInteger(AttributeId.ATTRIB_DEPTH);
|
||||
decoder.closeElement(el);
|
||||
resolver.addGotoRef(this, target, depth);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -21,9 +21,6 @@ import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.model.listing.VariableStorage;
|
||||
import ghidra.util.exception.AssertException;
|
||||
import ghidra.util.exception.InvalidInputException;
|
||||
import ghidra.util.xml.SpecXmlUtils;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
|
||||
/**
|
||||
* A HighSymbol mapping based on local hashing of the symbol's Varnode within a
|
||||
@ -63,11 +60,11 @@ public class DynamicEntry extends SymbolEntry {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreXML(XmlPullParser parser) throws PcodeXMLException {
|
||||
XmlElement addrel = parser.start("hash");
|
||||
hash = SpecXmlUtils.decodeLong(addrel.getAttribute("val"));
|
||||
parser.end(addrel);
|
||||
parseRangeList(parser);
|
||||
public void decode(Decoder decoder) throws PcodeXMLException {
|
||||
int addrel = decoder.openElement(ElementId.ELEM_HASH);
|
||||
hash = decoder.readUnsignedInteger(AttributeId.ATTRIB_VAL);
|
||||
decoder.closeElement(addrel);
|
||||
decodeRangeList(decoder);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -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);
|
||||
}
|
@ -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);
|
||||
}
|
@ -18,8 +18,6 @@ package ghidra.program.model.pcode;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.util.xml.SpecXmlUtils;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
|
||||
public class EquateSymbol extends HighSymbol {
|
||||
|
||||
@ -66,12 +64,22 @@ public class EquateSymbol extends HighSymbol {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreXML(XmlPullParser parser) throws PcodeXMLException {
|
||||
XmlElement symel = parser.start("equatesymbol");
|
||||
restoreXMLHeader(symel);
|
||||
public void decode(Decoder decoder) throws PcodeXMLException {
|
||||
int symel = decoder.openElement(ElementId.ELEM_EQUATESYMBOL);
|
||||
decodeHeader(decoder);
|
||||
type = DataType.DEFAULT;
|
||||
convert = FORMAT_DEFAULT;
|
||||
String formString = symel.getAttribute("format");
|
||||
decoder.rewindAttributes();
|
||||
String formString = null;
|
||||
for (;;) {
|
||||
int attribId = decoder.getNextAttributeId();
|
||||
if (attribId == 0) {
|
||||
break;
|
||||
}
|
||||
if (attribId == AttributeId.ATTRIB_FORMAT.getId()) {
|
||||
formString = decoder.readString();
|
||||
}
|
||||
}
|
||||
if (formString != null) {
|
||||
if (formString.equals("hex")) {
|
||||
convert = FORMAT_HEX;
|
||||
@ -89,9 +97,10 @@ public class EquateSymbol extends HighSymbol {
|
||||
convert = FORMAT_BIN;
|
||||
}
|
||||
}
|
||||
parser.start("value");
|
||||
value = SpecXmlUtils.decodeLong(parser.end().getText()); // End <value> tag
|
||||
parser.end(symel);
|
||||
int valel = decoder.openElement(ElementId.ELEM_VALUE);
|
||||
value = decoder.readUnsignedInteger(AttributeId.ATTRIB_CONTENT);
|
||||
decoder.closeElement(valel);
|
||||
decoder.closeElement(symel);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -21,8 +21,6 @@ import ghidra.program.model.listing.*;
|
||||
import ghidra.program.model.symbol.SourceType;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.xml.SpecXmlUtils;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -152,7 +150,7 @@ public class FunctionPrototype {
|
||||
if ((returnstorage == null) || (!returnstorage.isValid())) { // Unassigned or otherwise invalid storage
|
||||
outputlock = false;
|
||||
returnstorage = VariableStorage.VOID_STORAGE; // Treat as unlocked void
|
||||
returntype = DataType.VOID;
|
||||
returntype = VoidDataType.dataType;
|
||||
}
|
||||
voidinputlock =
|
||||
(f.getSignatureSource() != SourceType.DEFAULT) && f.getParameterCount() == 0;
|
||||
@ -413,22 +411,22 @@ public class FunctionPrototype {
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the function prototype from {@code <prototype>} tag.
|
||||
* @param parser is the XML document to parse
|
||||
* Decode the function prototype from a {@code <prototype>} element in the stream.
|
||||
* @param decoder is the stream decoder
|
||||
* @param dtmanage is the DataTypeManager used to parse data-type tags
|
||||
* @throws PcodeXMLException for any problems parsing
|
||||
* @throws PcodeXMLException for invalid encodings
|
||||
*/
|
||||
public void readPrototypeXML(XmlPullParser parser, PcodeDataTypeManager dtmanage)
|
||||
public void decodePrototype(Decoder decoder, PcodeDataTypeManager dtmanage)
|
||||
throws PcodeXMLException {
|
||||
XmlElement node = parser.start("prototype");
|
||||
modelname = node.getAttribute("model");
|
||||
int node = decoder.openElement(ElementId.ELEM_PROTOTYPE);
|
||||
modelname = decoder.readString(AttributeId.ATTRIB_MODEL);
|
||||
PrototypeModel protoModel =
|
||||
dtmanage.getProgram().getCompilerSpec().getCallingConvention(modelname);
|
||||
if (protoModel == null) {
|
||||
throw new PcodeXMLException("Bad prototype model name: " + modelname);
|
||||
}
|
||||
hasThis = protoModel.hasThisPointer();
|
||||
String val = node.getAttribute("extrapop");
|
||||
String val = decoder.readString(AttributeId.ATTRIB_EXTRAPOP);
|
||||
if (val.equals("unknown")) {
|
||||
extrapop = PrototypeModel.UNKNOWN_EXTRAPOP;
|
||||
}
|
||||
@ -436,52 +434,61 @@ public class FunctionPrototype {
|
||||
extrapop = SpecXmlUtils.decodeInt(val);
|
||||
}
|
||||
modellock = false;
|
||||
if (node.hasAttribute("modellock")) {
|
||||
modellock = SpecXmlUtils.decodeBoolean(node.getAttribute("modellock"));
|
||||
}
|
||||
dotdotdot = false;
|
||||
if (node.hasAttribute("dotdotdot")) {
|
||||
dotdotdot = SpecXmlUtils.decodeBoolean(node.getAttribute("dotdotdot"));
|
||||
}
|
||||
voidinputlock = false;
|
||||
if (node.hasAttribute("voidlock")) {
|
||||
voidinputlock = SpecXmlUtils.decodeBoolean(node.getAttribute("voidlock"));
|
||||
}
|
||||
isinline = false;
|
||||
if (node.hasAttribute("inline")) {
|
||||
isinline = SpecXmlUtils.decodeBoolean(node.getAttribute("inline"));
|
||||
}
|
||||
noreturn = false;
|
||||
if (node.hasAttribute("noreturn")) {
|
||||
noreturn = SpecXmlUtils.decodeBoolean(node.getAttribute("noreturn"));
|
||||
}
|
||||
custom = false;
|
||||
if (node.hasAttribute("custom")) {
|
||||
custom = SpecXmlUtils.decodeBoolean(node.getAttribute("custom"));
|
||||
}
|
||||
isConstruct = false;
|
||||
if (node.hasAttribute("constructor")) {
|
||||
isConstruct = SpecXmlUtils.decodeBoolean(node.getAttribute("constructor"));
|
||||
}
|
||||
isDestruct = false;
|
||||
if (node.hasAttribute("destructor")) {
|
||||
isDestruct = SpecXmlUtils.decodeBoolean(node.getAttribute("destructor"));
|
||||
for (;;) {
|
||||
int attribId = decoder.getNextAttributeId();
|
||||
if (attribId == 0) {
|
||||
break;
|
||||
}
|
||||
if (attribId == AttributeId.ATTRIB_MODELLOCK.getId()) {
|
||||
modellock = decoder.readBool();
|
||||
}
|
||||
else if (attribId == AttributeId.ATTRIB_DOTDOTDOT.getId()) {
|
||||
dotdotdot = decoder.readBool();
|
||||
}
|
||||
else if (attribId == AttributeId.ATTRIB_VOIDLOCK.getId()) {
|
||||
voidinputlock = decoder.readBool();
|
||||
}
|
||||
else if (attribId == AttributeId.ATTRIB_INLINE.getId()) {
|
||||
isinline = decoder.readBool();
|
||||
}
|
||||
else if (attribId == AttributeId.ATTRIB_NORETURN.getId()) {
|
||||
noreturn = decoder.readBool();
|
||||
}
|
||||
else if (attribId == AttributeId.ATTRIB_CUSTOM.getId()) {
|
||||
custom = decoder.readBool();
|
||||
}
|
||||
else if (attribId == AttributeId.ATTRIB_CONSTRUCTOR.getId()) {
|
||||
isConstruct = decoder.readBool();
|
||||
}
|
||||
else if (attribId == AttributeId.ATTRIB_DESTRUCTOR.getId()) {
|
||||
isDestruct = decoder.readBool();
|
||||
}
|
||||
}
|
||||
XmlElement retel = parser.start("returnsym");
|
||||
int retel = decoder.openElement(ElementId.ELEM_RETURNSYM);
|
||||
outputlock = false;
|
||||
if (retel.hasAttribute("typelock")) {
|
||||
outputlock = SpecXmlUtils.decodeBoolean(retel.getAttribute("typelock"));
|
||||
for (;;) {
|
||||
int attribId = decoder.getNextAttributeId();
|
||||
if (attribId == 0) {
|
||||
break;
|
||||
}
|
||||
if (attribId == AttributeId.ATTRIB_TYPELOCK.getId()) {
|
||||
outputlock = decoder.readBool();
|
||||
}
|
||||
}
|
||||
parser.discardSubTree();
|
||||
returnstorage = null; // For now don't use decompiler's return storage
|
||||
returntype = dtmanage.readXMLDataType(parser);
|
||||
parser.end(retel);
|
||||
|
||||
XmlElement peeknode = parser.peek();
|
||||
if ((peeknode != null) && peeknode.isStart()) {
|
||||
parser.discardSubTree(); // The decompiler may return an <inject> tag
|
||||
}
|
||||
parser.end(node);
|
||||
decoder.skipElement();
|
||||
returnstorage = null; // For now don't use decompiler's return storage
|
||||
returntype = dtmanage.decodeDataType(decoder);
|
||||
decoder.closeElement(retel);
|
||||
|
||||
decoder.closeElementSkipping(node);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -21,7 +21,6 @@ import ghidra.program.model.data.DataType;
|
||||
import ghidra.program.model.listing.*;
|
||||
import ghidra.program.model.symbol.SymbolUtilities;
|
||||
import ghidra.util.exception.InvalidInputException;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
|
||||
/**
|
||||
* A global symbol as part of the decompiler's model of a function. This symbol can
|
||||
@ -149,8 +148,8 @@ public class HighCodeSymbol extends HighSymbol {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreXML(XmlPullParser parser) throws PcodeXMLException {
|
||||
super.restoreXML(parser);
|
||||
public void decode(Decoder decoder) throws PcodeXMLException {
|
||||
super.decode(decoder);
|
||||
symbol = null;
|
||||
}
|
||||
|
||||
|
@ -20,9 +20,6 @@ import ghidra.program.model.data.AbstractIntegerDataType;
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.model.scalar.Scalar;
|
||||
import ghidra.util.xml.SpecXmlUtils;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -88,10 +85,19 @@ public class HighConstant extends HighVariable {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreXml(XmlPullParser parser) throws PcodeXMLException {
|
||||
XmlElement el = parser.start("high");
|
||||
long symref = SpecXmlUtils.decodeLong(el.getAttribute("symref"));
|
||||
restoreInstances(parser, el);
|
||||
public void decode(Decoder decoder) throws PcodeXMLException {
|
||||
//int el = decoder.openElement(ElementId.ELEM_HIGH);
|
||||
long symref = 0;
|
||||
for (;;) {
|
||||
int attribId = decoder.getNextAttributeId();
|
||||
if (attribId == 0) {
|
||||
break;
|
||||
}
|
||||
if (attribId == AttributeId.ATTRIB_SYMREF.getId()) {
|
||||
symref = decoder.readUnsignedInteger();
|
||||
}
|
||||
}
|
||||
decodeInstances(decoder);
|
||||
pcaddr = function.getPCAddress(represent);
|
||||
if (symref != 0) {
|
||||
symbol = function.getLocalSymbolMap().getSymbol(symref);
|
||||
@ -115,7 +121,7 @@ public class HighConstant extends HighVariable {
|
||||
symbol.setHighVariable(this);
|
||||
}
|
||||
}
|
||||
parser.end(el);
|
||||
//decoder.closeElement(el);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -15,12 +15,9 @@
|
||||
*/
|
||||
package ghidra.program.model.pcode;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.xml.sax.*;
|
||||
|
||||
import ghidra.program.database.function.FunctionDB;
|
||||
import ghidra.program.database.symbol.CodeSymbol;
|
||||
import ghidra.program.model.address.Address;
|
||||
@ -28,11 +25,9 @@ import ghidra.program.model.address.AddressOutOfBoundsException;
|
||||
import ghidra.program.model.lang.*;
|
||||
import ghidra.program.model.listing.*;
|
||||
import ghidra.program.model.symbol.*;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
import ghidra.util.exception.InvalidInputException;
|
||||
import ghidra.util.xml.SpecXmlUtils;
|
||||
import ghidra.xml.*;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -219,9 +214,9 @@ public class HighFunction extends PcodeSyntaxTree {
|
||||
return super.newVarnode(sz, addr, id);
|
||||
}
|
||||
|
||||
private void readHighXML(XmlPullParser parser) throws PcodeXMLException {
|
||||
XmlElement el = parser.peek();
|
||||
String classstring = el.getAttribute("class");
|
||||
private void decodeHigh(Decoder decoder) throws PcodeXMLException {
|
||||
int el = decoder.openElement(ElementId.ELEM_HIGH);
|
||||
String classstring = decoder.readString(AttributeId.ATTRIB_CLASS);
|
||||
HighVariable var;
|
||||
switch (classstring.charAt(0)) {
|
||||
case 'o':
|
||||
@ -242,81 +237,80 @@ public class HighFunction extends PcodeSyntaxTree {
|
||||
default:
|
||||
throw new PcodeXMLException("Unknown HighVariable class string: " + classstring);
|
||||
}
|
||||
var.restoreXml(parser);
|
||||
var.decode(decoder);
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
|
||||
private void readHighlistXML(XmlPullParser parser) throws PcodeXMLException {
|
||||
XmlElement el = parser.start("highlist");
|
||||
while (parser.peek().isStart()) {
|
||||
readHighXML(parser);
|
||||
private void decodeHighlist(Decoder decoder) throws PcodeXMLException {
|
||||
int el = decoder.openElement(ElementId.ELEM_HIGHLIST);
|
||||
while (decoder.peekElement() != 0) {
|
||||
decodeHigh(decoder);
|
||||
}
|
||||
parser.end(el);
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.program.model.pcode.PcodeSyntaxTree#readXML(org.jdom.Element)
|
||||
*/
|
||||
@Override
|
||||
public void readXML(XmlPullParser parser) throws PcodeXMLException {
|
||||
XmlElement start = parser.start("function");
|
||||
String name = start.getAttribute("name");
|
||||
public void decode(Decoder decoder) throws PcodeXMLException {
|
||||
int start = decoder.openElement(ElementId.ELEM_FUNCTION);
|
||||
String name = decoder.readString(AttributeId.ATTRIB_NAME);
|
||||
if (!func.getName().equals(name)) {
|
||||
throw new PcodeXMLException("Function name mismatch: " + func.getName() + " + " + name);
|
||||
}
|
||||
while (!parser.peek().isEnd()) {
|
||||
XmlElement subel = parser.peek();
|
||||
if (subel.getName().equals("addr")) {
|
||||
subel = parser.start("addr");
|
||||
Address addr = AddressXML.readXML(subel, getAddressFactory());
|
||||
parser.end(subel);
|
||||
for (;;) {
|
||||
int subel = decoder.peekElement();
|
||||
if (subel == 0) {
|
||||
break;
|
||||
}
|
||||
if (subel == ElementId.ELEM_ADDR.getId()) {
|
||||
Address addr = AddressXML.decode(decoder);
|
||||
addr = func.getEntryPoint().getAddressSpace().getOverlayAddress(addr);
|
||||
if (!func.getEntryPoint().equals(addr)) {
|
||||
throw new PcodeXMLException("Mismatched address in function tag");
|
||||
}
|
||||
}
|
||||
else if (subel.getName().equals("prototype")) {
|
||||
proto.readPrototypeXML(parser, getDataTypeManager());
|
||||
else if (subel == ElementId.ELEM_PROTOTYPE.getId()) {
|
||||
proto.decodePrototype(decoder, getDataTypeManager());
|
||||
}
|
||||
else if (subel.getName().equals("localdb")) {
|
||||
localSymbols.parseScopeXML(parser);
|
||||
else if (subel == ElementId.ELEM_LOCALDB.getId()) {
|
||||
localSymbols.decodeScope(decoder);
|
||||
}
|
||||
else if (subel.getName().equals("ast")) {
|
||||
super.readXML(parser);
|
||||
else if (subel == ElementId.ELEM_AST.getId()) {
|
||||
super.decode(decoder);
|
||||
}
|
||||
else if (subel.getName().equals("highlist")) {
|
||||
readHighlistXML(parser);
|
||||
else if (subel == ElementId.ELEM_HIGHLIST.getId()) {
|
||||
decodeHighlist(decoder);
|
||||
}
|
||||
else if (subel.getName().equals("jumptablelist")) {
|
||||
readJumpTableListXML(parser);
|
||||
else if (subel == ElementId.ELEM_JUMPTABLELIST.getId()) {
|
||||
decodeJumpTableList(decoder);
|
||||
}
|
||||
else if (subel.getName().equals("override")) {
|
||||
else if (subel == ElementId.ELEM_OVERRIDE.getId()) {
|
||||
// Do nothing with override at the moment
|
||||
parser.discardSubTree();
|
||||
decoder.skipElement();
|
||||
}
|
||||
else if (subel.getName().equals("scope")) {
|
||||
else if (subel == ElementId.ELEM_SCOPE.getId()) {
|
||||
// This must be a subscope of the local scope
|
||||
// Currently this can only hold static variables of the function
|
||||
// which ghidra already knows about
|
||||
parser.discardSubTree();
|
||||
decoder.skipElement();
|
||||
}
|
||||
else {
|
||||
throw new PcodeXMLException("Unknown tag in function: " + subel.getName());
|
||||
throw new PcodeXMLException("Unknown element in function");
|
||||
}
|
||||
}
|
||||
parser.end(start);
|
||||
decoder.closeElement(start);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read in the Jump Table list for this function from XML
|
||||
* Decode the Jump Table list for this function from the stream
|
||||
*
|
||||
* @param parser is the XML stream
|
||||
* @throws PcodeXMLException for any format errors
|
||||
* @param decoder is the stream decoder
|
||||
* @throws PcodeXMLException for invalid encodings
|
||||
*/
|
||||
private void readJumpTableListXML(XmlPullParser parser) throws PcodeXMLException {
|
||||
XmlElement el = parser.start("jumptablelist");
|
||||
while (parser.peek().isStart()) {
|
||||
private void decodeJumpTableList(Decoder decoder) throws PcodeXMLException {
|
||||
int el = decoder.openElement(ElementId.ELEM_JUMPTABLELIST);
|
||||
while (decoder.peekElement() != 0) {
|
||||
JumpTable table = new JumpTable(func.getEntryPoint().getAddressSpace());
|
||||
table.restoreXml(parser, getAddressFactory());
|
||||
table.decode(decoder);
|
||||
if (!table.isEmpty()) {
|
||||
if (jumpTables == null) {
|
||||
jumpTables = new ArrayList<>();
|
||||
@ -324,7 +318,7 @@ public class HighFunction extends PcodeSyntaxTree {
|
||||
jumpTables.add(table);
|
||||
}
|
||||
}
|
||||
parser.end(el);
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
|
||||
protected Address getPCAddress(Varnode rep) {
|
||||
@ -495,26 +489,6 @@ public class HighFunction extends PcodeSyntaxTree {
|
||||
return resBuf.toString();
|
||||
}
|
||||
|
||||
public static ErrorHandler getErrorHandler(final Object errOriginator,
|
||||
final String targetName) {
|
||||
return new ErrorHandler() {
|
||||
@Override
|
||||
public void error(SAXParseException exception) throws SAXException {
|
||||
Msg.error(errOriginator, "Error parsing " + targetName, exception);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fatalError(SAXParseException exception) throws SAXException {
|
||||
Msg.error(errOriginator, "Fatal error parsing " + targetName, exception);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void warning(SAXParseException exception) throws SAXException {
|
||||
Msg.warn(errOriginator, "Warning parsing " + targetName, exception);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static Namespace findOverrideSpace(Function func) {
|
||||
SymbolTable symtab = func.getProgram().getSymbolTable();
|
||||
return findNamespace(symtab, func, "override");
|
||||
@ -592,29 +566,6 @@ public class HighFunction extends PcodeSyntaxTree {
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create XML parse tree from an input XML string
|
||||
*
|
||||
* TODO: this probably doesn't belong here.
|
||||
*
|
||||
* @param xml is the XML string to parse
|
||||
* @param handler is the handler to use for parsing errors
|
||||
* @return the XML tree
|
||||
*
|
||||
* @throws PcodeXMLException for format errors in the XML
|
||||
*/
|
||||
static public XmlPullParser stringTree(InputStream xml, ErrorHandler handler)
|
||||
throws PcodeXMLException {
|
||||
try {
|
||||
XmlPullParser parser =
|
||||
XmlPullParserFactory.create(xml, "Decompiler Result Parser", handler, false);
|
||||
return parser;
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new PcodeXMLException("XML parsing error: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The decompiler treats some namespaces as equivalent to the "global" namespace.
|
||||
* Return true if the given namespace is treated as equivalent.
|
||||
|
@ -18,9 +18,6 @@ package ghidra.program.model.pcode;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.xml.SpecXmlUtils;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -50,15 +47,23 @@ public class HighGlobal extends HighVariable {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreXml(XmlPullParser parser) throws PcodeXMLException {
|
||||
XmlElement el = parser.start("high");
|
||||
long symref = SpecXmlUtils.decodeLong(el.getAttribute("symref"));
|
||||
String attrString = el.getAttribute("offset");
|
||||
public void decode(Decoder decoder) throws PcodeXMLException {
|
||||
// int el = decoder.openElement(ElementId.ELEM_HIGH);
|
||||
long symref = 0;
|
||||
offset = -1;
|
||||
if (attrString != null) {
|
||||
offset = SpecXmlUtils.decodeInt(attrString);
|
||||
for (;;) {
|
||||
int attribId = decoder.getNextAttributeId();
|
||||
if (attribId == 0) {
|
||||
break;
|
||||
}
|
||||
if (attribId == AttributeId.ATTRIB_OFFSET.getId()) {
|
||||
offset = (int) decoder.readSignedInteger();
|
||||
}
|
||||
else if (attribId == AttributeId.ATTRIB_SYMREF.getId()) {
|
||||
symref = decoder.readUnsignedInteger();
|
||||
}
|
||||
}
|
||||
restoreInstances(parser, el);
|
||||
decodeInstances(decoder);
|
||||
if (symref != 0) {
|
||||
symbol = function.getGlobalSymbolMap().getSymbol(symref);
|
||||
}
|
||||
@ -94,6 +99,6 @@ public class HighGlobal extends HighVariable {
|
||||
}
|
||||
symbol.setHighVariable(this);
|
||||
|
||||
parser.end(el);
|
||||
// decoder.closeElement(el);
|
||||
}
|
||||
}
|
||||
|
@ -17,9 +17,6 @@ package ghidra.program.model.pcode;
|
||||
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.util.xml.SpecXmlUtils;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
|
||||
public class HighLocal extends HighVariable {
|
||||
|
||||
@ -53,15 +50,21 @@ public class HighLocal extends HighVariable {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreXml(XmlPullParser parser) throws PcodeXMLException {
|
||||
XmlElement el = parser.start("high");
|
||||
long symref = SpecXmlUtils.decodeLong(el.getAttribute("symref"));
|
||||
public void decode(Decoder decoder) throws PcodeXMLException {
|
||||
//int el = decoder.openElement(ElementId.ELEM_HIGH);
|
||||
long symref = decoder.readUnsignedInteger(AttributeId.ATTRIB_SYMREF);
|
||||
offset = -1;
|
||||
String attrString = el.getAttribute("offset");
|
||||
if (attrString != null) {
|
||||
offset = SpecXmlUtils.decodeInt(attrString);
|
||||
for (;;) {
|
||||
int attribId = decoder.getNextAttributeId();
|
||||
if (attribId == 0) {
|
||||
break;
|
||||
}
|
||||
if (attribId == AttributeId.ATTRIB_OFFSET.getId()) {
|
||||
offset = (int) decoder.readUnsignedInteger();
|
||||
break;
|
||||
}
|
||||
}
|
||||
restoreInstances(parser, el);
|
||||
decodeInstances(decoder);
|
||||
symbol = function.getLocalSymbolMap().getSymbol(symref);
|
||||
if (symbol == null) {
|
||||
throw new PcodeXMLException("HighLocal is missing symbol");
|
||||
@ -75,7 +78,7 @@ public class HighLocal extends HighVariable {
|
||||
pcaddr = symbol.getPCAddress();
|
||||
symbol.setHighVariable(this);
|
||||
|
||||
parser.end(el);
|
||||
//decoder.closeElement(el);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -17,9 +17,6 @@ package ghidra.program.model.pcode;
|
||||
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.util.xml.SpecXmlUtils;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -66,25 +63,32 @@ public class HighOther extends HighVariable {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreXml(XmlPullParser parser) throws PcodeXMLException {
|
||||
XmlElement el = parser.start("high");
|
||||
long symref = SpecXmlUtils.decodeLong(el.getAttribute("symref"));
|
||||
public void decode(Decoder decoder) throws PcodeXMLException {
|
||||
// int el = decoder.openElement(ElementId.ELEM_HIGH);
|
||||
long symref = 0;
|
||||
offset = -1;
|
||||
String attrString = el.getAttribute("offset");
|
||||
restoreInstances(parser, el);
|
||||
for (;;) {
|
||||
int attribId = decoder.getNextAttributeId();
|
||||
if (attribId == 0) {
|
||||
break;
|
||||
}
|
||||
if (attribId == AttributeId.ATTRIB_OFFSET.getId()) {
|
||||
offset = (int) decoder.readSignedInteger();
|
||||
}
|
||||
else if (attribId == AttributeId.ATTRIB_SYMREF.getId()) {
|
||||
symref = decoder.readUnsignedInteger();
|
||||
}
|
||||
}
|
||||
decodeInstances(decoder);
|
||||
name = "UNNAMED";
|
||||
pcaddr = function.getPCAddress(represent);
|
||||
if (symref != 0) {
|
||||
offset = -1;
|
||||
if (attrString != null) {
|
||||
offset = SpecXmlUtils.decodeInt(attrString);
|
||||
}
|
||||
symbol = function.getLocalSymbolMap().getSymbol(symref);
|
||||
if (symbol != null && offset < 0) {
|
||||
name = symbol.getName();
|
||||
}
|
||||
}
|
||||
|
||||
parser.end(el);
|
||||
// decoder.closeElement(el);
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,6 @@ package ghidra.program.model.pcode;
|
||||
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -55,8 +54,8 @@ public class HighParam extends HighLocal {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreXml(XmlPullParser parser) throws PcodeXMLException {
|
||||
super.restoreXml(parser);
|
||||
public void decode(Decoder decoder) throws PcodeXMLException {
|
||||
super.decode(decoder);
|
||||
HighSymbol sym = getSymbol();
|
||||
slot = sym.getCategoryIndex();
|
||||
}
|
||||
|
@ -30,7 +30,6 @@ import ghidra.util.Msg;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
import ghidra.util.exception.InvalidInputException;
|
||||
import ghidra.util.xml.SpecXmlUtils;
|
||||
import ghidra.xml.*;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -132,66 +131,66 @@ public class HighParamID extends PcodeSyntaxTree {
|
||||
* @see ghidra.program.model.pcode.PcodeSyntaxTree#readXML(org.jdom.Element)
|
||||
*/
|
||||
@Override
|
||||
public void readXML(XmlPullParser parser) throws PcodeXMLException {
|
||||
XmlElement start = parser.start("parammeasures");
|
||||
functionname = start.getAttribute("name");
|
||||
public void decode(Decoder decoder) throws PcodeXMLException {
|
||||
int start = decoder.openElement(ElementId.ELEM_PARAMMEASURES);
|
||||
functionname = decoder.readString(AttributeId.ATTRIB_NAME);
|
||||
if (!func.getName().equals(functionname)) {
|
||||
throw new PcodeXMLException(
|
||||
"Function name mismatch: " + func.getName() + " + " + functionname);
|
||||
}
|
||||
while (!parser.peek().isEnd()) {
|
||||
XmlElement subel = parser.peek();
|
||||
if (subel.getName().equals("addr")) {
|
||||
subel = parser.start("addr");
|
||||
functionaddress = AddressXML.readXML(subel, getAddressFactory());
|
||||
parser.end(subel);
|
||||
for (;;) {
|
||||
int subel = decoder.peekElement();
|
||||
if (subel == 0) {
|
||||
break;
|
||||
}
|
||||
if (subel == ElementId.ELEM_ADDR.getId()) {
|
||||
functionaddress = AddressXML.decode(decoder);
|
||||
functionaddress =
|
||||
func.getEntryPoint().getAddressSpace().getOverlayAddress(functionaddress);
|
||||
if (!func.getEntryPoint().equals(functionaddress)) {
|
||||
throw new PcodeXMLException("Mismatched address in function tag");
|
||||
}
|
||||
}
|
||||
else if (subel.getName().equals("proto")) {
|
||||
subel = parser.start("proto");
|
||||
modelname = subel.getAttribute("model");
|
||||
String val = subel.getAttribute("extrapop");
|
||||
else if (subel == ElementId.ELEM_PROTO.getId()) {
|
||||
decoder.openElement();
|
||||
modelname = decoder.readString(AttributeId.ATTRIB_MODEL);
|
||||
String val = decoder.readString(AttributeId.ATTRIB_EXTRAPOP);
|
||||
if (val.equals("unknown")) {
|
||||
protoextrapop = PrototypeModel.UNKNOWN_EXTRAPOP;
|
||||
}
|
||||
else {
|
||||
protoextrapop = SpecXmlUtils.decodeInt(val);
|
||||
}
|
||||
parser.end(subel);
|
||||
decoder.closeElement(subel);
|
||||
}
|
||||
else if (subel.getName().equals("input")) {
|
||||
parseParamMeasureXML(parser, inputlist, "input");
|
||||
else if (subel == ElementId.ELEM_INPUT.getId()) {
|
||||
decodeParamMeasure(decoder, inputlist);
|
||||
}
|
||||
else if (subel.getName().equals("output")) {
|
||||
parseParamMeasureXML(parser, outputlist, "output");
|
||||
else if (subel == ElementId.ELEM_OUTPUT.getId()) {
|
||||
decodeParamMeasure(decoder, outputlist);
|
||||
}
|
||||
else {
|
||||
throw new PcodeXMLException("Unknown tag in parammeasures: " + subel.getName());
|
||||
throw new PcodeXMLException("Unknown tag in parammeasures");
|
||||
}
|
||||
}
|
||||
parser.end(start);
|
||||
decoder.closeElement(start);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read in the inputs or outputs list for this function from an XML rep
|
||||
* @param parser is the XML parser
|
||||
* Decode the inputs or outputs list for this function from a stream.
|
||||
* @param decoder is the stream decoder
|
||||
* @param pmlist is populated with the resulting list
|
||||
* @param tag is the name of the tag
|
||||
* @throws PcodeXMLException for improperly formed XML
|
||||
* @throws PcodeXMLException for invalid encodings
|
||||
*/
|
||||
private void parseParamMeasureXML(XmlPullParser parser, List<ParamMeasure> pmlist, String tag)
|
||||
private void decodeParamMeasure(Decoder decoder, List<ParamMeasure> pmlist)
|
||||
throws PcodeXMLException {
|
||||
XmlElement el = parser.start(tag);
|
||||
int el = decoder.openElement();
|
||||
ParamMeasure pm = new ParamMeasure();
|
||||
pm.readXml(parser, this);
|
||||
pm.decode(decoder, this);
|
||||
if (!pm.isEmpty()) {
|
||||
pmlist.add(pm);
|
||||
}
|
||||
parser.end(el);
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
|
||||
public static ErrorHandler getErrorHandler(final Object errOriginator,
|
||||
@ -214,29 +213,6 @@ public class HighParamID extends PcodeSyntaxTree {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and XML SAX parse tree from an input XML string
|
||||
*
|
||||
* TODO: this probably doesn't belong here.
|
||||
*
|
||||
* @param xml string to parse
|
||||
* @param handler is the error handler
|
||||
* @return an XML tree element
|
||||
*
|
||||
* @throws PcodeXMLException for improper XML
|
||||
*/
|
||||
static public XmlPullParser stringTree(String xml, ErrorHandler handler)
|
||||
throws PcodeXMLException {
|
||||
try {
|
||||
XmlPullParser parser =
|
||||
XmlPullParserFactory.create(xml, "Decompiler Result Parser", handler, false);
|
||||
return parser;
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new PcodeXMLException("XML parsing error: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update any parameters for this Function from parameters defined in this map.
|
||||
*
|
||||
@ -244,7 +220,6 @@ public class HighParamID extends PcodeSyntaxTree {
|
||||
* @param srctype function signature source
|
||||
*/
|
||||
public void storeReturnToDatabase(boolean storeDataTypes, SourceType srctype) {
|
||||
PcodeDataTypeManager dtManage = getDataTypeManager();
|
||||
try {
|
||||
//TODO: Currently, only storing one output, so looking for the best to report. When possible, change this to report all
|
||||
int best_index = 0;
|
||||
@ -285,7 +260,6 @@ public class HighParamID extends PcodeSyntaxTree {
|
||||
* @param srctype function signature source
|
||||
*/
|
||||
public void storeParametersToDatabase(boolean storeDataTypes, SourceType srctype) {
|
||||
PcodeDataTypeManager dtManage = getDataTypeManager();
|
||||
try {
|
||||
List<Variable> params = new ArrayList<>();
|
||||
for (ParamMeasure pm : inputlist) {
|
||||
|
@ -23,8 +23,6 @@ import ghidra.program.model.symbol.Namespace;
|
||||
import ghidra.program.model.symbol.Symbol;
|
||||
import ghidra.util.exception.InvalidInputException;
|
||||
import ghidra.util.xml.SpecXmlUtils;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
|
||||
/**
|
||||
* A symbol within the decompiler's model of a particular function. The symbol has a name and a data-type
|
||||
@ -405,69 +403,74 @@ public class HighSymbol {
|
||||
buf.append("</symbol>\n");
|
||||
}
|
||||
|
||||
protected void restoreXMLHeader(XmlElement symel) throws PcodeXMLException {
|
||||
id = SpecXmlUtils.decodeLong(symel.getAttribute("id"));
|
||||
if (id == 0) {
|
||||
throw new PcodeXMLException("missing unique symbol id");
|
||||
}
|
||||
protected void decodeHeader(Decoder decoder) throws PcodeXMLException {
|
||||
name = null;
|
||||
id = 0;
|
||||
typelock = false;
|
||||
String typelockstr = symel.getAttribute("typelock");
|
||||
if ((typelockstr != null) && (SpecXmlUtils.decodeBoolean(typelockstr))) {
|
||||
typelock = true;
|
||||
}
|
||||
namelock = false;
|
||||
String namelockstr = symel.getAttribute("namelock");
|
||||
if ((namelockstr != null) && (SpecXmlUtils.decodeBoolean(namelockstr))) {
|
||||
namelock = true;
|
||||
}
|
||||
isThis = false;
|
||||
String thisstring = symel.getAttribute("thisptr");
|
||||
if ((thisstring != null) && (SpecXmlUtils.decodeBoolean(thisstring))) {
|
||||
isThis = true;
|
||||
}
|
||||
isHidden = false;
|
||||
String hiddenstring = symel.getAttribute("hiddenretparm");
|
||||
if ((hiddenstring != null) && (SpecXmlUtils.decodeBoolean(hiddenstring))) {
|
||||
isHidden = true;
|
||||
}
|
||||
// isolate = false;
|
||||
// String isolatestr = symel.getAttribute("merge");
|
||||
// if ((isolatestr != null) && !SpecXmlUtils.decodeBoolean(isolatestr)) {
|
||||
// isolate = true;
|
||||
// }
|
||||
|
||||
name = symel.getAttribute("name");
|
||||
categoryIndex = -1;
|
||||
category = -1;
|
||||
if (symel.hasAttribute("cat")) {
|
||||
category = SpecXmlUtils.decodeInt(symel.getAttribute("cat"));
|
||||
if (category == 0) {
|
||||
categoryIndex = SpecXmlUtils.decodeInt(symel.getAttribute("index"));
|
||||
|
||||
for (;;) {
|
||||
int attribId = decoder.getNextAttributeId();
|
||||
if (attribId == 0) {
|
||||
break;
|
||||
}
|
||||
if (attribId == AttributeId.ATTRIB_ID.getId()) {
|
||||
id = decoder.readUnsignedInteger();
|
||||
}
|
||||
else if (attribId == AttributeId.ATTRIB_TYPELOCK.getId()) {
|
||||
typelock = decoder.readBool();
|
||||
}
|
||||
else if (attribId == AttributeId.ATTRIB_NAMELOCK.getId()) {
|
||||
namelock = decoder.readBool();
|
||||
}
|
||||
else if (attribId == AttributeId.ATTRIB_THISPTR.getId()) {
|
||||
isThis = decoder.readBool();
|
||||
}
|
||||
else if (attribId == AttributeId.ATTRIB_HIDDENRETPARM.getId()) {
|
||||
isHidden = decoder.readBool();
|
||||
}
|
||||
else if (attribId == AttributeId.ATTRIB_NAME.getId()) {
|
||||
name = decoder.readString();
|
||||
}
|
||||
else if (attribId == AttributeId.ATTRIB_CAT.getId()) {
|
||||
category = (int) decoder.readSignedInteger();
|
||||
}
|
||||
else if (attribId == AttributeId.ATTRIB_INDEX.getId()) {
|
||||
categoryIndex = (int) decoder.readUnsignedInteger();
|
||||
}
|
||||
}
|
||||
if (id == 0) {
|
||||
throw new PcodeXMLException("missing unique symbol id");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore this symbol object and its associated mappings from an XML description
|
||||
* in the given stream.
|
||||
* @param parser is the given XML stream
|
||||
* @throws PcodeXMLException if the XML description is invalid
|
||||
* Decode this symbol object and its associated mappings from the stream.
|
||||
* @param decoder is the stream decoder
|
||||
* @throws PcodeXMLException for invalid encodings
|
||||
*/
|
||||
public void restoreXML(XmlPullParser parser) throws PcodeXMLException {
|
||||
XmlElement symel = parser.start("symbol");
|
||||
restoreXMLHeader(symel);
|
||||
type = dtmanage.readXMLDataType(parser);
|
||||
parser.end(symel);
|
||||
public void decode(Decoder decoder) throws PcodeXMLException {
|
||||
int symel = decoder.openElement(ElementId.ELEM_SYMBOL);
|
||||
decodeHeader(decoder);
|
||||
type = dtmanage.decodeDataType(decoder);
|
||||
decoder.closeElement(symel);
|
||||
|
||||
if (categoryIndex >= 0 && name.startsWith("$$undef")) {
|
||||
// use default parameter name
|
||||
name = "param_" + Integer.toString(categoryIndex + 1);
|
||||
}
|
||||
|
||||
while (parser.peek().isStart()) {
|
||||
XmlElement el = parser.peek();
|
||||
for (;;) {
|
||||
int el = decoder.peekElement();
|
||||
if (el == 0) {
|
||||
break;
|
||||
}
|
||||
SymbolEntry entry;
|
||||
if (el.getName().equals("hash")) {
|
||||
if (el == ElementId.ELEM_HASH.getId()) {
|
||||
entry = new DynamicEntry(this);
|
||||
}
|
||||
else if (this instanceof HighCodeSymbol) {
|
||||
@ -476,7 +479,7 @@ public class HighSymbol {
|
||||
else {
|
||||
entry = new MappedEntry(this);
|
||||
}
|
||||
entry.restoreXML(parser);
|
||||
entry.decode(decoder);
|
||||
addMapEntry(entry);
|
||||
}
|
||||
if ((isThis || isHidden) && entryList != null) {
|
||||
@ -496,21 +499,21 @@ public class HighSymbol {
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore a full HighSymbol from the next <mapsym> tag in the given XML stream.
|
||||
* This method acts as an XML based HighSymbol factory, instantiating the correct class
|
||||
* based on the particular tags.
|
||||
* @param parser is the given XML stream
|
||||
* Restore a full HighSymbol from the next <mapsym> element in the stream.
|
||||
* This method acts as a HighSymbol factory, instantiating the correct class
|
||||
* based on the particular elements.
|
||||
* @param decoder is the stream decoder
|
||||
* @param isGlobal is true if this symbol is being read into a global scope
|
||||
* @param high is the function model that will own the new symbol
|
||||
* @return the new symbol
|
||||
* @throws PcodeXMLException if the XML description is invalid
|
||||
* @throws PcodeXMLException for invalid encodings
|
||||
*/
|
||||
public static HighSymbol restoreMapSymXML(XmlPullParser parser, boolean isGlobal,
|
||||
HighFunction high) throws PcodeXMLException {
|
||||
public static HighSymbol decodeMapSym(Decoder decoder, boolean isGlobal, HighFunction high)
|
||||
throws PcodeXMLException {
|
||||
HighSymbol res = null;
|
||||
parser.start("mapsym");
|
||||
XmlElement symel = parser.peek();
|
||||
if (symel.getName().equals("equatesymbol")) {
|
||||
int mapel = decoder.openElement(ElementId.ELEM_MAPSYM);
|
||||
int symel = decoder.peekElement();
|
||||
if (symel == ElementId.ELEM_EQUATESYMBOL.getId()) {
|
||||
res = new EquateSymbol(high);
|
||||
}
|
||||
else if (isGlobal) {
|
||||
@ -520,19 +523,23 @@ public class HighSymbol {
|
||||
else {
|
||||
res = new HighSymbol(high);
|
||||
}
|
||||
res.restoreXML(parser);
|
||||
while (parser.peek().isStart()) {
|
||||
res.decode(decoder);
|
||||
for (;;) {
|
||||
SymbolEntry entry;
|
||||
if (parser.peek().getName().equals("hash")) {
|
||||
int subid = decoder.peekElement();
|
||||
if (subid == 0) {
|
||||
break;
|
||||
}
|
||||
if (subid == ElementId.ELEM_HASH.getId()) {
|
||||
entry = new DynamicEntry(res);
|
||||
}
|
||||
else {
|
||||
entry = new MappedEntry(res);
|
||||
}
|
||||
entry.restoreXML(parser);
|
||||
entry.decode(decoder);
|
||||
res.addMapEntry(entry);
|
||||
}
|
||||
parser.end();
|
||||
decoder.closeElement(mapel);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -18,9 +18,6 @@ package ghidra.program.model.pcode;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.util.xml.SpecXmlUtils;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -58,7 +55,7 @@ public abstract class HighVariable {
|
||||
protected void setHighOnInstances() {
|
||||
for (Varnode instance : instances) {
|
||||
if (instance instanceof VarnodeAST) {
|
||||
((VarnodeAST)instance).setHigh(this);
|
||||
((VarnodeAST) instance).setHigh(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -141,15 +138,13 @@ public abstract class HighVariable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore the data-type and the Varnode instances of this HighVariable.
|
||||
* Decode the data-type and the Varnode instances of this HighVariable.
|
||||
* The "representative" Varnode is also populated.
|
||||
* @param parser is the XML stream
|
||||
* @param el is the root {@code <high>} tag
|
||||
* @throws PcodeXMLException if the XML is not valid
|
||||
* @param decoder is the stream decoder
|
||||
* @throws PcodeXMLException for invalid encodings
|
||||
*/
|
||||
protected void restoreInstances(XmlPullParser parser, XmlElement el)
|
||||
throws PcodeXMLException {
|
||||
int repref = SpecXmlUtils.decodeInt(el.getAttribute("repref"));
|
||||
protected void decodeInstances(Decoder decoder) throws PcodeXMLException {
|
||||
int repref = (int) decoder.readUnsignedInteger(AttributeId.ATTRIB_REPREF);
|
||||
Varnode rep = function.getRef(repref);
|
||||
if (rep == null) {
|
||||
throw new PcodeXMLException("Undefined varnode reference");
|
||||
@ -157,17 +152,15 @@ public abstract class HighVariable {
|
||||
|
||||
type = null;
|
||||
|
||||
ArrayList<Varnode> vnlist = new ArrayList<Varnode>();
|
||||
if (parser.peek().isStart()) {
|
||||
type = function.getDataTypeManager().readXMLDataType(parser);
|
||||
}
|
||||
ArrayList<Varnode> vnlist = new ArrayList<>();
|
||||
type = function.getDataTypeManager().decodeDataType(decoder);
|
||||
|
||||
if (type == null) {
|
||||
throw new PcodeXMLException("Missing <type> for HighVariable");
|
||||
}
|
||||
|
||||
while (parser.peek().isStart()) {
|
||||
Varnode vn = Varnode.readXML(parser, function);
|
||||
for (;;) {
|
||||
int subel = decoder.peekElement();
|
||||
if (subel == 0) {
|
||||
break;
|
||||
}
|
||||
Varnode vn = Varnode.decode(decoder, function);
|
||||
vnlist.add(vn);
|
||||
}
|
||||
Varnode[] vnarray = new Varnode[vnlist.size()];
|
||||
@ -193,9 +186,9 @@ public abstract class HighVariable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore this HighVariable from a {@code <high>} XML tag
|
||||
* @param parser is the XML stream
|
||||
* @throws PcodeXMLException if the XML is not valid
|
||||
* Decode this HighVariable from a {@code <high>} element in the stream
|
||||
* @param decoder is the stream decoder
|
||||
* @throws PcodeXMLException for invalid encodings
|
||||
*/
|
||||
public abstract void restoreXml(XmlPullParser parser) throws PcodeXMLException;
|
||||
public abstract void decode(Decoder decoder) throws PcodeXMLException;
|
||||
}
|
||||
|
@ -23,9 +23,6 @@ import ghidra.program.model.listing.Function;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.model.symbol.*;
|
||||
import ghidra.util.exception.InvalidInputException;
|
||||
import ghidra.util.xml.SpecXmlUtils;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
|
||||
/**
|
||||
* JumpTable found as part of the decompilation of a function
|
||||
@ -78,14 +75,12 @@ public class JumpTable {
|
||||
return num;
|
||||
}
|
||||
|
||||
public void restoreXml(XmlPullParser parser, AddressFactory addrFactory) {
|
||||
XmlElement el = parser.start("loadtable");
|
||||
size = SpecXmlUtils.decodeInt(el.getAttribute("size"));
|
||||
num = SpecXmlUtils.decodeInt(el.getAttribute("num"));
|
||||
XmlElement subel = parser.start("addr");
|
||||
addr = translateOverlayAddress(AddressXML.readXML(subel, addrFactory));
|
||||
parser.end(subel);
|
||||
parser.end(el);
|
||||
public void decode(Decoder decoder) throws PcodeXMLException {
|
||||
int el = decoder.openElement(ElementId.ELEM_LOADTABLE);
|
||||
size = (int) decoder.readSignedInteger(AttributeId.ATTRIB_SIZE);
|
||||
num = (int) decoder.readSignedInteger(AttributeId.ATTRIB_NUM);
|
||||
addr = translateOverlayAddress(AddressXML.decode(decoder));
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
}
|
||||
|
||||
@ -159,61 +154,62 @@ public class JumpTable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a JumpTable object by parsing the XML elements
|
||||
* @param parser is the XML parser
|
||||
* @param addrFactory is used to look-up address spaces
|
||||
* @throws PcodeXMLException for improperly formed XML
|
||||
* Decode a JumpTable object from the stream.
|
||||
* @param decoder is the stream decoder
|
||||
* @throws PcodeXMLException for invalid encodings
|
||||
*/
|
||||
public void restoreXml(XmlPullParser parser, AddressFactory addrFactory)
|
||||
throws PcodeXMLException {
|
||||
XmlElement el = parser.start("jumptable");
|
||||
try {
|
||||
ArrayList<Address> aTable = new ArrayList<>();
|
||||
ArrayList<Integer> lTable = new ArrayList<>();
|
||||
ArrayList<LoadTable> ldTable = new ArrayList<>();
|
||||
public void decode(Decoder decoder) throws PcodeXMLException {
|
||||
int el = decoder.openElement(ElementId.ELEM_JUMPTABLE);
|
||||
if (decoder.peekElement() == 0) { // Empty jumptable
|
||||
decoder.closeElement(el);
|
||||
return;
|
||||
}
|
||||
ArrayList<Address> aTable = new ArrayList<>();
|
||||
ArrayList<Integer> lTable = new ArrayList<>();
|
||||
ArrayList<LoadTable> ldTable = new ArrayList<>();
|
||||
|
||||
if (!parser.peek().isStart()) { // Empty jumptable
|
||||
return;
|
||||
Address switchAddr = translateOverlayAddress(AddressXML.decode(decoder));
|
||||
|
||||
for (;;) {
|
||||
int subel = decoder.peekElement();
|
||||
if (subel == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
XmlElement addrel = parser.start("addr");
|
||||
Address switchAddr = translateOverlayAddress(AddressXML.readXML(addrel, addrFactory));
|
||||
parser.end(addrel);
|
||||
|
||||
while (parser.peek().isStart()) {
|
||||
if (parser.peek().getName().equals("dest")) {
|
||||
XmlElement subel = parser.start("dest");
|
||||
Address caseAddr =
|
||||
translateOverlayAddress(AddressXML.readXML(subel, addrFactory));
|
||||
aTable.add(caseAddr);
|
||||
String slabel = subel.getAttribute("label");
|
||||
if (slabel != null) {
|
||||
int label = SpecXmlUtils.decodeInt(slabel);
|
||||
if (subel == ElementId.ELEM_DEST.getId()) {
|
||||
decoder.openElement();
|
||||
Address caseAddr = translateOverlayAddress(AddressXML.decodeFromAttributes(decoder));
|
||||
aTable.add(caseAddr);
|
||||
decoder.rewindAttributes();
|
||||
for (;;) {
|
||||
int attribId = decoder.getNextAttributeId();
|
||||
if (attribId == 0) {
|
||||
break;
|
||||
}
|
||||
if (attribId == AttributeId.ATTRIB_LABEL.getId()) {
|
||||
int label = (int) decoder.readUnsignedInteger();
|
||||
lTable.add(label);
|
||||
}
|
||||
parser.end(subel);
|
||||
}
|
||||
else if (parser.peek().getName().equals("loadtable")) {
|
||||
LoadTable loadtable = new LoadTable();
|
||||
loadtable.restoreXml(parser, addrFactory);
|
||||
ldTable.add(loadtable);
|
||||
}
|
||||
else {
|
||||
parser.discardSubTree();
|
||||
}
|
||||
decoder.closeElement(subel);
|
||||
}
|
||||
else if (subel == ElementId.ELEM_LOADTABLE.getId()) {
|
||||
LoadTable loadtable = new LoadTable();
|
||||
loadtable.decode(decoder);
|
||||
ldTable.add(loadtable);
|
||||
}
|
||||
else {
|
||||
decoder.skipElement();
|
||||
}
|
||||
}
|
||||
|
||||
opAddress = switchAddr;
|
||||
addressTable = new Address[aTable.size()];
|
||||
aTable.toArray(addressTable);
|
||||
labelTable = new Integer[lTable.size()];
|
||||
lTable.toArray(labelTable);
|
||||
loadTable = new LoadTable[ldTable.size()];
|
||||
ldTable.toArray(loadTable);
|
||||
}
|
||||
finally {
|
||||
parser.end(el);
|
||||
}
|
||||
opAddress = switchAddr;
|
||||
addressTable = new Address[aTable.size()];
|
||||
aTable.toArray(addressTable);
|
||||
labelTable = new Integer[lTable.size()];
|
||||
lTable.toArray(labelTable);
|
||||
loadTable = new LoadTable[ldTable.size()];
|
||||
ldTable.toArray(loadTable);
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
|
||||
public void buildXml(StringBuilder buf) {
|
||||
|
@ -24,8 +24,6 @@ import ghidra.program.model.listing.*;
|
||||
import ghidra.program.model.symbol.*;
|
||||
import ghidra.util.SystemUtilities;
|
||||
import ghidra.util.xml.SpecXmlUtils;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
|
||||
/**
|
||||
* A container for local symbols within the decompiler's model of a function. It contains HighSymbol
|
||||
@ -261,40 +259,40 @@ public class LocalSymbolMap {
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a <mapsym> tag in XML
|
||||
* @param parser is the XML parser
|
||||
* Decode a <mapsym> element from the stream.
|
||||
* @param decoder is the stream decoder
|
||||
* @return the reconstructed HighSymbol
|
||||
* @throws PcodeXMLException for problems sub tags
|
||||
*/
|
||||
private HighSymbol parseSymbolXML(XmlPullParser parser) throws PcodeXMLException {
|
||||
HighSymbol res = HighSymbol.restoreMapSymXML(parser, false, func);
|
||||
private HighSymbol decodeSymbol(Decoder decoder) throws PcodeXMLException {
|
||||
HighSymbol res = HighSymbol.decodeMapSym(decoder, false, func);
|
||||
insertSymbol(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a local symbol scope in XML from the <localdb> tag.
|
||||
* Decode a local symbol scope from the stream
|
||||
*
|
||||
* @param parser is the XML parser
|
||||
* @throws PcodeXMLException for problems parsing individual tags
|
||||
* @param decoder is the stream decoder
|
||||
* @throws PcodeXMLException for invalid encodings
|
||||
*/
|
||||
public void parseScopeXML(XmlPullParser parser) throws PcodeXMLException {
|
||||
XmlElement el = parser.start("localdb");
|
||||
spacename = el.getAttribute("main");
|
||||
XmlElement scopeel = parser.start("scope");
|
||||
public void decodeScope(Decoder decoder) throws PcodeXMLException {
|
||||
int el = decoder.openElement(ElementId.ELEM_LOCALDB);
|
||||
spacename = decoder.readString(AttributeId.ATTRIB_MAIN);
|
||||
int scopeel = decoder.openElement(ElementId.ELEM_SCOPE);
|
||||
|
||||
parser.discardSubTree(); // This is the parent scope path
|
||||
parser.discardSubTree(); // This is the address range
|
||||
decoder.skipElement(); // This is the parent scope path
|
||||
decoder.skipElement(); // This is the address range
|
||||
|
||||
addrMappedSymbols.clear(); // Clear out any old map
|
||||
symbolMap.clear(); // Clear out any old map
|
||||
addrMappedSymbols.clear(); // Clear out any old map
|
||||
symbolMap.clear(); // Clear out any old map
|
||||
|
||||
XmlElement nextEl = parser.peek();
|
||||
if (nextEl != null && nextEl.isStart() && "symbollist".equals(nextEl.getName())) {
|
||||
parseSymbolList(parser);
|
||||
int nextEl = decoder.peekElement();
|
||||
if (nextEl == ElementId.ELEM_SYMBOLLIST.getId()) {
|
||||
decodeSymbolList(decoder);
|
||||
}
|
||||
parser.end(scopeel);
|
||||
parser.end(el);
|
||||
decoder.closeElement(scopeel);
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
|
||||
private static final Comparator<HighSymbol> PARAM_SYMBOL_SLOT_COMPARATOR = new Comparator<>() {
|
||||
@ -305,15 +303,15 @@ public class LocalSymbolMap {
|
||||
};
|
||||
|
||||
/**
|
||||
* Add mapped symbols to this LocalVariableMap, by parsing the <symbollist> and <mapsym> tags.
|
||||
* @param parser is the XML parser
|
||||
* @throws PcodeXMLException for problems parsing a tag
|
||||
* Add mapped symbols to this LocalVariableMap, by decoding the <symbollist> and <mapsym> elements
|
||||
* @param decoder is the stream decoder
|
||||
* @throws PcodeXMLException for invalid encodings
|
||||
*/
|
||||
public void parseSymbolList(XmlPullParser parser) throws PcodeXMLException {
|
||||
XmlElement el = parser.start("symbollist");
|
||||
public void decodeSymbolList(Decoder decoder) throws PcodeXMLException {
|
||||
int el = decoder.openElement(ElementId.ELEM_SYMBOLLIST);
|
||||
ArrayList<HighSymbol> parms = new ArrayList<>();
|
||||
while (parser.peek().isStart()) {
|
||||
HighSymbol sym = parseSymbolXML(parser);
|
||||
while (decoder.peekElement() != 0) {
|
||||
HighSymbol sym = decodeSymbol(decoder);
|
||||
if (sym.isParameter()) {
|
||||
parms.add(sym);
|
||||
}
|
||||
@ -321,7 +319,7 @@ public class LocalSymbolMap {
|
||||
paramSymbols = new HighSymbol[parms.size()];
|
||||
parms.toArray(paramSymbols);
|
||||
Arrays.sort(paramSymbols, PARAM_SYMBOL_SLOT_COMPARATOR);
|
||||
parser.end(el);
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -17,7 +17,6 @@ package ghidra.program.model.pcode;
|
||||
|
||||
import ghidra.program.model.listing.Data;
|
||||
import ghidra.program.model.listing.VariableStorage;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
|
||||
/**
|
||||
* A normal address based HighSymbol mapping with an associated Data object
|
||||
@ -52,8 +51,8 @@ public class MappedDataEntry extends MappedEntry {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreXML(XmlPullParser parser) throws PcodeXMLException {
|
||||
super.restoreXML(parser);
|
||||
public void decode(Decoder decoder) throws PcodeXMLException {
|
||||
super.decode(decoder);
|
||||
data = symbol.getProgram().getListing().getDataAt(storage.getMinAddress());
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,8 @@
|
||||
*/
|
||||
package ghidra.program.model.pcode;
|
||||
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressSpace;
|
||||
import ghidra.program.model.data.AbstractFloatDataType;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.model.listing.VariableStorage;
|
||||
@ -23,8 +24,6 @@ import ghidra.program.model.mem.MemoryBlock;
|
||||
import ghidra.program.model.symbol.Reference;
|
||||
import ghidra.program.model.symbol.ReferenceIterator;
|
||||
import ghidra.util.exception.InvalidInputException;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
|
||||
/**
|
||||
* A normal mapping of a HighSymbol to a particular Address, consuming a set number of bytes
|
||||
@ -53,33 +52,33 @@ public class MappedEntry extends SymbolEntry {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreXML(XmlPullParser parser) throws PcodeXMLException {
|
||||
public void decode(Decoder decoder) throws PcodeXMLException {
|
||||
HighFunction function = symbol.function;
|
||||
Program program = function.getFunction().getProgram();
|
||||
AddressFactory addrFactory = function.getAddressFactory();
|
||||
|
||||
XmlElement addrel = parser.start("addr");
|
||||
int addrel = decoder.openElement(ElementId.ELEM_ADDR);
|
||||
int sz = symbol.type.getLength();
|
||||
if (sz == 0) {
|
||||
throw new PcodeXMLException(
|
||||
"Invalid symbol 0-sized data-type: " + symbol.type.getName());
|
||||
}
|
||||
try {
|
||||
Address varAddr = AddressXML.readXML(addrel, addrFactory);
|
||||
Address varAddr = AddressXML.decodeFromAttributes(decoder);
|
||||
AddressSpace spc = varAddr.getAddressSpace();
|
||||
if ((spc == null) || (spc.getType() != AddressSpace.TYPE_VARIABLE)) {
|
||||
storage = new VariableStorage(program, varAddr, sz);
|
||||
}
|
||||
else {
|
||||
storage = function.readXMLVarnodePieces(addrel, varAddr);
|
||||
decoder.rewindAttributes();
|
||||
storage = function.decodeVarnodePieces(decoder, varAddr);
|
||||
}
|
||||
}
|
||||
catch (InvalidInputException e) {
|
||||
throw new PcodeXMLException("Invalid storage: " + e.getMessage());
|
||||
}
|
||||
parser.end(addrel);
|
||||
decoder.closeElement(addrel);
|
||||
|
||||
parseRangeList(parser);
|
||||
decodeRangeList(decoder);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -16,9 +16,6 @@
|
||||
package ghidra.program.model.pcode;
|
||||
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.util.xml.SpecXmlUtils;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
|
||||
/**
|
||||
* ParamMeasure
|
||||
@ -43,24 +40,24 @@ public class ParamMeasure {
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
if (vn == null)
|
||||
if (vn == null) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a ParamMeasure object by parsing the XML elements
|
||||
* @param parser xml parser
|
||||
* Decode a ParamMeasure object from the stream.
|
||||
* @param decoder is the stream decoder
|
||||
* @param factory pcode factory
|
||||
* @throws PcodeXMLException if an error occurs when reading the xml.
|
||||
* @throws PcodeXMLException for an invalid encoding
|
||||
*/
|
||||
public void readXml(XmlPullParser parser, PcodeFactory factory) throws PcodeXMLException {
|
||||
vn = Varnode.readXML(parser, factory);
|
||||
dt = factory.getDataTypeManager().readXMLDataType(parser);
|
||||
XmlElement rankel = parser.start("rank");
|
||||
String strVal = rankel.getAttribute("val");
|
||||
rank = SpecXmlUtils.decodeInt(strVal);
|
||||
parser.end(rankel);
|
||||
public void decode(Decoder decoder, PcodeFactory factory) throws PcodeXMLException {
|
||||
vn = Varnode.decode(decoder, factory);
|
||||
dt = factory.getDataTypeManager().decodeDataType(decoder);
|
||||
int rankel = decoder.openElement(ElementId.ELEM_RANK);
|
||||
rank = (int) decoder.readSignedInteger(AttributeId.ATTRIB_VAL);
|
||||
decoder.closeElement(rankel);
|
||||
}
|
||||
|
||||
public Varnode getVarnode() {
|
||||
|
@ -21,8 +21,6 @@ import java.util.ArrayList;
|
||||
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.util.xml.SpecXmlUtils;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -160,32 +158,34 @@ public class PcodeBlock {
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore meta-data for a single edge
|
||||
* @param parser
|
||||
* Decode a single edge
|
||||
* @param decoder is the stream decoder
|
||||
* @param resolver used to recover PcodeBlock reference
|
||||
* @throws PcodeXMLException
|
||||
* @throws PcodeXMLException for invalid encodings
|
||||
*/
|
||||
public void restoreXml(XmlPullParser parser, BlockMap resolver) throws PcodeXMLException {
|
||||
XmlElement el = parser.start("edge");
|
||||
public void decode(Decoder decoder, BlockMap resolver) throws PcodeXMLException {
|
||||
int el = decoder.openElement(ElementId.ELEM_EDGE);
|
||||
label = 0; // Tag does not currently contain info about label
|
||||
int endIndex = SpecXmlUtils.decodeInt(el.getAttribute("end"));
|
||||
int endIndex = (int) decoder.readSignedInteger(AttributeId.ATTRIB_END);
|
||||
point = resolver.findLevelBlock(endIndex);
|
||||
if (point == null)
|
||||
if (point == null) {
|
||||
throw new PcodeXMLException("Bad serialized edge in block graph");
|
||||
reverse_index = SpecXmlUtils.decodeInt(el.getAttribute("rev"));
|
||||
parser.end(el);
|
||||
}
|
||||
reverse_index = (int) decoder.readSignedInteger(AttributeId.ATTRIB_REV);
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
|
||||
public void restoreXml(XmlPullParser parser, ArrayList<? extends PcodeBlock> blockList)
|
||||
public void decode(Decoder decoder, ArrayList<? extends PcodeBlock> blockList)
|
||||
throws PcodeXMLException {
|
||||
XmlElement el = parser.start("edge");
|
||||
int el = decoder.openElement(ElementId.ELEM_EDGE);
|
||||
label = 0; // Tag does not currently contain info about label
|
||||
int endIndex = SpecXmlUtils.decodeInt(el.getAttribute("end"));
|
||||
int endIndex = (int) decoder.readSignedInteger(AttributeId.ATTRIB_END);
|
||||
point = blockList.get(endIndex);
|
||||
if (point == null)
|
||||
if (point == null) {
|
||||
throw new PcodeXMLException("Bad serialized edge in block list");
|
||||
reverse_index = SpecXmlUtils.decodeInt(el.getAttribute("rev"));
|
||||
parser.end(el);
|
||||
}
|
||||
reverse_index = (int) decoder.readSignedInteger(AttributeId.ATTRIB_REV);
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -198,8 +198,8 @@ public class PcodeBlock {
|
||||
index = -1;
|
||||
blocktype = PLAIN;
|
||||
parent = null;
|
||||
intothis = new ArrayList<BlockEdge>();
|
||||
outofthis = new ArrayList<BlockEdge>();
|
||||
intothis = new ArrayList<>();
|
||||
outofthis = new ArrayList<>();
|
||||
}
|
||||
|
||||
public int getType() {
|
||||
@ -240,38 +240,37 @@ public class PcodeBlock {
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore the next input edge via XML
|
||||
* @param parser
|
||||
* @param resolver
|
||||
* @throws PcodeXMLException
|
||||
* Decode the next input edge from the stream
|
||||
* @param decoder is the stream decoder
|
||||
* @param resolver is used to find PcodeBlocks
|
||||
* @throws PcodeXMLException for any invalid encoding
|
||||
*/
|
||||
protected void restoreNextInEdge(XmlPullParser parser, BlockMap resolver)
|
||||
throws PcodeXMLException {
|
||||
protected void decodeNextInEdge(Decoder decoder, BlockMap resolver) throws PcodeXMLException {
|
||||
BlockEdge inEdge = new BlockEdge();
|
||||
intothis.add(inEdge);
|
||||
inEdge.restoreXml(parser, resolver);
|
||||
while(inEdge.point.outofthis.size() <= inEdge.reverse_index) {
|
||||
inEdge.decode(decoder, resolver);
|
||||
while (inEdge.point.outofthis.size() <= inEdge.reverse_index) {
|
||||
inEdge.point.outofthis.add(null);
|
||||
}
|
||||
BlockEdge outEdge = new BlockEdge(this,0,intothis.size()-1);
|
||||
BlockEdge outEdge = new BlockEdge(this, 0, intothis.size() - 1);
|
||||
inEdge.point.outofthis.set(inEdge.reverse_index, outEdge);
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore the next input edge via XML. Resolve block indices via a blockList
|
||||
* @param parser
|
||||
* Decode the next input edge from the stream. Resolve block indices via a blockList
|
||||
* @param decoder is the stream decoder
|
||||
* @param blockList allows lookup of PcodeBlock via index
|
||||
* @throws PcodeXMLException
|
||||
* @throws PcodeXMLException for any invalid encoding
|
||||
*/
|
||||
protected void restoreNextInEdge(XmlPullParser parser,
|
||||
ArrayList<? extends PcodeBlock> blockList) throws PcodeXMLException {
|
||||
protected void decodeNextInEdge(Decoder decoder, ArrayList<? extends PcodeBlock> blockList)
|
||||
throws PcodeXMLException {
|
||||
BlockEdge inEdge = new BlockEdge();
|
||||
intothis.add(inEdge);
|
||||
inEdge.restoreXml(parser, blockList);
|
||||
while(inEdge.point.outofthis.size() <= inEdge.reverse_index) {
|
||||
inEdge.decode(decoder, blockList);
|
||||
while (inEdge.point.outofthis.size() <= inEdge.reverse_index) {
|
||||
inEdge.point.outofthis.add(null);
|
||||
}
|
||||
BlockEdge outEdge = new BlockEdge(this,0,intothis.size()-1);
|
||||
BlockEdge outEdge = new BlockEdge(this, 0, intothis.size() - 1);
|
||||
inEdge.point.outofthis.set(inEdge.reverse_index, outEdge);
|
||||
}
|
||||
|
||||
@ -349,8 +348,8 @@ public class PcodeBlock {
|
||||
SpecXmlUtils.encodeSignedIntegerAttribute(buffer, "index", index);
|
||||
}
|
||||
|
||||
public void restoreXmlHeader(XmlElement el) throws PcodeXMLException {
|
||||
index = SpecXmlUtils.decodeInt(el.getAttribute("index"));
|
||||
public void decodeHeader(Decoder decoder) throws PcodeXMLException {
|
||||
index = (int) decoder.readSignedInteger(AttributeId.ATTRIB_INDEX);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -365,28 +364,29 @@ public class PcodeBlock {
|
||||
|
||||
public void saveXmlEdges(Writer writer) throws IOException {
|
||||
StringBuilder buf = new StringBuilder();
|
||||
for (int i = 0; i < intothis.size(); ++i) {
|
||||
intothis.get(i).saveXml(buf);
|
||||
for (BlockEdge element : intothis) {
|
||||
element.saveXml(buf);
|
||||
}
|
||||
writer.write(buf.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore the any additional information beyond header and edges from XML
|
||||
* @param parser is the XML parser
|
||||
* Restore the any additional information beyond header and edges from stream
|
||||
* @param decoder is the stream decoder
|
||||
* @param resolver is for looking up edge references
|
||||
* @throws PcodeXMLException for invalid XML descriptions
|
||||
* @throws PcodeXMLException for invalid encoding
|
||||
*/
|
||||
public void restoreXmlBody(XmlPullParser parser, BlockMap resolver) throws PcodeXMLException {
|
||||
public void decodeBody(Decoder decoder, BlockMap resolver) throws PcodeXMLException {
|
||||
// No body to restore by default
|
||||
}
|
||||
|
||||
public void restoreXmlEdges(XmlPullParser parser, BlockMap resolver) throws PcodeXMLException {
|
||||
while (parser.peek().isStart()) {
|
||||
if (!parser.peek().getName().equals("edge")) {
|
||||
return;
|
||||
public void decodeEdges(Decoder decoder, BlockMap resolver) throws PcodeXMLException {
|
||||
for (;;) {
|
||||
int el = decoder.peekElement();
|
||||
if (el != ElementId.ELEM_EDGE.getId()) {
|
||||
break;
|
||||
}
|
||||
restoreNextInEdge(parser, resolver);
|
||||
decodeNextInEdge(decoder, resolver);
|
||||
}
|
||||
}
|
||||
|
||||
@ -401,11 +401,11 @@ public class PcodeBlock {
|
||||
writer.write("</block>\n");
|
||||
}
|
||||
|
||||
public void restoreXml(XmlPullParser parser, BlockMap resolver) throws PcodeXMLException {
|
||||
XmlElement el = parser.start("block");
|
||||
restoreXmlHeader(el);
|
||||
restoreXmlBody(parser, resolver);
|
||||
restoreXmlEdges(parser, resolver);
|
||||
parser.end(el);
|
||||
public void decode(Decoder decoder, BlockMap resolver) throws PcodeXMLException {
|
||||
int el = decoder.openElement(ElementId.ELEM_BLOCK);
|
||||
decodeHeader(decoder);
|
||||
decodeBody(decoder, resolver);
|
||||
decodeEdges(decoder, resolver);
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
}
|
||||
|
@ -21,8 +21,7 @@ import java.util.Iterator;
|
||||
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.util.xml.SpecXmlUtils;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
@ -31,11 +30,11 @@ import ghidra.xml.XmlPullParser;
|
||||
public class PcodeBlockBasic extends PcodeBlock {
|
||||
private ListLinked<PcodeOp> oplist; // List of PcodeOps making up the basic block
|
||||
private AddressSet cover; // Addresses of instructions making up the block
|
||||
|
||||
|
||||
PcodeBlockBasic() {
|
||||
super();
|
||||
blocktype = PcodeBlock.BASIC;
|
||||
oplist = new ListLinked<PcodeOp>();
|
||||
oplist = new ListLinked<>();
|
||||
cover = new AddressSet();
|
||||
}
|
||||
|
||||
@ -64,21 +63,21 @@ public class PcodeBlockBasic extends PcodeBlock {
|
||||
* @param op is the new PcodeOp to insert
|
||||
*/
|
||||
protected void insertBefore(Iterator<PcodeOp> iter, PcodeOp op) {
|
||||
PcodeOpAST opast = (PcodeOpAST)op;
|
||||
PcodeOpAST opast = (PcodeOpAST) op;
|
||||
opast.setParent(this);
|
||||
Iterator<PcodeOp> newiter = oplist.insertBefore(iter,op);
|
||||
Iterator<PcodeOp> newiter = oplist.insertBefore(iter, op);
|
||||
opast.setBasicIter(newiter);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Insert a new PcodeOp after a specific point in the list of PcodeOps
|
||||
* @param iter points to the PcodeOp to insert after
|
||||
* @param op is the new PcodeOp to insert
|
||||
*/
|
||||
protected void insertAfter(Iterator<PcodeOp> iter, PcodeOp op) {
|
||||
PcodeOpAST opast = (PcodeOpAST)op;
|
||||
PcodeOpAST opast = (PcodeOpAST) op;
|
||||
opast.setParent(this);
|
||||
Iterator<PcodeOp> newiter = oplist.insertAfter(iter,opast);
|
||||
Iterator<PcodeOp> newiter = oplist.insertAfter(iter, opast);
|
||||
opast.setBasicIter(newiter);
|
||||
}
|
||||
|
||||
@ -87,22 +86,22 @@ public class PcodeBlockBasic extends PcodeBlock {
|
||||
* @param op is the PcodeOp to insert
|
||||
*/
|
||||
protected void insertEnd(PcodeOp op) {
|
||||
PcodeOpAST opast = (PcodeOpAST)op;
|
||||
PcodeOpAST opast = (PcodeOpAST) op;
|
||||
opast.setParent(this);
|
||||
Iterator<PcodeOp> newiter = oplist.add(opast);
|
||||
opast.setBasicIter(newiter);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove a PcodeOp from the block
|
||||
* @param op is the PcodeOp to remove
|
||||
*/
|
||||
protected void remove(PcodeOp op) {
|
||||
PcodeOpAST opast = (PcodeOpAST)op;
|
||||
PcodeOpAST opast = (PcodeOpAST) op;
|
||||
opast.setParent(null);
|
||||
oplist.remove(op.getBasicIter());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return an iterator over the PcodeOps in this basic block
|
||||
*/
|
||||
@ -129,21 +128,23 @@ public class PcodeBlockBasic extends PcodeBlock {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreXmlBody(XmlPullParser parser, BlockMap resolver) throws PcodeXMLException {
|
||||
AddressFactory addressFactory = resolver.getAddressFactory();
|
||||
XmlElement rangelistel = parser.start("rangelist");
|
||||
while (parser.peek().isStart()) {
|
||||
XmlElement rangeel = parser.start("range");
|
||||
String spc = rangeel.getAttribute("space");
|
||||
long offset = SpecXmlUtils.decodeLong(rangeel.getAttribute("first"));
|
||||
AddressSpace addressSpace = addressFactory.getAddressSpace(spc);
|
||||
public void decodeBody(Decoder decoder, BlockMap resolver) throws PcodeXMLException {
|
||||
int rangelistel = decoder.openElement(ElementId.ELEM_RANGELIST);
|
||||
for (;;) {
|
||||
int rangeel = decoder.peekElement();
|
||||
if (rangeel != ElementId.ELEM_RANGE.getId()) {
|
||||
break;
|
||||
}
|
||||
decoder.openElement();
|
||||
AddressSpace addressSpace = decoder.readSpace(AttributeId.ATTRIB_SPACE);
|
||||
long offset = decoder.readUnsignedInteger(AttributeId.ATTRIB_FIRST);
|
||||
Address start = addressSpace.getAddress(offset);
|
||||
offset = SpecXmlUtils.decodeLong(rangeel.getAttribute("last"));
|
||||
offset = decoder.readUnsignedInteger(AttributeId.ATTRIB_LAST);
|
||||
Address stop = addressSpace.getAddress(offset);
|
||||
cover.addRange(start, stop);
|
||||
parser.end(rangeel);
|
||||
decoder.closeElement(rangeel);
|
||||
}
|
||||
|
||||
parser.end(rangelistel);
|
||||
decoder.closeElement(rangelistel);
|
||||
}
|
||||
}
|
||||
|
@ -28,8 +28,6 @@ import ghidra.program.model.lang.CompilerSpec;
|
||||
import ghidra.program.model.lang.DecompilerLanguage;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.util.xml.SpecXmlUtils;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -123,13 +121,11 @@ public class PcodeDataTypeManager {
|
||||
* a corresponding data-type exists, this data-type is returned. Otherwise the first
|
||||
* built-in data-type with a matching name is returned
|
||||
* @param nm name of data-type
|
||||
* @param idstr is an optional string containing a data-type id number
|
||||
* @param id is an optional data-type id number
|
||||
* @return the data-type object or null if no matching data-type exists
|
||||
*/
|
||||
public DataType findBaseType(String nm, String idstr) {
|
||||
long id = 0;
|
||||
if (idstr != null) {
|
||||
id = SpecXmlUtils.decodeLong(idstr);
|
||||
public DataType findBaseType(String nm, long id) {
|
||||
if (id != 0) {
|
||||
if (id > 0) {
|
||||
DataType dt = progDataTypes.getDataType(id);
|
||||
if (dt != null) {
|
||||
@ -156,97 +152,106 @@ public class PcodeDataTypeManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the data type that corresponds to the given XML element.
|
||||
* @param parser the xml parser
|
||||
* @return the read data type
|
||||
* @throws PcodeXMLException if the data type could be resolved from the
|
||||
* element
|
||||
* Decode a data-type from the stream
|
||||
* @param decoder is the stream decoder
|
||||
* @return the decoded data-type object
|
||||
* @throws PcodeXMLException for invalid encodings
|
||||
*/
|
||||
public DataType readXMLDataType(XmlPullParser parser) throws PcodeXMLException {
|
||||
XmlElement el = parser.start("type", "void", "typeref", "def");
|
||||
try {
|
||||
if (el == null) {
|
||||
throw new PcodeXMLException("Bad <type> tag");
|
||||
public DataType decodeDataType(Decoder decoder) throws PcodeXMLException {
|
||||
int el = decoder.openElement();
|
||||
if (el == ElementId.ELEM_VOID.getId()) {
|
||||
decoder.closeElement(el);
|
||||
return voidDt;
|
||||
}
|
||||
String name = "";
|
||||
long id = 0;
|
||||
for (;;) {
|
||||
int attribId = decoder.getNextAttributeId();
|
||||
if (attribId == 0) {
|
||||
break;
|
||||
}
|
||||
if (attribId == AttributeId.ATTRIB_NAME.getId()) {
|
||||
name = decoder.readString();
|
||||
}
|
||||
else if (attribId == AttributeId.ATTRIB_ID.getId()) {
|
||||
id = decoder.readUnsignedInteger();
|
||||
}
|
||||
}
|
||||
if (el == ElementId.ELEM_TYPEREF.getId()) {
|
||||
decoder.closeElement(el);
|
||||
return findBaseType(name, id);
|
||||
}
|
||||
if (el == ElementId.ELEM_DEF.getId()) {
|
||||
decoder.closeElementSkipping(el);
|
||||
return findBaseType(name, id);
|
||||
}
|
||||
if (el != ElementId.ELEM_TYPE.getId()) {
|
||||
throw new PcodeXMLException("Expecting <type> element");
|
||||
}
|
||||
|
||||
if (el.getName().equals("void")) {
|
||||
return voidDt;
|
||||
}
|
||||
if (el.getName().equals("typeref")) {
|
||||
return findBaseType(el.getAttribute("name"), el.getAttribute("id"));
|
||||
}
|
||||
if (el.getName().equals("def")) {
|
||||
String nameStr = el.getAttribute("name");
|
||||
String idStr = el.getAttribute("id");
|
||||
parser.discardSubTree(); // Get rid of unused <typeref>
|
||||
return findBaseType(nameStr, idStr);
|
||||
}
|
||||
String name = el.getAttribute("name");
|
||||
if (name.length() != 0) {
|
||||
return findBaseType(name, el.getAttribute("id"));
|
||||
}
|
||||
String meta = el.getAttribute("metatype");
|
||||
DataType restype = null;
|
||||
if (meta.equals("ptr")) {
|
||||
int size = SpecXmlUtils.decodeInt(el.getAttribute("size"));
|
||||
if (parser.peek().isStart()) {
|
||||
DataType dt = readXMLDataType(parser);
|
||||
boolean useDefaultSize = (size == dataOrganization.getPointerSize() ||
|
||||
size > PointerDataType.MAX_POINTER_SIZE_BYTES);
|
||||
restype = new PointerDataType(dt, useDefaultSize ? -1 : size, progDataTypes);
|
||||
}
|
||||
}
|
||||
else if (meta.equals("array")) {
|
||||
int arrsize = SpecXmlUtils.decodeInt(el.getAttribute("arraysize"));
|
||||
if (parser.peek().isStart()) {
|
||||
DataType dt = readXMLDataType(parser);
|
||||
if (dt == null || dt.getLength() == 0) {
|
||||
dt = DataType.DEFAULT;
|
||||
}
|
||||
restype = new ArrayDataType(dt, arrsize, dt.getLength(), progDataTypes);
|
||||
}
|
||||
}
|
||||
else if (meta.equals("spacebase")) { // Typically the type of "the whole stack"
|
||||
parser.discardSubTree(); // get rid of unused "addr" element
|
||||
return voidDt;
|
||||
}
|
||||
else if (meta.equals("struct")) {
|
||||
// we now can reach here with the decompiler inventing structures, apparently
|
||||
// this is a band-aid so that we don't blow up
|
||||
// just make an undefined data type of the appropriate size
|
||||
int size = SpecXmlUtils.decodeInt(el.getAttribute("size"));
|
||||
return Undefined.getUndefinedDataType(size);
|
||||
// OLD COMMENT:
|
||||
// Structures should always be named so we should never reach here
|
||||
// if all the structures are contained in ghidra. I should probably add the
|
||||
// parsing here so the decompiler can pass new structures into ghidra
|
||||
}
|
||||
else if (meta.equals("int")) {
|
||||
int size = SpecXmlUtils.decodeInt(el.getAttribute("size"));
|
||||
return AbstractIntegerDataType.getSignedDataType(size, progDataTypes);
|
||||
}
|
||||
else if (meta.equals("uint")) {
|
||||
int size = SpecXmlUtils.decodeInt(el.getAttribute("size"));
|
||||
return AbstractIntegerDataType.getUnsignedDataType(size, progDataTypes);
|
||||
}
|
||||
else if (meta.equals("float")) {
|
||||
int size = SpecXmlUtils.decodeInt(el.getAttribute("size"));
|
||||
return AbstractFloatDataType.getFloatDataType(size, progDataTypes);
|
||||
}
|
||||
else { // We typically reach here if the decompiler invents a new type
|
||||
// probably an unknown with a non-standard size
|
||||
int size = SpecXmlUtils.decodeInt(el.getAttribute("size"));
|
||||
return Undefined.getUndefinedDataType(size).clone(progDataTypes);
|
||||
}
|
||||
if (restype == null) {
|
||||
throw new PcodeXMLException("Unable to resolve DataType");
|
||||
}
|
||||
return restype;
|
||||
if (name.length() != 0) {
|
||||
decoder.closeElementSkipping(el);
|
||||
return findBaseType(name, id);
|
||||
}
|
||||
finally {
|
||||
parser.discardSubTree(el);
|
||||
// parser.end(el);
|
||||
String meta = decoder.readString(AttributeId.ATTRIB_METATYPE);
|
||||
DataType restype = null;
|
||||
if (meta.equals("ptr")) {
|
||||
int size = (int) decoder.readSignedInteger(AttributeId.ATTRIB_SIZE);
|
||||
if (decoder.peekElement() != 0) {
|
||||
DataType dt = decodeDataType(decoder);
|
||||
boolean useDefaultSize = (size == dataOrganization.getPointerSize() ||
|
||||
size > PointerDataType.MAX_POINTER_SIZE_BYTES);
|
||||
restype = new PointerDataType(dt, useDefaultSize ? -1 : size, progDataTypes);
|
||||
}
|
||||
}
|
||||
else if (meta.equals("array")) {
|
||||
int arrsize = (int) decoder.readSignedInteger(AttributeId.ATTRIB_ARRAYSIZE);
|
||||
if (decoder.peekElement() != 0) {
|
||||
DataType dt = decodeDataType(decoder);
|
||||
if (dt == null || dt.getLength() == 0) {
|
||||
dt = DataType.DEFAULT;
|
||||
}
|
||||
restype = new ArrayDataType(dt, arrsize, dt.getLength(), progDataTypes);
|
||||
}
|
||||
}
|
||||
else if (meta.equals("spacebase")) { // Typically the type of "the whole stack"
|
||||
decoder.closeElementSkipping(el); // get rid of unused "addr" element
|
||||
return voidDt;
|
||||
}
|
||||
else if (meta.equals("struct")) {
|
||||
// We reach here if the decompiler invents a structure, apparently
|
||||
// this is a band-aid so that we don't blow up
|
||||
// just make an undefined data type of the appropriate size
|
||||
int size = (int) decoder.readSignedInteger(AttributeId.ATTRIB_SIZE);
|
||||
decoder.closeElementSkipping(el);
|
||||
return Undefined.getUndefinedDataType(size);
|
||||
}
|
||||
else if (meta.equals("int")) {
|
||||
int size = (int) decoder.readSignedInteger(AttributeId.ATTRIB_SIZE);
|
||||
decoder.closeElement(el);
|
||||
return AbstractIntegerDataType.getSignedDataType(size, progDataTypes);
|
||||
}
|
||||
else if (meta.equals("uint")) {
|
||||
int size = (int) decoder.readSignedInteger(AttributeId.ATTRIB_SIZE);
|
||||
decoder.closeElement(el);
|
||||
return AbstractIntegerDataType.getUnsignedDataType(size, progDataTypes);
|
||||
}
|
||||
else if (meta.equals("float")) {
|
||||
int size = (int) decoder.readSignedInteger(AttributeId.ATTRIB_SIZE);
|
||||
decoder.closeElement(el);
|
||||
return AbstractFloatDataType.getFloatDataType(size, progDataTypes);
|
||||
}
|
||||
else { // We typically reach here if the decompiler invents a new type
|
||||
// probably an unknown with a non-standard size
|
||||
int size = (int) decoder.readSignedInteger(AttributeId.ATTRIB_SIZE);
|
||||
decoder.closeElement(el);
|
||||
return Undefined.getUndefinedDataType(size).clone(progDataTypes);
|
||||
}
|
||||
if (restype == null) {
|
||||
throw new PcodeXMLException("Unable to resolve DataType");
|
||||
}
|
||||
decoder.closeElementSkipping(el);
|
||||
return restype;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -23,7 +23,7 @@ import ghidra.program.model.data.DataType;
|
||||
import ghidra.program.model.lang.UnknownInstructionException;
|
||||
import ghidra.program.model.listing.VariableStorage;
|
||||
import ghidra.util.exception.InvalidInputException;
|
||||
import ghidra.xml.XmlElement;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
@ -35,12 +35,12 @@ public interface PcodeFactory {
|
||||
* @return Address factory
|
||||
*/
|
||||
public AddressFactory getAddressFactory();
|
||||
|
||||
|
||||
/**
|
||||
* @return pcode data type manager used to convert strings to Ghidra data types
|
||||
*/
|
||||
public PcodeDataTypeManager getDataTypeManager();
|
||||
|
||||
|
||||
/**
|
||||
* Create a new Varnode with the given size an location
|
||||
*
|
||||
@ -49,24 +49,46 @@ public interface PcodeFactory {
|
||||
*
|
||||
* @return a new varnode
|
||||
*/
|
||||
public Varnode newVarnode(int sz,Address addr);
|
||||
|
||||
public Varnode newVarnode(int sz,Address addr,int refId);
|
||||
public VariableStorage readXMLVarnodePieces(XmlElement el, Address addr) throws PcodeXMLException, InvalidInputException;
|
||||
public Varnode createFromStorage(Address addr,VariableStorage storage, int logicalSize);
|
||||
public Varnode newVarnode(int sz, Address addr);
|
||||
|
||||
public Varnode newVarnode(int sz, Address addr, int refId);
|
||||
|
||||
/**
|
||||
* Decode a join address from "piece" attributes
|
||||
*
|
||||
* @param decoder is the stream decoder
|
||||
* @param addr join address associated with pieces
|
||||
*
|
||||
* @return the decoded VariableStorage
|
||||
* @throws PcodeXMLException for an improperly encoded stream
|
||||
* @throws InvalidInputException if the pieces are not valid storage locations
|
||||
*/
|
||||
public VariableStorage decodeVarnodePieces(Decoder decoder, Address addr)
|
||||
throws PcodeXMLException, InvalidInputException;
|
||||
|
||||
public Varnode createFromStorage(Address addr, VariableStorage storage, int logicalSize);
|
||||
|
||||
public VariableStorage buildStorage(Varnode vn) throws InvalidInputException;
|
||||
|
||||
public Varnode getRef(int refid);
|
||||
|
||||
public PcodeOp getOpRef(int refid);
|
||||
|
||||
public HighSymbol getSymbol(long symbolId);
|
||||
public Varnode setInput(Varnode vn,boolean val);
|
||||
public void setAddrTied(Varnode vn,boolean val);
|
||||
|
||||
public Varnode setInput(Varnode vn, boolean val);
|
||||
|
||||
public void setAddrTied(Varnode vn, boolean val);
|
||||
|
||||
public void setPersistent(Varnode vn, boolean val);
|
||||
public void setUnaffected(Varnode vn,boolean val);
|
||||
public void setMergeGroup(Varnode vn,short val);
|
||||
public void setDataType(Varnode vn,DataType type);
|
||||
|
||||
public PcodeOp newOp(SequenceNumber sq,int opc,ArrayList<Varnode> inputs,Varnode output)
|
||||
throws UnknownInstructionException;
|
||||
|
||||
|
||||
public void setUnaffected(Varnode vn, boolean val);
|
||||
|
||||
public void setMergeGroup(Varnode vn, short val);
|
||||
|
||||
public void setDataType(Varnode vn, DataType type);
|
||||
|
||||
public PcodeOp newOp(SequenceNumber sq, int opc, ArrayList<Varnode> inputs, Varnode output)
|
||||
throws UnknownInstructionException;
|
||||
|
||||
}
|
||||
|
@ -20,8 +20,6 @@ import java.util.*;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.lang.UnknownInstructionException;
|
||||
import ghidra.util.xml.SpecXmlUtils;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -418,7 +416,7 @@ public class PcodeOp {
|
||||
output = vn;
|
||||
}
|
||||
|
||||
public void buildXML(StringBuilder resBuf,AddressFactory addrFactory) {
|
||||
public void buildXML(StringBuilder resBuf, AddressFactory addrFactory) {
|
||||
resBuf.append("<op");
|
||||
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "code", opcode);
|
||||
resBuf.append('>');
|
||||
@ -446,29 +444,26 @@ public class PcodeOp {
|
||||
}
|
||||
|
||||
/**
|
||||
* Read p-code from XML stream
|
||||
* Decode p-code from a stream
|
||||
*
|
||||
* @param parser is the XML stream
|
||||
* @param decoder is the stream decoder
|
||||
* @param pfact factory used to create p-code correctly
|
||||
*
|
||||
* @return new PcodeOp
|
||||
* @throws PcodeXMLException if XML layout is incorrect
|
||||
* @throws PcodeXMLException if encodings are invalid
|
||||
*/
|
||||
public static PcodeOp readXML(XmlPullParser parser, PcodeFactory pfact)
|
||||
throws PcodeXMLException {
|
||||
XmlElement el = parser.start("op");
|
||||
int opc = SpecXmlUtils.decodeInt(el.getAttribute("code"));
|
||||
if (!parser.peek().isStart()) {
|
||||
throw new PcodeXMLException("Missing <seqnum> in PcodeOp");
|
||||
}
|
||||
SequenceNumber seqnum = SequenceNumber.readXML(parser, pfact.getAddressFactory());
|
||||
if (!parser.peek().isStart()) {
|
||||
throw new PcodeXMLException("Missing output in PcodeOp");
|
||||
}
|
||||
Varnode output = Varnode.readXML(parser, pfact);
|
||||
ArrayList<Varnode> inputlist = new ArrayList<Varnode>();
|
||||
while (parser.peek().isStart()) {
|
||||
Varnode vn = Varnode.readXML(parser, pfact);
|
||||
public static PcodeOp decode(Decoder decoder, PcodeFactory pfact) throws PcodeXMLException {
|
||||
int el = decoder.openElement(ElementId.ELEM_OP);
|
||||
int opc = (int) decoder.readSignedInteger(AttributeId.ATTRIB_CODE);
|
||||
SequenceNumber seqnum = SequenceNumber.decode(decoder);
|
||||
Varnode output = Varnode.decode(decoder, pfact);
|
||||
ArrayList<Varnode> inputlist = new ArrayList<>();
|
||||
for (;;) {
|
||||
int subel = decoder.peekElement();
|
||||
if (subel == 0) {
|
||||
break;
|
||||
}
|
||||
Varnode vn = Varnode.decode(decoder, pfact);
|
||||
inputlist.add(vn);
|
||||
}
|
||||
PcodeOp res;
|
||||
@ -478,7 +473,7 @@ public class PcodeOp {
|
||||
catch (UnknownInstructionException e) {
|
||||
throw new PcodeXMLException("Bad opcode: " + e.getMessage(), e);
|
||||
}
|
||||
parser.end(el);
|
||||
decoder.closeElement(el);
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -522,7 +517,7 @@ public class PcodeOp {
|
||||
* Generate a lookup table that maps pcode mnemonic strings to pcode operation codes.
|
||||
*/
|
||||
private static void generateOpcodeTable() {
|
||||
opcodeTable = new Hashtable<String, Integer>();
|
||||
opcodeTable = new Hashtable<>();
|
||||
for (int i = 0; i < PCODE_MAX; i++) {
|
||||
opcodeTable.put(getMnemonic(i), i);
|
||||
}
|
||||
|
@ -22,9 +22,6 @@ import ghidra.program.model.data.DataType;
|
||||
import ghidra.program.model.lang.UnknownInstructionException;
|
||||
import ghidra.program.model.listing.VariableStorage;
|
||||
import ghidra.util.exception.InvalidInputException;
|
||||
import ghidra.util.xml.SpecXmlUtils;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -99,26 +96,23 @@ public class PcodeSyntaxTree implements PcodeFactory {
|
||||
return new Varnode(space.getAddress(offset), size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read an XML join address with "piece" attributes
|
||||
*
|
||||
* @param el SAX parse tree element
|
||||
* @param addr join address associated with pieces
|
||||
*
|
||||
* @return the VariableStorage associated with xml
|
||||
* @throws PcodeXMLException for improperly formatted XML
|
||||
* @throws InvalidInputException if the pieces are not valid storage locations
|
||||
*/
|
||||
@Override
|
||||
public VariableStorage readXMLVarnodePieces(XmlElement el, Address addr)
|
||||
public VariableStorage decodeVarnodePieces(Decoder decoder, Address addr)
|
||||
throws PcodeXMLException, InvalidInputException {
|
||||
ArrayList<Varnode> list = new ArrayList<>();
|
||||
int index = 1;
|
||||
String nextPiece = "piece" + index;
|
||||
while (el.hasAttribute(nextPiece)) {
|
||||
String pieceStr = el.getAttribute(nextPiece);
|
||||
list.add(getVarnodePiece(pieceStr, addrFactory));
|
||||
nextPiece = "piece" + ++index;
|
||||
for (;;) {
|
||||
int attribId = decoder.getNextAttributeId();
|
||||
if (attribId == 0) {
|
||||
break;
|
||||
}
|
||||
else if (attribId >= AttributeId.ATTRIB_PIECE1.getId() &&
|
||||
attribId <= AttributeId.ATTRIB_PIECE9.getId()) {
|
||||
int index = attribId - AttributeId.ATTRIB_PIECE1.getId();
|
||||
if (index != list.size()) {
|
||||
throw new PcodeXMLException("\"piece\" attributes must be in order");
|
||||
}
|
||||
list.add(getVarnodePiece(decoder.readString(), decoder.getAddressFactory()));
|
||||
}
|
||||
}
|
||||
Varnode[] pieces = new Varnode[list.size()];
|
||||
list.toArray(pieces);
|
||||
@ -526,23 +520,30 @@ public class PcodeSyntaxTree implements PcodeFactory {
|
||||
return op;
|
||||
}
|
||||
|
||||
private void readVarnodeXML(XmlPullParser parser) throws PcodeXMLException {
|
||||
XmlElement el = parser.start("varnodes");
|
||||
while (parser.peek().isStart()) {
|
||||
Varnode.readXML(parser, this);
|
||||
private void decodeVarnode(Decoder decoder) throws PcodeXMLException {
|
||||
int el = decoder.openElement(ElementId.ELEM_VARNODES);
|
||||
for (;;) {
|
||||
int subId = decoder.peekElement();
|
||||
if (subId == 0) {
|
||||
break;
|
||||
}
|
||||
Varnode.decode(decoder, this);
|
||||
}
|
||||
parser.end(el);
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
|
||||
private void readBasicBlockXML(XmlPullParser parser, BlockMap resolver)
|
||||
throws PcodeXMLException {
|
||||
XmlElement el = parser.start("block");
|
||||
private void decodeBasicBlock(Decoder decoder, BlockMap resolver) throws PcodeXMLException {
|
||||
int el = decoder.openElement(ElementId.ELEM_BLOCK);
|
||||
int order = 0;
|
||||
PcodeBlockBasic bl = new PcodeBlockBasic();
|
||||
bl.restoreXmlHeader(el);
|
||||
bl.restoreXmlBody(parser, resolver);
|
||||
while (parser.peek().isStart()) {
|
||||
PcodeOp op = PcodeOp.readXML(parser, this);
|
||||
bl.decodeHeader(decoder);
|
||||
bl.decodeBody(decoder, resolver);
|
||||
for (;;) {
|
||||
int subel = decoder.peekElement();
|
||||
if (subel == 0) {
|
||||
break;
|
||||
}
|
||||
PcodeOp op = PcodeOp.decode(decoder, this);
|
||||
op.setOrder(order);
|
||||
order += 1;
|
||||
bl.insertEnd(op);
|
||||
@ -552,37 +553,44 @@ public class PcodeSyntaxTree implements PcodeFactory {
|
||||
bblocks.add(null);
|
||||
}
|
||||
bblocks.set(index, bl);
|
||||
parser.end(el);
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
|
||||
private void readBlockEdgeXML(XmlPullParser parser) throws PcodeXMLException {
|
||||
XmlElement el = parser.start("blockedge");
|
||||
int blockInd = SpecXmlUtils.decodeInt(el.getAttribute("index"));
|
||||
private void decodeBlockEdge(Decoder decoder) throws PcodeXMLException {
|
||||
int el = decoder.openElement(ElementId.ELEM_BLOCKEDGE);
|
||||
int blockInd = (int) decoder.readSignedInteger(AttributeId.ATTRIB_INDEX);
|
||||
PcodeBlockBasic curBlock = bblocks.get(blockInd);
|
||||
while (parser.peek().isStart()) {
|
||||
curBlock.restoreNextInEdge(parser, bblocks);
|
||||
for (;;) {
|
||||
int subel = decoder.peekElement();
|
||||
if (subel == 0) {
|
||||
break;
|
||||
}
|
||||
curBlock.decodeNextInEdge(decoder, bblocks);
|
||||
}
|
||||
parser.end(el);
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
|
||||
public void readXML(XmlPullParser parser) throws PcodeXMLException {
|
||||
XmlElement el = parser.start("ast");
|
||||
public void decode(Decoder decoder) throws PcodeXMLException {
|
||||
int el = decoder.openElement(ElementId.ELEM_AST);
|
||||
if (!vbank.isEmpty()) {
|
||||
clear();
|
||||
}
|
||||
readVarnodeXML(parser);
|
||||
decodeVarnode(decoder);
|
||||
buildVarnodeRefs(); // Build the HashMap
|
||||
BlockMap blockMap = new BlockMap(addrFactory);
|
||||
while (parser.peek().isStart()) {
|
||||
XmlElement subel = parser.peek();
|
||||
if (subel.getName().equals("block")) {
|
||||
readBasicBlockXML(parser, blockMap); // Read a basic block and all its PcodeOps
|
||||
for (;;) {
|
||||
int subel = decoder.peekElement();
|
||||
if (subel == 0) {
|
||||
break;
|
||||
}
|
||||
else if (subel == ElementId.ELEM_BLOCK.getId()) {
|
||||
decodeBasicBlock(decoder, blockMap); // Read a basic block and all its PcodeOps
|
||||
}
|
||||
else {
|
||||
readBlockEdgeXML(parser);
|
||||
decodeBlockEdge(decoder);
|
||||
}
|
||||
}
|
||||
parser.end(el);
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -15,9 +15,9 @@
|
||||
*/
|
||||
package ghidra.program.model.pcode;
|
||||
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.util.xml.*;
|
||||
import ghidra.xml.*;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressSpace;
|
||||
import ghidra.util.xml.SpecXmlUtils;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -29,10 +29,10 @@ import ghidra.xml.*;
|
||||
public class SequenceNumber implements Comparable<SequenceNumber> {
|
||||
private Address pc; // Address of assembly language instruction
|
||||
private int uniq; // Sub-address for distinguishing multiple PcodeOps at one
|
||||
// instruction address. Does not change over lifetime of PcodeOp
|
||||
// instruction address. Does not change over lifetime of PcodeOp
|
||||
private int order; // Contains relative position information of PcodeOps within
|
||||
// a basic block, may change as basic block is edited.
|
||||
|
||||
// a basic block, may change as basic block is edited.
|
||||
|
||||
/**
|
||||
* Construct a sequence number for an instruction at an address and sequence of pcode op within
|
||||
* that instructions set of pcode.
|
||||
@ -44,14 +44,14 @@ public class SequenceNumber implements Comparable<SequenceNumber> {
|
||||
pc = instrAddr;
|
||||
uniq = sequenceNum;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return get address of instruction this sequence belongs to
|
||||
*/
|
||||
public Address getTarget() {
|
||||
return pc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get unique Sub-address for distinguishing multiple PcodeOps at one
|
||||
* instruction address.
|
||||
@ -71,9 +71,9 @@ public class SequenceNumber implements Comparable<SequenceNumber> {
|
||||
* @param t unique id
|
||||
*/
|
||||
public void setTime(int t) {
|
||||
uniq = t;
|
||||
uniq = t;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get relative position information of PcodeOps within
|
||||
* a basic block, may change as basic block is edited.
|
||||
@ -83,7 +83,7 @@ public class SequenceNumber implements Comparable<SequenceNumber> {
|
||||
public int getOrder() {
|
||||
return order;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set relative position information of PcodeOps within
|
||||
* a basic block, may change as basic block is edited.
|
||||
@ -93,25 +93,34 @@ public class SequenceNumber implements Comparable<SequenceNumber> {
|
||||
public void setOrder(int o) {
|
||||
order = o;
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof SequenceNumber)) return false;
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof SequenceNumber)) {
|
||||
return false;
|
||||
}
|
||||
SequenceNumber sq = (SequenceNumber) o;
|
||||
return (pc.equals(sq.pc)&&(uniq==sq.uniq));
|
||||
return (pc.equals(sq.pc) && (uniq == sq.uniq));
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Comparable#compareTo(java.lang.Object)
|
||||
*/
|
||||
public int compareTo(SequenceNumber sq) {
|
||||
@Override
|
||||
public int compareTo(SequenceNumber sq) {
|
||||
int val = pc.compareTo(sq.pc);
|
||||
if (val != 0) return val;
|
||||
if (uniq < sq.uniq) return -1;
|
||||
if (sq.uniq < uniq) return 1;
|
||||
if (val != 0) {
|
||||
return val;
|
||||
}
|
||||
if (uniq < sq.uniq) {
|
||||
return -1;
|
||||
}
|
||||
if (sq.uniq < uniq) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -124,56 +133,53 @@ public class SequenceNumber implements Comparable<SequenceNumber> {
|
||||
AddressSpace space = pc.getAddressSpace();
|
||||
SpecXmlUtils.encodeStringAttribute(resBuf, "space", space.getName());
|
||||
SpecXmlUtils.encodeUnsignedIntegerAttribute(resBuf, "offset", pc.getOffset());
|
||||
if (uniq != -1)
|
||||
if (uniq != -1) {
|
||||
SpecXmlUtils.encodeUnsignedIntegerAttribute(resBuf, "uniq", uniq);
|
||||
}
|
||||
resBuf.append("/>");
|
||||
return resBuf;
|
||||
return resBuf;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a new Sequence number from XML SAX tree element.
|
||||
* Decode a new Sequence number from the stream
|
||||
*
|
||||
* @param parser the xml parser
|
||||
* @param factory pcode factory used to create new pcode
|
||||
* @param decoder is the stream decoder
|
||||
*
|
||||
* @return new sequence number
|
||||
* @throws PcodeXMLException for an invalid encoding
|
||||
*/
|
||||
public static SequenceNumber readXML(XmlPullParser parser,AddressFactory factory) {
|
||||
XmlElement el = parser.start("seqnum");
|
||||
String attrstring = el.getAttribute("uniq");
|
||||
int uniq;
|
||||
if (attrstring != null)
|
||||
uniq = SpecXmlUtils.decodeInt(attrstring);
|
||||
else
|
||||
uniq = -1; // Should fill in with something from factory
|
||||
String space = el.getAttribute("space");
|
||||
AddressSpace spc = factory.getAddressSpace(space);
|
||||
long offset = SpecXmlUtils.decodeLong(el.getAttribute("offset"));
|
||||
parser.end(el);
|
||||
return new SequenceNumber(spc.getAddress(offset),uniq);
|
||||
public static SequenceNumber decode(Decoder decoder) throws PcodeXMLException {
|
||||
int el = decoder.openElement(ElementId.ELEM_SEQNUM);
|
||||
int uniq = -1;
|
||||
for (;;) {
|
||||
int attribId = decoder.getNextAttributeId();
|
||||
if (attribId == 0) {
|
||||
break;
|
||||
}
|
||||
else if (attribId == AttributeId.ATTRIB_UNIQ.getId()) {
|
||||
uniq = (int) decoder.readUnsignedInteger();
|
||||
}
|
||||
}
|
||||
AddressSpace spc = decoder.readSpace(AttributeId.ATTRIB_SPACE);
|
||||
long offset = decoder.readUnsignedInteger(AttributeId.ATTRIB_OFFSET);
|
||||
decoder.closeElement(el);
|
||||
return new SequenceNumber(spc.getAddress(offset), uniq);
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return ("("
|
||||
+ pc.getAddressSpace().getName()
|
||||
+ ", 0x"
|
||||
+ Long.toHexString(pc.getOffset())
|
||||
+ ", "
|
||||
+ uniq
|
||||
+ ", "
|
||||
+ order
|
||||
+ ")");
|
||||
public String toString() {
|
||||
return ("(" + pc.getAddressSpace().getName() + ", 0x" + Long.toHexString(pc.getOffset()) +
|
||||
", " + uniq + ", " + order + ")");
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
public int hashCode() {
|
||||
return pc.hashCode() + uniq; // Don't hash order, as this is mutable
|
||||
}
|
||||
|
||||
|
@ -19,8 +19,6 @@ import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressSpace;
|
||||
import ghidra.program.model.listing.VariableStorage;
|
||||
import ghidra.util.xml.SpecXmlUtils;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
|
||||
/**
|
||||
* A mapping from a HighSymbol object to the storage that holds the symbol's value.
|
||||
@ -39,12 +37,11 @@ public abstract class SymbolEntry {
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore this entry from the given XML stream. Typically more than one tag is consumed
|
||||
* @param parser is the given XML stream
|
||||
* @throws PcodeXMLException if the XML is invalid
|
||||
* Decode this entry from the stream. Typically more than one element is consumed.
|
||||
* @param decoder is the stream decoder
|
||||
* @throws PcodeXMLException for invalid encodings
|
||||
*/
|
||||
public abstract void restoreXML(XmlPullParser parser)
|
||||
throws PcodeXMLException;
|
||||
public abstract void decode(Decoder decoder) throws PcodeXMLException;
|
||||
|
||||
/**
|
||||
* Save this entry as (a set of) XML tags to the given stream
|
||||
@ -83,21 +80,22 @@ public abstract class SymbolEntry {
|
||||
return pcaddr;
|
||||
}
|
||||
|
||||
protected void parseRangeList(XmlPullParser parser) {
|
||||
XmlElement rangelistel = parser.start("rangelist");
|
||||
if (parser.peek().isStart()) {
|
||||
protected void decodeRangeList(Decoder decoder) throws PcodeXMLException {
|
||||
int rangelistel = decoder.openElement(ElementId.ELEM_RANGELIST);
|
||||
if (decoder.peekElement() != 0) {
|
||||
// we only use this to establish first-use
|
||||
XmlElement rangeel = parser.start("range");
|
||||
String spc = rangeel.getAttribute("space");
|
||||
long offset = SpecXmlUtils.decodeLong(rangeel.getAttribute("first"));
|
||||
pcaddr = symbol.function.getAddressFactory().getAddressSpace(spc).getAddress(offset);
|
||||
pcaddr =
|
||||
symbol.function.getFunction().getEntryPoint().getAddressSpace().getOverlayAddress(
|
||||
pcaddr);
|
||||
parser.end(rangeel);
|
||||
int rangeel = decoder.openElement(ElementId.ELEM_RANGE);
|
||||
AddressSpace spc = decoder.readSpace(AttributeId.ATTRIB_SPACE);
|
||||
long offset = decoder.readUnsignedInteger(AttributeId.ATTRIB_FIRST);
|
||||
pcaddr = spc.getAddress(offset);
|
||||
pcaddr = symbol.function.getFunction()
|
||||
.getEntryPoint()
|
||||
.getAddressSpace()
|
||||
.getOverlayAddress(pcaddr);
|
||||
decoder.closeElement(rangeel);
|
||||
}
|
||||
|
||||
parser.end(rangelistel);
|
||||
decoder.closeElement(rangelistel);
|
||||
}
|
||||
|
||||
protected void buildRangelistXML(StringBuilder res) {
|
||||
|
@ -21,9 +21,6 @@ import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.lang.Language;
|
||||
import ghidra.program.model.lang.Register;
|
||||
import ghidra.util.exception.InvalidInputException;
|
||||
import ghidra.util.xml.SpecXmlUtils;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -322,83 +319,97 @@ public class Varnode {
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a Varnode from an XML stream
|
||||
* Decode a Varnode from a stream
|
||||
*
|
||||
* @param parser the parser
|
||||
* @param decoder is the stream decoder
|
||||
* @param factory pcode factory used to create valid pcode
|
||||
* @return new varnode element based on info in the XML.
|
||||
* @return the new Varnode
|
||||
* @throws PcodeXMLException if XML is improperly formed
|
||||
*/
|
||||
public static Varnode readXML(XmlPullParser parser, PcodeFactory factory)
|
||||
throws PcodeXMLException {
|
||||
XmlElement el = parser.start();
|
||||
try {
|
||||
if (el.getName().equals("void")) {
|
||||
return null;
|
||||
public static Varnode decode(Decoder decoder, PcodeFactory factory) throws PcodeXMLException {
|
||||
int el = decoder.peekElement();
|
||||
if (el == ElementId.ELEM_VOID.getId()) {
|
||||
decoder.openElement();
|
||||
decoder.closeElement(el);
|
||||
return null;
|
||||
}
|
||||
else if (el == ElementId.ELEM_SPACEID.getId() || el == ElementId.ELEM_IOP.getId()) {
|
||||
Address addr = AddressXML.decode(decoder);
|
||||
return factory.newVarnode(4, addr);
|
||||
}
|
||||
|
||||
el = decoder.openElement();
|
||||
int ref = -1;
|
||||
int sz = 4;
|
||||
for (;;) {
|
||||
int attribId = decoder.getNextAttributeId();
|
||||
if (attribId == 0) {
|
||||
break;
|
||||
}
|
||||
Varnode vn;
|
||||
String attrstring = el.getAttribute("ref");
|
||||
int ref = -1;
|
||||
if (attrstring != null) {
|
||||
ref = SpecXmlUtils.decodeInt(attrstring); // If we have a reference
|
||||
vn = factory.getRef(ref); // The varnode may already exist
|
||||
else if (attribId == AttributeId.ATTRIB_REF.getId()) { // If we have a reference
|
||||
ref = (int) decoder.readUnsignedInteger();
|
||||
Varnode vn = factory.getRef(ref); // The varnode may already exit
|
||||
if (vn != null) {
|
||||
decoder.closeElement(el);
|
||||
return vn;
|
||||
}
|
||||
}
|
||||
Address addr = AddressXML.readXML(el, factory.getAddressFactory());
|
||||
if (addr == null) {
|
||||
return null;
|
||||
else if (attribId == AttributeId.ATTRIB_SIZE.getId()) {
|
||||
sz = (int) decoder.readSignedInteger();
|
||||
}
|
||||
int sz;
|
||||
attrstring = el.getAttribute("size");
|
||||
if (attrstring != null) {
|
||||
sz = SpecXmlUtils.decodeInt(attrstring);
|
||||
}
|
||||
decoder.rewindAttributes();
|
||||
Varnode vn;
|
||||
Address addr = AddressXML.decodeFromAttributes(decoder);
|
||||
if (ref != -1) {
|
||||
vn = factory.newVarnode(sz, addr, ref);
|
||||
}
|
||||
else {
|
||||
vn = factory.newVarnode(sz, addr);
|
||||
}
|
||||
AddressSpace spc = addr.getAddressSpace();
|
||||
if ((spc != null) && (spc.getType() == AddressSpace.TYPE_VARIABLE)) { // Check for a composite Address
|
||||
decoder.rewindAttributes();
|
||||
try {
|
||||
factory.decodeVarnodePieces(decoder, addr);
|
||||
}
|
||||
else {
|
||||
sz = 4;
|
||||
catch (InvalidInputException e) {
|
||||
throw new PcodeXMLException("Invalid varnode pieces: " + e.getMessage());
|
||||
}
|
||||
if (ref != -1) {
|
||||
vn = factory.newVarnode(sz, addr, ref);
|
||||
}
|
||||
decoder.rewindAttributes();
|
||||
for (;;) {
|
||||
int attribId = decoder.getNextAttributeId();
|
||||
if (attribId == 0) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
vn = factory.newVarnode(sz, addr);
|
||||
}
|
||||
AddressSpace spc = addr.getAddressSpace();
|
||||
if ((spc != null) && (spc.getType() == AddressSpace.TYPE_VARIABLE)) { // Check for a composite Address
|
||||
try {
|
||||
factory.readXMLVarnodePieces(el, addr);
|
||||
}
|
||||
catch (InvalidInputException e) {
|
||||
throw new PcodeXMLException("Invalid varnode pieces: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
attrstring = el.getAttribute("grp");
|
||||
if (attrstring != null) {
|
||||
short val = (short) SpecXmlUtils.decodeInt(attrstring);
|
||||
else if (attribId == AttributeId.ATTRIB_GRP.getId()) {
|
||||
short val = (short) decoder.readSignedInteger();
|
||||
factory.setMergeGroup(vn, val);
|
||||
}
|
||||
attrstring = el.getAttribute("persists");
|
||||
if ((attrstring != null) && (SpecXmlUtils.decodeBoolean(attrstring))) {
|
||||
factory.setPersistent(vn, true);
|
||||
else if (attribId == AttributeId.ATTRIB_PERSISTS.getId()) {
|
||||
if (decoder.readBool()) {
|
||||
factory.setPersistent(vn, true);
|
||||
}
|
||||
}
|
||||
attrstring = el.getAttribute("addrtied");
|
||||
if ((attrstring != null) && (SpecXmlUtils.decodeBoolean(attrstring))) {
|
||||
factory.setAddrTied(vn, true);
|
||||
else if (attribId == AttributeId.ATTRIB_ADDRTIED.getId()) {
|
||||
if (decoder.readBool()) {
|
||||
factory.setAddrTied(vn, true);
|
||||
}
|
||||
}
|
||||
attrstring = el.getAttribute("unaff");
|
||||
if ((attrstring != null) && (SpecXmlUtils.decodeBoolean(attrstring))) {
|
||||
factory.setUnaffected(vn, true);
|
||||
else if (attribId == AttributeId.ATTRIB_UNAFF.getId()) {
|
||||
if (decoder.readBool()) {
|
||||
factory.setUnaffected(vn, true);
|
||||
}
|
||||
}
|
||||
attrstring = el.getAttribute("input");
|
||||
if ((attrstring != null) && (SpecXmlUtils.decodeBoolean(attrstring))) {
|
||||
vn = factory.setInput(vn, true);
|
||||
else if (attribId == AttributeId.ATTRIB_INPUT.getId()) {
|
||||
if (decoder.readBool()) {
|
||||
vn = factory.setInput(vn, true);
|
||||
}
|
||||
}
|
||||
return vn;
|
||||
}
|
||||
finally {
|
||||
parser.end(el);
|
||||
}
|
||||
decoder.closeElement(sz);
|
||||
return vn;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -16,6 +15,7 @@
|
||||
*/
|
||||
package ghidra.xml;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
public interface XmlElement {
|
||||
@ -31,6 +31,8 @@ public interface XmlElement {
|
||||
|
||||
public Map<String, String> getAttributes();
|
||||
|
||||
public Iterator<Map.Entry<String, String>> getAttributeIterator();
|
||||
|
||||
public boolean hasAttribute(String key);
|
||||
|
||||
public String getAttribute(String key);
|
||||
|
@ -1,6 +1,5 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -16,8 +15,7 @@
|
||||
*/
|
||||
package ghidra.xml;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
public class XmlElementImpl implements XmlElement {
|
||||
private final String name;
|
||||
@ -31,7 +29,8 @@ public class XmlElementImpl implements XmlElement {
|
||||
private final int lineNumber;
|
||||
|
||||
public XmlElementImpl(boolean isStart, boolean isEnd, String name, int level,
|
||||
LinkedHashMap<String, String> attributes, String text, int columnNumber, int lineNumber) {
|
||||
LinkedHashMap<String, String> attributes, String text, int columnNumber,
|
||||
int lineNumber) {
|
||||
if (isStart && isEnd) {
|
||||
throw new XmlException(
|
||||
"empty elements must be split into separate start and end elements (see splitEmptyElement)");
|
||||
@ -47,14 +46,17 @@ public class XmlElementImpl implements XmlElement {
|
||||
this.lineNumber = lineNumber;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getColumnNumber() {
|
||||
return columnNumber;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLineNumber() {
|
||||
return lineNumber;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasAttribute(String key) {
|
||||
if (attributes == null) {
|
||||
return false;
|
||||
@ -62,6 +64,7 @@ public class XmlElementImpl implements XmlElement {
|
||||
return attributes.containsKey(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAttribute(String key) {
|
||||
if (attributes == null) {
|
||||
return null;
|
||||
@ -69,34 +72,50 @@ public class XmlElementImpl implements XmlElement {
|
||||
return attributes.get(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LinkedHashMap<String, String> getAttributes() {
|
||||
return attributes == null ? null : new LinkedHashMap<String, String>(attributes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Map.Entry<String, String>> getAttributeIterator() {
|
||||
if (attributes == null) {
|
||||
return Collections.emptyIterator();
|
||||
}
|
||||
return attributes.entrySet().iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAttribute(String key, String value) {
|
||||
attributes.put(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLevel() {
|
||||
return level;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isContent() {
|
||||
return isContent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnd() {
|
||||
return isEnd;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStart() {
|
||||
return isStart;
|
||||
}
|
||||
@ -158,13 +177,12 @@ public class XmlElementImpl implements XmlElement {
|
||||
public static XmlElement[] splitEmptyElement(final XmlElementImpl element) {
|
||||
XmlElement[] result;
|
||||
if (element.isStart() && element.isEnd()) {
|
||||
result =
|
||||
new XmlElement[] {
|
||||
new XmlElementImpl(true, false, element.getName(), element.getLevel(),
|
||||
element.getAttributes(), null, element.getColumnNumber(),
|
||||
element.getLineNumber()),
|
||||
new XmlElementImpl(false, true, element.getName(), element.getLevel(), null,
|
||||
"", element.getColumnNumber(), element.getLineNumber()) };
|
||||
result = new XmlElement[] {
|
||||
new XmlElementImpl(true, false, element.getName(), element.getLevel(),
|
||||
element.getAttributes(), null, element.getColumnNumber(),
|
||||
element.getLineNumber()),
|
||||
new XmlElementImpl(false, true, element.getName(), element.getLevel(), null, "",
|
||||
element.getColumnNumber(), element.getLineNumber()) };
|
||||
}
|
||||
else {
|
||||
result = new XmlElement[] { element };
|
||||
|
Loading…
Reference in New Issue
Block a user